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@xxxxxxxxxxx> --- Eric Wong wrote: > I like this patch. Thanks. > Can we get an automated test of this functionality? This patch adds a test. I also fixed the property name/value parsing to remove leading and trailing whitespace. > We can (and probably should) set $HOME for the test and ignore the > existing ~/.subversion/config of the user. I used the --config-dir option. > Also, some minor nitpicks on whitespace/formatting inline below. Addressed. I missed the wrong indentation before because my second patch removed it. > I haven't had the chance to look at this. Can anybody else shed more > light on that bug? It's really strange that the tests won't run because > of it. Are you unable to run some git-svn tests or all of them? Just that one fails. All others (including the one in the patch below) pass. Thanks for reviewing, -Brad git-svn.perl | 52 ++++++++++++++++++++ t/t9124-git-svn-dcommit-auto-props.sh | 84 +++++++++++++++++++++++++++++++++ 2 files changed, 136 insertions(+), 0 deletions(-) create mode 100755 t/t9124-git-svn-dcommit-auto-props.sh
diff --git a/git-svn.perl b/git-svn.perl index 2e0e552..0a8e907 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -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,56 @@ 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); + $n =~ s/^\s+//; $n =~ s/\s+$//; + $v =~ s/^\s+//; $v =~ 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 +3586,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 index 0000000..beefbcc --- /dev/null +++ b/t/t9124-git-svn-dcommit-auto-props.sh @@ -0,0 +1,84 @@ +#!/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" >/dev/null && + cd .. && + 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 "#!/bin/sh" > 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 "#!/bin/sh" > 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