git-svn: add --shared and --template= options to pass to init-db
[gitweb.git] / contrib / git-svn / git-svn.perl
index 2dce4e7b83e072a2272c8a62e49922c67f0849f2..d8f103ed9adada780b56d5ae9270025e0a48ec6d 100755 (executable)
@@ -34,6 +34,8 @@
 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,
+       $_repack, $_repack_nr, $_repack_flags,
+       $_template, $_shared,
        $_version, $_upgrade, $_authors, $_branch_all_refs);
 my (@_branch_from, %tree_map, %users);
 my ($_svn_co_url_revs, $_svn_pg_peg_revs);
@@ -42,7 +44,9 @@
 my %fc_opts = ( 'no-ignore-externals' => \$_no_ignore_ext,
                'branch|b=s' => \@_branch_from,
                'branch-all-refs|B' => \$_branch_all_refs,
-               'authors-file|A=s' => \$_authors );
+               'authors-file|A=s' => \$_authors,
+               'repack:i' => \$_repack,
+               'repack-flags|repack-args|repack-opts=s' => \$_repack_flags);
 
 # yes, 'native' sets "\n".  Patches to fix this for non-*nix systems welcome:
 my %EOL = ( CR => "\015", LF => "\012", CRLF => "\015\012", native => "\012" );
