--- /dev/null
+version: 2
+
+jobs:
+ bootstrap:
+ macos:
+ xcode: "9.2.0"
+ working_directory: ~/go/src/github.com/git-lfs/git-lfs
+ steps:
+ - checkout
+ - run: brew update
+ - run: brew prune
+ - run: brew upgrade go || brew install go
+ - run: brew upgrade git || brew install git
+ - run: brew upgrade gettext || brew install gettext
+ - run:
+ command: git clone https://github.com/git/git.git git-source
+ working_directory: ~/go/src/github.com/git-lfs/git-lfs
+ - run: echo "export GOPATH=$HOME/go" >> $BASH_ENV
+ - run: go get -d -v github.com/spf13/cobra
+ - run: go get -d -v github.com/ThomsonReutersEikon/go-ntlm/ntlm
+ - save_cache:
+ key: git-lfs-{{ .Branch }}-{{ .Revision }}
+ paths:
+ - /usr/local/Cellar
+ - ~/go
+
+ build_with_system_git:
+ macos:
+ xcode: "9.2.0"
+ working_directory: ~/go/src/github.com/git-lfs/git-lfs
+ environment:
+ GIT_SOURCE_REPO: https://github.com/git/git.git
+ steps:
+ - restore_cache:
+ key: git-lfs-{{ .Branch }}-{{ .Revision }}
+ - run: echo go gettext | xargs brew link --force
+ - run: echo "export GOPATH=$HOME/go" >> $BASH_ENV
+ - run: echo "export PATH=$HOME/bin:$GOPATH/bin:$PATH" >> $BASH_ENV
+ - run: echo "export GIT_LFS_TEST_DIR=$HOME/git-lfs-tests" >> $BASH_ENV
+ - run: script/cibuild
+
+ build_with_earliest_supported_git:
+ macos:
+ xcode: "9.2.0"
+ working_directory: ~/go/src/github.com/git-lfs/git-lfs
+ environment:
+ GIT_EARLIEST_SUPPORTED_VERSION: v2.0.0
+ GIT_SOURCE_REPO: https://github.com/git/git.git
+ steps:
+ - restore_cache:
+ key: git-lfs-{{ .Branch }}-{{ .Revision }}
+ - run: echo go gettext | xargs brew link --force
+ - run:
+ command: ./script/install-git-source "$GIT_EARLIEST_SUPPORTED_VERSION"
+ environment:
+ NO_OPENSSL: YesPlease
+ APPLE_COMMON_CRYPTO: YesPlease
+ - run: echo "export GOPATH=$HOME/go" >> $BASH_ENV
+ - run: echo "export PATH=$HOME/bin:$GOPATH/bin:$PATH" >> $BASH_ENV
+ - run: echo "export GIT_LFS_TEST_DIR=$HOME/git-lfs-tests" >> $BASH_ENV
+ - run: script/cibuild
+
+ build_with_latest_git:
+ macos:
+ xcode: "9.2.0"
+ working_directory: ~/go/src/github.com/git-lfs/git-lfs
+ environment:
+ GIT_LATEST_SOURCE_BRANCH: master
+ GIT_SOURCE_REPO: https://github.com/git/git.git
+ steps:
+ - restore_cache:
+ key: git-lfs-{{ .Branch }}-{{ .Revision }}
+ - run: echo go gettext | xargs brew link --force
+ - run:
+ command: ./script/install-git-source "$GIT_LATEST_SOURCE_BRANCH"
+ environment:
+ NO_OPENSSL: YesPlease
+ APPLE_COMMON_CRYPTO: YesPlease
+ - run: echo "export GOPATH=$HOME/go" >> $BASH_ENV
+ - run: echo "export PATH=$HOME/bin:$GOPATH/bin:$PATH" >> $BASH_ENV
+ - run: echo "export GIT_LFS_TEST_DIR=$HOME/git-lfs-tests" >> $BASH_ENV
+ - run: script/cibuild
+
+workflows:
+ version: 2
+ build:
+ jobs:
+ - bootstrap
+ - build_with_earliest_supported_git:
+ requires:
+ - bootstrap
+ - build_with_latest_git:
+ requires:
+ - bootstrap
+ - build_with_system_git:
+ requires:
+ - bootstrap
# Git LFS Changelog
+### 2.4.1 (18 May, 2018)
+
+This release fixes a handful of bugs found and fixed since v2.4.0. In
+particular, Git LFS no longer panic()'s after invalid API responses, can
+correctly run 'fetch' on SHAs instead of references, migrates symbolic links
+correctly, and avoids writing to `$HOME/.gitconfig` more than is necessary.
+
+We would like to extend a "thank you" to the following contributors for their
+gracious patches:
+
+- @QuLogic fixed an issue with running tests that require credentials
+- @patrickmarlier made it possible for 'git lfs migrate import' to work
+ correctly with symbolic links.
+- @zackse fixed an inconsistency in `CONTRIBUTING.md`
+- @zanglang fixed an inconsistency in `README.md`
+
+Git LFS would not be possible without generous contributions from the
+open-source community. For these, and many more: thank you!
+
+### Features
+
+* script/packagecloud.rb: release on Ubuntu Bionic #2961 (@ttaylorr)
+
+### Bugs
+
+* lfsapi: canonicalize extra HTTP headers #3010 (@ttaylorr)
+* commands/lock: follow symlinks before locking #2996 (@ttaylorr)
+* lfs/attribute.go: remove default value from upgradeables #2994 (@ttaylorr)
+* git: include SHA1 in ref-less revisions #2982 (@ttaylorr)
+* Do not migrate the symlinks to LFS objects. #2983 (@patrickmarlier)
+* commands/uninstall: do not log about global hooks with --local #2976 (@ttaylorr)
+* commands/run.go: exit 127 on unknown sub-command #2969 (@ttaylorr)
+* commands/{un,}track: perform "prefix-agnostic" comparisons #2955 (@ttaylorr)
+* commands/migrate: escape paths before .gitattributes #2933 (@ttaylorr)
+* commands/ls-files: do not accept '--all' after '--' #2932 (@ttaylorr)
+* tq: prevent uint64 underflow with invalid API response #2902 (@ttaylorr)
+
+### Misc
+
+* test/test-env: skip comparing GIT_EXEC_PATH #3015 (@ttaylorr)
+* remove reference to CLA from contributor's guide #2997 (@zackse)
+* .gitattributes link is broken #2985 (@zanglang)
+* commands: make --version a synonym for 'version' #2968, #3017 (@ttaylorr)
+* test: ensure that git-mergetool(1) works with large files #2939 (@ttaylorr)
+* README.md: note the correct PackageCloud URL #2960 (@ttaylorr)
+* README.md: mention note about `git lfs track` retroactively #2948 (@ttaylorr)
+* README.md: reorganize into Core Team, Alumni #2941 (@ttaylorr)
+* README.md: :nail_care: #2942 (@ttaylorr)
+* circle.yml: upgrade to 'version: 2' syntax #2928 (@ttaylorr)
+* Use unique repo name for tests that require credentials. #2901 (@QuLogic)
+
## 2.4.0 (2 March, 2018)
This release introduces a rewrite of the underlying file matching engine,
0. Create a new branch based on `master`: `git checkout -b <my-branch-name> master`
0. Make your change, add tests, and make sure the tests still pass
0. Push to your fork and [submit a pull request][pr] from your branch to `master`
-0. Accept the [GitHub CLA][cla]
0. Pat yourself on the back and wait for your pull request to be reviewed
Here are a few things you can do that will increase the likelihood of your pull request being accepted:
[fork]: https://github.com/git-lfs/git-lfs/fork
[pr]: https://github.com/git-lfs/git-lfs/compare
[style]: https://github.com/golang/go/wiki/CodeReviewComments
-[cla]: https://cla.github.com/git-lfs/git-lfs/accept
[5]: https://ci.appveyor.com/api/projects/status/46a5yoqc3hk59bl5/branch/master?svg=true
[6]: https://ci.appveyor.com/project/git-lfs/git-lfs/branch/master
-Git LFS is a command line extension and [specification](docs/spec.md) for
-managing large files with Git. The client is written in Go, with pre-compiled
-binaries available for Mac, Windows, Linux, and FreeBSD. Check out the
-[Git LFS website][page] for an overview of features.
+[Git LFS](https://git-lfs.github.com) is a command line extension and
+[specification](docs/spec.md) for managing large files with Git.
-[page]: https://git-lfs.github.com/
+The client is written in Go, with pre-compiled binaries available for Mac,
+Windows, Linux, and FreeBSD. Check out the [website](http://git-lfs.github.com)
+for an overview of features.
## Getting Started
-By default, the Git LFS client needs a Git LFS server to sync the large files
-it manages. This works out of the box when using popular git repository
-hosting providers like GitHub, Atlassian, etc. When you host your own
-vanilla git server, for example, you need to either use a separate
-[Git LFS server instance](https://github.com/git-lfs/git-lfs/wiki/Implementations),
-or use the [custom transfer adapter](docs/custom-transfers.md) with
-a transfer agent in blind mode, without having to use a Git LFS server instance.
+### Installation
-You can install the Git LFS client in several different ways, depending on
-your setup and preferences.
+You can install the Git LFS client in several different ways, depending on your
+setup and preferences.
-* Linux users can install Debian or RPM packages from [PackageCloud](https://packagecloud.io/github/git-lfs/install). See the [Installation Guide](./INSTALLING.md) for details.
-* Mac users can install from [Homebrew](https://github.com/Homebrew/homebrew) with `brew install git-lfs`, or from [MacPorts](https://www.macports.org) with `port install git-lfs`.
-* Windows users can install from [Chocolatey](https://chocolatey.org/) with `choco install git-lfs`.
-* [Binary packages are available][rel] for Windows, Mac, Linux, and FreeBSD.
-* You can build it with Go 1.8.1+. See the [Contributing Guide](./CONTRIBUTING.md) for instructions.
+* **Linux users**. Debian and RPM packages are available from
+ [PackageCloud](https://packagecloud.io/github/git-lfs/install).
+* **macOS users**. [Homebrew](https://brew.sh) bottles are distributed, and can
+ be installed via `brew install git-lfs`.
+* **Windows users**. Chocolatey packages are distributed, and can be installed
+ via `choco install git-lfs`.
-[rel]: https://github.com/git-lfs/git-lfs/releases
+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).
-Note: Git LFS requires Git v1.8.5 or higher.
+### Usage
-Once installed, you need to setup the global Git hooks for Git LFS. This only
-needs to be done once per machine.
+Git LFS requires a global installation once per-machine. This can be done by
+running:
```bash
$ git lfs install
```
-Now, it's time to add some large files to a repository. The first step is to
-specify file patterns to store with Git LFS. These file patterns are stored in
-`.gitattributes`.
+To begin using Git LFS within your Git repository, you can indicate which files
+you would like Git LFS to manage. This can be done by running the following
+_from within Git repository_:
```bash
-$ mkdir large-repo
-$ cd large-repo
-$ git init
-
-# Add all zip files through Git LFS
-$ git lfs track "*.zip"
+$ git lfs track "*.psd"
```
-Now you're ready to push some commits:
+(Where `*.psd` is the pattern of filenames that you wish to track. You can read
+more about this pattern syntax
+[here](https://git-scm.com/docs/gitattributes)).
+
+After any invocation of `git-lfs-track(1)` or `git-lfs-untrack(1)`, you _must
+commit changes to your `.gitattributes` file_. This can be done by running:
```bash
$ git add .gitattributes
-$ git add my.zip
-$ git commit -m "add zip"
+$ git commit -m "track *.psd files using Git LFS"
```
-You can confirm that Git LFS is managing your zip file:
+You can now interact with your Git repository as usual, and Git LFS will take
+care of managing your large files. For example, changing a file named `my.psd`
+(tracked above via `*.psd`):
+
+```bash
+$ git add my.psd
+$ git commit -m "add psd"
+```
+
+> _Tip:_ if you have large files already in your repository's history, `git lfs
+> track` will _not_ track them retroactively. To migrate existing large files
+> in your history to use Git LFS, use `git lfs migrate`. For example:
+>
+> ```
+> $ git lfs migrate import --include="*.psd"
+> ```
+>
+> For more information, read [`git-lfs-migrate(1)`](https://github.com/git-lfs/git-lfs/blob/master/docs/man/git-lfs-migrate.1.ronn).
+
+You can confirm that Git LFS is managing your PSD file:
```bash
$ git lfs ls-files
-my.zip
+3c2f7aedfb * my.psd
```
Once you've made your commits, push your files to the Git remote:
```bash
$ git push origin master
-Sending my.zip
-LFS: 12.58 MB / 12.58 MB 100.00 %
-Counting objects: 2, done.
-Delta compression using up to 8 threads.
-Compressing objects: 100% (5/5), done.
-Writing objects: 100% (5/5), 548 bytes | 0 bytes/s, done.
-Total 5 (delta 1), reused 0 (delta 0)
+Uploading LFS objects: 100% (1/1), 810 B, 1.2 KB/s
+# ...
To https://github.com/git-lfs/git-lfs-test
67fcf6a..47b2002 master -> master
```
+Note: Git LFS requires Git v1.8.5 or higher.
+
## Limitations
Git LFS maintains a list of currently known limitations, which you can find and
```
The [official documentation](docs) has command references and specifications for
-the tool. You can ask questions in the [Git LFS chat room][chat], or [file a new
-issue][ish]. Be sure to include details about the problem so we can
-troubleshoot it.
+the tool.
-1. Include the output of `git lfs env`, which shows how your Git environment
-is setup.
-2. Include `GIT_TRACE=1` in any bad Git commands to enable debug messages.
-3. If the output includes a message like `Errors logged to /path/to/.git/lfs/objects/logs/*.log`,
-throw the contents in the issue, or as a link to a Gist or paste site.
+You can always [open an issue](https://github.com/git-lfs/git-lfs/issues), and
+one of the Core Team members will respond to you. Please be sure to include:
-[chat]: https://gitter.im/git-lfs/git-lfs
-[ish]: https://github.com/git-lfs/git-lfs/issues
+1. The output of `git lfs env`, which displays helpful information about your
+ Git repository useful in debugging.
+2. Any failed commands re-run with `GIT_TRACE=1` in the environment, which
+ displays additional information pertaining to why a command crashed.
## Contributing
See [CONTRIBUTING.md](CONTRIBUTING.md) for info on working on Git LFS and
sending patches. Related projects are listed on the [Implementations wiki
-page][impl]. You can also join [the project's chat room][chat].
+page](https://github.com/git-lfs/git-lfs/wiki/Implementations).
+
+## Core Team
+
+These are the humans that form the Git LFS core team, which runs the project.
-[impl]: https://github.com/git-lfs/git-lfs/wiki/Implementations
+In alphabetical order:
-### Using LFS from other Go code
+| [@larsxschneider][larsxschneider-user] | [@ttaylorr][ttaylorr-user] |
+|---|---|
+| [![][larsxschneider-img]][larsxschneider-user] | [![][ttaylorr-img]][ttaylorr-user] |
-At the moment git-lfs is only focussed on the stability of its command line
-interface, and the [server APIs](docs/api/README.md). The contents of the
-source packages is subject to change. We therefore currently discourage other
-Go code from depending on the git-lfs packages directly; an API to be used by
-external Go code may be provided in future.
+[larsxschneider-img]: https://avatars1.githubusercontent.com/u/477434?s=100&v=4
+[ttaylorr-img]: https://avatars2.githubusercontent.com/u/443245?s=100&v=4
+[larsxschneider-user]: https://github.com/larsxschneider
+[ttaylorr-user]: https://github.com/ttaylorr
-## Core Team
+### Alumni
-These are the humans that form the Git LFS core team, which runs the project.
+These are the humans that have in the past formed the Git LFS core team, or
+have otherwise contributed a significant amount to the project. Git LFS would
+not be possible without them.
In alphabetical order:
-| [@andyneff](https://github.com/andyneff) | [@rubyist](https://github.com/rubyist) | [@sinbad](https://github.com/sinbad) | [@technoweenie](https://github.com/technoweenie) | [@ttaylorr](https://github.com/ttaylorr) |
-|---|---|---|---|---|
-| [![](https://avatars1.githubusercontent.com/u/7596961?v=3&s=100)](https://github.com/andyneff) | [![](https://avatars1.githubusercontent.com/u/143?v=3&s=100)](https://github.com/rubyist) | [![](https://avatars1.githubusercontent.com/u/142735?v=3&s=100)](https://github.com/sinbad) | [![](https://avatars3.githubusercontent.com/u/21?v=3&s=100)](https://github.com/technoweenie) | [![](https://avatars3.githubusercontent.com/u/443245?v=3&s=100)](https://github.com/ttaylorr) |
+| [@andyneff][andyneff-user] | [@rubyist][rubyist-user] | [@sinbad][sinbad-user] | [@technoweenie][technoweenie-user] |
+|---|---|---|---|
+| [![][andyneff-img]][andyneff-user] | [![][rubyist-img]][rubyist-user] | [![][sinbad-img]][sinbad-user] | [![][technoweenie-img]][technoweenie-user] |
+
+[andyneff-img]: https://avatars1.githubusercontent.com/u/7596961?v=3&s=100
+[rubyist-img]: https://avatars1.githubusercontent.com/u/143?v=3&s=100
+[sinbad-img]: https://avatars1.githubusercontent.com/u/142735?v=3&s=100
+[technoweenie-img]: https://avatars3.githubusercontent.com/u/21?v=3&s=100
+[andyneff-user]: https://github.com/andyneff
+[sinbad-user]: https://github.com/sinbad
+[rubyist-user]: https://github.com/rubyist
+[technoweenie-user]: https://github.com/technoweenie
+++ /dev/null
-machine:
- environment:
- GIT_LFS_TEST_DIR: $HOME/git-lfs-tests
- GIT_SOURCE_REPO: https://github.com/git/git.git
- GIT_EARLIEST_SUPPORTED_VERSION: v2.0.0
- GIT_LATEST_SOURCE_BRANCH: master
- XCODE_SCHEME: test
- XCODE_WORKSPACE: test
- XCODE_PROJECT: test
- GOPATH: $HOME/git-lfs/.go
- NO_OPENSSL: YesPlease
- APPLE_COMMON_CRYPTO: YesPlease
- xcode:
- version: 8.2
-
-general:
- build_dir: .go/src/github.com/git-lfs/git-lfs
-
-checkout:
- post:
- - mkdir -p ~/git-lfs/.go/src/github.com/git-lfs
- - ln -s ~/git-lfs ~/git-lfs/.go/src/github.com/git-lfs
-
-dependencies:
- pre:
- - brew update
- - brew prune
- - brew upgrade go || brew install go
- - brew upgrade git || brew install git
- - brew upgrade gettext || brew install gettext
- - brew link --force gettext
- - git clone $GIT_SOURCE_REPO git-source
- override:
- - script/bootstrap
-
- # needed for git-lfs-test-server-api
- - go get -d -v github.com/spf13/cobra
- - go get -d -v github.com/ThomsonReutersEikon/go-ntlm/ntlm
-
-test:
- override:
- - script/cibuild
- - script/install-git-source "$GIT_EARLIEST_SUPPORTED_VERSION"
- - PATH="$HOME/bin:$PATH" SKIPCOMPILE=1 script/integration
- - script/install-git-source "$GIT_LATEST_SOURCE_BRANCH"
- - PATH="$HOME/bin:$PATH" SKIPCOMPILE=1 script/integration
if err != nil {
return "", err
}
+ wd, err = filepath.EvalSymlinks(wd)
+ if err != nil {
+ return "", errors.Wrapf(err,
+ "could not follow symlinks for %s", wd)
+ }
abs := filepath.Join(wd, file)
path := strings.TrimPrefix(abs, repo)
seen := make(map[string]struct{})
gitscanner := lfs.NewGitScanner(func(p *lfs.WrappedPointer, err error) {
+ if err != nil {
+ Exit("Could not scan for Git LFS tree: %s", err)
+ return
+ }
+
if !lsFilesScanAll {
if _, ok := seen[p.Name]; ok {
return
}
}
- if err != nil {
- Exit("Could not scan for Git LFS tree: %s", err)
- return
- }
-
if debug {
Print(
"filepath: %s\n"+
tracked := tools.NewOrderedSet()
for _, include := range filter.Include() {
- tracked.Add(fmt.Sprintf("%s filter=lfs diff=lfs merge=lfs -text", include))
+ tracked.Add(fmt.Sprintf("%s filter=lfs diff=lfs merge=lfs -text", escapeAttrPattern(include)))
}
for _, exclude := range filter.Exclude() {
- tracked.Add(fmt.Sprintf("%s text -filter -merge -diff", exclude))
+ tracked.Add(fmt.Sprintf("%s text -filter -merge -diff", escapeAttrPattern(exclude)))
}
return tracked
var writeablePatterns []string
ArgsLoop:
for _, unsanitizedPattern := range args {
- pattern := cleanRootPath(unsanitizedPattern)
+ pattern := trimCurrentPrefix(cleanRootPath(unsanitizedPattern))
if !trackNoModifyAttrsFlag {
for _, known := range knownPatterns {
if known.Path == filepath.Join(relpath, pattern) &&
}
// Generate the new / changed attrib line for merging
- encodedArg := escapeTrackPattern(pattern)
+ encodedArg := escapeAttrPattern(pattern)
lockableArg := ""
if trackLockableFlag { // no need to test trackNotLockableFlag, if we got here we're disabling
lockableArg = " " + git.LockableAttrib
writeablePatterns = append(writeablePatterns, pattern)
}
- Print("Tracking %q", unescapeTrackPattern(encodedArg))
+ Print("Tracking %q", unescapeAttrPattern(encodedArg))
}
// Now read the whole local attributes file and iterate over the contents,
}
)
-func escapeTrackPattern(unescaped string) string {
+func escapeAttrPattern(unescaped string) string {
var escaped string = strings.Replace(unescaped, `\`, "/", -1)
for from, to := range trackEscapePatterns {
return escaped
}
-func unescapeTrackPattern(escaped string) string {
+func unescapeAttrPattern(escaped string) string {
var unescaped string = escaped
for to, from := range trackEscapePatterns {
uninstallHooksCommand(cmd, args)
}
- Print("Global Git LFS configuration has been removed.")
+ if !localInstall {
+ Print("Global Git LFS configuration has been removed.")
+ }
}
// uninstallHooksCmd removes any hooks created by Git LFS.
path := strings.Fields(line)[0]
if removePath(path, args) {
- Print("Untracking %q", unescapeTrackPattern(path))
+ Print("Untracking %q", unescapeAttrPattern(path))
} else {
attributesFile.WriteString(line + "\n")
}
}
func removePath(path string, args []string) bool {
+ withoutCurrentDir := trimCurrentPrefix(path)
for _, t := range args {
- if path == escapeTrackPattern(t) {
+ if withoutCurrentDir == escapeAttrPattern(trimCurrentPrefix(t)) {
return true
}
}
}
}
+const (
+ windowsPrefix = `.\`
+ nixPrefix = `./`
+)
+
+// trimCurrentPrefix removes a leading prefix of "./" or ".\" (referring to the
+// current directory in a platform independent manner).
+//
+// It is useful for callers such as "git lfs track" and "git lfs untrack", that
+// wish to compare filepaths and/or attributes patterns without cleaning across
+// multiple platforms.
+func trimCurrentPrefix(p string) string {
+ if strings.HasPrefix(p, windowsPrefix) {
+ return strings.TrimPrefix(p, windowsPrefix)
+ }
+ return strings.TrimPrefix(p, nixPrefix)
+}
+
type env interface {
Get(string) (string, bool)
}
var (
commandFuncs []func() *cobra.Command
commandMu sync.Mutex
+
+ rootVersion bool
)
// NewCommand creates a new 'git-lfs' sub command, given a command name and
// Run initializes the 'git-lfs' command and runs it with the given stdin and
// command line args.
-func Run() {
+//
+// It returns an exit code.
+func Run() int {
log.SetOutput(ErrorWriter)
root := NewCommand("git-lfs", gitlfsCommand)
root.SetHelpFunc(helpCommand)
root.SetUsageFunc(usageCommand)
+ root.Flags().BoolVarP(&rootVersion, "version", "v", false, "")
+
cfg = config.New()
for _, f := range commandFuncs {
}
}
- root.Execute()
+ err := root.Execute()
closeAPIClient()
+
+ if err != nil {
+ return 127
+ }
+ return 0
}
func gitlfsCommand(cmd *cobra.Command, args []string) {
versionCommand(cmd, args)
- cmd.Usage()
+ if !rootVersion {
+ cmd.Usage()
+ }
}
func helpCommand(cmd *cobra.Command, args []string) {
)
const (
- Version = "2.4.0"
+ Version = "2.4.1"
)
func init() {
+git-lfs (2.4.1) stable; urgency=low
+
+ * New upstream version
+
+ -- Taylor Blau <me@ttaylorr.com> Mon, 21 May 2018 14:29:00 +0000
+
git-lfs (2.4.0) stable; urgency=low
* New upstream version
}
}()
- commands.Run()
+ code := commands.Run()
once.Do(commands.Cleanup)
+ os.Exit(code)
}
if len(lines) == 1 {
// ref is a sha1 and has no symbolic-full-name
- fullref.Name = lines[0] // fullref.Sha
+ fullref.Name = lines[0]
+ fullref.Sha = lines[0]
fullref.Type = RefTypeOther
return fullref, nil
}
continue
}
+ // If this is a symlink, skip it
+ if entry.Filemode == 0120000 {
+ entries = append(entries, copyEntry(entry))
+ continue
+ }
+
if cached := r.uncacheEntry(entry); cached != nil {
entries = append(entries, copyEntry(cached))
continue
"process": "git-lfs filter-process",
"required": "true",
},
- Upgradeables: upgradeables(),
+ Upgradeables: map[string][]string{
+ "clean": []string{
+ "git-lfs clean %f",
+ },
+ "smudge": []string{
+ "git-lfs smudge %f",
+ "git-lfs smudge --skip %f",
+ "git-lfs smudge --skip -- %f",
+ },
+ "process": []string{
+ "git-lfs filter",
+ "git-lfs filter --skip",
+ "git-lfs filter-process --skip",
+ },
+ },
}
}
"process": "git-lfs filter-process --skip",
"required": "true",
},
- Upgradeables: upgradeables(),
- }
-}
-
-func upgradeables() map[string][]string {
- return map[string][]string{
- "clean": []string{"git-lfs clean %f"},
- "smudge": []string{
- "git-lfs smudge %f",
- "git-lfs smudge --skip %f",
- "git-lfs smudge -- %f",
- "git-lfs smudge --skip -- %f",
- },
- "process": []string{
- "git-lfs filter",
- "git-lfs filter --skip",
- "git-lfs filter-process",
- "git-lfs filter-process --skip",
+ Upgradeables: map[string][]string{
+ "clean": []string{
+ "git-lfs clean -- %f",
+ },
+ "smudge": []string{
+ "git-lfs smudge %f",
+ "git-lfs smudge --skip %f",
+ "git-lfs smudge -- %f",
+ },
+ "process": []string{
+ "git-lfs filter",
+ "git-lfs filter --skip",
+ "git-lfs filter-process",
+ },
},
}
}
}
func requestHasAuth(req *http.Request) bool {
+ // The "Authorization" string constant is safe, since we assume that all
+ // request headers have been canonicalized.
if len(req.Header.Get("Authorization")) > 0 {
return true
}
"io"
"net"
"net/http"
+ "net/textproto"
"net/url"
"os"
"regexp"
}
k, v := parts[0], strings.TrimSpace(parts[1])
+ // If header keys are given in non-canonicalized form (e.g.,
+ // "AUTHORIZATION" as opposed to "Authorization") they will not
+ // be returned in calls to net/http.Header.Get().
+ //
+ // So, we avoid this problem by first canonicalizing header keys
+ // for extra headers.
+ k = textproto.CanonicalMIMEHeaderKey(k)
m[k] = append(m[k], v)
}
Name: git-lfs
-Version: 2.4.0
+Version: 2.4.1
Release: 1%{?dist}
Summary: Git extension for versioning large files
ubuntu/yakkety
ubuntu/zesty
ubuntu/artful
+ ubuntu/bionic
),
}
}
func missingRequiredCreds(w http.ResponseWriter, r *http.Request, repo string) bool {
- if repo != "requirecreds" {
+ if !strings.HasPrefix(repo, "requirecreds") {
return false
}
(
set -e
- reponame="requirecreds"
+ reponame="requirecreds-lfsurl"
setup_remote_repo "$reponame"
- clone_repo "$reponame" requirecreds-lfsurl
+ clone_repo "$reponame" "$reponame"
git lfs track "*.dat"
echo "push a" > a.dat
(
set -e
- reponame="requirecreds"
+ reponame="requirecreds-remoteurl"
setup_remote_repo "$reponame"
- clone_repo "$reponame" requirecreds-remoteurl
+ clone_repo "$reponame" "$reponame"
git lfs track "*.dat"
echo "push b" > b.dat
%s
%s
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual"
)
%s
%s
' "$(git lfs version)" "$(git version)" "$endpoint" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual"
cd .git
expected2=$(echo "$expected" | sed -e 's/LocalWorkingDir=.*/LocalWorkingDir=/')
- actual2=$(git lfs env)
+ actual2=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected2" "$actual2"
)
end_test
%s
%s
' "$(git lfs version)" "$(git version)" "$endpoint" "$endpoint2" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual"
cd .git
expected2=$(echo "$expected" | sed -e 's/LocalWorkingDir=.*/LocalWorkingDir=/')
- actual2=$(git lfs env)
+ actual2=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected2" "$actual2"
)
end_test
%s
%s
' "$(git lfs version)" "$(git version)" "$endpoint" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual"
cd .git
expected2=$(echo "$expected" | sed -e 's/LocalWorkingDir=.*/LocalWorkingDir=/')
- actual2=$(git lfs env)
+ actual2=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected2" "$actual2"
)
end_test
%s
%s
' "$(git lfs version)" "$(git version)" "$endpoint" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual"
cd .git
expected2=$(echo "$expected" | sed -e 's/LocalWorkingDir=.*/LocalWorkingDir=/')
- actual2=$(git lfs env)
+ actual2=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected2" "$actual2"
)
end_test
%s
%s
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual"
cd .git
expected2=$(echo "$expected" | sed -e 's/LocalWorkingDir=.*/LocalWorkingDir=/')
- actual2=$(git lfs env)
+ actual2=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected2" "$actual2"
)
end_test
%s
%s
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual"
cd .git
expected2=$(echo "$expected" | sed -e 's/LocalWorkingDir=.*/LocalWorkingDir=/')
- actual2=$(git lfs env)
+ actual2=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected2" "$actual2"
)
end_test
%s
%s
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual"
mkdir a
cd a
- actual2=$(git lfs env)
+ actual2=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual2"
)
end_test
%s
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree git lfs env)
+ actual=$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree git lfs env \
+ | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual"
cd $TRASHDIR/$reponame
- actual2=$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree git lfs env)
+ actual2=$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree git lfs env \
+ | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual2"
cd $TRASHDIR/$reponame/.git
- actual3=$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree git lfs env)
+ actual3=$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree git lfs env \
+ | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual3"
cd $TRASHDIR/$reponame/a/b/c
- actual4=$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree git lfs env)
+ actual4=$(GIT_DIR=$gitDir GIT_WORK_TREE=$workTree git lfs env \
+ | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual4"
envVars="$(GIT_DIR=$gitDir GIT_WORK_TREE=a/b env | grep "^GIT" | sort)"
UploadTransfers=basic
%s
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars")
- actual5=$(GIT_DIR=$gitDir GIT_WORK_TREE=a/b git lfs env)
+ actual5=$(GIT_DIR=$gitDir GIT_WORK_TREE=a/b git lfs env \
+ | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected5" "$actual5"
cd $TRASHDIR/$reponame/a/b
%s
%s
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual7=$(GIT_DIR=$gitDir git lfs env)
+ actual7=$(GIT_DIR=$gitDir git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected7" "$actual7"
cd $TRASHDIR/$reponame/a
%s
%s
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual8=$(GIT_WORK_TREE=$workTree git lfs env)
+ actual8=$(GIT_WORK_TREE=$workTree git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected8" "$actual8"
)
end_test
%s
%s
" "$(git lfs version)" "$(git version)" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual"
)
SSH=git@other-git-server.com:user/repo.git
GIT_SSH=lfs-ssh-echo'
- contains_same_elements "$expected" "$(git lfs env | grep -e "Endpoint" -e "SSH=")"
+ contains_same_elements "$expected" "$(git lfs env \
+ | grep -v "^GIT_EXEC_PATH=" | grep -e "Endpoint" -e "SSH=")"
)
end_test
%s
%s
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expectedenabled" "$actual"
git config --unset lfs.skipdownloaderrors
%s
%s
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expecteddisabled" "$actual"
# now enable via env var
- actual=$(GIT_LFS_SKIP_DOWNLOAD_ERRORS=1 git lfs env)
+ actual=$(GIT_LFS_SKIP_DOWNLOAD_ERRORS=1 git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expectedenabled" "$actual"
%s
%s
' "$(git lfs version)" "$(git version)" "$localwd" "$localgit" "$localgitstore" "$localmedia" "$tempdir" "$lfsstorage" "$envVars" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expectedenabled" "$actual"
)
(
set -e
- reponame="requirecreds"
+ reponame="requirecreds-extraHeader"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
- # See: test/cmd/lfstest-gitserver.go:1176.
+ # See: test/cmd/lfstest-gitserver.go:missingRequiredCreds().
user="requirecreds"
pass="pass"
auth="Basic $(echo -n $user:$pass | base64)"
[ "0" -eq "$(grep -c "creds: git credential reject" curl.log)" ]
)
end_test
+
+begin_test "http.<url>.extraHeader with authorization (casing)"
+(
+ set -e
+
+ reponame="requirecreds-extraHeaderCasing"
+ setup_remote_repo "$reponame"
+ clone_repo "$reponame" "$reponame"
+
+ # See: test/cmd/lfstest-gitserver.go:missingRequiredCreds().
+ user="requirecreds"
+ pass="pass"
+ auth="Basic $(echo -n $user:$pass | base64)"
+
+ git config --local --add lfs.access basic
+ # N.B.: "AUTHORIZATION" is not the correct casing, and is therefore the
+ # subject of this test. See lfsapi.Client.extraHeaders() for more.
+ git config --local --add "http.extraHeader" "AUTHORIZATION: $auth"
+
+ git lfs track "*.dat"
+ printf "contents" > a.dat
+ git add .gitattributes a.dat
+ git commit -m "initial commit"
+
+ git push origin master 2>&1 | tee curl.log
+ if [ "0" -ne "${PIPESTATUS[0]}" ]; then
+ echo >&2 "expected \`git push origin master\` to succeed, didn't"
+ exit 1
+ fi
+
+ [ "0" -eq "$(grep -c "creds: filling with GIT_ASKPASS" curl.log)" ]
+ [ "0" -eq "$(grep -c "creds: git credential approve" curl.log)" ]
+ [ "0" -eq "$(grep -c "creds: git credential cache" curl.log)" ]
+ [ "0" -eq "$(grep -c "creds: git credential fill" curl.log)" ]
+ [ "0" -eq "$(grep -c "creds: git credential reject" curl.log)" ]
+)
+end_test
begin_test "install again"
(
- set -e
+ set -eo pipefail
smudge="$(git config filter.lfs.smudge)"
clean="$(git config filter.lfs.clean)"
filter="$(git config filter.lfs.process)"
- printf "$smudge" | grep "git-lfs smudge"
- printf "$clean" | grep "git-lfs clean"
- printf "$filter" | grep "git-lfs filter-process"
+ [ "$smudge" = "git-lfs smudge -- %f" ]
+ [ "$clean" = "git-lfs clean -- %f" ]
+ [ "$filter" = "git-lfs filter-process" ]
- git lfs install
+ GIT_TRACE=1 git lfs install --skip-repo 2>&1 | tee install.log
+
+ if grep -q "--replace-all" install.log; then
+ echo >&2 "fatal: unexpected git config --replace-all via 'git lfs install'"
+ exit 1
+ fi
[ "$smudge" = "$(git config filter.lfs.smudge)" ]
[ "$clean" = "$(git config filter.lfs.clean)" ]
git lfs lock "a.dat" --json 2>&1 | tee lock.json
if [ "0" -ne "${PIPESTATUS[0]}" ]; then
- echo >&2 "fatal: expected 'git lfs lock \'a.dat\'' to succeed"
+ echo >&2 "fatal: expected \'git lfs lock \'a.dat\'\' to succeed"
exit 1
fi
git lfs lock "a.dat" --json 2>&1 | tee lock.json
if [ "0" -ne "${PIPESTATUS[0]}" ]; then
- echo >&2 "fatal: expected 'git lfs lock \'a.dat\'' to succeed"
+ echo >&2 "fatal: expected \'git lfs lock \'a.dat\'\' to succeed"
exit 1
fi
GIT_CURL_VERBOSE=1 git lfs lock "a.dat" 2>&1 | tee lock.json
if [ "0" -eq "${PIPESTATUS[0]}" ]; then
- echo >&2 "fatal: expected 'git lfs lock \'a.dat\'' to fail"
+ echo >&2 "fatal: expected \'git lfs lock \'a.dat\'\' to fail"
exit 1
fi
git lfs lock --json "a.dat" | tee lock.json
if [ "0" -ne "${PIPESTATUS[0]}" ]; then
- echo >&2 "fatal: expected 'git lfs lock \'a.dat\'' to succeed"
+ echo >&2 "fatal: expected \'git lfs lock \'a.dat\'\' to succeed"
exit 1
fi
assert_server_lock "$reponame" "$id"
)
end_test
+
+begin_test "creating a lock (symlinked working directory)"
+(
+ set -eo pipefail
+
+ if [[ $(uname) == *"MINGW"* ]]; then
+ echo >&2 "info: skipped on Windows ..."
+ exit 0
+ fi
+
+ reponame="lock-in-symlinked-working-directory"
+ setup_remote_repo "$reponame"
+ clone_repo "$reponame" "$reponame"
+
+ git lfs track -l "*.dat"
+ mkdir -p folder1 folder2
+ printf "hello" > folder2/a.dat
+ add_symlink "../folder2" "folder1/folder2"
+
+ git add --all .
+ git commit -m "initial commit"
+ git push origin master
+
+ pushd "$TRASHDIR" > /dev/null
+ ln -s "$reponame" "$reponame-symlink"
+ cd "$reponame-symlink"
+
+ git lfs lock --json folder1/folder2/a.dat 2>&1 | tee lock.json
+
+ id="$(assert_lock lock.json folder1/folder2/a.dat)"
+ assert_server_lock "$reponame" "$id" master
+ popd > /dev/null
+)
+end_test
[ 1 -eq $(grep -c "a\.dat" ls-files-deleted.log) ]
)
end_test
+
+begin_test "ls-files: invalid --all ordering"
+(
+ set -e
+
+ reponame="ls-files-invalid---all-ordering"
+ git init "$reponame"
+ cd "$reponame"
+
+ git lfs track "*.dat"
+ echo "Hello world" > a.dat
+
+ git add .gitattributes a.dat
+ git commit -m "initial commit"
+
+ git lfs ls-files -- --all 2>&1 | tee ls-files.out
+ if [ ${PIPESTATUS[0]} = "0" ]; then
+ echo >&2 "fatal: expected \`git lfs ls-files -- --all\' to fail"
+ exit 1
+ fi
+ grep "Could not scan for Git LFS tree" ls-files.out
+)
+end_test
--- /dev/null
+#!/usr/bin/env bash
+
+. "test/testlib.sh"
+
+begin_test "mergetool works with large files"
+(
+ set -e
+
+ reponame="mergetool-works-with-large-files"
+ git init "$reponame"
+ cd "$reponame"
+
+ git lfs track "*.dat"
+ printf "base" > conflict.dat
+ git add .gitattributes conflict.dat
+ git commit -m "initial commit"
+
+ git checkout -b conflict
+ printf "b" > conflict.dat
+ git add conflict.dat
+ git commit -m "conflict.dat: b"
+
+ git checkout master
+
+ printf "a" > conflict.dat
+ git add conflict.dat
+ git commit -m "conflict.dat: a"
+
+ set +e
+ git merge conflict
+ set -e
+
+ git config mergetool.inspect.cmd '
+ for i in BASE LOCAL REMOTE; do
+ echo "\$$i=$(eval "cat \"\$$i\"")";
+ done;
+ exit 1
+ '
+ git config mergetool.inspect.trustExitCode true
+
+ yes | git mergetool \
+ --no-prompt \
+ --tool=inspect \
+ -- conflict.dat 2>&1 \
+ | tee mergetool.log
+
+ grep "\$BASE=base" mergetool.log
+ grep "\$LOCAL=a" mergetool.log
+ grep "\$REMOTE=b" mergetool.log
+)
+end_test
fi
}
-# setup_multiple_local_branches creates a repository as follows:
+# setup_local_branch_with_gitattrs creates a repository as follows:
#
# A---B
# \
git checkout master
}
+# setup_local_branch_with_space creates a repository as follows:
+#
+# A
+# \
+# refs/heads/master
+#
+# - Commit 'A' has 50 bytes in a file named "a file.txt".
+setup_local_branch_with_space() {
+ set -e
+
+ reponame="migrate-local-branch-with-space"
+ filename="a file.txt"
+
+ remove_and_create_local_repo "$reponame"
+
+ base64 < /dev/urandom | head -c 50 > "$filename"
+
+ git add "$filename"
+ git commit -m "initial commit"
+}
+
# setup_single_remote_branch creates a repository as follows:
#
# A---B
git commit -m "initial commit"
}
+# setup_local_branch_with_symlink creates a repository as follows:
+#
+# A
+# \
+# refs/heads/master
+#
+# - Commit 'A' has 120, in a.txt, and a symbolic link link.txt to a.txt.
+setup_local_branch_with_symlink() {
+ set -e
+
+ reponame="migrate-single-local-branch-with-symlink"
+
+ remove_and_create_local_repo "$reponame"
+
+ base64 < /dev/urandom | head -c 120 > a.txt
+
+ git add a.txt
+ git commit -m "initial commit"
+
+ add_symlink "a.txt" "link.txt"
+ git commit -m "add symlink"
+}
+
# make_bare converts the existing full checkout of a repository into a bare one,
# and then `cd`'s into it.
make_bare() {
[ "$oid_root" = "$oid_root_after_migration" ]
)
end_test
+
+begin_test "migrate import (--include with space)"
+(
+ set -e
+
+ setup_local_branch_with_space
+
+ oid="$(calc_oid "$(git cat-file -p :"a file.txt")")"
+
+ git lfs migrate import --include "a file.txt"
+
+ assert_pointer "refs/heads/master" "a file.txt" "$oid" 50
+ cat .gitattributes
+ if [ 1 -ne "$(grep -c "a\[\[:space:\]\]file.txt" .gitattributes)" ]; then
+ echo >&2 "fatal: expected \"a[[:space:]]file.txt\" to appear in .gitattributes"
+ echo >&2 "fatal: got"
+ sed -e 's/^/ /g' < .gitattributes >&2
+ exit 1
+ fi
+)
+end_test
+
+begin_test "migrate import (handle symbolic link)"
+(
+ set -e
+
+ setup_local_branch_with_symlink
+
+ txt_oid="$(calc_oid "$(git cat-file -p :a.txt)")"
+ link_oid="$(calc_oid "$(git cat-file -p :link.txt)")"
+
+ git lfs migrate import --include="*.txt"
+
+ assert_pointer "refs/heads/master" "a.txt" "$txt_oid" "120"
+
+ assert_local_object "$txt_oid" "120"
+ # "link.txt" is a symbolic link so it should be not in LFS
+ refute_local_object "$link_oid" "5"
+)
+end_test
set -e
grep "invalid size (got: -1)" push.log
+ [ "0" -eq "$(grep -c "panic" push.log)" ]
[ "0" -ne "$res" ]
refute_server_object "$reponame" "$(calc_oid "$contents")"
[ "0" -eq "$(grep -c "\.png" track.log)" ]
)
end_test
+
+begin_test "track (with current-directory prefix)"
+(
+ set -e
+
+ reponame="track-with-current-directory-prefix"
+ git init "$reponame"
+ cd "$reponame"
+
+ git lfs track "./a.dat"
+ printf "a" > a.dat
+
+ git add .gitattributes a.dat
+ git commit -m "initial commit"
+
+ grep -e "^a.dat" .gitattributes
+)
+end_test
[ "global clean" = "$(git config --global filter.lfs.clean)" ]
[ "global filter" = "$(git config --global filter.lfs.process)" ]
- git lfs uninstall --local
+ git lfs uninstall --local 2>&1 | tee uninstall.log
+ if [ ${PIPESTATUS[0]} -ne 0 ]; then
+ echo >&2 "fatal: expected 'git lfs uninstall --local' to succeed"
+ exit 1
+ fi
+ grep -v "Global Git LFS configuration has been removed." uninstall.log
# global configs
[ "global smudge" = "$(git config --global filter.lfs.smudge)" ]
assert_attributes_count "\\#" "filter=lfs" 0
)
end_test
+
+begin_test "untrack removes prefixed patterns (legacy)"
+(
+ set -e
+
+ reponame="untrack-removes-prefix-patterns-legacy"
+ git init "$reponame"
+ cd "$reponame"
+
+ echo "./a.dat filter=lfs diff=lfs merge=lfs" > .gitattributes
+ printf "a" > a.dat
+ git add .gitattributes a.dat
+ git commit -m "initial commit"
+
+ git lfs untrack "./a.dat"
+
+ if [ ! -z "$(cat .gitattributes)" ]; then
+ echo &>2 "fatal: expected 'git lfs untrack' to clear .gitattributes"
+ exit 1
+ fi
+
+ git checkout -- .gitattributes
+
+ git lfs untrack "a.dat"
+
+ if [ ! -z "$(cat .gitattributes)" ]; then
+ echo &>2 "fatal: expected 'git lfs untrack' to clear .gitattributes"
+ exit 1
+ fi
+)
+end_test
+
+begin_test "untrack removes prefixed patterns (modern)"
+(
+ set -e
+
+ reponame="untrack-removes-prefix-patterns-modern"
+ git init "$reponame"
+ cd "$reponame"
+
+ echo "a.dat filter=lfs diff=lfs merge=lfs" > .gitattributes
+ printf "a" > a.dat
+ git add .gitattributes a.dat
+ git commit -m "initial commit"
+
+ git lfs untrack "./a.dat"
+
+ if [ ! -z "$(cat .gitattributes)" ]; then
+ echo &>2 "fatal: expected 'git lfs untrack' to clear .gitattributes"
+ exit 1
+ fi
+
+ git checkout -- .gitattributes
+
+ git lfs untrack "a.dat"
+
+ if [ ! -z "$(cat .gitattributes)" ]; then
+ echo &>2 "fatal: expected 'git lfs untrack' to clear .gitattributes"
+ exit 1
+ fi
+)
+end_test
--- /dev/null
+#!/usr/bin/env bash
+
+. "test/testlib.sh"
+
+begin_test "git lfs --version is a synonym of git lfs version"
+(
+ set -e
+
+ reponame="git-lfs-version-synonymous"
+ mkdir "$reponame"
+ cd "$reponame"
+
+ git lfs version 2>&1 >version.log
+ git lfs --version 2>&1 >flag.log
+
+ if [ "$(cat version.log)" != "$(cat flag.log)" ]; then
+ echo >&2 "fatal: expected 'git lfs version' and 'git lfs --version' to"
+ echo >&2 "produce identical output ..."
+
+ diff -u {version,flag}.log
+ fi
+)
+end_test
$(escape_path "$(env | grep "^GIT")")
%s
" "$(git lfs version)" "$(git version)" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual"
worktreename="worktree-2"
$(escape_path "$(env | grep "^GIT")")
%s
" "$(git lfs version)" "$(git version)" "$envInitConfig")
- actual=$(git lfs env)
+ actual=$(git lfs env | grep -v "^GIT_EXEC_PATH=")
contains_same_elements "$expected" "$actual"
)
end_test
exit 0
fi
}
+
+add_symlink() {
+ local src=$1
+ local dest=$2
+
+ prefix=`git rev-parse --show-prefix`
+ hashsrc=`printf "$src" | git hash-object -w --stdin`
+
+ git update-index --add --cacheinfo 120000 "$hashsrc" "$prefix$dest"
+ git checkout -- "$dest"
+}
import (
"fmt"
+ "math"
"os"
"path/filepath"
"strings"
direction,
percentage,
m.finishedFiles, m.estimatedFiles,
- humanize.FormatBytes(uint64(m.currentBytes)),
- humanize.FormatByteRate(uint64(m.avgBytes), time.Second))
+ humanize.FormatBytes(clamp(m.currentBytes)),
+ humanize.FormatByteRate(clampf(m.avgBytes), time.Second))
+}
+
+// clamp clamps the given "x" within the acceptable domain of the uint64 integer
+// type, so as to prevent over- and underflow.
+func clamp(x int64) uint64 {
+ if x < 0 {
+ return 0
+ }
+ if x > math.MaxInt64 {
+ return math.MaxUint64
+ }
+ return uint64(x)
+}
+
+func clampf(x float64) uint64 {
+ if x < 0 {
+ return 0
+ }
+ if x > math.MaxUint64 {
+ return math.MaxUint64
+ }
+ return uint64(x)
}
func (m *Meter) logBytes(direction, name string, read, total int64) {
"FileVersion": {
"Major": 2,
"Minor": 4,
- "Patch": 0,
+ "Patch": 1,
"Build": 0
}
},
"FileDescription": "Git LFS",
"LegalCopyright": "GitHub, Inc. and Git LFS contributors",
"ProductName": "Git Large File Storage (LFS)",
- "ProductVersion": "2.4.0"
+ "ProductVersion": "2.4.1"
},
"IconPath": "script/windows-installer/git-lfs-logo.ico"
}