From dbc6c74d0858d77e61e092a48d467e725211f8e9 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 11 Jan 2009 16:51:10 -0800 Subject: [PATCH 1/6] git-svn: handle empty files marked as symlinks in SVN Broken SVN clients generate empty files with the svn:special set to '*'. This attempts to denote a symlink pointing to a file with an empty path (""), which cannot be generated on a POSIX system. Thus, we mimic the behavior of svn(1) and create a zero-byte file in our tree. Signed-off-by: Eric Wong --- git-svn.perl | 55 +++++++++++++++++-- t/t9131-git-svn-empty-symlink.sh | 90 ++++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 5 deletions(-) create mode 100755 t/t9131-git-svn-empty-symlink.sh diff --git a/git-svn.perl b/git-svn.perl index ad01e182df..1b87a65299 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -3200,7 +3200,10 @@ sub new { my ($class, $git_svn) = @_; my $self = SVN::Delta::Editor->new; bless $self, $class; - $self->{c} = $git_svn->{last_commit} if exists $git_svn->{last_commit}; + if (exists $git_svn->{last_commit}) { + $self->{c} = $git_svn->{last_commit}; + $self->{empty_symlinks} = _mark_empty_symlinks($git_svn); + } $self->{empty} = {}; $self->{dir_prop} = {}; $self->{file_prop} = {}; @@ -3210,6 +3213,34 @@ sub new { $self; } +# this uses the Ra object, so it must be called before do_{switch,update}, +# not inside them (when the Git::SVN::Fetcher object is passed) to +# do_{switch,update} +sub _mark_empty_symlinks { + my ($git_svn) = @_; + my %ret; + my ($rev, $cmt) = $git_svn->last_rev_commit; + return {} unless ($rev && $cmt); + + chomp(my $empty_blob = `git hash-object -t blob --stdin < /dev/null`); + my ($ls, $ctx) = command_output_pipe(qw/ls-tree -r -z/, $cmt); + local $/ = "\0"; + my $pfx = $git_svn->{path}; + $pfx .= '/' if length($pfx); + while (<$ls>) { + chomp; + s/\A100644 blob $empty_blob\t//o or next; + my $path = $_; + my (undef, $props) = + $git_svn->ra->get_file($pfx.$path, $rev, undef); + if ($props->{'svn:special'}) { + $ret{$path} = 1; + } + } + command_close_pipe($ls, $ctx); + \%ret; +} + sub set_path_strip { my ($self, $path) = @_; $self->{path_strip} = qr/^\Q$path\E(\/|$)/ if length $path; @@ -3268,6 +3299,9 @@ sub open_file { unless (defined $mode && defined $blob) { die "$path was not found in commit $self->{c} (r$rev)\n"; } + if ($mode eq '100644' && $self->{empty_symlinks}->{$path}) { + $mode = '120000'; + } { path => $path, mode_a => $mode, mode_b => $mode, blob => $blob, pool => SVN::Pool->new, action => 'M' }; } @@ -3346,7 +3380,10 @@ sub apply_textdelta { open my $dup, '<&', $fh or croak $!; my $base = $::_repository->temp_acquire('git_blob'); if ($fb->{blob}) { - print $base 'link ' if ($fb->{mode_a} == 120000); + if ($fb->{mode_a} eq '120000' && + ! $self->{empty_symlinks}->{$fb->{path}}) { + print $base 'link ' or die "print $!\n"; + } my $size = $::_repository->cat_blob($fb->{blob}, $base); die "Failed to read object $fb->{blob}" if ($size < 0); @@ -3379,11 +3416,19 @@ sub close_file { } if ($fb->{mode_b} == 120000) { sysseek($fh, 0, 0) or croak $!; - sysread($fh, my $buf, 5) == 5 or croak $!; + my $rd = sysread($fh, my $buf, 5); - unless ($buf eq 'link ') { + if (!defined $rd) { + croak "sysread: $!\n"; + } elsif ($rd == 0) { warn "$path has mode 120000", - " but is not a link\n"; + " but it points to nothing\n", + "converting to an empty file with mode", + " 100644\n"; + $fb->{mode_b} = '100644'; + } elsif ($buf ne 'link ') { + warn "$path has mode 120000", + " but is not a link\n"; } else { my $tmp_fh = $::_repository->temp_acquire( 'svn_hash'); diff --git a/t/t9131-git-svn-empty-symlink.sh b/t/t9131-git-svn-empty-symlink.sh new file mode 100755 index 0000000000..704a4f8574 --- /dev/null +++ b/t/t9131-git-svn-empty-symlink.sh @@ -0,0 +1,90 @@ +#!/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 an empty file' 'test -f x/bar && ! test -s x/bar' +test_expect_success 'get "bar" => symlink fix from svn' \ + '(cd x && git svn rebase)' +test_expect_success '"bar" becomes a symlink' 'test -L x/bar' +test_done From baf5fa8a7fdefc696fb1d79c95ae15a4cc779c1e Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 11 Jan 2009 16:51:11 -0800 Subject: [PATCH 2/6] 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 --- git-svn.perl | 24 +++++-- t/t9132-git-svn-broken-symlink.sh | 102 ++++++++++++++++++++++++++++++ 2 files changed, 122 insertions(+), 4 deletions(-) create mode 100755 t/t9132-git-svn-broken-symlink.sh diff --git a/git-svn.perl b/git-svn.perl index 1b87a65299..b0e3d7c79a 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 0000000000..b8de59e493 --- /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 From e82f0d73f02e89a95d9477911774d314f70f1063 Mon Sep 17 00:00:00 2001 From: Pete Harlan Date: Sat, 17 Jan 2009 20:10:14 -0800 Subject: [PATCH 3/6] git-svn: Add --localtime option to "fetch" By default git-svn stores timestamps of fetched commits in Subversion's UTC format. Passing --localtime to fetch will convert them to the timezone of the server on which git-svn is run. This makes the timestamps of a resulting "git log" agree with what "svn log" shows for the same repository. Signed-off-by: Pete Harlan Acked-by: Eric Wong --- Documentation/git-svn.txt | 11 ++++++ contrib/completion/git-completion.bash | 2 +- git-svn.perl | 54 +++++++++++++++++++++++++- 3 files changed, 64 insertions(+), 3 deletions(-) diff --git a/Documentation/git-svn.txt b/Documentation/git-svn.txt index 8d0c421b80..63d2f5e962 100644 --- a/Documentation/git-svn.txt +++ b/Documentation/git-svn.txt @@ -92,6 +92,17 @@ COMMANDS .git/config file may be specified as an optional command-line argument. +--localtime;; + Store Git commit times in the local timezone instead of UTC. This + makes 'git-log' (even without --date=local) show the same times + that `svn log` would in the local timezone. + +This doesn't interfere with interoperating with the Subversion +repository you cloned from, but if you wish for your local Git +repository to be able to interoperate with someone else's local Git +repository, either don't use this option or you should both use it in +the same local timezone. + 'clone':: Runs 'init' and 'fetch'. It will automatically create a directory based on the basename of the URL passed to it; diff --git a/contrib/completion/git-completion.bash b/contrib/completion/git-completion.bash index ec701e8069..60497a4c2a 100755 --- a/contrib/completion/git-completion.bash +++ b/contrib/completion/git-completion.bash @@ -1576,7 +1576,7 @@ _git_svn () --follow-parent --authors-file= --repack= --no-metadata --use-svm-props --use-svnsync-props --log-window-size= --no-checkout --quiet - --repack-flags --user-log-author $remote_opts + --repack-flags --user-log-author --localtime $remote_opts " local init_opts=" --template= --shared= --trunk= --tags= diff --git a/git-svn.perl b/git-svn.perl index b0e3d7c79a..e3e125b098 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -84,6 +84,7 @@ my %fc_opts = ( 'follow-parent|follow!' => \$Git::SVN::_follow_parent, \$Git::SVN::_repack_flags, 'use-log-author' => \$Git::SVN::_use_log_author, 'add-author-from' => \$Git::SVN::_add_author_from, + 'localtime' => \$Git::SVN::_localtime, %remote_opts ); my ($_trunk, $_tags, $_branches, $_stdlayout); @@ -1364,7 +1365,7 @@ use constant rev_map_fmt => 'NH40'; use vars qw/$default_repo_id $default_ref_id $_no_metadata $_follow_parent $_repack $_repack_flags $_use_svm_props $_head $_use_svnsync_props $no_reuse_existing $_minimize_url - $_use_log_author $_add_author_from/; + $_use_log_author $_add_author_from $_localtime/; use Carp qw/croak/; use File::Path qw/mkpath/; use File::Copy qw/copy/; @@ -2526,12 +2527,61 @@ sub get_untracked { \@out; } +# parse_svn_date(DATE) +# -------------------- +# Given a date (in UTC) from Subversion, return a string in the format +# " " that Git will use. +# +# By default the parsed date will be in UTC; if $Git::SVN::_localtime +# is true we'll convert it to the local timezone instead. sub parse_svn_date { my $date = shift || return '+0000 1970-01-01 00:00:00'; my ($Y,$m,$d,$H,$M,$S) = ($date =~ /^(\d{4})\-(\d\d)\-(\d\d)T (\d\d)\:(\d\d)\:(\d\d).\d+Z$/x) or croak "Unable to parse date: $date\n"; - "+0000 $Y-$m-$d $H:$M:$S"; + my $parsed_date; # Set next. + + if ($Git::SVN::_localtime) { + # Translate the Subversion datetime to an epoch time. + # Begin by switching ourselves to $date's timezone, UTC. + my $old_env_TZ = $ENV{TZ}; + $ENV{TZ} = 'UTC'; + + my $epoch_in_UTC = + POSIX::strftime('%s', $S, $M, $H, $d, $m - 1, $Y - 1900); + + # Determine our local timezone (including DST) at the + # time of $epoch_in_UTC. $Git::SVN::Log::TZ stored the + # value of TZ, if any, at the time we were run. + if (defined $Git::SVN::Log::TZ) { + $ENV{TZ} = $Git::SVN::Log::TZ; + } else { + delete $ENV{TZ}; + } + + my $our_TZ = + POSIX::strftime('%Z', $S, $M, $H, $d, $m - 1, $Y - 1900); + + # This converts $epoch_in_UTC into our local timezone. + my ($sec, $min, $hour, $mday, $mon, $year, + $wday, $yday, $isdst) = localtime($epoch_in_UTC); + + $parsed_date = sprintf('%s %04d-%02d-%02d %02d:%02d:%02d', + $our_TZ, $year + 1900, $mon + 1, + $mday, $hour, $min, $sec); + + # Reset us to the timezone in effect when we entered + # this routine. + if (defined $old_env_TZ) { + $ENV{TZ} = $old_env_TZ; + } else { + delete $ENV{TZ}; + } + } else { + $parsed_date = "+0000 $Y-$m-$d $H:$M:$S"; + } + + return $parsed_date; } sub check_author { From 1ef626b4b6c70fc13062faafdccb2f0da7578a29 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sat, 17 Jan 2009 22:11:44 -0800 Subject: [PATCH 4/6] git-svn: fix SVN 1.1.x compatibility The get_log() function in the Perl SVN API introduced the limit parameter in 1.2.0. However, this got discarded in our SVN::Ra compatibility layer when used with SVN 1.1.x. We now emulate the limit functionality in older SVN versions by preventing the original callback from being called if the given limit has been reached. This emulation is less bandwidth efficient, but SVN 1.1.x is becoming rarer now. Additionally, the --limit parameter in svn(1) uses the aforementioned get_log() functionality change in SVN 1.2.x. t9129 no longer depends on --limit to work and instead uses Perl to parse out the commit message. Thanks to Tom G. Christensen for the bug report. Signed-off-by: Eric Wong --- git-svn.perl | 15 ++++++++++++++- t/t9129-git-svn-i18n-commitencoding.sh | 13 +++++++++++-- 2 files changed, 25 insertions(+), 3 deletions(-) diff --git a/git-svn.perl b/git-svn.perl index e3e125b098..71b8ef4265 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -4130,10 +4130,23 @@ sub DESTROY { # do not call the real DESTROY since we store ourselves in $RA } +# get_log(paths, start, end, limit, +# discover_changed_paths, strict_node_history, receiver) sub get_log { my ($self, @args) = @_; my $pool = SVN::Pool->new; - splice(@args, 3, 1) if ($SVN::Core::VERSION le '1.2.0'); + + # the limit parameter was not supported in SVN 1.1.x, so we + # drop it. Therefore, the receiver callback passed to it + # is made aware of this limitation by being wrapped if + # the limit passed to is being wrapped. + if ($SVN::Core::VERSION le '1.2.0') { + my $limit = splice(@args, 3, 1); + if ($limit > 0) { + my $receiver = pop @args; + push(@args, sub { &$receiver(@_) if (--$limit >= 0) }); + } + } my $ret = $self->SUPER::get_log(@args, $pool); $pool->clear; $ret; diff --git a/t/t9129-git-svn-i18n-commitencoding.sh b/t/t9129-git-svn-i18n-commitencoding.sh index 8a9dde44d5..9c7b1ad18b 100755 --- a/t/t9129-git-svn-i18n-commitencoding.sh +++ b/t/t9129-git-svn-i18n-commitencoding.sh @@ -15,8 +15,17 @@ compare_git_head_with () { } compare_svn_head_with () { - LC_ALL=en_US.UTF-8 svn log --limit 1 `git svn info --url` | \ - sed -e 1,3d -e "/^-\{1,\}\$/d" >current && + # extract just the log message and strip out committer info. + # don't use --limit here since svn 1.1.x doesn't have it, + LC_ALL=en_US.UTF-8 svn log `git svn info --url` | perl -w -e ' + use bytes; + $/ = ("-"x72) . "\n"; + my @x = ; + @x = split(/\n/, $x[1]); + splice(@x, 0, 2); + $x[-1] = ""; + print join("\n", @x); + ' > current && test_cmp current "$1" } From b03a71a660d15d76b63d7d3c5205b896f89f34b5 Mon Sep 17 00:00:00 2001 From: Eric Wong Date: Sun, 11 Jan 2009 18:23:38 -0800 Subject: [PATCH 5/6] git-svn: avoid importing nested git repos Some SVN repositories contain git repositories within them (hopefully accidentally checked in). Since git refuses to track nested ".git" repositories, this can be a problem when fetching updates from SVN. Thanks to Morgan Christiansson for the report and testing. Signed-off-by: Eric Wong --- git-svn.perl | 34 ++++++++-- t/t9133-git-svn-nested-git-repo.sh | 101 +++++++++++++++++++++++++++++ 2 files changed, 131 insertions(+), 4 deletions(-) create mode 100755 t/t9133-git-svn-nested-git-repo.sh diff --git a/git-svn.perl b/git-svn.perl index 71b8ef4265..55c4dfb968 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -3291,6 +3291,11 @@ sub _mark_empty_symlinks { \%ret; } +# returns true if a given path is inside a ".git" directory +sub in_dot_git { + $_[0] =~ m{(?:^|/)\.git(?:/|$)}; +} + sub set_path_strip { my ($self, $path) = @_; $self->{path_strip} = qr/^\Q$path\E(\/|$)/ if length $path; @@ -3316,6 +3321,7 @@ sub git_path { sub delete_entry { my ($self, $path, $rev, $pb) = @_; + return undef if in_dot_git($path); my $gpath = $self->git_path($path); return undef if ($gpath eq ''); @@ -3343,8 +3349,12 @@ sub delete_entry { sub open_file { my ($self, $path, $pb, $rev) = @_; + my ($mode, $blob); + + goto out if in_dot_git($path); + my $gpath = $self->git_path($path); - my ($mode, $blob) = (command('ls-tree', $self->{c}, '--', $gpath) + ($mode, $blob) = (command('ls-tree', $self->{c}, '--', $gpath) =~ /^(\d{6}) blob ([a-f\d]{40})\t/); unless (defined $mode && defined $blob) { die "$path was not found in commit $self->{c} (r$rev)\n"; @@ -3352,20 +3362,27 @@ sub open_file { if ($mode eq '100644' && $self->{empty_symlinks}->{$path}) { $mode = '120000'; } +out: { path => $path, mode_a => $mode, mode_b => $mode, blob => $blob, pool => SVN::Pool->new, action => 'M' }; } sub add_file { my ($self, $path, $pb, $cp_path, $cp_rev) = @_; - my ($dir, $file) = ($path =~ m#^(.*?)/?([^/]+)$#); - delete $self->{empty}->{$dir}; - { path => $path, mode_a => 100644, mode_b => 100644, + my $mode; + + if (!in_dot_git($path)) { + my ($dir, $file) = ($path =~ m#^(.*?)/?([^/]+)$#); + delete $self->{empty}->{$dir}; + $mode = '100644'; + } + { path => $path, mode_a => $mode, mode_b => $mode, pool => SVN::Pool->new, action => 'A' }; } sub add_directory { my ($self, $path, $cp_path, $cp_rev) = @_; + goto out if in_dot_git($path); my $gpath = $self->git_path($path); if ($gpath eq '') { my ($ls, $ctx) = command_output_pipe(qw/ls-tree @@ -3383,11 +3400,13 @@ sub add_directory { my ($dir, $file) = ($path =~ m#^(.*?)/?([^/]+)$#); delete $self->{empty}->{$dir}; $self->{empty}->{$path} = 1; +out: { path => $path }; } sub change_dir_prop { my ($self, $db, $prop, $value) = @_; + return undef if in_dot_git($db->{path}); $self->{dir_prop}->{$db->{path}} ||= {}; $self->{dir_prop}->{$db->{path}}->{$prop} = $value; undef; @@ -3395,6 +3414,7 @@ sub change_dir_prop { sub absent_directory { my ($self, $path, $pb) = @_; + return undef if in_dot_git($pb->{path}); $self->{absent_dir}->{$pb->{path}} ||= []; push @{$self->{absent_dir}->{$pb->{path}}}, $path; undef; @@ -3402,6 +3422,7 @@ sub absent_directory { sub absent_file { my ($self, $path, $pb) = @_; + return undef if in_dot_git($pb->{path}); $self->{absent_file}->{$pb->{path}} ||= []; push @{$self->{absent_file}->{$pb->{path}}}, $path; undef; @@ -3409,6 +3430,7 @@ sub absent_file { sub change_file_prop { my ($self, $fb, $prop, $value) = @_; + return undef if in_dot_git($fb->{path}); if ($prop eq 'svn:executable') { if ($fb->{mode_b} != 120000) { $fb->{mode_b} = defined $value ? 100755 : 100644; @@ -3424,11 +3446,13 @@ sub change_file_prop { sub apply_textdelta { my ($self, $fb, $exp) = @_; + return undef if (in_dot_git($fb->{path})); my $fh = $::_repository->temp_acquire('svn_delta'); # $fh gets auto-closed() by SVN::TxDelta::apply(), # (but $base does not,) so dup() it for reading in close_file open my $dup, '<&', $fh or croak $!; my $base = $::_repository->temp_acquire('git_blob'); + if ($fb->{blob}) { my ($base_is_link, $size); @@ -3469,6 +3493,8 @@ sub apply_textdelta { sub close_file { my ($self, $fb, $exp) = @_; + return undef if (in_dot_git($fb->{path})); + my $hash; my $path = $self->git_path($fb->{path}); if (my $fh = $fb->{fh}) { diff --git a/t/t9133-git-svn-nested-git-repo.sh b/t/t9133-git-svn-nested-git-repo.sh new file mode 100755 index 0000000000..893f57ef73 --- /dev/null +++ b/t/t9133-git-svn-nested-git-repo.sh @@ -0,0 +1,101 @@ +#!/bin/sh +# +# Copyright (c) 2009 Eric Wong +# + +test_description='git svn property tests' +. ./lib-git-svn.sh + +test_expect_success 'setup repo with a git repo inside it' ' + svn co "$svnrepo" s && + ( + cd s && + git init && + test -f .git/HEAD && + > .git/a && + echo a > a && + svn add .git a && + svn commit -m "create a nested git repo" && + svn up && + echo hi >> .git/a && + svn commit -m "modify .git/a" && + svn up + ) +' + +test_expect_success 'clone an SVN repo containing a git repo' ' + git svn clone "$svnrepo" g && + echo a > expect && + test_cmp expect g/a +' + +test_expect_success 'SVN-side change outside of .git' ' + ( + cd s && + echo b >> a && + svn commit -m "SVN-side change outside of .git" && + svn up && + svn log -v | fgrep "SVN-side change outside of .git" + ) +' + +test_expect_success 'update git svn-cloned repo' ' + ( + cd g && + git svn rebase && + echo a > expect && + echo b >> expect && + test_cmp a expect && + rm expect + ) +' + +test_expect_success 'SVN-side change inside of .git' ' + ( + cd s && + git add a && + git commit -m "add a inside an SVN repo" && + git log && + svn add --force .git && + svn commit -m "SVN-side change inside of .git" && + svn up && + svn log -v | fgrep "SVN-side change inside of .git" + ) +' + +test_expect_success 'update git svn-cloned repo' ' + ( + cd g && + git svn rebase && + echo a > expect && + echo b >> expect && + test_cmp a expect && + rm expect + ) +' + +test_expect_success 'SVN-side change in and out of .git' ' + ( + cd s && + echo c >> a && + git add a && + git commit -m "add a inside an SVN repo" && + svn commit -m "SVN-side change in and out of .git" && + svn up && + svn log -v | fgrep "SVN-side change in and out of .git" + ) +' + +test_expect_success 'update git svn-cloned repo again' ' + ( + cd g && + git svn rebase && + echo a > expect && + echo b >> expect && + echo c >> expect && + test_cmp a expect && + rm expect + ) +' + +test_done From 22ba47f544a233958c73a9260b18c57b431f44b3 Mon Sep 17 00:00:00 2001 From: Marcel Koeppen Date: Mon, 19 Jan 2009 03:02:01 +0100 Subject: [PATCH 6/6] git-svn: Show UUID in svn info for added directories with svn 1.5.5 In svn 1.5.5 the output of "svn info" for added directories was changed and now shows the repository UUID. This patch implements the same behavior for "git svn info" and makes t9119-git-svn-info.17 pass if svn 1.5.5 is used. Signed-off-by: Marcel Koeppen Acked-by: Eric Wong --- git-svn.perl | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/git-svn.perl b/git-svn.perl index 55c4dfb968..d4cb538b93 100755 --- a/git-svn.perl +++ b/git-svn.perl @@ -912,7 +912,8 @@ sub cmd_info { if ($@) { $result .= "Repository Root: (offline)\n"; } - $result .= "Repository UUID: $uuid\n" unless $diff_status eq "A"; + $result .= "Repository UUID: $uuid\n" unless $diff_status eq "A" && + ($SVN::Core::VERSION le '1.5.4' || $file_type ne "dir"); $result .= "Revision: " . ($diff_status eq "A" ? 0 : $rev) . "\n"; $result .= "Node Kind: " .