git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Alfred Perlstein <alfred@freebsd.org>
To: git@vger.kernel.org
Cc: Eric Wong <normalperson@yhbt.net>,
	Jonathan Nieder <jrnieder@gmail.com>,
	Junio C Hamano <gitster@pobox.com>,
	"Michael G. Schwern" <schwern@pobox.com>,
	David Fraser <davidf@sjsoft.com>
Subject: [PATCH] git-svn: Support for git-svn propset
Date: Sat, 6 Dec 2014 14:29:42 -0800	[thread overview]
Message-ID: <20141206222942.GB91825@elvis.mu.org> (raw)

This change allows git-svn to support setting subversion properties.

Very useful for manually setting properties when committing to a
subversion repo that *requires* properties to be set without requiring
moving your changeset to separate subversion checkout in order to
set props.

This change is initially from David Fraser <davidf () sjsoft ! com>
Appearing here:
  http://marc.info/?l=git&m=125259772625008&w=2

They are now forward ported to most recent git along with fixes to
deal with files in subdirectories.

Style and functional changes from Eric Wong have been taken
in thier entirety from:
  http://marc.info/?l=git&m=141742735608544&w=2

Reviewed-by: Eric Wong <normalperson@yhbt.net>
Signed-off-by: Alfred Perlstein <alfred@freebsd.org>
Signed-off-by: David Fraser <davidf@sjsoft.com>
---
 git-svn.perl               | 49 +++++++++++++++++++++++++++++++-
 perl/Git/SVN/Editor.pm     | 43 ++++++++++++++++++++++++++++
 t/t9148-git-svn-propset.sh | 71 ++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 162 insertions(+), 1 deletion(-)
 create mode 100755 t/t9148-git-svn-propset.sh

diff --git a/git-svn.perl b/git-svn.perl
index b6e2186..5cdbf39 100755
--- a/git-svn.perl
+++ b/git-svn.perl
@@ -115,7 +115,7 @@ my ($_stdin, $_help, $_edit,
 	$_before, $_after,
 	$_merge, $_strategy, $_preserve_merges, $_dry_run, $_parents, $_local,
 	$_prefix, $_no_checkout, $_url, $_verbose,
-	$_commit_url, $_tag, $_merge_info, $_interactive);
+	$_commit_url, $_tag, $_merge_info, $_interactive, $_set_svn_props);
 
 # This is a refactoring artifact so Git::SVN can get at this git-svn switch.
 sub opt_prefix { return $_prefix || '' }
