Commit 18da8c33b3

18da8c33b3c0caf1f457ef638eeccd9c2e8a47de

parent: 504b4d488c

Verified · cmc ci/build: success ci/test: success

cmc <hello@cleberg.net> · 2026-09-29 03:32 UTC

backup: verify skips LFS upload staging files; asset label names a missing repository by id

Ref #259

Layout: unified · split

cmd/gitbayd/backup.go +10 −4
@@ -24,6 +24,7 @@ import (
24 "gitbay.org/gitbay/internal/backuplock" 24 "gitbay.org/gitbay/internal/backuplock"
25 "gitbay.org/gitbay/internal/config" 25 "gitbay.org/gitbay/internal/config"
26 "gitbay.org/gitbay/internal/gitutil" 26 "gitbay.org/gitbay/internal/gitutil"
27 "gitbay.org/gitbay/internal/lfs"
27 "gitbay.org/gitbay/internal/store" 28 "gitbay.org/gitbay/internal/store"
28) 29)
29 30
@@ -514,9 +515,10 @@ func checkArchive(path, identity, dest string, full bool) error {
514 if err := extractTo(tr, dbPath); err != nil { 515 if err := extractTo(tr, dbPath); err != nil {
515 return fmt.Errorf("%s: extracting the database: %w", path, err) 516 return fmt.Errorf("%s: extracting the database: %w", path, err)
516 } 517 }
517 case strings.HasPrefix(h.Name, "lfs/") && h.Typeflag == tar.TypeReg: 518 case strings.HasPrefix(h.Name, "lfs/") && h.Typeflag == tar.TypeReg && lfs.OIDPat.MatchString(filepath.Base(h.Name)):
518 // Objects are named by their sha256, so each is checked as it 519 // Objects are named by their sha256, so each is checked as it
519 // streams past and none is extracted. 520 // streams past and none is extracted. Other names, such as an
521 // upload's .upload-* staging file, are not objects.
520 lfsObjects++ 522 lfsObjects++
521 if !filepath.IsLocal(h.Name) { 523 if !filepath.IsLocal(h.Name) {
522 return fmt.Errorf("%s: member %q leaves the archive root", path, h.Name) 524 return fmt.Errorf("%s: member %q leaves the archive root", path, h.Name)
@@ -664,8 +666,12 @@ func checkReleaseAssets(st *store.Store, repos []store.Repo, root string) (int,
664 return 0, nil, err 666 return 0, nil, err
665 } 667 }
666 n++ 668 n++
667 r := byID[repoID] 669 r, ok := byID[repoID]
668 label := fmt.Sprintf("%s release %d %s", r.Path(), relID, name) 670 owner := r.Path()
671 if !ok {
672 owner = fmt.Sprintf("repository %d", repoID)
673 }
674 label := fmt.Sprintf("%s release %d %s", owner, relID, name)
669 f, err := os.Open(filepath.Join(root, "repos", r.OwnerName, r.Name+".git", "gitbay-releases", strconv.FormatInt(relID, 10), name)) 675 f, err := os.Open(filepath.Join(root, "repos", r.OwnerName, r.Name+".git", "gitbay-releases", strconv.FormatInt(relID, 10), name))
670 if err != nil { 676 if err != nil {
671 bad = append(bad, label) 677 bad = append(bad, label)
cmd/gitbayd/backup_test.go +4 −2
@@ -879,6 +879,8 @@ func TestVerifyChecksReleaseAssetsAndLFS(t *testing.T) {
879 oid := sha256.Sum256(obj) 879 oid := sha256.Sum256(obj)
880 o := hex.EncodeToString(oid[:]) 880 o := hex.EncodeToString(oid[:])
881 writeFile(t, filepath.Join(root, "lfs", o[:2], o[2:4], o), obj) 881 writeFile(t, filepath.Join(root, "lfs", o[:2], o[2:4], o), obj)
882 // An upload in progress stages a temporary file beside the objects.
883 writeFile(t, filepath.Join(root, "lfs", o[:2], o[2:4], ".upload-123"), []byte("partial"))
882 884
883 good := filepath.Join(t.TempDir(), "good.tar.gz") 885 good := filepath.Join(t.TempDir(), "good.tar.gz")
884 if err := runBackup(cfg, good, false); err != nil { 886 if err := runBackup(cfg, good, false); err != nil {
@@ -899,8 +901,8 @@ func TestVerifyChecksReleaseAssetsAndLFS(t *testing.T) {
899 if err == nil || !strings.Contains(err.Error(), "krz/thing release") || !strings.Contains(err.Error(), wrong) { 901 if err == nil || !strings.Contains(err.Error(), "krz/thing release") || !strings.Contains(err.Error(), wrong) {
900 t.Fatalf("archive with a bad asset and LFS object: %v", err) 902 t.Fatalf("archive with a bad asset and LFS object: %v", err)
901 } 903 }
902 if strings.Contains(err.Error(), o) { 904 if strings.Contains(err.Error(), o) || strings.Contains(err.Error(), ".upload-") {
903 t.Fatalf("intact LFS object reported: %v", err) 905 t.Fatalf("intact LFS object or upload staging file reported: %v", err)
904 } 906 }
905} 907}
906 908