/[gentoo-x86]/dev-vcs/git/files/git-1.7.12-git-svn-backport.patch
Gentoo

Contents of /dev-vcs/git/files/git-1.7.12-git-svn-backport.patch

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.2 - (hide annotations) (download)
Tue Feb 4 09:36:35 2014 UTC (3 years, 7 months ago) by polynomial-c
Branch: MAIN
CVS Tags: HEAD
Changes since 1.1: +0 -0 lines
FILE REMOVED
Added rewritten init script which no longer contains "need net" (bug #490446). Added epatch_user (bug #497292). Added www-servers/nginx to the list of server who work with git-instaweb (bug #491862). Removed reference to no longer needed patch in remaining ebuilds. Removed old files and ebuilds

(Portage version: 2.2.8-r1/cvs/Linux x86_64, signed Manifest commit with key 0x981CA6FC)

1 robbat2 1.1 commit 0dfcf2dacd4be3f0c647a987b78def5136429165
2     Merge: 889d358 5eaa1fd
3     Author: Junio C Hamano <gitster@pobox.com>
4     Date: Tue Aug 21 15:27:57 2012 -0700
5    
6     Merge branch 'ms/git-svn-1.7' into jch
7    
8     A series by Michael Schwern via Eric to update git-svn to revamp the
9     way URLs are internally passed around, to make it work with SVN 1.7.
10    
11     Will merge to 'next' after pinging Eric to double check and then to 'master'.
12    
13     * ms/git-svn-1.7:
14     git-svn: remove ad-hoc canonicalizations
15     git-svn: canonicalize newly-minted URLs
16     git-svn: introduce add_path_to_url function
17     git-svn: canonicalize earlier
18     git-svn: replace URL escapes with canonicalization
19     git-svn: attempt to mimic SVN 1.7 URL canonicalization
20     t9107: fix typo
21     t9118: workaround inconsistency between SVN versions
22     Git::SVN{,::Ra}: canonicalize earlier
23     git-svn: path canonicalization uses SVN API
24     Git::SVN::Utils: remove irrelevant comment
25     git-svn: add join_paths() to safely concatenate paths
26     git-svn: factor out _collapse_dotdot function
27     git-svn: use SVN 1.7 to canonicalize when possible
28     git-svn: move canonicalization to Git::SVN::Utils
29     use Git::SVN{,::RA}->url accessor globally
30     use Git::SVN->path accessor globally
31     Git::SVN::Ra: use accessor for URLs
32     Git::SVN: use accessor for URLs internally
33     Git::SVN: use accessors internally for path
34    
35     diff --git a/git-svn.perl b/git-svn.perl
36     index 828b8f0..0d77ffb 100755
37     --- a/git-svn.perl
38     +++ b/git-svn.perl
39     @@ -29,7 +29,16 @@ use Git::SVN::Prompt;
40     use Git::SVN::Log;
41     use Git::SVN::Migration;
42    
43     -use Git::SVN::Utils qw(fatal can_compress);
44     +use Git::SVN::Utils qw(
45     + fatal
46     + can_compress
47     + canonicalize_path
48     + canonicalize_url
49     + join_paths
50     + add_path_to_url
51     + join_paths
52     +);
53     +
54     use Git qw(
55     git_cmd_try
56     command
57     @@ -1231,7 +1240,7 @@ sub cmd_show_ignore {
58     my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
59     $gs ||= Git::SVN->new;
60     my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
61     - $gs->prop_walk($gs->{path}, $r, sub {
62     + $gs->prop_walk($gs->path, $r, sub {
63     my ($gs, $path, $props) = @_;
64     print STDOUT "\n# $path\n";
65     my $s = $props->{'svn:ignore'} or return;
66     @@ -1247,7 +1256,7 @@ sub cmd_show_externals {
67     my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
68     $gs ||= Git::SVN->new;
69     my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
70     - $gs->prop_walk($gs->{path}, $r, sub {
71     + $gs->prop_walk($gs->path, $r, sub {
72     my ($gs, $path, $props) = @_;
73     print STDOUT "\n# $path\n";
74     my $s = $props->{'svn:externals'} or return;
75     @@ -1262,7 +1271,7 @@ sub cmd_create_ignore {
76     my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
77     $gs ||= Git::SVN->new;
78     my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
79     - $gs->prop_walk($gs->{path}, $r, sub {
80     + $gs->prop_walk($gs->path, $r, sub {
81     my ($gs, $path, $props) = @_;
82     # $path is of the form /path/to/dir/
83     $path = '.' . $path;
84     @@ -1292,31 +1301,6 @@ sub cmd_mkdirs {
85     $gs->mkemptydirs($_revision);
86     }
87    
88     -sub canonicalize_path {
89     - my ($path) = @_;
90     - my $dot_slash_added = 0;
91     - if (substr($path, 0, 1) ne "/") {
92     - $path = "./" . $path;
93     - $dot_slash_added = 1;
94     - }
95     - # File::Spec->canonpath doesn't collapse x/../y into y (for a
96     - # good reason), so let's do this manually.
97     - $path =~ s#/+#/#g;
98     - $path =~ s#/\.(?:/|$)#/#g;
99     - $path =~ s#/[^/]+/\.\.##g;
100     - $path =~ s#/$##g;
101     - $path =~ s#^\./## if $dot_slash_added;
102     - $path =~ s#^/##;
103     - $path =~ s#^\.$##;
104     - return $path;
105     -}
106     -
107     -sub canonicalize_url {
108     - my ($url) = @_;
109     - $url =~ s#^([^:]+://[^/]*/)(.*)$#$1 . canonicalize_path($2)#e;
110     - return $url;
111     -}
112     -
113     # get_svnprops(PATH)
114     # ------------------
115     # Helper for cmd_propget and cmd_proplist below.
116     @@ -1330,7 +1314,7 @@ sub get_svnprops {
117     $path = $cmd_dir_prefix . $path;
118     fatal("No such file or directory: $path") unless -e $path;
119     my $is_dir = -d $path ? 1 : 0;
120     - $path = $gs->{path} . '/' . $path;
121     + $path = join_paths($gs->{path}, $path);
122    
123     # canonicalize the path (otherwise libsvn will abort or fail to
124     # find the file)
125     @@ -1431,8 +1415,8 @@ sub cmd_commit_diff {
126     fatal("Needed URL or usable git-svn --id in ",
127     "the command-line\n", $usage);
128     }
129     - $url = $gs->{url};
130     - $svn_path = $gs->{path};
131     + $url = $gs->url;
132     + $svn_path = $gs->path;
133     }
134     unless (defined $_revision) {
135     fatal("-r|--revision is a required argument\n", $usage);
136     @@ -1466,24 +1450,6 @@ sub cmd_commit_diff {
137     }
138     }
139    
140     -sub escape_uri_only {
141     - my ($uri) = @_;
142     - my @tmp;
143     - foreach (split m{/}, $uri) {
144     - s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
145     - push @tmp, $_;
146     - }
147     - join('/', @tmp);
148     -}
149     -
150     -sub escape_url {
151     - my ($url) = @_;
152     - if ($url =~ m#^([^:]+)://([^/]*)(.*)$#) {
153     - my ($scheme, $domain, $uri) = ($1, $2, escape_uri_only($3));
154     - $url = "$scheme://$domain$uri";
155     - }
156     - $url;
157     -}
158    
159     sub cmd_info {
160     my $path = canonicalize_path(defined($_[0]) ? $_[0] : ".");
161     @@ -1508,21 +1474,21 @@ sub cmd_info {
162     # canonicalize_path() will return "" to make libsvn 1.5.x happy,
163     $path = "." if $path eq "";
164    
165     - my $full_url = $url . ($fullpath eq "" ? "" : "/$fullpath");
166     + my $full_url = canonicalize_url( add_path_to_url( $url, $fullpath ) );
167    
168     if ($_url) {
169     - print escape_url($full_url), "\n";
170     + print "$full_url\n";
171     return;
172     }
173    
174     my $result = "Path: $path\n";
175     $result .= "Name: " . basename($path) . "\n" if $file_type ne "dir";
176     - $result .= "URL: " . escape_url($full_url) . "\n";
177     + $result .= "URL: $full_url\n";
178    
179     eval {
180     my $repos_root = $gs->repos_root;
181     Git::SVN::remove_username($repos_root);
182     - $result .= "Repository Root: " . escape_url($repos_root) . "\n";
183     + $result .= "Repository Root: " . canonicalize_url($repos_root) . "\n";
184     };
185     if ($@) {
186     $result .= "Repository Root: (offline)\n";
187     @@ -1669,7 +1635,9 @@ sub post_fetch_checkout {
188    
189     sub complete_svn_url {
190     my ($url, $path) = @_;
191     - $path =~ s#/+$##;
192     + $path = canonicalize_path($path);
193     +
194     + # If the path is not a URL...
195     if ($path !~ m#^[a-z\+]+://#) {
196     if (!defined $url || $url !~ m#^[a-z\+]+://#) {
197     fatal("E: '$path' is not a complete URL ",
198     @@ -1686,7 +1654,7 @@ sub complete_url_ls_init {
199     print STDERR "W: $switch not specified\n";
200     return;
201     }
202     - $repo_path =~ s#/+$##;
203     + $repo_path = canonicalize_path($repo_path);
204     if ($repo_path =~ m#^[a-z\+]+://#) {
205     $ra = Git::SVN::Ra->new($repo_path);
206     $repo_path = '';
207     @@ -1697,18 +1665,18 @@ sub complete_url_ls_init {
208     "and a separate URL is not specified");
209     }
210     }
211     - my $url = $ra->{url};
212     + my $url = $ra->url;
213     my $gs = Git::SVN->init($url, undef, undef, undef, 1);
214     my $k = "svn-remote.$gs->{repo_id}.url";
215     my $orig_url = eval { command_oneline(qw/config --get/, $k) };
216     - if ($orig_url && ($orig_url ne $gs->{url})) {
217     + if ($orig_url && ($orig_url ne $gs->url)) {
218     die "$k already set: $orig_url\n",
219     - "wanted to set to: $gs->{url}\n";
220     + "wanted to set to: $gs->url\n";
221     }
222     - command_oneline('config', $k, $gs->{url}) unless $orig_url;
223     - my $remote_path = "$gs->{path}/$repo_path";
224     + command_oneline('config', $k, $gs->url) unless $orig_url;
225     +
226     + my $remote_path = join_paths( $gs->path, $repo_path );
227     $remote_path =~ s{%([0-9A-F]{2})}{chr hex($1)}ieg;
228     - $remote_path =~ s#/+#/#g;
229     $remote_path =~ s#^/##g;
230     $remote_path .= "/*" if $remote_path !~ /\*/;
231     my ($n) = ($switch =~ /^--(\w+)/);
232     diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm
233     index 8478d0c..acb2539 100644
234     --- a/perl/Git/SVN.pm
235     +++ b/perl/Git/SVN.pm
236     @@ -23,7 +23,14 @@ use Git qw(
237     command_output_pipe
238     command_close_pipe
239     );
240     -use Git::SVN::Utils qw(fatal can_compress);
241     +use Git::SVN::Utils qw(
242     + fatal
243     + can_compress
244     + join_paths
245     + canonicalize_path
246     + canonicalize_url
247     + add_path_to_url
248     +);
249    
250     my $can_use_yaml;
251     BEGIN {
252     @@ -195,9 +202,9 @@ sub read_all_remotes {
253     } elsif (m!^(.+)\.usesvmprops=\s*(.*)\s*$!) {
254     $r->{$1}->{svm} = {};
255     } elsif (m!^(.+)\.url=\s*(.*)\s*$!) {
256     - $r->{$1}->{url} = $2;
257     + $r->{$1}->{url} = canonicalize_url($2);
258     } elsif (m!^(.+)\.pushurl=\s*(.*)\s*$!) {
259     - $r->{$1}->{pushurl} = $2;
260     + $r->{$1}->{pushurl} = canonicalize_url($2);
261     } elsif (m!^(.+)\.ignore-refs=\s*(.*)\s*$!) {
262     $r->{$1}->{ignore_refs_regex} = $2;
263     } elsif (m!^(.+)\.(branches|tags)=$svn_refspec$!) {
264     @@ -290,7 +297,7 @@ sub find_existing_remote {
265    
266     sub init_remote_config {
267     my ($self, $url, $no_write) = @_;
268     - $url =~ s!/+$!!; # strip trailing slash
269     + $url = canonicalize_url($url);
270     my $r = read_all_remotes();
271     my $existing = find_existing_remote($url, $r);
272     if ($existing) {
273     @@ -314,12 +321,10 @@ sub init_remote_config {
274     print STDERR "Using higher level of URL: ",
275     "$url => $min_url\n";
276     }
277     - my $old_path = $self->{path};
278     - $self->{path} = $url;
279     - $self->{path} =~ s!^\Q$min_url\E(/|$)!!;
280     - if (length $old_path) {
281     - $self->{path} .= "/$old_path";
282     - }
283     + my $old_path = $self->path;
284     + $url =~ s!^\Q$min_url\E(/|$)!!;
285     + $url = join_paths($url, $old_path);
286     + $self->path($url);
287     $url = $min_url;
288     }
289     }
290     @@ -343,18 +348,22 @@ sub init_remote_config {
291     unless ($no_write) {
292     command_noisy('config',
293     "svn-remote.$self->{repo_id}.url", $url);
294     - $self->{path} =~ s{^/}{};
295     - $self->{path} =~ s{%([0-9A-F]{2})}{chr hex($1)}ieg;
296     + my $path = $self->path;
297     + $path =~ s{^/}{};
298     + $path =~ s{%([0-9A-F]{2})}{chr hex($1)}ieg;
299     + $self->path($path);
300     command_noisy('config', '--add',
301     "svn-remote.$self->{repo_id}.fetch",
302     - "$self->{path}:".$self->refname);
303     + $self->path.":".$self->refname);
304     }
305     - $self->{url} = $url;
306     + $self->url($url);
307     }
308    
309     sub find_by_url { # repos_root and, path are optional
310     my ($class, $full_url, $repos_root, $path) = @_;
311    
312     + $full_url = canonicalize_url($full_url);
313     +
314     return undef unless defined $full_url;
315     remove_username($full_url);
316     remove_username($repos_root) if defined $repos_root;
317     @@ -393,6 +402,11 @@ sub find_by_url { # repos_root and, path are optional
318     }
319     $p =~ s#^\Q$z\E(?:/|$)#$prefix# or next;
320     }
321     +
322     + # remote fetch paths are not URI escaped. Decode ours
323     + # so they match
324     + $p = uri_decode($p);
325     +
326     foreach my $f (keys %$fetch) {
327     next if $f ne $p;
328     return Git::SVN->new($fetch->{$f}, $repo_id, $f);
329     @@ -435,20 +449,25 @@ sub new {
330     }
331     }
332     my $self = _new($class, $repo_id, $ref_id, $path);
333     - if (!defined $self->{path} || !length $self->{path}) {
334     + if (!defined $self->path || !length $self->path) {
335     my $fetch = command_oneline('config', '--get',
336     "svn-remote.$repo_id.fetch",
337     ":$ref_id\$") or
338     die "Failed to read \"svn-remote.$repo_id.fetch\" ",
339     "\":$ref_id\$\" in config\n";
340     - ($self->{path}, undef) = split(/\s*:\s*/, $fetch);
341     + my($path) = split(/\s*:\s*/, $fetch);
342     + $self->path($path);
343     }
344     - $self->{path} =~ s{/+}{/}g;
345     - $self->{path} =~ s{\A/}{};
346     - $self->{path} =~ s{/\z}{};
347     - $self->{url} = command_oneline('config', '--get',
348     - "svn-remote.$repo_id.url") or
349     + {
350     + my $path = $self->path;
351     + $path =~ s{\A/}{};
352     + $path =~ s{/\z}{};
353     + $self->path($path);
354     + }
355     + my $url = command_oneline('config', '--get',
356     + "svn-remote.$repo_id.url") or
357     die "Failed to read \"svn-remote.$repo_id.url\" in config\n";
358     + $self->url($url);
359     $self->{pushurl} = eval { command_oneline('config', '--get',
360     "svn-remote.$repo_id.pushurl") };
361     $self->rebuild;
362     @@ -552,8 +571,7 @@ sub _set_svm_vars {
363     # username is of no interest
364     $src =~ s{(^[a-z\+]*://)[^/@]*@}{$1};
365    
366     - my $replace = $ra->{url};
367     - $replace .= "/$path" if length $path;
368     + my $replace = add_path_to_url($ra->url, $path);
369    
370     my $section = "svn-remote.$self->{repo_id}";
371     tmp_config("$section.svm-source", $src);
372     @@ -567,20 +585,21 @@ sub _set_svm_vars {
373     }
374    
375     my $r = $ra->get_latest_revnum;
376     - my $path = $self->{path};
377     + my $path = $self->path;
378     my %tried;
379     while (length $path) {
380     - unless ($tried{"$self->{url}/$path"}) {
381     + my $try = add_path_to_url($self->url, $path);
382     + unless ($tried{$try}) {
383     return $ra if $self->read_svm_props($ra, $path, $r);
384     - $tried{"$self->{url}/$path"} = 1;
385     + $tried{$try} = 1;
386     }
387     $path =~ s#/?[^/]+$##;
388     }
389     die "Path: '$path' should be ''\n" if $path ne '';
390     return $ra if $self->read_svm_props($ra, $path, $r);
391     - $tried{"$self->{url}/$path"} = 1;
392     + $tried{ add_path_to_url($self->url, $path) } = 1;
393    
394     - if ($ra->{repos_root} eq $self->{url}) {
395     + if ($ra->{repos_root} eq $self->url) {
396     die @err, (map { " $_\n" } keys %tried), "\n";
397     }
398    
399     @@ -590,20 +609,21 @@ sub _set_svm_vars {
400     $path = $ra->{svn_path};
401     $ra = Git::SVN::Ra->new($ra->{repos_root});
402     while (length $path) {
403     - unless ($tried{"$ra->{url}/$path"}) {
404     + my $try = add_path_to_url($ra->url, $path);
405     + unless ($tried{$try}) {
406     $ok = $self->read_svm_props($ra, $path, $r);
407     last if $ok;
408     - $tried{"$ra->{url}/$path"} = 1;
409     + $tried{$try} = 1;
410     }
411     $path =~ s#/?[^/]+$##;
412     }
413     die "Path: '$path' should be ''\n" if $path ne '';
414     $ok ||= $self->read_svm_props($ra, $path, $r);
415     - $tried{"$ra->{url}/$path"} = 1;
416     + $tried{ add_path_to_url($ra->url, $path) } = 1;
417     if (!$ok) {
418     die @err, (map { " $_\n" } keys %tried), "\n";
419     }
420     - Git::SVN::Ra->new($self->{url});
421     + Git::SVN::Ra->new($self->url);
422     }
423    
424     sub svnsync {
425     @@ -670,7 +690,7 @@ sub ra_uuid {
426     if (!$@ && $uuid && $uuid =~ /^([a-f\d\-]{30,})$/i) {
427     $self->{ra_uuid} = $uuid;
428     } else {
429     - die "ra_uuid called without URL\n" unless $self->{url};
430     + die "ra_uuid called without URL\n" unless $self->url;
431     $self->{ra_uuid} = $self->ra->get_uuid;
432     tmp_config('--add', $key, $self->{ra_uuid});
433     }
434     @@ -694,7 +714,7 @@ sub repos_root {
435    
436     sub ra {
437     my ($self) = shift;
438     - my $ra = Git::SVN::Ra->new($self->{url});
439     + my $ra = Git::SVN::Ra->new($self->url);
440     $self->_set_repos_root($ra->{repos_root});
441     if ($self->use_svm_props && !$self->{svm}) {
442     if ($self->no_metadata) {
443     @@ -728,7 +748,7 @@ sub prop_walk {
444     $path =~ s#^/*#/#g;
445     my $p = $path;
446     # Strip the irrelevant part of the path.
447     - $p =~ s#^/+\Q$self->{path}\E(/|$)#/#;
448     + $p =~ s#^/+\Q@{[$self->path]}\E(/|$)#/#;
449     # Ensure the path is terminated by a `/'.
450     $p =~ s#/*$#/#;
451    
452     @@ -749,7 +769,7 @@ sub prop_walk {
453    
454     foreach (sort keys %$dirent) {
455     next if $dirent->{$_}->{kind} != $SVN::Node::dir;
456     - $self->prop_walk($self->{path} . $p . $_, $rev, $sub);
457     + $self->prop_walk($self->path . $p . $_, $rev, $sub);
458     }
459     }
460    
461     @@ -919,20 +939,19 @@ sub rewrite_uuid {
462    
463     sub metadata_url {
464     my ($self) = @_;
465     - ($self->rewrite_root || $self->{url}) .
466     - (length $self->{path} ? '/' . $self->{path} : '');
467     + my $url = $self->rewrite_root || $self->url;
468     + return canonicalize_url( add_path_to_url( $url, $self->path ) );
469     }
470    
471     sub full_url {
472     my ($self) = @_;
473     - $self->{url} . (length $self->{path} ? '/' . $self->{path} : '');
474     + return canonicalize_url( add_path_to_url( $self->url, $self->path ) );
475     }
476    
477     sub full_pushurl {
478     my ($self) = @_;
479     if ($self->{pushurl}) {
480     - return $self->{pushurl} . (length $self->{path} ? '/' .
481     - $self->{path} : '');
482     + return canonicalize_url( add_path_to_url( $self->{pushurl}, $self->path ) );
483     } else {
484     return $self->full_url;
485     }
486     @@ -1048,20 +1067,20 @@ sub do_git_commit {
487    
488     sub match_paths {
489     my ($self, $paths, $r) = @_;
490     - return 1 if $self->{path} eq '';
491     - if (my $path = $paths->{"/$self->{path}"}) {
492     + return 1 if $self->path eq '';
493     + if (my $path = $paths->{"/".$self->path}) {
494     return ($path->{action} eq 'D') ? 0 : 1;
495     }
496     - $self->{path_regex} ||= qr/^\/\Q$self->{path}\E\//;
497     + $self->{path_regex} ||= qr{^/\Q@{[$self->path]}\E/};
498     if (grep /$self->{path_regex}/, keys %$paths) {
499     return 1;
500     }
501     my $c = '';
502     - foreach (split m#/#, $self->{path}) {
503     + foreach (split m#/#, $self->path) {
504     $c .= "/$_";
505     next unless ($paths->{$c} &&
506     ($paths->{$c}->{action} =~ /^[AR]$/));
507     - if ($self->ra->check_path($self->{path}, $r) ==
508     + if ($self->ra->check_path($self->path, $r) ==
509     $SVN::Node::dir) {
510     return 1;
511     }
512     @@ -1075,14 +1094,14 @@ sub find_parent_branch {
513     unless (defined $paths) {
514     my $err_handler = $SVN::Error::handler;
515     $SVN::Error::handler = \&Git::SVN::Ra::skip_unknown_revs;
516     - $self->ra->get_log([$self->{path}], $rev, $rev, 0, 1, 1,
517     + $self->ra->get_log([$self->path], $rev, $rev, 0, 1, 1,
518     sub { $paths = $_[0] });
519     $SVN::Error::handler = $err_handler;
520     }
521     return undef unless defined $paths;
522    
523     # look for a parent from another branch:
524     - my @b_path_components = split m#/#, $self->{path};
525     + my @b_path_components = split m#/#, $self->path;
526     my @a_path_components;
527     my $i;
528     while (@b_path_components) {
529     @@ -1099,8 +1118,8 @@ sub find_parent_branch {
530     }
531     my $r = $i->{copyfrom_rev};
532     my $repos_root = $self->ra->{repos_root};
533     - my $url = $self->ra->{url};
534     - my $new_url = $url . $branch_from;
535     + my $url = $self->ra->url;
536     + my $new_url = canonicalize_url( add_path_to_url( $url, $branch_from ) );
537     print STDERR "Found possible branch point: ",
538     "$new_url => ", $self->full_url, ", $r\n"
539     unless $::_q > 1;
540     @@ -1114,7 +1133,7 @@ sub find_parent_branch {
541     ($base, $head) = parse_revision_argument(0, $r);
542     } else {
543     if ($r0 < $r) {
544     - $gs->ra->get_log([$gs->{path}], $r0 + 1, $r, 1,
545     + $gs->ra->get_log([$gs->path], $r0 + 1, $r, 1,
546     0, 1, sub { $base = $_[1] - 1 });
547     }
548     }
549     @@ -1136,7 +1155,7 @@ sub find_parent_branch {
550     # at the moment), so we can't rely on it
551     $self->{last_rev} = $r0;
552     $self->{last_commit} = $parent;
553     - $ed = Git::SVN::Fetcher->new($self, $gs->{path});
554     + $ed = Git::SVN::Fetcher->new($self, $gs->path);
555     $gs->ra->gs_do_switch($r0, $rev, $gs,
556     $self->full_url, $ed)
557     or die "SVN connection failed somewhere...\n";
558     @@ -1235,7 +1254,7 @@ sub mkemptydirs {
559     close $fh;
560     }
561    
562     - my $strip = qr/\A\Q$self->{path}\E(?:\/|$)/;
563     + my $strip = qr/\A\Q@{[$self->path]}\E(?:\/|$)/;
564     foreach my $d (sort keys %empty_dirs) {
565     $d = uri_decode($d);
566     $d =~ s/$strip//;
567     @@ -1429,12 +1448,11 @@ sub find_extra_svk_parents {
568     for my $ticket ( @tickets ) {
569     my ($uuid, $path, $rev) = split /:/, $ticket;
570     if ( $uuid eq $self->ra_uuid ) {
571     - my $url = $self->{url};
572     - my $repos_root = $url;
573     + my $repos_root = $self->url;
574     my $branch_from = $path;
575     $branch_from =~ s{^/}{};
576     - my $gs = $self->other_gs($repos_root."/".$branch_from,
577     - $url,
578     + my $gs = $self->other_gs(add_path_to_url( $repos_root, $branch_from ),
579     + $repos_root,
580     $branch_from,
581     $rev,
582     $self->{ref_id});
583     @@ -1693,7 +1711,7 @@ sub find_extra_svn_parents {
584     # are now marked as merge, we can add the tip as a parent.
585     my @merges = split "\n", $mergeinfo;
586     my @merge_tips;
587     - my $url = $self->{url};
588     + my $url = $self->url;
589     my $uuid = $self->ra_uuid;
590     my %ranges;
591     for my $merge ( @merges ) {
592     @@ -1875,8 +1893,9 @@ sub make_log_entry {
593     $email ||= "$author\@$uuid";
594     $commit_email ||= "$author\@$uuid";
595     } elsif ($self->use_svnsync_props) {
596     - my $full_url = $self->svnsync->{url};
597     - $full_url .= "/$self->{path}" if length $self->{path};
598     + my $full_url = canonicalize_url(
599     + add_path_to_url( $self->svnsync->{url}, $self->path )
600     + );
601     remove_username($full_url);
602     my $uuid = $self->svnsync->{uuid};
603     $log_entry{metadata} = "$full_url\@$rev $uuid";
604     @@ -1923,7 +1942,7 @@ sub set_tree {
605     tree_b => $tree,
606     editor_cb => sub {
607     $self->set_tree_cb($log_entry, $tree, @_) },
608     - svn_path => $self->{path} );
609     + svn_path => $self->path );
610     if (!Git::SVN::Editor->new(\%ed_opts)->apply_diff) {
611     print "No changes\nr$self->{last_rev} = $tree\n";
612     }
613     @@ -2299,10 +2318,39 @@ sub _new {
614    
615     $_[3] = $path = '' unless (defined $path);
616     mkpath([$dir]);
617     - bless {
618     + my $obj = bless {
619     ref_id => $ref_id, dir => $dir, index => "$dir/index",
620     - path => $path, config => "$ENV{GIT_DIR}/svn/config",
621     + config => "$ENV{GIT_DIR}/svn/config",
622     map_root => "$dir/.rev_map", repo_id => $repo_id }, $class;
623     +
624     + # Ensure it gets canonicalized
625     + $obj->path($path);
626     +
627     + return $obj;
628     +}
629     +
630     +sub path {
631     + my $self = shift;
632     +
633     + if (@_) {
634     + my $path = shift;
635     + $self->{path} = canonicalize_path($path);
636     + return;
637     + }
638     +
639     + return $self->{path};
640     +}
641     +
642     +sub url {
643     + my $self = shift;
644     +
645     + if (@_) {
646     + my $url = shift;
647     + $self->{url} = canonicalize_url($url);
648     + return;
649     + }
650     +
651     + return $self->{url};
652     }
653    
654     # for read-only access of old .rev_db formats
655     diff --git a/perl/Git/SVN/Fetcher.pm b/perl/Git/SVN/Fetcher.pm
656     index 76fae9b..046a7a2 100644
657     --- a/perl/Git/SVN/Fetcher.pm
658     +++ b/perl/Git/SVN/Fetcher.pm
659     @@ -83,7 +83,7 @@ sub _mark_empty_symlinks {
660     chomp(my $empty_blob = `git hash-object -t blob --stdin < /dev/null`);
661     my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r -z/, $cmt);
662     local $/ = "\0";
663     - my $pfx = defined($switch_path) ? $switch_path : $git_svn->{path};
664     + my $pfx = defined($switch_path) ? $switch_path : $git_svn->path;
665     $pfx .= '/' if length($pfx);
666     while (<$ls>) {
667     chomp;
668     diff --git a/perl/Git/SVN/Migration.pm b/perl/Git/SVN/Migration.pm
669     index 75d7429..30daf35 100644
670     --- a/perl/Git/SVN/Migration.pm
671     +++ b/perl/Git/SVN/Migration.pm
672     @@ -177,14 +177,14 @@ sub minimize_connections {
673     my $ra = Git::SVN::Ra->new($url);
674    
675     # skip existing cases where we already connect to the root
676     - if (($ra->{url} eq $ra->{repos_root}) ||
677     + if (($ra->url eq $ra->{repos_root}) ||
678     ($ra->{repos_root} eq $repo_id)) {
679     - $root_repos->{$ra->{url}} = $repo_id;
680     + $root_repos->{$ra->url} = $repo_id;
681     next;
682     }
683    
684     my $root_ra = Git::SVN::Ra->new($ra->{repos_root});
685     - my $root_path = $ra->{url};
686     + my $root_path = $ra->url;
687     $root_path =~ s#^\Q$ra->{repos_root}\E(/|$)##;
688     foreach my $path (keys %$fetch) {
689     my $ref_id = $fetch->{$path};
690     diff --git a/perl/Git/SVN/Ra.pm b/perl/Git/SVN/Ra.pm
691     index 23ff43e..90ec30b 100644
692     --- a/perl/Git/SVN/Ra.pm
693     +++ b/perl/Git/SVN/Ra.pm
694     @@ -3,6 +3,12 @@ use vars qw/@ISA $config_dir $_ignore_refs_regex $_log_window_size/;
695     use strict;
696     use warnings;
697     use SVN::Client;
698     +use Git::SVN::Utils qw(
699     + canonicalize_url
700     + canonicalize_path
701     + add_path_to_url
702     +);
703     +
704     use SVN::Ra;
705     BEGIN {
706     @ISA = qw(SVN::Ra);
707     @@ -62,29 +68,11 @@ sub _auth_providers () {
708     \@rv;
709     }
710    
711     -sub escape_uri_only {
712     - my ($uri) = @_;
713     - my @tmp;
714     - foreach (split m{/}, $uri) {
715     - s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
716     - push @tmp, $_;
717     - }
718     - join('/', @tmp);
719     -}
720     -
721     -sub escape_url {
722     - my ($url) = @_;
723     - if ($url =~ m#^(https?)://([^/]+)(.*)$#) {
724     - my ($scheme, $domain, $uri) = ($1, $2, escape_uri_only($3));
725     - $url = "$scheme://$domain$uri";
726     - }
727     - $url;
728     -}
729    
730     sub new {
731     my ($class, $url) = @_;
732     - $url =~ s!/+$!!;
733     - return $RA if ($RA && $RA->{url} eq $url);
734     + $url = canonicalize_url($url);
735     + return $RA if ($RA && $RA->url eq $url);
736    
737     ::_req_svn();
738    
739     @@ -115,17 +103,34 @@ sub new {
740     $Git::SVN::Prompt::_no_auth_cache = 1;
741     }
742     } # no warnings 'once'
743     - my $self = SVN::Ra->new(url => escape_url($url), auth => $baton,
744     +
745     + my $self = SVN::Ra->new(url => $url, auth => $baton,
746     config => $config,
747     pool => SVN::Pool->new,
748     auth_provider_callbacks => $callbacks);
749     - $self->{url} = $url;
750     + $RA = bless $self, $class;
751     +
752     + # Make sure its canonicalized
753     + $self->url($url);
754     $self->{svn_path} = $url;
755     $self->{repos_root} = $self->get_repos_root;
756     $self->{svn_path} =~ s#^\Q$self->{repos_root}\E(/|$)##;
757     $self->{cache} = { check_path => { r => 0, data => {} },
758     get_dir => { r => 0, data => {} } };
759     - $RA = bless $self, $class;
760     +
761     + return $RA;
762     +}
763     +
764     +sub url {
765     + my $self = shift;
766     +
767     + if (@_) {
768     + my $url = shift;
769     + $self->{url} = canonicalize_url($url);
770     + return;
771     + }
772     +
773     + return $self->{url};
774     }
775    
776     sub check_path {
777     @@ -195,6 +200,7 @@ sub get_log {
778     qw/copyfrom_path copyfrom_rev action/;
779     if ($s{'copyfrom_path'}) {
780     $s{'copyfrom_path'} =~ s/$prefix_regex//;
781     + $s{'copyfrom_path'} = canonicalize_path($s{'copyfrom_path'});
782     }
783     $_[0]{$p} = \%s;
784     }
785     @@ -246,7 +252,7 @@ sub get_commit_editor {
786     sub gs_do_update {
787     my ($self, $rev_a, $rev_b, $gs, $editor) = @_;
788     my $new = ($rev_a == $rev_b);
789     - my $path = $gs->{path};
790     + my $path = $gs->path;
791    
792     if ($new && -e $gs->{index}) {
793     unlink $gs->{index} or die
794     @@ -282,30 +288,33 @@ sub gs_do_update {
795     # svn_ra_reparent didn't work before 1.4)
796     sub gs_do_switch {
797     my ($self, $rev_a, $rev_b, $gs, $url_b, $editor) = @_;
798     - my $path = $gs->{path};
799     + my $path = $gs->path;
800     my $pool = SVN::Pool->new;
801    
802     - my $full_url = $self->{url};
803     - my $old_url = $full_url;
804     - $full_url .= '/' . $path if length $path;
805     + my $old_url = $self->url;
806     + my $full_url = add_path_to_url( $self->url, $path );
807     my ($ra, $reparented);
808    
809     if ($old_url =~ m#^svn(\+ssh)?://# ||
810     ($full_url =~ m#^https?://# &&
811     - escape_url($full_url) ne $full_url)) {
812     + canonicalize_url($full_url) ne $full_url)) {
813     $_[0] = undef;
814     $self = undef;
815     $RA = undef;
816     $ra = Git::SVN::Ra->new($full_url);
817     $ra_invalid = 1;
818     } elsif ($old_url ne $full_url) {
819     - SVN::_Ra::svn_ra_reparent($self->{session}, $full_url, $pool);
820     - $self->{url} = $full_url;
821     + SVN::_Ra::svn_ra_reparent(
822     + $self->{session},
823     + canonicalize_url($full_url),
824     + $pool
825     + );
826     + $self->url($full_url);
827     $reparented = 1;
828     }
829    
830     $ra ||= $self;
831     - $url_b = escape_url($url_b);
832     + $url_b = canonicalize_url($url_b);
833     my $reporter = $ra->do_switch($rev_b, '', 1, $url_b, $editor, $pool);
834     my @lock = (::compare_svn_version('1.2.0') >= 0) ? (undef) : ();
835     $reporter->set_path('', $rev_a, 0, @lock, $pool);
836     @@ -313,7 +322,7 @@ sub gs_do_switch {
837    
838     if ($reparented) {
839     SVN::_Ra::svn_ra_reparent($self->{session}, $old_url, $pool);
840     - $self->{url} = $old_url;
841     + $self->url($old_url);
842     }
843    
844     $pool->clear;
845     @@ -326,7 +335,7 @@ sub longest_common_path {
846     my $common_max = scalar @$gsv;
847    
848     foreach my $gs (@$gsv) {
849     - my @tmp = split m#/#, $gs->{path};
850     + my @tmp = split m#/#, $gs->path;
851     my $p = '';
852     foreach (@tmp) {
853     $p .= length($p) ? "/$_" : $_;
854     @@ -362,7 +371,7 @@ sub gs_fetch_loop_common {
855     my $inc = $_log_window_size;
856     my ($min, $max) = ($base, $head < $base + $inc ? $head : $base + $inc);
857     my $longest_path = longest_common_path($gsv, $globs);
858     - my $ra_url = $self->{url};
859     + my $ra_url = $self->url;
860     my $find_trailing_edge;
861     while (1) {
862     my %revs;
863     @@ -508,7 +517,7 @@ sub match_globs {
864     ($self->check_path($p, $r) !=
865     $SVN::Node::dir));
866     next unless $p =~ /$g->{path}->{regex}/;
867     - $exists->{$p} = Git::SVN->init($self->{url}, $p, undef,
868     + $exists->{$p} = Git::SVN->init($self->url, $p, undef,
869     $g->{ref}->full_path($de), 1);
870     }
871     }
872     @@ -532,7 +541,7 @@ sub match_globs {
873     next if ($self->check_path($pathname, $r) !=
874     $SVN::Node::dir);
875     $exists->{$pathname} = Git::SVN->init(
876     - $self->{url}, $pathname, undef,
877     + $self->url, $pathname, undef,
878     $g->{ref}->full_path($p), 1);
879     }
880     my $c = '';
881     @@ -548,19 +557,20 @@ sub match_globs {
882    
883     sub minimize_url {
884     my ($self) = @_;
885     - return $self->{url} if ($self->{url} eq $self->{repos_root});
886     + return $self->url if ($self->url eq $self->{repos_root});
887     my $url = $self->{repos_root};
888     my @components = split(m!/!, $self->{svn_path});
889     my $c = '';
890     do {
891     - $url .= "/$c" if length $c;
892     + $url = add_path_to_url($url, $c);
893     eval {
894     my $ra = (ref $self)->new($url);
895     my $latest = $ra->get_latest_revnum;
896     $ra->get_log("", $latest, 0, 1, 0, 1, sub {});
897     };
898     } while ($@ && ($c = shift @components));
899     - $url;
900     +
901     + return canonicalize_url($url);
902     }
903    
904     sub can_do_switch {
905     @@ -568,7 +578,7 @@ sub can_do_switch {
906     unless (defined $can_do_switch) {
907     my $pool = SVN::Pool->new;
908     my $rep = eval {
909     - $self->do_switch(1, '', 0, $self->{url},
910     + $self->do_switch(1, '', 0, $self->url,
911     SVN::Delta::Editor->new, $pool);
912     };
913     if ($@) {
914     diff --git a/perl/Git/SVN/Utils.pm b/perl/Git/SVN/Utils.pm
915     index 496006b..4bb4dde 100644
916     --- a/perl/Git/SVN/Utils.pm
917     +++ b/perl/Git/SVN/Utils.pm
918     @@ -3,9 +3,18 @@ package Git::SVN::Utils;
919     use strict;
920     use warnings;
921    
922     +use SVN::Core;
923     +
924     use base qw(Exporter);
925    
926     -our @EXPORT_OK = qw(fatal can_compress);
927     +our @EXPORT_OK = qw(
928     + fatal
929     + can_compress
930     + canonicalize_path
931     + canonicalize_url
932     + join_paths
933     + add_path_to_url
934     +);
935    
936    
937     =head1 NAME
938     @@ -56,4 +65,169 @@ sub can_compress {
939     }
940    
941    
942     +=head3 canonicalize_path
943     +
944     + my $canoncalized_path = canonicalize_path($path);
945     +
946     +Converts $path into a canonical form which is safe to pass to the SVN
947     +API as a file path.
948     +
949     +=cut
950     +
951     +# Turn foo/../bar into bar
952     +sub _collapse_dotdot {
953     + my $path = shift;
954     +
955     + 1 while $path =~ s{/[^/]+/+\.\.}{};
956     + 1 while $path =~ s{[^/]+/+\.\./}{};
957     + 1 while $path =~ s{[^/]+/+\.\.}{};
958     +
959     + return $path;
960     +}
961     +
962     +
963     +sub canonicalize_path {
964     + my $path = shift;
965     + my $rv;
966     +
967     + # The 1.7 way to do it
968     + if ( defined &SVN::_Core::svn_dirent_canonicalize ) {
969     + $path = _collapse_dotdot($path);
970     + $rv = SVN::_Core::svn_dirent_canonicalize($path);
971     + }
972     + # The 1.6 way to do it
973     + # This can return undef on subversion-perl-1.4.2-2.el5 (CentOS 5.2)
974     + elsif ( defined &SVN::_Core::svn_path_canonicalize ) {
975     + $path = _collapse_dotdot($path);
976     + $rv = SVN::_Core::svn_path_canonicalize($path);
977     + }
978     +
979     + return $rv if defined $rv;
980     +
981     + # No SVN API canonicalization is available, or the SVN API
982     + # didn't return a successful result, do it ourselves
983     + return _canonicalize_path_ourselves($path);
984     +}
985     +
986     +
987     +sub _canonicalize_path_ourselves {
988     + my ($path) = @_;
989     + my $dot_slash_added = 0;
990     + if (substr($path, 0, 1) ne "/") {
991     + $path = "./" . $path;
992     + $dot_slash_added = 1;
993     + }
994     + $path =~ s#/+#/#g;
995     + $path =~ s#/\.(?:/|$)#/#g;
996     + $path = _collapse_dotdot($path);
997     + $path =~ s#/$##g;
998     + $path =~ s#^\./## if $dot_slash_added;
999     + $path =~ s#^/##;
1000     + $path =~ s#^\.$##;
1001     + return $path;
1002     +}
1003     +
1004     +
1005     +=head3 canonicalize_url
1006     +
1007     + my $canonicalized_url = canonicalize_url($url);
1008     +
1009     +Converts $url into a canonical form which is safe to pass to the SVN
1010     +API as a URL.
1011     +
1012     +=cut
1013     +
1014     +sub canonicalize_url {
1015     + my $url = shift;
1016     +
1017     + # The 1.7 way to do it
1018     + if ( defined &SVN::_Core::svn_uri_canonicalize ) {
1019     + return SVN::_Core::svn_uri_canonicalize($url);
1020     + }
1021     + # There wasn't a 1.6 way to do it, so we do it ourself.
1022     + else {
1023     + return _canonicalize_url_ourselves($url);
1024     + }
1025     +}
1026     +
1027     +
1028     +sub _canonicalize_url_path {
1029     + my ($uri_path) = @_;
1030     +
1031     + my @parts;
1032     + foreach my $part (split m{/+}, $uri_path) {
1033     + $part =~ s/([^~\w.%+-]|%(?![a-fA-F0-9]{2}))/sprintf("%%%02X",ord($1))/eg;
1034     + push @parts, $part;
1035     + }
1036     +
1037     + return join('/', @parts);
1038     +}
1039     +
1040     +sub _canonicalize_url_ourselves {
1041     + my ($url) = @_;
1042     + if ($url =~ m#^([^:]+)://([^/]*)(.*)$#) {
1043     + my ($scheme, $domain, $uri) = ($1, $2, _canonicalize_url_path(canonicalize_path($3)));
1044     + $url = "$scheme://$domain$uri";
1045     + }
1046     + $url;
1047     +}
1048     +
1049     +
1050     +=head3 join_paths
1051     +
1052     + my $new_path = join_paths(@paths);
1053     +
1054     +Appends @paths together into a single path. Any empty paths are ignored.
1055     +
1056     +=cut
1057     +
1058     +sub join_paths {
1059     + my @paths = @_;
1060     +
1061     + @paths = grep { defined $_ && length $_ } @paths;
1062     +
1063     + return '' unless @paths;
1064     + return $paths[0] if @paths == 1;
1065     +
1066     + my $new_path = shift @paths;
1067     + $new_path =~ s{/+$}{};
1068     +
1069     + my $last_path = pop @paths;
1070     + $last_path =~ s{^/+}{};
1071     +
1072     + for my $path (@paths) {
1073     + $path =~ s{^/+}{};
1074     + $path =~ s{/+$}{};
1075     + $new_path .= "/$path";
1076     + }
1077     +
1078     + return $new_path .= "/$last_path";
1079     +}
1080     +
1081     +
1082     +=head3 add_path_to_url
1083     +
1084     + my $new_url = add_path_to_url($url, $path);
1085     +
1086     +Appends $path onto the $url. If $path is empty, $url is returned unchanged.
1087     +
1088     +=cut
1089     +
1090     +sub add_path_to_url {
1091     + my($url, $path) = @_;
1092     +
1093     + return $url if !defined $path or !length $path;
1094     +
1095     + # Strip trailing and leading slashes so we don't
1096     + # wind up with http://x.com///path
1097     + $url =~ s{/+$}{};
1098     + $path =~ s{^/+}{};
1099     +
1100     + # If a path has a % in it, URI escape it so it's not
1101     + # mistaken for a URI escape later.
1102     + $path =~ s{%}{%25}g;
1103     +
1104     + return join '/', $url, $path;
1105     +}
1106     +
1107     1;
1108     diff --git a/t/Git-SVN/Utils/add_path_to_url.t b/t/Git-SVN/Utils/add_path_to_url.t
1109     new file mode 100644
1110     index 0000000..bfbd878
1111     --- /dev/null
1112     +++ b/t/Git-SVN/Utils/add_path_to_url.t
1113     @@ -0,0 +1,27 @@
1114     +#!/usr/bin/env perl
1115     +
1116     +use strict;
1117     +use warnings;
1118     +
1119     +use Test::More 'no_plan';
1120     +
1121     +use Git::SVN::Utils qw(
1122     + add_path_to_url
1123     +);
1124     +
1125     +# A reference cannot be a hash key, so we use an array.
1126     +my @tests = (
1127     + ["http://x.com", "bar"] => 'http://x.com/bar',
1128     + ["http://x.com", ""] => 'http://x.com',
1129     + ["http://x.com/foo/", undef] => 'http://x.com/foo/',
1130     + ["http://x.com/foo/", "/bar/baz/"] => 'http://x.com/foo/bar/baz/',
1131     + ["http://x.com", 'per%cent'] => 'http://x.com/per%25cent',
1132     +);
1133     +
1134     +while(@tests) {
1135     + my($have, $want) = splice @tests, 0, 2;
1136     +
1137     + my $args = join ", ", map { qq['$_'] } map { defined($_) ? $_ : 'undef' } @$have;
1138     + my $name = "add_path_to_url($args) eq $want";
1139     + is add_path_to_url(@$have), $want, $name;
1140     +}
1141     diff --git a/t/Git-SVN/Utils/canonicalize_url.t b/t/Git-SVN/Utils/canonicalize_url.t
1142     new file mode 100644
1143     index 0000000..05795ab
1144     --- /dev/null
1145     +++ b/t/Git-SVN/Utils/canonicalize_url.t
1146     @@ -0,0 +1,26 @@
1147     +#!/usr/bin/env perl
1148     +
1149     +# Test our own home rolled URL canonicalizer. Test the private one
1150     +# directly because we can't predict what the SVN API is doing to do.
1151     +
1152     +use strict;
1153     +use warnings;
1154     +
1155     +use Test::More 'no_plan';
1156     +
1157     +use Git::SVN::Utils;
1158     +my $canonicalize_url = \&Git::SVN::Utils::_canonicalize_url_ourselves;
1159     +
1160     +my %tests = (
1161     + "http://x.com" => "http://x.com",
1162     + "http://x.com/" => "http://x.com",
1163     + "http://x.com/foo/bar" => "http://x.com/foo/bar",
1164     + "http://x.com//foo//bar//" => "http://x.com/foo/bar",
1165     + "http://x.com/ /%/" => "http://x.com/%20%20/%25",
1166     +);
1167     +
1168     +for my $arg (keys %tests) {
1169     + my $want = $tests{$arg};
1170     +
1171     + is $canonicalize_url->($arg), $want, "canonicalize_url('$arg') => $want";
1172     +}
1173     diff --git a/t/Git-SVN/Utils/collapse_dotdot.t b/t/Git-SVN/Utils/collapse_dotdot.t
1174     new file mode 100644
1175     index 0000000..1da1cce
1176     --- /dev/null
1177     +++ b/t/Git-SVN/Utils/collapse_dotdot.t
1178     @@ -0,0 +1,23 @@
1179     +#!/usr/bin/env perl
1180     +
1181     +use strict;
1182     +use warnings;
1183     +
1184     +use Test::More 'no_plan';
1185     +
1186     +use Git::SVN::Utils;
1187     +my $collapse_dotdot = \&Git::SVN::Utils::_collapse_dotdot;
1188     +
1189     +my %tests = (
1190     + "foo/bar/baz" => "foo/bar/baz",
1191     + ".." => "..",
1192     + "foo/.." => "",
1193     + "/foo/bar/../../baz" => "/baz",
1194     + "deeply/.././deeply/nested" => "./deeply/nested",
1195     +);
1196     +
1197     +for my $arg (keys %tests) {
1198     + my $want = $tests{$arg};
1199     +
1200     + is $collapse_dotdot->($arg), $want, "_collapse_dotdot('$arg') => $want";
1201     +}
1202     diff --git a/t/Git-SVN/Utils/join_paths.t b/t/Git-SVN/Utils/join_paths.t
1203     new file mode 100644
1204     index 0000000..d4488e7
1205     --- /dev/null
1206     +++ b/t/Git-SVN/Utils/join_paths.t
1207     @@ -0,0 +1,32 @@
1208     +#!/usr/bin/env perl
1209     +
1210     +use strict;
1211     +use warnings;
1212     +
1213     +use Test::More 'no_plan';
1214     +
1215     +use Git::SVN::Utils qw(
1216     + join_paths
1217     +);
1218     +
1219     +# A reference cannot be a hash key, so we use an array.
1220     +my @tests = (
1221     + [] => '',
1222     + ["/x.com", "bar"] => '/x.com/bar',
1223     + ["x.com", ""] => 'x.com',
1224     + ["/x.com/foo/", undef, "bar"] => '/x.com/foo/bar',
1225     + ["x.com/foo/", "/bar/baz/"] => 'x.com/foo/bar/baz/',
1226     + ["foo", "bar"] => 'foo/bar',
1227     + ["/foo/bar", "baz", "/biff"] => '/foo/bar/baz/biff',
1228     + ["", undef, "."] => '.',
1229     + [] => '',
1230     +
1231     +);
1232     +
1233     +while(@tests) {
1234     + my($have, $want) = splice @tests, 0, 2;
1235     +
1236     + my $args = join ", ", map { qq['$_'] } map { defined($_) ? $_ : 'undef' } @$have;
1237     + my $name = "join_paths($args) eq '$want'";
1238     + is join_paths(@$have), $want, $name;
1239     +}
1240     diff --git a/t/t9107-git-svn-migrate.sh b/t/t9107-git-svn-migrate.sh
1241     index 289fc31..ee73013 100755
1242     --- a/t/t9107-git-svn-migrate.sh
1243     +++ b/t/t9107-git-svn-migrate.sh
1244     @@ -27,15 +27,17 @@ test_expect_success 'setup old-looking metadata' '
1245     head=`git rev-parse --verify refs/heads/git-svn-HEAD^0`
1246     test_expect_success 'git-svn-HEAD is a real HEAD' "test -n '$head'"
1247    
1248     +svnrepo_escaped=`echo $svnrepo | sed 's/ /%20/'`
1249     +
1250     test_expect_success 'initialize old-style (v0) git svn layout' '
1251     mkdir -p "$GIT_DIR"/git-svn/info "$GIT_DIR"/svn/info &&
1252     echo "$svnrepo" > "$GIT_DIR"/git-svn/info/url &&
1253     echo "$svnrepo" > "$GIT_DIR"/svn/info/url &&
1254     git svn migrate &&
1255     - ! test -d "$GIT_DIR"/git svn &&
1256     + ! test -d "$GIT_DIR"/git-svn &&
1257     git rev-parse --verify refs/${remotes_git_svn}^0 &&
1258     git rev-parse --verify refs/remotes/svn^0 &&
1259     - test "$(git config --get svn-remote.svn.url)" = "$svnrepo" &&
1260     + test "$(git config --get svn-remote.svn.url)" = "$svnrepo_escaped" &&
1261     test `git config --get svn-remote.svn.fetch` = \
1262     ":refs/${remotes_git_svn}"
1263     '
1264     diff --git a/t/t9118-git-svn-funky-branch-names.sh b/t/t9118-git-svn-funky-branch-names.sh
1265     index 63fc982..193d3ca 100755
1266     --- a/t/t9118-git-svn-funky-branch-names.sh
1267     +++ b/t/t9118-git-svn-funky-branch-names.sh
1268     @@ -32,6 +32,11 @@ test_expect_success 'setup svnrepo' '
1269     start_httpd
1270     '
1271    
1272     +# SVN 1.7 will truncate "not-a%40{0]" to just "not-a".
1273     +# Look at what SVN wound up naming the branch and use that.
1274     +# Be sure to escape the @ if it shows up.
1275     +non_reflog=`svn_cmd ls "$svnrepo/pr ject/branches" | grep not-a | sed 's/\///' | sed 's/@/%40/'`
1276     +
1277     test_expect_success 'test clone with funky branch names' '
1278     git svn clone -s "$svnrepo/pr ject" project &&
1279     (
1280     @@ -42,7 +47,7 @@ test_expect_success 'test clone with funky branch names' '
1281     git rev-parse "refs/remotes/%2Eleading_dot" &&
1282     git rev-parse "refs/remotes/trailing_dot%2E" &&
1283     git rev-parse "refs/remotes/trailing_dotlock%2Elock" &&
1284     - git rev-parse "refs/remotes/not-a%40{0}reflog"
1285     + git rev-parse "refs/remotes/$non_reflog"
1286     )
1287     '
1288    

  ViewVC Help
Powered by ViewVC 1.1.20