Skip to content

Commit 7b73d82

Browse files
committed
Merge git://git.bogomips.org/git-svn
* git://git.bogomips.org/git-svn: test case for regression caused by git-svn empty symlink fix git-svn: fix broken symlink workaround when switching branches git-svn: Print revision while searching for earliest use of path git-svn: abstract out a block into new method other_gs() git-svn: allow disabling expensive broken symlink checks
2 parents 9e5b80c + 39111f6 commit 7b73d82

File tree

5 files changed

+279
-21
lines changed

5 files changed

+279
-21
lines changed

Documentation/git-svn.txt

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -499,6 +499,14 @@ svn-remote.<name>.rewriteRoot::
499499
the repository with a public http:// or svn:// URL in the
500500
metadata so users of it will see the public URL.
501501

502+
svn.brokenSymlinkWorkaround::
503+
This disables potentially expensive checks to workaround broken symlinks
504+
checked into SVN by broken clients. Set this option to "false" if you
505+
track a SVN repository with many empty blobs that are not symlinks.
506+
This option may be changed while "git-svn" is running and take effect on
507+
the next revision fetched. If unset, git-svn assumes this option to be
508+
"true".
509+
502510
--
503511

504512
Since the noMetadata, rewriteRoot, useSvnsyncProps and useSvmProps