@@ -51,7 +55,9 @@
        fetch => [ \&fetch, "Download new revisions from SVN",
                        { 'revision|r=s' => \$_revision, %fc_opts } ],
        init => [ \&init, "Initialize a repo for tracking" .
-                         " (requires URL argument)", { } ],
+                         " (requires URL argument)",
+                         { 'template=s' => \$_template,
+                           'shared' => \$_shared } ],
        commit => [ \&commit, "Commit git revisions to SVN",
                        {       'stdin|' => \$_stdin,
                                'edit|e' => \$_edit,
 
 my %opts = %{$cmd{$cmd}->[2]} if (defined $cmd);
 
-# convert GetOpt::Long specs for use by git-repo-config
-foreach my $o (keys %opts) {
-       my $v = $opts{$o};
-       my ($key) = ($o =~ /^([a-z\-]+)/);
-       $key =~ s/-//g;
-       my $arg = 'git-repo-config';
-       $arg .= ' --int' if ($o =~ /=i$/);
-       $arg .= ' --bool' if ($o !~ /=[sfi]$/);
-       if (ref $v eq 'ARRAY') {
-               chomp(my @tmp = `$arg --get-all svn.$key`);
-               @$v = @tmp if @tmp;
-       } else {
-               chomp(my $tmp = `$arg --get svn.$key`);
-               if ($tmp && !($arg =~ / --bool / && $tmp eq 'false')) {
-                       $$v = $tmp;
-               }
-       }
-}
-
+read_repo_config(\%opts);
 GetOptions(%opts, 'help|H|h' => \$_help,
                'version|V' => \$_version,
                'id|i=s' => \$GIT_SVN) or exit 1;
 
-$GIT_SVN ||= $ENV{GIT_SVN_ID} || 'git-svn';
-$GIT_SVN_DIR = "$GIT_DIR/svn/$GIT_SVN";
-$GIT_SVN_INDEX = "$GIT_SVN_DIR/index";
-$SVN_URL = undef;
-$REV_DIR = "$GIT_SVN_DIR/revs";
-$SVN_WC = "$GIT_SVN_DIR/tree";
-
+set_default_vals();
 usage(0) if $_help;
 version() if $_version;
 usage(1) unless defined $cmd;
+init_vars();
 load_authors() if $_authors;
 load_all_refs() if $_branch_all_refs;
 svn_compat_check();
@@ -132,7 +115,7 @@ sub usage {
                print $fd '  ',pack('A13',$_),$cmd{$_}->[1],"\n";
                foreach (keys %{$cmd{$_}->[2]}) {
                        # prints out arguments as they should be passed:
-                       my $x = s#=s$## ? '<arg>' : s#=i$## ? '<num>' : '';
+                       my $x = s#[:=]s$## ? '<arg>' : s#[:=]i$## ? '<num>' : '';
                        print $fd ' ' x 17, join(', ', map { length $_ > 1 ?
                                                        "--$_" : "-$_" }
                                                split /\|/,$_)," $x\n";
@@ -220,9 +203,10 @@ sub rebuild {
                sys(@svn_up,"-r$newest_rev");
                $ENV{GIT_INDEX_FILE} = $GIT_SVN_INDEX;
                index_changes();
-               exec('git-write-tree');
+               exec('git-write-tree') or croak $!;
        }
        waitpid $pid, 0;
+       croak $? if $?;
 
        if ($_upgrade) {
                print STDERR <<"";
@@ -236,7 +220,10 @@ sub init {
        $SVN_URL = shift or die "SVN repository location required " .
                                "as a command-line argument\n";
        unless (-d $GIT_DIR) {
-               sys('git-init-db');
+               my @init_db = ('git-init-db');
+               push @init_db, "--template=$_template" if defined $_template;
+               push @init_db, "--shared" if defined $_shared;
+               sys(@init_db);
        }
        setup_git_svn();
 }
@@ -295,6 +282,7 @@ sub fetch {
        unless (-e "$GIT_DIR/refs/heads/master") {
                sys(qw(git-update-ref refs/heads/master),$last_commit);
        }
+       close $svn_log->{fh};
        return $last;
 }
 
@@ -830,7 +818,7 @@ sub svn_log_raw {
                exec (qw(svn log), @log_args) or croak $!
        }
        waitpid $pid, 0;
-       croak if $?;
+       croak $? if $?;
        seek $log_fh, 0, 0 or croak $!;
        return { state => 'sep', fh => $log_fh };
 }
@@ -1090,7 +1078,7 @@ sub git_commit {
                $ENV{GIT_INDEX_FILE} = $GIT_SVN_INDEX;
                index_changes();
                chomp(my $tree = `git-write-tree`);
-               croak if $?;
+               croak $? if $?;
                if (exists $tree_map{$tree}) {
                        my %seen_parent = map { $_ => 1 } @exec_parents;
                        foreach (@{$tree_map{$tree}}) {
@@ -1118,7 +1106,7 @@ sub git_commit {
                exec @exec or croak $!;
        }
        waitpid($pid,0);
-       croak if $?;
+       croak $? if $?;
 
        $out_fh->flush == 0 or croak $!;
        seek $out_fh, 0, 0 or croak $!;
@@ -1134,7 +1122,7 @@ sub git_commit {
                        close STDERR;
                        close STDOUT;
                        exec 'git-rev-parse','--verify',
-                                               "refs/remotes/$GIT_SVN^0";
+                                       "refs/remotes/$GIT_SVN^0" or croak $!;
                }
                waitpid $pid, 0;
                push @update_ref, $primary_parent unless $?;
@@ -1142,6 +1130,10 @@ sub git_commit {
        sys(@update_ref);
        sys('git-update-ref',"svn/$GIT_SVN/revs/$log_msg->{revision}",$commit);
        print "r$log_msg->{revision} = $commit\n";
+       if ($_repack && (--$_repack_nr == 0)) {
+               $_repack_nr = $_repack;
+               sys("git repack $_repack_flags");
+       }
        return $commit;
 }
 
@@ -1190,7 +1182,7 @@ sub blob_to_file {
 
        if ($pid == 0) {
                open STDOUT, '>&', $blob_fh or croak $!;
-               exec('git-cat-file','blob',$blob);
+               exec('git-cat-file','blob',$blob) or croak $!;
        }
        waitpid $pid, 0;
        croak $? if $?;
@@ -1202,7 +1194,7 @@ sub safe_qx {
        my $pid = open my $child, '-|';
        defined $pid or croak $!;
        if ($pid == 0) {
-               exec(@_) or croak $?;
+               exec(@_) or croak $!;
        }
        my @ret = (<$child>);
        close $child or croak $?;
@@ -1252,7 +1244,7 @@ sub check_upgrade_needed {
                defined $pid or croak $!;
                if ($pid == 0) {
                        close STDERR;
-                       exec('git-rev-parse',"$GIT_SVN-HEAD") or croak $?;
+                       exec('git-rev-parse',"$GIT_SVN-HEAD") or croak $!;
                }
                my @ret = (<$child>);
                close $child or croak $?;
@@ -1276,7 +1268,7 @@ sub map_tree_joins {
                defined $pid or croak $!;
                if ($pid == 0) {
                        exec(qw(git-rev-list --topo-order --pretty=raw), $br)
-                                                               or croak $?;
+                                                               or croak $!;
                }
                while (<$pipe>) {
                        if (/^commit ($sha1)$/o) {
@@ -1352,6 +1344,46 @@ sub migration_check {
        print "Done upgrading.\n";
 }
 
+sub init_vars {
+       $GIT_SVN ||= $ENV{GIT_SVN_ID} || 'git-svn';
+       $GIT_SVN_DIR = "$GIT_DIR/svn/$GIT_SVN";
+       $GIT_SVN_INDEX = "$GIT_SVN_DIR/index";
+       $SVN_URL = undef;
+       $REV_DIR = "$GIT_SVN_DIR/revs";
+       $SVN_WC = "$GIT_SVN_DIR/tree";
+}
+
+# convert GetOpt::Long specs for use by git-repo-config
+sub read_repo_config {
+       return unless -d $GIT_DIR;
+       my $opts = shift;
+       foreach my $o (keys %$opts) {
+               my $v = $opts->{$o};
+               my ($key) = ($o =~ /^([a-z\-]+)/);
+               $key =~ s/-//g;
+               my $arg = 'git-repo-config';
+               $arg .= ' --int' if ($o =~ /[:=]i$/);
+               $arg .= ' --bool' if ($o !~ /[:=][sfi]$/);
+               if (ref $v eq 'ARRAY') {
+                       chomp(my @tmp = `$arg --get-all svn.$key`);
+                       @$v = @tmp if @tmp;
+               } else {
+                       chomp(my $tmp = `$arg --get svn.$key`);
+                       if ($tmp && !($arg =~ / --bool / && $tmp eq 'false')) {
+                               $$v = $tmp;
+                       }
+               }
+       }
+}
+
+sub set_default_vals {
+       if (defined $_repack) {
+               $_repack = 1000 if ($_repack <= 0);
+               $_repack_nr = $_repack;
+               $_repack_flags ||= '';
+       }
+}
+
 __END__
 
 Data structures: