{"thread":{"id":"38134","subject":"[PATCH] git-svn: Support for git-svn propset","startedAt":"2014-12-06T22:29:42Z","lastAt":"2014-12-07T09:52:30Z","messageCount":6,"participants":["Alfred Perlstein","Eric Wong","Torsten Bögershausen","Eric Sunshine"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"253258","messageId":"20141206222942.GB91825@elvis.mu.org","threadId":"38134","inReplyTo":null,"subject":"[PATCH] git-svn: Support for git-svn propset","fromName":"Alfred Perlstein","fromEmail":"alfred@freebsd.org","sentAt":"2014-12-06T22:29:42Z","receivedAt":"2014-12-06T22:29:42Z","isPatch":true,"sender":{"key":"alfred@freebsd.org","avatar":"https://avatars.githubusercontent.com/u/629072?v=4"},"body":"This change allows git-svn to support setting subversion properties.\n\nVery useful for manually setting properties when committing to a\nsubversion repo that *requires* properties to be set without requiring\nmoving your changeset to separate subversion checkout in order to\nset props.\n\nThis change is initially from David Fraser <davidf () sjsoft ! com>\nAppearing here:\n  http://marc.info/?l=git&m=125259772625008&w=2\n\nThey are now forward ported to most recent git along with fixes to\ndeal with files in subdirectories.\n\nStyle and functional changes from Eric Wong have been taken\nin thier entirety from:\n  http://marc.info/?l=git&m=141742735608544&w=2\n\nReviewed-by: Eric Wong <normalperson@yhbt.net>\nSigned-off-by: Alfred Perlstein <alfred@freebsd.org>\nSigned-off-by: David Fraser <davidf@sjsoft.com>\n---\n git-svn.perl               | 49 +++++++++++++++++++++++++++++++-\n perl/Git/SVN/Editor.pm     | 43 ++++++++++++++++++++++++++++\n t/t9148-git-svn-propset.sh | 71 ++++++++++++++++++++++++++++++++++++++++++++++\n 3 files changed, 162 insertions(+), 1 deletion(-)\n create mode 100755 t/t9148-git-svn-propset.sh\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex b6e2186..5cdbf39 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -115,7 +115,7 @@ my ($_stdin, $_help, $_edit,\n \t$_before, $_after,\n \t$_merge, $_strategy, $_preserve_merges, $_dry_run, $_parents, $_local,\n \t$_prefix, $_no_checkout, $_url, $_verbose,\n-\t$_commit_url, $_tag, $_merge_info, $_interactive);\n+\t$_commit_url, $_tag, $_merge_info, $_interactive, $_set_svn_props);\n \n # This is a refactoring artifact so Git::SVN can get at this git-svn switch.\n sub opt_prefix { return $_prefix || '' }\n@@ -193,6 +193,7 @@ my %cmd = (\n \t\t\t  'dry-run|n' => \\$_dry_run,\n \t\t\t  'fetch-all|all' => \\$_fetch_all,\n \t\t\t  'commit-url=s' => \\$_commit_url,\n+\t\t\t  'set-svn-props=s' => \\$_set_svn_props,\n \t\t\t  'revision|r=i' => \\$_revision,\n \t\t\t  'no-rebase' => \\$_no_rebase,\n \t\t\t  'mergeinfo=s' => \\$_merge_info,\n@@ -228,6 +229,9 @@ my %cmd = (\n         'propget' => [ \\&cmd_propget,\n \t\t       'Print the value of a property on a file or directory',\n \t\t       { 'revision|r=i' => \\$_revision } ],\n+        'propset' => [ \\&cmd_propset,\n+\t\t       'Set the value of a property on a file or directory - will be set on commit',\n+\t\t       {} ],\n         'proplist' => [ \\&cmd_proplist,\n \t\t       'List all properties of a file or directory',\n \t\t       { 'revision|r=i' => \\$_revision } ],\n@@ -1376,6 +1380,49 @@ sub cmd_propget {\n \tprint $props->{$prop} . \"\\n\";\n }\n \n+# cmd_propset (PROPNAME, PROPVAL, PATH)\n+# ------------------------\n+# Adjust the SVN property PROPNAME to PROPVAL for PATH.\n+sub cmd_propset {\n+\tmy ($propname, $propval, $path) = @_;\n+\t$path = '.' if not defined $path;\n+\t$path = $cmd_dir_prefix . $path;\n+\tusage(1) if not defined $propname;\n+\tusage(1) if not defined $propval;\n+\tmy $file = basename($path);\n+\tmy $dn = dirname($path);\n+\tmy $cur_props = Git::SVN::Editor::check_attr( \"svn-properties\", $path );\n+\tmy $new_props = \"\";\n+\tif ($cur_props eq \"unset\" || $cur_props eq \"\" || $cur_props eq \"set\") {\n+\t\t$new_props = \"$propname=$propval\";\n+\t} else {\n+\t\t# TODO: handle combining properties better\n+\t\tmy @props = split(/;/, $cur_props);\n+\t\tmy $replaced_prop;\n+\t\tforeach my $prop (@props) {\n+\t\t\t# Parse 'name=value' syntax and set the property.\n+\t\t\tif ($prop =~ /([^=]+)=(.*)/) {\n+\t\t\t\tmy ($n,$v) = ($1,$2);\n+\t\t\t\tif ($n eq $propname)\n+\t\t\t\t{\n+\t\t\t\t\t$v = $propval;\n+\t\t\t\t\t$replaced_prop = 1;\n+\t\t\t\t}\n+\t\t\t\tif ($new_props eq \"\") { $new_props=\"$n=$v\"; }\n+\t\t\t\telse { $new_props=\"$new_props;$n=$v\"; }\n+\t\t\t}\n+\t\t}\n+\t\tif (!$replaced_prop) {\n+\t\t\t$new_props = \"$new_props;$propname=$propval\";\n+\t\t}\n+\t}\n+\tmy $attrfile = \"$dn/.gitattributes\";\n+\topen my $attrfh, '>>', $attrfile or die \"Can't open $attrfile: $!\\n\";\n+\t# TODO: don't simply append here if $file already has svn-properties\n+\tprint $attrfh \"$file svn-properties=$new_props\\n\" or die \"write to $attrfile\";\n+\tclose $attrfh or die \"close $attrfile\";\n+}\n+\n # cmd_proplist (PATH)\n # -------------------\n # Print the list of SVN properties for PATH.\ndiff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm\nindex 34e8af9..dd15318 100644\n--- a/perl/Git/SVN/Editor.pm\n+++ b/perl/Git/SVN/Editor.pm\n@@ -288,6 +288,45 @@ sub apply_autoprops {\n \t}\n }\n \n+sub check_attr\n+{\n+\tmy ($attr,$path) = @_;\n+\tmy $fh = command_output_pipe(\"check-attr\", $attr, \"--\", $path);\n+\treturn undef if (!$fh);\n+\n+\tmy $val = <$fh>;\n+\tclose $fh;\n+\t$val =~ s/^[^:]*:\\s*[^:]*:\\s*(.*)\\s*$/$1/;\n+\treturn $val;\n+}\n+\n+sub apply_manualprops {\n+\tmy ($self, $file, $fbat) = @_;\n+\tmy $pending_properties = check_attr( \"svn-properties\", $file );\n+\tif ($pending_properties eq \"\") { return; }\n+\t# Parse the list of properties to set.\n+\tmy @props = split(/;/, $pending_properties);\n+\t# TODO: get existing properties to compare to - this fails for add so currently not done\n+\t# my $existing_props = ::get_svnprops($file);\n+\tmy $existing_props = {};\n+\t# TODO: caching svn properties or storing them in .gitattributes would make that faster\n+\tforeach my $prop (@props) {\n+\t\t# Parse 'name=value' syntax and set the property.\n+\t\tif ($prop =~ /([^=]+)=(.*)/) {\n+\t\t\tmy ($n,$v) = ($1,$2);\n+\t\t\tfor ($n, $v) {\n+\t\t\t\ts/^\\s+//; s/\\s+$//;\n+\t\t\t}\n+\t\t\t# FIXME: clearly I don't know perl and couldn't work\n+\t\t\t# out how to evaluate this better\n+\t\t\tmy $existing = $existing_props->{$n};\n+\t\t\tif (!defined($existing) || $existing ne $v) {\n+\t\t\t    $self->change_file_prop($fbat, $n, $v);\n+\t\t\t}\n+\t\t}\n+\t}\n+}\n+\n sub A {\n \tmy ($self, $m, $deletions) = @_;\n \tmy ($dir, $file) = split_path($m->{file_b});\n@@ -296,6 +335,7 @@ sub A {\n \t\t\t\t\tundef, -1);\n \tprint \"\\tA\\t$m->{file_b}\\n\" unless $::_q;\n \t$self->apply_autoprops($file, $fbat);\n+\t$self->apply_manualprops($m->{file_b}, $fbat);\n \t$self->chg_file($fbat, $m);\n \t$self->close_file($fbat,undef,$self->{pool});\n }\n@@ -311,6 +351,7 @@ sub C {\n \tmy $fbat = $self->add_file($self->repo_path($m->{file_b}), $pbat,\n \t\t\t\t$upa, $self->{r});\n \tprint \"\\tC\\t$m->{file_a} => $m->{file_b}\\n\" unless $::_q;\n+\t$self->apply_manualprops($m->{file_b}, $fbat);\n \t$self->chg_file($fbat, $m);\n \t$self->close_file($fbat,undef,$self->{pool});\n }\n@@ -333,6 +374,7 @@ sub R {\n \t\t\t\t$upa, $self->{r});\n \tprint \"\\tR\\t$m->{file_a} => $m->{file_b}\\n\" unless $::_q;\n \t$self->apply_autoprops($file, $fbat);\n+\t$self->apply_manualprops($m->{file_b}, $fbat);\n \t$self->chg_file($fbat, $m);\n \t$self->close_file($fbat,undef,$self->{pool});\n \n@@ -348,6 +390,7 @@ sub M {\n \tmy $fbat = $self->open_file($self->repo_path($m->{file_b}),\n \t\t\t\t$pbat,$self->{r},$self->{pool});\n \tprint \"\\t$m->{chg}\\t$m->{file_b}\\n\" unless $::_q;\n+\t$self->apply_manualprops($m->{file_b}, $fbat);\n \t$self->chg_file($fbat, $m);\n \t$self->close_file($fbat,undef,$self->{pool});\n }\ndiff --git a/t/t9148-git-svn-propset.sh b/t/t9148-git-svn-propset.sh\nnew file mode 100755\nindex 0000000..b36a8a2\n--- /dev/null\n+++ b/t/t9148-git-svn-propset.sh\n@@ -0,0 +1,71 @@\n+#!/bin/sh\n+#\n+# Copyright (c) 2014 Alfred Perlstein\n+#\n+\n+test_description='git svn propset tests'\n+\n+. ./lib-git-svn.sh\n+\n+foo_subdir2=\"subdir/subdir2/foo_subdir2\"\n+\n+mkdir import\n+(cd import\n+\tmkdir subdir\n+\tmkdir subdir/subdir2\n+\ttouch foo\t\t# for 'add props top level'\n+\ttouch subdir/foo_subdir # for 'add props relative'\n+\ttouch \"$foo_subdir2\"\t# for 'add props subdir'\n+\tsvn_cmd import -m 'import for git svn' . \"$svnrepo\" >/dev/null\n+)\n+rm -rf import\n+\n+test_expect_success 'initialize git svn' 'git svn init \"$svnrepo\"'\n+test_expect_success 'fetch revisions from svn' 'git svn fetch'\n+\n+# There is a bogus feature about svn propset which means that it will only\n+# be taken as a delta for svn dcommit iff the file is also modified.\n+# That is fine for now.\n+test_expect_success 'add props top level' '\n+\tgit svn propset svn:keywords \"FreeBSD=%H\" foo &&\n+\techo hello >> foo &&\n+\tgit commit -m \"testing propset\" foo &&\n+\tgit svn dcommit\n+\tsvn_cmd co \"$svnrepo\" svn_project &&\n+\t(cd svn_project && test \"`svn propget svn:keywords foo`\" = \"FreeBSD=%H\") &&\n+\trm -rf svn_project\n+\t'\n+\n+test_expect_success 'add multiple props' '\n+\tgit svn propset svn:keywords \"FreeBSD=%H\" foo &&\n+\tgit svn propset fbsd:nokeywords yes foo &&\n+\techo hello >> foo &&\n+\tgit commit -m \"testing propset\" foo &&\n+\tgit svn dcommit\n+\tsvn_cmd co \"$svnrepo\" svn_project &&\n+\t(cd svn_project && test \"`svn propget svn:keywords foo`\" = \"FreeBSD=%H\") &&\n+\t(cd svn_project && test \"`svn propget fbsd:nokeywords foo`\" = \"yes\") &&\n+\t(cd svn_project && test \"`svn proplist -q foo | wc -l`\" -eq 2) &&\n+\trm -rf svn_project\n+\t'\n+\n+test_expect_success 'add props subdir' '\n+\tgit svn propset svn:keywords \"FreeBSD=%H\" \"$foo_subdir2\" &&\n+\techo hello >> \"$foo_subdir2\" &&\n+\tgit commit -m \"testing propset\" \"$foo_subdir2\" &&\n+\tgit svn dcommit\n+\tsvn_cmd co \"$svnrepo\" svn_project &&\n+\t(cd svn_project && test \"`svn propget svn:keywords \"$foo_subdir2\"`\" = \"FreeBSD=%H\") &&\n+\trm -rf svn_project\n+\t'\n+\n+test_expect_success 'add props relative' '\n+\t(cd subdir/subdir2 && git svn propset svn:keywords \"FreeBSD=%H\" ../foo_subdir ) &&\n+\techo hello >> subdir/foo_subdir &&\n+\tgit commit -m \"testing propset\" subdir/foo_subdir &&\n+\tgit svn dcommit\n+\tsvn_cmd co \"$svnrepo\" svn_project &&\n+\t(cd svn_project && test \"`svn propget svn:keywords subdir/foo_subdir`\" = \"FreeBSD=%H\") &&\n+\trm -rf svn_project\n+\t'\n+test_done\n-- \n2.1.2\n"},{"id":"253262","messageId":"20141207054211.GA25793@dcvr.yhbt.net","threadId":"38134","inReplyTo":"20141206222942.GB91825@elvis.mu.org","subject":"Re: [PATCH] git-svn: Support for git-svn propset","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2014-12-07T05:42:11Z","receivedAt":"2014-12-07T05:42:11Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Alfred Perlstein <alfred@freebsd.org> wrote:\n> This change allows git-svn to support setting subversion properties.\n> \n> Very useful for manually setting properties when committing to a\n> subversion repo that *requires* properties to be set without requiring\n> moving your changeset to separate subversion checkout in order to\n> set props.\n> \n> This change is initially from David Fraser <davidf () sjsoft ! com>\n\nNo point to obfuscate email addresses in commit messages (especially\nit's also in the Signed-off-by :).\n\n> Appearing here:\n>   http://marc.info/?l=git&m=125259772625008&w=2\n> \n> They are now forward ported to most recent git along with fixes to\n> deal with files in subdirectories.\n> \n> Style and functional changes from Eric Wong have been taken\n> in thier entirety from:\n\ns/thier/their/\n\n>   http://marc.info/?l=git&m=141742735608544&w=2\n\nFwiw, I prefer equivalent mid.gmane.org links since the message-ID\nremains useful if the web server ever goes away. e.g.:\n\n  http://mid.gmane.org/20141201094911.GA13931@dcvr.yhbt.net\n\n> Reviewed-by: Eric Wong <normalperson@yhbt.net>\n> Signed-off-by: Alfred Perlstein <alfred@freebsd.org>\n> Signed-off-by: David Fraser <davidf@sjsoft.com>\n\nI'd like to squash in the following changes (in order of importance):\n\n- use && to chain commands throughout tests\n- use svn_cmd wrapper throughout tests\n- show $! in die messages\n- favor $(...) over `...` in tests\n- make new_props an array simplify building the final list\n- wrap long comments (help output still needs fixing)\n- remove unnecessary FIXME comment\n\nNo need to resend if you're OK with these things.  Thanks again.\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex 5cdbf39..ec5cee4 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -1392,9 +1392,9 @@ sub cmd_propset {\n \tmy $file = basename($path);\n \tmy $dn = dirname($path);\n \tmy $cur_props = Git::SVN::Editor::check_attr( \"svn-properties\", $path );\n-\tmy $new_props = \"\";\n+\tmy @new_props;\n \tif ($cur_props eq \"unset\" || $cur_props eq \"\" || $cur_props eq \"set\") {\n-\t\t$new_props = \"$propname=$propval\";\n+\t\tpush @new_props, \"$propname=$propval\";\n \t} else {\n \t\t# TODO: handle combining properties better\n \t\tmy @props = split(/;/, $cur_props);\n@@ -1403,24 +1403,24 @@ sub cmd_propset {\n \t\t\t# Parse 'name=value' syntax and set the property.\n \t\t\tif ($prop =~ /([^=]+)=(.*)/) {\n \t\t\t\tmy ($n,$v) = ($1,$2);\n-\t\t\t\tif ($n eq $propname)\n-\t\t\t\t{\n+\t\t\t\tif ($n eq $propname) {\n \t\t\t\t\t$v = $propval;\n \t\t\t\t\t$replaced_prop = 1;\n \t\t\t\t}\n-\t\t\t\tif ($new_props eq \"\") { $new_props=\"$n=$v\"; }\n-\t\t\t\telse { $new_props=\"$new_props;$n=$v\"; }\n+\t\t\t\tpush @new_props, \"$n=$v\";\n \t\t\t}\n \t\t}\n \t\tif (!$replaced_prop) {\n-\t\t\t$new_props = \"$new_props;$propname=$propval\";\n+\t\t\tpush @new_props, \"$propname=$propval\";\n \t\t}\n \t}\n \tmy $attrfile = \"$dn/.gitattributes\";\n \topen my $attrfh, '>>', $attrfile or die \"Can't open $attrfile: $!\\n\";\n \t# TODO: don't simply append here if $file already has svn-properties\n-\tprint $attrfh \"$file svn-properties=$new_props\\n\" or die \"write to $attrfile\";\n-\tclose $attrfh or die \"close $attrfile\";\n+\tmy $new_props = join(';', @new_props);\n+\tprint $attrfh \"$file svn-properties=$new_props\\n\" or\n+\t\tdie \"write to $attrfile: $!\\n\";\n+\tclose $attrfh or die \"close $attrfile: $!\\n\";\n }\n \n # cmd_proplist (PATH)\ndiff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm\nindex dd15318..8bed2d9 100644\n--- a/perl/Git/SVN/Editor.pm\n+++ b/perl/Git/SVN/Editor.pm\n@@ -288,8 +288,7 @@ sub apply_autoprops {\n \t}\n }\n \n-sub check_attr\n-{\n+sub check_attr {\n \tmy ($attr,$path) = @_;\n \tmy $fh = command_output_pipe(\"check-attr\", $attr, \"--\", $path);\n \treturn undef if (!$fh);\n@@ -306,10 +305,12 @@ sub apply_manualprops {\n \tif ($pending_properties eq \"\") { return; }\n \t# Parse the list of properties to set.\n \tmy @props = split(/;/, $pending_properties);\n-\t# TODO: get existing properties to compare to - this fails for add so currently not done\n+\t# TODO: get existing properties to compare to\n+\t# - this fails for add so currently not done\n \t# my $existing_props = ::get_svnprops($file);\n \tmy $existing_props = {};\n-\t# TODO: caching svn properties or storing them in .gitattributes would make that faster\n+\t# TODO: caching svn properties or storing them in .gitattributes\n+\t# would make that faster\n \tforeach my $prop (@props) {\n \t\t# Parse 'name=value' syntax and set the property.\n \t\tif ($prop =~ /([^=]+)=(.*)/) {\n@@ -317,8 +318,6 @@ sub apply_manualprops {\n \t\t\tfor ($n, $v) {\n \t\t\t\ts/^\\s+//; s/\\s+$//;\n \t\t\t}\n-\t\t\t# FIXME: clearly I don't know perl and couldn't work\n-\t\t\t# out how to evaluate this better\n \t\t\tmy $existing = $existing_props->{$n};\n \t\t\tif (!defined($existing) || $existing ne $v) {\n \t\t\t    $self->change_file_prop($fbat, $n, $v);\ndiff --git a/t/t9148-git-svn-propset.sh b/t/t9148-git-svn-propset.sh\nindex b36a8a2..6973e8d 100755\n--- a/t/t9148-git-svn-propset.sh\n+++ b/t/t9148-git-svn-propset.sh\n@@ -9,16 +9,14 @@ test_description='git svn propset tests'\n \n foo_subdir2=\"subdir/subdir2/foo_subdir2\"\n \n-mkdir import\n-(cd import\n-\tmkdir subdir\n-\tmkdir subdir/subdir2\n-\ttouch foo\t\t# for 'add props top level'\n-\ttouch subdir/foo_subdir # for 'add props relative'\n-\ttouch \"$foo_subdir2\"\t# for 'add props subdir'\n+(mkdir import && cd import &&\n+\tmkdir subdir &&\n+\tmkdir subdir/subdir2 &&\n+\ttouch foo && : \"for 'add props top level'\" &&\n+\ttouch subdir/foo_subdir && : \"for 'add props relative'\" &&\n+\ttouch \"$foo_subdir2\" && : \"for 'add props subdir'\" &&\n \tsvn_cmd import -m 'import for git svn' . \"$svnrepo\" >/dev/null\n-)\n-rm -rf import\n+) && rm -rf import\n \n test_expect_success 'initialize git svn' 'git svn init \"$svnrepo\"'\n test_expect_success 'fetch revisions from svn' 'git svn fetch'\n@@ -30,9 +28,10 @@ test_expect_success 'add props top level' '\n \tgit svn propset svn:keywords \"FreeBSD=%H\" foo &&\n \techo hello >> foo &&\n \tgit commit -m \"testing propset\" foo &&\n-\tgit svn dcommit\n+\tgit svn dcommit &&\n \tsvn_cmd co \"$svnrepo\" svn_project &&\n-\t(cd svn_project && test \"`svn propget svn:keywords foo`\" = \"FreeBSD=%H\") &&\n+\t(cd svn_project &&\n+\t test \"$(svn_cmd propget svn:keywords foo)\" = \"FreeBSD=%H\") &&\n \trm -rf svn_project\n \t'\n \n@@ -41,11 +40,12 @@ test_expect_success 'add multiple props' '\n \tgit svn propset fbsd:nokeywords yes foo &&\n \techo hello >> foo &&\n \tgit commit -m \"testing propset\" foo &&\n-\tgit svn dcommit\n+\tgit svn dcommit &&\n \tsvn_cmd co \"$svnrepo\" svn_project &&\n-\t(cd svn_project && test \"`svn propget svn:keywords foo`\" = \"FreeBSD=%H\") &&\n-\t(cd svn_project && test \"`svn propget fbsd:nokeywords foo`\" = \"yes\") &&\n-\t(cd svn_project && test \"`svn proplist -q foo | wc -l`\" -eq 2) &&\n+\t(cd svn_project &&\n+\t\ttest \"$(svn_cmd propget svn:keywords foo)\" = \"FreeBSD=%H\" &&\n+\t\ttest \"$(svn_cmd propget fbsd:nokeywords foo)\" = \"yes\" &&\n+\t\ttest \"$(svn_cmd proplist -q foo | wc -l)\" -eq 2) &&\n \trm -rf svn_project\n \t'\n \n@@ -53,19 +53,24 @@ test_expect_success 'add props subdir' '\n \tgit svn propset svn:keywords \"FreeBSD=%H\" \"$foo_subdir2\" &&\n \techo hello >> \"$foo_subdir2\" &&\n \tgit commit -m \"testing propset\" \"$foo_subdir2\" &&\n-\tgit svn dcommit\n+\tgit svn dcommit &&\n \tsvn_cmd co \"$svnrepo\" svn_project &&\n-\t(cd svn_project && test \"`svn propget svn:keywords \"$foo_subdir2\"`\" = \"FreeBSD=%H\") &&\n+\t(cd svn_project &&\n+\t test \"$(svn_cmd propget svn:keywords \"$foo_subdir2\")\" = \"FreeBSD=%H\"\n+\t) &&\n \trm -rf svn_project\n \t'\n \n test_expect_success 'add props relative' '\n-\t(cd subdir/subdir2 && git svn propset svn:keywords \"FreeBSD=%H\" ../foo_subdir ) &&\n+\t(cd subdir/subdir2 &&\n+\t git svn propset svn:keywords \"FreeBSD=%H\" ../foo_subdir ) &&\n \techo hello >> subdir/foo_subdir &&\n \tgit commit -m \"testing propset\" subdir/foo_subdir &&\n-\tgit svn dcommit\n+\tgit svn dcommit &&\n \tsvn_cmd co \"$svnrepo\" svn_project &&\n-\t(cd svn_project && test \"`svn propget svn:keywords subdir/foo_subdir`\" = \"FreeBSD=%H\") &&\n+\t(cd svn_project &&\n+\t test \"$(svn_cmd propget svn:keywords subdir/foo_subdir)\" = \"FreeBSD=%H\"\n+\t) &&\n \trm -rf svn_project\n \t'\n test_done\n"},{"id":"253263","messageId":"5483E968.6060708@web.de","threadId":"38134","inReplyTo":"20141206222942.GB91825@elvis.mu.org","subject":"Re: [PATCH] git-svn: Support for git-svn propset","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2014-12-07T05:45:12Z","receivedAt":"2014-12-07T05:45:12Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"\n> diff --git a/t/t9148-git-svn-propset.sh b/t/t9148-git-svn-propset.sh\n> new file mode 100755\n> index 0000000..b36a8a2\n> --- /dev/null\n> +++ b/t/t9148-git-svn-propset.sh\n> @@ -0,0 +1,71 @@\n> +#!/bin/sh\n> +#\n> +# Copyright (c) 2014 Alfred Perlstein\n> +#\n> +\n> +test_description='git svn propset tests'\n> +\n> +. ./lib-git-svn.sh\n> +\n> +foo_subdir2=\"subdir/subdir2/foo_subdir2\"\n> +\nIn case something goes wrong (for whatever reason):\ndo we need a && chain here ?\n> +mkdir import\n> +(cd import\n> +\tmkdir subdir\n> +\tmkdir subdir/subdir2\n> +\ttouch foo\t\t# for 'add props top level'\n\"touch foo\" can be written shorter:\n>foo\n\n> +\ttouch subdir/foo_subdir # for 'add props relative'\n> +\ttouch \"$foo_subdir2\"\t# for 'add props subdir'\n> +\tsvn_cmd import -m 'import for git svn' . \"$svnrepo\" >/dev/null\n> +)\n> +rm -rf import\n> +\n\n> +test_expect_success 'initialize git svn' 'git svn init \"$svnrepo\"'\n> +test_expect_success 'fetch revisions from svn' 'git svn fetch'\nThis may look a little bit strange, 2 times test_expect_success in a row,\nis the indentention OK ?\n> +\n> +# There is a bogus feature about svn propset which means that it will only\n> +# be taken as a delta for svn dcommit iff the file is also modified.\n> +# That is fine for now.\n\"there is a bogus feature ?\"\nSmall typo: s/iff/if/\nHow about this:\n#The current implementation has a restriction:\n#svn propset will be taken as a delta for svn dcommit only\n#if the file content is also modified\n\n> +test_expect_success 'add props top level' '\n> +\tgit svn propset svn:keywords \"FreeBSD=%H\" foo &&\n> +\techo hello >> foo &&\n> +\tgit commit -m \"testing propset\" foo &&\n> +\tgit svn dcommit\n> +\tsvn_cmd co \"$svnrepo\" svn_project &&\n> +\t(cd svn_project && test \"`svn propget svn:keywords foo`\" = \"FreeBSD=%H\") &&\n> +\trm -rf svn_project\n> +\t'\nIs there a reason why there is no \"&&\" after \"git svn dcommit\" ?\nIf yes, it could be better to make this really clear to the readers and write\n(This idea is stolen from Peff)\n\n{ git svn dcommit || true } &&\n\n> +\n> +test_expect_success 'add multiple props' '\n> +\tgit svn propset svn:keywords \"FreeBSD=%H\" foo &&\n> +\tgit svn propset fbsd:nokeywords yes foo &&\n> +\techo hello >> foo &&\n> +\tgit commit -m \"testing propset\" foo &&\n> +\tgit svn dcommit\n> +\tsvn_cmd co \"$svnrepo\" svn_project &&\n> +\t(cd svn_project && test \"`svn propget svn:keywords foo`\" = \"FreeBSD=%H\") &&\n> +\t(cd svn_project && test \"`svn propget fbsd:nokeywords foo`\" = \"yes\") &&\n> +\t(cd svn_project && test \"`svn proplist -q foo | wc -l`\" -eq 2) &&\n> +\trm -rf svn_project\n> +\t'\n> +\nAh, another small thing:\nthe \"wc -l\" will not work under Mac OS X.\nPlease see test_line_count() in t/test-lib-functions.sh\n\nAnd thanks for improving Git\n"},{"id":"253267","messageId":"5484090C.8070101@web.de","threadId":"38134","inReplyTo":"5483E968.6060708@web.de","subject":"Re: [PATCH] git-svn: Support for git-svn propset","fromName":"Torsten Bögershausen","fromEmail":"tboegi@web.de","sentAt":"2014-12-07T08:00:12Z","receivedAt":"2014-12-07T08:00:12Z","isPatch":true,"sender":{"key":"tboegi@web.de","avatar":"https://avatars.githubusercontent.com/u/7138363?v=4"},"body":"On 2014-12-07 06.45, Torsten Bögershausen wrote:\n[]\n>> +\n>> +test_expect_success 'add multiple props' '\n>> +\tgit svn propset svn:keywords \"FreeBSD=%H\" foo &&\n>> +\tgit svn propset fbsd:nokeywords yes foo &&\n>> +\techo hello >> foo &&\n>> +\tgit commit -m \"testing propset\" foo &&\n>> +\tgit svn dcommit\n>> +\tsvn_cmd co \"$svnrepo\" svn_project &&\n>> +\t(cd svn_project && test \"`svn propget svn:keywords foo`\" = \"FreeBSD=%H\") &&\n>> +\t(cd svn_project && test \"`svn propget fbsd:nokeywords foo`\" = \"yes\") &&\n>> +\t(cd svn_project && test \"`svn proplist -q foo | wc -l`\" -eq 2) &&\n>> +\trm -rf svn_project\n>> +\t'\n>> +\n> Ah, another small thing:\n> the \"wc -l\" will not work under Mac OS X.\n> Please see test_line_count() in t/test-lib-functions.sh\n> \nMy excuse:\nI think I am wrong here and I need to correct myself after having looked at other TC's.\nThe \"wc -l\" should work under Mac OS X.\n\nAnother small nit:\n\nThis \n\"`svn propget svn:keywords foo`\" = \"FreeBSD=%H\")\ncan be written as\n\"$(svn propget svn:keywords foo)\" = \"FreeBSD=%H\")\n\n(if you want to use the \"Git style\" for command substitution)\n"},{"id":"253270","messageId":"CAPig+cTH5XXxMkaB9HOSm6ppFuZj4fVnCRmbSva2i_h5d4QVOA@mail.gmail.com","threadId":"38134","inReplyTo":"5484090C.8070101@web.de","subject":"Re: [PATCH] git-svn: Support for git-svn propset","fromName":"Eric Sunshine","fromEmail":"sunshine@sunshineco.com","sentAt":"2014-12-07T09:23:20Z","receivedAt":"2014-12-07T09:23:20Z","isPatch":true,"sender":{"key":"sunshine@sunshineco.com","avatar":"https://avatars.githubusercontent.com/u/163641?v=4"},"body":"On Sun, Dec 7, 2014 at 3:00 AM, Torsten Bögershausen <tboegi@web.de> wrote:\n> On 2014-12-07 06.45, Torsten Bögershausen wrote:\n> []\n>>> +\n>>> +test_expect_success 'add multiple props' '\n>>> +    git svn propset svn:keywords \"FreeBSD=%H\" foo &&\n>>> +    git svn propset fbsd:nokeywords yes foo &&\n>>> +    echo hello >> foo &&\n>>> +    git commit -m \"testing propset\" foo &&\n>>> +    git svn dcommit\n>>> +    svn_cmd co \"$svnrepo\" svn_project &&\n>>> +    (cd svn_project && test \"`svn propget svn:keywords foo`\" = \"FreeBSD=%H\") &&\n>>> +    (cd svn_project && test \"`svn propget fbsd:nokeywords foo`\" = \"yes\") &&\n>>> +    (cd svn_project && test \"`svn proplist -q foo | wc -l`\" -eq 2) &&\n>>> +    rm -rf svn_project\n>>> +    '\n>>> +\n>> Ah, another small thing:\n>> the \"wc -l\" will not work under Mac OS X.\n>> Please see test_line_count() in t/test-lib-functions.sh\n>>\n> My excuse:\n> I think I am wrong here and I need to correct myself after having looked at other TC's.\n> The \"wc -l\" should work under Mac OS X.\n\nMore specifically: On Mac OS X, \"wc -l\" outputs \"{whitespace}number\"\nwhich won't match \"2\" with the string '=' operator, however, this case\nworks because the '-eq' operator coerces the output of \"wc -l\" to a\nnumber, which can match the 2.\n"},{"id":"253273","messageId":"5484235E.5070003@freebsd.org","threadId":"38134","inReplyTo":"20141207054211.GA25793@dcvr.yhbt.net","subject":"Re: [PATCH] git-svn: Support for git-svn propset","fromName":"Alfred Perlstein","fromEmail":"alfred@freebsd.org","sentAt":"2014-12-07T09:52:30Z","receivedAt":"2014-12-07T09:52:30Z","isPatch":true,"sender":{"key":"alfred@freebsd.org","avatar":"https://avatars.githubusercontent.com/u/629072?v=4"},"body":"\nOn 12/6/14, 9:42 PM, Eric Wong wrote:\n> Alfred Perlstein <alfred@freebsd.org> wrote:\n>> This change allows git-svn to support setting subversion properties.\n>>\n>> Very useful for manually setting properties when committing to a\n>> subversion repo that *requires* properties to be set without requiring\n>> moving your changeset to separate subversion checkout in order to\n>> set props.\n>>\n>> This change is initially from David Fraser <davidf () sjsoft ! com>\n> No point to obfuscate email addresses in commit messages (especially\n> it's also in the Signed-off-by :).\n>\n>> Appearing here:\n>>    http://marc.info/?l=git&m=125259772625008&w=2\n>>\n>> They are now forward ported to most recent git along with fixes to\n>> deal with files in subdirectories.\n>>\n>> Style and functional changes from Eric Wong have been taken\n>> in thier entirety from:\n> s/thier/their/\n>\n>>    http://marc.info/?l=git&m=141742735608544&w=2\n> Fwiw, I prefer equivalent mid.gmane.org links since the message-ID\n> remains useful if the web server ever goes away. e.g.:\n>\n>    http://mid.gmane.org/20141201094911.GA13931@dcvr.yhbt.net\n>\n>> Reviewed-by: Eric Wong <normalperson@yhbt.net>\n>> Signed-off-by: Alfred Perlstein <alfred@freebsd.org>\n>> Signed-off-by: David Fraser <davidf@sjsoft.com>\n> I'd like to squash in the following changes (in order of importance):\n>\n> - use && to chain commands throughout tests\n> - use svn_cmd wrapper throughout tests\n> - show $! in die messages\n> - favor $(...) over `...` in tests\n> - make new_props an array simplify building the final list\n> - wrap long comments (help output still needs fixing)\n> - remove unnecessary FIXME comment\n>\n> No need to resend if you're OK with these things.  Thanks again.\nHmm, I refactored tests because it bothered me that I had done all that \ncut and pasting, in doing so I found and fixed a bug with uninitialized \nvariables in the check_attr() function.\n\nLet me send my final diff, I will try to properly incorporate your \nchanges as well in that diff.\n\n-Alfred\n\n\n>\n> diff --git a/git-svn.perl b/git-svn.perl\n> index 5cdbf39..ec5cee4 100755\n> --- a/git-svn.perl\n> +++ b/git-svn.perl\n> @@ -1392,9 +1392,9 @@ sub cmd_propset {\n>   \tmy $file = basename($path);\n>   \tmy $dn = dirname($path);\n>   \tmy $cur_props = Git::SVN::Editor::check_attr( \"svn-properties\", $path );\n> -\tmy $new_props = \"\";\n> +\tmy @new_props;\n>   \tif ($cur_props eq \"unset\" || $cur_props eq \"\" || $cur_props eq \"set\") {\n> -\t\t$new_props = \"$propname=$propval\";\n> +\t\tpush @new_props, \"$propname=$propval\";\n>   \t} else {\n>   \t\t# TODO: handle combining properties better\n>   \t\tmy @props = split(/;/, $cur_props);\n> @@ -1403,24 +1403,24 @@ sub cmd_propset {\n>   \t\t\t# Parse 'name=value' syntax and set the property.\n>   \t\t\tif ($prop =~ /([^=]+)=(.*)/) {\n>   \t\t\t\tmy ($n,$v) = ($1,$2);\n> -\t\t\t\tif ($n eq $propname)\n> -\t\t\t\t{\n> +\t\t\t\tif ($n eq $propname) {\n>   \t\t\t\t\t$v = $propval;\n>   \t\t\t\t\t$replaced_prop = 1;\n>   \t\t\t\t}\n> -\t\t\t\tif ($new_props eq \"\") { $new_props=\"$n=$v\"; }\n> -\t\t\t\telse { $new_props=\"$new_props;$n=$v\"; }\n> +\t\t\t\tpush @new_props, \"$n=$v\";\n>   \t\t\t}\n>   \t\t}\n>   \t\tif (!$replaced_prop) {\n> -\t\t\t$new_props = \"$new_props;$propname=$propval\";\n> +\t\t\tpush @new_props, \"$propname=$propval\";\n>   \t\t}\n>   \t}\n>   \tmy $attrfile = \"$dn/.gitattributes\";\n>   \topen my $attrfh, '>>', $attrfile or die \"Can't open $attrfile: $!\\n\";\n>   \t# TODO: don't simply append here if $file already has svn-properties\n> -\tprint $attrfh \"$file svn-properties=$new_props\\n\" or die \"write to $attrfile\";\n> -\tclose $attrfh or die \"close $attrfile\";\n> +\tmy $new_props = join(';', @new_props);\n> +\tprint $attrfh \"$file svn-properties=$new_props\\n\" or\n> +\t\tdie \"write to $attrfile: $!\\n\";\n> +\tclose $attrfh or die \"close $attrfile: $!\\n\";\n>   }\n>   \n>   # cmd_proplist (PATH)\n> diff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm\n> index dd15318..8bed2d9 100644\n> --- a/perl/Git/SVN/Editor.pm\n> +++ b/perl/Git/SVN/Editor.pm\n> @@ -288,8 +288,7 @@ sub apply_autoprops {\n>   \t}\n>   }\n>   \n> -sub check_attr\n> -{\n> +sub check_attr {\n>   \tmy ($attr,$path) = @_;\n>   \tmy $fh = command_output_pipe(\"check-attr\", $attr, \"--\", $path);\n>   \treturn undef if (!$fh);\n> @@ -306,10 +305,12 @@ sub apply_manualprops {\n>   \tif ($pending_properties eq \"\") { return; }\n>   \t# Parse the list of properties to set.\n>   \tmy @props = split(/;/, $pending_properties);\n> -\t# TODO: get existing properties to compare to - this fails for add so currently not done\n> +\t# TODO: get existing properties to compare to\n> +\t# - this fails for add so currently not done\n>   \t# my $existing_props = ::get_svnprops($file);\n>   \tmy $existing_props = {};\n> -\t# TODO: caching svn properties or storing them in .gitattributes would make that faster\n> +\t# TODO: caching svn properties or storing them in .gitattributes\n> +\t# would make that faster\n>   \tforeach my $prop (@props) {\n>   \t\t# Parse 'name=value' syntax and set the property.\n>   \t\tif ($prop =~ /([^=]+)=(.*)/) {\n> @@ -317,8 +318,6 @@ sub apply_manualprops {\n>   \t\t\tfor ($n, $v) {\n>   \t\t\t\ts/^\\s+//; s/\\s+$//;\n>   \t\t\t}\n> -\t\t\t# FIXME: clearly I don't know perl and couldn't work\n> -\t\t\t# out how to evaluate this better\n>   \t\t\tmy $existing = $existing_props->{$n};\n>   \t\t\tif (!defined($existing) || $existing ne $v) {\n>   \t\t\t    $self->change_file_prop($fbat, $n, $v);\n> diff --git a/t/t9148-git-svn-propset.sh b/t/t9148-git-svn-propset.sh\n> index b36a8a2..6973e8d 100755\n> --- a/t/t9148-git-svn-propset.sh\n> +++ b/t/t9148-git-svn-propset.sh\n> @@ -9,16 +9,14 @@ test_description='git svn propset tests'\n>   \n>   foo_subdir2=\"subdir/subdir2/foo_subdir2\"\n>   \n> -mkdir import\n> -(cd import\n> -\tmkdir subdir\n> -\tmkdir subdir/subdir2\n> -\ttouch foo\t\t# for 'add props top level'\n> -\ttouch subdir/foo_subdir # for 'add props relative'\n> -\ttouch \"$foo_subdir2\"\t# for 'add props subdir'\n> +(mkdir import && cd import &&\n> +\tmkdir subdir &&\n> +\tmkdir subdir/subdir2 &&\n> +\ttouch foo && : \"for 'add props top level'\" &&\n> +\ttouch subdir/foo_subdir && : \"for 'add props relative'\" &&\n> +\ttouch \"$foo_subdir2\" && : \"for 'add props subdir'\" &&\n>   \tsvn_cmd import -m 'import for git svn' . \"$svnrepo\" >/dev/null\n> -)\n> -rm -rf import\n> +) && rm -rf import\n>   \n>   test_expect_success 'initialize git svn' 'git svn init \"$svnrepo\"'\n>   test_expect_success 'fetch revisions from svn' 'git svn fetch'\n> @@ -30,9 +28,10 @@ test_expect_success 'add props top level' '\n>   \tgit svn propset svn:keywords \"FreeBSD=%H\" foo &&\n>   \techo hello >> foo &&\n>   \tgit commit -m \"testing propset\" foo &&\n> -\tgit svn dcommit\n> +\tgit svn dcommit &&\n>   \tsvn_cmd co \"$svnrepo\" svn_project &&\n> -\t(cd svn_project && test \"`svn propget svn:keywords foo`\" = \"FreeBSD=%H\") &&\n> +\t(cd svn_project &&\n> +\t test \"$(svn_cmd propget svn:keywords foo)\" = \"FreeBSD=%H\") &&\n>   \trm -rf svn_project\n>   \t'\n>   \n> @@ -41,11 +40,12 @@ test_expect_success 'add multiple props' '\n>   \tgit svn propset fbsd:nokeywords yes foo &&\n>   \techo hello >> foo &&\n>   \tgit commit -m \"testing propset\" foo &&\n> -\tgit svn dcommit\n> +\tgit svn dcommit &&\n>   \tsvn_cmd co \"$svnrepo\" svn_project &&\n> -\t(cd svn_project && test \"`svn propget svn:keywords foo`\" = \"FreeBSD=%H\") &&\n> -\t(cd svn_project && test \"`svn propget fbsd:nokeywords foo`\" = \"yes\") &&\n> -\t(cd svn_project && test \"`svn proplist -q foo | wc -l`\" -eq 2) &&\n> +\t(cd svn_project &&\n> +\t\ttest \"$(svn_cmd propget svn:keywords foo)\" = \"FreeBSD=%H\" &&\n> +\t\ttest \"$(svn_cmd propget fbsd:nokeywords foo)\" = \"yes\" &&\n> +\t\ttest \"$(svn_cmd proplist -q foo | wc -l)\" -eq 2) &&\n>   \trm -rf svn_project\n>   \t'\n>   \n> @@ -53,19 +53,24 @@ test_expect_success 'add props subdir' '\n>   \tgit svn propset svn:keywords \"FreeBSD=%H\" \"$foo_subdir2\" &&\n>   \techo hello >> \"$foo_subdir2\" &&\n>   \tgit commit -m \"testing propset\" \"$foo_subdir2\" &&\n> -\tgit svn dcommit\n> +\tgit svn dcommit &&\n>   \tsvn_cmd co \"$svnrepo\" svn_project &&\n> -\t(cd svn_project && test \"`svn propget svn:keywords \"$foo_subdir2\"`\" = \"FreeBSD=%H\") &&\n> +\t(cd svn_project &&\n> +\t test \"$(svn_cmd propget svn:keywords \"$foo_subdir2\")\" = \"FreeBSD=%H\"\n> +\t) &&\n>   \trm -rf svn_project\n>   \t'\n>   \n>   test_expect_success 'add props relative' '\n> -\t(cd subdir/subdir2 && git svn propset svn:keywords \"FreeBSD=%H\" ../foo_subdir ) &&\n> +\t(cd subdir/subdir2 &&\n> +\t git svn propset svn:keywords \"FreeBSD=%H\" ../foo_subdir ) &&\n>   \techo hello >> subdir/foo_subdir &&\n>   \tgit commit -m \"testing propset\" subdir/foo_subdir &&\n> -\tgit svn dcommit\n> +\tgit svn dcommit &&\n>   \tsvn_cmd co \"$svnrepo\" svn_project &&\n> -\t(cd svn_project && test \"`svn propget svn:keywords subdir/foo_subdir`\" = \"FreeBSD=%H\") &&\n> +\t(cd svn_project &&\n> +\t test \"$(svn_cmd propget svn:keywords subdir/foo_subdir)\" = \"FreeBSD=%H\"\n> +\t) &&\n>   \trm -rf svn_project\n>   \t'\n>   test_done\n>\n"}]}