Merge git://git.bogomips.org/git-svn
* git://git.bogomips.org/git-svn: git-svn: Show UUID in svn info for added directories with svn 1.5.5 git-svn: avoid importing nested git repos git-svn: fix SVN 1.1.x compatibility git-svn: Add --localtime option to "fetch" git-svn: better attempt to handle broken symlink updates git-svn: handle empty files marked as symlinks in SVN
This commit is contained in:
commit
9003dd4027
@ -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;
|
||||
|
@ -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=
|
||||
|
185
git-svn.perl
185
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);
|
||||
@ -911,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: " .
|
||||
@ -1364,7 +1366,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 +2528,61 @@ sub get_untracked {
|
||||
\@out;
|
||||
}
|
||||
|
||||
# parse_svn_date(DATE)
|
||||
# --------------------
|
||||
# Given a date (in UTC) from Subversion, return a string in the format
|
||||
# "<TZ Offset> <local date/time>" 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 {
|
||||
@ -3200,7 +3251,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 +3264,39 @@ 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;
|
||||
}
|
||||
|
||||
# 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;
|
||||
@ -3235,6 +3322,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 '');
|
||||
@ -3262,26 +3350,40 @@ 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";
|
||||
}
|
||||
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
|
||||
@ -3299,11 +3401,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;
|
||||
@ -3311,6 +3415,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;
|
||||
@ -3318,6 +3423,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;
|
||||
@ -3325,6 +3431,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;
|
||||
@ -3340,22 +3447,43 @@ 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}) {
|
||||
print $base 'link ' if ($fb->{mode_a} == 120000);
|
||||
my $size = $::_repository->cat_blob($fb->{blob}, $base);
|
||||
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;
|
||||
}
|
||||
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 $!;
|
||||
@ -3366,6 +3494,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}) {
|
||||
@ -3379,11 +3509,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');
|
||||
@ -4019,10 +4157,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;
|
||||
|
@ -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 = <STDIN>;
|
||||
@x = split(/\n/, $x[1]);
|
||||
splice(@x, 0, 2);
|
||||
$x[-1] = "";
|
||||
print join("\n", @x);
|
||||
' > current &&
|
||||
test_cmp current "$1"
|
||||
}
|
||||
|
||||
|
90
t/t9131-git-svn-empty-symlink.sh
Executable file
90
t/t9131-git-svn-empty-symlink.sh
Executable file
@ -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" <<EOF
|
||||
SVN-fs-dump-format-version: 2
|
||||
|
||||
UUID: 60780f9a-7df5-43b4-83ab-60e2c0673ef7
|
||||
|
||||
Revision-number: 0
|
||||
Prop-content-length: 56
|
||||
Content-length: 56
|
||||
|
||||
K 8
|
||||
svn:date
|
||||
V 27
|
||||
2008-11-26T07:17:27.590577Z
|
||||
PROPS-END
|
||||
|
||||
Revision-number: 1
|
||||
Prop-content-length: 111
|
||||
Content-length: 111
|
||||
|
||||
K 7
|
||||
svn:log
|
||||
V 4
|
||||
test
|
||||
K 10
|
||||
svn:author
|
||||
V 12
|
||||
normalperson
|
||||
K 8
|
||||
svn:date
|
||||
V 27
|
||||
2008-11-26T07:18:03.511836Z
|
||||
PROPS-END
|
||||
|
||||
Node-path: bar
|
||||
Node-kind: file
|
||||
Node-action: add
|
||||
Prop-content-length: 33
|
||||
Text-content-length: 0
|
||||
Text-content-md5: d41d8cd98f00b204e9800998ecf8427e
|
||||
Content-length: 33
|
||||
|
||||
K 11
|
||||
svn:special
|
||||
V 1
|
||||
*
|
||||
PROPS-END
|
||||
|
||||
Revision-number: 2
|
||||
Prop-content-length: 121
|
||||
Content-length: 121
|
||||
|
||||
K 7
|
||||
svn:log
|
||||
V 13
|
||||
bar => 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
|
102
t/t9132-git-svn-broken-symlink.sh
Executable file
102
t/t9132-git-svn-broken-symlink.sh
Executable file
@ -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" <<EOF
|
||||
SVN-fs-dump-format-version: 2
|
||||
|
||||
UUID: 60780f9a-7df5-43b4-83ab-60e2c0673ef7
|
||||
|
||||
Revision-number: 0
|
||||
Prop-content-length: 56
|
||||
Content-length: 56
|
||||
|
||||
K 8
|
||||
svn:date
|
||||
V 27
|
||||
2008-11-26T07:17:27.590577Z
|
||||
PROPS-END
|
||||
|
||||
Revision-number: 1
|
||||
Prop-content-length: 111
|
||||
Content-length: 111
|
||||
|
||||
K 7
|
||||
svn:log
|
||||
V 4
|
||||
test
|
||||
K 10
|
||||
svn:author
|
||||
V 12
|
||||
normalperson
|
||||
K 8
|
||||
svn:date
|
||||
V 27
|
||||
2008-11-26T07:18:03.511836Z
|
||||
PROPS-END
|
||||
|
||||
Node-path: bar
|
||||
Node-kind: file
|
||||
Node-action: add
|
||||
Prop-content-length: 33
|
||||
Text-content-length: 4
|
||||
Text-content-md5: 912ec803b2ce49e4a541068d495ab570
|
||||
Content-length: 37
|
||||
|
||||
K 11
|
||||
svn:special
|
||||
V 1
|
||||
*
|
||||
PROPS-END
|
||||
asdf
|
||||
|
||||
Revision-number: 2
|
||||
Prop-content-length: 121
|
||||
Content-length: 121
|
||||
|
||||
K 7
|
||||
svn:log
|
||||
V 13
|
||||
bar => 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
|
101
t/t9133-git-svn-nested-git-repo.sh
Executable file
101
t/t9133-git-svn-nested-git-repo.sh
Executable file
@ -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
|
Loading…
Reference in New Issue
Block a user