git/list[1] front-page[2] threads[3] people[4] search[5] about
 

Re: [PATCH] git-svn: teach to create and operate on bare repositories

From
EWEric Wong <normalperson@yhbt.net>
Date
Apr 21, 2009, 18:01 UTC
Message-ID
<20090421180101.GA16642@dcvr.yhbt.net>
In-Reply-To
<lGoUDENjg0Z+sDE9v/txzTLyfk8@7qgLKkvX/1U6eu9avhKQpU/1pEI>
Eygene Ryabinkin <rea-git@codelabs.ru> wrote:
Show 7 quoted lines
> 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@codelabs.ru>
Show 19 quoted lines
> 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,
Show 65 quoted lines
>  }
>  
>  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);
Show 7 quoted lines
> +# 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.

Show 20 quoted lines
>  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) = @_;
Show 12 quoted lines
> +	# 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
Previous: Eygene RyabinkinNext: Eygene Ryabinkin
Message 2 of 4 in “git-svn: teach to create and operate on bare repositories”
  1. git-svn: teach to create and operate on bare repositoriesEygene Ryabinkin, Apr 19, 2009
  2. Eric WongApr 21, 2009
  3. Eygene RyabinkinApr 22, 2009
  4. Eric WongApr 23, 2009

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.