Code

git-svn: teach dcommit about svn auto-props
authorBrad King <brad.king@kitware.com>
Fri, 25 Jul 2008 15:32:37 +0000 (11:32 -0400)
committerJunio C Hamano <gitster@pobox.com>
Sat, 26 Jul 2008 00:54:19 +0000 (17:54 -0700)
Subversion repositories often require files to have properties such as
svn:mime-type and svn:eol-style set when they are added.  Users
typically set these properties automatically using the SVN auto-props
feature with 'svn add'.  This commit teaches dcommit to look at the user
SVN configuration and apply matching auto-props entries for files added
by a diff as it is applied to the SVN remote.

Signed-off-by: Brad King <brad.king@kitware.com>
Acked-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Junio C Hamano <gitster@pobox.com>
git-svn.perl
t/t9124-git-svn-dcommit-auto-props.sh [new file with mode: 0755]

index 2e0e55242ff089cda3c87ae57f7c776c13508a56..cf6dbbc42773fef394c27cd87109b69c3144753c 100755 (executable)
@@ -3340,6 +3340,7 @@ sub new {
        $self->{rm} = { };
        $self->{path_prefix} = length $self->{svn_path} ?
                               "$self->{svn_path}/" : '';
+       $self->{config} = $opts->{config};
        return $self;
 }
 
@@ -3528,6 +3529,57 @@ sub ensure_path {
        return $bat->{$c};
 }
 
+# Subroutine to convert a globbing pattern to a regular expression.
+# From perl cookbook.
+sub glob2pat {
+       my $globstr = shift;
+       my %patmap = ('*' => '.*', '?' => '.', '[' => '[', ']' => ']');
+       $globstr =~ s{(.)} { $patmap{$1} || "\Q$1" }ge;
+       return '^' . $globstr . '$';
+}
+
+sub check_autoprop {
+       my ($self, $pattern, $properties, $file, $fbat) = @_;
+       # Convert the globbing pattern to a regular expression.
+       my $regex = glob2pat($pattern);
+       # Check if the pattern matches the file name.
+       if($file =~ m/($regex)/) {
+               # Parse the list of properties to set.
+               my @props = split(/;/, $properties);
+               foreach my $prop (@props) {
+                       # Parse 'name=value' syntax and set the property.
+                       if ($prop =~ /([^=]+)=(.*)/) {
+                               my ($n,$v) = ($1,$2);
+                               for ($n, $v) {
+                                       s/^\s+//; s/\s+$//;
+                               }
+                               $self->change_file_prop($fbat, $n, $v);
+                       }
+               }
+       }
+}
+
+sub apply_autoprops {
+       my ($self, $file, $fbat) = @_;
+       my $conf_t = ${$self->{config}}{'config'};
+       no warnings 'once';
+       # Check [miscellany]/enable-auto-props in svn configuration.
+       if (SVN::_Core::svn_config_get_bool(
+               $conf_t,
+               $SVN::_Core::SVN_CONFIG_SECTION_MISCELLANY,
+               $SVN::_Core::SVN_CONFIG_OPTION_ENABLE_AUTO_PROPS,
+               0)) {
+               # Auto-props are enabled.  Enumerate them to look for matches.
+               my $callback = sub {
+                       $self->check_autoprop($_[0], $_[1], $file, $fbat);
+               };
+               SVN::_Core::svn_config_enumerate(
+                       $conf_t,
+                       $SVN::_Core::SVN_CONFIG_SECTION_AUTO_PROPS,
+                       $callback);
+       }
+}
+
 sub A {
        my ($self, $m) = @_;
        my ($dir, $file) = split_path($m->{file_b});
@@ -3535,6 +3587,7 @@ sub A {
        my $fbat = $self->add_file($self->repo_path($m->{file_b}), $pbat,
                                        undef, -1);
        print "\tA\t$m->{file_b}\n" unless $::_q;
+       $self->apply_autoprops($file, $fbat);
        $self->chg_file($fbat, $m);
        $self->close_file($fbat,undef,$self->{pool});
 }
diff --git a/t/t9124-git-svn-dcommit-auto-props.sh b/t/t9124-git-svn-dcommit-auto-props.sh
new file mode 100755 (executable)
index 0000000..8223c59
--- /dev/null
@@ -0,0 +1,86 @@
+#!/bin/sh
+#
+# Copyright (c) 2008 Brad King
+
+test_description='git-svn dcommit honors auto-props'
+
+. ./lib-git-svn.sh
+
+generate_auto_props() {
+cat << EOF
+[miscellany]
+enable-auto-props=$1
+[auto-props]
+*.sh  = svn:mime-type=application/x-shellscript; svn:eol-style=LF
+*.txt = svn:mime-type=text/plain; svn:eol-style = native
+EOF
+}
+
+test_expect_success 'initialize git-svn' '
+       mkdir import &&
+       (
+               cd import &&
+               echo foo >foo &&
+               svn import -m "import for git-svn" . "$svnrepo"
+       ) &&
+       rm -rf import &&
+       git-svn init "$svnrepo"
+       git-svn fetch
+'
+
+test_expect_success 'enable auto-props config' '
+       cd "$gittestrepo" &&
+       mkdir user &&
+       generate_auto_props yes >user/config
+'
+
+test_expect_success 'add files matching auto-props' '
+       cd "$gittestrepo" &&
+       echo "#!$SHELL_PATH" >exec1.sh &&
+       chmod +x exec1.sh &&
+       echo "hello" >hello.txt &&
+       echo bar >bar &&
+       git add exec1.sh hello.txt bar &&
+       git commit -m "files for enabled auto-props" &&
+       git svn dcommit --config-dir=user
+'
+
+test_expect_success 'disable auto-props config' '
+       cd "$gittestrepo" &&
+       generate_auto_props no >user/config
+'
+
+test_expect_success 'add files matching disabled auto-props' '
+       cd "$gittestrepo" &&
+       echo "#$SHELL_PATH" >exec2.sh &&
+       chmod +x exec2.sh &&
+       echo "world" >world.txt &&
+       echo zot >zot &&
+       git add exec2.sh world.txt zot &&
+       git commit -m "files for disabled auto-props" &&
+       git svn dcommit --config-dir=user
+'
+
+test_expect_success 'check resulting svn repository' '
+       mkdir work &&
+       cd work &&
+       svn co "$svnrepo" &&
+       cd svnrepo &&
+
+       # Check properties from first commit.
+       test "x$(svn propget svn:executable exec1.sh)" = "x*" &&
+       test "x$(svn propget svn:mime-type exec1.sh)" = \
+            "xapplication/x-shellscript" &&
+       test "x$(svn propget svn:mime-type hello.txt)" = "xtext/plain" &&
+       test "x$(svn propget svn:eol-style hello.txt)" = "xnative" &&
+       test "x$(svn propget svn:mime-type bar)" = "x" &&
+
+       # Check properties from second commit.
+       test "x$(svn propget svn:executable exec2.sh)" = "x*" &&
+       test "x$(svn propget svn:mime-type exec2.sh)" = "x" &&
+       test "x$(svn propget svn:mime-type world.txt)" = "x" &&
+       test "x$(svn propget svn:eol-style world.txt)" = "x" &&
+       test "x$(svn propget svn:mime-type zot)" = "x"
+'
+
+test_done