Compare commits
21 Commits
v1.6.6-rc3
...
v1.6.6
Author | SHA1 | Date | |
---|---|---|---|
902f235378 | |||
b7f44fdf27 | |||
150d38c4f3 | |||
129a5a6dea | |||
0fe19753f2 | |||
c8cba79181 | |||
063681d72e | |||
7a955a5365 | |||
ea020cbd6a | |||
33973a5b17 | |||
7d944c3399 | |||
1d144aa25e | |||
af57b41d41 | |||
577e9fcad2 | |||
ab0964d951 | |||
b6b9f83ea1 | |||
e49ca974d6 | |||
8eca03c861 | |||
a5b80d9263 | |||
afab0fe052 | |||
63b76948e1 |
@ -22,10 +22,10 @@ These changes were discussed long time ago and existing behaviours have
|
||||
been identified as more problematic to the userbase than keeping them for
|
||||
the sake of backward compatibility.
|
||||
|
||||
When necessary, transition strategy for existing users has been designed
|
||||
When necessary, a transition strategy for existing users has been designed
|
||||
not to force them running around setting configuration variables and
|
||||
updating their scripts in order to either keep the traditional behaviour
|
||||
or adjust to the new behaviour on the day their sysadmin decides to install
|
||||
or adjust to the new behaviour, on the day their sysadmin decides to install
|
||||
the new version of git. When we switched from "git-foo" to "git foo" in
|
||||
1.6.0, even though the change had been advertised and the transition
|
||||
guide had been provided for a very long time, the users procrastinated
|
||||
@ -34,11 +34,12 @@ their sysadmins updated their git installation. We are trying to avoid
|
||||
repeating that unpleasantness in the 1.7.0 release.
|
||||
|
||||
For changes decided to be in 1.7.0, commands that will be affected
|
||||
have been much louder to strongly discourage such procrastination. If
|
||||
you have been using recent versions of git, you would have seen
|
||||
warnings issued when you exercised features whose behaviour will
|
||||
change, with a clear instruction on how to keep the existing behaviour
|
||||
if you want to. You hopefully are already well prepared.
|
||||
have been much louder to strongly discourage such procrastination, and
|
||||
they continue to be in this release. If you have been using recent
|
||||
versions of git, you would have seen warnings issued when you used
|
||||
features whose behaviour will change, with a clear instruction on how
|
||||
to keep the existing behaviour if you want to. You hopefully are
|
||||
already well prepared.
|
||||
|
||||
Of course, we have also been giving "this and that will change in
|
||||
1.7.0; prepare yourselves" warnings in the release notes and
|
||||
@ -208,15 +209,14 @@ Updates since v1.6.5
|
||||
|
||||
* "git svn" learned to read SVN 1.5+ and SVK merge tickets.
|
||||
|
||||
* "git svn" learned to recreate empty directories tracked only by SVN.
|
||||
|
||||
* "gitweb" can optionally render its "blame" output incrementally (this
|
||||
requires JavaScript on the client side).
|
||||
|
||||
* Author names shown in gitweb output are links to search commits by the
|
||||
author.
|
||||
|
||||
|
||||
(developers)
|
||||
|
||||
Fixes since v1.6.5
|
||||
------------------
|
||||
|
||||
|
@ -43,6 +43,11 @@ unreleased) version of git, that is available from 'master'
|
||||
branch of the `git.git` repository.
|
||||
Documentation for older releases are available here:
|
||||
|
||||
* link:v1.6.6/git.html[documentation for release 1.6.6]
|
||||
|
||||
* release notes for
|
||||
link:RelNotes-1.6.6.txt[1.6.6].
|
||||
|
||||
* link:v1.6.5.7/git.html[documentation for release 1.6.5.7]
|
||||
|
||||
* release notes for
|
||||
|
@ -1,6 +1,52 @@
|
||||
hash API
|
||||
========
|
||||
|
||||
Talk about <hash.h>
|
||||
The hash API is a collection of simple hash table functions. Users are expected
|
||||
to implement their own hashing.
|
||||
|
||||
(Linus)
|
||||
Data Structures
|
||||
---------------
|
||||
|
||||
`struct hash_table`::
|
||||
|
||||
The hash table structure. The `array` member points to the hash table
|
||||
entries. The `size` member counts the total number of valid and invalid
|
||||
entries in the table. The `nr` member keeps track of the number of
|
||||
valid entries.
|
||||
|
||||
`struct hash_table_entry`::
|
||||
|
||||
An opaque structure representing an entry in the hash table. The `hash`
|
||||
member is the entry's hash key and the `ptr` member is the entry's
|
||||
value.
|
||||
|
||||
Functions
|
||||
---------
|
||||
|
||||
`init_hash`::
|
||||
|
||||
Initialize the hash table.
|
||||
|
||||
`free_hash`::
|
||||
|
||||
Release memory associated with the hash table.
|
||||
|
||||
`insert_hash`::
|
||||
|
||||
Insert a pointer into the hash table. If an entry with that hash
|
||||
already exists, a pointer to the existing entry's value is returned.
|
||||
Otherwise NULL is returned. This allows callers to implement
|
||||
chaining, etc.
|
||||
|
||||
`lookup_hash`::
|
||||
|
||||
Lookup an entry in the hash table. If an entry with that hash exists
|
||||
the entry's value is returned. Otherwise NULL is returned.
|
||||
|
||||
`for_each_hash`::
|
||||
|
||||
Call a function for each entry in the hash table. The function is
|
||||
expected to take the entry's value as its only argument and return an
|
||||
int. If the function returns a negative int the loop is aborted
|
||||
immediately. Otherwise, the return value is accumulated and the sum
|
||||
returned upon completion of the loop.
|
||||
|
@ -12,7 +12,7 @@ strbuf API actually relies on the string being free of NULs.
|
||||
|
||||
strbufs has some invariants that are very important to keep in mind:
|
||||
|
||||
. The `buf` member is never NULL, so you it can be used in any usual C
|
||||
. The `buf` member is never NULL, so it can be used in any usual C
|
||||
string operations safely. strbuf's _have_ to be initialized either by
|
||||
`strbuf_init()` or by `= STRBUF_INIT` before the invariants, though.
|
||||
+
|
||||
@ -55,7 +55,7 @@ Data structures
|
||||
|
||||
* `struct strbuf`
|
||||
|
||||
This is string buffer structure. The `len` member can be used to
|
||||
This is the string buffer structure. The `len` member can be used to
|
||||
determine the current length of the string, and `buf` member provides access to
|
||||
the string itself.
|
||||
|
||||
@ -253,3 +253,9 @@ same behaviour as well.
|
||||
comments are considered contents to be removed or not.
|
||||
|
||||
`launch_editor`::
|
||||
|
||||
Launch the user preferred editor to edit a file and fill the buffer
|
||||
with the file's contents upon the user completing their editing. The
|
||||
third argument can be used to set the environment which the editor is
|
||||
run in. If the buffer is NULL the editor is launched as usual but the
|
||||
file's contents are not read into the buffer upon completion.
|
||||
|
@ -1,7 +1,7 @@
|
||||
#!/bin/sh
|
||||
|
||||
GVF=GIT-VERSION-FILE
|
||||
DEF_VER=v1.6.6-rc3.GIT
|
||||
DEF_VER=v1.6.6
|
||||
|
||||
LF='
|
||||
'
|
||||
|
@ -1305,6 +1305,7 @@ static void get_ac_line(const char *inbuf, const char *what,
|
||||
error_out:
|
||||
/* Ugh */
|
||||
*tz = "(unknown)";
|
||||
strcpy(person, *tz);
|
||||
strcpy(mail, *tz);
|
||||
*time = 0;
|
||||
return;
|
||||
@ -1314,20 +1315,26 @@ static void get_ac_line(const char *inbuf, const char *what,
|
||||
tmp = person;
|
||||
tmp += len;
|
||||
*tmp = 0;
|
||||
while (*tmp != ' ')
|
||||
while (person < tmp && *tmp != ' ')
|
||||
tmp--;
|
||||
if (tmp <= person)
|
||||
goto error_out;
|
||||
*tz = tmp+1;
|
||||
tzlen = (person+len)-(tmp+1);
|
||||
|
||||
*tmp = 0;
|
||||
while (*tmp != ' ')
|
||||
while (person < tmp && *tmp != ' ')
|
||||
tmp--;
|
||||
if (tmp <= person)
|
||||
goto error_out;
|
||||
*time = strtoul(tmp, NULL, 10);
|
||||
timepos = tmp;
|
||||
|
||||
*tmp = 0;
|
||||
while (*tmp != ' ')
|
||||
while (person < tmp && *tmp != ' ')
|
||||
tmp--;
|
||||
if (tmp <= person)
|
||||
return;
|
||||
mailpos = tmp + 1;
|
||||
*tmp = 0;
|
||||
maillen = timepos - tmp;
|
||||
|
@ -779,7 +779,7 @@ EOF
|
||||
|
||||
cp "$TODO" "$TODO".backup
|
||||
git_editor "$TODO" ||
|
||||
die "Could not execute editor"
|
||||
die_abort "Could not execute editor"
|
||||
|
||||
has_action "$TODO" ||
|
||||
die_abort "Nothing to do"
|
||||
|
281
git-svn.perl
281
git-svn.perl
@ -663,7 +663,8 @@ sub cmd_branch {
|
||||
}
|
||||
$head ||= 'HEAD';
|
||||
|
||||
my ($src, $rev, undef, $gs) = working_head_info($head);
|
||||
my (undef, $rev, undef, $gs) = working_head_info($head);
|
||||
my $src = $gs->full_url;
|
||||
|
||||
my $remote = Git::SVN::read_all_remotes()->{$gs->{repo_id}};
|
||||
my $allglobs = $remote->{ $_tag ? 'tags' : 'branches' };
|
||||
@ -1634,6 +1635,7 @@ use Carp qw/croak/;
|
||||
use File::Path qw/mkpath/;
|
||||
use File::Copy qw/copy/;
|
||||
use IPC::Open3;
|
||||
use Memoize; # core since 5.8.0, Jul 2002
|
||||
|
||||
my ($_gc_nr, $_gc_period);
|
||||
|
||||
@ -1741,7 +1743,11 @@ sub fetch_all {
|
||||
my $ra = Git::SVN::Ra->new($url);
|
||||
my $uuid = $ra->get_uuid;
|
||||
my $head = $ra->get_latest_revnum;
|
||||
$ra->get_log("", $head, 0, 1, 0, 1, sub { $head = $_[1] });
|
||||
|
||||
# ignore errors, $head revision may not even exist anymore
|
||||
eval { $ra->get_log("", $head, 0, 1, 0, 1, sub { $head = $_[1] }) };
|
||||
warn "W: $@\n" if $@;
|
||||
|
||||
my $base = defined $fetch ? $head : 0;
|
||||
|
||||
# read the max revs for wildcard expansion (branches/*, tags/*)
|
||||
@ -2446,12 +2452,6 @@ sub get_commit_parents {
|
||||
next if $seen{$p};
|
||||
$seen{$p} = 1;
|
||||
push @ret, $p;
|
||||
# MAXPARENT is defined to 16 in commit-tree.c:
|
||||
last if @ret >= 16;
|
||||
}
|
||||
if (@tmp) {
|
||||
die "r$log_entry->{revision}: No room for parents:\n\t",
|
||||
join("\n\t", @tmp), "\n";
|
||||
}
|
||||
@ret;
|
||||
}
|
||||
@ -2740,21 +2740,44 @@ sub do_fetch {
|
||||
|
||||
sub mkemptydirs {
|
||||
my ($self, $r) = @_;
|
||||
my %empty_dirs = ();
|
||||
|
||||
open my $fh, '<', "$self->{dir}/unhandled.log" or return;
|
||||
binmode $fh or croak "binmode: $!";
|
||||
while (<$fh>) {
|
||||
if (defined $r && /^r(\d+)$/) {
|
||||
last if $1 > $r;
|
||||
} elsif (/^ \+empty_dir: (.+)$/) {
|
||||
$empty_dirs{$1} = 1;
|
||||
} elsif (/^ \-empty_dir: (.+)$/) {
|
||||
my @d = grep {m[^\Q$1\E(/|$)]} (keys %empty_dirs);
|
||||
delete @empty_dirs{@d};
|
||||
sub scan {
|
||||
my ($r, $empty_dirs, $line) = @_;
|
||||
if (defined $r && $line =~ /^r(\d+)$/) {
|
||||
return 0 if $1 > $r;
|
||||
} elsif ($line =~ /^ \+empty_dir: (.+)$/) {
|
||||
$empty_dirs->{$1} = 1;
|
||||
} elsif ($line =~ /^ \-empty_dir: (.+)$/) {
|
||||
my @d = grep {m[^\Q$1\E(/|$)]} (keys %$empty_dirs);
|
||||
delete @$empty_dirs{@d};
|
||||
}
|
||||
1; # continue
|
||||
};
|
||||
|
||||
my %empty_dirs = ();
|
||||
my $gz_file = "$self->{dir}/unhandled.log.gz";
|
||||
if (-f $gz_file) {
|
||||
if (!$can_compress) {
|
||||
warn "Compress::Zlib could not be found; ",
|
||||
"empty directories in $gz_file will not be read\n";
|
||||
} else {
|
||||
my $gz = Compress::Zlib::gzopen($gz_file, "rb") or
|
||||
die "Unable to open $gz_file: $!\n";
|
||||
my $line;
|
||||
while ($gz->gzreadline($line) > 0) {
|
||||
scan($r, \%empty_dirs, $line) or last;
|
||||
}
|
||||
$gz->gzclose;
|
||||
}
|
||||
}
|
||||
close $fh;
|
||||
|
||||
if (open my $fh, '<', "$self->{dir}/unhandled.log") {
|
||||
binmode $fh or croak "binmode: $!";
|
||||
while (<$fh>) {
|
||||
scan($r, \%empty_dirs, $_) or last;
|
||||
}
|
||||
close $fh;
|
||||
}
|
||||
|
||||
my $strip = qr/\A\Q$self->{path}\E(?:\/|$)/;
|
||||
foreach my $d (sort keys %empty_dirs) {
|
||||
@ -2967,6 +2990,111 @@ sub find_extra_svk_parents {
|
||||
}
|
||||
}
|
||||
|
||||
sub lookup_svn_merge {
|
||||
my $uuid = shift;
|
||||
my $url = shift;
|
||||
my $merge = shift;
|
||||
|
||||
my ($source, $revs) = split ":", $merge;
|
||||
my $path = $source;
|
||||
$path =~ s{^/}{};
|
||||
my $gs = Git::SVN->find_by_url($url.$source, $url, $path);
|
||||
if ( !$gs ) {
|
||||
warn "Couldn't find revmap for $url$source\n";
|
||||
return;
|
||||
}
|
||||
my @ranges = split ",", $revs;
|
||||
my ($tip, $tip_commit);
|
||||
my @merged_commit_ranges;
|
||||
# find the tip
|
||||
for my $range ( @ranges ) {
|
||||
my ($bottom, $top) = split "-", $range;
|
||||
$top ||= $bottom;
|
||||
my $bottom_commit = $gs->find_rev_after( $bottom, 1, $top );
|
||||
my $top_commit = $gs->find_rev_before( $top, 1, $bottom );
|
||||
|
||||
unless ($top_commit and $bottom_commit) {
|
||||
warn "W:unknown path/rev in svn:mergeinfo "
|
||||
."dirprop: $source:$range\n";
|
||||
next;
|
||||
}
|
||||
|
||||
push @merged_commit_ranges,
|
||||
"$bottom_commit^..$top_commit";
|
||||
|
||||
if ( !defined $tip or $top > $tip ) {
|
||||
$tip = $top;
|
||||
$tip_commit = $top_commit;
|
||||
}
|
||||
}
|
||||
return ($tip_commit, @merged_commit_ranges);
|
||||
}
|
||||
|
||||
sub _rev_list {
|
||||
my ($msg_fh, $ctx) = command_output_pipe(
|
||||
"rev-list", @_,
|
||||
);
|
||||
my @rv;
|
||||
while ( <$msg_fh> ) {
|
||||
chomp;
|
||||
push @rv, $_;
|
||||
}
|
||||
command_close_pipe($msg_fh, $ctx);
|
||||
@rv;
|
||||
}
|
||||
|
||||
sub check_cherry_pick {
|
||||
my $base = shift;
|
||||
my $tip = shift;
|
||||
my @ranges = @_;
|
||||
my %commits = map { $_ => 1 }
|
||||
_rev_list("--no-merges", $tip, "--not", $base);
|
||||
for my $range ( @ranges ) {
|
||||
delete @commits{_rev_list($range)};
|
||||
}
|
||||
return (keys %commits);
|
||||
}
|
||||
|
||||
BEGIN {
|
||||
memoize 'lookup_svn_merge';
|
||||
memoize 'check_cherry_pick';
|
||||
}
|
||||
|
||||
sub parents_exclude {
|
||||
my $parents = shift;
|
||||
my @commits = @_;
|
||||
return unless @commits;
|
||||
|
||||
my @excluded;
|
||||
my $excluded;
|
||||
do {
|
||||
my @cmd = ('rev-list', "-1", @commits, "--not", @$parents );
|
||||
$excluded = command_oneline(@cmd);
|
||||
if ( $excluded ) {
|
||||
my @new;
|
||||
my $found;
|
||||
for my $commit ( @commits ) {
|
||||
if ( $commit eq $excluded ) {
|
||||
push @excluded, $commit;
|
||||
$found++;
|
||||
last;
|
||||
}
|
||||
else {
|
||||
push @new, $commit;
|
||||
}
|
||||
}
|
||||
die "saw commit '$excluded' in rev-list output, "
|
||||
."but we didn't ask for that commit (wanted: @commits --not @$parents)"
|
||||
unless $found;
|
||||
@commits = @new;
|
||||
}
|
||||
}
|
||||
while ($excluded and @commits);
|
||||
|
||||
return @excluded;
|
||||
}
|
||||
|
||||
|
||||
# note: this function should only be called if the various dirprops
|
||||
# have actually changed
|
||||
sub find_extra_svn_parents {
|
||||
@ -2979,82 +3107,73 @@ sub find_extra_svn_parents {
|
||||
# are now marked as merge, we can add the tip as a parent.
|
||||
my @merges = split "\n", $mergeinfo;
|
||||
my @merge_tips;
|
||||
my @merged_commit_ranges;
|
||||
my $url = $self->rewrite_root || $self->{url};
|
||||
my $uuid = $self->ra_uuid;
|
||||
my %ranges;
|
||||
for my $merge ( @merges ) {
|
||||
my ($source, $revs) = split ":", $merge;
|
||||
my $path = $source;
|
||||
$path =~ s{^/}{};
|
||||
my $gs = Git::SVN->find_by_url($url.$source, $url, $path);
|
||||
if ( !$gs ) {
|
||||
warn "Couldn't find revmap for $url$source\n";
|
||||
next;
|
||||
}
|
||||
my @ranges = split ",", $revs;
|
||||
my ($tip, $tip_commit);
|
||||
# find the tip
|
||||
for my $range ( @ranges ) {
|
||||
my ($bottom, $top) = split "-", $range;
|
||||
$top ||= $bottom;
|
||||
my $bottom_commit =
|
||||
$gs->rev_map_get($bottom, $self->ra_uuid) ||
|
||||
$gs->rev_map_get($bottom+1, $self->ra_uuid);
|
||||
my $top_commit;
|
||||
for (; !$top_commit && $top >= $bottom; --$top) {
|
||||
$top_commit =
|
||||
$gs->rev_map_get($top, $self->ra_uuid);
|
||||
}
|
||||
|
||||
unless ($top_commit and $bottom_commit) {
|
||||
warn "W:unknown path/rev in svn:mergeinfo "
|
||||
."dirprop: $source:$range\n";
|
||||
next;
|
||||
}
|
||||
|
||||
push @merged_commit_ranges,
|
||||
"$bottom_commit..$top_commit";
|
||||
|
||||
if ( !defined $tip or $top > $tip ) {
|
||||
$tip = $top;
|
||||
$tip_commit = $top_commit;
|
||||
}
|
||||
}
|
||||
my ($tip_commit, @ranges) =
|
||||
lookup_svn_merge( $uuid, $url, $merge );
|
||||
unless (!$tip_commit or
|
||||
grep { $_ eq $tip_commit } @$parents ) {
|
||||
push @merge_tips, $tip_commit;
|
||||
$ranges{$tip_commit} = \@ranges;
|
||||
} else {
|
||||
push @merge_tips, undef;
|
||||
}
|
||||
}
|
||||
|
||||
my %excluded = map { $_ => 1 }
|
||||
parents_exclude($parents, grep { defined } @merge_tips);
|
||||
|
||||
# check merge tips for new parents
|
||||
my @new_parents;
|
||||
for my $merge_tip ( @merge_tips ) {
|
||||
my $spec = shift @merges;
|
||||
next unless $merge_tip;
|
||||
my @cmd = ('rev-list', "-1", $merge_tip,
|
||||
"--not", @$parents );
|
||||
my ($msg_fh, $ctx) = command_output_pipe(@cmd);
|
||||
my $new;
|
||||
while ( <$msg_fh> ) {
|
||||
$new=1;last;
|
||||
next unless $merge_tip and $excluded{$merge_tip};
|
||||
|
||||
my $ranges = $ranges{$merge_tip};
|
||||
|
||||
# check out 'new' tips
|
||||
my $merge_base = command_oneline(
|
||||
"merge-base",
|
||||
@$parents, $merge_tip,
|
||||
);
|
||||
|
||||
# double check that there are no missing non-merge commits
|
||||
my (@incomplete) = check_cherry_pick(
|
||||
$merge_base, $merge_tip,
|
||||
@$ranges,
|
||||
);
|
||||
|
||||
if ( @incomplete ) {
|
||||
warn "W:svn cherry-pick ignored ($spec) - missing "
|
||||
.@incomplete." commit(s) (eg $incomplete[0])\n";
|
||||
} else {
|
||||
warn
|
||||
"Found merge parent (svn:mergeinfo prop): ",
|
||||
$merge_tip, "\n";
|
||||
push @new_parents, $merge_tip;
|
||||
}
|
||||
command_close_pipe($msg_fh, $ctx);
|
||||
if ( $new ) {
|
||||
push @cmd, @merged_commit_ranges;
|
||||
my ($msg_fh, $ctx) = command_output_pipe(@cmd);
|
||||
my $unmerged;
|
||||
while ( <$msg_fh> ) {
|
||||
$unmerged=1;last;
|
||||
}
|
||||
command_close_pipe($msg_fh, $ctx);
|
||||
if ( $unmerged ) {
|
||||
warn "W:svn cherry-pick ignored ($spec)\n";
|
||||
} else {
|
||||
warn
|
||||
"Found merge parent (svn:mergeinfo prop): ",
|
||||
$merge_tip, "\n";
|
||||
push @$parents, $merge_tip;
|
||||
}
|
||||
|
||||
# cater for merges which merge commits from multiple branches
|
||||
if ( @new_parents > 1 ) {
|
||||
for ( my $i = 0; $i <= $#new_parents; $i++ ) {
|
||||
for ( my $j = 0; $j <= $#new_parents; $j++ ) {
|
||||
next if $i == $j;
|
||||
next unless $new_parents[$i];
|
||||
next unless $new_parents[$j];
|
||||
my $revs = command_oneline(
|
||||
"rev-list", "-1",
|
||||
"$new_parents[$i]..$new_parents[$j]",
|
||||
);
|
||||
if ( !$revs ) {
|
||||
undef($new_parents[$i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
push @$parents, grep { defined } @new_parents;
|
||||
}
|
||||
|
||||
sub make_log_entry {
|
||||
|
@ -144,4 +144,17 @@ test_expect_success 'blame path that used to be a directory' '
|
||||
git blame HEAD^.. -- path
|
||||
'
|
||||
|
||||
test_expect_success 'blame to a commit with no author name' '
|
||||
TREE=`git rev-parse HEAD:`
|
||||
cat >badcommit <<EOF
|
||||
tree $TREE
|
||||
author <noname> 1234567890 +0000
|
||||
committer David Reiss <dreiss@facebook.com> 1234567890 +0000
|
||||
|
||||
some message
|
||||
EOF
|
||||
COMMIT=`git hash-object -t commit -w badcommit`
|
||||
git --no-pager blame $COMMIT -- uno >/dev/null
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -114,5 +114,29 @@ test_expect_success 'removed top-level directory does not exist' '
|
||||
test ! -e removed/d
|
||||
|
||||
'
|
||||
unhandled=.git/svn/refs/remotes/git-svn/unhandled.log
|
||||
test_expect_success 'git svn gc-ed files work' '
|
||||
(
|
||||
cd removed &&
|
||||
git svn gc &&
|
||||
: Compress::Zlib may not be available &&
|
||||
if test -f "$unhandled".gz
|
||||
then
|
||||
svn_cmd mkdir -m gz "$svnrepo"/gz &&
|
||||
git reset --hard $(git rev-list HEAD | tail -1) &&
|
||||
git svn rebase &&
|
||||
test -f "$unhandled".gz &&
|
||||
test -f "$unhandled" &&
|
||||
for i in a b c "weird file name" gz "! !"
|
||||
do
|
||||
if ! test -d "$i"
|
||||
then
|
||||
echo >&2 "$i does not exist"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
fi
|
||||
)
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -15,12 +15,27 @@ test_expect_success 'load svn dump' "
|
||||
git svn fetch --all
|
||||
"
|
||||
|
||||
test_expect_success 'represent svn merges without intervening commits' "
|
||||
[ `git cat-file commit HEAD^1 | grep parent | wc -l` -eq 2 ]
|
||||
"
|
||||
test_expect_success 'all svn merges became git merge commits' '
|
||||
unmarked=$(git rev-list --parents --all --grep=Merge |
|
||||
grep -v " .* " | cut -f1 -d" ")
|
||||
[ -z "$unmarked" ]
|
||||
'
|
||||
|
||||
test_expect_success 'represent svn merges with intervening commits' "
|
||||
[ `git cat-file commit HEAD | grep parent | wc -l` -eq 2 ]
|
||||
"
|
||||
test_expect_success 'cherry picks did not become git merge commits' '
|
||||
bad_cherries=$(git rev-list --parents --all --grep=Cherry |
|
||||
grep " .* " | cut -f1 -d" ")
|
||||
[ -z "$bad_cherries" ]
|
||||
'
|
||||
|
||||
test_expect_success 'svn non-merge merge commits did not become git merge commits' '
|
||||
bad_non_merges=$(git rev-list --parents --all --grep=non-merge |
|
||||
grep " .* " | cut -f1 -d" ")
|
||||
[ -z "$bad_non_merges" ]
|
||||
'
|
||||
|
||||
test_expect_success 'everything got merged in the end' '
|
||||
unmerged=$(git rev-list --all --not master)
|
||||
[ -z "$unmerged" ]
|
||||
'
|
||||
|
||||
test_done
|
||||
|
@ -11,93 +11,151 @@ mkdir foo.svn
|
||||
svnadmin create foo.svn
|
||||
svn co file://`pwd`/foo.svn foo
|
||||
|
||||
commit() {
|
||||
i=$(( $1 + 1 ))
|
||||
shift;
|
||||
svn commit -m "(r$i) $*" >/dev/null || exit 1
|
||||
echo $i
|
||||
}
|
||||
|
||||
say() {
|
||||
echo "[1m * $*[0m"
|
||||
}
|
||||
|
||||
i=0
|
||||
cd foo
|
||||
mkdir trunk
|
||||
mkdir branches
|
||||
svn add trunk branches
|
||||
svn commit -m "Setup trunk and branches"
|
||||
cd trunk
|
||||
i=$(commit $i "Setup trunk and branches")
|
||||
|
||||
git cat-file blob 6683463e:Makefile > Makefile
|
||||
svn add Makefile
|
||||
git cat-file blob 6683463e:Makefile > trunk/Makefile
|
||||
svn add trunk/Makefile
|
||||
|
||||
echo "Committing ANCESTOR"
|
||||
svn commit -m "ancestor"
|
||||
cd ..
|
||||
say "Committing ANCESTOR"
|
||||
i=$(commit $i "ancestor")
|
||||
svn cp trunk branches/left
|
||||
|
||||
echo "Committing BRANCH POINT"
|
||||
svn commit -m "make left branch"
|
||||
say "Committing BRANCH POINT"
|
||||
i=$(commit $i "make left branch")
|
||||
svn cp trunk branches/right
|
||||
|
||||
echo "Committing other BRANCH POINT"
|
||||
svn commit -m "make right branch"
|
||||
cd branches/left/
|
||||
say "Committing other BRANCH POINT"
|
||||
i=$(commit $i "make right branch")
|
||||
|
||||
#$sm init
|
||||
#svn commit -m "init svnmerge"
|
||||
say "Committing LEFT UPDATE"
|
||||
git cat-file blob 5873b67e:Makefile > branches/left/Makefile
|
||||
i=$(commit $i "left update 1")
|
||||
|
||||
git cat-file blob 5873b67e:Makefile > Makefile
|
||||
echo "Committing BRANCH UPDATE 1"
|
||||
svn commit -m "left update 1"
|
||||
cd ../..
|
||||
git cat-file blob 75118b13:Makefile > branches/right/Makefile
|
||||
say "Committing RIGHT UPDATE"
|
||||
pre_right_update_1=$i
|
||||
i=$(commit $i "right update 1")
|
||||
|
||||
cd trunk
|
||||
git cat-file blob 75118b13:Makefile > Makefile
|
||||
echo "Committing TRUNK UPDATE"
|
||||
svn commit -m "trunk update"
|
||||
say "Making more commits on LEFT"
|
||||
git cat-file blob ff5ebe39:Makefile > branches/left/Makefile
|
||||
i=$(commit $i "left update 2")
|
||||
git cat-file blob b5039db6:Makefile > branches/left/Makefile
|
||||
i=$(commit $i "left update 3")
|
||||
|
||||
cd ../branches/left
|
||||
git cat-file blob ff5ebe39:Makefile > Makefile
|
||||
echo "Committing BRANCH UPDATE 2"
|
||||
svn commit -m "left update 2"
|
||||
say "Making a LEFT SUB-BRANCH"
|
||||
svn cp branches/left branches/left-sub
|
||||
sub_left_make=$i
|
||||
i=$(commit $i "make left sub-branch")
|
||||
|
||||
git cat-file blob b5039db6:Makefile > Makefile
|
||||
echo "Committing BRANCH UPDATE 3"
|
||||
svn commit -m "left update 3"
|
||||
say "Making a commit on LEFT SUB-BRANCH"
|
||||
echo "crunch" > branches/left-sub/README
|
||||
svn add branches/left-sub/README
|
||||
i=$(commit $i "left sub-branch update 1")
|
||||
|
||||
# merge to trunk
|
||||
|
||||
cd ../..
|
||||
say "Merging LEFT to TRUNK"
|
||||
svn update
|
||||
cd trunk
|
||||
|
||||
svn merge ../branches/left --accept postpone
|
||||
|
||||
git cat-file blob b51ad431:Makefile > Makefile
|
||||
|
||||
svn resolved Makefile
|
||||
|
||||
svn commit -m "Merge trunk 1"
|
||||
|
||||
# create commits on both branches
|
||||
|
||||
cd ../branches/left
|
||||
git cat-file blob ff5ebe39:Makefile > Makefile
|
||||
echo "Committing BRANCH UPDATE 4"
|
||||
svn commit -m "left update 4"
|
||||
|
||||
cd ../right
|
||||
git cat-file blob b5039db6:Makefile > Makefile
|
||||
echo "Committing other BRANCH UPDATE 1"
|
||||
svn commit -m "right update 1"
|
||||
svn resolved Makefile
|
||||
i=$(commit $i "Merge left to trunk 1")
|
||||
cd ..
|
||||
|
||||
# merge to trun again
|
||||
say "Making more commits on LEFT and RIGHT"
|
||||
echo "touche" > branches/left/zlonk
|
||||
svn add branches/left/zlonk
|
||||
i=$(commit $i "left update 4")
|
||||
echo "thwacke" > branches/right/bang
|
||||
svn add branches/right/bang
|
||||
i=$(commit $i "right update 2")
|
||||
|
||||
cd ../..
|
||||
say "Squash merge of RIGHT tip 2 commits onto TRUNK"
|
||||
svn update
|
||||
cd trunk
|
||||
svn merge -r$pre_right_update_1:$i ../branches/right
|
||||
i=$(commit $i "Cherry-pick right 2 commits to trunk")
|
||||
cd ..
|
||||
|
||||
svn merge ../branches/left --accept postpone
|
||||
|
||||
say "Merging RIGHT to TRUNK"
|
||||
svn update
|
||||
cd trunk
|
||||
svn merge ../branches/right --accept postpone
|
||||
git cat-file blob b51ad431:Makefile > Makefile
|
||||
|
||||
svn resolved Makefile
|
||||
i=$(commit $i "Merge right to trunk 1")
|
||||
cd ..
|
||||
|
||||
svn commit -m "Merge trunk 2"
|
||||
say "Making more commits on RIGHT and TRUNK"
|
||||
echo "whamm" > branches/right/urkkk
|
||||
svn add branches/right/urkkk
|
||||
i=$(commit $i "right update 3")
|
||||
echo "pow" > trunk/vronk
|
||||
svn add trunk/vronk
|
||||
i=$(commit $i "trunk update 1")
|
||||
|
||||
say "Merging RIGHT to LEFT SUB-BRANCH"
|
||||
svn update
|
||||
cd branches/left-sub
|
||||
svn merge ../right --accept postpone
|
||||
git cat-file blob b51ad431:Makefile > Makefile
|
||||
svn resolved Makefile
|
||||
i=$(commit $i "Merge right to left sub-branch")
|
||||
cd ../..
|
||||
|
||||
say "Making more commits on LEFT SUB-BRANCH and LEFT"
|
||||
echo "zowie" > branches/left-sub/wham_eth
|
||||
svn add branches/left-sub/wham_eth
|
||||
pre_sub_left_update_2=$i
|
||||
i=$(commit $i "left sub-branch update 2")
|
||||
sub_left_update_2=$i
|
||||
echo "eee_yow" > branches/left/glurpp
|
||||
svn add branches/left/glurpp
|
||||
i=$(commit $i "left update 5")
|
||||
|
||||
say "Cherry pick LEFT SUB-BRANCH commit to LEFT"
|
||||
svn update
|
||||
cd branches/left
|
||||
svn merge -r$pre_sub_left_update_2:$sub_left_update_2 ../left-sub
|
||||
i=$(commit $i "Cherry-pick left sub-branch commit to left")
|
||||
cd ../..
|
||||
|
||||
say "Merging LEFT SUB-BRANCH back to LEFT"
|
||||
svn update
|
||||
cd branches/left
|
||||
# it's only a merge because the previous merge cherry-picked the top commit
|
||||
svn merge -r$sub_left_make:$sub_left_update_2 ../left-sub --accept postpone
|
||||
i=$(commit $i "Merge left sub-branch to left")
|
||||
cd ../..
|
||||
|
||||
say "Merging EVERYTHING to TRUNK"
|
||||
svn update
|
||||
cd trunk
|
||||
svn merge ../branches/left --accept postpone
|
||||
svn resolved bang
|
||||
i=$(commit $i "Merge left to trunk 2")
|
||||
# this merge, svn happily updates the mergeinfo, but there is actually
|
||||
# nothing to merge. git-svn will not make a meaningless merge commit.
|
||||
svn merge ../branches/right --accept postpone
|
||||
i=$(commit $i "non-merge right to trunk 2")
|
||||
cd ..
|
||||
|
||||
cd ..
|
||||
svnadmin dump foo.svn > svn-mergeinfo.dump
|
||||
|
||||
rm -rf foo foo.svn
|
||||
|
File diff suppressed because it is too large
Load Diff
40
t/t9152-svn-empty-dirs-after-gc.sh
Executable file
40
t/t9152-svn-empty-dirs-after-gc.sh
Executable file
@ -0,0 +1,40 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
# Copyright (c) 2009 Robert Zeh
|
||||
|
||||
test_description='git svn creates empty directories, calls git gc, makes sure they are still empty'
|
||||
. ./lib-git-svn.sh
|
||||
|
||||
test_expect_success 'initialize repo' '
|
||||
for i in a b c d d/e d/e/f "weird file name"
|
||||
do
|
||||
svn_cmd mkdir -m "mkdir $i" "$svnrepo"/"$i"
|
||||
done
|
||||
'
|
||||
|
||||
test_expect_success 'clone' 'git svn clone "$svnrepo" cloned'
|
||||
|
||||
test_expect_success 'git svn gc runs' '
|
||||
(
|
||||
cd cloned &&
|
||||
git svn gc
|
||||
)
|
||||
'
|
||||
|
||||
test_expect_success 'git svn mkdirs recreates empty directories after git svn gc' '
|
||||
(
|
||||
cd cloned &&
|
||||
rm -r * &&
|
||||
git svn mkdirs &&
|
||||
for i in a b c d d/e d/e/f "weird file name"
|
||||
do
|
||||
if ! test -d "$i"
|
||||
then
|
||||
echo >&2 "$i does not exist"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
)
|
||||
'
|
||||
|
||||
test_done
|
Reference in New Issue
Block a user