-# grafts set here are 'stronger' in that they're based on actual tree
-# matches, and won't be deleted from merge-base checking in write_grafts()
-sub graft_tree_joins {
- my $grafts = shift;
- map_tree_joins() if (@_branch_from && !%tree_map);
- return unless %tree_map;
-
- git_svn_each(sub {
- my $i = shift;
- my @args = (qw/rev-list --pretty=raw/, "refs/remotes/$i");
- my ($fh, $ctx) = command_output_pipe(@args);
- while (<$fh>) {
- next unless /^commit ($sha1)$/o;
- my $c = $1;
- my ($t) = (<$fh> =~ /^tree ($sha1)$/o);
- next unless $tree_map{$t};
-
- my $l;
- do {
- $l = readline $fh;
- } until ($l =~ /^committer (?:.+) (\d+) ([\-\+]?\d+)$/);
-
- my ($s, $tz) = ($1, $2);
- if ($tz =~ s/^\+//) {
- $s += tz_to_s_offset($tz);
- } elsif ($tz =~ s/^\-//) {
- $s -= tz_to_s_offset($tz);
- }
-
- my ($url_a, $r_a, $uuid_a) = cmt_metadata($c);
-
- foreach my $p (@{$tree_map{$t}}) {
- next if $p eq $c;
- my $mb = eval { command('merge-base', $c, $p) };
- next unless ($@ || $?);
- if (defined $r_a) {
- # see if SVN says it's a relative
- my ($url_b, $r_b, $uuid_b) =
- cmt_metadata($p);
- next if (defined $url_b &&
- defined $url_a &&
- ($url_a eq $url_b) &&
- ($uuid_a eq $uuid_b));
- if ($uuid_a eq $uuid_b) {
- if ($r_b < $r_a) {
- $grafts->{$c}->{$p} = 2;
- next;
- } elsif ($r_b > $r_a) {
- $grafts->{$p}->{$c} = 2;
- next;
- }
- }
- }
- my $ct = get_commit_time($p);
- if ($ct < $s) {
- $grafts->{$c}->{$p} = 2;
- } elsif ($ct > $s) {
- $grafts->{$p}->{$c} = 2;
- }
- # what should we do when $ct == $s ?
- }
- }
- command_close_pipe($fh, $ctx);
- });
-}
-
-sub graft_file_copy_lib {
- my ($grafts, $l_map, $u) = @_;
- my $tree_paths = $l_map->{$u};
- my $pfx = common_prefix([keys %$tree_paths]);
- my ($repo, $path) = repo_path_split($u.$pfx);
- $SVN = Git::SVN::Ra->new($repo);
-
- my ($base, $head) = libsvn_parse_revision();
- my $inc = 1000;
- my ($min, $max) = ($base, $head < $base+$inc ? $head : $base+$inc);
- my $eh = $SVN::Error::handler;
- $SVN::Error::handler = \&libsvn_skip_unknown_revs;
- while (1) {
- $SVN->dup->get_log([$path], $min, $max, 0, 2, 1,
- sub {
- libsvn_graft_file_copies($grafts, $tree_paths,
- $path, @_);
- });
- last if ($max >= $head);
- $min = $max + 1;
- $max += $inc;
- $max = $head if ($max > $head);
- }
- $SVN::Error::handler = $eh;
-}
-
-sub process_merge_msg_matches {
- my ($grafts, $l_map, $u, $p, $c, @matches) = @_;
- my (@strong, @weak);
- foreach (@matches) {
- # merging with ourselves is not interesting
- next if $_ eq $p;
- if ($l_map->{$u}->{$_}) {
- push @strong, $_;
- } else {
- push @weak, $_;
- }
- }
- foreach my $w (@weak) {
- last if @strong;
- # no exact match, use branch name as regexp.
- my $re = qr/\Q$w\E/i;
- foreach (keys %{$l_map->{$u}}) {
- if (/$re/) {
- push @strong, $l_map->{$u}->{$_};
- last;
- }
- }
- last if @strong;
- $w = basename($w);
- $re = qr/\Q$w\E/i;
- foreach (keys %{$l_map->{$u}}) {
- if (/$re/) {
- push @strong, $l_map->{$u}->{$_};
- last;
- }
- }
- }
- my ($rev) = ($c->{m} =~ /^git-svn-id:\s(?:\S+?)\@(\d+)
- \s(?:[a-f\d\-]+)$/xsm);
- unless (defined $rev) {
- ($rev) = ($c->{m} =~/^git-svn-id:\s(\d+)
- \@(?:[a-f\d\-]+)/xsm);
- return unless defined $rev;
- }
- foreach my $m (@strong) {
- my ($r0, $s0) = find_rev_before($rev, $m, 1);
- $grafts->{$c->{c}}->{$s0} = 1 if defined $s0;
- }
-}
-
-sub graft_merge_msg {
- my ($grafts, $l_map, $u, $p, @re) = @_;
-
- my $x = $l_map->{$u}->{$p};
- my $rl = rev_list_raw("refs/remotes/$x");
- while (my $c = next_rev_list_entry($rl)) {
- foreach my $re (@re) {
- my (@br) = ($c->{m} =~ /$re/g);
- next unless @br;
- process_merge_msg_matches($grafts,$l_map,$u,$p,$c,@br);
- }
- }
-}
-