Eygene Ryabinkin <rea-git@xxxxxxxxxxx> wrote: > This mode is useful when we're mirrorring one-to-one Subversion and Git > repositories and then using Git as the repository to base other work on. > > Bare mode is currently restricted only to init, clone, fetch, log, > find-rev, show-ignore, show-externals, create-ignore, propget, proplist > and info commands. Others won't work at all and error message will > be produced. Hi Eygene, This definitely seems useful. I'd like a basic test to ensure it continues working in the future. More comments inline. > Signed-off-by: Eygene Ryabinkin <rea-git@xxxxxxxxxxx> > index c5965c9..4756abf 100755 > --- a/git-svn.perl > +++ b/git-svn.perl > @@ -63,13 +63,14 @@ $sha1 = qr/[a-f\d]{40}/; > $sha1_short = qr/[a-f\d]{4,40}/; > my ($_stdin, $_help, $_edit, > $_message, $_file, > - $_template, $_shared, > + $_template, $_shared, $_bare, > $_version, $_fetch_all, $_no_rebase, $_fetch_parent, > $_merge, $_strategy, $_dry_run, $_local, > $_prefix, $_no_checkout, $_url, $_verbose, > $_git_format, $_commit_url, $_tag); > $Git::SVN::_follow_parent = 1; > $_q ||= 0; > +$_bare = 0; > my %remote_opts = ( 'username=s' => \$Git::SVN::Prompt::_username, > 'config-dir=s' => \$Git::SVN::Ra::config_dir, > 'no-auth-cache' => \$Git::SVN::Prompt::_no_auth_cache, > } > > sub do_git_init_db { > - unless (-d $ENV{GIT_DIR}) { > + unless (-d $ENV{GIT_DIR} && !$_bare) { > my @init_db = ('init'); > push @init_db, "--template=$_template" if defined $_template; > if (defined $_shared) { > @@ -325,8 +327,15 @@ sub do_git_init_db { > push @init_db, "--shared"; > } > } > + push @init_db, "--bare" if $_bare; > command_noisy(@init_db); > - $_repository = Git->repository(Repository => ".git"); > + if ($_bare && -d $ENV{GIT_DIR}) { > + $_repository = > + Git->repository(Repository => $ENV{GIT_DIR}); > + } else { > + $_repository = > + Git->repository(Repository => ".git"); > + } > } > command_noisy('config', 'core.autocrlf', 'false'); > my $set; > @@ -344,9 +353,20 @@ sub do_git_init_db { > > sub init_subdir { > my $repo_path = shift or return; > + my $full_path; > + if ($repo_path =~ /^\//) { > + $full_path = $repo_path; > + } else { > + use POSIX qw(getcwd); > + $full_path = POSIX::getcwd() . "/" . $repo_path; > + } > mkpath([$repo_path]) unless -d $repo_path; > chdir $repo_path or die "Couldn't chdir to $repo_path: $!\n"; > - $ENV{GIT_DIR} = '.git'; > + if (!$_bare) { > + $ENV{GIT_DIR} = $full_path . '/.git'; > + } else { > + $ENV{GIT_DIR} = $full_path; > + } > $_repository = Git->repository(Repository => $ENV{GIT_DIR}); > } > > @@ -389,6 +409,7 @@ sub cmd_fetch { > if (@_ > 1) { > die "Usage: $0 fetch [--all] [--parent] [svn-remote]\n"; > } > + get_bareness(); > if ($_fetch_parent) { > my ($url, $rev, $uuid, $gs) = working_head_info('HEAD'); > unless ($gs) { > @@ -408,6 +429,12 @@ sub cmd_fetch { > > sub cmd_set_tree { > my (@commits) = @_; > + > + get_bareness(); > + if ($_bare) { > + fatal("'set-tree' isn't supported for bare repositories."); > + } > + This repetition with get_bareness() and then checking for $_bare all over the place bothers me a bit. I'd rather just have something like this: fatal_if_bare('set-tree'); Or even: fatal_if_bare($cmd); > +# Initialize bareness flag for an existing repository > +sub get_bareness { > + return unless -d $ENV{GIT_DIR}; > + my $result = Git::config_bool('core.bare'); > + $result = 0 unless defined($result); > + $_bare = $result; > +} Perhaps this function can go into Git.pm since core.bare affects all of git, not just git-svn. I'd also like to just use something like if (Git::config_bare()) { ... } ...rather than having to check/initialize a variable every time. Of course, we can have config caching for platforms that really need it done via Sam's Git::Config module when it gets merged. > sub extract_metadata { > my $id = shift or return (undef, undef, undef); > my ($url, $rev, $uuid) = ($id =~ /^\s*git-svn-id:\s+(.*)\@(\d+) > @@ -1527,6 +1588,51 @@ sub parse_revision_argument { > die "revision argument: $::_revision not understood by git-svn\n"; > } > > +# > +# While we are fetching to bare repositories, we should update branch > +# heads manually, because it is not possible to do merges within bare > +# repositories. > +# > +# Arguments: > +# - name of remote branch, for example 'refs/remotes/git-svn'; > +# - name of the corresponding local head, for example 'refs/heads/master'. > +# > +sub fast_forward_bare_fetch { > + return unless defined($_bare); > + return unless defined($_[0]); > + return unless defined($_[1]); Checking for arguments here seems unnecessarily defensive. > + my $remote = $_[0]; > + my $localhead = $_[1]; The general git-svn style is this: my ($remote, $localhead) = @_; > + # Update (fast-forward) heads for bare repository. > + if (defined($_bare)) { > + foreach my $gs (@gs) { > + my $remote = 'refs/remotes/' . $gs->{ref_id}; > + my $localhead = 'refs/heads/master'; > + if (open(FH, "<", "HEAD")) { > + chomp(my $head = <FH>); > + close FH; > + if ($head =~ /^ref: (.*)$/) { > + $localhead = $1; > + } > + } "git rev-parse --symbolic-full-name HEAD" should work better than parsing HEAD ourselves. Thanks! -- Eric Wong -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html