git-svn: factor out _collapse_dotdot function

The SVN API functions will not accept ../foo but their canonicalization functions will not collapse it. So we'll have to do it ourselves. _collapse_dotdot() works better than the existing regex did. This will be used shortly when canonicalize_path() starts using the SVN API. [ew: commit title] Signed-off-by: Eric Wong <normalperson@yhbt.net>

Michael G. Schwern committed Jul 28, 2012 at 02:38 UTC 280ad88aa0e851b2f2945222edb8e7b681a7574b
2 files changed +36 -1
perl/Git/SVN/Utils.pm
+13 -1
@@ -72,6 +72,18 @@ API as a file path.
72
73 =cut
74
75 +# Turn foo/../bar into bar
76 +sub _collapse_dotdot {
77 + my $path = shift;
78 +
79 + 1 while $path =~ s{/[^/]+/+\.\.}{};
80 + 1 while $path =~ s{[^/]+/+\.\./}{};
81 + 1 while $path =~ s{[^/]+/+\.\.}{};
82 +
83 + return $path;
84 +}
85 +
86 +
87 sub canonicalize_path {
88 my ($path) = @_;
89 my $dot_slash_added = 0;
@@ -83,7 +95,7 @@ sub canonicalize_path {
95 # good reason), so let's do this manually.
96 $path =~ s#/+#/#g;
97 $path =~ s#/\.(?:/|$)#/#g;
86 - $path =~ s#/[^/]+/\.\.##g;
98 + $path = _collapse_dotdot($path);
99 $path =~ s#/$##g;
100 $path =~ s#^\./## if $dot_slash_added;
101 $path =~ s#^/##;
t/Git-SVN/Utils/collapse_dotdot.t new
+23
@@ -0,0 +1,23 @@
1 +#!/usr/bin/env perl
2 +
3 +use strict;
4 +use warnings;
5 +
6 +use Test::More 'no_plan';
7 +
8 +use Git::SVN::Utils;
9 +my $collapse_dotdot = \&Git::SVN::Utils::_collapse_dotdot;
10 +
11 +my %tests = (
12 + "foo/bar/baz" => "foo/bar/baz",
13 + ".." => "..",
14 + "foo/.." => "",
15 + "/foo/bar/../../baz" => "/baz",
16 + "deeply/.././deeply/nested" => "./deeply/nested",
17 +);
18 +
19 +for my $arg (keys %tests) {
20 + my $want = $tests{$arg};
21 +
22 + is $collapse_dotdot->($arg), $want, "_collapse_dotdot('$arg') => $want";
23 +}