Skip to content

Commit ef59f32

Browse files
committed
Merge branch 'for-junio' of git://bogomips.org/git-svn
* 'for-junio' of git://bogomips.org/git-svn: git-svn: use SVN::Ra::get_dir2 when possible git-svn: add space after "W:" prefix in warning git-svn: (cleanup) remove editor param passing git-svn: prepare SVN::Ra config pieces once Git.pm: add specified name to tempfile template git-svn: disable _rev_list memoization git-svn: save a little memory as fetch progresses git-svn: remove unnecessary DESTROY override git-svn: reload RA every log-window-size git-svn.txt: advertise pushurl with dcommit git-svn: remove mergeinfo rev caching git-svn: cache only mergeinfo revisions git-svn: reduce check_cherry_pick cache overhead git-svn: only look at the root path for svn:mergeinfo git-svn: only look at the new parts of svn:mergeinfo
2 parents 1d42cf3 + 7ffa35b commit ef59f32

File tree

4 files changed

+145
-91
lines changed

4 files changed

+145
-91
lines changed

Documentation/git-svn.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,10 @@ Use of 'dcommit' is preferred to 'set-tree' (below).
252252
config key: svn-remote.<name>.commiturl
253253
config key: svn.commiturl (overwrites all svn-remote.<name>.commiturl options)
254254
+
255+
Note that the SVN URL of the commiturl config key includes the SVN branch.
256+
If you rather want to set the commit URL for an entire SVN repository use
257+
svn-remote.<name>.pushurl instead.
258+
+
255259
Using this option for any other purpose (don't ask) is very strongly
256260
discouraged.
257261

perl/Git.pm

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1294,8 +1294,11 @@ sub _temp_cache {
12941294
$tmpdir = $self->repo_path();
12951295
}
12961296

1297+
my $n = $name;
1298+
$n =~ s/\W/_/g; # no strange chars
1299+
12971300
($$temp_fd, $fname) = File::Temp::tempfile(
1298-
'Git_XXXXXX', UNLINK => 1, DIR => $tmpdir,
1301+
"Git_${n}_XXXXXX", UNLINK => 1, DIR => $tmpdir,
12991302
) or throw Error::Simple("couldn't open new temp file");
13001303

13011304
$$temp_fd->autoflush;

perl/Git/SVN.pm

Lines changed: 76 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -1178,7 +1178,7 @@ sub find_parent_branch {
11781178
or die "SVN connection failed somewhere...\n";
11791179
}
11801180
print STDERR "Successfully followed parent\n" unless $::_q > 1;
1181-
return $self->make_log_entry($rev, [$parent], $ed);
1181+
return $self->make_log_entry($rev, [$parent], $ed, $r0, $branch_from);
11821182
}
11831183
return undef;
11841184
}
@@ -1210,7 +1210,7 @@ sub do_fetch {
12101210
unless ($self->ra->gs_do_update($last_rev, $rev, $self, $ed)) {
12111211
die "SVN connection failed somewhere...\n";
12121212
}
1213-
$self->make_log_entry($rev, \@parents, $ed);
1213+
$self->make_log_entry($rev, \@parents, $ed, $last_rev, $self->path);
12141214
}
12151215

