Merge branch 'master' into ttaylorr/migrate-warn-if-dirty
This commit is contained in:
commit
9763ac1623
@ -179,13 +179,31 @@ func includeExcludeRefs(l *tasklog.Logger, args []string) (include, exclude []st
|
|||||||
include = append(include, migrateIncludeRefs...)
|
include = append(include, migrateIncludeRefs...)
|
||||||
exclude = append(exclude, migrateExcludeRefs...)
|
exclude = append(exclude, migrateExcludeRefs...)
|
||||||
} else if migrateEverything {
|
} else if migrateEverything {
|
||||||
localRefs, err := git.LocalRefs()
|
refs, err := git.AllRefsIn("")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, ref := range localRefs {
|
for _, ref := range refs {
|
||||||
include = append(include, ref.Refspec())
|
switch ref.Type {
|
||||||
|
case git.RefTypeLocalBranch, git.RefTypeLocalTag,
|
||||||
|
git.RefTypeRemoteBranch, git.RefTypeRemoteTag:
|
||||||
|
|
||||||
|
include = append(include, ref.Refspec())
|
||||||
|
case git.RefTypeOther:
|
||||||
|
parts := strings.SplitN(ref.Refspec(), "/", 3)
|
||||||
|
if len(parts) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
switch parts[1] {
|
||||||
|
// The following are GitLab-, GitHub-, VSTS-,
|
||||||
|
// and BitBucket-specific reference naming
|
||||||
|
// conventions.
|
||||||
|
case "merge-requests", "pull", "pull-requests":
|
||||||
|
include = append(include, ref.Refspec())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
bare, err := git.IsBare()
|
bare, err := git.IsBare()
|
||||||
|
@ -311,8 +311,8 @@ func (c *Configuration) LocalGitStorageDir() string {
|
|||||||
return c.Filesystem().GitStorageDir
|
return c.Filesystem().GitStorageDir
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Configuration) LocalReferenceDir() string {
|
func (c *Configuration) LocalReferenceDirs() []string {
|
||||||
return c.Filesystem().ReferenceDir
|
return c.Filesystem().ReferenceDirs
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Configuration) LFSStorageDir() string {
|
func (c *Configuration) LFSStorageDir() string {
|
||||||
@ -346,7 +346,12 @@ func (c *Configuration) Filesystem() *fs.Filesystem {
|
|||||||
|
|
||||||
if c.fs == nil {
|
if c.fs == nil {
|
||||||
lfsdir, _ := c.Git.Get("lfs.storage")
|
lfsdir, _ := c.Git.Get("lfs.storage")
|
||||||
c.fs = fs.New(c.LocalGitDir(), c.LocalWorkingDir(), lfsdir)
|
c.fs = fs.New(
|
||||||
|
c.Os,
|
||||||
|
c.LocalGitDir(),
|
||||||
|
c.LocalWorkingDir(),
|
||||||
|
lfsdir,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.fs
|
return c.fs
|
||||||
|
@ -158,6 +158,7 @@ func keyIsUnsafe(key string) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var safeKeys = []string{
|
var safeKeys = []string{
|
||||||
|
"lfs.allowincompletepush",
|
||||||
"lfs.fetchexclude",
|
"lfs.fetchexclude",
|
||||||
"lfs.fetchinclude",
|
"lfs.fetchinclude",
|
||||||
"lfs.gitprotocol",
|
"lfs.gitprotocol",
|
||||||
|
@ -190,8 +190,8 @@ The following configuration:
|
|||||||
|
|
||||||
Would, therefore, include commits: F, E, D, C, B, but exclude commit A.
|
Would, therefore, include commits: F, E, D, C, B, but exclude commit A.
|
||||||
|
|
||||||
The presence of flag `--everything` indicates that all local references should be
|
The presence of flag `--everything` indicates that all local and remote
|
||||||
migrated.
|
references should be migrated.
|
||||||
|
|
||||||
## EXAMPLES
|
## EXAMPLES
|
||||||
|
|
||||||
@ -253,16 +253,20 @@ Note: This will require a force push to any existing Git remotes.
|
|||||||
|
|
||||||
### Migrate without rewriting local history
|
### Migrate without rewriting local history
|
||||||
|
|
||||||
You can also migrate files without modifying the existing history of your respoitory:
|
You can also migrate files without modifying the existing history of your
|
||||||
|
repository:
|
||||||
|
|
||||||
Without a specified commit message:
|
Without a specified commit message:
|
||||||
|
|
||||||
```
|
```
|
||||||
git lfs migrate import --no-rewrite test.zip *.mp3 *.psd
|
$ git lfs migrate import --no-rewrite test.zip *.mp3 *.psd
|
||||||
```
|
```
|
||||||
|
|
||||||
With a specified commit message:
|
With a specified commit message:
|
||||||
|
|
||||||
```
|
```
|
||||||
git lfs migrate import --no-rewrite -m "Import .zip, .mp3, .psd files" \
|
$ git lfs migrate import --no-rewrite -m "Import .zip, .mp3, .psd files" \
|
||||||
test.zip *.mpd *.psd
|
test.zip *.mpd *.psd
|
||||||
```
|
```
|
||||||
|
|
||||||
## SEE ALSO
|
## SEE ALSO
|
||||||
|
108
fs/fs.go
108
fs/fs.go
@ -1,6 +1,7 @@
|
|||||||
package fs
|
package fs
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@ -12,10 +13,19 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/git-lfs/git-lfs/tools"
|
"github.com/git-lfs/git-lfs/tools"
|
||||||
|
"github.com/rubyist/tracerx"
|
||||||
)
|
)
|
||||||
|
|
||||||
var oidRE = regexp.MustCompile(`\A[[:alnum:]]{64}`)
|
var oidRE = regexp.MustCompile(`\A[[:alnum:]]{64}`)
|
||||||
|
|
||||||
|
// Environment is a copy of a subset of the interface
|
||||||
|
// github.com/git-lfs/git-lfs/config.Environment.
|
||||||
|
//
|
||||||
|
// For more information, see config/environment.go.
|
||||||
|
type Environment interface {
|
||||||
|
Get(key string) (val string, ok bool)
|
||||||
|
}
|
||||||
|
|
||||||
// Object represents a locally stored LFS object.
|
// Object represents a locally stored LFS object.
|
||||||
type Object struct {
|
type Object struct {
|
||||||
Oid string
|
Oid string
|
||||||
@ -23,9 +33,9 @@ type Object struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type Filesystem struct {
|
type Filesystem struct {
|
||||||
GitStorageDir string // parent of objects/lfs (may be same as GitDir but may not)
|
GitStorageDir string // parent of objects/lfs (may be same as GitDir but may not)
|
||||||
LFSStorageDir string // parent of lfs objects and tmp dirs. Default: ".git/lfs"
|
LFSStorageDir string // parent of lfs objects and tmp dirs. Default: ".git/lfs"
|
||||||
ReferenceDir string // alternative local media dir (relative to clone reference repo)
|
ReferenceDirs []string // alternative local media dirs (relative to clone reference repo)
|
||||||
lfsobjdir string
|
lfsobjdir string
|
||||||
tmpdir string
|
tmpdir string
|
||||||
logdir string
|
logdir string
|
||||||
@ -105,12 +115,16 @@ func (f *Filesystem) localObjectDir(oid string) string {
|
|||||||
return filepath.Join(f.LFSObjectDir(), oid[0:2], oid[2:4])
|
return filepath.Join(f.LFSObjectDir(), oid[0:2], oid[2:4])
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Filesystem) ObjectReferencePath(oid string) string {
|
func (f *Filesystem) ObjectReferencePaths(oid string) []string {
|
||||||
if len(f.ReferenceDir) == 0 {
|
if len(f.ReferenceDirs) == 0 {
|
||||||
return f.ReferenceDir
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
return filepath.Join(f.ReferenceDir, oid[0:2], oid[2:4], oid)
|
var paths []string
|
||||||
|
for _, ref := range f.ReferenceDirs {
|
||||||
|
paths = append(paths, filepath.Join(ref, oid[0:2], oid[2:4], oid))
|
||||||
|
}
|
||||||
|
return paths
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Filesystem) LFSObjectDir() string {
|
func (f *Filesystem) LFSObjectDir() string {
|
||||||
@ -159,12 +173,12 @@ func (f *Filesystem) Cleanup() error {
|
|||||||
// New initializes a new *Filesystem with the given directories. gitdir is the
|
// New initializes a new *Filesystem with the given directories. gitdir is the
|
||||||
// path to the bare repo, workdir is the path to the repository working
|
// path to the bare repo, workdir is the path to the repository working
|
||||||
// directory, and lfsdir is the optional path to the `.git/lfs` directory.
|
// directory, and lfsdir is the optional path to the `.git/lfs` directory.
|
||||||
func New(gitdir, workdir, lfsdir string) *Filesystem {
|
func New(env Environment, gitdir, workdir, lfsdir string) *Filesystem {
|
||||||
fs := &Filesystem{
|
fs := &Filesystem{
|
||||||
GitStorageDir: resolveGitStorageDir(gitdir),
|
GitStorageDir: resolveGitStorageDir(gitdir),
|
||||||
}
|
}
|
||||||
|
|
||||||
fs.ReferenceDir = resolveReferenceDir(fs.GitStorageDir)
|
fs.ReferenceDirs = resolveReferenceDirs(env, fs.GitStorageDir)
|
||||||
|
|
||||||
if len(lfsdir) == 0 {
|
if len(lfsdir) == 0 {
|
||||||
lfsdir = "lfs"
|
lfsdir = "lfs"
|
||||||
@ -179,19 +193,75 @@ func New(gitdir, workdir, lfsdir string) *Filesystem {
|
|||||||
return fs
|
return fs
|
||||||
}
|
}
|
||||||
|
|
||||||
func resolveReferenceDir(gitStorageDir string) string {
|
func resolveReferenceDirs(env Environment, gitStorageDir string) []string {
|
||||||
cloneReferencePath := filepath.Join(gitStorageDir, "objects", "info", "alternates")
|
var references []string
|
||||||
if tools.FileExists(cloneReferencePath) {
|
|
||||||
buffer, err := ioutil.ReadFile(cloneReferencePath)
|
envAlternates, ok := env.Get("GIT_ALTERNATE_OBJECT_DIRECTORIES")
|
||||||
if err == nil {
|
if ok {
|
||||||
path := strings.TrimSpace(string(buffer[:]))
|
splits := strings.Split(envAlternates, string(os.PathListSeparator))
|
||||||
referenceLfsStoragePath := filepath.Join(filepath.Dir(path), "lfs", "objects")
|
for _, split := range splits {
|
||||||
if tools.DirExists(referenceLfsStoragePath) {
|
if dir, ok := existsAlternate(split); ok {
|
||||||
return referenceLfsStoragePath
|
references = append(references, dir)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return ""
|
|
||||||
|
cloneReferencePath := filepath.Join(gitStorageDir, "objects", "info", "alternates")
|
||||||
|
if tools.FileExists(cloneReferencePath) {
|
||||||
|
f, err := os.Open(cloneReferencePath)
|
||||||
|
if err != nil {
|
||||||
|
tracerx.Printf("could not open %s: %s",
|
||||||
|
cloneReferencePath, err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
scanner := bufio.NewScanner(f)
|
||||||
|
for scanner.Scan() {
|
||||||
|
text := strings.TrimSpace(scanner.Text())
|
||||||
|
if len(text) == 0 || strings.HasPrefix(text, "#") {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if dir, ok := existsAlternate(text); ok {
|
||||||
|
references = append(references, dir)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := scanner.Err(); err != nil {
|
||||||
|
tracerx.Printf("could not scan %s: %s",
|
||||||
|
cloneReferencePath, err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return references
|
||||||
|
}
|
||||||
|
|
||||||
|
// existsAlternate takes an object directory given in "objs" (read as a single,
|
||||||
|
// line from .git/objects/info/alternates). If that is a satisfiable alternates
|
||||||
|
// directory (i.e., it exists), the directory is returned along with "true". If
|
||||||
|
// not, the empty string and false is returned instead.
|
||||||
|
func existsAlternate(objs string) (string, bool) {
|
||||||
|
objs = strings.TrimSpace(objs)
|
||||||
|
if strings.HasPrefix(objs, "\"") {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
unquote := strings.LastIndex(objs, "\"")
|
||||||
|
if unquote == 0 {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
|
||||||
|
objs, err = strconv.Unquote(objs[:unquote+1])
|
||||||
|
if err != nil {
|
||||||
|
return "", false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
storage := filepath.Join(filepath.Dir(objs), "lfs", "objects")
|
||||||
|
|
||||||
|
if tools.DirExists(storage) {
|
||||||
|
return storage, true
|
||||||
|
}
|
||||||
|
return "", false
|
||||||
}
|
}
|
||||||
|
|
||||||
// From a git dir, get the location that objects are to be stored (we will store lfs alongside)
|
// From a git dir, get the location that objects are to be stored (we will store lfs alongside)
|
||||||
|
@ -16,6 +16,18 @@ import (
|
|||||||
|
|
||||||
func (f *GitFilter) SmudgeToFile(filename string, ptr *Pointer, download bool, manifest *tq.Manifest, cb tools.CopyCallback) error {
|
func (f *GitFilter) SmudgeToFile(filename string, ptr *Pointer, download bool, manifest *tq.Manifest, cb tools.CopyCallback) error {
|
||||||
os.MkdirAll(filepath.Dir(filename), 0755)
|
os.MkdirAll(filepath.Dir(filename), 0755)
|
||||||
|
|
||||||
|
if stat, _ := os.Stat(filename); stat != nil && stat.Mode()&0200 == 0 {
|
||||||
|
if err := os.Chmod(filename, stat.Mode()|0200); err != nil {
|
||||||
|
return errors.Wrap(err,
|
||||||
|
"Could not restore write permission")
|
||||||
|
}
|
||||||
|
|
||||||
|
// When we're done, return the file back to its normal
|
||||||
|
// permission bits.
|
||||||
|
defer os.Chmod(filename, stat.Mode())
|
||||||
|
}
|
||||||
|
|
||||||
file, err := os.Create(filename)
|
file, err := os.Create(filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Could not create working directory file: %v", err)
|
return fmt.Errorf("Could not create working directory file: %v", err)
|
||||||
|
18
lfs/lfs.go
18
lfs/lfs.go
@ -35,12 +35,14 @@ func Environ(cfg *config.Configuration, manifest *tq.Manifest) []string {
|
|||||||
|
|
||||||
fetchPruneConfig := NewFetchPruneConfig(cfg.Git)
|
fetchPruneConfig := NewFetchPruneConfig(cfg.Git)
|
||||||
|
|
||||||
|
references := strings.Join(cfg.LocalReferenceDirs(), ", ")
|
||||||
|
|
||||||
env = append(env,
|
env = append(env,
|
||||||
fmt.Sprintf("LocalWorkingDir=%s", cfg.LocalWorkingDir()),
|
fmt.Sprintf("LocalWorkingDir=%s", cfg.LocalWorkingDir()),
|
||||||
fmt.Sprintf("LocalGitDir=%s", cfg.LocalGitDir()),
|
fmt.Sprintf("LocalGitDir=%s", cfg.LocalGitDir()),
|
||||||
fmt.Sprintf("LocalGitStorageDir=%s", cfg.LocalGitStorageDir()),
|
fmt.Sprintf("LocalGitStorageDir=%s", cfg.LocalGitStorageDir()),
|
||||||
fmt.Sprintf("LocalMediaDir=%s", cfg.LFSObjectDir()),
|
fmt.Sprintf("LocalMediaDir=%s", cfg.LFSObjectDir()),
|
||||||
fmt.Sprintf("LocalReferenceDir=%s", cfg.LocalReferenceDir()),
|
fmt.Sprintf("LocalReferenceDirs=%s", references),
|
||||||
fmt.Sprintf("TempDir=%s", cfg.TempDir()),
|
fmt.Sprintf("TempDir=%s", cfg.TempDir()),
|
||||||
fmt.Sprintf("ConcurrentTransfers=%d", api.ConcurrentTransfers),
|
fmt.Sprintf("ConcurrentTransfers=%d", api.ConcurrentTransfers),
|
||||||
fmt.Sprintf("TusTransfers=%v", cfg.TusTransfersAllowed()),
|
fmt.Sprintf("TusTransfers=%v", cfg.TusTransfersAllowed()),
|
||||||
@ -98,13 +100,19 @@ func LinkOrCopyFromReference(cfg *config.Configuration, oid string, size int64)
|
|||||||
if cfg.LFSObjectExists(oid, size) {
|
if cfg.LFSObjectExists(oid, size) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
altMediafile := cfg.Filesystem().ObjectReferencePath(oid)
|
altMediafiles := cfg.Filesystem().ObjectReferencePaths(oid)
|
||||||
mediafile, err := cfg.Filesystem().ObjectPath(oid)
|
mediafile, err := cfg.Filesystem().ObjectPath(oid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if altMediafile != "" && tools.FileExistsOfSize(altMediafile, size) {
|
for _, altMediafile := range altMediafiles {
|
||||||
return LinkOrCopy(cfg, altMediafile, mediafile)
|
tracerx.Printf("altMediafile: %s", altMediafile)
|
||||||
|
if altMediafile != "" && tools.FileExistsOfSize(altMediafile, size) {
|
||||||
|
err = LinkOrCopy(cfg, altMediafile, mediafile)
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return err
|
||||||
}
|
}
|
||||||
|
106
lfsapi/creds.go
106
lfsapi/creds.go
@ -78,6 +78,14 @@ type AskPassCredentialHelper struct {
|
|||||||
Program string
|
Program string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type credValueType int
|
||||||
|
|
||||||
|
const (
|
||||||
|
credValueTypeUnknown credValueType = iota
|
||||||
|
credValueTypeUsername
|
||||||
|
credValueTypePassword
|
||||||
|
)
|
||||||
|
|
||||||
// Fill implements fill by running the ASKPASS program and returning its output
|
// Fill implements fill by running the ASKPASS program and returning its output
|
||||||
// as a password encoded in the Creds type given the key "password".
|
// as a password encoded in the Creds type given the key "password".
|
||||||
//
|
//
|
||||||
@ -86,60 +94,92 @@ type AskPassCredentialHelper struct {
|
|||||||
//
|
//
|
||||||
// If there was an error running the command, it is returned instead of a set of
|
// If there was an error running the command, it is returned instead of a set of
|
||||||
// filled credentials.
|
// filled credentials.
|
||||||
|
//
|
||||||
|
// The ASKPASS program is only queried if a credential was not already
|
||||||
|
// provided, i.e. through the git URL
|
||||||
func (a *AskPassCredentialHelper) Fill(what Creds) (Creds, error) {
|
func (a *AskPassCredentialHelper) Fill(what Creds) (Creds, error) {
|
||||||
var user bytes.Buffer
|
|
||||||
var pass bytes.Buffer
|
|
||||||
var err bytes.Buffer
|
|
||||||
|
|
||||||
u := &url.URL{
|
u := &url.URL{
|
||||||
Scheme: what["protocol"],
|
Scheme: what["protocol"],
|
||||||
Host: what["host"],
|
Host: what["host"],
|
||||||
Path: what["path"],
|
Path: what["path"],
|
||||||
}
|
}
|
||||||
|
|
||||||
// 'ucmd' will run the GIT_ASKPASS (or core.askpass) command prompting
|
creds := make(Creds)
|
||||||
// for a username.
|
|
||||||
ucmd := exec.Command(a.Program, a.args(fmt.Sprintf("Username for %q", u))...)
|
|
||||||
ucmd.Stderr = &err
|
|
||||||
ucmd.Stdout = &user
|
|
||||||
|
|
||||||
tracerx.Printf("creds: filling with GIT_ASKPASS: %s", strings.Join(ucmd.Args, " "))
|
username, err := a.getValue(what, credValueTypeUsername, u)
|
||||||
if err := ucmd.Run(); err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
creds["username"] = username
|
||||||
|
|
||||||
if err.Len() > 0 {
|
if len(username) > 0 {
|
||||||
return nil, errors.New(err.String())
|
|
||||||
}
|
|
||||||
|
|
||||||
if username := strings.TrimSpace(user.String()); len(username) > 0 {
|
|
||||||
// If a non-empty username was given, add it to the URL via func
|
// If a non-empty username was given, add it to the URL via func
|
||||||
// 'net/url.User()'.
|
// 'net/url.User()'.
|
||||||
u.User = url.User(username)
|
u.User = url.User(creds["username"])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Regardless, create 'pcmd' to run the GIT_ASKPASS (or core.askpass)
|
password, err := a.getValue(what, credValueTypePassword, u)
|
||||||
// command prompting for a password.
|
if err != nil {
|
||||||
pcmd := exec.Command(a.Program, a.args(fmt.Sprintf("Password for %q", u))...)
|
|
||||||
pcmd.Stderr = &err
|
|
||||||
pcmd.Stdout = &pass
|
|
||||||
|
|
||||||
tracerx.Printf("creds: filling with GIT_ASKPASS: %s", strings.Join(pcmd.Args, " "))
|
|
||||||
if err := pcmd.Run(); err != nil {
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
creds["password"] = password
|
||||||
|
|
||||||
|
return creds, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AskPassCredentialHelper) getValue(what Creds, valueType credValueType, u *url.URL) (string, error) {
|
||||||
|
var valueString string
|
||||||
|
|
||||||
|
switch valueType {
|
||||||
|
case credValueTypeUsername:
|
||||||
|
valueString = "username"
|
||||||
|
case credValueTypePassword:
|
||||||
|
valueString = "password"
|
||||||
|
default:
|
||||||
|
return "", errors.Errorf("Invalid Credential type queried from AskPass")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the existing credential if it was already provided, otherwise
|
||||||
|
// query AskPass for it
|
||||||
|
if given, ok := what[valueString]; ok {
|
||||||
|
return given, nil
|
||||||
|
}
|
||||||
|
return a.getFromProgram(valueType, u)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *AskPassCredentialHelper) getFromProgram(valueType credValueType, u *url.URL) (string, error) {
|
||||||
|
var (
|
||||||
|
value bytes.Buffer
|
||||||
|
err bytes.Buffer
|
||||||
|
|
||||||
|
valueString string
|
||||||
|
)
|
||||||
|
|
||||||
|
switch valueType {
|
||||||
|
case credValueTypeUsername:
|
||||||
|
valueString = "Username"
|
||||||
|
case credValueTypePassword:
|
||||||
|
valueString = "Password"
|
||||||
|
default:
|
||||||
|
return "", errors.Errorf("Invalid Credential type queried from AskPass")
|
||||||
|
}
|
||||||
|
|
||||||
|
// 'cmd' will run the GIT_ASKPASS (or core.askpass) command prompting
|
||||||
|
// for the desired valueType (`Username` or `Password`)
|
||||||
|
cmd := exec.Command(a.Program, a.args(fmt.Sprintf("%s for %q", valueString, u))...)
|
||||||
|
cmd.Stderr = &err
|
||||||
|
cmd.Stdout = &value
|
||||||
|
|
||||||
|
tracerx.Printf("creds: filling with GIT_ASKPASS: %s", strings.Join(cmd.Args, " "))
|
||||||
|
if err := cmd.Run(); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
|
||||||
if err.Len() > 0 {
|
if err.Len() > 0 {
|
||||||
return nil, errors.New(err.String())
|
return "", errors.New(err.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, now that we have the username and password information,
|
return strings.TrimSpace(value.String()), nil
|
||||||
// store it in the creds instance that we will return to the caller.
|
|
||||||
creds := make(Creds)
|
|
||||||
creds["username"] = strings.TrimSpace(user.String())
|
|
||||||
creds["password"] = strings.TrimSpace(pass.String())
|
|
||||||
|
|
||||||
return creds, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Approve implements CredentialHelper.Approve, and returns nil. The ASKPASS
|
// Approve implements CredentialHelper.Approve, and returns nil. The ASKPASS
|
||||||
|
143
test/test-alternates.sh
Executable file
143
test/test-alternates.sh
Executable file
@ -0,0 +1,143 @@
|
|||||||
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
|
. "test/testlib.sh"
|
||||||
|
|
||||||
|
begin_test "alternates (single)"
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
reponame="alternates-single-alternate"
|
||||||
|
setup_remote_repo_with_file "$reponame" "a.txt"
|
||||||
|
|
||||||
|
pushd "$TRASHDIR" > /dev/null
|
||||||
|
clone_repo "$reponame" "${reponame}_alternate"
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
rm -rf .git/lfs/objects
|
||||||
|
|
||||||
|
alternate="$TRASHDIR/${reponame}_alternate/.git/objects"
|
||||||
|
echo "$alternate" > .git/objects/info/alternates
|
||||||
|
|
||||||
|
GIT_TRACE=1 git lfs fetch origin master 2>&1 | tee fetch.log
|
||||||
|
[ "0" -eq "$(grep -c "sending batch of size 1" fetch.log)" ]
|
||||||
|
)
|
||||||
|
end_test
|
||||||
|
|
||||||
|
begin_test "alternates (multiple)"
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
reponame="alternates-multiple-alternates"
|
||||||
|
setup_remote_repo_with_file "$reponame" "a.txt"
|
||||||
|
|
||||||
|
pushd "$TRASHDIR" > /dev/null
|
||||||
|
clone_repo "$reponame" "${reponame}_alternate_stale"
|
||||||
|
rm -rf .git/lfs/objects
|
||||||
|
popd > /dev/null
|
||||||
|
pushd "$TRASHDIR" > /dev/null
|
||||||
|
clone_repo "$reponame" "${reponame}_alternate"
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
rm -rf .git/lfs/objects
|
||||||
|
|
||||||
|
alternate_stale="$TRASHDIR/${reponame}_alternate_stale/.git/objects"
|
||||||
|
alternate="$TRASHDIR/${reponame}_alternate/.git/objects"
|
||||||
|
echo "$alternate" > .git/objects/info/alternates
|
||||||
|
echo "$alternate_stale" >> .git/objects/info/alternates
|
||||||
|
|
||||||
|
GIT_TRACE=1 git lfs fetch origin master 2>&1 | tee fetch.log
|
||||||
|
[ "0" -eq "$(grep -c "sending batch of size 1" fetch.log)" ]
|
||||||
|
)
|
||||||
|
end_test
|
||||||
|
|
||||||
|
begin_test "alternates (commented)"
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
reponame="alternates-commented-alternate"
|
||||||
|
setup_remote_repo_with_file "$reponame" "a.txt"
|
||||||
|
|
||||||
|
pushd "$TRASHDIR" > /dev/null
|
||||||
|
clone_repo "$reponame" "${reponame}_alternate"
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
rm -rf .git/lfs/objects
|
||||||
|
|
||||||
|
alternate="$TRASHDIR/${reponame}_alternate/.git/objects"
|
||||||
|
echo "# $alternate" > .git/objects/info/alternates
|
||||||
|
|
||||||
|
GIT_TRACE=1 git lfs fetch origin master 2>&1 | tee fetch.log
|
||||||
|
[ "1" -eq "$(grep -c "sending batch of size 1" fetch.log)" ]
|
||||||
|
)
|
||||||
|
end_test
|
||||||
|
|
||||||
|
begin_test "alternates (quoted)"
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
reponame="alternates-quoted-alternate"
|
||||||
|
setup_remote_repo_with_file "$reponame" "a.txt"
|
||||||
|
|
||||||
|
pushd "$TRASHDIR" > /dev/null
|
||||||
|
clone_repo "$reponame" "${reponame}_alternate"
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
rm -rf .git/lfs/objects
|
||||||
|
|
||||||
|
alternate="$TRASHDIR/${reponame}_alternate/.git/objects"
|
||||||
|
echo "\"$alternate\"" > .git/objects/info/alternates
|
||||||
|
|
||||||
|
GIT_TRACE=1 git lfs fetch origin master 2>&1 | tee fetch.log
|
||||||
|
[ "0" -eq "$(grep -c "sending batch of size 1" fetch.log)" ]
|
||||||
|
)
|
||||||
|
end_test
|
||||||
|
|
||||||
|
begin_test "alternates (OS environment, single)"
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
reponame="alternates-environment-single-alternate"
|
||||||
|
setup_remote_repo_with_file "$reponame" "a.txt"
|
||||||
|
|
||||||
|
pushd "$TRASHDIR" > /dev/null
|
||||||
|
clone_repo "$reponame" "${reponame}_alternate"
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
rm -rf .git/lfs/objects
|
||||||
|
|
||||||
|
alternate="$TRASHDIR/${reponame}_alternate/.git/objects"
|
||||||
|
|
||||||
|
GIT_ALTERNATE_OBJECT_DIRECTORIES="$alternate" \
|
||||||
|
GIT_TRACE=1 \
|
||||||
|
git lfs fetch origin master 2>&1 | tee fetch.log
|
||||||
|
[ "0" -eq "$(grep -c "sending batch of size 1" fetch.log)" ]
|
||||||
|
)
|
||||||
|
end_test
|
||||||
|
|
||||||
|
begin_test "alternates (OS environment, multiple)"
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
reponame="alternates-environment-multiple-alternates"
|
||||||
|
setup_remote_repo_with_file "$reponame" "a.txt"
|
||||||
|
|
||||||
|
pushd "$TRASHDIR" > /dev/null
|
||||||
|
clone_repo "$reponame" "${reponame}_alternate_stale"
|
||||||
|
rm -rf .git/lfs/objects
|
||||||
|
popd > /dev/null
|
||||||
|
pushd "$TRASHDIR" > /dev/null
|
||||||
|
clone_repo "$reponame" "${reponame}_alternate"
|
||||||
|
popd > /dev/null
|
||||||
|
|
||||||
|
rm -rf .git/lfs/objects
|
||||||
|
|
||||||
|
alternate_stale="$TRASHDIR/${reponame}_alternate_stale/.git/objects"
|
||||||
|
alternate="$TRASHDIR/${reponame}_alternate/.git/objects"
|
||||||
|
sep="$(native_path_list_separator)"
|
||||||
|
|
||||||
|
GIT_ALTERNATE_OBJECT_DIRECTORIES="$alternate_stale$sep$alternate" \
|
||||||
|
GIT_TRACE=1 \
|
||||||
|
git lfs fetch origin master 2>&1 | tee fetch.log
|
||||||
|
[ "0" -eq "$(grep -c "sending batch of size 1" fetch.log)" ]
|
||||||
|
)
|
||||||
|
end_test
|
@ -102,3 +102,33 @@ begin_test "askpass: push with SSH_ASKPASS"
|
|||||||
grep "master -> master" push.log
|
grep "master -> master" push.log
|
||||||
)
|
)
|
||||||
end_test
|
end_test
|
||||||
|
|
||||||
|
begin_test "askpass: defaults to provided credentials"
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
reponame="askpass-provided-creds"
|
||||||
|
setup_remote_repo "$reponame"
|
||||||
|
clone_repo "$reponame" "$reponame"
|
||||||
|
|
||||||
|
git lfs track "*.dat"
|
||||||
|
echo "hello" > a.dat
|
||||||
|
|
||||||
|
git add .gitattributes a.dat
|
||||||
|
git commit -m "initial commit"
|
||||||
|
|
||||||
|
# $password is defined from test/cmd/lfstest-gitserver.go (see: skipIfBadAuth)
|
||||||
|
export LFS_ASKPASS_USERNAME="fakeuser"
|
||||||
|
export LFS_ASKPASS_PASSWORD="fakepass"
|
||||||
|
git config --local "credential.helper" ""
|
||||||
|
|
||||||
|
url=$(git config --get remote.origin.url)
|
||||||
|
newurl=${url/http:\/\//http:\/\/user\:pass@}
|
||||||
|
git remote set-url origin "$newurl"
|
||||||
|
|
||||||
|
GIT_ASKPASS="lfs-askpass" GIT_TRACE=1 GIT_CURL_VERBOSE=1 git push origin master 2>&1 | tee push.log
|
||||||
|
|
||||||
|
[ ! $(grep "filling with GIT_ASKPASS" push.log) ]
|
||||||
|
grep "master -> master" push.log
|
||||||
|
)
|
||||||
|
end_test
|
||||||
|
@ -156,3 +156,29 @@ begin_test "checkout: outside git repository"
|
|||||||
grep "Not in a git repository" checkout.log
|
grep "Not in a git repository" checkout.log
|
||||||
)
|
)
|
||||||
end_test
|
end_test
|
||||||
|
|
||||||
|
begin_test "checkout: write-only file"
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
reponame="checkout-locked"
|
||||||
|
filename="a.txt"
|
||||||
|
|
||||||
|
setup_remote_repo_with_file "$reponame" "$filename"
|
||||||
|
|
||||||
|
pushd "$TRASHDIR" > /dev/null
|
||||||
|
GIT_LFS_SKIP_SMUDGE=1 clone_repo "$reponame" "${reponame}_checkout"
|
||||||
|
|
||||||
|
chmod -w "$filename"
|
||||||
|
|
||||||
|
refute_file_writeable "$filename"
|
||||||
|
assert_pointer "refs/heads/master" "$filename" "$(calc_oid "$filename\n")" 6
|
||||||
|
|
||||||
|
git lfs fetch
|
||||||
|
git lfs checkout "$filename"
|
||||||
|
|
||||||
|
refute_file_writeable "$filename"
|
||||||
|
[ "$filename" = "$(cat "$filename")" ]
|
||||||
|
popd > /dev/null
|
||||||
|
)
|
||||||
|
end_test
|
||||||
|
@ -29,7 +29,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -81,7 +81,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -140,7 +140,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -197,7 +197,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -256,7 +256,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -316,7 +316,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -377,7 +377,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=5
|
ConcurrentTransfers=5
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -445,7 +445,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -500,7 +500,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -549,7 +549,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -582,7 +582,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -615,7 +615,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -660,7 +660,7 @@ LocalWorkingDir=
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -739,7 +739,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -772,7 +772,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -838,7 +838,7 @@ LocalWorkingDir=%s
|
|||||||
LocalGitDir=%s
|
LocalGitDir=%s
|
||||||
LocalGitStorageDir=%s
|
LocalGitStorageDir=%s
|
||||||
LocalMediaDir=%s
|
LocalMediaDir=%s
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=%s
|
TempDir=%s
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=true
|
TusTransfers=true
|
||||||
|
@ -178,7 +178,7 @@ setup_single_local_branch_tracked_corrupt() {
|
|||||||
#
|
#
|
||||||
# - Commit 'A' has 120, 140 bytes of data in a.txt, and a.md, respectively.
|
# - Commit 'A' has 120, 140 bytes of data in a.txt, and a.md, respectively.
|
||||||
#
|
#
|
||||||
# - Commit 'B' has 30 bytes of data in a.txt, and includes commit 'A' as a
|
# - Commit 'B' has 30 bytes of data in a.md, and includes commit 'A' as a
|
||||||
# parent.
|
# parent.
|
||||||
setup_multiple_local_branches() {
|
setup_multiple_local_branches() {
|
||||||
set -e
|
set -e
|
||||||
@ -218,6 +218,29 @@ setup_multiple_local_branches_with_gitattrs() {
|
|||||||
git commit -m "add .gitattributes"
|
git commit -m "add .gitattributes"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# setup_multiple_local_branches_non_standard creates a repository as follows:
|
||||||
|
#
|
||||||
|
# refs/pull/1/head
|
||||||
|
# /
|
||||||
|
# |
|
||||||
|
# B
|
||||||
|
# / \
|
||||||
|
# A refs/heads/my-feature
|
||||||
|
# |\
|
||||||
|
# | refs/heads/master
|
||||||
|
# \
|
||||||
|
# refs/pull/1/base
|
||||||
|
#
|
||||||
|
# With the same contents in 'A' and 'B' as setup_multiple_local_branches.
|
||||||
|
setup_multiple_local_branches_non_standard() {
|
||||||
|
set -e
|
||||||
|
|
||||||
|
setup_multiple_local_branches
|
||||||
|
|
||||||
|
git update-ref refs/pull/1/head "$(git rev-parse my-feature)"
|
||||||
|
git update-ref refs/pull/1/base "$(git rev-parse master)"
|
||||||
|
}
|
||||||
|
|
||||||
# setup_multiple_local_branches_tracked creates a repo with exactly the same
|
# setup_multiple_local_branches_tracked creates a repo with exactly the same
|
||||||
# structure as in setup_multiple_local_branches, but with all files tracked by
|
# structure as in setup_multiple_local_branches, but with all files tracked by
|
||||||
# Git LFS
|
# Git LFS
|
||||||
|
@ -763,3 +763,29 @@ begin_test "migrate import (dirty copy, positive answer)"
|
|||||||
assert_local_object "$oid" "5"
|
assert_local_object "$oid" "5"
|
||||||
)
|
)
|
||||||
end_test
|
end_test
|
||||||
|
|
||||||
|
begin_test "migrate import (non-standard refs)"
|
||||||
|
(
|
||||||
|
set -e
|
||||||
|
|
||||||
|
setup_multiple_local_branches_non_standard
|
||||||
|
|
||||||
|
md_oid="$(calc_oid "$(git cat-file -p :a.md)")"
|
||||||
|
txt_oid="$(calc_oid "$(git cat-file -p :a.txt)")"
|
||||||
|
md_feature_oid="$(calc_oid "$(git cat-file -p my-feature:a.md)")"
|
||||||
|
|
||||||
|
git lfs migrate import --everything
|
||||||
|
|
||||||
|
assert_pointer "refs/heads/master" "a.md" "$md_oid" "140"
|
||||||
|
assert_pointer "refs/heads/master" "a.txt" "$txt_oid" "120"
|
||||||
|
assert_pointer "refs/pull/1/base" "a.md" "$md_oid" "140"
|
||||||
|
assert_pointer "refs/pull/1/base" "a.txt" "$txt_oid" "120"
|
||||||
|
|
||||||
|
assert_pointer "refs/heads/my-feature" "a.txt" "$txt_oid" "120"
|
||||||
|
assert_pointer "refs/pull/1/head" "a.txt" "$txt_oid" "120"
|
||||||
|
|
||||||
|
assert_local_object "$md_oid" "140"
|
||||||
|
assert_local_object "$txt_oid" "120"
|
||||||
|
assert_local_object "$md_feature_oid" "30"
|
||||||
|
)
|
||||||
|
end_test
|
||||||
|
@ -25,7 +25,7 @@ LocalWorkingDir=$(native_path_escaped "$TRASHDIR/$reponame")
|
|||||||
LocalGitDir=$(native_path_escaped "$TRASHDIR/$reponame/.git")
|
LocalGitDir=$(native_path_escaped "$TRASHDIR/$reponame/.git")
|
||||||
LocalGitStorageDir=$(native_path_escaped "$TRASHDIR/$reponame/.git")
|
LocalGitStorageDir=$(native_path_escaped "$TRASHDIR/$reponame/.git")
|
||||||
LocalMediaDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/lfs/objects")
|
LocalMediaDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/lfs/tmp")
|
TempDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/lfs/tmp")
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
@ -61,7 +61,7 @@ LocalWorkingDir=$(native_path_escaped "$TRASHDIR/$worktreename")
|
|||||||
LocalGitDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/worktrees/$worktreename")
|
LocalGitDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/worktrees/$worktreename")
|
||||||
LocalGitStorageDir=$(native_path_escaped "$TRASHDIR/$reponame/.git")
|
LocalGitStorageDir=$(native_path_escaped "$TRASHDIR/$reponame/.git")
|
||||||
LocalMediaDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/lfs/objects")
|
LocalMediaDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/lfs/objects")
|
||||||
LocalReferenceDir=
|
LocalReferenceDirs=
|
||||||
TempDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/worktrees/$worktreename/lfs/tmp")
|
TempDir=$(native_path_escaped "$TRASHDIR/$reponame/.git/worktrees/$worktreename/lfs/tmp")
|
||||||
ConcurrentTransfers=3
|
ConcurrentTransfers=3
|
||||||
TusTransfers=false
|
TusTransfers=false
|
||||||
|
@ -40,7 +40,7 @@ refute_pointer() {
|
|||||||
|
|
||||||
file=$(git cat-file -p $gitblob)
|
file=$(git cat-file -p $gitblob)
|
||||||
version="version https://git-lfs.github.com/spec/v[0-9]"
|
version="version https://git-lfs.github.com/spec/v[0-9]"
|
||||||
oid="oid sha256:[0-9a-f]\{32\}"
|
oid="oid sha256:[0-9a-f]\{64\}"
|
||||||
size="size [0-9]*"
|
size="size [0-9]*"
|
||||||
regex="$version.*$oid.*$size"
|
regex="$version.*$oid.*$size"
|
||||||
|
|
||||||
@ -730,6 +730,16 @@ native_path_escaped() {
|
|||||||
escape_path "$unescaped"
|
escape_path "$unescaped"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# native_path_list_separator prints the operating system-specific path list
|
||||||
|
# separator.
|
||||||
|
native_path_list_separator() {
|
||||||
|
if [ "$IS_WINDOWS" -eq 1 ]; then
|
||||||
|
printf ";";
|
||||||
|
else
|
||||||
|
printf ":";
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
cat_end() {
|
cat_end() {
|
||||||
if [ $IS_WINDOWS -eq 1 ]; then
|
if [ $IS_WINDOWS -eq 1 ]; then
|
||||||
printf '^M$'
|
printf '^M$'
|
||||||
|
Loading…
Reference in New Issue
Block a user