git.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Stas Maximov <smaximov@yahoo.com>
To: Junio C Hamano <gitster@pobox.com>
Cc: git@vger.kernel.org
Subject: Re: [PATCH] git-svnimport: added explicit merge graph option -G
Date: Mon, 25 Jun 2007 09:23:55 -0700 (PDT)	[thread overview]
Message-ID: <961604.41519.qm@web43137.mail.sp1.yahoo.com> (raw)

[-- Attachment #1: Type: text/plain, Size: 6976 bytes --]

Hi Junio,

Thank you for a thorough review and good suggestions. New cumulative patch is pasted and attached. 

>From: Junio C Hamano <gitster@pobox.com>
> ...
>> +# 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@yahoo.com>
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@yahoo.com>
---
 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 #2: 0001-git-svnimport-added-explicit-merge-graph-option-G.patch --]
[-- Type: application/octet-stream, Size: 5760 bytes --]

From b17c89b82441dc3c5dc3155acee560a1d7f0149d Mon Sep 17 00:00:00 2001
From: Stas Maximov <smaximov@yahoo.com>
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@yahoo.com>
---
 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


             reply	other threads:[~2007-06-25 16:24 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-06-25 16:23 Stas Maximov [this message]
  -- strict thread matches above, loose matches on Subject: below --
2007-06-24 23:10 [PATCH] git-svnimport: added explicit merge graph option -G Stas Maximov
2007-06-25  7:05 ` Junio C Hamano
2007-06-24 21:48 Stas Maximov
2007-06-24 22:17 ` Junio C Hamano
2007-06-24  7:06 Junio C Hamano
2007-06-24  8:44 ` Peter Baumann
2007-06-24 17:27   ` Steven Grimm
2007-06-25  8:54   ` Peter Baumann
2007-06-24  9:32 ` Alex Riesen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=961604.41519.qm@web43137.mail.sp1.yahoo.com \
    --to=smaximov@yahoo.com \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).