12161216
sub mkemptydirs {
@@ -1433,7 +1433,7 @@ sub check_author {
14331433
}
14341434

14351435
sub find_extra_svk_parents {
1436-
my ($self, $ed, $tickets, $parents) = @_;
1436+
my ($self, $tickets, $parents) = @_;
14371437
# aha! svk:merge property changed...
14381438
my @tickets = split "\n", $tickets;
14391439
my @known_parents;
@@ -1478,9 +1478,9 @@ sub find_extra_svk_parents {
14781478
sub lookup_svn_merge {
14791479
my $uuid = shift;
14801480
my $url = shift;
1481-
my $merge = shift;
1481+
my $source = shift;
1482+
my $revs = shift;
14821483

1483-
my ($source, $revs) = split ":", $merge;
14841484
my $path = $source;
14851485
$path =~ s{^/}{};
14861486
my $gs = Git::SVN->find_by_url($url.$source, $url, $path);
@@ -1537,7 +1537,7 @@ sub _rev_list {
15371537
@rv;
15381538
}
15391539

1540-
sub check_cherry_pick {
1540+
sub check_cherry_pick2 {
15411541
my $base = shift;
15421542
my $tip = shift;
15431543
my $parents = shift;
@@ -1552,7 +1552,8 @@ sub check_cherry_pick {
15521552
delete $commits{$commit};
15531553
}
15541554
}
1555-
return (keys %commits);
1555+
my @k = (keys %commits);
1556+
return (scalar @k, $k[0]);
15561557
}
15571558

15581559
sub has_no_changes {
@@ -1597,9 +1598,8 @@ sub tie_for_persistent_memoization {
15971598
mkpath([$cache_path]) unless -d $cache_path;
15981599

15991600
my %lookup_svn_merge_cache;
1600-
my %check_cherry_pick_cache;
1601+
my %check_cherry_pick2_cache;
16011602
my %has_no_changes_cache;
1602-
my %_rev_list_cache;
16031603

16041604
tie_for_persistent_memoization(\%lookup_svn_merge_cache,
16051605
"$cache_path/lookup_svn_merge");
@@ -1608,11 +1608,11 @@ sub tie_for_persistent_memoization {
16081608
LIST_CACHE => ['HASH' => \%lookup_svn_merge_cache],
16091609
;
16101610

1611-
tie_for_persistent_memoization(\%check_cherry_pick_cache,
1612-
"$cache_path/check_cherry_pick");
1613-
memoize 'check_cherry_pick',
1611+
tie_for_persistent_memoization(\%check_cherry_pick2_cache,
1612+
"$cache_path/check_cherry_pick2");
1613+
memoize 'check_cherry_pick2',
16141614
SCALAR_CACHE => 'FAULT',
1615-
LIST_CACHE => ['HASH' => \%check_cherry_pick_cache],
1615+
LIST_CACHE => ['HASH' => \%check_cherry_pick2_cache],
16161616
;
16171617

16181618
tie_for_persistent_memoization(\%has_no_changes_cache,
@@ -1621,24 +1621,15 @@ sub tie_for_persistent_memoization {
16211621
SCALAR_CACHE => ['HASH' => \%has_no_changes_cache],
16221622
LIST_CACHE => 'FAULT',
16231623
;
1624-
1625-
tie_for_persistent_memoization(\%_rev_list_cache,
1626-
"$cache_path/_rev_list");
1627-
memoize '_rev_list',
1628-
SCALAR_CACHE => 'FAULT',
1629-
LIST_CACHE => ['HASH' => \%_rev_list_cache],
1630-
;
1631-
16321624
}
16331625

16341626
sub unmemoize_svn_mergeinfo_functions {
16351627
return if not $memoized;
16361628
$memoized = 0;
16371629

16381630
Memoize::unmemoize 'lookup_svn_merge';
1639-
Memoize::unmemoize 'check_cherry_pick';
1631+
Memoize::unmemoize 'check_cherry_pick2';
16401632
Memoize::unmemoize 'has_no_changes';
1641-
Memoize::unmemoize '_rev_list';
16421633
}
16431634

16441635
sub clear_memoized_mergeinfo_caches {
@@ -1648,7 +1639,8 @@ sub tie_for_persistent_memoization {
16481639
return unless -d $cache_path;
16491640

16501641
for my $cache_file (("$cache_path/lookup_svn_merge",
1651-
"$cache_path/check_cherry_pick",
1642+
"$cache_path/check_cherry_pick", # old
1643+
"$cache_path/check_cherry_pick2",
16521644
"$cache_path/has_no_changes")) {
16531645
for my $suffix (qw(yaml db)) {
16541646
my $file = "$cache_file.$suffix";
@@ -1702,11 +1694,49 @@ sub parents_exclude {
17021694
return @excluded;
17031695
}
17041696

1697+
# Compute what's new in svn:mergeinfo.
1698+
sub mergeinfo_changes {
1699+
my ($self, $old_path, $old_rev, $path, $rev, $mergeinfo_prop) = @_;
1700+
my %minfo = map {split ":", $_ } split "\n", $mergeinfo_prop;
1701+
my $old_minfo = {};
1702+
1703+
my $ra = $self->ra;
1704+
# Give up if $old_path isn't in the repo.
1705+
# This is probably a merge on a subtree.
1706+
if ($ra->check_path($old_path, $old_rev) != $SVN::Node::dir) {
1707+
warn "W: ignoring svn:mergeinfo on $old_path, ",
1708+
"directory didn't exist in r$old_rev\n";
1709+
return {};
1710+
}
1711+
my (undef, undef, $props) = $ra->get_dir($old_path, $old_rev);
1712+
if (defined $props->{"svn:mergeinfo"}) {
1713+
my %omi = map {split ":", $_ } split "\n",
1714+
$props->{"svn:mergeinfo"};
1715+
$old_minfo = \%omi;
1716+
}
1717+
1718+
my %changes = ();
1719+
foreach my $p (keys %minfo) {
1720+
my $a = $old_minfo->{$p} || "";
1721+
my $b = $minfo{$p};
1722+
# Omit merged branches whose ranges lists are unchanged.
1723+
next if $a eq $b;
1724+
# Remove any common range list prefix.
1725+
($a ^ $b) =~ /^[\0]*/;
1726+
my $common_prefix = rindex $b, ",", $+[0] - 1;
1727+
$changes{$p} = substr $b, $common_prefix + 1;
1728+
}
1729+
print STDERR "Checking svn:mergeinfo changes since r$old_rev: ",
1730+
scalar(keys %minfo), " sources, ",
1731+
scalar(keys %changes), " changed\n";
1732+
1733+
return \%changes;
1734+
}
17051735

17061736
# note: this function should only be called if the various dirprops
17071737
# have actually changed
17081738
sub find_extra_svn_parents {
1709-
my ($self, $ed, $mergeinfo, $parents) = @_;
1739+
my ($self, $mergeinfo, $parents) = @_;
17101740
# aha! svk:merge property changed...
17111741

17121742
memoize_svn_mergeinfo_functions();
@@ -1715,14 +1745,15 @@ sub find_extra_svn_parents {
17151745
# history. Then, we figure out which git revisions are in
17161746
# that tip, but not this revision. If all of those revisions
17171747
# are now marked as merge, we can add the tip as a parent.
1718-
my @merges = split "\n", $mergeinfo;
1748+
my @merges = sort keys %$mergeinfo;
17191749
my @merge_tips;
17201750
my $url = $self->url;
17211751
my $uuid = $self->ra_uuid;
17221752
my @all_ranges;
17231753
for my $merge ( @merges ) {
17241754
my ($tip_commit, @ranges) =
1725-
lookup_svn_merge( $uuid, $url, $merge );
1755+
lookup_svn_merge( $uuid, $url,
1756+
$merge, $mergeinfo->{$merge} );
17261757
unless (!$tip_commit or
17271758
grep { $_ eq $tip_commit } @$parents ) {
17281759
push @merge_tips, $tip_commit;
@@ -1738,8 +1769,9 @@ sub find_extra_svn_parents {
17381769
# check merge tips for new parents
17391770
my @new_parents;
17401771
for my $merge_tip ( @merge_tips ) {
1741-
my $spec = shift @merges;
1772+
my $merge = shift @merges;
17421773
next unless $merge_tip and $excluded{$merge_tip};
1774+
my $spec = "$merge:$mergeinfo->{$merge}";
17431775

17441776
# check out 'new' tips
17451777
my $merge_base;
@@ -1759,19 +1791,17 @@ sub find_extra_svn_parents {
17591791
}
17601792

17611793
# double check that there are no missing non-merge commits
1762-
my (@incomplete) = check_cherry_pick(
1794+
my ($ninc, $ifirst) = check_cherry_pick2(
17631795
$merge_base, $merge_tip,
17641796
$parents,
17651797
@all_ranges,
17661798
);
17671799

1768-
if ( @incomplete ) {
1769-
warn "W:svn cherry-pick ignored ($spec) - missing "
1770-
.@incomplete." commit(s) (eg $incomplete[0])\n";
1800+
if ($ninc) {
1801+
warn "W: svn cherry-pick ignored ($spec) - missing " .
1802+
"$ninc commit(s) (eg $ifirst)\n";
17711803
} else {
1772-
warn
1773-
"Found merge parent (svn:mergeinfo prop): ",
1774-
$merge_tip, "\n";
1804+
warn "Found merge parent ($spec): ", $merge_tip, "\n";
17751805
push @new_parents, $merge_tip;
17761806
}
17771807
}
@@ -1797,23 +1827,20 @@ sub find_extra_svn_parents {
17971827
}
17981828

17991829
sub make_log_entry {
1800-
my ($self, $rev, $parents, $ed) = @_;
1830+
my ($self, $rev, $parents, $ed, $parent_rev, $parent_path) = @_;
18011831
my $untracked = $self->get_untracked($ed);
18021832

18031833
my @parents = @$parents;
1804-
my $ps = $ed->{path_strip} || "";
1805-
for my $path ( grep { m/$ps/ } %{$ed->{dir_prop}} ) {
1806-
my $props = $ed->{dir_prop}{$path};
1807-
if ( $props->{"svk:merge"} ) {
1808-
$self->find_extra_svk_parents
1809-
($ed, $props->{"svk:merge"}, \@parents);
1810-
}
1811-
if ( $props->{"svn:mergeinfo"} ) {
1812-
$self->find_extra_svn_parents
1813-
($ed,
1814-
$props->{"svn:mergeinfo"},
1815-
\@parents);
1816-
}
1834+
my $props = $ed->{dir_prop}{$self->path};
1835+
if ( $props->{"svk:merge"} ) {
1836+
$self->find_extra_svk_parents($props->{"svk:merge"}, \@parents);
1837+
}
1838+
if ( $props->{"svn:mergeinfo"} ) {
1839+
my $mi_changes = $self->mergeinfo_changes
1840+
($parent_path, $parent_rev,
1841+
$self->path, $rev,
1842+
$props->{"svn:mergeinfo"});
1843+
$self->find_extra_svn_parents($mi_changes, \@parents);
18171844
}
18181845

18191846
open my $un, '>>', "$self->{dir}/unhandled.log" or croak $!;

0 commit comments

Comments
 (0)