All of lore.kernel.org
 help / color / mirror / Atom feed
From: "Michael G. Schwern" <schwern@pobox.com>
To: git@vger.kernel.org, gitster@pobox.com
Cc: robbat2@gentoo.org, bwalton@artsci.utoronto.ca,
	normalperson@yhbt.net, jrnieder@gmail.com, schwern@pobox.com
Subject: [PATCH 4/7] Add join_paths() to safely concatenate paths.
Date: Sat, 28 Jul 2012 02:38:29 -0700	[thread overview]
Message-ID: <1343468312-72024-5-git-send-email-schwern@pobox.com> (raw)
In-Reply-To: <1343468312-72024-1-git-send-email-schwern@pobox.com>

From: "Michael G. Schwern" <schwern@pobox.com>

Otherwise you might wind up with things like...

    my $path1 = undef;
    my $path2 = 'foo';
    my $path = $path1 . '/' . $path2;

creating '/foo'.  Or this...

    my $path1 = 'foo/';
    my $path2 = 'bar';
    my $path = $path1 . '/' . $path2;

creating 'foo//bar'.

Could have used File::Spec, but I'm shying away from it due to SVN
1.7's pickiness about paths.  Felt it would be better to have our own
we can control completely.
---
 git-svn.perl                 |  3 ++-
 perl/Git/SVN.pm              | 10 ++++++----
 perl/Git/SVN/Utils.pm        | 32 ++++++++++++++++++++++++++++++++
 t/Git-SVN/Utils/join_paths.t | 32 ++++++++++++++++++++++++++++++++
 4 files changed, 72 insertions(+), 5 deletions(-)
 create mode 100644 t/Git-SVN/Utils/join_paths.t

