git-svn: add git svn propget
authorBenoit Sigoure <tsuna@lrde.epita.fr>
Tue, 16 Oct 2007 14:36:50 +0000 (16:36 +0200)
committerShawn O. Pearce <spearce@spearce.org>
Wed, 17 Oct 2007 06:47:37 +0000 (02:47 -0400)
This allows one to easily retrieve a single SVN property from within
git-svn without requiring svn or remembering the URL of a repository

* git-svn.perl (%cmd): Add the new command `propget'.
($cmd_dir_prefix): New global.
(&get_svnprops): New helper.
(&cmd_propget): New.  Use &get_svnprops.
* t/t9101-git-svn-props.sh: Add a test case for propget.

[ew: make sure the rev-parse --show-prefix call doesn't break
     the `git-svn clone' command]

Signed-off-by: Benoit Sigoure <tsuna@lrde.epita.fr>
Acked-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
git-svn.perl
t/t9101-git-svn-props.sh

index 6daf8d8ea068e3bcab328dac94032b7bd18842fb..e97eba21fda31a64a3a6a4009a2d875e8cfd7aaf 100755 (executable)
@@ -9,6 +9,11 @@ use vars qw/   $AUTHOR $VERSION
 $AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
 $VERSION = '@@GIT_VERSION@@';
 
+# From which subdir have we been invoked?
+my $cmd_dir_prefix = eval {
+       command_oneline([qw/rev-parse --show-prefix/], STDERR => 0)
+} || '';
+
 my $git_dir_user_set = 1 if defined $ENV{GIT_DIR};
 $ENV{GIT_DIR} ||= '.git';
 $Git::SVN::default_repo_id = 'svn';
@@ -127,6 +132,9 @@ my %cmd = (
                             'Create a .gitignore per svn:ignore',
                             { 'revision|r=i' => \$_revision
                             } ],
+        'propget' => [ \&cmd_propget,
+                      'Print the value of a property on a file or directory',
+                      { 'revision|r=i' => \$_revision } ],
        'show-ignore' => [ \&cmd_show_ignore, "Show svn:ignore listings",
                        { 'revision|r=i' => \$_revision
                        } ],
@@ -526,6 +534,55 @@ sub cmd_create_ignore {
        });
 }
 
+# get_svnprops(PATH)
+# ------------------
+# Helper for cmd_propget below.
+sub get_svnprops {
+       my $path = shift;
+       my ($url, $rev, $uuid, $gs) = working_head_info('HEAD');
+       $gs ||= Git::SVN->new;
+
+       # prefix THE PATH by the sub-directory from which the user
+       # invoked us.
+       $path = $cmd_dir_prefix . $path;
+       fatal("No such file or directory: $path\n") unless -e $path;
+       my $is_dir = -d $path ? 1 : 0;
+       $path = $gs->{path} . '/' . $path;
+
+       # canonicalize the path (otherwise libsvn will abort or fail to
+       # find the file)
+       # File::Spec->canonpath doesn't collapse x/../y into y (for a
+       # good reason), so let's do this manually.
+       $path =~ s#/+#/#g;
+       $path =~ s#/\.(?:/|$)#/#g;
+       $path =~ s#/[^/]+/\.\.##g;
+       $path =~ s#/$##g;
+
+       my $r = (defined $_revision ? $_revision : $gs->ra->get_latest_revnum);
+       my $props;
+       if ($is_dir) {
+               (undef, undef, $props) = $gs->ra->get_dir($path, $r);
+       }
+       else {
+               (undef, $props) = $gs->ra->get_file($path, $r, undef);
+       }
+       return $props;
+}
+
+# cmd_propget (PROP, PATH)
+# ------------------------
+# Print the SVN property PROP for PATH.
+sub cmd_propget {
+       my ($prop, $path) = @_;
+       $path = '.' if not defined $path;
+       usage(1) if not defined $prop;
+       my $props = get_svnprops($path);
+       if (not defined $props->{$prop}) {
+               fatal("`$path' does not have a `$prop' SVN property.\n");
+       }
+       print $props->{$prop} . "\n";
+}
+
 sub cmd_multi_init {
        my $url = shift;
        unless (defined $_trunk || defined $_branches || defined $_tags) {
index 796d80e90e456536991cff460e4f49c3c48a6a2c..61c879959ca50d44e55a9b82519b1c45825e700b 100755 (executable)
@@ -170,4 +170,27 @@ test_expect_success 'test create-ignore' "
        git ls-files -s | grep gitignore | cmp - create-ignore-index.expect
        "
 
+cat >prop.expect <<\EOF
+no-such-file*
+
+EOF
+cat >prop2.expect <<\EOF
+8
+EOF
+
+# This test can be improved: since all the svn:ignore contain the same
+# pattern, it can pass even though the propget did not execute on the
+# right directory.
+test_expect_success 'test propget' "
+       git-svn propget svn:ignore . | cmp - prop.expect &&
+       cd deeply &&
+       git-svn propget svn:ignore . | cmp - ../prop.expect &&
+       git-svn propget svn:entry:committed-rev nested/directory/.keep \
+         | cmp - ../prop2.expect &&
+       git-svn propget svn:ignore .. | cmp - ../prop.expect &&
+       git-svn propget svn:ignore nested/ | cmp - ../prop.expect &&
+       git-svn propget svn:ignore ./nested | cmp - ../prop.expect &&
+       git-svn propget svn:ignore .././deeply/nested | cmp - ../prop.expect
+       "
+
 test_done