git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
* git-svn vs. $Id$
@ 2006-05-16 17:33 Tommi Virtanen
  2006-05-16 17:48 ` Linus Torvalds
  2006-05-21  3:03 ` [PATCH] git-svn: ignore expansion of svn:keywords Eric Wong
  0 siblings, 2 replies; 8+ messages in thread
From: Tommi Virtanen @ 2006-05-16 17:33 UTC (permalink / raw
  To: git

Hi. I just ran into trouble with git-svn, related to a file
containing $Id$. Yes, I know $Id$ sucks and should be avoided,
and I'll be removing them shortly, but that doesn't change the
fact that the history contains files with them.

Just wanted to let you know of a workaround:
manually edit the relevant file in .git/git-svn/tree/ to
undo the $Id$ change, and git-svn fetch works again.

$ git-svn fetch
Tree mismatch, Got: c242bb60d78c1dfce133e0bbaca7f13895de00b2, Expected:
07d35ac911cc56aabea86f4467cafc1d92b724c4
 at /home/tv/bin/git-svn line 426
        main::assert_tree('a5890d459de08dc8adbbe34cdfb4b1f44f377ad8')
called at /home/tv/bin/git-svn line 392
        main::assert_svn_wc_clean(2039,
'a5890d459de08dc8adbbe34cdfb4b1f44f377ad8') called at
/home/tv/bin/git-svn line 262
        main::fetch() called at /home/tv/bin/git-svn line 105

$ git diff-tree -p 07d35ac911cc56aabea86f4467cafc1d92b724c4 \
  c242bb60d78c1dfce133e0bbaca7f13895de00b2
diff --git a/anonymized b/anonymized
index 16b3988..f43782a 100644
--- a/anonymized
+++ b/anonymized
@@ -1,4 +1,4 @@
-## $Id: anonymized 1775 2006-04-20 09:25:22Z tv $
+## $Id: anonymized 2025 2006-05-16 07:25:24Z tv $

 blah
 blah


So editing .git/git-svn/tree/anonymized and replacing
"1775 2006-04-20 09:25:22Z tv" with "2025 2006-05-16 07:25:24Z tv"
make git-svn happy again.

-- 
Inoi Oy, Tykistökatu 4 D (4. krs), FI-20520 Turku, Finland
http://www.inoi.fi/
Mobile +358 40 762 5656

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

* Re: git-svn vs. $Id$
  2006-05-16 17:33 git-svn vs. $Id$ Tommi Virtanen
@ 2006-05-16 17:48 ` Linus Torvalds
  2006-05-16 18:12   ` Tommi Virtanen
  2006-05-21  3:03 ` [PATCH] git-svn: ignore expansion of svn:keywords Eric Wong
  1 sibling, 1 reply; 8+ messages in thread
From: Linus Torvalds @ 2006-05-16 17:48 UTC (permalink / raw
  To: Tommi Virtanen; +Cc: git



On Tue, 16 May 2006, Tommi Virtanen wrote:
> 
> Just wanted to let you know of a workaround:
> manually edit the relevant file in .git/git-svn/tree/ to
> undo the $Id$ change, and git-svn fetch works again.

Isn't there some flag to svn to avoid keyword expansion, like "-ko" to 
CVS?

Any import script definitely should avoid keyword expansion (and that's 
true whether you end up wanting to use keywords or not).

(And yes, CVS is probably a bad example. Those "substitution modes" are 
confusing as hell, and I don't know which one is the right one. Is it 
"-ko" or "-kk"? Don't ask me, I'm CVS-illiterate. I don't know why the 
current cvsimport uses -kk, and only does it conditionally. Whatever.)

		Linus

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

* Re: git-svn vs. $Id$
  2006-05-16 17:48 ` Linus Torvalds
@ 2006-05-16 18:12   ` Tommi Virtanen
  2006-05-21  1:12     ` Eric Wong
  0 siblings, 1 reply; 8+ messages in thread
From: Tommi Virtanen @ 2006-05-16 18:12 UTC (permalink / raw
  To: Linus Torvalds; +Cc: git

Linus Torvalds wrote:
> Isn't there some flag to svn to avoid keyword expansion, like "-ko" to 
> CVS?
> 
> Any import script definitely should avoid keyword expansion (and that's 
> true whether you end up wanting to use keywords or not).

Well, yes, I agree. But, at least git-svn.txt says this:

BUGS
----
...
svn:keywords can't be ignored in Subversion (at least I don't know of
a way to ignore them).

I guess one might be able to reach that information through the svn API.

Or just propget svn:keywords and sed s/\$Id\(:[^$]*\)\$/$Id$/ all files
with keywords, for all relevant keywords. Eww.

-- 
Inoi Oy, Tykistökatu 4 D (4. krs), FI-20520 Turku, Finland
http://www.inoi.fi/
Mobile +358 40 762 5656

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

* Re: git-svn vs. $Id$
  2006-05-16 18:12   ` Tommi Virtanen
@ 2006-05-21  1:12     ` Eric Wong
  0 siblings, 0 replies; 8+ messages in thread
From: Eric Wong @ 2006-05-21  1:12 UTC (permalink / raw
  To: Tommi Virtanen; +Cc: Linus Torvalds, git

Tommi Virtanen <tv@inoi.fi> wrote:
> Linus Torvalds wrote:
> > Isn't there some flag to svn to avoid keyword expansion, like "-ko" to 
> > CVS?
> > 
> > Any import script definitely should avoid keyword expansion (and that's 
> > true whether you end up wanting to use keywords or not).
> 
> Well, yes, I agree. But, at least git-svn.txt says this:
> 
> BUGS
> ----
> ...
> svn:keywords can't be ignored in Subversion (at least I don't know of
> a way to ignore them).
> 
> I guess one might be able to reach that information through the svn API.
> 
> Or just propget svn:keywords and sed s/\$Id\(:[^$]*\)\$/$Id$/ all files
> with keywords, for all relevant keywords. Eww.

I'm working on a solution to this (using files in .svn/text-base).

keyword expansion behavior seems inconsistent on some SVN repos and I
can't reproduce it on my local repositories, so I think I will have to
weaken some integrity checks[1] in git-svn to work around it...

1 - I don't think these integrity checks were ever tripped in the first
place.

-- 
Eric Wong

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

* [PATCH] git-svn: ignore expansion of svn:keywords
  2006-05-16 17:33 git-svn vs. $Id$ Tommi Virtanen
  2006-05-16 17:48 ` Linus Torvalds
@ 2006-05-21  3:03 ` Eric Wong
  2006-05-24  2:23   ` git-svn vs. $Id$ Eric Wong
  1 sibling, 1 reply; 8+ messages in thread
From: Eric Wong @ 2006-05-21  3:03 UTC (permalink / raw
  To: Tommi Virtanen; +Cc: git

Can you try this patch?

This weakens an integrity in order to work on certain
repositories (see comments).  It's probably safe to use,
though...  More testing and feedback would be nice.

I've split out the test for this feature to make things easier
to manage and test, too.

Also changed assert_svn_wc_clean() to only work on svn, and
require a separate call to assert_tree() to check wc integrity
against git in preparation for another change I'm planning.

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

---

 @Junio: please don't apply this to git.git just yet, thanks.

 contrib/git-svn/Makefile                         |    1 
 contrib/git-svn/git-svn.perl                     |   79 +++++++++++++++++-----
 contrib/git-svn/t/lib-git-svn.sh                 |   39 +++++++++++
 contrib/git-svn/t/t0000-contrib-git-svn.sh       |   43 +-----------
 contrib/git-svn/t/t0001-contrib-git-svn-props.sh |   51 ++++++++++++++
 5 files changed, 153 insertions(+), 60 deletions(-)
 create mode 100644 contrib/git-svn/t/lib-git-svn.sh
 create mode 100644 contrib/git-svn/t/t0001-contrib-git-svn-props.sh

eb8f17257c7d15ec6815baf18208af06f72b3cdb
diff --git a/contrib/git-svn/Makefile b/contrib/git-svn/Makefile
index acedf73..48f60b3 100644
--- a/contrib/git-svn/Makefile
+++ b/contrib/git-svn/Makefile
@@ -30,6 +30,7 @@ git-svn.html : git-svn.txt
 		-f ../../Documentation/asciidoc.conf $<
 test: git-svn
 	cd t && $(SHELL) ./t0000-contrib-git-svn.sh
+	cd t && $(SHELL) ./t0001-contrib-git-svn-props.sh
 
 clean:
 	rm -f git-svn *.xml *.html *.1
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index de13a96..86b687a 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -26,6 +26,7 @@ use Carp qw/croak/;
 use IO::File qw//;
 use File::Basename qw/dirname basename/;
 use File::Path qw/mkpath/;
+use File::Copy qw/cp/;
 use Getopt::Long qw/:config gnu_getopt no_ignore_case auto_abbrev/;
 use File::Spec qw//;
 use POSIX qw/strftime/;
@@ -207,7 +208,7 @@ sub rebuild {
 		push @svn_up, '--ignore-externals' unless $_no_ignore_ext;
 		sys(@svn_up,"-r$newest_rev");
 		$ENV{GIT_INDEX_FILE} = $GIT_SVN_INDEX;
-		git_addremove();
+		index_changes();
 		exec('git-write-tree');
 	}
 	waitpid $pid, 0;
@@ -249,7 +250,7 @@ sub fetch {
 		chdir $SVN_WC or croak $!;
 		read_uuid();
 		$last_commit = git_commit($base, @parents);
-		assert_svn_wc_clean($base->{revision}, $last_commit);
+		assert_tree($last_commit);
 	} else {
 		chdir $SVN_WC or croak $!;
 		read_uuid();
@@ -259,7 +260,11 @@ sub fetch {
 	push @svn_up, '--ignore-externals' unless $_no_ignore_ext;
 	my $last = $base;
 	while (my $log_msg = next_log_entry($svn_log)) {
-		assert_svn_wc_clean($last->{revision}, $last_commit);
+		# this assertion is commented out because it breaks keywords
+		# on https://svn.musicpd.org/Jamming/trunk (r166:167), but
+		# I can't seem to reproduce something like that on a test...
+		# assert_svn_wc_clean($last->{revision});
+		assert_tree($last_commit);
 		if ($last->{revision} >= $log_msg->{revision}) {
 			croak "Out of order: last >= current: ",
 				"$last->{revision} >= $log_msg->{revision}\n";
@@ -268,7 +273,8 @@ sub fetch {
 		$last_commit = git_commit($log_msg, $last_commit, @parents);
 		$last = $log_msg;
 	}
-	assert_svn_wc_clean($last->{revision}, $last_commit);
+	assert_svn_wc_clean($last->{revision});
+	assert_tree($last_commit);
 	unless (-e "$GIT_DIR/refs/heads/master") {
 		sys(qw(git-update-ref refs/heads/master),$last_commit);
 	}
@@ -314,7 +320,6 @@ sub commit {
 		$svn_current_rev = svn_commit_tree($svn_current_rev, $c);
 	}
 	print "Done committing ",scalar @revs," revisions to SVN\n";
-
 }
 
 sub show_ignore {
@@ -367,13 +372,11 @@ sub setup_git_svn {
 }
 
 sub assert_svn_wc_clean {
-	my ($svn_rev, $treeish) = @_;
+	my ($svn_rev) = @_;
 	croak "$svn_rev is not an integer!\n" unless ($svn_rev =~ /^\d+$/);
-	croak "$treeish is not a sha1!\n" unless ($treeish =~ /^$sha1$/o);
 	my $lcr = svn_info('.')->{'Last Changed Rev'};
 	if ($svn_rev != $lcr) {
 		print STDERR "Checking for copy-tree ... ";
-		# use
 		my @diff = grep(/^Index: /,(safe_qx(qw(svn diff),
 						"-r$lcr:$svn_rev")));
 		if (@diff) {
@@ -389,7 +392,6 @@ sub assert_svn_wc_clean {
 		print STDERR $_ foreach @status;
 		croak;
 	}
-	assert_tree($treeish);
 }
 
 sub assert_tree {
@@ -416,7 +418,7 @@ sub assert_tree {
 		unlink $tmpindex or croak $!;
 	}
 	$ENV{GIT_INDEX_FILE} = $tmpindex;
-	git_addremove();
+	index_changes(1);
 	chomp(my $tree = `git-write-tree`);
 	if ($old_index) {
 		$ENV{GIT_INDEX_FILE} = $old_index;
@@ -426,6 +428,7 @@ sub assert_tree {
 	if ($tree ne $expected) {
 		croak "Tree mismatch, Got: $tree, Expected: $expected\n";
 	}
+	unlink $tmpindex;
 }
 
 sub parse_diff_tree {
@@ -562,7 +565,8 @@ sub precommit_check {
 sub svn_checkout_tree {
 	my ($svn_rev, $treeish) = @_;
 	my $from = file_to_s("$REV_DIR/$svn_rev");
-	assert_svn_wc_clean($svn_rev,$from);
+	assert_svn_wc_clean($svn_rev);
+	assert_tree($from);
 	print "diff-tree $from $treeish\n";
 	my $pid = open my $diff_fh, '-|';
 	defined $pid or croak $!;
@@ -852,13 +856,50 @@ sub svn_info {
 
 sub sys { system(@_) == 0 or croak $? }
 
-sub git_addremove {
-	system( "git-diff-files --name-only -z ".
-				" | 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"
-		) == 0 or croak $?
+sub do_update_index {
+	my ($z_cmd, $cmd, $no_text_base) = @_;
+
+	my $z = open my $p, '-|';
+	defined $z or croak $!;
+	unless ($z) { exec @$z_cmd or croak $! }
+
+	my $pid = open my $ui, '|-';
+	defined $pid or croak $!;
+	unless ($pid) {
+		exec('git-update-index',"--$cmd",'-z','--stdin') or croak $!;
+	}
+	local $/ = "\0";
+	while (my $x = <$p>) {
+		chomp $x;
+		if (!$no_text_base && lstat $x && ! -l _) {
+			my $mode = -x _ ? 0755 : 0644;
+			my ($v,$d,$f) = File::Spec->splitpath($x);
+			my $tb = File::Spec->catfile($d, '.svn', 'tmp',
+						'text-base',"$f.svn-base");
+			$tb =~ s#^/##;
+			unless (-f $tb) {
+				$tb = File::Spec->catfile($d, '.svn',
+						'text-base',"$f.svn-base");
+				$tb =~ s#^/##;
+			}
+			unlink $x or croak $!;
+			cp($tb, $x) or croak $!;
+			chmod(($mode &~ umask), $x) or croak $!;
+		}
+		print $ui $x,"\0";
+	}
+	close $ui or croak $!;
+}
+
+sub index_changes {
+	my $no_text_base = shift;
+	do_update_index([qw/git-diff-files --name-only -z/],
+			'remove',
+			$no_text_base);
+	do_update_index([qw/git-ls-files -z --others/,
+			      "--exclude-from=$GIT_DIR/$GIT_SVN/info/exclude"],
+			'add',
+			$no_text_base);
 }
 
 sub s_to_file {
@@ -936,7 +977,7 @@ sub git_commit {
 	defined $pid or croak $!;
 	if ($pid == 0) {
 		$ENV{GIT_INDEX_FILE} = $GIT_SVN_INDEX;
-		git_addremove();
+		index_changes();
 		chomp(my $tree = `git-write-tree`);
 		croak if $?;
 		if (exists $tree_map{$tree}) {
diff --git a/contrib/git-svn/t/lib-git-svn.sh b/contrib/git-svn/t/lib-git-svn.sh
new file mode 100644
index 0000000..a98e9d1
--- /dev/null
+++ b/contrib/git-svn/t/lib-git-svn.sh
@@ -0,0 +1,39 @@
+PATH=$PWD/../:$PATH
+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"
+
+
diff --git a/contrib/git-svn/t/t0000-contrib-git-svn.sh b/contrib/git-svn/t/t0000-contrib-git-svn.sh
index 80ad357..8b3a0d9 100644
--- a/contrib/git-svn/t/t0000-contrib-git-svn.sh
+++ b/contrib/git-svn/t/t0000-contrib-git-svn.sh
@@ -3,48 +3,10 @@ #
 # 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"
+. ./lib-git-svn.sh
 
 mkdir import
-
 cd import
 
 echo foo > foo
@@ -55,10 +17,9 @@ 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
+svn import -m 'import for git-svn' . "$svnrepo" >/dev/null
 
 cd ..
-
 rm -rf import
 
 test_expect_success \
diff --git a/contrib/git-svn/t/t0001-contrib-git-svn-props.sh b/contrib/git-svn/t/t0001-contrib-git-svn-props.sh
new file mode 100644
index 0000000..20c5c4e
--- /dev/null
+++ b/contrib/git-svn/t/t0001-contrib-git-svn-props.sh
@@ -0,0 +1,51 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Eric Wong
+#
+
+test_description='git-svn property tests'
+. ./lib-git-svn.sh
+
+mkdir import
+
+cd import
+	cat >> kw.c <<''
+/* Make it look like somebody copied a file from CVS into SVN: */
+/* $Id: kw.c,v 1.1.1.1 1994/03/06 00:00:00 eric Exp $ */
+
+	svn import -m 'import for git-svn' . "$svnrepo" >/dev/null
+cd ..
+
+rm -rf import
+svn co "$svnrepo" test_wc
+
+cd test_wc
+	echo 'Greetings' >> kw.c
+	svn commit -m 'Not yet an $Id$'
+	svn up
+
+	echo 'Hello world' >> kw.c
+	svn commit -m 'Modified file, but still not yet an $Id$'
+	svn up
+
+	svn propset svn:keywords Id kw.c
+	svn commit -m 'Propset $Id$'
+	svn up
+cd ..
+
+git-svn init "$svnrepo"
+git-svn fetch
+
+git checkout -b mybranch remotes/git-svn
+echo 'Hi again' >> kw.c
+name='test svn:keywords ignoring'
+
+git commit -a -m "$name"
+git-svn commit remotes/git-svn..mybranch
+git pull . remotes/git-svn
+
+expect='/* $Id$ */'
+got="`sed -ne 2p kw.c`"
+test_expect_success 'raw $Id$ found in kw.c' "test '$expect' = '$got'"
+
+test_done
-- 
1.3.2.g7d11

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

* Re: git-svn vs. $Id$
  2006-05-21  3:03 ` [PATCH] git-svn: ignore expansion of svn:keywords Eric Wong
@ 2006-05-24  2:23   ` Eric Wong
  2006-05-24  2:23     ` [PATCH] git-svn: starting a 1.1.0-pre development version Eric Wong
  0 siblings, 1 reply; 8+ messages in thread
From: Eric Wong @ 2006-05-24  2:23 UTC (permalink / raw
  To: Tommi Virtanen; +Cc: Junio C Hamano, git

Tommi: I'm reasonably confident about this patch, but I won't be
getting much real-world usage since I rarely see repos that use
svn:keywords, and I'm afflicted with RSI which prevents me from
doing very much in front of a computer these days.  So
feedback/testing from you or any other git-svn guine^Wusers
would be greatly appreciated.

Junio: This is probably safe enough for next or even master, the
one in pu is completely broken wrt svn:eol-style.

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

* [PATCH] git-svn: starting a 1.1.0-pre development version
  2006-05-24  2:23   ` git-svn vs. $Id$ Eric Wong
@ 2006-05-24  2:23     ` Eric Wong
  2006-05-24  2:23       ` [PATCH] git-svn: ignore expansion of svn:keywords Eric Wong
  0 siblings, 1 reply; 8+ messages in thread
From: Eric Wong @ 2006-05-24  2:23 UTC (permalink / raw
  To: Tommi Virtanen; +Cc: Junio C Hamano, git, Eric Wong

Some not-very-well-tested changes coming...

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

---

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

49967a4b7bc2c9938b0ebf0670cd47d4ccfe85a3
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index de13a96..39471b5 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -8,7 +8,7 @@ use vars qw/	$AUTHOR $VERSION
 		$GIT_SVN_INDEX $GIT_SVN
 		$GIT_DIR $REV_DIR/;
 $AUTHOR = 'Eric Wong <normalperson@yhbt.net>';
-$VERSION = '1.0.0';
+$VERSION = '1.1.0-pre';
 
 use Cwd qw/abs_path/;
 $GIT_DIR = abs_path($ENV{GIT_DIR} || '.git');
-- 
1.3.2.g7d11

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

* [PATCH] git-svn: ignore expansion of svn:keywords
  2006-05-24  2:23     ` [PATCH] git-svn: starting a 1.1.0-pre development version Eric Wong
@ 2006-05-24  2:23       ` Eric Wong
  0 siblings, 0 replies; 8+ messages in thread
From: Eric Wong @ 2006-05-24  2:23 UTC (permalink / raw
  To: Tommi Virtanen; +Cc: Junio C Hamano, git, Eric Wong

Unlike my earlier test patch, this also checks svn:eol-style and
makes sure it's applied to working copy updates.  This is
definitely more correct than my original attempt at killing
keyword expansions, but I still haven't tested it enough to
know.  Feedback would be much appreciated.

Also changed assert_svn_wc_clean() to only work on the svn
working copy.  This requires a separate call to assert_tree() to
check wc integrity against git in preparation for another change
I'm planning.

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

---

 contrib/git-svn/Makefile                         |    1 
 contrib/git-svn/git-svn.perl                     |  106 +++++++++++++++----
 contrib/git-svn/t/lib-git-svn.sh                 |   39 +++++++
 contrib/git-svn/t/t0000-contrib-git-svn.sh       |   43 --------
 contrib/git-svn/t/t0001-contrib-git-svn-props.sh |  125 ++++++++++++++++++++++
 5 files changed, 254 insertions(+), 60 deletions(-)
 create mode 100644 contrib/git-svn/t/lib-git-svn.sh
 create mode 100644 contrib/git-svn/t/t0001-contrib-git-svn-props.sh

b9ba79157fc4f92e14aac89d9a5f838539d6eede
diff --git a/contrib/git-svn/Makefile b/contrib/git-svn/Makefile
index acedf73..48f60b3 100644
--- a/contrib/git-svn/Makefile
+++ b/contrib/git-svn/Makefile
@@ -30,6 +30,7 @@ git-svn.html : git-svn.txt
 		-f ../../Documentation/asciidoc.conf $<
 test: git-svn
 	cd t && $(SHELL) ./t0000-contrib-git-svn.sh
+	cd t && $(SHELL) ./t0001-contrib-git-svn-props.sh
 
 clean:
 	rm -f git-svn *.xml *.html *.1
diff --git a/contrib/git-svn/git-svn.perl b/contrib/git-svn/git-svn.perl
index 39471b5..fc9b7ef 100755
--- a/contrib/git-svn/git-svn.perl
+++ b/contrib/git-svn/git-svn.perl
@@ -39,6 +39,10 @@ my $_svn_co_url_revs;
 my %fc_opts = ( 'no-ignore-externals' => \$_no_ignore_ext,
 		'branch|b=s' => \@_branch_from,
 		'authors-file|A=s' => \$_authors );
+
+# yes, 'native' sets "\n".  Patches to fix this for non-*nix systems welcome:
+my %EOL = ( CR => "\015", LF => "\012", CRLF => "\015\012", native => "\012" );
+
 my %cmd = (
 	fetch => [ \&fetch, "Download new revisions from SVN",
 			{ 'revision|r=s' => \$_revision, %fc_opts } ],
@@ -207,7 +211,7 @@ sub rebuild {
 		push @svn_up, '--ignore-externals' unless $_no_ignore_ext;
 		sys(@svn_up,"-r$newest_rev");
 		$ENV{GIT_INDEX_FILE} = $GIT_SVN_INDEX;
-		git_addremove();
+		index_changes();
 		exec('git-write-tree');
 	}
 	waitpid $pid, 0;
@@ -249,7 +253,7 @@ sub fetch {
 		chdir $SVN_WC or croak $!;
 		read_uuid();
 		$last_commit = git_commit($base, @parents);
-		assert_svn_wc_clean($base->{revision}, $last_commit);
+		assert_tree($last_commit);
 	} else {
 		chdir $SVN_WC or croak $!;
 		read_uuid();
@@ -259,16 +263,20 @@ sub fetch {
 	push @svn_up, '--ignore-externals' unless $_no_ignore_ext;
 	my $last = $base;
 	while (my $log_msg = next_log_entry($svn_log)) {
-		assert_svn_wc_clean($last->{revision}, $last_commit);
+		assert_tree($last_commit);
 		if ($last->{revision} >= $log_msg->{revision}) {
 			croak "Out of order: last >= current: ",
 				"$last->{revision} >= $log_msg->{revision}\n";
 		}
+		# Revert is needed for cases like:
+		# https://svn.musicpd.org/Jamming/trunk (r166:167), but
+		# I can't seem to reproduce something like that on a test...
+		sys(qw/svn revert -R ./);
+		assert_svn_wc_clean($last->{revision});
 		sys(@svn_up,"-r$log_msg->{revision}");
 		$last_commit = git_commit($log_msg, $last_commit, @parents);
 		$last = $log_msg;
 	}
-	assert_svn_wc_clean($last->{revision}, $last_commit);
 	unless (-e "$GIT_DIR/refs/heads/master") {
 		sys(qw(git-update-ref refs/heads/master),$last_commit);
 	}
@@ -314,7 +322,6 @@ sub commit {
 		$svn_current_rev = svn_commit_tree($svn_current_rev, $c);
 	}
 	print "Done committing ",scalar @revs," revisions to SVN\n";
-
 }
 
 sub show_ignore {
@@ -367,13 +374,11 @@ sub setup_git_svn {
 }
 
 sub assert_svn_wc_clean {
-	my ($svn_rev, $treeish) = @_;
+	my ($svn_rev) = @_;
 	croak "$svn_rev is not an integer!\n" unless ($svn_rev =~ /^\d+$/);
-	croak "$treeish is not a sha1!\n" unless ($treeish =~ /^$sha1$/o);
 	my $lcr = svn_info('.')->{'Last Changed Rev'};
 	if ($svn_rev != $lcr) {
 		print STDERR "Checking for copy-tree ... ";
-		# use
 		my @diff = grep(/^Index: /,(safe_qx(qw(svn diff),
 						"-r$lcr:$svn_rev")));
 		if (@diff) {
@@ -389,7 +394,6 @@ sub assert_svn_wc_clean {
 		print STDERR $_ foreach @status;
 		croak;
 	}
-	assert_tree($treeish);
 }
 
 sub assert_tree {
@@ -416,7 +420,7 @@ sub assert_tree {
 		unlink $tmpindex or croak $!;
 	}
 	$ENV{GIT_INDEX_FILE} = $tmpindex;
-	git_addremove();
+	index_changes(1);
 	chomp(my $tree = `git-write-tree`);
 	if ($old_index) {
 		$ENV{GIT_INDEX_FILE} = $old_index;
@@ -426,6 +430,7 @@ sub assert_tree {
 	if ($tree ne $expected) {
 		croak "Tree mismatch, Got: $tree, Expected: $expected\n";
 	}
+	unlink $tmpindex;
 }
 
 sub parse_diff_tree {
@@ -562,7 +567,8 @@ sub precommit_check {
 sub svn_checkout_tree {
 	my ($svn_rev, $treeish) = @_;
 	my $from = file_to_s("$REV_DIR/$svn_rev");
-	assert_svn_wc_clean($svn_rev,$from);
+	assert_svn_wc_clean($svn_rev);
+	assert_tree($from);
 	print "diff-tree $from $treeish\n";
 	my $pid = open my $diff_fh, '-|';
 	defined $pid or croak $!;
@@ -852,13 +858,75 @@ sub svn_info {
 
 sub sys { system(@_) == 0 or croak $? }
 
-sub git_addremove {
-	system( "git-diff-files --name-only -z ".
-				" | 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"
-		) == 0 or croak $?
+sub eol_cp {
+	my ($from, $to) = @_;
+	my $es = safe_qx(qw/svn propget svn:eol-style/, $to);
+	open my $rfd, '<', $from or croak $!;
+	binmode $rfd or croak $!;
+	open my $wfd, '>', $to or croak $!;
+	binmode $wfd or croak $!;
+
+	my $eol = $EOL{$es} or undef;
+	if ($eol) {
+		print  "$eol: $from => $to\n";
+	}
+	my $buf;
+	while (1) {
+		my ($r, $w, $t);
+		defined($r = sysread($rfd, $buf, 4096)) or croak $!;
+		return unless $r;
+		$buf =~ s/(?:\015|\012|\015\012)/$eol/gs if $eol;
+		for ($w = 0; $w < $r; $w += $t) {
+			$t = syswrite($wfd, $buf, $r - $w, $w) or croak $!;
+		}
+	}
+}
+
+sub do_update_index {
+	my ($z_cmd, $cmd, $no_text_base) = @_;
+
+	my $z = open my $p, '-|';
+	defined $z or croak $!;
+	unless ($z) { exec @$z_cmd or croak $! }
+
+	my $pid = open my $ui, '|-';
+	defined $pid or croak $!;
+	unless ($pid) {
+		exec('git-update-index',"--$cmd",'-z','--stdin') or croak $!;
+	}
+	local $/ = "\0";
+	while (my $x = <$p>) {
+		chomp $x;
+		if (!$no_text_base && lstat $x && ! -l _ &&
+				safe_qx(qw/svn propget svn:keywords/,$x)) {
+			my $mode = -x _ ? 0755 : 0644;
+			my ($v,$d,$f) = File::Spec->splitpath($x);
+			my $tb = File::Spec->catfile($d, '.svn', 'tmp',
+						'text-base',"$f.svn-base");
+			$tb =~ s#^/##;
+			unless (-f $tb) {
+				$tb = File::Spec->catfile($d, '.svn',
+						'text-base',"$f.svn-base");
+				$tb =~ s#^/##;
+			}
+			unlink $x or croak $!;
+			eol_cp($tb, $x);
+			chmod(($mode &~ umask), $x) or croak $!;
+		}
+		print $ui $x,"\0";
+	}
+	close $ui or croak $!;
+}
+
+sub index_changes {
+	my $no_text_base = shift;
+	do_update_index([qw/git-diff-files --name-only -z/],
+			'remove',
+			$no_text_base);
+	do_update_index([qw/git-ls-files -z --others/,
+			      "--exclude-from=$GIT_DIR/$GIT_SVN/info/exclude"],
+			'add',
+			$no_text_base);
 }
 
 sub s_to_file {
@@ -936,7 +1004,7 @@ sub git_commit {
 	defined $pid or croak $!;
 	if ($pid == 0) {
 		$ENV{GIT_INDEX_FILE} = $GIT_SVN_INDEX;
-		git_addremove();
+		index_changes();
 		chomp(my $tree = `git-write-tree`);
 		croak if $?;
 		if (exists $tree_map{$tree}) {
diff --git a/contrib/git-svn/t/lib-git-svn.sh b/contrib/git-svn/t/lib-git-svn.sh
new file mode 100644
index 0000000..a98e9d1
--- /dev/null
+++ b/contrib/git-svn/t/lib-git-svn.sh
@@ -0,0 +1,39 @@
+PATH=$PWD/../:$PATH
+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"
+
+
diff --git a/contrib/git-svn/t/t0000-contrib-git-svn.sh b/contrib/git-svn/t/t0000-contrib-git-svn.sh
index f400202..a07fbad 100644
--- a/contrib/git-svn/t/t0000-contrib-git-svn.sh
+++ b/contrib/git-svn/t/t0000-contrib-git-svn.sh
@@ -3,48 +3,10 @@ #
 # 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"
+. ./lib-git-svn.sh
 
 mkdir import
-
 cd import
 
 echo foo > foo
@@ -55,10 +17,9 @@ 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
+svn import -m 'import for git-svn' . "$svnrepo" >/dev/null
 
 cd ..
-
 rm -rf import
 
 test_expect_success \
diff --git a/contrib/git-svn/t/t0001-contrib-git-svn-props.sh b/contrib/git-svn/t/t0001-contrib-git-svn-props.sh
new file mode 100644
index 0000000..6fa7889
--- /dev/null
+++ b/contrib/git-svn/t/t0001-contrib-git-svn-props.sh
@@ -0,0 +1,125 @@
+#!/bin/sh
+#
+# Copyright (c) 2006 Eric Wong
+#
+
+test_description='git-svn property tests'
+. ./lib-git-svn.sh
+
+mkdir import
+
+a_crlf=
+a_lf=
+a_cr=
+a_ne_crlf=
+a_ne_lf=
+a_ne_cr=
+a_empty=
+a_empty_lf=
+a_empty_cr=
+a_empty_crlf=
+
+cd import
+	cat >> kw.c <<''
+/* Make it look like somebody copied a file from CVS into SVN: */
+/* $Id: kw.c,v 1.1.1.1 1994/03/06 00:00:00 eric Exp $ */
+
+	printf "Hello\r\nWorld\r\n" > crlf
+	a_crlf=`git-hash-object -w crlf`
+	printf "Hello\rWorld\r" > cr
+	a_cr=`git-hash-object -w cr`
+	printf "Hello\nWorld\n" > lf
+	a_lf=`git-hash-object -w lf`
+
+	printf "Hello\r\nWorld" > ne_crlf
+	a_ne_crlf=`git-hash-object -w ne_crlf`
+	printf "Hello\nWorld" > ne_lf
+	a_ne_lf=`git-hash-object -w ne_lf`
+	printf "Hello\rWorld" > ne_cr
+	a_ne_cr=`git-hash-object -w ne_cr`
+
+	touch empty
+	a_empty=`git-hash-object -w empty`
+	printf "\n" > empty_lf
+	a_empty_lf=`git-hash-object -w empty_lf`
+	printf "\r" > empty_cr
+	a_empty_cr=`git-hash-object -w empty_cr`
+	printf "\r\n" > empty_crlf
+	a_empty_crlf=`git-hash-object -w empty_crlf`
+
+	svn import -m 'import for git-svn' . "$svnrepo" >/dev/null
+cd ..
+
+rm -rf import
+svn co "$svnrepo" test_wc
+
+cd test_wc
+	echo 'Greetings' >> kw.c
+	svn commit -m 'Not yet an $Id$'
+	svn up
+
+	echo 'Hello world' >> kw.c
+	svn commit -m 'Modified file, but still not yet an $Id$'
+	svn up
+
+	svn propset svn:keywords Id kw.c
+	svn commit -m 'Propset $Id$'
+	svn up
+cd ..
+
+git-svn init "$svnrepo"
+git-svn fetch
+
+git checkout -b mybranch remotes/git-svn
+echo 'Hi again' >> kw.c
+name='test svn:keywords ignoring'
+
+git commit -a -m "$name"
+git-svn commit remotes/git-svn..mybranch
+git pull . remotes/git-svn
+
+expect='/* $Id$ */'
+got="`sed -ne 2p kw.c`"
+test_expect_success 'raw $Id$ found in kw.c' "test '$expect' = '$got'"
+
+cd test_wc
+	svn propset svn:eol-style CR empty
+	svn propset svn:eol-style CR crlf
+	svn propset svn:eol-style CR ne_crlf
+	svn commit -m 'propset CR on crlf files'
+	svn up
+cd ..
+
+git-svn fetch
+git pull . remotes/git-svn
+
+svn co "$svnrepo" new_wc
+for i in crlf ne_crlf lf ne_lf cr ne_cr empty_cr empty_lf empty empty_crlf
+do
+	test_expect_success "Comparing $i" "cmp $i new_wc/$i"
+done
+
+
+cd test_wc
+	printf '$Id$\rHello\rWorld\r' > cr
+	printf '$Id$\rHello\rWorld' > ne_cr
+	a_cr=`printf '$Id$\r\nHello\r\nWorld\r\n' | git-hash-object --stdin`
+	a_ne_cr=`printf '$Id$\r\nHello\r\nWorld' | git-hash-object --stdin`
+	svn propset svn:eol-style CRLF cr
+	svn propset svn:eol-style CRLF ne_cr
+	svn propset svn:keywords Id cr
+	svn propset svn:keywords Id ne_cr
+	svn commit -m 'propset CRLF on cr files'
+	svn up
+cd ..
+
+git-svn fetch
+git pull . remotes/git-svn
+
+b_cr="`git-hash-object cr`"
+b_ne_cr="`git-hash-object ne_cr`"
+
+test_expect_success 'CRLF + $Id$' "test '$a_cr' = '$b_cr'"
+test_expect_success 'CRLF + $Id$ (no newline)' "test '$a_ne_cr' = '$b_ne_cr'"
+
+test_done
-- 
1.3.2.g7d11

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

end of thread, other threads:[~2006-05-24  2:23 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-05-16 17:33 git-svn vs. $Id$ Tommi Virtanen
2006-05-16 17:48 ` Linus Torvalds
2006-05-16 18:12   ` Tommi Virtanen
2006-05-21  1:12     ` Eric Wong
2006-05-21  3:03 ` [PATCH] git-svn: ignore expansion of svn:keywords Eric Wong
2006-05-24  2:23   ` git-svn vs. $Id$ Eric Wong
2006-05-24  2:23     ` [PATCH] git-svn: starting a 1.1.0-pre development version Eric Wong
2006-05-24  2:23       ` [PATCH] git-svn: ignore expansion of svn:keywords Eric Wong

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).