@@ -193,6 +193,7 @@ my %cmd = (
 			  'dry-run|n' => \$_dry_run,
 			  'fetch-all|all' => \$_fetch_all,
 			  'commit-url=s' => \$_commit_url,
+			  'set-svn-props=s' => \$_set_svn_props,
 			  'revision|r=i' => \$_revision,
 			  'no-rebase' => \$_no_rebase,
 			  'mergeinfo=s' => \$_merge_info,
@@ -228,6 +229,9 @@ my %cmd = (
         'propget' => [ \&cmd_propget,
 		       'Print the value of a property on a file or directory',
 		       { 'revision|r=i' => \$_revision } ],
+        'propset' => [ \&cmd_propset,
+		       'Set the value of a property on a file or directory - will be set on commit',
+		       {} ],
         'proplist' => [ \&cmd_proplist,
 		       'List all properties of a file or directory',
 		       { 'revision|r=i' => \$_revision } ],
@@ -1376,6 +1380,49 @@ sub cmd_propget {
 	print $props->{$prop} . "\n";
 }
 
+# cmd_propset (PROPNAME, PROPVAL, PATH)
+# ------------------------
+# Adjust the SVN property PROPNAME to PROPVAL for PATH.
+sub cmd_propset {
+	my ($propname, $propval, $path) = @_;
+	$path = '.' if not defined $path;
+	$path = $cmd_dir_prefix . $path;
+	usage(1) if not defined $propname;
+	usage(1) if not defined $propval;
+	my $file = basename($path);
+	my $dn = dirname($path);
+	my $cur_props = Git::SVN::Editor::check_attr( "svn-properties", $path );
+	my $new_props = "";
+	if ($cur_props eq "unset" || $cur_props eq "" || $cur_props eq "set") {
+		$new_props = "$propname=$propval";
+	} else {
+		# TODO: handle combining properties better
+		my @props = split(/;/, $cur_props);
+		my $replaced_prop;
+		foreach my $prop (@props) {
+			# Parse 'name=value' syntax and set the property.
+			if ($prop =~ /([^=]+)=(.*)/) {
+				my ($n,$v) = ($1,$2);
+				if ($n eq $propname)
+				{
+					$v = $propval;
+					$replaced_prop = 1;
+				}
+				if ($new_props eq "") { $new_props="$n=$v"; }
+				else { $new_props="$new_props;$n=$v"; }
+			}
+		}
+		if (!$replaced_prop) {
+			$new_props = "$new_props;$propname=$propval";
+		}
+	}
+	my $attrfile = "$dn/.gitattributes";
+	open my $attrfh, '>>', $attrfile or die "Can't open $attrfile: $!\n";
+	# TODO: don't simply append here if $file already has svn-properties
+	print $attrfh "$file svn-properties=$new_props\n" or die "write to $attrfile";
+	close $attrfh or die "close $attrfile";
+}
+
 # cmd_proplist (PATH)
 # -------------------
 # Print the list of SVN properties for PATH.
diff --git a/perl/Git/SVN/Editor.pm b/perl/Git/SVN/Editor.pm
index 34e8af9..dd15318 100644
--- a/perl/Git/SVN/Editor.pm
+++ b/perl/Git/SVN/Editor.pm
@@ -288,6 +288,45 @@ sub apply_autoprops {
 	}
 }
 
+sub check_attr
+{
+	my ($attr,$path) = @_;
+	my $fh = command_output_pipe("check-attr", $attr, "--", $path);
+	return undef if (!$fh);
+
+	my $val = <$fh>;
+	close $fh;
+	$val =~ s/^[^:]*:\s*[^:]*:\s*(.*)\s*$/$1/;
+	return $val;
+}
+
+sub apply_manualprops {
+	my ($self, $file, $fbat) = @_;
+	my $pending_properties = check_attr( "svn-properties", $file );
+	if ($pending_properties eq "") { return; }
+	# Parse the list of properties to set.
+	my @props = split(/;/, $pending_properties);
+	# TODO: get existing properties to compare to - this fails for add so currently not done
+	# my $existing_props = ::get_svnprops($file);
+	my $existing_props = {};
+	# TODO: caching svn properties or storing them in .gitattributes would make that faster
+	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+$//;
+			}
+			# FIXME: clearly I don't know perl and couldn't work
+			# out how to evaluate this better
+			my $existing = $existing_props->{$n};
+			if (!defined($existing) || $existing ne $v) {
+			    $self->change_file_prop($fbat, $n, $v);
+			}
+		}
+	}
+}
+
 sub A {
 	my ($self, $m, $deletions) = @_;
 	my ($dir, $file) = split_path($m->{file_b});
@@ -296,6 +335,7 @@ sub A {
 					undef, -1);
 	print "\tA\t$m->{file_b}\n" unless $::_q;
 	$self->apply_autoprops($file, $fbat);
+	$self->apply_manualprops($m->{file_b}, $fbat);
 	$self->chg_file($fbat, $m);
 	$self->close_file($fbat,undef,$self->{pool});
 }
@@ -311,6 +351,7 @@ sub C {
 	my $fbat = $self->add_file($self->repo_path($m->{file_b}), $pbat,
 				$upa, $self->{r});
 	print "\tC\t$m->{file_a} => $m->{file_b}\n" unless $::_q;
+	$self->apply_manualprops($m->{file_b}, $fbat);
 	$self->chg_file($fbat, $m);
 	$self->close_file($fbat,undef,$self->{pool});
 }
@@ -333,6 +374,7 @@ sub R {
 				$upa, $self->{r});
 	print "\tR\t$m->{file_a} => $m->{file_b}\n" unless $::_q;
 	$self->apply_autoprops($file, $fbat);
+	$self->apply_manualprops($m->{file_b}, $fbat);
 	$self->chg_file($fbat, $m);
 	$self->close_file($fbat,undef,$self->{pool});
 
@@ -348,6 +390,7 @@ sub M {
 	my $fbat = $self->open_file($self->repo_path($m->{file_b}),
 				$pbat,$self->{r},$self->{pool});
 	print "\t$m->{chg}\t$m->{file_b}\n" unless $::_q;
+	$self->apply_manualprops($m->{file_b}, $fbat);
 	$self->chg_file($fbat, $m);
 	$self->close_file($fbat,undef,$self->{pool});
 }
