Skip to content

Fix LFS file not stored in LFS when uploaded/edited via API or web UI #34367

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
May 8, 2025
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion modules/git/attribute/batch.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func NewBatchChecker(repo *git.Repository, treeish string, attributes []string)
}
}()

cmd, envs, cleanup, err := checkAttrCommand(repo, treeish, nil, attributes)
cmd, envs, cleanup, err := checkAttrCommand(repo, treeish, nil, attributes, false)
if err != nil {
return nil, err
}
Expand Down
9 changes: 7 additions & 2 deletions modules/git/attribute/checker.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
"code.gitea.io/gitea/modules/git"
)

func checkAttrCommand(gitRepo *git.Repository, treeish string, filenames, attributes []string) (*git.Command, []string, func(), error) {
func checkAttrCommand(gitRepo *git.Repository, treeish string, filenames, attributes []string, cached bool) (*git.Command, []string, func(), error) {
cancel := func() {}
envs := []string{"GIT_FLUSH=1"}
cmd := git.NewCommand("check-attr", "-z")
Expand All @@ -39,6 +39,10 @@ func checkAttrCommand(gitRepo *git.Repository, treeish string, filenames, attrib
)
cancel = deleteTemporaryFile
}
} else if cached {
// read from existing index instead of work tree, in cases where the repo is bare and has an index or the work tree
// contains unstaged changes that shouldn't affect the attribute check
cmd.AddArguments("--cached")
} // else: no treeish, assume it is a not a bare repo, read from working directory

cmd.AddDynamicArguments(attributes...)
Expand All @@ -51,12 +55,13 @@ func checkAttrCommand(gitRepo *git.Repository, treeish string, filenames, attrib
type CheckAttributeOpts struct {
Filenames []string
Attributes []string
Cached bool
}

// CheckAttributes return the attributes of the given filenames and attributes in the given treeish.
// If treeish is empty, then it will use current working directory, otherwise it will use the provided treeish on the bare repo
func CheckAttributes(ctx context.Context, gitRepo *git.Repository, treeish string, opts CheckAttributeOpts) (map[string]*Attributes, error) {
cmd, envs, cancel, err := checkAttrCommand(gitRepo, treeish, opts.Filenames, opts.Attributes)
cmd, envs, cancel, err := checkAttrCommand(gitRepo, treeish, opts.Filenames, opts.Attributes, opts.Cached)
if err != nil {
return nil, err
}
Expand Down
13 changes: 12 additions & 1 deletion modules/git/attribute/checker_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,19 @@ func Test_Checker(t *testing.T) {
assert.Equal(t, expectedAttrs(), attrs["i-am-a-python.p"])
})

t.Run("Run git check-attr in bare repository using index", func(t *testing.T) {
attrs, err := CheckAttributes(t.Context(), gitRepo, "", CheckAttributeOpts{
Filenames: []string{"i-am-a-python.p"},
Attributes: LinguistAttributes,
Cached: true,
})
assert.NoError(t, err)
assert.Len(t, attrs, 1)
assert.Equal(t, expectedAttrs(), attrs["i-am-a-python.p"])
})

if !git.DefaultFeatures().SupportCheckAttrOnBare {
t.Skip("git version 2.40 is required to support run check-attr on bare repo")
t.Skip("git version 2.40 is required to support run check-attr on bare repo without using index")
return
}

Expand Down
2 changes: 2 additions & 0 deletions services/repository/files/update.go
Original file line number Diff line number Diff line change
Expand Up @@ -495,6 +495,8 @@ func CreateOrUpdateFile(ctx context.Context, t *TemporaryUploadRepository, file
attributesMap, err := attribute.CheckAttributes(ctx, t.gitRepo, "" /* use temp repo's working dir */, attribute.CheckAttributeOpts{
Attributes: []string{attribute.Filter},
Filenames: []string{file.Options.treePath},
// An index is set, so it's okay to list the attributes from it
Cached: true,
})
if err != nil {
return err
Expand Down
4 changes: 3 additions & 1 deletion services/repository/files/upload.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,10 +107,12 @@ func UploadRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use
}

var attributesMap map[string]*attribute.Attributes
if setting.LFS.StartServer {
if setting.LFS.StartServer && hasOldBranch {
attributesMap, err = attribute.CheckAttributes(ctx, t.gitRepo, "" /* use temp repo's working dir */, attribute.CheckAttributeOpts{
Attributes: []string{attribute.Filter},
Filenames: names,
// An index is set, so it's okay to list the attributes from it
Cached: true,
})
if err != nil {
return err
Expand Down
Loading