{"thread":{"id":"20895","subject":"git svn propset support","startedAt":"2009-09-10T15:41:06Z","lastAt":"2009-09-10T15:41:06Z","messageCount":1,"participants":["David Fraser"],"isPatch":false,"patchVersion":null,"patchTotal":null},"messages":[{"id":"122817","messageId":"1077746712.371252597266033.JavaMail.root@klofta.sjsoft.com","threadId":"20895","inReplyTo":"1699967795.351252597251356.JavaMail.root@klofta.sjsoft.com","subject":"git svn propset support","fromName":"David Fraser","fromEmail":"davidf@sjsoft.com","sentAt":"2009-09-10T15:41:06Z","receivedAt":"2009-09-10T15:41:06Z","isPatch":false,"sender":{"key":"davidf@sjsoft.com","avatar":null},"body":"Hi\n\nI've been trying to hack at getting manually property setting support for git-svn.\n\nI've got a start of a patch that basically stores an attribute 'svn-properties' for each file that needs them changed, and then sets the properties when committing.\n\nIssues remaining:\n * The way it edits the .gitattributes file is suboptimal - it just appends to the end the latest version\n * It could use the existing code to get the current svn properties to see if properties need to be changed; but this doesn't work on add\n * It would be better to cache all the svn properties locally - this could be done automatically in .gitattributes but I'm not sure everyone would want this, etc\n * No support for deleting properties\n\nUsage is:\n git svn propset PROPNAME PROPVALUE PATH\n\nPatch attached (against 1.6.0.2) - any comments welcome\n\nDavid\n\n-- \nDavid Fraser\nSt James Software\n\n\n--- git-1.6.0.2/git-svn.perl\t2008-12-15 15:52:14.000000000 +0200\n+++ git-svn.perl\t2009-09-10 17:35:04.000000000 +0200\n@@ -66,7 +66,7 @@\n \t$_version, $_fetch_all, $_no_rebase,\n \t$_merge, $_strategy, $_dry_run, $_local,\n \t$_prefix, $_no_checkout, $_url, $_verbose,\n-\t$_git_format, $_commit_url);\n+\t$_git_format, $_commit_url, $_set_svn_props);\n $Git::SVN::_follow_parent = 1;\n my %remote_opts = ( 'username=s' => \\$Git::SVN::Prompt::_username,\n                     'config-dir=s' => \\$Git::SVN::Ra::config_dir,\n@@ -128,6 +128,7 @@\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%cmt_opts, %fc_opts } ],\n@@ -141,6 +142,9 @@\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@@ -700,6 +704,64 @@\n \tprint $props->{$prop} . \"\\n\";\n }\n \n+sub check_attr\n+{\n+    my ($attr,$path) = @_;\n+    if ( open my $fh, '-|', \"git\", \"check-attr\", $attr, \"--\", $path )\n+    {\n+\tmy $val = <$fh>;\n+\tclose $fh;\n+\t$val =~ s/^[^:]*:\\s*[^:]*:\\s*(.*)\\s*$/$1/;\n+\treturn $val;\n+    }\n+    else\n+    {\n+\treturn undef;\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 $current_properties = check_attr( \"svn-properties\", $path );\n+\tmy $new_properties = \"\";\n+\tif ($current_properties eq \"unset\" || $current_properties eq \"\" || $current_properties eq \"set\") {\n+\t\t$new_properties = \"$propname=$propval\";\n+\t} else {\n+\t\t# TODO: handle combining properties better\n+\t\tmy @props = split(/;/, $current_properties);\n+\t\tmy $replaced_prop = 0;\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_properties eq \"\") { $new_properties=\"$n=$v\"; }\n+\t\t\t\telse { $new_properties=\"$new_properties;$n=$v\"; }\n+\t\t\t}\n+\t\t}\n+\t\tif ($replaced_prop eq 0) {\n+\t\t\t$new_properties = \"$new_properties;$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_properties\\n\";\n+}\n+\n # cmd_proplist (PATH)\n # -------------------\n # Print the list of SVN properties for PATH.\n@@ -3598,6 +3660,34 @@\n \t}\n }\n \n+sub apply_manualprops {\n+\tmy ($self, $file, $fbat) = @_;\n+\tmy $path = $cmd_dir_prefix . $file;\n+\tmy $pending_properties = ::check_attr( \"svn-properties\", $path );\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 out how to evaluate this better\n+\t\t\tif (defined $existing_props->{$n} && $existing_props->{$n} eq $v) {\n+\t\t\t\tmy $needed = 0;\n+\t\t\t} else {\n+\t\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) = @_;\n \tmy ($dir, $file) = split_path($m->{file_b});\n@@ -3606,6 +3696,7 @@\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($file, $fbat);\n \t$self->chg_file($fbat, $m);\n \t$self->close_file($fbat,undef,$self->{pool});\n }\n@@ -3617,6 +3708,7 @@\n \tmy $fbat = $self->add_file($self->repo_path($m->{file_b}), $pbat,\n \t\t\t\t$self->url_path($m->{file_a}), $self->{r});\n \tprint \"\\tC\\t$m->{file_a} => $m->{file_b}\\n\" unless $::_q;\n+\t$self->apply_manualprops($file, $fbat);\n \t$self->chg_file($fbat, $m);\n \t$self->close_file($fbat,undef,$self->{pool});\n }\n@@ -3636,6 +3728,7 @@\n \tmy $fbat = $self->add_file($self->repo_path($m->{file_b}), $pbat,\n \t\t\t\t$self->url_path($m->{file_a}), $self->{r});\n \tprint \"\\tR\\t$m->{file_a} => $m->{file_b}\\n\" unless $::_q;\n+\t$self->apply_manualprops($file, $fbat);\n \t$self->chg_file($fbat, $m);\n \t$self->close_file($fbat,undef,$self->{pool});\n \n@@ -3651,6 +3744,7 @@\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($file, $fbat);\n \t$self->chg_file($fbat, $m);\n \t$self->close_file($fbat,undef,$self->{pool});\n }\n"}]}