From 5db937016a371a039458fc6e5694fee1644fc1fb Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Wed, 13 Jun 2018 12:24:15 -0500 Subject: [PATCH 01/11] lfsapi: prefer proxying from gitconfig before environment --- lfsapi/proxy.go | 17 ++++++++++------- lfsapi/proxy_test.go | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/lfsapi/proxy.go b/lfsapi/proxy.go index d67f2dcd..c7410774 100644 --- a/lfsapi/proxy.go +++ b/lfsapi/proxy.go @@ -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) { - if urlCfg != nil { - httpProxy, _ = urlCfg.Get("http", u.String(), "proxy") - if strings.HasPrefix(httpProxy, "https://") { - httpsProxy = httpProxy - } - } - if osEnv == nil { return } @@ -76,6 +69,16 @@ func getProxyServers(u *url.URL, urlCfg *config.URLConfig, osEnv config.Environm 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") if len(noProxy) == 0 { noProxy, _ = osEnv.Get("no_proxy") diff --git a/lfsapi/proxy_test.go b/lfsapi/proxy_test.go index ad98419b..e8e7e76a 100644 --- a/lfsapi/proxy_test.go +++ b/lfsapi/proxy_test.go @@ -20,7 +20,7 @@ func TestHttpsProxyFromGitConfig(t *testing.T) { require.Nil(t, err) 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) } From c6383b9ca36c29b6300828da48b532781c9d01f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= Date: Wed, 13 Jun 2018 17:25:17 -0400 Subject: [PATCH 02/11] add basic example in main manpage Every time I go back to git LFS after a long break, I wonder how it works and how to get started. The first manual page is currently a reference to a fairly large number of other manual pages and, as the core documentation of LFS, does not really help users in getting basic things done. In comparison, the LFS homepage has a good primer, so I have taken it as an example for a basic example that would work in the manual page to help users get out of the weeds quickly. --- docs/man/git-lfs.1.ronn | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/man/git-lfs.1.ronn b/docs/man/git-lfs.1.ronn index dc5cc42e..bd23ca10 100644 --- a/docs/man/git-lfs.1.ronn +++ b/docs/man/git-lfs.1.ronn @@ -82,3 +82,28 @@ commands and low level ("plumbing") commands. Git pre-push hook implementation. * git-lfs-smudge(1): 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 From 2e22042f90fa9f27894e8c0d79bd8e76f181da6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Antoine=20Beaupr=C3=A9?= Date: Wed, 13 Jun 2018 17:26:27 -0400 Subject: [PATCH 03/11] point to gitignore in track manpage We point to the online manual for gitignore, but it's not very useful when reading the manual pages with man or another offline manpage viewer. A more useful pointer is in the SEE ALSO section at the bottom. --- docs/man/git-lfs-track.1.ronn | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/man/git-lfs-track.1.ronn b/docs/man/git-lfs-track.1.ronn index 234880e6..41810bca 100644 --- a/docs/man/git-lfs-track.1.ronn +++ b/docs/man/git-lfs-track.1.ronn @@ -59,6 +59,6 @@ to match paths. ## 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. From 45289c68264c8b8f7d5889045e03dd5d449926ab Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Mon, 18 Jun 2018 18:52:36 -0500 Subject: [PATCH 04/11] README.md: add link to installation wiki page --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 8bc3c65b..07716375 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,9 @@ setup and preferences. 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 -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 From 44b7e44094719eaf3bc7f7470dcf3d2edcf63e5b Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Mon, 18 Jun 2018 19:18:48 -0500 Subject: [PATCH 05/11] git/attribs.go: extract attrPaths from GetAttributePaths --- git/attribs.go | 92 +++++++++++++++++++++++++++----------------------- 1 file changed, 50 insertions(+), 42 deletions(-) diff --git a/git/attribs.go b/git/attribs.go index fb690bf8..8cf81b1c 100644 --- a/git/attribs.go +++ b/git/attribs.go @@ -43,58 +43,66 @@ func GetAttributePaths(workingDir, gitDir string) []AttributePath { paths := make([]AttributePath, 0) for _, path := range findAttributeFiles(workingDir, gitDir) { - attributes, err := os.Open(path) - if err != nil { + paths = append(paths, attrPaths(path, workingDir)...) + } + + 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 } - relfile, _ := filepath.Rel(workingDir, path) - reldir := filepath.Dir(relfile) - source := &AttributeSource{Path: relfile} + // Check for filter=lfs (signifying that LFS is tracking + // this file) or "lockable", which indicates that the + // 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{} - scanner := bufio.NewScanner(attributes) - scanner.Split(le.ScanLines) - - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - - if strings.HasPrefix(line, "#") { - continue + fields := strings.Fields(line) + pattern := fields[0] + if len(reldir) > 0 { + pattern = filepath.Join(reldir, pattern) } - - // Check for filter=lfs (signifying that LFS is tracking - // this file) or "lockable", which indicates that the - // file is lockable (and may or may not be tracked by - // Git LFS). - if strings.Contains(line, "filter=lfs") || - strings.HasSuffix(line, "lockable") { - - 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 } - // 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 } From f99790b70bdf0ef9a89de6f63756e45a610b304e Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Mon, 18 Jun 2018 19:28:39 -0500 Subject: [PATCH 06/11] commands: extract getAllKnownPatterns() --- commands/command_track.go | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/commands/command_track.go b/commands/command_track.go index 5ba06925..a70bb28b 100644 --- a/commands/command_track.go +++ b/commands/command_track.go @@ -49,7 +49,7 @@ func trackCommand(cmd *cobra.Command, args []string) { return } - knownPatterns := git.GetAttributePaths(cfg.LocalWorkingDir(), cfg.LocalGitDir()) + knownPatterns := getAllKnownPatterns() lineEnd := getAttributeLineEnding(knownPatterns) if len(lineEnd) == 0 { lineEnd = gitLineEnding(cfg.Git) @@ -213,7 +213,7 @@ ArgsLoop: } func listPatterns() { - knownPatterns := git.GetAttributePaths(cfg.LocalWorkingDir(), cfg.LocalGitDir()) + knownPatterns := getAllKnownPatterns() if len(knownPatterns) < 1 { return } @@ -228,6 +228,12 @@ func listPatterns() { } } +func getAllKnownPatterns() []git.AttributePath { + knownPatterns := git.GetAttributePaths(cfg.LocalWorkingDir(), cfg.LocalGitDir()) + + return knownPatterns +} + func getAttributeLineEnding(attribs []git.AttributePath) string { for _, a := range attribs { if a.Source.Path == ".gitattributes" { From b0de5dc8831ca814d69a5f353497d97f4f96b854 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Mon, 18 Jun 2018 19:19:10 -0500 Subject: [PATCH 07/11] git/attribs.go: consider root attribute paths --- commands/command_track.go | 1 + git/attribs.go | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/commands/command_track.go b/commands/command_track.go index a70bb28b..5077c9fb 100644 --- a/commands/command_track.go +++ b/commands/command_track.go @@ -230,6 +230,7 @@ func listPatterns() { func getAllKnownPatterns() []git.AttributePath { knownPatterns := git.GetAttributePaths(cfg.LocalWorkingDir(), cfg.LocalGitDir()) + knownPatterns = append(knownPatterns, git.GetRootAttributePaths(cfg.Git)...) return knownPatterns } diff --git a/git/attribs.go b/git/attribs.go index 8cf81b1c..0f80e829 100644 --- a/git/attribs.go +++ b/git/attribs.go @@ -35,6 +35,18 @@ func (s *AttributeSource) String() string { 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, "") +} + // GetAttributePaths returns a list of entries in .gitattributes which are // configured with the filter=lfs attribute // workingDir is the root of the working copy From 1f0214adee47d55ee34e27797c945b15a9b5e777 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Mon, 18 Jun 2018 19:19:25 -0500 Subject: [PATCH 08/11] git/attribs.go: consider system attribute paths --- commands/command_track.go | 1 + git/attribs.go | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/commands/command_track.go b/commands/command_track.go index 5077c9fb..94a43c08 100644 --- a/commands/command_track.go +++ b/commands/command_track.go @@ -231,6 +231,7 @@ 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 } diff --git a/git/attribs.go b/git/attribs.go index 0f80e829..6a033b55 100644 --- a/git/attribs.go +++ b/git/attribs.go @@ -47,6 +47,24 @@ func GetRootAttributePaths(cfg Env) []AttributePath { 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 // configured with the filter=lfs attribute // workingDir is the root of the working copy From 719921585e7a655a1de4458b18f7891b04506b6a Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Mon, 18 Jun 2018 19:30:46 -0500 Subject: [PATCH 09/11] test/test-track: examine global gitattributes --- test/test-track.sh | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/test/test-track.sh b/test/test-track.sh index 02ff7ce0..453e27a0 100755 --- a/test/test-track.sh +++ b/test/test-track.sh @@ -558,3 +558,21 @@ begin_test "track (with current-directory prefix)" grep -e "^a.dat" .gitattributes ) 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 From 0cdbe90662a1876866a582af1f0a8690b2f63fa2 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Mon, 18 Jun 2018 19:42:22 -0500 Subject: [PATCH 10/11] test/test-track: examine system gitattributes --- test/test-track.sh | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/test/test-track.sh b/test/test-track.sh index 453e27a0..3823a1c7 100755 --- a/test/test-track.sh +++ b/test/test-track.sh @@ -576,3 +576,22 @@ begin_test "track (global gitattributes)" 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 From 707a7175a70cc2c25df9552090ecd2d019fdff35 Mon Sep 17 00:00:00 2001 From: Taylor Blau Date: Mon, 18 Jun 2018 19:55:27 -0500 Subject: [PATCH 11/11] commands/command_track: allow overwriting repository-level patterns --- commands/command_track.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/commands/command_track.go b/commands/command_track.go index 94a43c08..8d160dcb 100644 --- a/commands/command_track.go +++ b/commands/command_track.go @@ -49,7 +49,9 @@ func trackCommand(cmd *cobra.Command, args []string) { return } - knownPatterns := getAllKnownPatterns() + // Intentionally do _not_ consider global- and system-level + // .gitattributes here. + knownPatterns := git.GetAttributePaths(cfg.LocalWorkingDir(), cfg.LocalGitDir()) lineEnd := getAttributeLineEnding(knownPatterns) if len(lineEnd) == 0 { lineEnd = gitLineEnding(cfg.Git)