Ability determine if gitattributes matches a file at a given ref/branch
What
We need to be able to look up values for a branch's .gitattributes
file. Currently we can only do this using info/attributes
from the default branch.
Ideally this behaviour would match git's normal behaviour, which might involve checking .gitattributes
files nested in subfolders and allowing filters to be overidden, cancelled out, etc. Some investigation might be required to see how rugged's approach (on bare repos) differs from using check-attr
normally.
Why
This is needed so we can determine if files match the LFS filter in https://gitlab.com/gitlab-org/gitlab-ce/issues/29876 and in https://gitlab.com/gitlab-org/gitlab-ce/issues/39785
.gitattributes order
https://git-scm.com/docs/gitattributes#_description:
When deciding what attributes are assigned to a path, Git consults $GIT_DIR/info/attributes file (which has the highest precedence), .gitattributes file in the same directory as the path in question, and its parent directories up to the toplevel of the work tree (the further the directory that contains .gitattributes is from the path in question, the lower its precedence). Finally global and system-wide files are considered (they have the lowest precedence).
Gitlab::Git::Attributes
model
Current This has been hardcoded to info/attributes
and can't handle .gitattributes
files individually, but can probably be reused either with a differnt path or by passing in the contents of .gitattributes
as a string.
The Attributes
class also overwrites rugged's methods in UseGitlabGitAttributes
.
What Rugged provides
For some reason this doesn't ask for a specific branch, even when using [:file, :index]
priority. Uses rugged_copy_gitattributes
for a given branch does make this work, but I'm not sure if it only ends up using info/attributes
.
Rugged allows different search strategies such as [:index, :file]
, [:index]
or :skip_system
, which change the flag passed in to fetch_attributes(file_path, nil, 0)
.
check-attr
with a temporary index
Using As suggested in https://gitlab.com/gitlab-org/gitlab-ce/issues/39785#note_52245379 it is possible to use check-attr
for this, using a temporary index file to workaround the limitations of bare repositories.
Using values set in the nested .gitattributes
file in https://gitlab.com/jamedjo/engine/blob/master/subdir/.gitattributes we get the following:
engine.git|master» GIT_INDEX_FILE=tmp-index git read-tree --reset -i master
engine.git|master» GIT_INDEX_FILE=tmp-index git check-attr --cached --all subdir/pointer.sub
subdir/pointer.sub: diff: lfs
subdir/pointer.sub: merge: lfs
subdir/pointer.sub: text: unset
subdir/pointer.sub: filter: lfs
Performance
We switched to Gitlab::Git::Attributes
for performance reasons in gitlab_git@340e111e. We might want to re-examine this before starting to use rugged again for this new scenario.
Related
- Support .gitattributes for bare repositories (libgit2#3676)
- https://gitlab.com/gitlab-org/gitlab-ce/issues/2315#note_4218925
- gitlab_git!73 (merged)
- gitlab_git@340e111e
- http://git.661346.n2.nabble.com/git-check-attr-problems-amp-questions-td4802038.html
- https://gitlab.com/gitlab-org/gitlab-ce/issues/20085