git-svn: allow UUID to be manually remapped via rewriteUUID

In certain situations it may be necessary to manually remap an svn
repostitory UUID. For example:

                  o--- [git-svn clone]
                 /
[origin svn repo]
                 \
                  o--- [svnsync clone]

Imagine that only "git-svn clone" and "svnsync clone" are made available
to external users. Furthur, "git-svn clone" contains only trunk, and for
reasons unknown, "svnsync clone" is missing the revision properties that
normally provide the origin svn repo's UUID.

A git user who has cloned the "git-svn clone" repo now wishes to use
git-svn to pull in the missing branches from the "synsync clone" repo.
In order for git-svn to get the history correct for those branches,
it needs to know the origin svn repo's UUID. Hence rewriteUUID.

Signed-off-by: Jay Soffian <jaysoffian@gmail.com>
Acked-by: Eric Wong <normalperson@yhbt.net>
This commit is contained in:
Jay Soffian 2010-01-23 03:30:00 -05:00 committed by Eric Wong
parent c79f1189bc
commit 3e18ce1ac3
4 changed files with 140 additions and 8 deletions

View File

@ -62,6 +62,8 @@ COMMANDS
Set the 'useSvnsyncProps' option in the [svn-remote] config. Set the 'useSvnsyncProps' option in the [svn-remote] config.
--rewrite-root=<URL>;; --rewrite-root=<URL>;;
Set the 'rewriteRoot' option in the [svn-remote] config. Set the 'rewriteRoot' option in the [svn-remote] config.
--rewrite-uuid=<UUID>;;
Set the 'rewriteUUID' option in the [svn-remote] config.
--username=<USER>;; --username=<USER>;;
For transports that SVN handles authentication for (http, For transports that SVN handles authentication for (http,
https, and plain svn), specify the username. For other https, and plain svn), specify the username. For other
@ -629,6 +631,12 @@ svn-remote.<name>.rewriteRoot::
the repository with a public http:// or svn:// URL in the the repository with a public http:// or svn:// URL in the
metadata so users of it will see the public URL. metadata so users of it will see the public URL.
svn-remote.<name>.rewriteUUID::
Similar to the useSvmProps option; this is for users who need
to remap the UUID manually. This may be useful in situations
where the original UUID is not available via either useSvmProps
or useSvnsyncProps.
svn.brokenSymlinkWorkaround:: svn.brokenSymlinkWorkaround::
This disables potentially expensive checks to workaround This disables potentially expensive checks to workaround
broken symlinks checked into SVN by broken clients. Set this broken symlinks checked into SVN by broken clients. Set this
@ -638,13 +646,14 @@ svn.brokenSymlinkWorkaround::
revision fetched. If unset, 'git svn' assumes this option to revision fetched. If unset, 'git svn' assumes this option to
be "true". be "true".
Since the noMetadata, rewriteRoot, useSvnsyncProps and useSvmProps Since the noMetadata, rewriteRoot, rewriteUUID, useSvnsyncProps and useSvmProps
options all affect the metadata generated and used by 'git svn'; they options all affect the metadata generated and used by 'git svn'; they
*must* be set in the configuration file before any history is imported *must* be set in the configuration file before any history is imported
and these settings should never be changed once they are set. and these settings should never be changed once they are set.
Additionally, only one of these four options can be used per-svn-remote Additionally, only one of these options can be used per svn-remote
section because they affect the 'git-svn-id:' metadata line. section because they affect the 'git-svn-id:' metadata line, except
for rewriteRoot and rewriteUUID which can be used together.
BASIC EXAMPLES BASIC EXAMPLES

View File

