{"thread":{"id":"6763","subject":"[PATCH] git-svn: re-map repository URLs and UUIDs on SVK mirror paths","startedAt":"2007-02-10T23:34:45Z","lastAt":"2007-02-14T05:18:21Z","messageCount":5,"participants":["Sam Vilain","Eric Wong"],"isPatch":true,"patchVersion":1,"patchTotal":null},"messages":[{"id":"34145","messageId":"20070210233750.A333013A384@magnus.utsl.gen.nz","threadId":"6763","inReplyTo":null,"subject":"[PATCH] git-svn: re-map repository URLs and UUIDs on SVK mirror paths","fromName":"Sam Vilain","fromEmail":"sam@vilain.net","sentAt":"2007-02-10T23:34:45Z","receivedAt":"2007-02-10T23:34:45Z","isPatch":true,"sender":{"key":"sam@vilain.net","avatar":"https://gravatar.com/avatar/8fc840ca854dbf6f7065b4335e3b934951c1dca3b11db688e95e471901f8f4a8?d=mp&s=160"},"body":"If an SVN revision has a property, \"svm:headrev\", it is likely that\nthe revision was created by SVN::Mirror (a part of SVK).  The property\ncontains a repository UUID and a revision.  We want to make it look\nlike we are mirroring the original URL, so introduce a helper function\nthat returns the original identity URL and UUID, and use it when\ngenerating commit messages.\n---\n git-svn.perl |   39 +++++++++++++++++++++++++++++++++------\n 1 files changed, 33 insertions(+), 6 deletions(-)\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex 59d9faf..5b0d8b7 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -1055,10 +1055,23 @@ sub do_git_commit {\n \tdefined(my $pid = open3(my $msg_fh, my $out_fh, '>&STDERR', @exec))\n \t                                                           or croak $!;\n \tprint $msg_fh $log_entry->{log} or croak $!;\n+\tmy $at = \"\";\n \tunless ($_no_metadata) {\n-\t\tprint $msg_fh \"\\ngit-svn-id: \", $self->full_url, '@',\n-\t\t              $log_entry->{revision}, ' ',\n-\t\t              $self->ra->uuid, \"\\n\" or croak $!;\n+\t\tmy $full_url = $self->full_url;\n+\t\tmy $revision = $log_entry->{revision};\n+\t\tmy $uuid = $self->ra->uuid;\n+\t\tmy $repo_id = $Git::SVN::default_repo_id;\n+\t\t$DB::single = 1;\n+\t\tif ( $log_entry->{headrev} ) {\n+\t\t\tmy ($from_uuid, $rev) = $log_entry->{headrev} =~ m{^([a-f0-9\\-]{30,}):(\\d+)$};\n+\t\t\t($full_url, $uuid) = get_svm_url( $repo_id, $full_url, $uuid );\n+\t\t\tdie \"UUID mismatch on SVM path : $uuid vs $from_uuid\"\n+\t\t\t\tif $from_uuid ne $uuid;\n+\t\t\t$revision = $rev;\n+\t\t\t$at = \" (\\@$rev)\";\n+\t\t}\n+\t\tprint $msg_fh \"\\ngit-svn-id: \", $full_url, '@',\n+\t\t              $revision, ' ', $uuid, \"\\n\" or croak $!;\n \t}\n \t$msg_fh->flush == 0 or croak $!;\n \tclose $msg_fh or croak $!;\n@@ -1074,7 +1087,7 @@ sub do_git_commit {\n \n \t$self->{last_rev} = $log_entry->{revision};\n \t$self->{last_commit} = $commit;\n-\tprint \"r$log_entry->{revision} = $commit ($self->{ref_id})\\n\";\n+\tprint \"r$log_entry->{revision}$at = $commit ($self->{ref_id})\\n\";\n \tif (defined $_repack && (--$_repack_nr == 0)) {\n \t\t$_repack_nr = $_repack;\n \t\t# repack doesn't use any arguments with spaces in them, does it?\n@@ -1284,8 +1297,9 @@ sub make_log_entry {\n \tmy $rp = $self->ra->rev_proplist($rev);\n \tforeach (sort keys %$rp) {\n \t\tmy $v = $rp->{$_};\n-\t\tif (/^svn:(author|date|log)$/) {\n-\t\t\t$log_entry{$1} = $v;\n+\t\t$DB::single = 1 if /svm:/;\n+\t\tif (/^(?:svn:(author|date|log)|svm:(headrev))$/) {\n+\t\t\t$log_entry{$1||$2} = $v;\n \t\t} else {\n \t\t\tprint $un \"  rev_prop: \", uri_encode($_), ' ',\n \t\t                  uri_encode($v), \"\\n\";\n@@ -1492,6 +1506,19 @@ sub uri_encode {\n \t$f\n }\n \n+our %svm_urls;\n+sub get_svm_url {\n+\tmy ($repo_id, $url, $uuid) = @_;\n+\tmy $spec = $url.\":\".$uuid;\n+\tif (!exists $svm_urls{$spec}) {\n+\t\tmy $source = `git-repo-config --get svn-remote.$repo_id.source`;\n+\t\tmy $svmuuid = `git-repo-config --get svn-remote.$repo_id.uuid`;\n+\t\tchomp for ($source, $svmuuid);\n+\t\t$svm_urls{$spec}=[$source,$svmuuid];\n+\t}\n+\t($url,$uuid) = @{$svm_urls{$spec}};\n+}\n+\n package Git::SVN::Prompt;\n use strict;\n use warnings;\n-- \n1.5.0.rc3.g3e023\n"},{"id":"34152","messageId":"20070211045518.GA20663@mayonaise.dyndns.org","threadId":"6763","inReplyTo":"20070210233750.A333013A384@magnus.utsl.gen.nz","subject":"Re: [PATCH] git-svn: re-map repository URLs and UUIDs on SVK mirror paths","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2007-02-11T04:55:18Z","receivedAt":"2007-02-11T04:55:18Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Note: these patches (both Sam's and mine below) are not meant for\nmaster, but the development/semi-rewrite version of git-svn at\nhttp://git.bogomips.org/git-svn.git\n\nSam: here's my take on your patches.  I'll add support for\nper-[svn-remote \"...\"] configuration that we talked about\non IRC in a separate patch.\n\n>From 45fd937a6129aebc9cad1b7128f2811dd32af454 Mon Sep 17 00:00:00 2001\nFrom: Eric Wong <normalperson@yhbt.net>\nDate: Sat, 10 Feb 2007 20:46:50 -0800\nSubject: [PATCH] git-svn: add support for SVN::Mirror/svk using revprops for metadata\n\nPass --use-svm-props or set the svn.usesvmprops key with git-config\nto enable using properties set by SVN::Mirror when it mirrored the\nupstream URL.\n\nThis is heavily based on work from Sam Vilain:\n> From: Sam Vilain <sam@vilain.net>\n> Date: Sun, 11 Feb 2007 12:34:45 +1300\n> Subject: [PATCH] git-svn: re-map repository URLs and UUIDs on SVK mirror paths\n>\n> If an SVN revision has a property, \"svm:headrev\", it is likely that\n> the revision was created by SVN::Mirror (a part of SVK).  The property\n> contains a repository UUID and a revision.  We want to make it look\n> like we are mirroring the original URL, so introduce a helper function\n> that returns the original identity URL and UUID, and use it when\n> generating commit messages.\n\nSigned-off-by: Eric Wong <normalperson@yhbt.net>\n---\n git-svn.perl |  115 +++++++++++++++++++++++++++++++++++++++++++++++++++++-----\n 1 files changed, 105 insertions(+), 10 deletions(-)\n\ndiff --git a/git-svn.perl b/git-svn.perl\nindex 7e1a655..23e1d42 100755\n--- a/git-svn.perl\n+++ b/git-svn.perl\n@@ -64,6 +64,7 @@ my %fc_opts = ( 'follow-parent|follow!' => \\$Git::SVN::_follow_parent,\n \t\t'authors-file|A=s' => \\$_authors,\n \t\t'repack:i' => \\$Git::SVN::_repack,\n \t\t'no-metadata' => \\$Git::SVN::_no_metadata,\n+\t\t'use-svm-props|svm-props' => \\$Git::SVN::_use_svm_props,\n \t\t'quiet|q' => \\$_q,\n \t\t'repack-flags|repack-args|repack-opts=s' =>\n \t\t   \\$Git::SVN::_repack_flags,\n@@ -645,7 +646,7 @@ package Git::SVN;\n use strict;\n use warnings;\n use vars qw/$default_repo_id $default_ref_id $_no_metadata $_follow_parent\n-            $_repack $_repack_flags/;\n+            $_repack $_repack_flags $_use_svm_props/;\n use Carp qw/croak/;\n use File::Path qw/mkpath/;\n use File::Copy qw/copy/;\n@@ -920,9 +921,54 @@ sub new {\n \n sub refname { \"refs/remotes/$_[0]->{ref_id}\" }\n \n+sub set_svm_vars {\n+\tmy ($self, $ra) = @_;\n+\tmy $section = \"svn-remote.$self->{repo_id}\";\n+\n+\t# see if we have it in our config, first:\n+\teval {\n+\t\t$self->{svm} = {\n+\t\t  source => $self->tmp_config('--get', \"$section.svm-source\"),\n+\t\t  uuid => $self->tmp_config('--get', \"$section.svm-uuid\"),\n+\t\t}\n+\t};\n+\treturn $ra if ($self->{svm}->{source} && $self->{svm}->{uuid});\n+\n+\t# nope, make sure we're connected to the repository root:\n+\tif ($ra->{repos_root} ne $self->{url}) {\n+\t\t$ra = Git::SVN::Ra->new($ra->{repos_root});\n+\t}\n+\tmy $r = $ra->get_latest_revnum;\n+\tmy ($props) = ($ra->get_dir('', $r))[2];\n+\tif (my $src = $props->{'svm:source'}) {\n+\t\t# don't know what a '!' is there for, also the\n+\t\t# username is of no interest\n+\t\t$src =~ s{!$}{};\n+\t\t$src =~ s{(^[a-z\\+]*://)[^/@]*@}{$1};\n+\t\t$self->tmp_config('--add', \"$section.svm-source\", $src);\n+\n+\t\tmy $uuid = $props->{'svm:uuid'};\n+\t\t$uuid =~ m{^[0-9a-f\\-]{30,}$}\n+\t\t    or die \"doesn't look right - svm:uuid is '$uuid'\\n\";\n+\t\t$self->tmp_config('--add', \"$section.svm-uuid\", $uuid);\n+\n+\t\t$self->{svm} = { source => $src , uuid => $uuid };\n+\t}\n+\tif ($ra->{repos_root} ne $self->{url}) {\n+\t\t$ra = Git::SVN::Ra->new($self->{url});\n+\t}\n+\t$ra;\n+}\n+\n sub ra {\n \tmy ($self) = shift;\n-\tGit::SVN::Ra->new($self->{url});\n+\tmy $ra = Git::SVN::Ra->new($self->{url});\n+\t$self->{-use_svm_props} = $Git::SVN::_use_svm_props;\n+\tif ($self->{-use_svm_props} && !$self->{svm}) {\n+\t\t$ra = $self->set_svm_vars($ra);\n+\t\t$self->{-want_revprops} = 1;\n+\t}\n+\t$ra;\n }\n \n sub rel_path {\n@@ -1006,16 +1052,44 @@ sub get_fetch_range {\n \t(++$min, $max);\n }\n \n+sub tmp_config {\n+\tmy ($self, @args) = @_;\n+\tunless (-f $self->{config}) {\n+\t\topen my $fh, '>', $self->{config} or\n+\t\t    die \"Can't open $self->{config}: $!\\n\";\n+\t\tprint $fh \"; This file is used internally by git-svn\\n\" or\n+\t\t      die \"Couldn't write to $self->{config}: $!\\n\";\n+\t\tprint $fh \"; You should not have to edit it\\n\" or\n+\t\t      die \"Couldn't write to $self->{config}: $!\\n\";\n+\t\tclose $fh or die \"Couldn't close $self->{config}: $!\\n\";\n+\t}\n+\tmy $old_config = $ENV{GIT_CONFIG};\n+\t$ENV{GIT_CONFIG} = $self->{config};\n+\t$@ = undef;\n+\tmy @ret = eval { command('config', @args) };\n+\tmy $err = $@;\n+\tif (defined $old_config) {\n+\t\t$ENV{GIT_CONFIG} = $old_config;\n+\t} else {\n+\t\tdelete $ENV{GIT_CONFIG};\n+\t}\n+\tdie $err if $err;\n+\twantarray ? @ret : $ret[0];\n+}\n+\n sub tmp_index_do {\n \tmy ($self, $sub) = @_;\n \tmy $old_index = $ENV{GIT_INDEX_FILE};\n \t$ENV{GIT_INDEX_FILE} = $self->{index};\n-\tmy @ret = &$sub;\n-\tif ($old_index) {\n+\t$@ = undef;\n+\tmy @ret = eval { &$sub };\n+\tmy $err = $@;\n+\tif (defined $old_index) {\n \t\t$ENV{GIT_INDEX_FILE} = $old_index;\n \t} else {\n \t\tdelete $ENV{GIT_INDEX_FILE};\n \t}\n+\tdie $err if $err;\n \twantarray ? @ret : $ret[0];\n }\n \n@@ -1105,9 +1179,8 @@ sub do_git_commit {\n \t                                                           or croak $!;\n \tprint $msg_fh $log_entry->{log} or croak $!;\n \tunless ($_no_metadata) {\n-\t\tprint $msg_fh \"\\ngit-svn-id: \", $self->full_url, '@',\n-\t\t              $log_entry->{revision}, ' ',\n-\t\t              $self->ra->uuid, \"\\n\" or croak $!;\n+\t\tprint $msg_fh \"\\ngit-svn-id: $log_entry->{metadata}\\n\"\n+\t\t              or croak $!;\n \t}\n \t$msg_fh->flush == 0 or croak $!;\n \tclose $msg_fh or croak $!;\n@@ -1123,7 +1196,11 @@ sub do_git_commit {\n \n \t$self->{last_rev} = $log_entry->{revision};\n \t$self->{last_commit} = $commit;\n-\tprint \"r$log_entry->{revision} = $commit ($self->{ref_id})\\n\";\n+\tprint \"r$log_entry->{revision}\";\n+\tif (defined $log_entry->{svm_revision}) {\n+\t\t print \" (\\@$log_entry->{svm_revision})\";\n+\t}\n+\tprint \" = $commit ($self->{ref_id})\\n\";\n \tif (defined $_repack && (--$_repack_nr == 0)) {\n \t\t$_repack_nr = $_repack;\n \t\t# repack doesn't use any arguments with spaces in them, does it?\n@@ -1351,13 +1428,16 @@ sub make_log_entry {\n \tmy %log_entry = ( parents => $parents || [], revision => $rev,\n \t                  log => '');\n \n+\tmy $headrev;\n \tmy $logged = delete $self->{logged_rev_props};\n-\tif (!$logged || $self->{-want_extra_revprops}) {\n+\tif (!$logged || $self->{-want_revprops}) {\n \t\tmy $rp = $self->ra->rev_proplist($rev);\n \t\tforeach (sort keys %$rp) {\n \t\t\tmy $v = $rp->{$_};\n \t\t\tif (/^svn:(author|date|log)$/) {\n \t\t\t\t$log_entry{$1} = $v;\n+\t\t\t} elsif ($_ eq 'svm:headrev') {\n+\t\t\t\t$headrev = $v;\n \t\t\t} else {\n \t\t\t\tprint $un \"  rev_prop: \", uri_encode($_), ' ',\n \t\t\t\t\t  uri_encode($v), \"\\n\";\n@@ -1371,6 +1451,21 @@ sub make_log_entry {\n \t$log_entry{date} = parse_svn_date($log_entry{date});\n \t$log_entry{author} = check_author($log_entry{author});\n \t$log_entry{log} .= \"\\n\";\n+\tif (defined $headrev && $self->{-use_svm_props}) {\n+\t\tmy ($uuid, $r) = $headrev =~ m{^([a-f\\d\\-]{30,}):(\\d+)$};\n+\t\tif ($uuid ne $self->{svm}->{uuid}) {\n+\t\t\tdie \"UUID mismatch on SVM path:\\n\",\n+\t\t\t    \"expected: $self->{svm}->{uuid}\\n\",\n+\t\t\t    \"     got: $uuid\\n\";\n+\t\t}\n+\t\tmy $full_url = $self->{svm}->{source};\n+\t\t$full_url .= \"/$self->{path}\" if length $self->{path};\n+\t\t$log_entry{metadata} = \"$full_url\\@$r $uuid\";\n+\t\t$log_entry{svm_revision} = $r;\n+\t} else {\n+\t\t$log_entry{metadata} = $self->full_url . \"\\@$rev \" .\n+\t\t                       $self->ra->uuid;\n+\t}\n \t\\%log_entry;\n }\n \n@@ -1549,7 +1644,7 @@ sub _new {\n \t\tclose $fh or croak $!;\n \t}\n \tbless { ref_id => $ref_id, dir => $dir, index => \"$dir/index\",\n-\t        path => $path,\n+\t        path => $path, config => \"$ENV{GIT_DIR}/svn/config\",\n \t        db_path => \"$dir/.rev_db\", repo_id => $repo_id }, $class;\n }\n \n-- \n1.5.0.rc4.104.g9cd7c\n\n\n-- \nEric Wong\n"},{"id":"34159","messageId":"20070211094114.GB19590@hand.yhbt.net","threadId":"6763","inReplyTo":"20070211045518.GA20663@mayonaise.dyndns.org","subject":"Re: [PATCH] git-svn: re-map repository URLs and UUIDs on SVK mirror paths","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2007-02-11T09:41:15Z","receivedAt":"2007-02-11T09:41:15Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Eric Wong <normalperson@yhbt.net> wrote:\n> Note: these patches (both Sam's and mine below) are not meant for\n> master, but the development/semi-rewrite version of git-svn at\n> http://git.bogomips.org/git-svn.git\n> \n> Sam: here's my take on your patches.  I'll add support for\n> per-[svn-remote \"...\"] configuration that we talked about\n> on IRC in a separate patch.\n\nI've added per-[svn-remote \"...\"] config support to my latest revision.\nI forgot to take into account the 'log' command breakage/inconsistency\nfrom using .rev_db with svn-remote.svn.useSvmProps, so the 'git svn log'\ncommand won't work well with -r.  I'll try to find time for that\ntomorrow.\n\n-- \nEric Wong\n"},{"id":"34471","messageId":"20070213222102.GA25092@localdomain","threadId":"6763","inReplyTo":"20070210233750.A333013A384@magnus.utsl.gen.nz","subject":"Re: [PATCH] git-svn: re-map repository URLs and UUIDs on SVK mirror paths","fromName":"Eric Wong","fromEmail":"normalperson@yhbt.net","sentAt":"2007-02-13T22:21:02Z","receivedAt":"2007-02-13T22:21:02Z","isPatch":true,"sender":{"key":"e@80x24.org","avatar":null},"body":"Sam Vilain <sam@vilain.net> wrote:\n> If an SVN revision has a property, \"svm:headrev\", it is likely that\n> the revision was created by SVN::Mirror (a part of SVK).  The property\n> contains a repository UUID and a revision.  We want to make it look\n> like we are mirroring the original URL, so introduce a helper function\n> that returns the original identity URL and UUID, and use it when\n> generating commit messages.\n\nIf somebody is using these options with git-svn and wants to dcommit,\nthey should only be committing to the svm:source repository and not to\nthe repository managed by SVN::Mirror, right?\n\n-- \nEric Wong\n"},{"id":"34497","messageId":"45D29B9D.5010701@vilain.net","threadId":"6763","inReplyTo":"20070213222102.GA25092@localdomain","subject":"Re: [PATCH] git-svn: re-map repository URLs and UUIDs on SVK mirror paths","fromName":"Sam Vilain","fromEmail":"sam@vilain.net","sentAt":"2007-02-14T05:18:21Z","receivedAt":"2007-02-14T05:18:21Z","isPatch":true,"sender":{"key":"sam@vilain.net","avatar":"https://gravatar.com/avatar/8fc840ca854dbf6f7065b4335e3b934951c1dca3b11db688e95e471901f8f4a8?d=mp&s=160"},"body":"Eric Wong wrote:\n>> If an SVN revision has a property, \"svm:headrev\", it is likely that\n>> the revision was created by SVN::Mirror (a part of SVK).  The property\n>> contains a repository UUID and a revision.  We want to make it look\n>> like we are mirroring the original URL, so introduce a helper function\n>> that returns the original identity URL and UUID, and use it when\n>> generating commit messages.\n>>     \n> If somebody is using these options with git-svn and wants to dcommit,\n> they should only be committing to the svm:source repository and not to\n> the repository managed by SVN::Mirror, right?\n\nYes. Only SVM::Mirror should write to paths below where svm:source and\nsvm:uuid are seen.\n\nSam.\n"}]}