Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support git rev-parse --show-toplevel #74

Open
StevenACoffman opened this issue May 23, 2020 · 6 comments
Open

Support git rev-parse --show-toplevel #74

StevenACoffman opened this issue May 23, 2020 · 6 comments
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed no-autoclose Issues/PRs to be ignored by stale bot

Comments

@StevenACoffman
Copy link

StevenACoffman commented May 23, 2020

If I have a repository at ~/foo, I can run git rev-parse --show-toplevel in ~/foo/bar without a problem to find the root of the current repository (~/foo).

This was mentioned way back in src-d/go-git#765

However, the fine folks at Google worked around this issue by the code here:
GoogleContainerTools/skaffold#275

And I think it would be handy to include this commonly needed functionality in go-git itself so people didn't need to rely on go-findroot and the presence of the git binary to achieve this.

@StevenACoffman
Copy link
Author

StevenACoffman commented May 23, 2020

Code in question looks like this:

func findTopLevelGitDir(workingDir string) (string, error) {
	dir, err := filepath.Abs(workingDir)
	if err != nil {
		return "", errors.Wrap(err, "invalid working dir")
	}

	for {
		if _, err := os.Stat(filepath.Join(dir, ".git")); err == nil {
			return dir, nil
		}

		parent := filepath.Dir(dir)
		if parent == dir {
			return "", errors.New("no git repository found")
		}
		dir = parent
	}
}

Currently go-git's dotGitToOSFilesystems behaves similarly.

@mcuadros mcuadros added enhancement New feature or request help wanted Extra attention is needed labels May 24, 2020
@MichaelMure
Copy link
Contributor

MichaelMure commented Jun 22, 2020

I believe this doesn't detect properly bare repositories. This is what I'm doing:

func detectGitPath(path string) (string, error) {
	// normalize the path
	path, err := filepath.Abs(path)
	if err != nil {
		return "", err
	}

	for {
		fi, err := os.Stat(stdpath.Join(path, ".git"))
		if err == nil {
			if !fi.IsDir() {
				return "", fmt.Errorf(".git exist but is not a directory")
			}
			return stdpath.Join(path, ".git"), nil
		}
		if !os.IsNotExist(err) {
			// unknown error
			return "", err
		}

		// detect bare repo
		ok, err := isGitDir(path)
		if err != nil {
			return "", err
		}
		if ok {
			return path, nil
		}

		if parent := filepath.Dir(path); parent == path {
			return "", fmt.Errorf(".git not found")
		} else {
			path = parent
		}
	}
}

func isGitDir(path string) (bool, error) {
	markers := []string{"HEAD", "objects", "refs"}

	for _, marker := range markers {
		_, err := os.Stat(stdpath.Join(path, marker))
		if err == nil {
			continue
		}
		if !os.IsNotExist(err) {
			// unknown error
			return false, err
		} else {
			return false, nil
		}
	}

	return true, nil
}

It's based on https://github.com/git/git/blob/3bab5d56259722843359702bc27111475437ad2a/setup.c#L328-L338

@github-actions
Copy link

github-actions bot commented Oct 4, 2023

To help us keep things tidy and focus on the active tasks, we've introduced a stale bot to spot issues/PRs that haven't had any activity in a while.

This particular issue hasn't had any updates or activity in the past 90 days, so it's been labeled as 'stale'. If it remains inactive for the next 30 days, it'll be automatically closed.

We understand everyone's busy, but if this issue is still important to you, please feel free to add a comment or make an update to keep it active.

Thanks for your understanding and cooperation!

@github-actions github-actions bot added the stale Issues/PRs that are marked for closure due to inactivity label Oct 4, 2023
@mitar
Copy link

mitar commented Oct 4, 2023

This has 11 upvotes, I think it is not yet stale.

@pjbgf pjbgf added no-autoclose Issues/PRs to be ignored by stale bot good first issue Good for newcomers and removed stale Issues/PRs that are marked for closure due to inactivity labels Oct 4, 2023
@IP1102
Copy link

IP1102 commented Nov 14, 2023

Hey, I was thinking of adding native git rev-parse <options> support. It's not supported as of now. It will also help parsing repo much more efficient. Something like what PyDriller does in Python.

Also, I am new to this, can anyone give any suggestion on where to start so I can pick up this feature?

@pjbgf
Copy link
Member

pjbgf commented Nov 14, 2023

I believe this is already supported if you use go-billy's BoundOS:

func main() {
	CheckArgs("<path>")
	path := os.Args[1]

	wt := osfs.New(path, osfs.WithBoundOS())
	dot, err := wt.Chroot(git.GitDirName)
	CheckIfError(err)

	storer := filesystem.NewStorage(dot, cache.NewObjectLRUDefault())
	r, err := git.Open(storer, wt)
	CheckIfError(err)

	w, err := r.Worktree()
	CheckIfError(err)

	Info("git rev-parse --show-toplevel")
	d, err := filepath.Abs(w.Filesystem.Root())
	CheckIfError(err)

	fmt.Println(d)
}

Please note that the worktree filesystem is abstracted by go-billy and until recently you had two options: osfs or memfs, both of which would return / as they operate with a "soft-chroot".

With BoundOS you can see the actual directory - as per above.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request good first issue Good for newcomers help wanted Extra attention is needed no-autoclose Issues/PRs to be ignored by stale bot
Projects
None yet
Development

No branches or pull requests

6 participants