]> git.ipfire.org Git - thirdparty/git.git/blobdiff - contrib/git-svn/git-svn.perl
git-svn: add the commit-diff command
[thirdparty/git.git] / contrib / git-svn / git-svn.perl
index be38f94170cacbc425b158e1a090ffa414460f10..4bdc9766cdd04cb8a62f437c71fa04b4738312d7 100755 (executable)
@@ -46,6 +46,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, $_cp_similarity, $_cp_remote,
        $_repack, $_repack_nr, $_repack_flags,
+       $_message, $_file,
        $_template, $_shared, $_no_default_regex, $_no_graft_copy,
        $_limit, $_verbose, $_incremental, $_oneline, $_l_fmt, $_show_commit,
        $_version, $_upgrade, $_authors, $_branch_all_refs, @_opt_m);
@@ -65,6 +66,12 @@ my %multi_opts = ( 'trunk|T=s' => \$_trunk,
                'tags|t=s' => \$_tags,
                'branches|b=s' => \$_branches );
 my %init_opts = ( 'template=s' => \$_template, 'shared' => \$_shared );
+my %cmt_opts = ( 'edit|e' => \$_edit,
+               'rmdir' => \$_rmdir,
+               'find-copies-harder' => \$_find_copies_harder,
+               'l=i' => \$_l,
+               'copy-similarity|C=i'=> \$_cp_similarity
+);
 
 # yes, 'native' sets "\n".  Patches to fix this for non-*nix systems welcome:
 my %EOL = ( CR => "\015", LF => "\012", CRLF => "\015\012", native => "\012" );
@@ -76,14 +83,7 @@ my %cmd = (
                          " (requires URL argument)",
                          \%init_opts ],
        commit => [ \&commit, "Commit git revisions to SVN",
-                       {       'stdin|' => \$_stdin,
-                               'edit|e' => \$_edit,
-                               'rmdir' => \$_rmdir,
-                               'find-copies-harder' => \$_find_copies_harder,
-                               'l=i' => \$_l,
-                               'copy-similarity|C=i'=> \$_cp_similarity,
-                               %fc_opts,
-                       } ],
+                       {       'stdin|' => \$_stdin, %cmt_opts, %fc_opts, } ],
        'show-ignore' => [ \&show_ignore, "Show svn:ignore listings",
                        { 'revision|r=i' => \$_revision } ],
        rebuild => [ \&rebuild, "Rebuild git-svn metadata (after git clone)",
@@ -112,6 +112,10 @@ my %cmd = (
                          'show-commit' => \$_show_commit,
                          'authors-file|A=s' => \$_authors,
                        } ],
+       'commit-diff' => [ \&commit_diff, 'Commit a diff between two trees',
+                       { 'message|m=s' => \$_message,
+                         'file|F=s' => \$_file,
+                       %cmt_opts } ],
 );
 
 my $cmd;
@@ -484,11 +488,7 @@ sub commit_lib {
        my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef, 0) : ();
        my $commit_msg = "$GIT_SVN_DIR/.svn-commit.tmp.$$";
 
-       if (defined $LC_ALL) {
-               $ENV{LC_ALL} = $LC_ALL;
-       } else {
-               delete $ENV{LC_ALL};
-       }
+       set_svn_commit_env();
        foreach my $c (@revs) {
                my $log_msg = get_commit_message($c, $commit_msg);
 
@@ -723,6 +723,55 @@ out:
        print '-' x72,"\n" unless $_incremental || $_oneline;
 }
 
+sub commit_diff_usage {
+       print STDERR "Usage: $0 commit-diff <tree-ish> <tree-ish> [<URL>]\n";
+       exit 1
+}
+
+sub commit_diff {
+       if (!$_use_lib) {
+               print STDERR "commit-diff must be used with SVN libraries\n";
+               exit 1;
+       }
+       my $ta = shift or commit_diff_usage();
+       my $tb = shift or commit_diff_usage();
+       if (!eval { $SVN_URL = shift || file_to_s("$GIT_SVN_DIR/info/url") }) {
+               print STDERR "Needed URL or usable git-svn id command-line\n";
+               commit_diff_usage();
+       }
+       if (defined $_message && defined $_file) {
+               print STDERR "Both --message/-m and --file/-F specified ",
+                               "for the commit message.\n",
+                               "I have no idea what you mean\n";
+               exit 1;
+       }
+       if (defined $_file) {
+               $_message = file_to_s($_message);
+       } else {
+               $_message ||= get_commit_message($tb,
+                                       "$GIT_DIR/.svn-commit.tmp.$$")->{msg};
+       }
+       my $repo;
+       ($repo, $SVN_PATH) = repo_path_split($SVN_URL);
+       $SVN_LOG ||= libsvn_connect($repo);
+       $SVN ||= libsvn_connect($repo);
+       my @lock = $SVN::Core::VERSION ge '1.2.0' ? (undef, 0) : ();
+       my $ed = SVN::Git::Editor->new({        r => $SVN->get_latest_revnum,
+                                               ra => $SVN, c => $tb,
+                                               svn_path => $SVN_PATH
+                                       },
+                               $SVN->get_commit_editor($_message,
+                                       sub {print "Committed $_[0]\n"},@lock)
+                               );
+       my $mods = libsvn_checkout_tree($ta, $tb, $ed);
+       if (@$mods == 0) {
+               print "No changes\n$ta == $tb\n";
+               $ed->abort_edit;
+       } else {
+               $ed->close_edit;
+       }
+}
+
 ########################### utility functions #########################
 
 sub cmt_showable {
@@ -1470,7 +1519,6 @@ sub get_commit_message {
        my %log_msg = ( msg => '' );
        open my $msg, '>', $commit_msg or croak $!;
 
-       print "commit: $commit\n";
        chomp(my $type = `git-cat-file -t $commit`);
        if ($type eq 'commit') {
                my $pid = open my $msg_fh, '-|';
@@ -1507,6 +1555,14 @@ sub get_commit_message {
        return \%log_msg;
 }
 
+sub set_svn_commit_env {
+       if (defined $LC_ALL) {
+               $ENV{LC_ALL} = $LC_ALL;
+       } else {
+               delete $ENV{LC_ALL};
+       }
+}
+
 sub svn_commit_tree {
        my ($last, $commit) = @_;
        my $commit_msg = "$GIT_SVN_DIR/.svn-commit.tmp.$$";
@@ -1514,11 +1570,7 @@ sub svn_commit_tree {
        my ($oneline) = ($log_msg->{msg} =~ /([^\n\r]+)/);
        print "Committing $commit: $oneline\n";
 
-       if (defined $LC_ALL) {
-               $ENV{LC_ALL} = $LC_ALL;
-       } else {
-               delete $ENV{LC_ALL};
-       }
+       set_svn_commit_env();
        my @ci_output = safe_qx(qw(svn commit -F),$commit_msg);
        $ENV{LC_ALL} = 'C';
        unlink $commit_msg;