Merge branch 'master' into status-in-sub-directory
This commit is contained in:
commit
5899e91ad7
@ -34,7 +34,9 @@ setup and preferences.
|
|||||||
|
|
||||||
In addition, [binary packages](https://github.com/git-lfs/git-lfs/releases) are
|
In addition, [binary packages](https://github.com/git-lfs/git-lfs/releases) are
|
||||||
available for Linux, macOS, Windows, and FreeBSD. This repository can also be
|
available for Linux, macOS, Windows, and FreeBSD. This repository can also be
|
||||||
built-from-source using the latest version of [Go](https://golang.org).
|
built from source using the latest version of [Go](https://golang.org), and the
|
||||||
|
available instructions in our
|
||||||
|
[Wiki](https://github.com/git-lfs/git-lfs/wiki/Installation#source).
|
||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
|
@ -49,6 +49,8 @@ func trackCommand(cmd *cobra.Command, args []string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Intentionally do _not_ consider global- and system-level
|
||||||
|
// .gitattributes here.
|
||||||
knownPatterns := git.GetAttributePaths(cfg.LocalWorkingDir(), cfg.LocalGitDir())
|
knownPatterns := git.GetAttributePaths(cfg.LocalWorkingDir(), cfg.LocalGitDir())
|
||||||
lineEnd := getAttributeLineEnding(knownPatterns)
|
lineEnd := getAttributeLineEnding(knownPatterns)
|
||||||
if len(lineEnd) == 0 {
|
if len(lineEnd) == 0 {
|
||||||
@ -213,7 +215,7 @@ ArgsLoop:
|
|||||||
}
|
}
|
||||||
|
|
||||||
func listPatterns() {
|
func listPatterns() {
|
||||||
knownPatterns := git.GetAttributePaths(cfg.LocalWorkingDir(), cfg.LocalGitDir())
|
knownPatterns := getAllKnownPatterns()
|
||||||
if len(knownPatterns) < 1 {
|
if len(knownPatterns) < 1 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -228,6 +230,14 @@ func listPatterns() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func getAllKnownPatterns() []git.AttributePath {
|
||||||
|
knownPatterns := git.GetAttributePaths(cfg.LocalWorkingDir(), cfg.LocalGitDir())
|
||||||
|
knownPatterns = append(knownPatterns, git.GetRootAttributePaths(cfg.Git)...)
|
||||||
|
knownPatterns = append(knownPatterns, git.GetSystemAttributePaths(cfg.Os)...)
|
||||||
|
|
||||||
|
return knownPatterns
|
||||||
|
}
|
||||||
|
|
||||||
func getAttributeLineEnding(attribs []git.AttributePath) string {
|
func getAttributeLineEnding(attribs []git.AttributePath) string {
|
||||||
for _, a := range attribs {
|
for _, a := range attribs {
|
||||||
if a.Source.Path == ".gitattributes" {
|
if a.Source.Path == ".gitattributes" {
|
||||||
|
@ -59,6 +59,6 @@ to match paths.
|
|||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
|
|
||||||
git-lfs-untrack(1), git-lfs-install(1), gitattributes(5).
|
git-lfs-untrack(1), git-lfs-install(1), gitattributes(5), gitignore(5).
|
||||||
|
|
||||||
Part of the git-lfs(1) suite.
|
Part of the git-lfs(1) suite.
|
||||||
|
@ -85,3 +85,28 @@ commands and low level ("plumbing") commands.
|
|||||||
Git process filter that converts between large files and pointers.
|
Git process filter that converts between large files and pointers.
|
||||||
* git-lfs-smudge(1):
|
* git-lfs-smudge(1):
|
||||||
Git smudge filter that converts pointer in blobs to the actual content.
|
Git smudge filter that converts pointer in blobs to the actual content.
|
||||||
|
|
||||||
|
## EXAMPLES
|
||||||
|
|
||||||
|
To get started with Git LFS, the following commands can be used.
|
||||||
|
|
||||||
|
1. Setup Git LFS on your system. You only have to do this once per
|
||||||
|
repository per machine:
|
||||||
|
|
||||||
|
git lfs install
|
||||||
|
|
||||||
|
2. Choose the type of files you want to track, for examples all `ISO`
|
||||||
|
images, with git-lfs-track(1):
|
||||||
|
|
||||||
|
git lfs track "*.iso"
|
||||||
|
|
||||||
|
3. The above stores this information in gitattributes(5) files, so
|
||||||
|
that file need to be added to the repository:
|
||||||
|
|
||||||
|
git add .gitattributes
|
||||||
|
|
||||||
|
3. Commit, push and work with the files normally:
|
||||||
|
|
||||||
|
git add file.iso
|
||||||
|
git commit -m "Add disk image"
|
||||||
|
git push
|
||||||
|
122
git/attribs.go
122
git/attribs.go
@ -35,6 +35,36 @@ func (s *AttributeSource) String() string {
|
|||||||
return s.Path
|
return s.Path
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetRootAttributePaths beahves as GetRootAttributePaths, and loads information
|
||||||
|
// only from the global gitattributes file.
|
||||||
|
func GetRootAttributePaths(cfg Env) []AttributePath {
|
||||||
|
af, ok := cfg.Get("core.attributesfile")
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// The working directory for the root gitattributes file is blank.
|
||||||
|
return attrPaths(af, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSystemAttributePaths behaves as GetAttributePaths, and loads information
|
||||||
|
// only from the system gitattributes file, respecting the $PREFIX environment
|
||||||
|
// variable.
|
||||||
|
func GetSystemAttributePaths(env Env) []AttributePath {
|
||||||
|
prefix, _ := env.Get("PREFIX")
|
||||||
|
if len(prefix) == 0 {
|
||||||
|
prefix = string(filepath.Separator)
|
||||||
|
}
|
||||||
|
|
||||||
|
path := filepath.Join(prefix, "etc", "gitattributes")
|
||||||
|
|
||||||
|
if _, err := os.Stat(path); os.IsNotExist(err) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return attrPaths(path, "")
|
||||||
|
}
|
||||||
|
|
||||||
// GetAttributePaths returns a list of entries in .gitattributes which are
|
// GetAttributePaths returns a list of entries in .gitattributes which are
|
||||||
// configured with the filter=lfs attribute
|
// configured with the filter=lfs attribute
|
||||||
// workingDir is the root of the working copy
|
// workingDir is the root of the working copy
|
||||||
@ -43,58 +73,66 @@ func GetAttributePaths(workingDir, gitDir string) []AttributePath {
|
|||||||
paths := make([]AttributePath, 0)
|
paths := make([]AttributePath, 0)
|
||||||
|
|
||||||
for _, path := range findAttributeFiles(workingDir, gitDir) {
|
for _, path := range findAttributeFiles(workingDir, gitDir) {
|
||||||
attributes, err := os.Open(path)
|
paths = append(paths, attrPaths(path, workingDir)...)
|
||||||
if err != nil {
|
}
|
||||||
|
|
||||||
|
return paths
|
||||||
|
}
|
||||||
|
|
||||||
|
func attrPaths(path, workingDir string) []AttributePath {
|
||||||
|
attributes, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var paths []AttributePath
|
||||||
|
|
||||||
|
relfile, _ := filepath.Rel(workingDir, path)
|
||||||
|
reldir := filepath.Dir(relfile)
|
||||||
|
source := &AttributeSource{Path: relfile}
|
||||||
|
|
||||||
|
le := &lineEndingSplitter{}
|
||||||
|
scanner := bufio.NewScanner(attributes)
|
||||||
|
scanner.Split(le.ScanLines)
|
||||||
|
|
||||||
|
for scanner.Scan() {
|
||||||
|
line := strings.TrimSpace(scanner.Text())
|
||||||
|
|
||||||
|
if strings.HasPrefix(line, "#") {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
relfile, _ := filepath.Rel(workingDir, path)
|
// Check for filter=lfs (signifying that LFS is tracking
|
||||||
reldir := filepath.Dir(relfile)
|
// this file) or "lockable", which indicates that the
|
||||||
source := &AttributeSource{Path: relfile}
|
// file is lockable (and may or may not be tracked by
|
||||||
|
// Git LFS).
|
||||||
|
if strings.Contains(line, "filter=lfs") ||
|
||||||
|
strings.HasSuffix(line, "lockable") {
|
||||||
|
|
||||||
le := &lineEndingSplitter{}
|
fields := strings.Fields(line)
|
||||||
scanner := bufio.NewScanner(attributes)
|
pattern := fields[0]
|
||||||
scanner.Split(le.ScanLines)
|
if len(reldir) > 0 {
|
||||||
|
pattern = filepath.Join(reldir, pattern)
|
||||||
for scanner.Scan() {
|
|
||||||
line := strings.TrimSpace(scanner.Text())
|
|
||||||
|
|
||||||
if strings.HasPrefix(line, "#") {
|
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
// Find lockable flag in any position after pattern to avoid
|
||||||
// Check for filter=lfs (signifying that LFS is tracking
|
// edge case of matching "lockable" to a file pattern
|
||||||
// this file) or "lockable", which indicates that the
|
lockable := false
|
||||||
// file is lockable (and may or may not be tracked by
|
for _, f := range fields[1:] {
|
||||||
// Git LFS).
|
if f == LockableAttrib {
|
||||||
if strings.Contains(line, "filter=lfs") ||
|
lockable = true
|
||||||
strings.HasSuffix(line, "lockable") {
|
break
|
||||||
|
|
||||||
fields := strings.Fields(line)
|
|
||||||
pattern := fields[0]
|
|
||||||
if len(reldir) > 0 {
|
|
||||||
pattern = filepath.Join(reldir, pattern)
|
|
||||||
}
|
}
|
||||||
// Find lockable flag in any position after pattern to avoid
|
|
||||||
// edge case of matching "lockable" to a file pattern
|
|
||||||
lockable := false
|
|
||||||
for _, f := range fields[1:] {
|
|
||||||
if f == LockableAttrib {
|
|
||||||
lockable = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
paths = append(paths, AttributePath{
|
|
||||||
Path: pattern,
|
|
||||||
Source: source,
|
|
||||||
Lockable: lockable,
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
paths = append(paths, AttributePath{
|
||||||
|
Path: pattern,
|
||||||
|
Source: source,
|
||||||
|
Lockable: lockable,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
source.LineEnding = le.LineEnding()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
source.LineEnding = le.LineEnding()
|
||||||
|
|
||||||
return paths
|
return paths
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -49,13 +49,6 @@ func proxyFromClient(c *Client) func(req *http.Request) (*url.URL, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getProxyServers(u *url.URL, urlCfg *config.URLConfig, osEnv config.Environment) (httpsProxy string, httpProxy string, noProxy string) {
|
func getProxyServers(u *url.URL, urlCfg *config.URLConfig, osEnv config.Environment) (httpsProxy string, httpProxy string, noProxy string) {
|
||||||
if urlCfg != nil {
|
|
||||||
httpProxy, _ = urlCfg.Get("http", u.String(), "proxy")
|
|
||||||
if strings.HasPrefix(httpProxy, "https://") {
|
|
||||||
httpsProxy = httpProxy
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if osEnv == nil {
|
if osEnv == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@ -76,6 +69,16 @@ func getProxyServers(u *url.URL, urlCfg *config.URLConfig, osEnv config.Environm
|
|||||||
httpProxy, _ = osEnv.Get("http_proxy")
|
httpProxy, _ = osEnv.Get("http_proxy")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if urlCfg != nil {
|
||||||
|
gitProxy, ok := urlCfg.Get("http", u.String(), "proxy")
|
||||||
|
if len(gitProxy) > 0 && ok {
|
||||||
|
if strings.HasPrefix(gitProxy, "https://") {
|
||||||
|
httpsProxy = gitProxy
|
||||||
|
}
|
||||||
|
httpProxy = gitProxy
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
noProxy, _ = osEnv.Get("NO_PROXY")
|
noProxy, _ = osEnv.Get("NO_PROXY")
|
||||||
if len(noProxy) == 0 {
|
if len(noProxy) == 0 {
|
||||||
noProxy, _ = osEnv.Get("no_proxy")
|
noProxy, _ = osEnv.Get("no_proxy")
|
||||||
|
@ -20,7 +20,7 @@ func TestHttpsProxyFromGitConfig(t *testing.T) {
|
|||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
|
|
||||||
proxyURL, err := proxyFromClient(c)(req)
|
proxyURL, err := proxyFromClient(c)(req)
|
||||||
assert.Equal(t, "proxy-from-git-config:8080", proxyURL.Host)
|
assert.Equal(t, "proxy-from-env:8080", proxyURL.Host)
|
||||||
assert.Nil(t, err)
|
assert.Nil(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -558,3 +558,40 @@ begin_test "track (with current-directory prefix)"
|
|||||||
grep -e "^a.dat" .gitattributes
|
grep -e "^a.dat" .gitattributes
|
||||||
)
|
)
|
||||||
end_test
|
end_test
|
||||||
|
|
||||||
|
begin_test "track (global gitattributes)"
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
reponame="track-global-gitattributes"
|
||||||
|
git init "$reponame"
|
||||||
|
cd "$reponame"
|
||||||
|
|
||||||
|
global="$(cd .. && pwd)/gitattributes-global"
|
||||||
|
|
||||||
|
echo "*.dat filter=lfs diff=lfs merge=lfs -text" > "$global"
|
||||||
|
git config --local core.attributesfile "$global"
|
||||||
|
|
||||||
|
git lfs track 2>&1 | tee track.log
|
||||||
|
grep "*.dat" track.log
|
||||||
|
)
|
||||||
|
end_test
|
||||||
|
|
||||||
|
begin_test "track (system gitattributes)"
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
reponame="track-system-gitattributes"
|
||||||
|
git init "$reponame"
|
||||||
|
cd "$reponame"
|
||||||
|
|
||||||
|
pushd "$TRASHDIR" > /dev/null
|
||||||
|
mkdir -p "prefix/${reponame}/etc"
|
||||||
|
cd "prefix/${reponame}/etc"
|
||||||
|
echo "*.dat filter=lfs diff=lfs merge=lfs -text" > gitattributes
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
PREFIX="${TRASHDIR}/prefix/${reponame}" git lfs track 2>&1 | tee track.log
|
||||||
|
grep "*.dat" track.log
|
||||||
|
)
|
||||||
|
end_test
|
||||||
|
Loading…
Reference in New Issue
Block a user