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

Re: [PATCH v2 2/2] setup: allow Git.pm to do unsafe repo checking

From
Jeff King <peff@peff.net>
Date
Oct 22, 2022, 21:16 UTC
Message-ID
<Y1Rdtog/XQV0YLj0@coredump.intra.peff.net>
In-Reply-To
<20221022011931.43992-3-michael@mcclimon.org>
On Fri, Oct 21, 2022 at 09:19:32PM -0400, Michael McClimon wrote:
Show 12 quoted lines
> diff --git a/perl/Git.pm b/perl/Git.pm
> index cf15ead6..002c29bb 100644
> --- a/perl/Git.pm
> +++ b/perl/Git.pm
> @@ -1674,6 +1674,7 @@ sub _cmd_exec {
>  sub _setup_git_cmd_env {
>  	my $self = shift;
>  	if ($self) {
> +		$ENV{GIT_PERL_FORCE_OWNERSHIP_CHECK} = 1;
>  		$self->repo_path() and $ENV{'GIT_DIR'} = $self->repo_path();
>  		$self->repo_path() and $self->wc_path()
>  			and $ENV{'GIT_WORK_TREE'} = $self->wc_path();

I'm not familiar enough with Git.pm to know if this is the right spot. But we'd not want to break the case where GIT_DIR is set already. I.e.:

  GIT_DIR=/path/to/repo.git perl -MGit -e 'Git->repository'

should continue to work regardless of the ownership of repo.git. Only the repo-discovery phase would want to force the ownership check.

Again, I'm not too familiar with Git.pm, but it seems it ought to be asking Git: are we in a valid Git repo, and if so where is it? Something like:

  my $git_dir = `git rev-parse --absolute-git-dir`;
  $? and die "nope, not in a git repo";
  # later, when we run git commands, we do specify this; the script may
  # have chdir()'d in the meantime, and we want to make sure we are
  # referring to the same repo via the object.
  local $ENV{GIT_DIR} = abs_path($git_dir);
  ...run some git command...

Looking at the code, we even seem to do that first part! But if it returns an error, then we go on to check for a bare repository ourselves by looking for refs/, objects/, etc. Which is just...weird.

It feels like this try/catch should just go away:
diff --git a/perl/Git.pm b/perl/Git.pm
index cf15ead664..7a7d8a2987 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -177,13 +177,7 @@ sub repository {
 		-d $opts{Directory} or throw Error::Simple("Directory not found: $opts{Directory} $!");
 
 		my $search = Git->repository(WorkingCopy => $opts{Directory});
-		my $dir;
-		try {
-			$dir = $search->command_oneline(['rev-parse', '--git-dir'],
-			                                STDERR => 0);
-		} catch Git::Error::Command with {
-			$dir = undef;
-		};
+		my $dir = $search->command_oneline(['rev-parse', '--git-dir']);
 
 		require Cwd;
 		if ($dir) {

And then the code below that to check for bare/not-bare should be using
"git rev-parse --is-bare-repository" or similar. Something like:

diff --git a/perl/Git.pm b/perl/Git.pm
index 7a7d8a2987..280df9cee1 100644
--- a/perl/Git.pm
+++ b/perl/Git.pm
@@ -179,8 +179,14 @@ sub repository {
 		my $search = Git->repository(WorkingCopy => $opts{Directory});
 		my $dir = $search->command_oneline(['rev-parse', '--git-dir']);
 
+		# could be merged with command above to be more efficient; or
+		# could probably use --show-toplevel to avoid prefix query
+		# below
+		my $bare = $search->command_oneline(['rev-parse', '--is-bare-repository'])
+		             eq 'true';
+
 		require Cwd;
-		if ($dir) {
+		if (!$bare) {
 			require File::Spec;
 			File::Spec->file_name_is_absolute($dir) or $dir = $opts{Directory} . '/' . $dir;
 			$opts{Repository} = Cwd::abs_path($dir);
@@ -198,21 +204,6 @@ sub repository {
 			$opts{WorkingSubdir} = $prefix;
 
 		} else {
-			# A bare repository? Let's see...
-			$dir = $opts{Directory};
-
-			unless (-d "$dir/refs" and -d "$dir/objects" and -e "$dir/HEAD") {
-				# Mimic git-rev-parse --git-dir error message:
-				throw Error::Simple("fatal: Not a git repository: $dir");
-			}
-			my $search = Git->repository(Repository => $dir);
-			try {
-				$search->command('symbolic-ref', 'HEAD');
-			} catch Git::Error::Command with {
-				# Mimic git-rev-parse --git-dir error message:
-				throw Error::Simple("fatal: Not a git repository: $dir");
-			};
-
 			$opts{Repository} = Cwd::abs_path($dir);
 		}
 

But given how much more complicated the current code is, I wonder if I
am missing some case. Or perhaps this code is just so old that it used
to do this stuff itself (because rev-parse didn't give us so much help).

-Peff
Previous: Jeff KingNext: Jeff King
Message 19 of 23 in “Git.pm: add semicolon after catch statement”
  1. 0/1 Git.pm: add semicolon after catch statementMichael McClimon, Oct 16, 2022
  2. 1/1 Git.pm: add semicolon after catch statementMichael McClimon, Oct 16, 2022
  3. Jeff KingOct 16, 2022
  4. Michael McClimonOct 17, 2022
  5. Jeff KingOct 17, 2022
  6. Michael McClimonOct 18, 2022
  7. Johannes SchindelinNov 10, 2022
  8. Jeff KingNov 10, 2022
  9. 0/2 Fix behavior of Git.pm in unsafe bare repositoriesMichael McClimon, Oct 22, 2022
  10. 1/2 Git.pm: add semicolon after catch statementMichael McClimon, Oct 22, 2022
  11. 2/2 setup: allow Git.pm to do unsafe repo checkingMichael McClimon, Oct 22, 2022
  12. Junio C HamanoOct 22, 2022
  13. Jeff KingOct 22, 2022
  14. Junio C HamanoOct 22, 2022
  15. Ævar Arnfjörð BjarmasonOct 22, 2022
  16. Jeff KingOct 22, 2022
  17. Ævar Arnfjörð BjarmasonOct 24, 2022
  18. Jeff KingOct 24, 2022
  19. Jeff KingOct 22, 2022
  20. Jeff KingOct 22, 2022
  21. Michael McClimonOct 22, 2022
  22. Jeff KingOct 24, 2022
  23. Junio C HamanoOct 22, 2022

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.