git-svn.perl

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2389,22 +2389,8 @@ sub find_parent_branch {
23892389
print STDERR "Found possible branch point: ",
23902390
"$new_url => ", $self->full_url, ", $r\n";
23912391
$branch_from =~ s#^/##;
2392-
my $gs = Git::SVN->find_by_url($new_url, $repos_root, $branch_from);
2393-
unless ($gs) {
2394-
my $ref_id = $self->{ref_id};
2395-
$ref_id =~ s/\@\d+$//;
2396-
$ref_id .= "\@$r";
2397-
# just grow a tail if we're not unique enough :x
2398-
$ref_id .= '-' while find_ref($ref_id);
2399-
print STDERR "Initializing parent: $ref_id\n";
2400-
my ($u, $p, $repo_id) = ($new_url, '', $ref_id);
2401-
if ($u =~ s#^\Q$url\E(/|$)##) {
2402-
$p = $u;
2403-
$u = $url;
2404-
$repo_id = $self->{repo_id};
2405-
}
2406-
$gs = Git::SVN->init($u, $p, $repo_id, $ref_id, 1);
2407-
}
2392+
my $gs = $self->other_gs($new_url, $url, $repos_root,
2393+
$branch_from, $r, $self->{ref_id});
24082394
my ($r0, $parent) = $gs->find_rev_before($r, 1);
24092395
{
24102396
my ($base, $head);
@@ -2431,7 +2417,7 @@ sub find_parent_branch {
24312417
# is not included with SVN 1.4.3 (the latest version
24322418
# at the moment), so we can't rely on it
24332419
$self->{last_commit} = $parent;
2434-
$ed = SVN::Git::Fetcher->new($self);
2420+
$ed = SVN::Git::Fetcher->new($self, $gs->{path});
24352421
$gs->ra->gs_do_switch($r0, $rev, $gs,
24362422
$self->full_url, $ed)
24372423
or die "SVN connection failed somewhere...\n";
@@ -2586,6 +2572,28 @@ sub parse_svn_date {
25862572
return $parsed_date;
25872573
}
25882574

2575+
sub other_gs {
2576+
my ($self, $new_url, $url, $repos_root,
2577+
$branch_from, $r, $old_ref_id) = @_;
2578+
my $gs = Git::SVN->find_by_url($new_url, $repos_root, $branch_from);
2579+
unless ($gs) {
2580+
my $ref_id = $old_ref_id;
2581+
$ref_id =~ s/\@\d+$//;
2582+
$ref_id .= "\@$r";
2583+
# just grow a tail if we're not unique enough :x
2584+
$ref_id .= '-' while find_ref($ref_id);
2585+
print STDERR "Initializing parent: $ref_id\n";
2586+
my ($u, $p, $repo_id) = ($new_url, '', $ref_id);
2587+
if ($u =~ s#^\Q$url\E(/|$)##) {
2588+
$p = $u;
2589+
$u = $url;
2590+
$repo_id = $self->{repo_id};
2591+
}
2592+
$gs = Git::SVN->init($u, $p, $repo_id, $ref_id, 1);
2593+
}
2594+
$gs
2595+
}
2596+
25892597
sub check_author {
25902598
my ($author) = @_;
25912599
if (!defined $author || length $author == 0) {
@@ -3250,12 +3258,13 @@ package SVN::Git::Fetcher;
32503258

32513259
# file baton members: path, mode_a, mode_b, pool, fh, blob, base
32523260
sub new {
3253-
my ($class, $git_svn) = @_;
3261+
my ($class, $git_svn, $switch_path) = @_;
32543262
my $self = SVN::Delta::Editor->new;
32553263
bless $self, $class;
32563264
if (exists $git_svn->{last_commit}) {
32573265
$self->{c} = $git_svn->{last_commit};
3258-
$self->{empty_symlinks} = _mark_empty_symlinks($git_svn);
3266+
$self->{empty_symlinks} =
3267+
_mark_empty_symlinks($git_svn, $switch_path);
32593268
}
32603269
$self->{empty} = {};
32613270
$self->{dir_prop} = {};
@@ -3270,19 +3279,39 @@ sub new {
32703279
# not inside them (when the Git::SVN::Fetcher object is passed) to
32713280
# do_{switch,update}
32723281
sub _mark_empty_symlinks {
3273-
my ($git_svn) = @_;
3282+
my ($git_svn, $switch_path) = @_;
3283+
my $bool = Git::config_bool('svn.brokenSymlinkWorkaround');
3284+
return {} if (defined($bool) && ! $bool);
3285+
32743286
my %ret;
32753287
my ($rev, $cmt) = $git_svn->last_rev_commit;
32763288
return {} unless ($rev && $cmt);
32773289

3290+
# allow the warning to be printed for each revision we fetch to
3291+
# ensure the user sees it. The user can also disable the workaround
3292+
# on the repository even while git svn is running and the next
3293+
# revision fetched will skip this expensive function.
3294+
my $printed_warning;
32783295
chomp(my $empty_blob = `git hash-object -t blob --stdin < /dev/null`);
32793296
my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r -z/, $cmt);
32803297
local $/ = "\0";
3281-
my $pfx = $git_svn->{path};
3298+
my $pfx = defined($switch_path) ? $switch_path : $git_svn->{path};
32823299
$pfx .= '/' if length($pfx);
32833300
while (<$ls>) {
32843301
chomp;
32853302
s/\A100644 blob $empty_blob\t//o or next;
3303+
unless ($printed_warning) {
3304+
print STDERR "Scanning for empty symlinks, ",
3305+
"this may take a while if you have ",
3306+
"many empty files\n",
3307+
"You may disable this with `",
3308+
"git config svn.brokenSymlinkWorkaround ",
3309+
"false'.\n",
3310+
"This may be done in a different ",
3311+
"terminal without restarting ",
3312+
"git svn\n";
3313+
$printed_warning = 1;
3314+
}
32863315
my $path = $_;
32873316
my (undef, $props) =
32883317
$git_svn->ra->get_file($pfx.$path, $rev, undef);
@@ -4348,6 +4377,9 @@ sub gs_fetch_loop_common {
43484377
}
43494378
$self->get_log([$longest_path], $min, $max, 0, 1, 1,
43504379
sub { $revs{$_[1]} = _cb(@_) });
4380+
if ($err) {
4381+
print "Checked through r$max\r";
4382+
}
43514383
if ($err && $max >= $head) {
43524384
print STDERR "Path '$longest_path' ",
43534385
"was probably deleted:\n",

t/t9131-git-svn-empty-symlink.sh

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,4 +87,14 @@ test_expect_success '"bar" is an empty file' 'test -f x/bar && ! test -s x/bar'
8787
test_expect_success 'get "bar" => symlink fix from svn' \
8888
'(cd x && git svn rebase)'
8989
test_expect_success '"bar" becomes a symlink' 'test -L x/bar'
90+
91+
92+
test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" y'
93+
test_expect_success 'disable broken symlink workaround' \
94+
'(cd y && git config svn.brokenSymlinkWorkaround false)'
95+
test_expect_success '"bar" is an empty file' 'test -f y/bar && ! test -s y/bar'
96+
test_expect_success 'get "bar" => symlink fix from svn' \
97+
'(cd y && git svn rebase)'
98+
test_expect_success '"bar" does not become a symlink' '! test -L y/bar'
99+
90100
test_done
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
#!/bin/sh
2+
3+
test_description='test moved svn branch with missing empty files'
4+
5+
. ./lib-git-svn.sh
6+
test_expect_success 'load svn dumpfile' '
7+
svnadmin load "$rawsvnrepo" < "${TEST_DIRECTORY}/t9135/svn.dump"
8+
'
9+
10+
test_expect_success 'clone using git svn' 'git svn clone -s "$svnrepo" x'
11+
12+
test_expect_success 'test that b1 exists and is empty' '
13+
(cd x && test -f b1 && ! test -s b1)
14+
'
15+
16+
test_done

t/t9135/svn.dump

Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
SVN-fs-dump-format-version: 2
2+
3+
UUID: 1f80e919-e9e3-4d80-a3ae-d9f21095e27b
4+
5+
Revision-number: 0
6+
Prop-content-length: 56
7+
Content-length: 56
8+
9+
K 8
10+
svn:date
11+
V 27
12+
2009-02-10T19:23:16.424027Z
13+
PROPS-END
14+
15+
Revision-number: 1
16+
Prop-content-length: 123
17+
Content-length: 123
18+
19+
K 7
20+
svn:log
21+
V 20
22+
init standard layout
23+
K 10
24+
svn:author
25+
V 8
26+
john.doe
27+
K 8
28+
svn:date
29+
V 27
30+
2009-02-10T19:23:17.195072Z
31+
PROPS-END
32+
33+
Node-path: branches
34+
Node-kind: dir
35+
Node-action: add
36+
Prop-content-length: 10
37+
Content-length: 10
38+
39+
PROPS-END
40+
41+
42+
Node-path: trunk
43+
Node-kind: dir
44+
Node-action: add
45+
Prop-content-length: 10
46+
Content-length: 10
47+
48+
PROPS-END
49+
50+
51+
Revision-number: 2
52+
Prop-content-length: 121
53+
Content-length: 121
54+
55+
K 7
56+
svn:log
57+
V 18
58+
branch-b off trunk
59+
K 10
60+
svn:author
61+
V 8
62+
john.doe
63+
K 8
64+
svn:date
65+
V 27
66+
2009-02-10T19:23:19.160095Z
67+
PROPS-END
68+
69+
Node-path: branches/branch-b
70+
Node-kind: dir
71+
Node-action: add
72+
Node-copyfrom-rev: 1
73+
Node-copyfrom-path: trunk
74+
Prop-content-length: 34
75+
Content-length: 34
76+
77+
K 13
78+
svn:mergeinfo
79+
V 0
80+
81+
PROPS-END
82+
83+
84+
Revision-number: 3
85+
Prop-content-length: 120
86+
Content-length: 120
87+
88+
K 7
89+
svn:log
90+
V 17
91+
add empty file b1
92+
K 10
93+
svn:author
94+
V 8
95+
john.doe
96+
K 8
97+
svn:date
98+
V 27
99+
2009-02-10T19:23:20.194568Z
100+
PROPS-END
101+
102+
Node-path: branches/branch-b/b1
103+
Node-kind: file
104+
Node-action: add
105+
Prop-content-length: 10
106+
Text-content-length: 0
107+
Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
108+
Content-length: 10
109+
110+
PROPS-END
111+
112+
113+
Revision-number: 4
114+
Prop-content-length: 110
115+
Content-length: 110
116+
117+
K 7
118+
svn:log
119+
V 8
120+
branch-c
121+
K 10
122+
svn:author
123+
V 8
124+
john.doe
125+
K 8
126+
svn:date
127+
V 27
128+
2009-02-10T19:23:21.169100Z
129+
PROPS-END
130+
131+
Node-path: branches/branch-c
132+
Node-kind: dir
133+
Node-action: add
134+
Node-copyfrom-rev: 3
135+
Node-copyfrom-path: trunk
136+
137+
138+
Revision-number: 5
139+
Prop-content-length: 126
140+
Content-length: 126
141+
142+
K 7
143+
svn:log
144+
V 23
145+
oops, wrong branchpoint
146+
K 10
147+
svn:author
148+
V 8
149+
john.doe
150+
K 8
151+
svn:date
152+
V 27
153+
2009-02-10T19:23:21.253557Z
154+
PROPS-END
155+
156+
Node-path: branches/branch-c
157+
Node-action: delete
158+
159+
160+
Revision-number: 6
161+
Prop-content-length: 127
162+
Content-length: 127
163+
164+
K 7
165+
svn:log
166+
V 24
167+
branch-c off of branch-b
168+
K 10
169+
svn:author
170+
V 8
171+
john.doe
172+
K 8
173+
svn:date
174+
V 27
175+
2009-02-10T19:23:21.314659Z
176+
PROPS-END
177+
178+
Node-path: branches/branch-c
179+
Node-kind: dir
180+
Node-action: add
181+
Node-copyfrom-rev: 5
182+
Node-copyfrom-path: branches/branch-b
183+
Prop-content-length: 34
184+
Content-length: 34
185+
186+
K 13
187+
svn:mergeinfo
188+
V 0
189+
190+
PROPS-END
191+
192+

0 commit comments

Comments
 (0)