mirror of
https://github.com/docker/docker-agent.git
synced 2026-11-04 10:02:15 +00:00
161 lines
4.9 KiB
Go
161 lines
4.9 KiB
Go
package gitroot
|
|
|
|
import (
|
|
"os"
|
|
"path/filepath"
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// newRepo creates a fake main repository at dir with a .git directory.
|
|
func newRepo(t *testing.T, dir string) {
|
|
t.Helper()
|
|
require.NoError(t, os.MkdirAll(filepath.Join(dir, ".git"), 0o755))
|
|
}
|
|
|
|
// newWorktree links a fake worktree at dir to the main repository at mainDir,
|
|
// mirroring the on-disk layout produced by `git worktree add`.
|
|
func newWorktree(t *testing.T, dir, mainDir string) {
|
|
t.Helper()
|
|
gitdir := filepath.Join(mainDir, ".git", "worktrees", filepath.Base(dir))
|
|
require.NoError(t, os.MkdirAll(gitdir, 0o755))
|
|
require.NoError(t, os.WriteFile(filepath.Join(gitdir, "commondir"), []byte("../..\n"), 0o644))
|
|
require.NoError(t, os.MkdirAll(dir, 0o755))
|
|
require.NoError(t, os.WriteFile(filepath.Join(dir, ".git"), []byte("gitdir: "+gitdir+"\n"), 0o644))
|
|
}
|
|
|
|
func TestRoot_MainRepository(t *testing.T) {
|
|
t.Parallel()
|
|
repo := t.TempDir()
|
|
newRepo(t, repo)
|
|
|
|
assert.Equal(t, repo, Root(repo))
|
|
}
|
|
|
|
func TestRoot_Subdirectory(t *testing.T) {
|
|
t.Parallel()
|
|
repo := t.TempDir()
|
|
newRepo(t, repo)
|
|
sub := filepath.Join(repo, "a", "b")
|
|
require.NoError(t, os.MkdirAll(sub, 0o755))
|
|
|
|
assert.Equal(t, repo, Root(sub))
|
|
}
|
|
|
|
func TestRoot_LinkedWorktree(t *testing.T) {
|
|
t.Parallel()
|
|
base := t.TempDir()
|
|
repo := filepath.Join(base, "repo")
|
|
newRepo(t, repo)
|
|
wt := filepath.Join(base, "wt")
|
|
newWorktree(t, wt, repo)
|
|
|
|
assert.Equal(t, repo, Root(wt))
|
|
}
|
|
|
|
func TestRoot_LinkedWorktreeSubdirectory(t *testing.T) {
|
|
t.Parallel()
|
|
base := t.TempDir()
|
|
repo := filepath.Join(base, "repo")
|
|
newRepo(t, repo)
|
|
wt := filepath.Join(base, "wt")
|
|
newWorktree(t, wt, repo)
|
|
sub := filepath.Join(wt, "pkg")
|
|
require.NoError(t, os.MkdirAll(sub, 0o755))
|
|
|
|
assert.Equal(t, repo, Root(sub))
|
|
}
|
|
|
|
func TestRoot_LinkedWorktreeAbsoluteCommondir(t *testing.T) {
|
|
t.Parallel()
|
|
base := t.TempDir()
|
|
repo := filepath.Join(base, "repo")
|
|
newRepo(t, repo)
|
|
gitdir := filepath.Join(repo, ".git", "worktrees", "wt")
|
|
require.NoError(t, os.MkdirAll(gitdir, 0o755))
|
|
require.NoError(t, os.WriteFile(filepath.Join(gitdir, "commondir"), []byte(filepath.Join(repo, ".git")+"\n"), 0o644))
|
|
wt := filepath.Join(base, "wt")
|
|
require.NoError(t, os.MkdirAll(wt, 0o755))
|
|
require.NoError(t, os.WriteFile(filepath.Join(wt, ".git"), []byte("gitdir: "+gitdir+"\n"), 0o644))
|
|
|
|
assert.Equal(t, repo, Root(wt))
|
|
}
|
|
|
|
func TestRoot_LinkedWorktreeOfBareRepository(t *testing.T) {
|
|
t.Parallel()
|
|
base := t.TempDir()
|
|
// Bare repositories are their own git dir; commondir points straight at them.
|
|
bare := filepath.Join(base, "project.git")
|
|
gitdir := filepath.Join(bare, "worktrees", "wt")
|
|
require.NoError(t, os.MkdirAll(gitdir, 0o755))
|
|
require.NoError(t, os.WriteFile(filepath.Join(gitdir, "commondir"), []byte("../..\n"), 0o644))
|
|
wt := filepath.Join(base, "wt")
|
|
require.NoError(t, os.MkdirAll(wt, 0o755))
|
|
require.NoError(t, os.WriteFile(filepath.Join(wt, ".git"), []byte("gitdir: "+gitdir+"\n"), 0o644))
|
|
|
|
assert.Equal(t, bare, Root(wt), "bare-repo worktrees resolve to the bare repo, not its parent")
|
|
}
|
|
|
|
func TestRoot_SubmoduleIsItsOwnRoot(t *testing.T) {
|
|
t.Parallel()
|
|
repo := t.TempDir()
|
|
newRepo(t, repo)
|
|
// Submodule git dirs live under .git/modules and have no commondir file.
|
|
gitdir := filepath.Join(repo, ".git", "modules", "sub")
|
|
require.NoError(t, os.MkdirAll(gitdir, 0o755))
|
|
sub := filepath.Join(repo, "sub")
|
|
require.NoError(t, os.MkdirAll(sub, 0o755))
|
|
require.NoError(t, os.WriteFile(filepath.Join(sub, ".git"), []byte("gitdir: "+gitdir+"\n"), 0o644))
|
|
|
|
assert.Equal(t, sub, Root(sub))
|
|
}
|
|
|
|
func TestRoot_DanglingGitdirPointer(t *testing.T) {
|
|
t.Parallel()
|
|
dir := t.TempDir()
|
|
require.NoError(t, os.WriteFile(filepath.Join(dir, ".git"),
|
|
[]byte("gitdir: "+filepath.Join(dir, "missing")+"\n"), 0o644))
|
|
|
|
assert.Equal(t, dir, Root(dir), "a dangling gitdir pointer falls back to the dir itself")
|
|
}
|
|
|
|
func TestRoot_OversizedGitFile(t *testing.T) {
|
|
t.Parallel()
|
|
dir := t.TempDir()
|
|
huge := append([]byte("gitdir: "), make([]byte, maxPointerFileSize)...)
|
|
require.NoError(t, os.WriteFile(filepath.Join(dir, ".git"), huge, 0o644))
|
|
|
|
assert.Equal(t, dir, Root(dir), "oversized .git files are treated as malformed")
|
|
}
|
|
|
|
func TestRoot_UncleanInput(t *testing.T) {
|
|
t.Parallel()
|
|
repo := t.TempDir()
|
|
newRepo(t, repo)
|
|
|
|
assert.Equal(t, repo, Root(repo+string(filepath.Separator)))
|
|
assert.Equal(t, repo, Root(filepath.Join(repo, "a", "..")))
|
|
}
|
|
|
|
func TestRoot_NotARepository(t *testing.T) {
|
|
t.Parallel()
|
|
assert.Empty(t, Root(t.TempDir()))
|
|
}
|
|
|
|
func TestRoot_EmptyDir(t *testing.T) {
|
|
t.Parallel()
|
|
assert.Empty(t, Root(""))
|
|
}
|
|
|
|
func TestRoot_UnreadableGitFile(t *testing.T) {
|
|
t.Parallel()
|
|
dir := t.TempDir()
|
|
// A .git file with unexpected content: treated as the repo root anyway,
|
|
// matching git's behavior of stopping the upward walk at any .git entry.
|
|
require.NoError(t, os.WriteFile(filepath.Join(dir, ".git"), []byte("garbage"), 0o644))
|
|
|
|
assert.Equal(t, dir, Root(dir))
|
|
}
|