diff --git a/git-svn.perl b/git-svn.perl
index a857484..6e3e240 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -34,6 +34,7 @@ use Git::SVN::Utils qw(
 	can_compress
 	canonicalize_path
 	canonicalize_url
+	join_paths
 );
 
 use Git qw(
@@ -1275,7 +1276,7 @@ sub get_svnprops {
 	$path = $cmd_dir_prefix . $path;
 	fatal("No such file or directory: $path") unless -e $path;
 	my $is_dir = -d $path ? 1 : 0;
-	$path = $gs->{path} . '/' . $path;
+	$path = join_paths($gs->{path}, $path);
 
 	# canonicalize the path (otherwise libsvn will abort or fail to
 	# find the file)
diff --git a/perl/Git/SVN.pm b/perl/Git/SVN.pm
index 7913d8f..b0ed3ea 100644
--- a/perl/Git/SVN.pm
+++ b/perl/Git/SVN.pm
@@ -23,7 +23,11 @@ use Git qw(
     command_output_pipe
     command_close_pipe
 );
-use Git::SVN::Utils qw(fatal can_compress);
+use Git::SVN::Utils qw(
+	fatal
+	can_compress
+	join_paths
+);
 
 my $can_use_yaml;
 BEGIN {
@@ -316,9 +320,7 @@ sub init_remote_config {
 			}
 			my $old_path = $self->path;
 			$url =~ s!^\Q$min_url\E(/|$)!!;
-			if (length $old_path) {
-				$url .= "/$old_path";
-			}
+			$url = join_paths($url, $old_path);
 			$self->path($url);
 			$url = $min_url;
 		}
diff --git a/perl/Git/SVN/Utils.pm b/perl/Git/SVN/Utils.pm
index 7314e52..deade07 100644
--- a/perl/Git/SVN/Utils.pm
+++ b/perl/Git/SVN/Utils.pm
@@ -12,6 +12,7 @@ our @EXPORT_OK = qw(
 	can_compress
 	canonicalize_path
 	canonicalize_url
+	join_paths
 );
 
 
@@ -134,4 +135,35 @@ sub _canonicalize_url_ourselves {
 }
 
 
+=head3 join_paths
+
+    my $new_path = join_paths(@paths);
+
+Appends @paths together into a single path.  Any empty paths are ignored.
+
+=cut
+
+sub join_paths {
+	my @paths = @_;
+
+	@paths = grep { defined $_ && length $_ } @paths;
+
+	return '' unless @paths;
+	return $paths[0] if @paths == 1;
+
+	my $new_path = shift @paths;
+	$new_path =~ s{/+$}{};
+
+	my $last_path = pop @paths;
+	$last_path =~ s{^/+}{};
+
+	for my $path (@paths) {
+		$path =~ s{^/+}{};
+		$path =~ s{/+$}{};
+		$new_path .= "/$path";
+	}
+
+	return $new_path .= "/$last_path";
+}
+
 1;
diff --git a/t/Git-SVN/Utils/join_paths.t b/t/Git-SVN/Utils/join_paths.t
new file mode 100644
index 0000000..d4488e7
--- /dev/null
+++ b/t/Git-SVN/Utils/join_paths.t
@@ -0,0 +1,32 @@
+#!/usr/bin/env perl
+
+use strict;
+use warnings;
+
+use Test::More 'no_plan';
+
+use Git::SVN::Utils qw(
+	join_paths
+);
+
+# A reference cannot be a hash key, so we use an array.
+my @tests = (
+	[]					=> '',
+	["/x.com", "bar"]			=> '/x.com/bar',
+	["x.com", ""]				=> 'x.com',
+	["/x.com/foo/", undef, "bar"]		=> '/x.com/foo/bar',
+	["x.com/foo/", "/bar/baz/"]		=> 'x.com/foo/bar/baz/',
+	["foo", "bar"]				=> 'foo/bar',
+	["/foo/bar", "baz", "/biff"]		=> '/foo/bar/baz/biff',
+	["", undef, "."]			=> '.',
+	[]					=> '',
+
+);
+
+while(@tests) {
+	my($have, $want) = splice @tests, 0, 2;
+
+	my $args = join ", ", map { qq['$_'] } map { defined($_) ? $_ : 'undef' } @$have;
+	my $name = "join_paths($args) eq '$want'";
+	is join_paths(@$have), $want, $name;
+}
-- 
1.7.11.3

  parent reply	other threads:[~2012-07-28  9:39 UTC|newest]

Thread overview: 39+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-07-28  9:38 Canonicalize the git-svn path & url accessors Michael G. Schwern
2012-07-28  9:38 ` [PATCH 1/7] Move the canonicalization functions to Git::SVN::Utils Michael G. Schwern
2012-07-28  9:38 ` [PATCH 2/7] Change canonicalize_url() to use the SVN 1.7 API when available Michael G. Schwern
2012-07-28 13:50   ` Jonathan Nieder
2012-07-28 19:01     ` Michael G Schwern
2012-07-28 19:30       ` Jonathan Nieder
2012-07-28 19:51         ` Michael G Schwern
2012-07-28 19:57           ` Jonathan Nieder
2012-07-28 20:02             ` Jonathan Nieder
2012-07-28 20:24               ` Michael G Schwern
2012-10-14 11:42       ` [PATCH/RFC 0/2] " Jonathan Nieder
2012-10-14 11:45         ` [PATCH 1/2] git svn: do not overescape URLs (fallback case) Jonathan Nieder
2012-10-14 11:48         ` [PATCH 2/2] git svn: canonicalize_url(): use svn_path_canonicalize when available Jonathan Nieder
2012-10-23 22:58           ` Eric Wong
2012-07-28  9:38 ` [PATCH 3/7] Extract, test and enhance the logic to collapse ../foo paths Michael G. Schwern
2012-07-30 19:51   ` Eric Wong
2012-07-30 20:46     ` Michael G Schwern
2012-09-26 19:45       ` Jonathan Nieder
2012-09-26 20:58         ` Eric Wong
2012-09-26 21:38           ` Jonathan Nieder
2012-09-26 21:54             ` Eric Wong
2012-09-26 22:43               ` Jonathan Nieder
2012-09-27  0:15                 ` Eric Wong
2012-09-27  2:11                   ` Jonathan Nieder
2012-07-28  9:38 ` Michael G. Schwern [this message]
2012-09-26 20:51   ` [PATCH 4/7] Add join_paths() to safely concatenate paths Jonathan Nieder
2012-07-28  9:38 ` [PATCH 5/7] Remove irrelevant comment Michael G. Schwern
2012-07-28  9:38 ` [PATCH 6/7] Switch path canonicalization to use the SVN API Michael G. Schwern
2012-07-28 13:55   ` Jonathan Nieder
2012-07-28 19:07     ` Michael G Schwern
2012-07-30 20:04       ` Eric Wong
2012-08-02 21:51         ` Eric Wong
2012-08-02 23:18           ` Michael G Schwern
2012-10-05  7:04       ` [PATCH] git-svn: keep leading slash when canonicalizing paths (fallback case) Jonathan Nieder
2012-10-05 23:12         ` Eric Wong
2012-10-06  5:36           ` Junio C Hamano
2012-07-28  9:38 ` [PATCH 7/7] Make Git::SVN and Git::SVN::Ra canonicalize paths and urls Michael G. Schwern
2012-07-28 14:11   ` Jonathan Nieder
2012-07-28 19:15     ` Michael G Schwern

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1343468312-72024-5-git-send-email-schwern@pobox.com \
    --to=schwern@pobox.com \
    --cc=bwalton@artsci.utoronto.ca \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jrnieder@gmail.com \
    --cc=normalperson@yhbt.net \
    --cc=robbat2@gentoo.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.