Skip to content

Instantly share code, notes, and snippets.

@timmattison
Last active March 5, 2024 14:22
Show Gist options
  • Save timmattison/9f6b48fbbc60745951f0d427980c14f3 to your computer and use it in GitHub Desktop.
Save timmattison/9f6b48fbbc60745951f0d427980c14f3 to your computer and use it in GitHub Desktop.
Find the base directory of a git repo in Golang
package lib
// GetRepoBase get the directory that contains the .git directory for this repository. This DOES NOT give you the path
// you are running from or the path of the executable if you're running a binary from "go build". If your repo looks
// like this:
//
// - repo
// - .git
// - main.go
// - lib
// - shared.go
//
// And this function is in shared.go it will return the absolute path of `repo` even when using a binary that is running
// on another system. This function is useful for referencing data files inside a code base.
func GetRepoBase() string {
// Find the path of this current file
// NOTE: This means the current .go file in your source code repo, NOT where the compiled binary exists or is running from!
_, b, _, _ := runtime.Caller(0)
// Get the directory the file is in
basePath := filepath.Dir(b)
// Make sure we don't end up in a loop by checking if our last path is the same as the current path
lastBasePath := ""
// Make sure we don't end up in a loop by checking to see if we do too many iterations
maximumIterations := 50
iterationCount := 0
for {
gitDirectory := path.Join(basePath, ".git")
_, err := os.Stat(gitDirectory)
if err == nil {
// .git exists, we are done
// NOTE: This means this may not work as expected when using submodules or nested repos
return filepath.Dir(gitDirectory)
}
basePath = filepath.Dir(basePath)
iterationCount++
if iterationCount >= maximumIterations {
break
}
if lastBasePath == basePath {
break
}
lastBasePath = basePath
}
return ""
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment