git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 1/9] git-svn: fix a typo in defining the --no-stop-on-copy option
  2006-02-20 18:57 git-svn: nearing 1.0.0 Eric Wong
@ 2006-02-20 18:57 ` Eric Wong
  2006-02-20 18:57   ` [PATCH 2/9] git-svn: allow --find-copies-harder and -l<num> to be passed on commit Eric Wong
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Wong @ 2006-02-20 18:57 UTC (permalink / raw)
  To: git; +Cc: junkio, Eric Wong

Just a typo, I doubt anybody would use (and I highly recommend not
using) this option anyways.  But you never know...

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 contrib/git-svn/git-svn |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

7292b0320d5aab4f335b7c1198b77231bf78d44a
diff --git a/contrib/git-svn/git-svn b/contrib/git-svn/git-svn
index 71a8b3b..1a8f40e 100755
--- a/contrib/git-svn/git-svn
+++ b/contrib/git-svn/git-svn
@@ -38,7 +38,7 @@ GetOptions(	'revision|r=s' => \$_revisio
 		'edit|e' => \$_edit,
 		'rmdir' => \$_rmdir,
 		'help|H|h' => \$_help,
-		'no-stop-copy' => \$_no_stop_copy );
+		'no-stop-on-copy' => \$_no_stop_copy );
 my %cmd = (
 	fetch => [ \&fetch, "Download new revisions from SVN" ],
 	init => [ \&init, "Initialize and fetch (import)"],
-- 
1.2.0.gdee6

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* git-svn: nearing 1.0.0
@ 2006-02-20 18:57 Eric Wong
  2006-02-20 18:57 ` [PATCH 1/9] git-svn: fix a typo in defining the --no-stop-on-copy option Eric Wong
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Wong @ 2006-02-20 18:57 UTC (permalink / raw)
  To: git; +Cc: junkio

      
This should hopefully be the last set of bugfixes I have for git-svn.  I'm
pretty satisfied with it, as I haven't needed to directly invoke svn and wait
for it in any of my day-to-day operations for doing work on svn repositories.

Most of the major changes are in 'commit' functionality where several
corner-case bugs have been found and fixed.

      git-svn: fix a typo in defining the --no-stop-on-copy option
      git-svn: allow --find-copies-harder and -l<num> to be passed on commit
      git-svn: Allow for more argument types for commit (from..to)
      git-svn: remove any need for the XML::Simple dependency
      git-svn: change ; to && in addremove()
      contrib/git-svn.txt: add a note about renamed/copied directory support
      git-svn: fix several corner-case and rare bugs with 'commit'
      contrib/git-svn: add Makefile, test, and associated ignores
      git-svn: 0.9.1: add --version and copyright/license (GPL v2+) information

 .gitignore                 |    4 
 Makefile                   |   32 +++
 git-svn.perl               |  382 +++++++++++++++++++++++++++++++--------------
 git-svn.txt                |   16 +
 t/t0000-contrib-git-svn.sh |  216 +++++++++++++++++++++++++
 5 files changed, 532 insertions(+), 118 deletions(-)

-- 
Eric Wong

^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH 2/9] git-svn: allow --find-copies-harder and -l<num> to be passed on commit
  2006-02-20 18:57 ` [PATCH 1/9] git-svn: fix a typo in defining the --no-stop-on-copy option Eric Wong
@ 2006-02-20 18:57   ` Eric Wong
  2006-02-20 18:57     ` [PATCH 3/9] git-svn: Allow for more argument types for commit (from..to) Eric Wong
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Wong @ 2006-02-20 18:57 UTC (permalink / raw)
  To: git; +Cc: junkio, Eric Wong

Both of these options are passed directly to git-diff-tree when
committing to a SVN repository.

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 contrib/git-svn/git-svn     |   10 ++++++++--
 contrib/git-svn/git-svn.txt |    7 +++++++
 2 files changed, 15 insertions(+), 2 deletions(-)

f00770e6f3151e5fdc94208efab22b3068dbb882
diff --git a/contrib/git-svn/git-svn b/contrib/git-svn/git-svn
index 1a8f40e..477ec16 100755
--- a/contrib/git-svn/git-svn
+++ b/contrib/git-svn/git-svn
@@ -30,7 +30,8 @@ use Getopt::Long qw/:config gnu_getopt n
 use File::Spec qw//;
 my $sha1 = qr/[a-f\d]{40}/;
 my $sha1_short = qr/[a-f\d]{6,40}/;
-my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit);
+my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit,
+	$_find_copies_harder, $_l);
 
 GetOptions(	'revision|r=s' => \$_revision,
 		'no-ignore-externals' => \$_no_ignore_ext,
@@ -38,6 +39,8 @@ GetOptions(	'revision|r=s' => \$_revisio
 		'edit|e' => \$_edit,
 		'rmdir' => \$_rmdir,
 		'help|H|h' => \$_help,
+		'find-copies-harder' => \$_find_copies_harder,
+		'l=i' => \$_l,
 		'no-stop-on-copy' => \$_no_stop_copy );
 my %cmd = (
 	fetch => [ \&fetch, "Download new revisions from SVN" ],
@@ -348,7 +351,10 @@ sub svn_checkout_tree {
 	my $pid = open my $diff_fh, '-|';
 	defined $pid or croak $!;
 	if ($pid == 0) {
-		exec(qw(git-diff-tree -z -r -C), $from, $commit) or croak $!;
+		my @diff_tree = qw(git-diff-tree -z -r -C);
+		push @diff_tree, '--find-copies-harder' if $_find_copies_harder;
+		push @diff_tree, "-l$_l" if defined $_l;
+		exec(@diff_tree, $from, $commit) or croak $!;
 	}
 	my $mods = parse_diff_tree($diff_fh);
 	unless (@$mods) {
diff --git a/contrib/git-svn/git-svn.txt b/contrib/git-svn/git-svn.txt
index 4b79fb0..9912f5a 100644
--- a/contrib/git-svn/git-svn.txt
+++ b/contrib/git-svn/git-svn.txt
@@ -99,6 +99,13 @@ OPTIONS
 	default for objects that are commits, and forced on when committing
 	tree objects.
 
+-l<num>::
+--find-copies-harder::
+	Both of these are only used with the 'commit' command.
+
+	They are both passed directly to git-diff-tree see
+	git-diff-tree(1) for more information.
+
 COMPATIBILITY OPTIONS
 ---------------------
 --no-ignore-externals::
-- 
1.2.0.gdee6

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 3/9] git-svn: Allow for more argument types for commit (from..to)
  2006-02-20 18:57   ` [PATCH 2/9] git-svn: allow --find-copies-harder and -l<num> to be passed on commit Eric Wong
@ 2006-02-20 18:57     ` Eric Wong
  2006-02-20 18:57       ` [PATCH 4/9] git-svn: remove any need for the XML::Simple dependency Eric Wong
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Wong @ 2006-02-20 18:57 UTC (permalink / raw)
  To: git; +Cc: junkio, Eric Wong

Allow 'from..to' notation from the command line.

More liberal sha1 parsing when reading from stdin no longer requires the
sha1 to be the first character, so a leading 'commit ' string is OK.

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 contrib/git-svn/git-svn     |   13 ++++++++++---
 contrib/git-svn/git-svn.txt |    2 +-
 2 files changed, 11 insertions(+), 4 deletions(-)

4d8326c4868461e8a48a4e25ef11ece6e9f92843
diff --git a/contrib/git-svn/git-svn b/contrib/git-svn/git-svn
index 477ec16..5f23d6b 100755
--- a/contrib/git-svn/git-svn
+++ b/contrib/git-svn/git-svn
@@ -216,14 +216,21 @@ sub commit {
 		print "Reading from stdin...\n";
 		@commits = ();
 		while (<STDIN>) {
-			if (/^([a-f\d]{6,40})\b/) {
+			if (/\b([a-f\d]{6,40})\b/) {
 				unshift @commits, $1;
 			}
 		}
 	}
 	my @revs;
-	foreach (@commits) {
-		push @revs, (safe_qx('git-rev-parse',$_));
+	foreach my $c (@commits) {
+		chomp(my @tmp = safe_qx('git-rev-parse',$c));
+		if (scalar @tmp == 1) {
+			push @revs, $tmp[0];
+		} elsif (scalar @tmp > 1) {
+			push @revs, reverse (safe_qx('git-rev-list',@tmp));
+		} else {
+			die "Failed to rev-parse $c\n";
+		}
 	}
 	chomp @revs;
 
diff --git a/contrib/git-svn/git-svn.txt b/contrib/git-svn/git-svn.txt
index 9912f5a..07a236f 100644
--- a/contrib/git-svn/git-svn.txt
+++ b/contrib/git-svn/git-svn.txt
@@ -149,7 +149,7 @@ Tracking and contributing to an Subversi
 # Commit only the git commits you want to SVN::
 	git-svn commit <tree-ish> [<tree-ish_2> ...]
 # Commit all the git commits from my-branch that don't exist in SVN::
-	git rev-list --pretty=oneline git-svn-HEAD..my-branch | git-svn commit
+	git commit git-svn-HEAD..my-branch
 # Something is committed to SVN, pull the latest into your branch::
 	git-svn fetch && git pull . git-svn-HEAD
 
-- 
1.2.0.gdee6

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 5/9] git-svn: change ; to && in addremove()
  2006-02-20 18:57       ` [PATCH 4/9] git-svn: remove any need for the XML::Simple dependency Eric Wong
@ 2006-02-20 18:57         ` Eric Wong
  2006-02-20 18:57           ` [PATCH 6/9] contrib/git-svn.txt: add a note about renamed/copied directory support Eric Wong
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Wong @ 2006-02-20 18:57 UTC (permalink / raw)
  To: git; +Cc: junkio, Eric Wong

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 contrib/git-svn/git-svn |    4 ++--
 1 files changed, 2 insertions(+), 2 deletions(-)

ff01f98a865018be26baf1008c669009e95a93bf
diff --git a/contrib/git-svn/git-svn b/contrib/git-svn/git-svn
index 4391bc3..25c248d 100755
--- a/contrib/git-svn/git-svn
+++ b/contrib/git-svn/git-svn
@@ -580,10 +580,10 @@ sub sys { system(@_) == 0 or croak $? }
 
 sub git_addremove {
 	system( "git-diff-files --name-only -z ".
-				" | git-update-index --remove -z --stdin; ".
+				" | git-update-index --remove -z --stdin && ".
 		"git-ls-files -z --others ".
 			"'--exclude-from=$GIT_DIR/$GIT_SVN/info/exclude'".
-				" | git-update-index --add -z --stdin; "
+				" | git-update-index --add -z --stdin"
 		) == 0 or croak $?
 }
 
-- 
1.2.0.gdee6

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 6/9] contrib/git-svn.txt: add a note about renamed/copied directory support
  2006-02-20 18:57         ` [PATCH 5/9] git-svn: change ; to && in addremove() Eric Wong
@ 2006-02-20 18:57           ` Eric Wong
  2006-02-20 18:57             ` [PATCH 7/9] git-svn: fix several corner-case and rare bugs with 'commit' Eric Wong
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Wong @ 2006-02-20 18:57 UTC (permalink / raw)
  To: git; +Cc: junkio, Eric Wong

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 contrib/git-svn/git-svn.txt |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

72331d46b99b182406e06070e905123f76abbac8
diff --git a/contrib/git-svn/git-svn.txt b/contrib/git-svn/git-svn.txt
index 07a236f..cf098d7 100644
--- a/contrib/git-svn/git-svn.txt
+++ b/contrib/git-svn/git-svn.txt
@@ -206,6 +206,13 @@ working trees with metadata files.
 svn:keywords can't be ignored in Subversion (at least I don't know of
 a way to ignore them).
 
+Renamed and copied directories are not detected by git and hence not
+tracked when committing to SVN.  I do not plan on adding support for
+this as it's quite difficult and time-consuming to get working for all
+the possible corner cases (git doesn't do it, either).  Renamed and
+copied files are fully supported if they're similar enough for git to
+detect them.
+
 Author
 ------
 Written by Eric Wong <normalperson@yhbt.net>.
-- 
1.2.0.gdee6

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 7/9] git-svn: fix several corner-case and rare bugs with 'commit'
  2006-02-20 18:57           ` [PATCH 6/9] contrib/git-svn.txt: add a note about renamed/copied directory support Eric Wong
@ 2006-02-20 18:57             ` Eric Wong
  2006-02-20 18:57               ` [PATCH 8/9] contrib/git-svn: add Makefile, test, and associated ignores Eric Wong
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Wong @ 2006-02-20 18:57 UTC (permalink / raw)
  To: git; +Cc: junkio, Eric Wong

None of these were really show-stoppers (or even triggered)
on most of the trees I've tracked.

* Node change prevention for identically named nodes.  This is
  a limitation of SVN, but we find the error and exit before
  it's passed to SVN so we don't dirty our working tree when our
  commit fails.  git-svn will exit with an error code 1 if any
  of the following conditions are found:

  1.  a directory is removed and a file of the same name of the
      removed directory is created
  1a. a file has its parent directory removed and the file is
      takes the name of the removed parent directory::
          baz/zzz    =>  baz
  2.  a file is removed and a directory of the same name of the
      removed file is created.
  2a. a file is moved into a deeper directory that shares the
      previous name of the file::
          dir/$file  =>  dir/file/$file

  Since SVN cannot handle these cases, the user will have to
  manually split the commit into several parts.

* --rmdir now handles nested/deep removals. If dir/a/b/c/d/e/file
  is removed, and everything else is in the dir/ hierarchy is
  otherwise empty, then dir/ will be deleted when file is deleted
  from svn and --rmdir specified.

* Always assert that we have written the tree we want to write
  on commits.  This helped me find several bugs in the symlink
  handling code (which as been fixed).

* Several symlink handling fixes.  We now refuse to set
  permissions on symlinks.  We also always unlink a file
  if we're going to overwrite it.

* Apply changes in a pre-determined order, so we always have
  rename from locations handy before we delete them.

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 contrib/git-svn/git-svn |  260 ++++++++++++++++++++++++++++++++++++-----------
 1 files changed, 200 insertions(+), 60 deletions(-)

cc9e5f27fee073de35fd6f50ec15ea59dda8b71b
diff --git a/contrib/git-svn/git-svn b/contrib/git-svn/git-svn
index 25c248d..3a59454 100755
--- a/contrib/git-svn/git-svn
+++ b/contrib/git-svn/git-svn
@@ -238,7 +238,11 @@ sub commit {
 	my $svn_current_rev =  svn_info('.')->{'Last Changed Rev'};
 	foreach my $c (@revs) {
 		print "Committing $c\n";
-		svn_checkout_tree($svn_current_rev, $c);
+		my $mods = svn_checkout_tree($svn_current_rev, $c);
+		if (scalar @$mods == 0) {
+			print "Skipping, no changes detected\n";
+			next;
+		}
 		$svn_current_rev = svn_commit_tree($svn_current_rev, $c);
 	}
 	print "Done committing ",scalar @revs," revisions to SVN\n";
@@ -267,9 +271,9 @@ sub setup_git_svn {
 }
 
 sub assert_svn_wc_clean {
-	my ($svn_rev, $commit) = @_;
+	my ($svn_rev, $treeish) = @_;
 	croak "$svn_rev is not an integer!\n" unless ($svn_rev =~ /^\d+$/);
-	croak "$commit is not a sha1!\n" unless ($commit =~ /^$sha1$/o);
+	croak "$treeish is not a sha1!\n" unless ($treeish =~ /^$sha1$/o);
 	my $svn_info = svn_info('.');
 	if ($svn_rev != $svn_info->{'Last Changed Rev'}) {
 		croak "Expected r$svn_rev, got r",
@@ -282,12 +286,42 @@ sub assert_svn_wc_clean {
 		print STDERR $_ foreach @status;
 		croak;
 	}
-	my ($tree_a) = grep(/^tree $sha1$/o,`git-cat-file commit $commit`);
-	$tree_a =~ s/^tree //;
-	chomp $tree_a;
-	chomp(my $tree_b = `GIT_INDEX_FILE=$GIT_SVN_INDEX git-write-tree`);
-	if ($tree_a ne $tree_b) {
-		croak "$svn_rev != $commit, $tree_a != $tree_b\n";
+	assert_tree($treeish);
+}
+
+sub assert_tree {
+	my ($treeish) = @_;
+	croak "Not a sha1: $treeish\n" unless $treeish =~ /^$sha1$/o;
+	chomp(my $type = `git-cat-file -t $treeish`);
+	my $expected;
+	while ($type eq 'tag') {
+		chomp(($treeish, $type) = `git-cat-file tag $treeish`);
+	}
+	if ($type eq 'commit') {
+		$expected = (grep /^tree /,`git-cat-file commit $treeish`)[0];
+		($expected) = ($expected =~ /^tree ($sha1)$/);
+		die "Unable to get tree from $treeish\n" unless $expected;
+	} elsif ($type eq 'tree') {
+		$expected = $treeish;
+	} else {
+		die "$treeish is a $type, expected tree, tag or commit\n";
+	}
+
+	my $old_index = $ENV{GIT_INDEX_FILE};
+	my $tmpindex = $GIT_SVN_INDEX.'.assert-tmp';
+	if (-e $tmpindex) {
+		unlink $tmpindex or croak $!;
+	}
+	$ENV{GIT_INDEX_FILE} = $tmpindex;
+	git_addremove();
+	chomp(my $tree = `git-write-tree`);
+	if ($old_index) {
+		$ENV{GIT_INDEX_FILE} = $old_index;
+	} else {
+		delete $ENV{GIT_INDEX_FILE};
+	}
+	if ($tree ne $expected) {
+		croak "Tree mismatch, Got: $tree, Expected: $expected\n";
 	}
 }
 
@@ -298,7 +332,6 @@ sub parse_diff_tree {
 	my @mods;
 	while (<$diff_fh>) {
 		chomp $_; # this gets rid of the trailing "\0"
-		print $_,"\n";
 		if ($state eq 'meta' && /^:(\d{6})\s(\d{6})\s
 					$sha1\s($sha1)\s([MTCRAD])\d*$/xo) {
 			push @mods, {	mode_a => $1, mode_b => $2,
@@ -309,36 +342,44 @@ sub parse_diff_tree {
 				$state = 'file_b';
 			}
 		} elsif ($state eq 'file_a') {
-			my $x = $mods[$#mods] or croak __LINE__,": Empty array\n";
+			my $x = $mods[$#mods] or croak "Empty array\n";
 			if ($x->{chg} !~ /^(?:C|R)$/) {
-				croak __LINE__,": Error parsing $_, $x->{chg}\n";
+				croak "Error parsing $_, $x->{chg}\n";
 			}
 			$x->{file_a} = $_;
 			$state = 'file_b';
 		} elsif ($state eq 'file_b') {
-			my $x = $mods[$#mods] or croak __LINE__,": Empty array\n";
+			my $x = $mods[$#mods] or croak "Empty array\n";
 			if (exists $x->{file_a} && $x->{chg} !~ /^(?:C|R)$/) {
-				croak __LINE__,": Error parsing $_, $x->{chg}\n";
+				croak "Error parsing $_, $x->{chg}\n";
 			}
 			if (!exists $x->{file_a} && $x->{chg} =~ /^(?:C|R)$/) {
-				croak __LINE__,": Error parsing $_, $x->{chg}\n";
+				croak "Error parsing $_, $x->{chg}\n";
 			}
 			$x->{file_b} = $_;
 			$state = 'meta';
 		} else {
-			croak __LINE__,": Error parsing $_\n";
+			croak "Error parsing $_\n";
 		}
 	}
 	close $diff_fh or croak $!;
+
 	return \@mods;
 }
 
 sub svn_check_prop_executable {
 	my $m = shift;
-	if ($m->{mode_b} =~ /755$/ && $m->{mode_a} !~ /755$/) {
-		sys(qw(svn propset svn:executable 1), $m->{file_b});
+	return if -l $m->{file_b};
+	if ($m->{mode_b} =~ /755$/) {
+		chmod((0755 &~ umask),$m->{file_b}) or croak $!;
+		if ($m->{mode_a} !~ /755$/) {
+			sys(qw(svn propset svn:executable 1), $m->{file_b});
+		}
+		-x $m->{file_b} or croak "$m->{file_b} is not executable!\n";
 	} elsif ($m->{mode_b} !~ /755$/ && $m->{mode_a} =~ /755$/) {
 		sys(qw(svn propdel svn:executable), $m->{file_b});
+		chmod((0644 &~ umask),$m->{file_b}) or croak $!;
+		-x $m->{file_b} and croak "$m->{file_b} is executable!\n";
 	}
 }
 
@@ -349,84 +390,166 @@ sub svn_ensure_parent_path {
 	sys(qw(svn add -N), $dir_b) unless (-d "$dir_b/.svn");
 }
 
+sub precommit_check {
+	my $mods = shift;
+	my (%rm_file, %rmdir_check, %added_check);
+
+	my %o = ( D => 0, R => 1, C => 2, A => 3, M => 3, T => 3 );
+	foreach my $m (sort { $o{$a->{chg}} <=> $o{$b->{chg}} } @$mods) {
+		if ($m->{chg} eq 'R') {
+			if (-d $m->{file_b}) {
+				err_dir_to_file("$m->{file_a} => $m->{file_b}");
+			}
+			# dir/$file => dir/file/$file
+			my $dirname = dirname($m->{file_b});
+			while ($dirname ne File::Spec->curdir) {
+				if ($dirname ne $m->{file_a}) {
+					$dirname = dirname($dirname);
+					next;
+				}
+				err_file_to_dir("$m->{file_a} => $m->{file_b}");
+			}
+			# baz/zzz => baz (baz is a file)
+			$dirname = dirname($m->{file_a});
+			while ($dirname ne File::Spec->curdir) {
+				if ($dirname ne $m->{file_b}) {
+					$dirname = dirname($dirname);
+					next;
+				}
+				err_dir_to_file("$m->{file_a} => $m->{file_b}");
+			}
+		}
+		if ($m->{chg} =~ /^(D|R)$/) {
+			my $t = $1 eq 'D' ? 'file_b' : 'file_a';
+			$rm_file{ $m->{$t} } = 1;
+			my $dirname = dirname( $m->{$t} );
+			my $basename = basename( $m->{$t} );
+			$rmdir_check{$dirname}->{$basename} = 1;
+		} elsif ($m->{chg} =~ /^(?:A|C)$/) {
+			if (-d $m->{file_b}) {
+				err_dir_to_file($m->{file_b});
+			}
+			my $dirname = dirname( $m->{file_b} );
+			my $basename = basename( $m->{file_b} );
+			$added_check{$dirname}->{$basename} = 1;
+			while ($dirname ne File::Spec->curdir) {
+				if ($rm_file{$dirname}) {
+					err_file_to_dir($m->{file_b});
+				}
+				$dirname = dirname $dirname;
+			}
+		}
+	}
+	return (\%rmdir_check, \%added_check);
+
+	sub err_dir_to_file {
+		my $file = shift;
+		print STDERR "Node change from directory to file ",
+				"is not supported by Subversion: ",$file,"\n";
+		exit 1;
+	}
+	sub err_file_to_dir {
+		my $file = shift;
+		print STDERR "Node change from file to directory ",
+				"is not supported by Subversion: ",$file,"\n";
+		exit 1;
+	}
+}
+
 sub svn_checkout_tree {
-	my ($svn_rev, $commit) = @_;
+	my ($svn_rev, $treeish) = @_;
 	my $from = file_to_s("$REV_DIR/$svn_rev");
 	assert_svn_wc_clean($svn_rev,$from);
-	print "diff-tree '$from' '$commit'\n";
+	print "diff-tree '$from' '$treeish'\n";
 	my $pid = open my $diff_fh, '-|';
 	defined $pid or croak $!;
 	if ($pid == 0) {
 		my @diff_tree = qw(git-diff-tree -z -r -C);
 		push @diff_tree, '--find-copies-harder' if $_find_copies_harder;
 		push @diff_tree, "-l$_l" if defined $_l;
-		exec(@diff_tree, $from, $commit) or croak $!;
+		exec(@diff_tree, $from, $treeish) or croak $!;
 	}
 	my $mods = parse_diff_tree($diff_fh);
 	unless (@$mods) {
 		# git can do empty commits, SVN doesn't allow it...
-		return $svn_rev;
+		return $mods;
 	}
-	my %rm;
-	foreach my $m (@$mods) {
+	my ($rm, $add) = precommit_check($mods);
+
+	my %o = ( D => 1, R => 0, C => -1, A => 3, M => 3, T => 3 );
+	foreach my $m (sort { $o{$a->{chg}} <=> $o{$b->{chg}} } @$mods) {
 		if ($m->{chg} eq 'C') {
 			svn_ensure_parent_path( $m->{file_b} );
 			sys(qw(svn cp),		$m->{file_a}, $m->{file_b});
-			blob_to_file(		$m->{sha1_b}, $m->{file_b});
+			apply_mod_line_blob($m);
 			svn_check_prop_executable($m);
 		} elsif ($m->{chg} eq 'D') {
-			$rm{dirname $m->{file_b}}->{basename $m->{file_b}} = 1;
 			sys(qw(svn rm --force), $m->{file_b});
 		} elsif ($m->{chg} eq 'R') {
 			svn_ensure_parent_path( $m->{file_b} );
 			sys(qw(svn mv --force), $m->{file_a}, $m->{file_b});
-			blob_to_file(		$m->{sha1_b}, $m->{file_b});
+			apply_mod_line_blob($m);
 			svn_check_prop_executable($m);
-			$rm{dirname $m->{file_a}}->{basename $m->{file_a}} = 1;
 		} elsif ($m->{chg} eq 'M') {
-			if ($m->{mode_b} =~ /^120/ && $m->{mode_a} =~ /^120/) {
-				unlink $m->{file_b} or croak $!;
-				blob_to_symlink($m->{sha1_b}, $m->{file_b});
-			} else {
-				blob_to_file($m->{sha1_b}, $m->{file_b});
-			}
+			apply_mod_line_blob($m);
 			svn_check_prop_executable($m);
 		} elsif ($m->{chg} eq 'T') {
 			sys(qw(svn rm --force),$m->{file_b});
-			if ($m->{mode_b} =~ /^120/ && $m->{mode_a} =~ /^100/) {
-				blob_to_symlink($m->{sha1_b}, $m->{file_b});
-			} else {
-				blob_to_file($m->{sha1_b}, $m->{file_b});
-			}
-			svn_check_prop_executable($m);
+			apply_mod_line_blob($m);
 			sys(qw(svn add --force), $m->{file_b});
+			svn_check_prop_executable($m);
 		} elsif ($m->{chg} eq 'A') {
 			svn_ensure_parent_path( $m->{file_b} );
-			blob_to_file(		$m->{sha1_b}, $m->{file_b});
-			if ($m->{mode_b} =~ /755$/) {
-				chmod 0755, $m->{file_b};
-			}
+			apply_mod_line_blob($m);
 			sys(qw(svn add --force), $m->{file_b});
+			svn_check_prop_executable($m);
 		} else {
 			croak "Invalid chg: $m->{chg}\n";
 		}
 	}
-	if ($_rmdir) {
-		my $old_index = $ENV{GIT_INDEX_FILE};
-		$ENV{GIT_INDEX_FILE} = $GIT_SVN_INDEX;
-		foreach my $dir (keys %rm) {
-			my $files = $rm{$dir};
-			my @files;
-			foreach (safe_qx('svn','ls',$dir)) {
-				chomp;
-				push @files, $_ unless $files->{$_};
-			}
-			sys(qw(svn rm),$dir) unless @files;
-		}
-		if ($old_index) {
-			$ENV{GIT_INDEX_FILE} = $old_index;
-		} else {
-			delete $ENV{GIT_INDEX_FILE};
+
+	assert_tree($treeish);
+	if ($_rmdir) { # remove empty directories
+		handle_rmdir($rm, $add);
+	}
+	assert_tree($treeish);
+	return $mods;
+}
+
+# svn ls doesn't work with respect to the current working tree, but what's
+# in the repository.  There's not even an option for it... *sigh*
+# (added files don't show up and removed files remain in the ls listing)
+sub svn_ls_current {
+	my ($dir, $rm, $add) = @_;
+	chomp(my @ls = safe_qx('svn','ls',$dir));
+	my @ret = ();
+	foreach (@ls) {
+		s#/$##; # trailing slashes are evil
+		push @ret, $_ unless $rm->{$dir}->{$_};
+	}
+	if (exists $add->{$dir}) {
+		push @ret, keys %{$add->{$dir}};
+	}
+	return \@ret;
+}
+
+sub handle_rmdir {
+	my ($rm, $add) = @_;
+
+	foreach my $dir (sort {length $b <=> length $a} keys %$rm) {
+		my $ls = svn_ls_current($dir, $rm, $add);
+		next if (scalar @$ls);
+		sys(qw(svn rm --force),$dir);
+
+		my $dn = dirname $dir;
+		$rm->{ $dn }->{ basename $dir } = 1;
+		$ls = svn_ls_current($dn, $rm, $add);
+		while (scalar @$ls == 0 && $dn ne File::Spec->curdir) {
+			sys(qw(svn rm --force),$dn);
+			$dir = basename $dn;
+			$dn = dirname $dn;
+			$rm->{ $dn }->{ $dir } = 1;
+			$ls = svn_ls_current($dn, $rm, $add);
 		}
 	}
 }
@@ -692,10 +815,23 @@ sub git_commit {
 	return $commit;
 }
 
+sub apply_mod_line_blob {
+	my $m = shift;
+	if ($m->{mode_b} =~ /^120/) {
+		blob_to_symlink($m->{sha1_b}, $m->{file_b});
+	} else {
+		blob_to_file($m->{sha1_b}, $m->{file_b});
+	}
+}
+
 sub blob_to_symlink {
 	my ($blob, $link) = @_;
 	defined $link or croak "\$link not defined!\n";
 	croak "Not a sha1: $blob\n" unless $blob =~ /^$sha1$/o;
+	if (-l $link || -f _) {
+		unlink $link or croak $!;
+	}
+
 	my $dest = `git-cat-file blob $blob`; # no newline, so no chomp
 	symlink $dest, $link or croak $!;
 }
@@ -704,6 +840,10 @@ sub blob_to_file {
 	my ($blob, $file) = @_;
 	defined $file or croak "\$file not defined!\n";
 	croak "Not a sha1: $blob\n" unless $blob =~ /^$sha1$/o;
+	if (-l $file || -f _) {
+		unlink $file or croak $!;
+	}
+
 	open my $blob_fh, '>', $file or croak "$!: $file\n";
 	my $pid = fork;
 	defined $pid or croak $!;
-- 
1.2.0.gdee6

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 4/9] git-svn: remove any need for the XML::Simple dependency
  2006-02-20 18:57     ` [PATCH 3/9] git-svn: Allow for more argument types for commit (from..to) Eric Wong
@ 2006-02-20 18:57       ` Eric Wong
  2006-02-20 18:57         ` [PATCH 5/9] git-svn: change ; to && in addremove() Eric Wong
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Wong @ 2006-02-20 18:57 UTC (permalink / raw)
  To: git; +Cc: junkio, Eric Wong

XML::Simple was originally required back when I made svn-arch-mirror
because I needed to explictly track renames with Arch.  Then I carried
it over to git-svn because I was afraid somebody could commit an svn
log message that could throw off a non-XML log parser.  Then I noticed
the <n> lines column in the header.  So, no more XML :)

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 contrib/git-svn/git-svn |   84 ++++++++++++++++++++---------------------------
 1 files changed, 35 insertions(+), 49 deletions(-)

9b380ed2f8f1b18f95d12b86cb760f95e6e0cefe
diff --git a/contrib/git-svn/git-svn b/contrib/git-svn/git-svn
index 5f23d6b..4391bc3 100755
--- a/contrib/git-svn/git-svn
+++ b/contrib/git-svn/git-svn
@@ -21,7 +21,7 @@ $ENV{LC_ALL} = 'C';
 
 # If SVN:: library support is added, please make the dependencies
 # optional and preserve the capability to use the command-line client.
-# See what I do with XML::Simple to make the dependency optional.
+# use eval { require SVN::... } to make it lazy load
 use Carp qw/croak/;
 use IO::File qw//;
 use File::Basename qw/dirname basename/;
@@ -177,8 +177,7 @@ sub fetch {
 	push @log_args, "-r$_revision";
 	push @log_args, '--stop-on-copy' unless $_no_stop_copy;
 
-	eval { require XML::Simple or croak $! };
-	my $svn_log = $@ ? svn_log_raw(@log_args) : svn_log_xml(@log_args);
+	my $svn_log = svn_log_raw(@log_args);
 	@$svn_log = sort { $a->{revision} <=> $b->{revision} } @$svn_log;
 
 	my $base = shift @$svn_log or croak "No base revision!\n";
@@ -476,49 +475,6 @@ sub svn_commit_tree {
 	return fetch("$rev_committed=$commit")->{revision};
 }
 
-sub svn_log_xml {
-	my (@log_args) = @_;
-	my $log_fh = IO::File->new_tmpfile or croak $!;
-
-	my $pid = fork;
-	defined $pid or croak $!;
-
-	if ($pid == 0) {
-		open STDOUT, '>&', $log_fh or croak $!;
-		exec (qw(svn log --xml), @log_args) or croak $!
-	}
-
-	waitpid $pid, 0;
-	croak $? if $?;
-
-	seek $log_fh, 0, 0;
-	my @svn_log;
-	my $log = XML::Simple::XMLin( $log_fh,
-				ForceArray => ['path','revision','logentry'],
-				KeepRoot => 0,
-				KeyAttr => {	logentry => '+revision',
-						paths => '+path' },
-			)->{logentry};
-	foreach my $r (sort {$a <=> $b} keys %$log) {
-		my $log_msg = $log->{$r};
-		my ($Y,$m,$d,$H,$M,$S) = ($log_msg->{date} =~
-					/(\d{4})\-(\d\d)\-(\d\d)T
-					 (\d\d)\:(\d\d)\:(\d\d)\.\d+Z$/x)
-					 or croak "Failed to parse date: ",
-						 $log->{$r}->{date};
-		$log_msg->{date} = "+0000 $Y-$m-$d $H:$M:$S";
-
-		# XML::Simple can't handle <msg></msg> as a string:
-		if (ref $log_msg->{msg} eq 'HASH') {
-			$log_msg->{msg} = "\n";
-		} else {
-			$log_msg->{msg} .= "\n";
-		}
-		push @svn_log, $log->{$r};
-	}
-	return \@svn_log;
-}
-
 sub svn_log_raw {
 	my (@log_args) = @_;
 	my $pid = open my $log_fh,'-|';
@@ -529,21 +485,42 @@ sub svn_log_raw {
 	}
 
 	my @svn_log;
-	my $state;
+	my $state = 'sep';
 	while (<$log_fh>) {
 		chomp;
 		if (/^\-{72}$/) {
+			if ($state eq 'msg') {
+				if ($svn_log[$#svn_log]->{lines}) {
+					$svn_log[$#svn_log]->{msg} .= $_."\n";
+					unless(--$svn_log[$#svn_log]->{lines}) {
+						$state = 'sep';
+					}
+				} else {
+					croak "Log parse error at: $_\n",
+						$svn_log[$#svn_log]->{revision},
+						"\n";
+				}
+				next;
+			}
+			if ($state ne 'sep') {
+				croak "Log parse error at: $_\n",
+					"state: $state\n",
+					$svn_log[$#svn_log]->{revision},
+					"\n";
+			}
 			$state = 'rev';
 
 			# if we have an empty log message, put something there:
 			if (@svn_log) {
 				$svn_log[$#svn_log]->{msg} ||= "\n";
+				delete $svn_log[$#svn_log]->{lines};
 			}
 			next;
 		}
 		if ($state eq 'rev' && s/^r(\d+)\s*\|\s*//) {
 			my $rev = $1;
-			my ($author, $date) = split(/\s*\|\s*/, $_, 2);
+			my ($author, $date, $lines) = split(/\s*\|\s*/, $_, 3);
+			($lines) = ($lines =~ /(\d+)/);
 			my ($Y,$m,$d,$H,$M,$S,$tz) = ($date =~
 					/(\d{4})\-(\d\d)\-(\d\d)\s
 					 (\d\d)\:(\d\d)\:(\d\d)\s([\-\+]\d+)/x)
@@ -551,6 +528,7 @@ sub svn_log_raw {
 			my %log_msg = (	revision => $rev,
 					date => "$tz $Y-$m-$d $H:$M:$S",
 					author => $author,
+					lines => $lines,
 					msg => '' );
 			push @svn_log, \%log_msg;
 			$state = 'msg_start';
@@ -560,7 +538,15 @@ sub svn_log_raw {
 		if ($state eq 'msg_start' && /^$/) {
 			$state = 'msg';
 		} elsif ($state eq 'msg') {
-			$svn_log[$#svn_log]->{msg} .= $_."\n";
+			if ($svn_log[$#svn_log]->{lines}) {
+				$svn_log[$#svn_log]->{msg} .= $_."\n";
+				unless (--$svn_log[$#svn_log]->{lines}) {
+					$state = 'sep';
+				}
+			} else {
+				croak "Log parse error at: $_\n",
+					$svn_log[$#svn_log]->{revision},"\n";
+			}
 		}
 	}
 	close $log_fh or croak $?;
-- 
1.2.0.gdee6

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 9/9] git-svn: 0.9.1: add --version and copyright/license (GPL v2+) information
  2006-02-20 18:57               ` [PATCH 8/9] contrib/git-svn: add Makefile, test, and associated ignores Eric Wong
@ 2006-02-20 18:57                 ` Eric Wong
  0 siblings, 0 replies; 10+ messages in thread
From: Eric Wong @ 2006-02-20 18:57 UTC (permalink / raw)
  To: git; +Cc: junkio, Eric Wong

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 contrib/git-svn/git-svn.perl |   13 +++++++++++--
 1 files changed, 11 insertions(+), 2 deletions(-)

372473c658e9f48323430af003f8a1a887989edf
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index 3a59454..a32ce15 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -1,4 +1,6 @@
 #!/usr/bin/env perl
+# Copyright (C) 2006, Eric Wong <normalperson@yhbt.net>
+# License: GPL v2 or later
 use warnings;
 use strict;
 use vars qw/	$AUTHOR $VERSION
@@ -6,7 +8,7 @@ use vars qw/	$AUTHOR $VERSION
 		$GIT_SVN_INDEX $GIT_SVN
 		$GIT_DIR $REV_DIR/;
 $AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
-$VERSION = '0.9.0';
+$VERSION = '0.9.1';
 $GIT_DIR = $ENV{GIT_DIR} || "$ENV{PWD}/.git";
 $GIT_SVN = $ENV{GIT_SVN_ID} || 'git-svn';
 $GIT_SVN_INDEX = "$GIT_DIR/$GIT_SVN/index";
@@ -31,7 +33,7 @@ use File::Spec qw//;
 my $sha1 = qr/[a-f\d]{40}/;
 my $sha1_short = qr/[a-f\d]{6,40}/;
 my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit,
-	$_find_copies_harder, $_l);
+	$_find_copies_harder, $_l, $_version);
 
 GetOptions(	'revision|r=s' => \$_revision,
 		'no-ignore-externals' => \$_no_ignore_ext,
@@ -41,6 +43,7 @@ GetOptions(	'revision|r=s' => \$_revisio
 		'help|H|h' => \$_help,
 		'find-copies-harder' => \$_find_copies_harder,
 		'l=i' => \$_l,
+		'version|V' => \$_version,
 		'no-stop-on-copy' => \$_no_stop_copy );
 my %cmd = (
 	fetch => [ \&fetch, "Download new revisions from SVN" ],
@@ -66,6 +69,7 @@ foreach (keys %cmd) {
 	}
 }
 usage(0) if $_help;
+version() if $_version;
 usage(1) unless (defined $cmd);
 svn_check_ignore_externals();
 $cmd{$cmd}->[0]->(@ARGV);
@@ -91,6 +95,11 @@ and want to keep them separate.
 	exit $exit;
 }
 
+sub version {
+	print "git-svn version $VERSION\n";
+	exit 0;
+}
+
 sub rebuild {
 	$SVN_URL = shift or undef;
 	my $repo_uuid;
-- 
1.2.0.gdee6

^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH 8/9] contrib/git-svn: add Makefile, test, and associated ignores
  2006-02-20 18:57             ` [PATCH 7/9] git-svn: fix several corner-case and rare bugs with 'commit' Eric Wong
@ 2006-02-20 18:57               ` Eric Wong
  2006-02-20 18:57                 ` [PATCH 9/9] git-svn: 0.9.1: add --version and copyright/license (GPL v2+) information Eric Wong
  0 siblings, 1 reply; 10+ messages in thread
From: Eric Wong @ 2006-02-20 18:57 UTC (permalink / raw)
  To: git; +Cc: junkio, Eric Wong

Signed-off-by: Eric Wong <normalperson@yhbt.net>

---

 contrib/git-svn/.gitignore                 |    4 +
 contrib/git-svn/Makefile                   |   32 ++++
 contrib/git-svn/git-svn.perl               |    0 
 contrib/git-svn/t/t0000-contrib-git-svn.sh |  216 ++++++++++++++++++++++++++++
 4 files changed, 252 insertions(+), 0 deletions(-)
 create mode 100644 contrib/git-svn/.gitignore
 create mode 100644 contrib/git-svn/Makefile
 rename contrib/git-svn/{git-svn => git-svn.perl} (100%)
 create mode 100644 contrib/git-svn/t/t0000-contrib-git-svn.sh

1f5de0dcbe26fedb3236c437808d2cb20ab282c1
diff --git a/contrib/git-svn/.gitignore b/contrib/git-svn/.gitignore
new file mode 100644
index 0000000..d8d87e3
--- /dev/null
+++ b/contrib/git-svn/.gitignore
@@ -0,0 +1,4 @@
+git-svn
+git-svn.xml
+git-svn.html
+git-svn.1
diff --git a/contrib/git-svn/Makefile b/contrib/git-svn/Makefile
new file mode 100644
index 0000000..a330c61
--- /dev/null
+++ b/contrib/git-svn/Makefile
@@ -0,0 +1,32 @@
+all: git-svn
+
+prefix?=$(HOME)
+bindir=$(prefix)/bin
+mandir=$(prefix)/man
+man1=$(mandir)/man1
+INSTALL?=install
+doc_conf=../../Documentation/asciidoc.conf
+-include ../../config.mak
+
+git-svn: git-svn.perl
+	cp $< $@
+	chmod +x $@
+
+install: all
+	$(INSTALL) -d -m755 $(DESTDIR)$(bindir)
+	$(INSTALL) git-svn $(DESTDIR)$(bindir)
+
+install-doc: doc
+	$(INSTALL) git-svn.1 $(DESTDIR)$(man1)
+
+doc: git-svn.1
+git-svn.1 : git-svn.xml
+	xmlto man git-svn.xml
+git-svn.xml : git-svn.txt
+	asciidoc -b docbook -d manpage \
+		-f ../../Documentation/asciidoc.conf $<
+test:
+	cd t && $(SHELL) ./t0000-contrib-git-svn.sh
+
+clean:
+	rm -f git-svn *.xml *.html *.1
diff --git a/contrib/git-svn/git-svn b/contrib/git-svn/git-svn.perl
similarity index 100%
rename from contrib/git-svn/git-svn
rename to contrib/git-svn/git-svn.perl
diff --git a/contrib/git-svn/t/t0000-contrib-git-svn.sh b/contrib/git-svn/t/t0000-contrib-git-svn.sh
new file mode 100644
index 0000000..181dfe0
--- /dev/null
+++ b/contrib/git-svn/t/t0000-contrib-git-svn.sh
@@ -0,0 +1,216 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Eric Wong
+#
+
+
+PATH=$PWD/../:$PATH
+test_description='git-svn tests'
+if test -d ../../../t
+then
+    cd ../../../t
+else
+    echo "Must be run in contrib/git-svn/t" >&2
+    exit 1
+fi
+
+. ./test-lib.sh
+
+GIT_DIR=$PWD/.git
+GIT_SVN_DIR=$GIT_DIR/git-svn
+SVN_TREE=$GIT_SVN_DIR/tree
+
+svnadmin >/dev/null 2>&1
+if test $? != 1
+then
+    test_expect_success 'skipping contrib/git-svn test' :
+    test_done
+    exit
+fi
+
+svn >/dev/null 2>&1
+if test $? != 1
+then
+    test_expect_success 'skipping contrib/git-svn test' :
+    test_done
+    exit
+fi
+
+svnrepo=$PWD/svnrepo
+
+set -e
+
+svnadmin create $svnrepo
+svnrepo="file://$svnrepo/test-git-svn"
+
+mkdir import
+
+cd import
+
+echo foo > foo
+ln -s foo foo.link
+mkdir -p dir/a/b/c/d/e
+echo 'deep dir' > dir/a/b/c/d/e/file
+mkdir -p bar
+echo 'zzz' > bar/zzz
+echo '#!/bin/sh' > exec.sh
+chmod +x exec.sh
+svn import -m 'import for git-svn' . $svnrepo >/dev/null
+
+cd ..
+
+rm -rf import
+
+test_expect_success \
+    'initialize git-svn' \
+    "git-svn init $svnrepo"
+
+test_expect_success \
+    'import an SVN revision into git' \
+    'git-svn fetch'
+
+
+name='try a deep --rmdir with a commit'
+git checkout -b mybranch git-svn-HEAD
+mv dir/a/b/c/d/e/file dir/file
+cp dir/file file
+git update-index --add --remove dir/a/b/c/d/e/file dir/file file
+git commit -m "$name"
+
+test_expect_success "$name" \
+    "git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch &&
+     test -d $SVN_TREE/dir && test ! -d $SVN_TREE/dir/a"
+
+
+name='detect node change from file to directory #1'
+mkdir dir/new_file
+mv dir/file dir/new_file/file
+mv dir/new_file dir/file
+git update-index --remove dir/file
+git update-index --add dir/file/file
+git commit -m "$name"
+
+test_expect_code 1 "$name" \
+    'git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch' \
+    || true
+
+
+name='detect node change from directory to file #1'
+rm -rf dir $GIT_DIR/index
+git checkout -b mybranch2 git-svn-HEAD
+mv bar/zzz zzz
+rm -rf bar
+mv zzz bar
+git update-index --remove -- bar/zzz
+git update-index --add -- bar
+git commit -m "$name"
+
+test_expect_code 1 "$name" \
+    'git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch2' \
+    || true
+
+
+name='detect node change from file to directory #2'
+rm -f $GIT_DIR/index
+git checkout -b mybranch3 git-svn-HEAD
+rm bar/zzz
+git-update-index --remove bar/zzz
+mkdir bar/zzz
+echo yyy > bar/zzz/yyy
+git-update-index --add bar/zzz/yyy
+git commit -m "$name"
+
+test_expect_code 1 "$name" \
+    'git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch3' \
+    || true
+
+
+name='detect node change from directory to file #2'
+rm -f $GIT_DIR/index
+git checkout -b mybranch4 git-svn-HEAD
+rm -rf dir
+git update-index --remove -- dir/file
+touch dir
+echo asdf > dir
+git update-index --add -- dir
+git commit -m "$name"
+
+test_expect_code 1 "$name" \
+    'git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch4' \
+    || true
+
+
+name='remove executable bit from a file'
+rm -f $GIT_DIR/index
+git checkout -b mybranch5 git-svn-HEAD
+chmod -x exec.sh
+git update-index exec.sh
+git commit -m "$name"
+
+test_expect_success "$name" \
+    "git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch5 &&
+     test ! -x $SVN_TREE/exec.sh"
+
+
+name='add executable bit back file'
+chmod +x exec.sh
+git update-index exec.sh
+git commit -m "$name"
+
+test_expect_success "$name" \
+    "git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch5 &&
+     test -x $SVN_TREE/exec.sh"
+
+
+
+name='executable file becomes a symlink to bar/zzz (file)'
+rm exec.sh
+ln -s bar/zzz exec.sh
+git update-index exec.sh
+git commit -m "$name"
+
+test_expect_success "$name" \
+    "git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch5 &&
+     test -L $SVN_TREE/exec.sh"
+
+
+
+name='new symlink is added to a file that was also just made executable'
+chmod +x bar/zzz
+ln -s bar/zzz exec-2.sh
+git update-index --add bar/zzz exec-2.sh
+git commit -m "$name"
+
+test_expect_success "$name" \
+    "git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch5 &&
+     test -x $SVN_TREE/bar/zzz &&
+     test -L $SVN_TREE/exec-2.sh"
+
+
+
+name='modify a symlink to become a file'
+git help > help || true
+rm exec-2.sh
+cp help exec-2.sh
+git update-index exec-2.sh
+git commit -m "$name"
+
+test_expect_success "$name" \
+    "git-svn commit --find-copies-harder --rmdir git-svn-HEAD..mybranch5 &&
+     test -f $SVN_TREE/exec-2.sh &&
+     test ! -L $SVN_TREE/exec-2.sh &&
+     diff -u help $SVN_TREE/exec-2.sh"
+
+
+
+name='test fetch functionality (svn => git) with alternate GIT_SVN_ID'
+GIT_SVN_ID=alt
+export GIT_SVN_ID
+test_expect_success "$name" \
+    "git-svn init $svnrepo && git-svn fetch -v &&
+     git-rev-list --pretty=raw git-svn-HEAD | grep ^tree | uniq > a &&
+     git-rev-list --pretty=raw alt-HEAD | grep ^tree | uniq > b &&
+     diff -u a b"
+
+test_done
+
-- 
1.2.0.gdee6

^ permalink raw reply related	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2006-02-20 18:57 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-02-20 18:57 git-svn: nearing 1.0.0 Eric Wong
2006-02-20 18:57 ` [PATCH 1/9] git-svn: fix a typo in defining the --no-stop-on-copy option Eric Wong
2006-02-20 18:57   ` [PATCH 2/9] git-svn: allow --find-copies-harder and -l<num> to be passed on commit Eric Wong
2006-02-20 18:57     ` [PATCH 3/9] git-svn: Allow for more argument types for commit (from..to) Eric Wong
2006-02-20 18:57       ` [PATCH 4/9] git-svn: remove any need for the XML::Simple dependency Eric Wong
2006-02-20 18:57         ` [PATCH 5/9] git-svn: change ; to && in addremove() Eric Wong
2006-02-20 18:57           ` [PATCH 6/9] contrib/git-svn.txt: add a note about renamed/copied directory support Eric Wong
2006-02-20 18:57             ` [PATCH 7/9] git-svn: fix several corner-case and rare bugs with 'commit' Eric Wong
2006-02-20 18:57               ` [PATCH 8/9] contrib/git-svn: add Makefile, test, and associated ignores Eric Wong
2006-02-20 18:57                 ` [PATCH 9/9] git-svn: 0.9.1: add --version and copyright/license (GPL v2+) information Eric Wong

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 NNTP newsgroup(s).