Gentoo Archives: gentoo-commits

From: "Robin H. Johnson (robbat2)" <robbat2@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] gentoo-x86 commit in dev-vcs/git/files: git-1.7.12-git-svn-backport.patch git-1.7.12-optional-cvs.patch
Date: Wed, 22 Aug 2012 04:44:19
Message-Id: 20120822044408.1793E202E0@flycatcher.gentoo.org
1 robbat2 12/08/22 04:44:08
2
3 Added: git-1.7.12-git-svn-backport.patch
4 git-1.7.12-optional-cvs.patch
5 Log:
6 Finally, a Git that works with SVN 1.7, per bug #418431! 1.7.12-r1 contains backported ms/git-svn-1.7 branch that will be merged into Git 1.7.13. 1.7.12-r0 excludes that backport but is otherwise identical. Thanks to Michael Schwern for the development work!
7
8 (Portage version: 2.2.0_alpha121/cvs/Linux x86_64)
9
10 Revision Changes Path
11 1.1 dev-vcs/git/files/git-1.7.12-git-svn-backport.patch
12
13 file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-vcs/git/files/git-1.7.12-git-svn-backport.patch?rev=1.1&view=markup
14 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-vcs/git/files/git-1.7.12-git-svn-backport.patch?rev=1.1&content-type=text/plain
15
16 Index: git-1.7.12-git-svn-backport.patch
17 ===================================================================
18 commit 0dfcf2dacd4be3f0c647a987b78def5136429165
19 Merge: 889d358 5eaa1fd
20 Author: Junio C Hamano <gitster@×××××.com>
21 Date: Tue Aug 21 15:27:57 2012 -0700
22
23 Merge branch 'ms/git-svn-1.7' into jch
24
25 A series by Michael Schwern via Eric to update git-svn to revamp the
26 way URLs are internally passed around, to make it work with SVN 1.7.
27
28 Will merge to 'next' after pinging Eric to double check and then to 'master'.
29
30 * ms/git-svn-1.7:
31 git-svn: remove ad-hoc canonicalizations
32 git-svn: canonicalize newly-minted URLs
33 git-svn: introduce add_path_to_url function
34 git-svn: canonicalize earlier
35 git-svn: replace URL escapes with canonicalization
36 git-svn: attempt to mimic SVN 1.7 URL canonicalization
37 t9107: fix typo
38 t9118: workaround inconsistency between SVN versions
39 Git::SVN{,::Ra}: canonicalize earlier
40 git-svn: path canonicalization uses SVN API
41 Git::SVN::Utils: remove irrelevant comment
42 git-svn: add join_paths() to safely concatenate paths
43 git-svn: factor out _collapse_dotdot function
44 git-svn: use SVN 1.7 to canonicalize when possible
45 git-svn: move canonicalization to Git::SVN::Utils
46 use Git::SVN{,::RA}->url accessor globally
47 use Git::SVN->path accessor globally
48 Git::SVN::Ra: use accessor for URLs
49 Git::SVN: use accessor for URLs internally
50 Git::SVN: use accessors internally for path
51
52 diff --git a/git-svn.perl b/git-svn.perl
53 index 828b8f0..0d77ffb 100755
54 --- a/git-svn.perl
55 +++ b/git-svn.perl
56 @@ -29,7 +29,16 @@ use Git::SVN::Prompt;
57 use Git::SVN::Log;
58 use Git::SVN::Migration;
59
60 -use Git::SVN::Utils qw(fatal can_compress);
61 +use Git::SVN::Utils qw(
62 + fatal
63 + can_compress
64 + canonicalize_path
65 + canonicalize_url
66 + join_paths
67 + add_path_to_url
68 + join_paths
69 +);
70 +
71 use Git qw(
72 git_cmd_try
73 command
74 @@ -1231,7 +1240,7 @@ sub cmd_show_ignore {
75 my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
76 $gs ||= Git::SVN->new;
77 my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
78 - $gs->prop_walk($gs->{path}, $r, sub {
79 + $gs->prop_walk($gs->path, $r, sub {
80 my ($gs, $path, $props) = @_;
81 print STDOUT "\n# $path\n";
82 my $s = $props->{'svn:ignore'} or return;
83 @@ -1247,7 +1256,7 @@ sub cmd_show_externals {
84 my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
85 $gs ||= Git::SVN->new;
86 my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
87 - $gs->prop_walk($gs->{path}, $r, sub {
88 + $gs->prop_walk($gs->path, $r, sub {
89 my ($gs, $path, $props) = @_;
90 print STDOUT "\n# $path\n";
91 my $s = $props->{'svn:externals'} or return;
92 @@ -1262,7 +1271,7 @@ sub cmd_create_ignore {
93 my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
94 $gs ||= Git::SVN->new;
95 my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
96 - $gs->prop_walk($gs->{path}, $r, sub {
97 + $gs->prop_walk($gs->path, $r, sub {
98 my ($gs, $path, $props) = @_;
99 # $path is of the form /path/to/dir/
100 $path = '.' . $path;
101 @@ -1292,31 +1301,6 @@ sub cmd_mkdirs {
102 $gs->mkemptydirs($_revision);
103 }
104
105 -sub canonicalize_path {
106 - my ($path) = @_;
107 - my $dot_slash_added = 0;
108 - if (substr($path, 0, 1) ne "/") {
109 - $path = "./" . $path;
110 - $dot_slash_added = 1;
111 - }
112 - # File::Spec->canonpath doesn't collapse x/../y into y (for a
113 - # good reason), so let's do this manually.
114 - $path =~ s#/+#/#g;
115 - $path =~ s#/\.(?:/|$)#/#g;
116 - $path =~ s#/[^/]+/\.\.##g;
117 - $path =~ s#/$##g;
118 - $path =~ s#^\./## if $dot_slash_added;
119 - $path =~ s#^/##;
120 - $path =~ s#^\.$##;
121 - return $path;
122 -}
123 -
124 -sub canonicalize_url {
125 - my ($url) = @_;
126 - $url =~ s#^([^:]+://[^/]*/)(.*)$#$1 . canonicalize_path($2)#e;
127 - return $url;
128 -}
129 -
130 # get_svnprops(PATH)
131 # ------------------
132 # Helper for cmd_propget and cmd_proplist below.
133 @@ -1330,7 +1314,7 @@ sub get_svnprops {
134 $path = $cmd_dir_prefix . $path;
135 fatal("No such file or directory: $path") unless -e $path;
136 my $is_dir = -d $path ? 1 : 0;
137 - $path = $gs->{path} . '/' . $path;
138 + $path = join_paths($gs->{path}, $path);
139
140 # canonicalize the path (otherwise libsvn will abort or fail to
141 # find the file)
142 @@ -1431,8 +1415,8 @@ sub cmd_commit_diff {
143 fatal("Needed URL or usable git-svn --id in ",
144 "the command-line\n", $usage);
145 }
146 - $url = $gs->{url};
147 - $svn_path = $gs->{path};
148 + $url = $gs->url;
149 + $svn_path = $gs->path;
150 }
151 unless (defined $_revision) {
152 fatal("-r|--revision is a required argument\n", $usage);
153 @@ -1466,24 +1450,6 @@ sub cmd_commit_diff {
154 }
155 }
156
157 -sub escape_uri_only {
158 - my ($uri) = @_;
159 - my @tmp;
160 - foreach (split m{/}, $uri) {
161 - s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
162 - push @tmp, $_;
163 - }
164 - join('/', @tmp);
165 -}
166 -
167 -sub escape_url {
168 - my ($url) = @_;
169 - if ($url =~ m#^([^:]+)://([^/]*)(.*)$#) {
170 - my ($scheme, $domain, $uri) = ($1, $2, escape_uri_only($3));
171 - $url = "$scheme://$domain$uri";
172 - }
173 - $url;
174 -}
175
176 sub cmd_info {
177 my $path = canonicalize_path(defined($_[0]) ? $_[0] : ".");
178 @@ -1508,21 +1474,21 @@ sub cmd_info {
179 # canonicalize_path() will return "" to make libsvn 1.5.x happy,
180 $path = "." if $path eq "";
181
182 - my $full_url = $url . ($fullpath eq "" ? "" : "/$fullpath");
183 + my $full_url = canonicalize_url( add_path_to_url( $url, $fullpath ) );
184
185 if ($_url) {
186 - print escape_url($full_url), "\n";
187 + print "$full_url\n";
188 return;
189 }
190
191 my $result = "Path: $path\n";
192 $result .= "Name: " . basename($path) . "\n" if $file_type ne "dir";
193 - $result .= "URL: " . escape_url($full_url) . "\n";
194 + $result .= "URL: $full_url\n";
195
196 eval {
197 my $repos_root = $gs->repos_root;
198 Git::SVN::remove_username($repos_root);
199 - $result .= "Repository Root: " . escape_url($repos_root) . "\n";
200 + $result .= "Repository Root: " . canonicalize_url($repos_root) . "\n";
201 };
202 if ($@) {
203 $result .= "Repository Root: (offline)\n";
204 @@ -1669,7 +1635,9 @@ sub post_fetch_checkout {
205
206 sub complete_svn_url {
207 my ($url, $path) = @_;
208 - $path =~ s#/+$##;
209 + $path = canonicalize_path($path);
210 +
211 + # If the path is not a URL...
212 if ($path !~ m#^[a-z\+]+://#) {
213 if (!defined $url || $url !~ m#^[a-z\+]+://#) {
214 fatal("E: '$path' is not a complete URL ",
215 @@ -1686,7 +1654,7 @@ sub complete_url_ls_init {
216 print STDERR "W: $switch not specified\n";
217 return;
218 }
219 - $repo_path =~ s#/+$##;
220 + $repo_path = canonicalize_path($repo_path);
221 if ($repo_path =~ m#^[a-z\+]+://#) {
222 $ra = Git::SVN::Ra->new($repo_path);
223 $repo_path = '';
224 @@ -1697,18 +1665,18 @@ sub complete_url_ls_init {
225 "and a separate URL is not specified");
226 }
227 }
228 - my $url = $ra->{url};
229 + my $url = $ra->url;
230 my $gs = Git::SVN->init($url, undef, undef, undef, 1);
231 my $k = "svn-remote.$gs->{repo_id}.url";
232 my $orig_url = eval { command_oneline(qw/config --get/, $k) };
233 - if ($orig_url && ($orig_url ne $gs->{url})) {
234 + if ($orig_url && ($orig_url ne $gs->url)) {
235 die "$k already set: $orig_url\n",
236 - "wanted to set to: $gs->{url}\n";
237 + "wanted to set to: $gs->url\n";
238 }
239 - command_oneline('config', $k, $gs->{url}) unless $orig_url;
240 - my $remote_path = "$gs->{path}/$repo_path";
241 + command_oneline('config', $k, $gs->url) unless $orig_url;
242 +
243 + my $remote_path = join_paths( $gs->path, $repo_path );
244 $remote_path =~ s{%([0-9A-F]{2})}{chr hex($1)}ieg;
245 - $remote_path =~ s#/+#/#g;
246 $remote_path =~ s#^/##g;
247 $remote_path .= "/*" if $remote_path !~ /\*/;
248 my ($n) = ($switch =~ /^--(\w+)/);
249 diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm
250 index 8478d0c..acb2539 100644
251 --- a/perl/Git/SVN.pm
252 +++ b/perl/Git/SVN.pm
253 @@ -23,7 +23,14 @@ use Git qw(
254 command_output_pipe
255 command_close_pipe
256 );
257 -use Git::SVN::Utils qw(fatal can_compress);
258 +use Git::SVN::Utils qw(
259 + fatal
260 + can_compress
261 + join_paths
262 + canonicalize_path
263 + canonicalize_url
264 + add_path_to_url
265 +);
266
267 my $can_use_yaml;
268 BEGIN {
269 @@ -195,9 +202,9 @@ sub read_all_remotes {
270 } elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) {
271 $r->{$1}->{svm} = {};
272 } elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
273 - $r->{$1}->{url} = $2;
274 + $r->{$1}->{url} = canonicalize_url($2);
275 } elsif (m!^(.+)\.pushurl=\s*(.*)\s*$!) {
276 - $r->{$1}->{pushurl} = $2;
277 + $r->{$1}->{pushurl} = canonicalize_url($2);
278 } elsif (m!^(.+)\.ignore-refs=\s*(.*)\s*$!) {
279 $r->{$1}->{ignore_refs_regex} = $2;
280 } elsif (m!^(.+)\.(branches|tags)=$svn_refspec$!) {
281 @@ -290,7 +297,7 @@ sub find_existing_remote {
282
283 sub init_remote_config {
284 my ($self, $url, $no_write) = @_;
285 - $url =~ s!/+$!!; # strip trailing slash
286 + $url = canonicalize_url($url);
287 my $r = read_all_remotes();
288 my $existing = find_existing_remote($url, $r);
289 if ($existing) {
290 @@ -314,12 +321,10 @@ sub init_remote_config {
291 print STDERR "Using higher level of URL: ",
292 "$url => $min_url\n";
293 }
294 - my $old_path = $self->{path};
295 - $self->{path} = $url;
296 - $self->{path} =~ s!^\Q$min_url\E(/|$)!!;
297 - if (length $old_path) {
298 - $self->{path} .= "/$old_path";
299 - }
300 + my $old_path = $self->path;
301 + $url =~ s!^\Q$min_url\E(/|$)!!;
302 + $url = join_paths($url, $old_path);
303 + $self->path($url);
304 $url = $min_url;
305 }
306 }
307 @@ -343,18 +348,22 @@ sub init_remote_config {
308 unless ($no_write) {
309 command_noisy('config',
310 "svn-remote.$self->{repo_id}.url", $url);
311 - $self->{path} =~ s{^/}{};
312 - $self->{path} =~ s{%([0-9A-F]{2})}{chr hex($1)}ieg;
313 + my $path = $self->path;
314 + $path =~ s{^/}{};
315 + $path =~ s{%([0-9A-F]{2})}{chr hex($1)}ieg;
316 + $self->path($path);
317 command_noisy('config', '--add',
318 "svn-remote.$self->{repo_id}.fetch",
319 - "$self->{path}:".$self->refname);
320 + $self->path.":".$self->refname);
321 }
322 - $self->{url} = $url;
323 + $self->url($url);
324 }
325
326 sub find_by_url { # repos_root and, path are optional
327 my ($class, $full_url, $repos_root, $path) = @_;
328
329 + $full_url = canonicalize_url($full_url);
330 +
331 return undef unless defined $full_url;
332 remove_username($full_url);
333 remove_username($repos_root) if defined $repos_root;
334 @@ -393,6 +402,11 @@ sub find_by_url { # repos_root and, path are optional
335 }
336 $p =~ s#^\Q$z\E(?:/|$)#$prefix# or next;
337 }
338 +
339 + # remote fetch paths are not URI escaped. Decode ours
340 + # so they match
341 + $p = uri_decode($p);
342 +
343 foreach my $f (keys %$fetch) {
344 next if $f ne $p;
345 return Git::SVN->new($fetch->{$f}, $repo_id, $f);
346 @@ -435,20 +449,25 @@ sub new {
347 }
348 }
349 my $self = _new($class, $repo_id, $ref_id, $path);
350 - if (!defined $self->{path} || !length $self->{path}) {
351 + if (!defined $self->path || !length $self->path) {
352 my $fetch = command_oneline('config', '--get',
353 "svn-remote.$repo_id.fetch",
354 ":$ref_id\$") or
355 die "Failed to read \"svn-remote.$repo_id.fetch\" ",
356 "\":$ref_id\$\" in config\n";
357 - ($self->{path}, undef) = split(/\s*:\s*/, $fetch);
358 + my($path) = split(/\s*:\s*/, $fetch);
359 + $self->path($path);
360 }
361 - $self->{path} =~ s{/+}{/}g;
362 - $self->{path} =~ s{\A/}{};
363 - $self->{path} =~ s{/\z}{};
364 - $self->{url} = command_oneline('config', '--get',
365 - "svn-remote.$repo_id.url") or
366 + {
367 + my $path = $self->path;
368 + $path =~ s{\A/}{};
369 + $path =~ s{/\z}{};
370 + $self->path($path);
371 + }
372 + my $url = command_oneline('config', '--get',
373 + "svn-remote.$repo_id.url") or
374 die "Failed to read \"svn-remote.$repo_id.url\" in config\n";
375 + $self->url($url);
376 $self->{pushurl} = eval { command_oneline('config', '--get',
377 "svn-remote.$repo_id.pushurl") };
378 $self->rebuild;
379 @@ -552,8 +571,7 @@ sub _set_svm_vars {
380 # username is of no interest
381 $src =~ s{(^[a-z\+]*://)[^/@]*@}{$1};
382
383 - my $replace = $ra->{url};
384 - $replace .= "/$path" if length $path;
385 + my $replace = add_path_to_url($ra->url, $path);
386
387 my $section = "svn-remote.$self->{repo_id}";
388 tmp_config("$section.svm-source", $src);
389 @@ -567,20 +585,21 @@ sub _set_svm_vars {
390 }
391
392 my $r = $ra->get_latest_revnum;
393 - my $path = $self->{path};
394 + my $path = $self->path;
395 my %tried;
396 while (length $path) {
397 - unless ($tried{"$self->{url}/$path"}) {
398 + my $try = add_path_to_url($self->url, $path);
399 + unless ($tried{$try}) {
400 return $ra if $self->read_svm_props($ra, $path, $r);
401 - $tried{"$self->{url}/$path"} = 1;
402 + $tried{$try} = 1;
403 }
404 $path =~ s#/?[^/]+$##;
405 }
406 die "Path: '$path' should be ''\n" if $path ne '';
407 return $ra if $self->read_svm_props($ra, $path, $r);
408 - $tried{"$self->{url}/$path"} = 1;
409 + $tried{ add_path_to_url($self->url, $path) } = 1;
410
411 - if ($ra->{repos_root} eq $self->{url}) {
412 + if ($ra->{repos_root} eq $self->url) {
413 die @err, (map { " $_\n" } keys %tried), "\n";
414 }
415
416 @@ -590,20 +609,21 @@ sub _set_svm_vars {
417 $path = $ra->{svn_path};
418 $ra = Git::SVN::Ra->new($ra->{repos_root});
419 while (length $path) {
420 - unless ($tried{"$ra->{url}/$path"}) {
421 + my $try = add_path_to_url($ra->url, $path);
422 + unless ($tried{$try}) {
423 $ok = $self->read_svm_props($ra, $path, $r);
424 last if $ok;
425 - $tried{"$ra->{url}/$path"} = 1;
426 + $tried{$try} = 1;
427 }
428 $path =~ s#/?[^/]+$##;
429 }
430 die "Path: '$path' should be ''\n" if $path ne '';
431 $ok ||= $self->read_svm_props($ra, $path, $r);
432 - $tried{"$ra->{url}/$path"} = 1;
433 + $tried{ add_path_to_url($ra->url, $path) } = 1;
434 if (!$ok) {
435 die @err, (map { " $_\n" } keys %tried), "\n";
436 }
437 - Git::SVN::Ra->new($self->{url});
438 + Git::SVN::Ra->new($self->url);
439 }
440
441 sub svnsync {
442 @@ -670,7 +690,7 @@ sub ra_uuid {
443 if (!$@ && $uuid && $uuid =~ /^([a-f\d\-]{30,})$/i) {
444 $self->{ra_uuid} = $uuid;
445 } else {
446 - die "ra_uuid called without URL\n" unless $self->{url};
447 + die "ra_uuid called without URL\n" unless $self->url;
448 $self->{ra_uuid} = $self->ra->get_uuid;
449 tmp_config('--add', $key, $self->{ra_uuid});
450 }
451 @@ -694,7 +714,7 @@ sub repos_root {
452
453 sub ra {
454 my ($self) = shift;
455 - my $ra = Git::SVN::Ra->new($self->{url});
456 + my $ra = Git::SVN::Ra->new($self->url);
457 $self->_set_repos_root($ra->{repos_root});
458 if ($self->use_svm_props && !$self->{svm}) {
459 if ($self->no_metadata) {
460 @@ -728,7 +748,7 @@ sub prop_walk {
461 $path =~ s#^/*#/#g;
462 my $p = $path;
463 # Strip the irrelevant part of the path.
464 - $p =~ s#^/+\Q$self->{path}\E(/|$)#/#;
465 + $p =~ s#^/+\Q@{[$self->path]}\E(/|$)#/#;
466 # Ensure the path is terminated by a `/'.
467 $p =~ s#/*$#/#;
468
469 @@ -749,7 +769,7 @@ sub prop_walk {
470
471 foreach (sort keys %$dirent) {
472 next if $dirent->{$_}->{kind} != $SVN::Node::dir;
473 - $self->prop_walk($self->{path} . $p . $_, $rev, $sub);
474 + $self->prop_walk($self->path . $p . $_, $rev, $sub);
475 }
476 }
477
478 @@ -919,20 +939,19 @@ sub rewrite_uuid {
479
480 sub metadata_url {
481 my ($self) = @_;
482 - ($self->rewrite_root || $self->{url}) .
483 - (length $self->{path} ? '/' . $self->{path} : '');
484 + my $url = $self->rewrite_root || $self->url;
485 + return canonicalize_url( add_path_to_url( $url, $self->path ) );
486 }
487
488 sub full_url {
489 my ($self) = @_;
490 - $self->{url} . (length $self->{path} ? '/' . $self->{path} : '');
491 + return canonicalize_url( add_path_to_url( $self->url, $self->path ) );
492 }
493
494 sub full_pushurl {
495 my ($self) = @_;
496 if ($self->{pushurl}) {
497 - return $self->{pushurl} . (length $self->{path} ? '/' .
498 - $self->{path} : '');
499 + return canonicalize_url( add_path_to_url( $self->{pushurl}, $self->path ) );
500 } else {
501 return $self->full_url;
502 }
503 @@ -1048,20 +1067,20 @@ sub do_git_commit {
504
505 sub match_paths {
506 my ($self, $paths, $r) = @_;
507 - return 1 if $self->{path} eq '';
508 - if (my $path = $paths->{"/$self->{path}"}) {
509 + return 1 if $self->path eq '';
510 + if (my $path = $paths->{"/".$self->path}) {
511 return ($path->{action} eq 'D') ? 0 : 1;
512 }
513 - $self->{path_regex} ||= qr/^\/\Q$self->{path}\E\//;
514 + $self->{path_regex} ||= qr{^/\Q@{[$self->path]}\E/};
515 if (grep /$self->{path_regex}/, keys %$paths) {
516 return 1;
517 }
518 my $c = '';
519 - foreach (split m#/#, $self->{path}) {
520 + foreach (split m#/#, $self->path) {
521 $c .= "/$_";
522 next unless ($paths->{$c} &&
523 ($paths->{$c}->{action} =~ /^[AR]$/));
524 - if ($self->ra->check_path($self->{path}, $r) ==
525 + if ($self->ra->check_path($self->path, $r) ==
526 $SVN::Node::dir) {
527 return 1;
528 }
529 @@ -1075,14 +1094,14 @@ sub find_parent_branch {
530 unless (defined $paths) {
531 my $err_handler = $SVN::Error::handler;
532 $SVN::Error::handler = \&Git::SVN::Ra::skip_unknown_revs;
533 - $self->ra->get_log([$self->{path}], $rev, $rev, 0, 1, 1,
534 + $self->ra->get_log([$self->path], $rev, $rev, 0, 1, 1,
535 sub { $paths = $_[0] });
536 $SVN::Error::handler = $err_handler;
537 }
538 return undef unless defined $paths;
539
540 # look for a parent from another branch:
541 - my @b_path_components = split m#/#, $self->{path};
542 + my @b_path_components = split m#/#, $self->path;
543 my @a_path_components;
544 my $i;
545 while (@b_path_components) {
546 @@ -1099,8 +1118,8 @@ sub find_parent_branch {
547 }
548 my $r = $i->{copyfrom_rev};
549 my $repos_root = $self->ra->{repos_root};
550 - my $url = $self->ra->{url};
551 - my $new_url = $url . $branch_from;
552 + my $url = $self->ra->url;
553 + my $new_url = canonicalize_url( add_path_to_url( $url, $branch_from ) );
554 print STDERR "Found possible branch point: ",
555 "$new_url => ", $self->full_url, ", $r\n"
556 unless $::_q > 1;
557 @@ -1114,7 +1133,7 @@ sub find_parent_branch {
558 ($base, $head) = parse_revision_argument(0, $r);
559 } else {
560 if ($r0 < $r) {
561 - $gs->ra->get_log([$gs->{path}], $r0 + 1, $r, 1,
562 + $gs->ra->get_log([$gs->path], $r0 + 1, $r, 1,
563 0, 1, sub { $base = $_[1] - 1 });
564 }
565 }
566 @@ -1136,7 +1155,7 @@ sub find_parent_branch {
567 # at the moment), so we can't rely on it
568 $self->{last_rev} = $r0;
569 $self->{last_commit} = $parent;
570 - $ed = Git::SVN::Fetcher->new($self, $gs->{path});
571 + $ed = Git::SVN::Fetcher->new($self, $gs->path);
572 $gs->ra->gs_do_switch($r0, $rev, $gs,
573 $self->full_url, $ed)
574 or die "SVN connection failed somewhere...\n";
575 @@ -1235,7 +1254,7 @@ sub mkemptydirs {
576 close $fh;
577 }
578
579 - my $strip = qr/\A\Q$self->{path}\E(?:\/|$)/;
580 + my $strip = qr/\A\Q@{[$self->path]}\E(?:\/|$)/;
581 foreach my $d (sort keys %empty_dirs) {
582 $d = uri_decode($d);
583 $d =~ s/$strip//;
584 @@ -1429,12 +1448,11 @@ sub find_extra_svk_parents {
585 for my $ticket ( @tickets ) {
586 my ($uuid, $path, $rev) = split /:/, $ticket;
587 if ( $uuid eq $self->ra_uuid ) {
588 - my $url = $self->{url};
589 - my $repos_root = $url;
590 + my $repos_root = $self->url;
591 my $branch_from = $path;
592 $branch_from =~ s{^/}{};
593 - my $gs = $self->other_gs($repos_root."/".$branch_from,
594 - $url,
595 + my $gs = $self->other_gs(add_path_to_url( $repos_root, $branch_from ),
596 + $repos_root,
597 $branch_from,
598 $rev,
599 $self->{ref_id});
600 @@ -1693,7 +1711,7 @@ sub find_extra_svn_parents {
601 # are now marked as merge, we can add the tip as a parent.
602 my @merges = split "\n", $mergeinfo;
603 my @merge_tips;
604 - my $url = $self->{url};
605 + my $url = $self->url;
606 my $uuid = $self->ra_uuid;
607 my %ranges;
608 for my $merge ( @merges ) {
609 @@ -1875,8 +1893,9 @@ sub make_log_entry {
610 $email ||= "$author\@$uuid";
611 $commit_email ||= "$author\@$uuid";
612 } elsif ($self->use_svnsync_props) {
613 - my $full_url = $self->svnsync->{url};
614 - $full_url .= "/$self->{path}" if length $self->{path};
615 + my $full_url = canonicalize_url(
616 + add_path_to_url( $self->svnsync->{url}, $self->path )
617 + );
618 remove_username($full_url);
619 my $uuid = $self->svnsync->{uuid};
620 $log_entry{metadata} = "$full_url\@$rev $uuid";
621 @@ -1923,7 +1942,7 @@ sub set_tree {
622 tree_b => $tree,
623 editor_cb => sub {
624 $self->set_tree_cb($log_entry, $tree, @_) },
625 - svn_path => $self->{path} );
626 + svn_path => $self->path );
627 if (!Git::SVN::Editor->new(\%ed_opts)->apply_diff) {
628 print "No changes\nr$self->{last_rev} = $tree\n";
629 }
630 @@ -2299,10 +2318,39 @@ sub _new {
631
632 $_[3] = $path = '' unless (defined $path);
633 mkpath([$dir]);
634 - bless {
635 + my $obj = bless {
636 ref_id => $ref_id, dir => $dir, index => "$dir/index",
637 - path => $path, config => "$ENV{GIT_DIR}/svn/config",
638 + config => "$ENV{GIT_DIR}/svn/config",
639 map_root => "$dir/.rev_map", repo_id => $repo_id }, $class;
640 +
641 + # Ensure it gets canonicalized
642 + $obj->path($path);
643 +
644 + return $obj;
645 +}
646 +
647 +sub path {
648 + my $self = shift;
649 +
650 + if (@_) {
651 + my $path = shift;
652 + $self->{path} = canonicalize_path($path);
653 + return;
654 + }
655 +
656 + return $self->{path};
657 +}
658 +
659 +sub url {
660 + my $self = shift;
661 +
662 + if (@_) {
663 + my $url = shift;
664 + $self->{url} = canonicalize_url($url);
665 + return;
666 + }
667 +
668 + return $self->{url};
669 }
670
671 # for read-only access of old .rev_db formats
672 diff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm
673 index 76fae9b..046a7a2 100644
674 --- a/perl/Git/SVN/Fetcher.pm
675 +++ b/perl/Git/SVN/Fetcher.pm
676 @@ -83,7 +83,7 @@ sub _mark_empty_symlinks {
677 chomp(my $empty_blob = `git hash-object -t blob --stdin < /dev/null`);
678 my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r -z/, $cmt);
679 local $/ = "\0";
680 - my $pfx = defined($switch_path) ? $switch_path : $git_svn->{path};
681 + my $pfx = defined($switch_path) ? $switch_path : $git_svn->path;
682 $pfx .= '/' if length($pfx);
683 while (<$ls>) {
684 chomp;
685 diff --git a/perl/Git/SVN/Migration.pm b/perl/Git/SVN/Migration.pm
686 index 75d7429..30daf35 100644
687 --- a/perl/Git/SVN/Migration.pm
688 +++ b/perl/Git/SVN/Migration.pm
689 @@ -177,14 +177,14 @@ sub minimize_connections {
690 my $ra = Git::SVN::Ra->new($url);
691
692 # skip existing cases where we already connect to the root
693 - if (($ra->{url} eq $ra->{repos_root}) ||
694 + if (($ra->url eq $ra->{repos_root}) ||
695 ($ra->{repos_root} eq $repo_id)) {
696 - $root_repos->{$ra->{url}} = $repo_id;
697 + $root_repos->{$ra->url} = $repo_id;
698 next;
699 }
700
701 my $root_ra = Git::SVN::Ra->new($ra->{repos_root});
702 - my $root_path = $ra->{url};
703 + my $root_path = $ra->url;
704 $root_path =~ s#^\Q$ra->{repos_root}\E(/|$)##;
705 foreach my $path (keys %$fetch) {
706 my $ref_id = $fetch->{$path};
707 diff --git a/perl/Git/SVN/Ra.pm b/perl/Git/SVN/Ra.pm
708 index 23ff43e..90ec30b 100644
709 --- a/perl/Git/SVN/Ra.pm
710 +++ b/perl/Git/SVN/Ra.pm
711 @@ -3,6 +3,12 @@ use vars qw/@ISA $config_dir $_ignore_refs_regex $_log_window_size/;
712 use strict;
713 use warnings;
714 use SVN::Client;
715 +use Git::SVN::Utils qw(
716 + canonicalize_url
717 + canonicalize_path
718 + add_path_to_url
719 +);
720 +
721 use SVN::Ra;
722 BEGIN {
723 @ISA = qw(SVN::Ra);
724 @@ -62,29 +68,11 @@ sub _auth_providers () {
725 \@rv;
726 }
727
728 -sub escape_uri_only {
729 - my ($uri) = @_;
730 - my @tmp;
731 - foreach (split m{/}, $uri) {
732 - s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
733 - push @tmp, $_;
734 - }
735 - join('/', @tmp);
736 -}
737 -
738 -sub escape_url {
739 - my ($url) = @_;
740 - if ($url =~ m#^(https?)://([^/]+)(.*)$#) {
741 - my ($scheme, $domain, $uri) = ($1, $2, escape_uri_only($3));
742 - $url = "$scheme://$domain$uri";
743 - }
744 - $url;
745 -}
746
747 sub new {
748 my ($class, $url) = @_;
749 - $url =~ s!/+$!!;
750 - return $RA if ($RA && $RA->{url} eq $url);
751 + $url = canonicalize_url($url);
752 + return $RA if ($RA && $RA->url eq $url);
753
754 ::_req_svn();
755
756 @@ -115,17 +103,34 @@ sub new {
757 $Git::SVN::Prompt::_no_auth_cache = 1;
758 }
759 } # no warnings 'once'
760 - my $self = SVN::Ra->new(url => escape_url($url), auth => $baton,
761 +
762 + my $self = SVN::Ra->new(url => $url, auth => $baton,
763 config => $config,
764 pool => SVN::Pool->new,
765 auth_provider_callbacks => $callbacks);
766 - $self->{url} = $url;
767 + $RA = bless $self, $class;
768 +
769 + # Make sure its canonicalized
770 + $self->url($url);
771 $self->{svn_path} = $url;
772 $self->{repos_root} = $self->get_repos_root;
773 $self->{svn_path} =~ s#^\Q$self->{repos_root}\E(/|$)##;
774 $self->{cache} = { check_path => { r => 0, data => {} },
775 get_dir => { r => 0, data => {} } };
776 - $RA = bless $self, $class;
777 +
778 + return $RA;
779 +}
780 +
781 +sub url {
782 + my $self = shift;
783 +
784 + if (@_) {
785 + my $url = shift;
786 + $self->{url} = canonicalize_url($url);
787 + return;
788 + }
789 +
790 + return $self->{url};
791 }
792
793 sub check_path {
794 @@ -195,6 +200,7 @@ sub get_log {
795 qw/copyfrom_path copyfrom_rev action/;
796 if ($s{'copyfrom_path'}) {
797 $s{'copyfrom_path'} =~ s/$prefix_regex//;
798 + $s{'copyfrom_path'} = canonicalize_path($s{'copyfrom_path'});
799 }
800 $_[0]{$p} = \%s;
801 }
802 @@ -246,7 +252,7 @@ sub get_commit_editor {
803 sub gs_do_update {
804 my ($self, $rev_a, $rev_b, $gs, $editor) = @_;
805 my $new = ($rev_a == $rev_b);
806 - my $path = $gs->{path};
807 + my $path = $gs->path;
808
809 if ($new && -e $gs->{index}) {
810 unlink $gs->{index} or die
811 @@ -282,30 +288,33 @@ sub gs_do_update {
812 # svn_ra_reparent didn't work before 1.4)
813 sub gs_do_switch {
814 my ($self, $rev_a, $rev_b, $gs, $url_b, $editor) = @_;
815 - my $path = $gs->{path};
816 + my $path = $gs->path;
817 my $pool = SVN::Pool->new;
818
819 - my $full_url = $self->{url};
820 - my $old_url = $full_url;
821 - $full_url .= '/' . $path if length $path;
822 + my $old_url = $self->url;
823 + my $full_url = add_path_to_url( $self->url, $path );
824 my ($ra, $reparented);
825
826 if ($old_url =~ m#^svn(\+ssh)?://# ||
827 ($full_url =~ m#^https?://# &&
828 - escape_url($full_url) ne $full_url)) {
829 + canonicalize_url($full_url) ne $full_url)) {
830 $_[0] = undef;
831 $self = undef;
832 $RA = undef;
833 $ra = Git::SVN::Ra->new($full_url);
834 $ra_invalid = 1;
835 } elsif ($old_url ne $full_url) {
836 - SVN::_Ra::svn_ra_reparent($self->{session}, $full_url, $pool);
837 - $self->{url} = $full_url;
838 + SVN::_Ra::svn_ra_reparent(
839 + $self->{session},
840 + canonicalize_url($full_url),
841 + $pool
842 + );
843 + $self->url($full_url);
844 $reparented = 1;
845 }
846
847 $ra ||= $self;
848 - $url_b = escape_url($url_b);
849 + $url_b = canonicalize_url($url_b);
850 my $reporter = $ra->do_switch($rev_b, '', 1, $url_b, $editor, $pool);
851 my @lock = (::compare_svn_version('1.2.0') >= 0) ? (undef) : ();
852 $reporter->set_path('', $rev_a, 0, @lock, $pool);
853 @@ -313,7 +322,7 @@ sub gs_do_switch {
854
855 if ($reparented) {
856 SVN::_Ra::svn_ra_reparent($self->{session}, $old_url, $pool);
857 - $self->{url} = $old_url;
858 + $self->url($old_url);
859 }
860
861 $pool->clear;
862 @@ -326,7 +335,7 @@ sub longest_common_path {
863 my $common_max = scalar @$gsv;
864
865 foreach my $gs (@$gsv) {
866 - my @tmp = split m#/#, $gs->{path};
867 + my @tmp = split m#/#, $gs->path;
868 my $p = '';
869 foreach (@tmp) {
870 $p .= length($p) ? "/$_" : $_;
871 @@ -362,7 +371,7 @@ sub gs_fetch_loop_common {
872 my $inc = $_log_window_size;
873 my ($min, $max) = ($base, $head < $base + $inc ? $head : $base + $inc);
874 my $longest_path = longest_common_path($gsv, $globs);
875 - my $ra_url = $self->{url};
876 + my $ra_url = $self->url;
877 my $find_trailing_edge;
878 while (1) {
879 my %revs;
880 @@ -508,7 +517,7 @@ sub match_globs {
881 ($self->check_path($p, $r) !=
882 $SVN::Node::dir));
883 next unless $p =~ /$g->{path}->{regex}/;
884 - $exists->{$p} = Git::SVN->init($self->{url}, $p, undef,
885 + $exists->{$p} = Git::SVN->init($self->url, $p, undef,
886 $g->{ref}->full_path($de), 1);
887 }
888 }
889 @@ -532,7 +541,7 @@ sub match_globs {
890 next if ($self->check_path($pathname, $r) !=
891 $SVN::Node::dir);
892 $exists->{$pathname} = Git::SVN->init(
893 - $self->{url}, $pathname, undef,
894 + $self->url, $pathname, undef,
895 $g->{ref}->full_path($p), 1);
896 }
897 my $c = '';
898 @@ -548,19 +557,20 @@ sub match_globs {
899
900 sub minimize_url {
901 my ($self) = @_;
902 - return $self->{url} if ($self->{url} eq $self->{repos_root});
903 + return $self->url if ($self->url eq $self->{repos_root});
904 my $url = $self->{repos_root};
905 my @components = split(m!/!, $self->{svn_path});
906 my $c = '';
907 do {
908 - $url .= "/$c" if length $c;
909 + $url = add_path_to_url($url, $c);
910 eval {
911 my $ra = (ref $self)->new($url);
912 my $latest = $ra->get_latest_revnum;
913 $ra->get_log("", $latest, 0, 1, 0, 1, sub {});
914 };
915 } while ($@ && ($c = shift @components));
916 - $url;
917 +
918 + return canonicalize_url($url);
919 }
920
921 sub can_do_switch {
922 @@ -568,7 +578,7 @@ sub can_do_switch {
923 unless (defined $can_do_switch) {
924 my $pool = SVN::Pool->new;
925 my $rep = eval {
926 - $self->do_switch(1, '', 0, $self->{url},
927 + $self->do_switch(1, '', 0, $self->url,
928 SVN::Delta::Editor->new, $pool);
929 };
930 if ($@) {
931 diff --git a/perl/Git/SVN/Utils.pm b/perl/Git/SVN/Utils.pm
932 index 496006b..4bb4dde 100644
933 --- a/perl/Git/SVN/Utils.pm
934 +++ b/perl/Git/SVN/Utils.pm
935 @@ -3,9 +3,18 @@ package Git::SVN::Utils;
936 use strict;
937 use warnings;
938
939 +use SVN::Core;
940 +
941 use base qw(Exporter);
942
943 -our @EXPORT_OK = qw(fatal can_compress);
944 +our @EXPORT_OK = qw(
945 + fatal
946 + can_compress
947 + canonicalize_path
948 + canonicalize_url
949 + join_paths
950 + add_path_to_url
951 +);
952
953
954 =head1 NAME
955 @@ -56,4 +65,169 @@ sub can_compress {
956 }
957
958
959 +=head3 canonicalize_path
960 +
961 + my $canoncalized_path = canonicalize_path($path);
962 +
963 +Converts $path into a canonical form which is safe to pass to the SVN
964 +API as a file path.
965 +
966 +=cut
967 +
968 +# Turn foo/../bar into bar
969 +sub _collapse_dotdot {
970 + my $path = shift;
971 +
972 + 1 while $path =~ s{/[^/]+/+\.\.}{};
973 + 1 while $path =~ s{[^/]+/+\.\./}{};
974 + 1 while $path =~ s{[^/]+/+\.\.}{};
975 +
976 + return $path;
977 +}
978 +
979 +
980 +sub canonicalize_path {
981 + my $path = shift;
982 + my $rv;
983 +
984 + # The 1.7 way to do it
985 + if ( defined &SVN::_Core::svn_dirent_canonicalize ) {
986 + $path = _collapse_dotdot($path);
987 + $rv = SVN::_Core::svn_dirent_canonicalize($path);
988 + }
989 + # The 1.6 way to do it
990 + # This can return undef on subversion-perl-1.4.2-2.el5 (CentOS 5.2)
991 + elsif ( defined &SVN::_Core::svn_path_canonicalize ) {
992 + $path = _collapse_dotdot($path);
993 + $rv = SVN::_Core::svn_path_canonicalize($path);
994 + }
995 +
996 + return $rv if defined $rv;
997 +
998 + # No SVN API canonicalization is available, or the SVN API
999 + # didn't return a successful result, do it ourselves
1000 + return _canonicalize_path_ourselves($path);
1001 +}
1002 +
1003 +
1004 +sub _canonicalize_path_ourselves {
1005 + my ($path) = @_;
1006 + my $dot_slash_added = 0;
1007 + if (substr($path, 0, 1) ne "/") {
1008 + $path = "./" . $path;
1009 + $dot_slash_added = 1;
1010 + }
1011 + $path =~ s#/+#/#g;
1012 + $path =~ s#/\.(?:/|$)#/#g;
1013 + $path = _collapse_dotdot($path);
1014 + $path =~ s#/$##g;
1015 + $path =~ s#^\./## if $dot_slash_added;
1016 + $path =~ s#^/##;
1017 + $path =~ s#^\.$##;
1018 + return $path;
1019 +}
1020 +
1021 +
1022 +=head3 canonicalize_url
1023 +
1024 + my $canonicalized_url = canonicalize_url($url);
1025 +
1026 +Converts $url into a canonical form which is safe to pass to the SVN
1027 +API as a URL.
1028 +
1029 +=cut
1030 +
1031 +sub canonicalize_url {
1032 + my $url = shift;
1033 +
1034 + # The 1.7 way to do it
1035 + if ( defined &SVN::_Core::svn_uri_canonicalize ) {
1036 + return SVN::_Core::svn_uri_canonicalize($url);
1037 + }
1038 + # There wasn't a 1.6 way to do it, so we do it ourself.
1039 + else {
1040 + return _canonicalize_url_ourselves($url);
1041 + }
1042 +}
1043 +
1044 +
1045 +sub _canonicalize_url_path {
1046 + my ($uri_path) = @_;
1047 +
1048 + my @parts;
1049 + foreach my $part (split m{/+}, $uri_path) {
1050 + $part =~ s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
1051 + push @parts, $part;
1052 + }
1053 +
1054 + return join('/', @parts);
1055 +}
1056 +
1057 +sub _canonicalize_url_ourselves {
1058 + my ($url) = @_;
1059 + if ($url =~ m#^([^:]+)://([^/]*)(.*)$#) {
1060 + my ($scheme, $domain, $uri) = ($1, $2, _canonicalize_url_path(canonicalize_path($3)));
1061 + $url = "$scheme://$domain$uri";
1062 + }
1063 + $url;
1064 +}
1065 +
1066 +
1067 +=head3 join_paths
1068 +
1069 + my $new_path = join_paths(@paths);
1070 +
1071 +Appends @paths together into a single path. Any empty paths are ignored.
1072 +
1073 +=cut
1074 +
1075 +sub join_paths {
1076 + my @paths = @_;
1077 +
1078 + @paths = grep { defined $_ && length $_ } @paths;
1079 +
1080 + return '' unless @paths;
1081 + return $paths[0] if @paths == 1;
1082 +
1083 + my $new_path = shift @paths;
1084 + $new_path =~ s{/+$}{};
1085 +
1086 + my $last_path = pop @paths;
1087 + $last_path =~ s{^/+}{};
1088 +
1089 + for my $path (@paths) {
1090 + $path =~ s{^/+}{};
1091 + $path =~ s{/+$}{};
1092 + $new_path .= "/$path";
1093 + }
1094 +
1095 + return $new_path .= "/$last_path";
1096 +}
1097 +
1098 +
1099 +=head3 add_path_to_url
1100 +
1101 + my $new_url = add_path_to_url($url, $path);
1102 +
1103 +Appends $path onto the $url. If $path is empty, $url is returned unchanged.
1104 +
1105 +=cut
1106 +
1107 +sub add_path_to_url {
1108 + my($url, $path) = @_;
1109 +
1110 + return $url if !defined $path or !length $path;
1111 +
1112 + # Strip trailing and leading slashes so we don't
1113 + # wind up with http://x.com///path
1114 + $url =~ s{/+$}{};
1115 + $path =~ s{^/+}{};
1116 +
1117 + # If a path has a % in it, URI escape it so it's not
1118 + # mistaken for a URI escape later.
1119 + $path =~ s{%}{%25}g;
1120 +
1121 + return join '/', $url, $path;
1122 +}
1123 +
1124 1;
1125 diff --git a/t/Git-SVN/Utils/add_path_to_url.t b/t/Git-SVN/Utils/add_path_to_url.t
1126 new file mode 100644
1127 index 0000000..bfbd878
1128 --- /dev/null
1129 +++ b/t/Git-SVN/Utils/add_path_to_url.t
1130 @@ -0,0 +1,27 @@
1131 +#!/usr/bin/env perl
1132 +
1133 +use strict;
1134 +use warnings;
1135 +
1136 +use Test::More 'no_plan';
1137 +
1138 +use Git::SVN::Utils qw(
1139 + add_path_to_url
1140 +);
1141 +
1142 +# A reference cannot be a hash key, so we use an array.
1143 +my @tests = (
1144 + ["http://x.com", "bar"] => 'http://x.com/bar',
1145 + ["http://x.com", ""] => 'http://x.com',
1146 + ["http://x.com/foo/", undef] => 'http://x.com/foo/',
1147 + ["http://x.com/foo/", "/bar/baz/"] => 'http://x.com/foo/bar/baz/',
1148 + ["http://x.com", 'per%cent'] => 'http://x.com/per%25cent',
1149 +);
1150 +
1151 +while(@tests) {
1152 + my($have, $want) = splice @tests, 0, 2;
1153 +
1154 + my $args = join ", ", map { qq['$_'] } map { defined($_) ? $_ : 'undef' } @$have;
1155 + my $name = "add_path_to_url($args) eq $want";
1156 + is add_path_to_url(@$have), $want, $name;
1157 +}
1158 diff --git a/t/Git-SVN/Utils/canonicalize_url.t b/t/Git-SVN/Utils/canonicalize_url.t
1159 new file mode 100644
1160 index 0000000..05795ab
1161 --- /dev/null
1162 +++ b/t/Git-SVN/Utils/canonicalize_url.t
1163 @@ -0,0 +1,26 @@
1164 +#!/usr/bin/env perl
1165 +
1166 +# Test our own home rolled URL canonicalizer. Test the private one
1167 +# directly because we can't predict what the SVN API is doing to do.
1168 +
1169 +use strict;
1170 +use warnings;
1171 +
1172 +use Test::More 'no_plan';
1173 +
1174 +use Git::SVN::Utils;
1175 +my $canonicalize_url = \&Git::SVN::Utils::_canonicalize_url_ourselves;
1176 +
1177 +my %tests = (
1178 + "http://x.com" => "http://x.com",
1179 + "http://x.com/" => "http://x.com",
1180 + "http://x.com/foo/bar" => "http://x.com/foo/bar",
1181 + "http://x.com//foo//bar//" => "http://x.com/foo/bar",
1182 + "http://x.com/ /%/" => "http://x.com/%20%20/%25",
1183 +);
1184 +
1185 +for my $arg (keys %tests) {
1186 + my $want = $tests{$arg};
1187 +
1188 + is $canonicalize_url->($arg), $want, "canonicalize_url('$arg') => $want";
1189 +}
1190 diff --git a/t/Git-SVN/Utils/collapse_dotdot.t b/t/Git-SVN/Utils/collapse_dotdot.t
1191 new file mode 100644
1192 index 0000000..1da1cce
1193 --- /dev/null
1194 +++ b/t/Git-SVN/Utils/collapse_dotdot.t
1195 @@ -0,0 +1,23 @@
1196 +#!/usr/bin/env perl
1197 +
1198 +use strict;
1199 +use warnings;
1200 +
1201 +use Test::More 'no_plan';
1202 +
1203 +use Git::SVN::Utils;
1204 +my $collapse_dotdot = \&Git::SVN::Utils::_collapse_dotdot;
1205 +
1206 +my %tests = (
1207 + "foo/bar/baz" => "foo/bar/baz",
1208 + ".." => "..",
1209 + "foo/.." => "",
1210 + "/foo/bar/../../baz" => "/baz",
1211 + "deeply/.././deeply/nested" => "./deeply/nested",
1212 +);
1213 +
1214 +for my $arg (keys %tests) {
1215 + my $want = $tests{$arg};
1216 +
1217 + is $collapse_dotdot->($arg), $want, "_collapse_dotdot('$arg') => $want";
1218 +}
1219 diff --git a/t/Git-SVN/Utils/join_paths.t b/t/Git-SVN/Utils/join_paths.t
1220 new file mode 100644
1221 index 0000000..d4488e7
1222 --- /dev/null
1223 +++ b/t/Git-SVN/Utils/join_paths.t
1224 @@ -0,0 +1,32 @@
1225 +#!/usr/bin/env perl
1226 +
1227 +use strict;
1228 +use warnings;
1229 +
1230 +use Test::More 'no_plan';
1231 +
1232 +use Git::SVN::Utils qw(
1233 + join_paths
1234 +);
1235 +
1236 +# A reference cannot be a hash key, so we use an array.
1237 +my @tests = (
1238 + [] => '',
1239 + ["/x.com", "bar"] => '/x.com/bar',
1240 + ["x.com", ""] => 'x.com',
1241 + ["/x.com/foo/", undef, "bar"] => '/x.com/foo/bar',
1242 + ["x.com/foo/", "/bar/baz/"] => 'x.com/foo/bar/baz/',
1243 + ["foo", "bar"] => 'foo/bar',
1244 + ["/foo/bar", "baz", "/biff"] => '/foo/bar/baz/biff',
1245 + ["", undef, "."] => '.',
1246 + [] => '',
1247 +
1248 +);
1249 +
1250 +while(@tests) {
1251 + my($have, $want) = splice @tests, 0, 2;
1252 +
1253 + my $args = join ", ", map { qq['$_'] } map { defined($_) ? $_ : 'undef' } @$have;
1254 + my $name = "join_paths($args) eq '$want'";
1255 + is join_paths(@$have), $want, $name;
1256 +}
1257 diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh
1258 index 289fc31..ee73013 100755
1259 --- a/t/t9107-git-svn-migrate.sh
1260 +++ b/t/t9107-git-svn-migrate.sh
1261 @@ -27,15 +27,17 @@ test_expect_success 'setup old-looking metadata' '
1262 head=`git rev-parse --verify refs/heads/git-svn-HEAD^0`
1263 test_expect_success 'git-svn-HEAD is a real HEAD' "test -n '$head'"
1264
1265 +svnrepo_escaped=`echo $svnrepo | sed 's/ /%20/'`
1266 +
1267 test_expect_success 'initialize old-style (v0) git svn layout' '
1268 mkdir -p "$GIT_DIR"/git-svn/info "$GIT_DIR"/svn/info &&
1269 echo "$svnrepo" > "$GIT_DIR"/git-svn/info/url &&
1270 echo "$svnrepo" > "$GIT_DIR"/svn/info/url &&
1271 git svn migrate &&
1272 - ! test -d "$GIT_DIR"/git svn &&
1273 + ! test -d "$GIT_DIR"/git-svn &&
1274 git rev-parse --verify refs/${remotes_git_svn}^0 &&
1275 git rev-parse --verify refs/remotes/svn^0 &&
1276 - test "$(git config --get svn-remote.svn.url)" = "$svnrepo" &&
1277 + test "$(git config --get svn-remote.svn.url)" = "$svnrepo_escaped" &&
1278 test `git config --get svn-remote.svn.fetch` = \
1279 ":refs/${remotes_git_svn}"
1280 '
1281 diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh
1282 index 63fc982..193d3ca 100755
1283 --- a/t/t9118-git-svn-funky-branch-names.sh
1284 +++ b/t/t9118-git-svn-funky-branch-names.sh
1285 @@ -32,6 +32,11 @@ test_expect_success 'setup svnrepo' '
1286 start_httpd
1287 '
1288
1289 +# SVN 1.7 will truncate "not-a%40{0]" to just "not-a".
1290 +# Look at what SVN wound up naming the branch and use that.
1291 +# Be sure to escape the @ if it shows up.
1292 +non_reflog=`svn_cmd ls "$svnrepo/pr ject/branches" | grep not-a | sed 's/\///' | sed 's/@/%40/'`
1293 +
1294 test_expect_success 'test clone with funky branch names' '
1295 git svn clone -s "$svnrepo/pr ject" project &&
1296 (
1297 @@ -42,7 +47,7 @@ test_expect_success 'test clone with funky branch names' '
1298 git rev-parse "refs/remotes/%2Eleading_dot" &&
1299 git rev-parse "refs/remotes/trailing_dot%2E" &&
1300 git rev-parse "refs/remotes/trailing_dotlock%2Elock" &&
1301 - git rev-parse "refs/remotes/not-a%40{0}reflog"
1302 + git rev-parse "refs/remotes/$non_reflog"
1303 )
1304 '
1305
1306
1307
1308
1309 1.1 dev-vcs/git/files/git-1.7.12-optional-cvs.patch
1310
1311 file : http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-vcs/git/files/git-1.7.12-optional-cvs.patch?rev=1.1&view=markup
1312 plain: http://sources.gentoo.org/viewvc.cgi/gentoo-x86/dev-vcs/git/files/git-1.7.12-optional-cvs.patch?rev=1.1&content-type=text/plain
1313
1314 Index: git-1.7.12-optional-cvs.patch
1315 ===================================================================
1316 From eadb20b065c33d46b49c8c95d8cde0c9fe7c62a4 Mon Sep 17 00:00:00 2001
1317 From: Robin Johnson <robbat2@g.o>
1318 Date: Wed, 22 Aug 2012 04:25:06 +0000
1319 Subject: [PATCH] Makefile: Add NO_CVS define to disable all CVS interface
1320 utilities
1321
1322 Forward-ported from 1.7.10.2 to current git.git v1.7.12 tag PLUS fix-svn branch.
1323
1324 diff -Nuar --exclude '*.orig' --exclude '*.rej' git-1.7.12.orig/Makefile git-1.7.12/Makefile
1325 --- git-1.7.12.orig/Makefile 2012-08-20 01:22:48.000000000 +0000
1326 +++ git-1.7.12/Makefile 2012-08-22 04:23:48.335032122 +0000
1327 @@ -224,6 +224,8 @@
1328 #
1329 # Define NO_TCLTK if you do not want Tcl/Tk GUI.
1330 #
1331 +# Define NO_CVS if you do not want any CVS interface utilities.
1332 +#
1333 # The TCL_PATH variable governs the location of the Tcl interpreter
1334 # used to optimize git-gui for your system. Only used if NO_TCLTK
1335 # is not set. Defaults to the bare 'tclsh'.
1336 @@ -405,6 +407,7 @@
1337 PROGRAM_OBJS =
1338 PROGRAMS =
1339 SCRIPT_PERL =
1340 +SCRIPT_PERL_CVS =
1341 SCRIPT_PYTHON =
1342 SCRIPT_SH =
1343 SCRIPT_LIB =
1344 @@ -445,18 +448,19 @@
1345 SCRIPT_PERL += git-add--interactive.perl
1346 SCRIPT_PERL += git-difftool.perl
1347 SCRIPT_PERL += git-archimport.perl
1348 -SCRIPT_PERL += git-cvsexportcommit.perl
1349 -SCRIPT_PERL += git-cvsimport.perl
1350 -SCRIPT_PERL += git-cvsserver.perl
1351 SCRIPT_PERL += git-relink.perl
1352 SCRIPT_PERL += git-send-email.perl
1353 SCRIPT_PERL += git-svn.perl
1354
1355 +SCRIPT_PERL_CVS += git-cvsexportcommit.perl
1356 +SCRIPT_PERL_CVS += git-cvsimport.perl
1357 +SCRIPT_PERL_CVS += git-cvsserver.perl
1358 +
1359 SCRIPT_PYTHON += git-remote-testgit.py
1360 SCRIPT_PYTHON += git-p4.py
1361
1362 SCRIPTS = $(patsubst %.sh,%,$(SCRIPT_SH)) \
1363 - $(patsubst %.perl,%,$(SCRIPT_PERL)) \
1364 + $(patsubst %.perl,%,$(SCRIPT_PERL) $(SCRIPT_PERL_CVS)) \
1365 $(patsubst %.py,%,$(SCRIPT_PYTHON)) \
1366 git-instaweb
1367
1368 @@ -2088,8 +2092,18 @@
1369 $(QUIET_GEN)$(cmd_munge_script) && \
1370 mv $@+ $@
1371
1372 +_SCRIPT_PERL_BUILD =
1373 +_SCRIPT_PERL_NOBUILD =
1374 +
1375 ifndef NO_PERL
1376 -$(patsubst %.perl,%,$(SCRIPT_PERL)): perl/perl.mak
1377 +
1378 +_SCRIPT_PERL_BUILD += $(SCRIPT_PERL)
1379 +
1380 +ifndef NO_CVS
1381 +_SCRIPT_PERL_BUILD += $(SCRIPT_PERL_CVS)
1382 +else # NO_CVS
1383 +_SCRIPT_PERL_NOBUILD += $(SCRIPT_PERL_CVS)
1384 +endif # NO_CVS
1385
1386 perl/perl.mak: perl/PM.stamp
1387
1388 @@ -2101,7 +2115,7 @@
1389 perl/perl.mak: GIT-CFLAGS GIT-PREFIX perl/Makefile perl/Makefile.PL
1390 $(QUIET_SUBDIR0)perl $(QUIET_SUBDIR1) PERL_PATH='$(PERL_PATH_SQ)' prefix='$(prefix_SQ)' $(@F)
1391
1392 -$(patsubst %.perl,%,$(SCRIPT_PERL)): % : %.perl GIT-VERSION-FILE
1393 +$(patsubst %.perl,%,$(_SCRIPT_PERL_BUILD)): % : %.perl GIT-VERSION-FILE
1394 $(QUIET_GEN)$(RM) $@ $@+ && \
1395 INSTLIBDIR=`MAKEFLAGS= $(MAKE) -C perl -s --no-print-directory instlibdir` && \
1396 sed -e '1{' \
1397 @@ -2126,14 +2140,17 @@
1398 chmod +x $@+ && \
1399 mv $@+ $@
1400 else # NO_PERL
1401 -$(patsubst %.perl,%,$(SCRIPT_PERL)) git-instaweb: % : unimplemented.sh
1402 +_SCRIPT_PERL_NOBUILD += $(SCRIPT_PERL) $(SCRIPT_PERL_CVS) git-instaweb
1403 +endif # NO_PERL
1404 +
1405 +# This is any perl scripts that were disabled it might be empty...
1406 +$(patsubst %.perl,%,$(_SCRIPT_PERL_NOBUILD)): % : unimplemented.sh
1407 $(QUIET_GEN)$(RM) $@ $@+ && \
1408 sed -e '1s|#!.*/sh|#!$(SHELL_PATH_SQ)|' \
1409 -e 's|@@REASON@@|NO_PERL=$(NO_PERL)|g' \
1410 unimplemented.sh >$@+ && \
1411 chmod +x $@+ && \
1412 mv $@+ $@
1413 -endif # NO_PERL
1414
1415 ifndef NO_PYTHON
1416 $(patsubst %.py,%,$(SCRIPT_PYTHON)): GIT-CFLAGS GIT-PREFIX
1417 diff -Nuar --exclude '*.orig' --exclude '*.rej' git-1.7.12.orig/t/t9200-git-cvsexportcommit.sh git-1.7.12/t/t9200-git-cvsexportcommit.sh
1418 --- git-1.7.12.orig/t/t9200-git-cvsexportcommit.sh 2012-08-20 01:22:48.000000000 +0000
1419 +++ git-1.7.12/t/t9200-git-cvsexportcommit.sh 2012-08-22 04:19:23.650741974 +0000
1420 @@ -12,6 +12,11 @@
1421 test_done
1422 fi
1423
1424 +if ! test_have_prereq CVS; then
1425 + skip_all='skipping git cvsexportcommit tests, cvs not available'
1426 + test_done
1427 +fi
1428 +
1429 cvs >/dev/null 2>&1
1430 if test $? -ne 1
1431 then
1432 diff -Nuar --exclude '*.orig' --exclude '*.rej' git-1.7.12.orig/t/t9400-git-cvsserver-server.sh git-1.7.12/t/t9400-git-cvsserver-server.sh
1433 --- git-1.7.12.orig/t/t9400-git-cvsserver-server.sh 2012-08-20 01:22:48.000000000 +0000
1434 +++ git-1.7.12/t/t9400-git-cvsserver-server.sh 2012-08-22 04:19:23.650741974 +0000
1435 @@ -11,9 +11,15 @@
1436 . ./test-lib.sh
1437
1438 if ! test_have_prereq PERL; then
1439 - skip_all='skipping git cvsserver tests, perl not available'
1440 + skip_all='skipping git-cvsserver tests, perl not available'
1441 test_done
1442 fi
1443 +
1444 +if ! test_have_prereq CVS; then
1445 + skip_all='skipping git-cvsserver tests, cvs not available'
1446 + test_done
1447 +fi
1448 +
1449 cvs >/dev/null 2>&1
1450 if test $? -ne 1
1451 then
1452 diff -Nuar --exclude '*.orig' --exclude '*.rej' git-1.7.12.orig/t/t9401-git-cvsserver-crlf.sh git-1.7.12/t/t9401-git-cvsserver-crlf.sh
1453 --- git-1.7.12.orig/t/t9401-git-cvsserver-crlf.sh 2012-08-20 01:22:48.000000000 +0000
1454 +++ git-1.7.12/t/t9401-git-cvsserver-crlf.sh 2012-08-22 04:19:23.650741974 +0000
1455 @@ -38,15 +38,20 @@
1456 fi
1457 }
1458
1459 -cvs >/dev/null 2>&1
1460 -if test $? -ne 1
1461 +if ! test_have_prereq PERL
1462 then
1463 - skip_all='skipping git-cvsserver tests, cvs not found'
1464 + skip_all='skipping git-cvsserver tests, perl not available'
1465 test_done
1466 fi
1467 -if ! test_have_prereq PERL
1468 +if ! test_have_prereq CVS
1469 then
1470 - skip_all='skipping git-cvsserver tests, perl not available'
1471 + skip_all='skipping git-cvsserver tests, cvs not available'
1472 + test_done
1473 +fi
1474 +cvs >/dev/null 2>&1
1475 +if test $? -ne 1
1476 +then
1477 + skip_all='skipping git-cvsserver tests, cvs not found'
1478 test_done
1479 fi
1480 "$PERL_PATH" -e 'use DBI; use DBD::SQLite' >/dev/null 2>&1 || {
1481 diff -Nuar --exclude '*.orig' --exclude '*.rej' git-1.7.12.orig/t/t9600-cvsimport.sh git-1.7.12/t/t9600-cvsimport.sh
1482 --- git-1.7.12.orig/t/t9600-cvsimport.sh 2012-08-20 01:22:48.000000000 +0000
1483 +++ git-1.7.12/t/t9600-cvsimport.sh 2012-08-22 04:19:23.650741974 +0000
1484 @@ -3,14 +3,25 @@
1485 test_description='git cvsimport basic tests'
1486 . ./lib-cvs.sh
1487
1488 -test_expect_success PERL 'setup cvsroot environment' '
1489 +if ! test_have_prereq PERL
1490 +then
1491 + skip_all='skipping git cvsimport tests, perl not available'
1492 + test_done
1493 +fi
1494 +if ! test_have_prereq CVS
1495 +then
1496 + skip_all='skipping git cvsimport tests, cvs not available'
1497 + test_done
1498 +fi
1499 +
1500 +test_expect_success 'setup cvsroot environment' '
1501 CVSROOT=$(pwd)/cvsroot &&
1502 export CVSROOT
1503 '
1504
1505 -test_expect_success PERL 'setup cvsroot' '$CVS init'
1506 +test_expect_success 'setup cvsroot' '$CVS init'
1507
1508 -test_expect_success PERL 'setup a cvs module' '
1509 +test_expect_success 'setup a cvs module' '
1510
1511 mkdir "$CVSROOT/module" &&
1512 $CVS co -d module-cvs module &&
1513 @@ -42,23 +53,23 @@
1514 )
1515 '
1516
1517 -test_expect_success PERL 'import a trivial module' '
1518 +test_expect_success 'import a trivial module' '
1519
1520 git cvsimport -a -R -z 0 -C module-git module &&
1521 test_cmp module-cvs/o_fortuna module-git/o_fortuna
1522
1523 '
1524
1525 -test_expect_success PERL 'pack refs' '(cd module-git && git gc)'
1526 +test_expect_success 'pack refs' '(cd module-git && git gc)'
1527
1528 -test_expect_success PERL 'initial import has correct .git/cvs-revisions' '
1529 +test_expect_success 'initial import has correct .git/cvs-revisions' '
1530
1531 (cd module-git &&
1532 git log --format="o_fortuna 1.1 %H" -1) > expected &&
1533 test_cmp expected module-git/.git/cvs-revisions
1534 '
1535
1536 -test_expect_success PERL 'update cvs module' '
1537 +test_expect_success 'update cvs module' '
1538 (cd module-cvs &&
1539 cat <<EOF >o_fortuna &&
1540 O Fortune,
1541 @@ -86,7 +97,7 @@
1542 )
1543 '
1544
1545 -test_expect_success PERL 'update git module' '
1546 +test_expect_success 'update git module' '
1547
1548 (cd module-git &&
1549 git config cvsimport.trackRevisions true &&
1550 @@ -97,7 +108,7 @@
1551
1552 '
1553
1554 -test_expect_success PERL 'update has correct .git/cvs-revisions' '
1555 +test_expect_success 'update has correct .git/cvs-revisions' '
1556
1557 (cd module-git &&
1558 git log --format="o_fortuna 1.1 %H" -1 HEAD^ &&
1559 @@ -105,7 +116,7 @@
1560 test_cmp expected module-git/.git/cvs-revisions
1561 '
1562
1563 -test_expect_success PERL 'update cvs module' '
1564 +test_expect_success 'update cvs module' '
1565
1566 (cd module-cvs &&
1567 echo 1 >tick &&
1568 @@ -114,7 +125,7 @@
1569 )
1570 '
1571
1572 -test_expect_success PERL 'cvsimport.module config works' '
1573 +test_expect_success 'cvsimport.module config works' '
1574
1575 (cd module-git &&
1576 git config cvsimport.module module &&
1577 @@ -126,7 +137,7 @@
1578
1579 '
1580
1581 -test_expect_success PERL 'second update has correct .git/cvs-revisions' '
1582 +test_expect_success 'second update has correct .git/cvs-revisions' '
1583
1584 (cd module-git &&
1585 git log --format="o_fortuna 1.1 %H" -1 HEAD^^ &&
1586 @@ -135,7 +146,7 @@
1587 test_cmp expected module-git/.git/cvs-revisions
1588 '
1589
1590 -test_expect_success PERL 'import from a CVS working tree' '
1591 +test_expect_success 'import from a CVS working tree' '
1592
1593 $CVS co -d import-from-wt module &&
1594 (cd import-from-wt &&
1595 @@ -148,12 +159,12 @@
1596
1597 '
1598
1599 -test_expect_success PERL 'no .git/cvs-revisions created by default' '
1600 +test_expect_success 'no .git/cvs-revisions created by default' '
1601
1602 ! test -e import-from-wt/.git/cvs-revisions
1603
1604 '
1605
1606 -test_expect_success PERL 'test entire HEAD' 'test_cmp_branch_tree master'
1607 +test_expect_success 'test entire HEAD' 'test_cmp_branch_tree master'
1608
1609 test_done
1610 diff -Nuar --exclude '*.orig' --exclude '*.rej' git-1.7.12.orig/t/t9601-cvsimport-vendor-branch.sh git-1.7.12/t/t9601-cvsimport-vendor-branch.sh
1611 --- git-1.7.12.orig/t/t9601-cvsimport-vendor-branch.sh 2012-08-20 01:22:48.000000000 +0000
1612 +++ git-1.7.12/t/t9601-cvsimport-vendor-branch.sh 2012-08-22 04:19:23.650741974 +0000
1613 @@ -34,6 +34,17 @@
1614 test_description='git cvsimport handling of vendor branches'
1615 . ./lib-cvs.sh
1616
1617 +if ! test_have_prereq PERL
1618 +then
1619 + skip_all='skipping git cvsimport tests, perl not available'
1620 + test_done
1621 +fi
1622 +if ! test_have_prereq CVS
1623 +then
1624 + skip_all='skipping git cvsimport tests, cvs not available'
1625 + test_done
1626 +fi
1627 +
1628 setup_cvs_test_repository t9601
1629
1630 test_expect_success PERL 'import a module with a vendor branch' '
1631 diff -Nuar --exclude '*.orig' --exclude '*.rej' git-1.7.12.orig/t/t9602-cvsimport-branches-tags.sh git-1.7.12/t/t9602-cvsimport-branches-tags.sh
1632 --- git-1.7.12.orig/t/t9602-cvsimport-branches-tags.sh 2012-08-20 01:22:48.000000000 +0000
1633 +++ git-1.7.12/t/t9602-cvsimport-branches-tags.sh 2012-08-22 04:19:23.650741974 +0000
1634 @@ -6,6 +6,17 @@
1635 test_description='git cvsimport handling of branches and tags'
1636 . ./lib-cvs.sh
1637
1638 +if ! test_have_prereq PERL
1639 +then
1640 + skip_all='skipping git cvsimport tests, perl not available'
1641 + test_done
1642 +fi
1643 +if ! test_have_prereq CVS
1644 +then
1645 + skip_all='skipping git cvsimport tests, cvs not available'
1646 + test_done
1647 +fi
1648 +
1649 setup_cvs_test_repository t9602
1650
1651 test_expect_success PERL 'import module' '
1652 diff -Nuar --exclude '*.orig' --exclude '*.rej' git-1.7.12.orig/t/t9603-cvsimport-patchsets.sh git-1.7.12/t/t9603-cvsimport-patchsets.sh
1653 --- git-1.7.12.orig/t/t9603-cvsimport-patchsets.sh 2012-08-20 01:22:48.000000000 +0000
1654 +++ git-1.7.12/t/t9603-cvsimport-patchsets.sh 2012-08-22 04:19:23.650741974 +0000
1655 @@ -14,6 +14,17 @@
1656 test_description='git cvsimport testing for correct patchset estimation'
1657 . ./lib-cvs.sh
1658
1659 +if ! test_have_prereq PERL
1660 +then
1661 + skip_all='skipping git cvsimport tests, perl not available'
1662 + test_done
1663 +fi
1664 +if ! test_have_prereq CVS
1665 +then
1666 + skip_all='skipping git cvsimport tests, cvs not available'
1667 + test_done
1668 +fi
1669 +
1670 setup_cvs_test_repository t9603
1671
1672 test_expect_failure 'import with criss cross times on revisions' '
1673 diff -Nuar --exclude '*.orig' --exclude '*.rej' git-1.7.12.orig/t/test-lib.sh git-1.7.12/t/test-lib.sh
1674 --- git-1.7.12.orig/t/test-lib.sh 2012-08-20 01:22:48.000000000 +0000
1675 +++ git-1.7.12/t/test-lib.sh 2012-08-22 04:19:23.650741974 +0000
1676 @@ -618,6 +618,7 @@
1677 esac
1678
1679 ( COLUMNS=1 && test $COLUMNS = 1 ) && test_set_prereq COLUMNS_CAN_BE_1
1680 +test -z "$NO_CVS" && test_set_prereq CVS
1681 test -z "$NO_PERL" && test_set_prereq PERL
1682 test -z "$NO_PYTHON" && test_set_prereq PYTHON
1683 test -n "$USE_LIBPCRE" && test_set_prereq LIBPCRE