Resolve LFS objects from git common dir

This commit is contained in:
2026-04-18 16:03:49 +02:00
parent dfde20f679
commit 8e7ffd8f4f
2 changed files with 75 additions and 3 deletions
+22 -3
View File
@@ -733,10 +733,14 @@ func chunksFromManifest(assets []assetResource, entries []BuildManifestHAK) ([]h
func collectLFSAssetInfo(p *project.Project) (map[string]lfsAssetInfo, error) { func collectLFSAssetInfo(p *project.Project) (map[string]lfsAssetInfo, error) {
result := make(map[string]lfsAssetInfo) result := make(map[string]lfsAssetInfo)
lfsObjectRoot, err := resolveLFSObjectRoot(p.Root)
if err != nil {
return nil, err
}
for _, rel := range p.Inventory.AssetFiles { for _, rel := range p.Inventory.AssetFiles {
rel = filepath.ToSlash(rel) rel = filepath.ToSlash(rel)
abs := filepath.Join(p.AssetsDir(), filepath.FromSlash(rel)) abs := filepath.Join(p.AssetsDir(), filepath.FromSlash(rel))
info, ok, err := parseLFSPointerFile(abs, p.Root) info, ok, err := parseLFSPointerFile(abs, lfsObjectRoot)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -748,7 +752,22 @@ func collectLFSAssetInfo(p *project.Project) (map[string]lfsAssetInfo, error) {
return result, nil return result, nil
} }
func parseLFSPointerFile(path, repoRoot string) (lfsAssetInfo, bool, error) { func resolveLFSObjectRoot(repoRoot string) (string, error) {
output, err := gitOutput(repoRoot, "rev-parse", "--git-common-dir")
if err != nil {
return filepath.Join(repoRoot, ".git", "lfs", "objects"), nil
}
commonDir := strings.TrimSpace(output)
if commonDir == "" {
return filepath.Join(repoRoot, ".git", "lfs", "objects"), nil
}
if !filepath.IsAbs(commonDir) {
commonDir = filepath.Join(repoRoot, commonDir)
}
return filepath.Join(filepath.Clean(commonDir), "lfs", "objects"), nil
}
func parseLFSPointerFile(path, lfsObjectRoot string) (lfsAssetInfo, bool, error) {
entry, err := os.Lstat(path) entry, err := os.Lstat(path)
if err != nil { if err != nil {
return lfsAssetInfo{}, false, fmt.Errorf("stat %s: %w", path, err) return lfsAssetInfo{}, false, fmt.Errorf("stat %s: %w", path, err)
@@ -784,7 +803,7 @@ func parseLFSPointerFile(path, repoRoot string) (lfsAssetInfo, bool, error) {
return lfsAssetInfo{}, false, nil return lfsAssetInfo{}, false, nil
} }
if len(info.OID) >= 4 { if len(info.OID) >= 4 {
info.ObjectPath = filepath.Join(repoRoot, ".git", "lfs", "objects", info.OID[:2], info.OID[2:4], info.OID) info.ObjectPath = filepath.Join(lfsObjectRoot, info.OID[:2], info.OID[2:4], info.OID)
} }
return info, true, nil return info, true, nil
} }
+53
View File
@@ -1874,6 +1874,59 @@ func TestPlanHAKChunksPutsNewestAssetsInLastChunk(t *testing.T) {
} }
} }
func TestCollectLFSAssetInfoUsesGitCommonDirForWorktree(t *testing.T) {
if _, err := exec.LookPath("git"); err != nil {
t.Skip("git not available")
}
parent := t.TempDir()
repoRoot := filepath.Join(parent, "repo")
worktreeRoot := filepath.Join(parent, "worktree")
mustMkdir(t, repoRoot)
runGitTest(t, repoRoot, "init")
mustWriteFile(t, filepath.Join(repoRoot, "README.md"), "test\n")
runGitTest(t, repoRoot, "add", ".")
runGitTest(t, repoRoot, "config", "user.name", "Test User")
runGitTest(t, repoRoot, "config", "user.email", "test@example.com")
runGitTest(t, repoRoot, "commit", "-m", "initial")
runGitTest(t, repoRoot, "worktree", "add", worktreeRoot, "HEAD")
oid := strings.Repeat("a", 64)
assetRel := filepath.Join("core", "foo.mdl")
assetPath := filepath.Join(worktreeRoot, "assets", assetRel)
mustMkdir(t, filepath.Dir(assetPath))
mustWriteFile(t, assetPath, "version https://git-lfs.github.com/spec/v1\n"+"oid sha256:"+oid+"\n"+"size 5\n")
lfsObjectPath := filepath.Join(repoRoot, ".git", "lfs", "objects", oid[:2], oid[2:4], oid)
mustMkdir(t, filepath.Dir(lfsObjectPath))
mustWriteFile(t, lfsObjectPath, "model")
proj := &project.Project{
Root: worktreeRoot,
Config: project.Config{
Paths: project.PathConfig{Source: "src", Assets: "assets", Build: "build"},
},
Inventory: project.Inventory{
AssetFiles: []string{filepath.ToSlash(assetRel)},
},
}
infos, err := collectLFSAssetInfo(proj)
if err != nil {
t.Fatalf("collect lfs asset info: %v", err)
}
info, ok := infos[filepath.ToSlash(assetRel)]
if !ok {
t.Fatal("expected LFS asset info")
}
if got, want := info.ObjectPath, lfsObjectPath; got != want {
t.Fatalf("unexpected LFS object path:\ngot %s\nwant %s", got, want)
}
if _, err := lfsPathResource(assetPath, info, true); err != nil {
t.Fatalf("expected worktree LFS object to resolve: %v", err)
}
}
func runGitCommitTest(t *testing.T, dir, timestamp, message string) { func runGitCommitTest(t *testing.T, dir, timestamp, message string) {
t.Helper() t.Helper()
runGitTest(t, dir, "add", ".") runGitTest(t, dir, "add", ".")