Merge branch 'master' into status-in-sub-directory

This commit is contained in:
Taylor Blau 2018-06-21 15:42:43 -05:00 committed by GitHub
commit 5899e91ad7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 168 additions and 53 deletions

@ -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

@ -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