diff --git a/t/t9148-git-svn-propset.sh b/t/t9148-git-svn-propset.sh
new file mode 100755
index 0000000..b36a8a2
--- /dev/null
+++ b/t/t9148-git-svn-propset.sh
@@ -0,0 +1,71 @@
+#!/bin/sh
+#
+# Copyright (c) 2014 Alfred Perlstein
+#
+
+test_description='git svn propset tests'
+
+. ./lib-git-svn.sh
+
+foo_subdir2="subdir/subdir2/foo_subdir2"
+
+mkdir import
+(cd import
+	mkdir subdir
+	mkdir subdir/subdir2
+	touch foo		# for 'add props top level'
+	touch subdir/foo_subdir # for 'add props relative'
+	touch "$foo_subdir2"	# for 'add props subdir'
+	svn_cmd import -m 'import for git svn' . "$svnrepo" >/dev/null
+)
+rm -rf import
+
+test_expect_success 'initialize git svn' 'git svn init "$svnrepo"'
+test_expect_success 'fetch revisions from svn' 'git svn fetch'
+
+# There is a bogus feature about svn propset which means that it will only
+# be taken as a delta for svn dcommit iff the file is also modified.
+# That is fine for now.
+test_expect_success 'add props top level' '
+	git svn propset svn:keywords "FreeBSD=%H" foo &&
+	echo hello >> foo &&
+	git commit -m "testing propset" foo &&
+	git svn dcommit
+	svn_cmd co "$svnrepo" svn_project &&
+	(cd svn_project && test "`svn propget svn:keywords foo`" = "FreeBSD=%H") &&
+	rm -rf svn_project
+	'
+
+test_expect_success 'add multiple props' '
+	git svn propset svn:keywords "FreeBSD=%H" foo &&
+	git svn propset fbsd:nokeywords yes foo &&
+	echo hello >> foo &&
+	git commit -m "testing propset" foo &&
+	git svn dcommit
+	svn_cmd co "$svnrepo" svn_project &&
+	(cd svn_project && test "`svn propget svn:keywords foo`" = "FreeBSD=%H") &&
+	(cd svn_project && test "`svn propget fbsd:nokeywords foo`" = "yes") &&
+	(cd svn_project && test "`svn proplist -q foo | wc -l`" -eq 2) &&
+	rm -rf svn_project
+	'
+
+test_expect_success 'add props subdir' '
+	git svn propset svn:keywords "FreeBSD=%H" "$foo_subdir2" &&
+	echo hello >> "$foo_subdir2" &&
+	git commit -m "testing propset" "$foo_subdir2" &&
+	git svn dcommit
+	svn_cmd co "$svnrepo" svn_project &&
+	(cd svn_project && test "`svn propget svn:keywords "$foo_subdir2"`" = "FreeBSD=%H") &&
+	rm -rf svn_project
+	'
+
+test_expect_success 'add props relative' '
+	(cd subdir/subdir2 && git svn propset svn:keywords "FreeBSD=%H" ../foo_subdir ) &&
+	echo hello >> subdir/foo_subdir &&
+	git commit -m "testing propset" subdir/foo_subdir &&
+	git svn dcommit
+	svn_cmd co "$svnrepo" svn_project &&
+	(cd svn_project && test "`svn propget svn:keywords subdir/foo_subdir`" = "FreeBSD=%H") &&
+	rm -rf svn_project
+	'
+test_done
-- 
2.1.2

             reply	other threads:[~2014-12-06 22:29 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-12-06 22:29 Alfred Perlstein [this message]
2014-12-07  5:42 ` [PATCH] git-svn: Support for git-svn propset Eric Wong
2014-12-07  9:52   ` Alfred Perlstein
2014-12-07  5:45 ` Torsten Bögershausen
2014-12-07  8:00   ` Torsten Bögershausen
2014-12-07  9:23     ` Eric Sunshine
  -- strict thread matches above, loose matches on Subject: below --
2014-12-07 10:47 Alfred Perlstein
2014-12-08 21:36 ` Eric Wong
2014-12-08 23:43   ` Alfred Perlstein
2014-12-01  6:24 Alfred Perlstein
2014-12-01  9:49 ` Eric Wong

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20141206222942.GB91825@elvis.mu.org \
    --to=alfred@freebsd.org \
    --cc=davidf@sjsoft.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=jrnieder@gmail.com \
    --cc=normalperson@yhbt.net \
    --cc=schwern@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).