@ -115,6 +115,7 @@ my %init_opts = ( 'template=s' => \$_template, 'shared:s' => \$_shared,
'use-svm-props' => sub { $icv{useSvmProps} = 1 }, 'use-svm-props' => sub { $icv{useSvmProps} = 1 },
'use-svnsync-props' => sub { $icv{useSvnsyncProps} = 1 }, 'use-svnsync-props' => sub { $icv{useSvnsyncProps} = 1 },
'rewrite-root=s' => sub { $icv{rewriteRoot} = $_[1] }, 'rewrite-root=s' => sub { $icv{rewriteRoot} = $_[1] },
'rewrite-uuid=s' => sub { $icv{rewriteUUID} = $_[1] },
%remote_opts ); %remote_opts );
my %cmt_opts = ( 'edit|e' => \$_edit, my %cmt_opts = ( 'edit|e' => \$_edit,
'rmdir' => \$SVN::Git::Editor::_rmdir, 'rmdir' => \$SVN::Git::Editor::_rmdir,
@ -2207,6 +2208,10 @@ sub svnsync {
die "Can't have both 'useSvnsyncProps' and 'rewriteRoot' ", die "Can't have both 'useSvnsyncProps' and 'rewriteRoot' ",
"options set!\n"; "options set!\n";
} }
if ($self->rewrite_uuid) {
die "Can't have both 'useSvnsyncProps' and 'rewriteUUID' ",
"options set!\n";
}
my $svnsync; my $svnsync;
# see if we have it in our config, first: # see if we have it in our config, first:
@ -2488,6 +2493,20 @@ sub rewrite_root {
$self->{-rewrite_root} = $rwr; $self->{-rewrite_root} = $rwr;
} }
sub rewrite_uuid {
my ($self) = @_;
return $self->{-rewrite_uuid} if exists $self->{-rewrite_uuid};
my $k = "svn-remote.$self->{repo_id}.rewriteUUID";
my $rwid = eval { command_oneline(qw/config --get/, $k) };
if ($rwid) {
$rwid =~ s#/+$##;
if ($rwid !~ m#^[a-f0-9]{8}-(?:[a-f0-9]{4}-){3}[a-f0-9]{12}$#) {
die "$rwid is not a valid UUID (key: $k)\n";
}
}
$self->{-rewrite_uuid} = $rwid;
}
sub metadata_url { sub metadata_url {
my ($self) = @_; my ($self) = @_;
($self->rewrite_root || $self->{url}) . ($self->rewrite_root || $self->{url}) .
@ -3306,6 +3325,10 @@ sub make_log_entry {
die "Can't have both 'useSvmProps' and 'rewriteRoot' ", die "Can't have both 'useSvmProps' and 'rewriteRoot' ",
"options set!\n"; "options set!\n";
} }
if ($self->rewrite_uuid) {
die "Can't have both 'useSvmProps' and 'rewriteUUID' ",
"options set!\n";
}
my ($uuid, $r) = $headrev =~ m{^([a-f\d\-]{30,}):(\d+)$}i; my ($uuid, $r) = $headrev =~ m{^([a-f\d\-]{30,}):(\d+)$}i;
# we don't want "SVM: initializing mirror for junk" ... # we don't want "SVM: initializing mirror for junk" ...
return undef if $r == 0; return undef if $r == 0;
@ -3336,10 +3359,10 @@ sub make_log_entry {
} else { } else {
my $url = $self->metadata_url; my $url = $self->metadata_url;
remove_username($url); remove_username($url);
$log_entry{metadata} = "$url\@$rev " . my $uuid = $self->rewrite_uuid || $self->ra->get_uuid;
$self->ra->get_uuid; $log_entry{metadata} = "$url\@$rev " . $uuid;
$email ||= "$author\@" . $self->ra->get_uuid; $email ||= "$author\@" . $uuid;
$commit_email ||= "$author\@" . $self->ra->get_uuid; $commit_email ||= "$author\@" . $uuid;
} }
$log_entry{name} = $name; $log_entry{name} = $name;
$log_entry{email} = $email; $log_entry{email} = $email;
@ -3421,7 +3444,7 @@ sub rebuild {
'--'); '--');
my $metadata_url = $self->metadata_url; my $metadata_url = $self->metadata_url;
remove_username($metadata_url); remove_username($metadata_url);
my $svn_uuid = $self->ra_uuid; my $svn_uuid = $self->rewrite_uuid || $self->ra_uuid;
my $c; my $c;
while (<$log>) { while (<$log>) {
if ( m{^commit ($::sha1)$} ) { if ( m{^commit ($::sha1)$} ) {

25
t/t9153-git-svn-rewrite-uuid.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/sh
#
# Copyright (c) 2010 Jay Soffian
#
test_description='git svn --rewrite-uuid test'
. ./lib-git-svn.sh
uuid=6cc8ada4-5932-4b4a-8242-3534ed8a3232
test_expect_success 'load svn repo' "
svnadmin load -q '$rawsvnrepo' < '$TEST_DIRECTORY/t9153/svn.dump' &&
git svn init --minimize-url --rewrite-uuid='$uuid' '$svnrepo' &&
git svn fetch
"
test_expect_success 'verify uuid' "
git cat-file commit refs/remotes/git-svn~0 | \
grep '^${git_svn_id}: .*@2 $uuid$' &&
git cat-file commit refs/remotes/git-svn~1 | \
grep '^${git_svn_id}: .*@1 $uuid$'
"
test_done

75
t/t9153/svn.dump Normal file
View File

@ -0,0 +1,75 @@
SVN-fs-dump-format-version: 2
UUID: b4885626-c94f-4a6c-b179-00c030fc68e8
Revision-number: 0
Prop-content-length: 56
Content-length: 56
K 8
svn:date
V 27
2010-01-23T06:41:03.908576Z
PROPS-END
Revision-number: 1
Prop-content-length: 109
Content-length: 109
K 7
svn:log
V 11
initial foo
K 10
svn:author
V 3
jay
K 8
svn:date
V 27
2010-01-23T06:41:48.353776Z
PROPS-END
Node-path: foo
Node-kind: file
Node-action: add
Prop-content-length: 10
Text-content-length: 4
Text-content-md5: d3b07384d113edec49eaa6238ad5ff00
Text-content-sha1: f1d2d2f924e986ac86fdf7b36c94bcdf32beec15
Content-length: 14
PROPS-END
foo
Revision-number: 2
Prop-content-length: 110
Content-length: 110
K 7
svn:log
V 12
now with bar
K 10
svn:author
V 3
jay
K 8
svn:date
V 27
2010-01-23T06:42:14.214640Z
PROPS-END
Node-path: foo
Node-kind: file
Node-action: change
Text-content-length: 8
Text-content-md5: f47c75614087a8dd938ba4acff252494
Text-content-sha1: 4e48e2c9a3d2ca8a708cb0cc545700544efb5021
Content-length: 8
foo
bar