Hi Junio, Thank you for a thorough review and good suggestions. New cumulative patch is pasted and attached. >From: Junio C Hamano <gitster@xxxxxxxxx> > ... >> +# Given an SVN revision (string), returns all corresponding GIT revisions. >> +# >> +# Note that it is possible that one SVN revision needs to be split into two or >> +# more GIT commits (revision). For example, this will happen if SVN user >> +# commits two branches at once. >> +sub svnrev_to_gitrevs($) >> ... >> + my $svnrev = shift; >> + my @gitrevs; >> + for my $b (keys(%branches)) { >> + push (@gitrevs, $branches{$b}{$svnrev}) >> + if defined($branches{$b}{$svnrev}); >> + } >> + return @gitrevs; >> +} > >Hmph. The computation cost for this is proportional to the >number of branches on the SVN side? Would that be a problem in >real-life (not an objection, but am just wondering. "Not a >problem, because..." is an acceptable answer). I chose not to add and maintain an inverted data structure in parallel to %branches for simplicity. Stas. >From b17c89b82441dc3c5dc3155acee560a1d7f0149d Mon Sep 17 00:00:00 2001 From: Stas Maximov <smaximov@xxxxxxxxx> Date: Mon, 25 Jun 2007 09:18:35 -0700 Subject: [PATCH] git-svnimport: added explicit merge graph option -G Allows explicit merge graph information to be provided. Each line of merge graph file must contain a pair of SVN revision numbers separated by space. The first number is child (merged to) SVN rev number and the second is the parent (merged from) SVN rev number. Comments can be started with '#' and continue to the end of line. Empty and space-only lines are allowed and will be ignored. Signed-off-by: Stas Maximov <smaximov@xxxxxxxxx> --- Documentation/git-svnimport.txt | 11 +++++- git-svnimport.perl | 74 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 81 insertions(+), 4 deletions(-) diff --git a/Documentation/git-svnimport.txt b/Documentation/git-svnimport.txt index e97d15e..c902b64 100644 --- a/Documentation/git-svnimport.txt +++ b/Documentation/git-svnimport.txt @@ -13,7 +13,8 @@ SYNOPSIS 'git-svnimport' [ -o <branch-for-HEAD> ] [ -h ] [ -v ] [ -d | -D ] [ -C <GIT_repository> ] [ -i ] [ -u ] [-l limit_rev] [ -b branch_subdir ] [ -T trunk_subdir ] [ -t tag_subdir ] - [ -s start_chg ] [ -m ] [ -r ] [ -M regex ] + [ -s start_chg ] [ -r ] + [ -m ] [ -M regex ] [-G merge_graph_file ] [ -I <ignorefile_name> ] [ -A <author_file> ] [ -R <repack_each_revs>] [ -P <path_from_trunk> ] <SVN_repository_URL> [ <path> ] @@ -102,6 +103,14 @@ repository without -A. regex. It can be used with -m to also see the default regexes. You must escape forward slashes. +-G <merge_graph_file>:: + Allows explicit merge graph information to be provided. Each line + of merge graph file must contain a pair of SVN revision numbers + separated by space. The first number is child (merged to) SVN rev + number and the second is the parent (merged from) SVN rev number. + Comments can be started with '#' and continue to the end of line. + Empty and space-only lines are allowed and will be ignored. + -l <max_rev>:: Specify a maximum revision number to pull. + diff --git a/git-svnimport.perl b/git-svnimport.perl index b73d649..ea0bc90 100755 --- a/git-svnimport.perl +++ b/git-svnimport.perl @@ -32,7 +32,7 @@ $ENV{'TZ'}="UTC"; our($opt_h,$opt_o,$opt_v,$opt_u,$opt_C,$opt_i,$opt_m,$opt_M,$opt_t,$opt_T, $opt_b,$opt_r,$opt_I,$opt_A,$opt_s,$opt_l,$opt_d,$opt_D,$opt_S,$opt_F, - $opt_P,$opt_R); + $opt_P,$opt_R,$opt_G); sub usage() { print STDERR <<END; @@ -40,12 +40,13 @@ Usage: ${\basename $0} # fetch/update GIT from SVN [-o branch-for-HEAD] [-h] [-v] [-l max_rev] [-R repack_each_revs] [-C GIT_repository] [-t tagname] [-T trunkname] [-b branchname] [-d|-D] [-i] [-u] [-r] [-I ignorefilename] [-s start_chg] - [-m] [-M regex] [-A author_file] [-S] [-F] [-P project_name] [SVN_URL] + [-m] [-M regex] [-G merge_graph_file] [-A author_file] + [-S] [-F] [-P project_name] [SVN_URL] END exit(1); } -getopts("A:b:C:dDFhiI:l:mM:o:rs:t:T:SP:R:uv") or usage(); +getopts("A:b:C:dDFhiI:l:mM:G:o:rs:t:T:SP:R:uv") or usage(); usage if $opt_h; my $tag_name = $opt_t || "tags"; @@ -80,6 +81,44 @@ if ($opt_M) { unshift (@mergerx, qr/$opt_M/); } + +# merge_graph will be used for finding all parent SVN revisions for a given SVN +# revision. It will be implemented as a hash of arrays. Hash will be keyed with +# the child SVN rev and contain an array of the parent SVN revisions. +our %merge_graph; + +# read-in the explicit merge graph specified with -G option +if ($opt_G) { + open F, '<', $opt_G + or die("Cannot open '$opt_G'"); + while (<F>) { + chomp; + s/#.*//; + next if (/^\s*$/); + if (/^\s*(\d+)\s+(\d+)\s*$/) { + # $1: child_rev, $2: $parent_rev + $merge_graph{$1} ||= []; + push @{$merge_graph{$1}}, $2; + } else { + die "$opt_G:$. :malformed input $_\n"; + } + } + close(F); +} + + +# Given an SVN revision (string), finds all its parent SVN revisions in the +# merge graph. +sub merge_graph_get_parents { + my $child_svnrev = shift; + if (exists $merge_graph{$child_svnrev}) { + return @{$merge_graph{$child_svnrev}}; + } + return (); +} + + + # Absolutize filename now, since we will have chdir'ed by the time we # get around to opening it. $opt_A = File::Spec->rel2abs($opt_A) if $opt_A; @@ -356,6 +395,23 @@ if ($opt_A) { open BRANCHES,">>", "$git_dir/svn2git"; + +# Given an SVN revision (string), returns all corresponding GIT revisions. +# +# Note that it is possible that one SVN revision needs to be split into two or +# more GIT commits (revision). For example, this will happen if SVN user +# commits two branches at once. +sub svnrev_to_gitrevs($) { + my $svnrev = shift; + my @gitrevs; + for my $b (keys(%branches)) { + push (@gitrevs, $branches{$b}{$svnrev}) + if defined($branches{$b}{$svnrev}); + } + return @gitrevs; +} + + sub node_kind($$) { my ($svnpath, $revision) = @_; my $pool=SVN::Pool->new; @@ -815,6 +871,18 @@ sub commit { } } } + + # add parents from explicit merge graph (-G) + { + my @svnpars = merge_graph_get_parents($revision); + foreach my $svnp (@svnpars) { + my @gitpars = svnrev_to_gitrevs($svnp); + foreach my $gitp (@gitpars) { + push (@parents, $gitp); + } + } + } + my %seen_parents = (); my @unique_parents = grep { ! $seen_parents{$_} ++ } @parents; foreach my $bparent (@unique_parents) { -- 1.5.1.3
Attachment:
0001-git-svnimport-added-explicit-merge-graph-option-G.patch
Description: Binary data