From: Eric Wong Date: Mon, 12 Jan 2009 00:51:11 +0000 (-0800) Subject: git-svn: better attempt to handle broken symlink updates X-Git-Tag: v1.6.2-rc0~128^2~4 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=baf5fa8a7fdefc696fb1d79c95ae15a4cc779c1e;p=git.git git-svn: better attempt to handle broken symlink updates This is a followup to 7fc35e0e94782bbbefb920875813519038659930, (workaround a for broken symlinks in SVN). Since broken SVN clients can commit svn:special files without the magic "link " prefix, this can affect delta application when we update the broken svn:special file. So now we fall back and retry the delta application on symlinks if having a "link " prefix fails. Our behavior differs from svn(1) (v1.5.1) slightly: When a svn:special file is created w/o a "link " prefix, svn will create a regular file (mode 100644 to git) with the contents of the blob as-is. Our behavior is to continue creating the symlink (mode 120000 to git) with the contents of the blob as-is. While this differs from current svn(1) behavior, this is easier and more efficient to implement (and the correctness of the svn(1) is debatable, since it's a workaround for a bug in the first place). More information on this SVN bug is described here: http://subversion.tigris.org/issues/show_bug.cgi?id=2692 Signed-off-by: Eric Wong --- diff --git a/git-svn.perl b/git-svn.perl index 1b87a6529..b0e3d7c79 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -3380,19 +3380,35 @@ sub apply_textdelta { open my $dup, '<&', $fh or croak $!; my $base = $::_repository->temp_acquire('git_blob'); if ($fb->{blob}) { + my ($base_is_link, $size); + if ($fb->{mode_a} eq '120000' && ! $self->{empty_symlinks}->{$fb->{path}}) { print $base 'link ' or die "print $!\n"; + $base_is_link = 1; } - my $size = $::_repository->cat_blob($fb->{blob}, $base); + retry: + $size = $::_repository->cat_blob($fb->{blob}, $base); die "Failed to read object $fb->{blob}" if ($size < 0); if (defined $exp) { seek $base, 0, 0 or croak $!; my $got = ::md5sum($base); - die "Checksum mismatch: $fb->{path} $fb->{blob}\n", - "expected: $exp\n", - " got: $got\n" if ($got ne $exp); + if ($got ne $exp) { + my $err = "Checksum mismatch: ". + "$fb->{path} $fb->{blob}\n" . + "expected: $exp\n" . + " got: $got\n"; + if ($base_is_link) { + warn $err, + "Retrying... (possibly ", + "a bad symlink from SVN)\n"; + $::_repository->temp_reset($base); + $base_is_link = 0; + goto retry; + } + die $err; + } } } seek $base, 0, 0 or croak $!; diff --git a/t/t9132-git-svn-broken-symlink.sh b/t/t9132-git-svn-broken-symlink.sh new file mode 100755 index 000000000..b8de59e49 --- /dev/null +++ b/t/t9132-git-svn-broken-symlink.sh @@ -0,0 +1,102 @@ +#!/bin/sh + +test_description='test that git handles an svn repository with empty symlinks' + +. ./lib-git-svn.sh +test_expect_success 'load svn dumpfile' ' + svnadmin load "$rawsvnrepo" < doink + +K 10 +svn:author +V 12 +normalperson +K 8 +svn:date +V 27 +2008-11-27T03:55:31.601672Z +PROPS-END + +Node-path: bar +Node-kind: file +Node-action: change +Text-content-length: 10 +Text-content-md5: 92ca4fe7a9721f877f765c252dcd66c9 +Content-length: 10 + +link doink + +EOF +' + +test_expect_success 'clone using git svn' 'git svn clone -r1 "$svnrepo" x' + +test_expect_success '"bar" is a symlink that points to "asdf"' ' + test -L x/bar && + (cd x && test xasdf = x"`git cat-file blob HEAD:bar`") +' + +test_expect_success 'get "bar" => symlink fix from svn' ' + (cd x && git svn rebase) +' + +test_expect_success '"bar" remains a proper symlink' ' + test -L x/bar && + (cd x && test xdoink = x"`git cat-file blob HEAD:bar`") +' + +test_done