contrib/git-svn: fix svn compat and fetch args
'svn info' doesn't work with URLs in svn <= 1.1. Now we only run svn info in local directories. As a side effect, this should also work better for 'init' off directories that are no longer in the latest revision of the repository. svn checkout -r<revision> arguments are fixed. Newer versions of svn (1.2.x) seem to need URL@REV as well as -rREV to checkout a particular revision... Add an example in the manpage of how to track directory that has been moved since its initial revision. A huge thanks to Yann Dirson for the bug reporting and testing my original patch. Thanks also to Junio C Hamano for suggesting a safer way to use git-rev-parse. Signed-off-by: Eric Wong <normalperson@yhbt.net> Signed-off-by: Junio C Hamano <junkio@cox.net>
This commit is contained in:
parent
d2c4af7373
commit
1d52aba839
@ -30,6 +30,7 @@ my $sha1_short = qr/[a-f\d]{4,40}/;
|
||||
my ($_revision,$_stdin,$_no_ignore_ext,$_no_stop_copy,$_help,$_rmdir,$_edit,
|
||||
$_find_copies_harder, $_l, $_version, $_upgrade, $_authors);
|
||||
my (@_branch_from, %tree_map, %users);
|
||||
my $_svn_co_url_revs;
|
||||
|
||||
my %fc_opts = ( 'no-ignore-externals' => \$_no_ignore_ext,
|
||||
'branch|b=s' => \@_branch_from,
|
||||
@ -77,7 +78,7 @@ usage(0) if $_help;
|
||||
version() if $_version;
|
||||
usage(1) unless defined $cmd;
|
||||
load_authors() if $_authors;
|
||||
svn_check_ignore_externals();
|
||||
svn_compat_check();
|
||||
$cmd{$cmd}->[0]->(@ARGV);
|
||||
exit 0;
|
||||
|
||||
@ -162,7 +163,8 @@ sub rebuild {
|
||||
croak "SVN repository location required: $url\n";
|
||||
}
|
||||
$SVN_URL ||= $url;
|
||||
$SVN_UUID ||= setup_git_svn();
|
||||
$SVN_UUID ||= $uuid;
|
||||
setup_git_svn();
|
||||
$latest = $rev;
|
||||
}
|
||||
assert_revision_eq_or_unknown($rev, $c);
|
||||
@ -171,9 +173,7 @@ sub rebuild {
|
||||
}
|
||||
close $rev_list or croak $?;
|
||||
if (!chdir $SVN_WC) {
|
||||
my @svn_co = ('svn','co',"-r$latest");
|
||||
push @svn_co, '--ignore-externals' unless $_no_ignore_ext;
|
||||
sys(@svn_co, $SVN_URL, $SVN_WC);
|
||||
svn_cmd_checkout($SVN_URL, $latest, $SVN_WC);
|
||||
chdir $SVN_WC or croak $!;
|
||||
}
|
||||
|
||||
@ -222,14 +222,14 @@ sub fetch {
|
||||
my $base = shift @$svn_log or croak "No base revision!\n";
|
||||
my $last_commit = undef;
|
||||
unless (-d $SVN_WC) {
|
||||
my @svn_co = ('svn','co',"-r$base->{revision}");
|
||||
push @svn_co,'--ignore-externals' unless $_no_ignore_ext;
|
||||
sys(@svn_co, $SVN_URL, $SVN_WC);
|
||||
svn_cmd_checkout($SVN_URL,$base->{revision},$SVN_WC);
|
||||
chdir $SVN_WC or croak $!;
|
||||
read_uuid();
|
||||
$last_commit = git_commit($base, @parents);
|
||||
assert_svn_wc_clean($base->{revision}, $last_commit);
|
||||
} else {
|
||||
chdir $SVN_WC or croak $!;
|
||||
read_uuid();
|
||||
$last_commit = file_to_s("$REV_DIR/$base->{revision}");
|
||||
}
|
||||
my @svn_up = qw(svn up);
|
||||
@ -275,7 +275,9 @@ sub commit {
|
||||
|
||||
fetch();
|
||||
chdir $SVN_WC or croak $!;
|
||||
my $svn_current_rev = svn_info('.')->{'Last Changed Rev'};
|
||||
my $info = svn_info('.');
|
||||
read_uuid($info);
|
||||
my $svn_current_rev = $info->{'Last Changed Rev'};
|
||||
foreach my $c (@revs) {
|
||||
my $mods = svn_checkout_tree($svn_current_rev, $c);
|
||||
if (scalar @$mods == 0) {
|
||||
@ -314,6 +316,14 @@ sub show_ignore {
|
||||
|
||||
########################### utility functions #########################
|
||||
|
||||
sub read_uuid {
|
||||
return if $SVN_UUID;
|
||||
my $info = shift || svn_info('.');
|
||||
$SVN_UUID = $info->{'Repository UUID'} or
|
||||
croak "Repository UUID unreadable\n";
|
||||
s_to_file($SVN_UUID,"$GIT_DIR/$GIT_SVN/info/uuid");
|
||||
}
|
||||
|
||||
sub setup_git_svn {
|
||||
defined $SVN_URL or croak "SVN repository location required\n";
|
||||
unless (-d $GIT_DIR) {
|
||||
@ -323,14 +333,10 @@ sub setup_git_svn {
|
||||
mkpath(["$GIT_DIR/$GIT_SVN/info"]);
|
||||
mkpath([$REV_DIR]);
|
||||
s_to_file($SVN_URL,"$GIT_DIR/$GIT_SVN/info/url");
|
||||
$SVN_UUID = svn_info($SVN_URL)->{'Repository UUID'} or
|
||||
croak "Repository UUID unreadable\n";
|
||||
s_to_file($SVN_UUID,"$GIT_DIR/$GIT_SVN/info/uuid");
|
||||
|
||||
open my $fd, '>>', "$GIT_DIR/$GIT_SVN/info/exclude" or croak $!;
|
||||
print $fd '.svn',"\n";
|
||||
close $fd or croak $!;
|
||||
return $SVN_UUID;
|
||||
}
|
||||
|
||||
sub assert_svn_wc_clean {
|
||||
@ -860,7 +866,6 @@ sub git_commit {
|
||||
my ($log_msg, @parents) = @_;
|
||||
assert_revision_unknown($log_msg->{revision});
|
||||
my $out_fh = IO::File->new_tmpfile or croak $!;
|
||||
$SVN_UUID ||= svn_info('.')->{'Repository UUID'};
|
||||
|
||||
map_tree_joins() if (@_branch_from && !%tree_map);
|
||||
|
||||
@ -922,7 +927,16 @@ sub git_commit {
|
||||
}
|
||||
my @update_ref = ('git-update-ref',"refs/remotes/$GIT_SVN",$commit);
|
||||
if (my $primary_parent = shift @exec_parents) {
|
||||
push @update_ref, $primary_parent;
|
||||
$pid = fork;
|
||||
defined $pid or croak $!;
|
||||
if (!$pid) {
|
||||
close STDERR;
|
||||
close STDOUT;
|
||||
exec 'git-rev-parse','--verify',
|
||||
"refs/remotes/$GIT_SVN^0";
|
||||
}
|
||||
waitpid $pid, 0;
|
||||
push @update_ref, $primary_parent unless $?;
|
||||
}
|
||||
sys(@update_ref);
|
||||
sys('git-update-ref',"$GIT_SVN/revs/$log_msg->{revision}",$commit);
|
||||
@ -995,13 +1009,26 @@ sub safe_qx {
|
||||
return wantarray ? @ret : join('',@ret);
|
||||
}
|
||||
|
||||
sub svn_check_ignore_externals {
|
||||
return if $_no_ignore_ext;
|
||||
unless (grep /ignore-externals/,(safe_qx(qw(svn co -h)))) {
|
||||
sub svn_compat_check {
|
||||
my @co_help = safe_qx(qw(svn co -h));
|
||||
unless (grep /ignore-externals/,@co_help) {
|
||||
print STDERR "W: Installed svn version does not support ",
|
||||
"--ignore-externals\n";
|
||||
$_no_ignore_ext = 1;
|
||||
}
|
||||
if (grep /usage: checkout URL\[\@REV\]/,@co_help) {
|
||||
$_svn_co_url_revs = 1;
|
||||
}
|
||||
}
|
||||
|
||||
# *sigh*, new versions of svn won't honor -r<rev> without URL@<rev>,
|
||||
# (and they won't honor URL@<rev> without -r<rev>, too!)
|
||||
sub svn_cmd_checkout {
|
||||
my ($url, $rev, $dir) = @_;
|
||||
my @cmd = ('svn','co', "-r$rev");
|
||||
push @cmd, '--ignore-externals' unless $_no_ignore_ext;
|
||||
$url .= "\@$rev" if $_svn_co_url_revs;
|
||||
sys(@cmd, $url, $dir);
|
||||
}
|
||||
|
||||
sub check_upgrade_needed {
|
||||
|
@ -175,8 +175,8 @@ COMPATIBILITY OPTIONS
|
||||
Do not use this flag unless you know exactly what you're getting
|
||||
yourself into. You have been warned.
|
||||
|
||||
Examples
|
||||
~~~~~~~~
|
||||
Basic Examples
|
||||
~~~~~~~~~~~~~~
|
||||
|
||||
Tracking and contributing to an Subversion managed-project:
|
||||
|
||||
@ -234,6 +234,34 @@ This allows you to tie unfetched SVN revision 375 to your current HEAD::
|
||||
|
||||
git-svn fetch 375=$(git-rev-parse HEAD)
|
||||
|
||||
Advanced Example: Tracking a Reorganized Repository
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
If you're tracking a directory that has moved, or otherwise been
|
||||
branched or tagged off of another directory in the repository and you
|
||||
care about the full history of the project, then you can read this
|
||||
section.
|
||||
|
||||
This is how Yann Dirson tracked the trunk of the ufoai directory when
|
||||
the /trunk directory of his repository was moved to /ufoai/trunk and
|
||||
he needed to continue tracking /ufoai/trunk where /trunk left off.
|
||||
|
||||
# This log message shows when the repository was reorganized::
|
||||
r166 | ydirson | 2006-03-02 01:36:55 +0100 (Thu, 02 Mar 2006) | 1 line
|
||||
Changed paths:
|
||||
D /trunk
|
||||
A /ufoai/trunk (from /trunk:165)
|
||||
|
||||
# First we start tracking the old revisions::
|
||||
GIT_SVN_ID=git-oldsvn git-svn init \
|
||||
https://svn.sourceforge.net/svnroot/ufoai/trunk
|
||||
GIT_SVN_ID=git-oldsvn git-svn fetch -r1:165
|
||||
|
||||
# And now, we continue tracking the new revisions::
|
||||
GIT_SVN_ID=git-newsvn git-svn init \
|
||||
https://svn.sourceforge.net/svnroot/ufoai/ufoai/trunk
|
||||
GIT_SVN_ID=git-newsvn git-svn fetch \
|
||||
166=`git-rev-parse refs/remotes/git-oldsvn`
|
||||
|
||||
BUGS
|
||||
----
|
||||
If somebody commits a conflicting changeset to SVN at a bad moment
|
||||
|
Loading…
Reference in New Issue
Block a user