fix(LFS): recalculate repo LFSSize after gc-lfs removes orphaned data (#39406)

Related to #36169 

this PR makes `gc-lfs` update the `repo.LFSSize` on object removal,
updates the test to also cover the recalculation of sizes.
doesn't touch `storage-lfs` as it removes files with no LFSMetaObject
row, and LFSSize is calculated from those rows

---------

Signed-off-by: Myle <myle.ataraxia@pm.me>
Co-authored-by: silverwind <me@silverwind.io>
This commit is contained in:
Myle
2026-09-24 13:28:14 +00:00
committed by GitHub
co-authored by silverwind
parent 484981fd74
commit d5ed7375ce
2 changed files with 21 additions and 2 deletions
+12 -2
View File
@@ -14,6 +14,7 @@ import (
"gitea.dev/modules/git"
"gitea.dev/modules/lfs"
"gitea.dev/modules/log"
repo_module "gitea.dev/modules/repository"
"gitea.dev/modules/setting"
"gitea.dev/modules/timeutil"
)
@@ -51,7 +52,10 @@ func GarbageCollectLFSMetaObjects(ctx context.Context, opts GarbageCollectLFSMet
if newMinimum := int64(float64(count) * opts.ProportionToCheckPerRepo); newMinimum > opts.NumberToCheckPerRepo && opts.NumberToCheckPerRepo != 0 {
opts.NumberToCheckPerRepo = newMinimum
}
return GarbageCollectLFSMetaObjectsForRepo(ctx, repo, opts)
if err := GarbageCollectLFSMetaObjectsForRepo(ctx, repo, opts); err != nil {
log.Error("Unable to garbage collect LFS meta objects in %-v: %v", repo, err)
}
return nil
})
}
@@ -128,9 +132,15 @@ func GarbageCollectLFSMetaObjectsForRepo(ctx context.Context, repo *repo_model.R
if err == errStop {
opts.LogDetail("Processing stopped at %d total LFSMetaObjects in %-v", total, repo)
return nil
} else if err != nil {
return err
}
if collected > 0 {
if err := repo_module.UpdateRepoSize(ctx, repo); err != nil {
return fmt.Errorf("unable to update size for %s: %w", repo.FullName(), err)
}
}
return nil
}
+9
View File
@@ -12,6 +12,7 @@ import (
repo_model "gitea.dev/models/repo"
"gitea.dev/models/unittest"
"gitea.dev/modules/lfs"
repo_module "gitea.dev/modules/repository"
"gitea.dev/modules/setting"
"gitea.dev/modules/storage"
"gitea.dev/modules/test"
@@ -34,6 +35,8 @@ func TestGarbageCollectLFSMetaObjects(t *testing.T) {
// add lfs object
lfsContent := []byte("gitea1")
lfsOid := storeObjectInRepo(t, repo.ID, &lfsContent)
lfsContentInRepoWithoutGitDir := []byte("gitea3")
storeObjectInRepo(t, 6, &lfsContentInRepoWithoutGitDir)
// gc
err = repo_service.GarbageCollectLFSMetaObjects(t.Context(), repo_service.GarbageCollectLFSMetaObjectsOptions{
@@ -62,6 +65,8 @@ func TestGarbageCollectLFSMetaObjectsForRepoAutoFix(t *testing.T) {
lfsContent := []byte("gitea2")
lfsOid := storeObjectInRepo(t, repo.ID, &lfsContent)
assert.NoError(t, repo_module.UpdateRepoSize(t.Context(), repo))
err = repo_service.GarbageCollectLFSMetaObjectsForRepo(t.Context(), repo, repo_service.GarbageCollectLFSMetaObjectsOptions{
LogDetail: func(string, ...any) {},
AutoFix: true,
@@ -72,6 +77,10 @@ func TestGarbageCollectLFSMetaObjectsForRepoAutoFix(t *testing.T) {
_, err = git_model.GetLFSMetaObjectByOid(t.Context(), repo.ID, lfsOid)
assert.ErrorIs(t, err, git_model.ErrLFSObjectNotExist)
// LFSSize is recalculated to reflect the removed orphaned object
repo = unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 1})
assert.EqualValues(t, 0, repo.LFSSize)
}
func storeObjectInRepo(t *testing.T, repositoryID int64, content *[]byte) string {