lfs,git: send refspec in batch api calls from smudge filter
This commit is contained in:
parent
0855165dc8
commit
8c1ad56924
101
git/refs.go
Normal file
101
git/refs.go
Normal file
@ -0,0 +1,101 @@
|
||||
package git
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/rubyist/tracerx"
|
||||
)
|
||||
|
||||
type RefUpdate struct {
|
||||
git Env
|
||||
remote string
|
||||
left *Ref
|
||||
right *Ref
|
||||
}
|
||||
|
||||
func NewRefUpdate(g Env, remote string, l, r *Ref) *RefUpdate {
|
||||
return &RefUpdate{
|
||||
git: g,
|
||||
remote: remote,
|
||||
left: l,
|
||||
right: r,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *RefUpdate) Left() *Ref {
|
||||
return u.left
|
||||
}
|
||||
|
||||
func (u *RefUpdate) LeftCommitish() string {
|
||||
return refCommitish(u.Left())
|
||||
}
|
||||
|
||||
func (u *RefUpdate) Right() *Ref {
|
||||
if u.right == nil {
|
||||
u.right = defaultRemoteRef(u.git, u.remote, u.Left())
|
||||
}
|
||||
return u.right
|
||||
}
|
||||
|
||||
// defaultRemoteRef returns the remote ref receiving a push based on the current
|
||||
// repository config and local ref being pushed.
|
||||
//
|
||||
// See push.default rules in https://git-scm.com/docs/git-config
|
||||
func defaultRemoteRef(g Env, remote string, left *Ref) *Ref {
|
||||
pushMode, _ := g.Get("push.default")
|
||||
tracerx.Printf("DEBUG %q pushmode = %q", remote, pushMode)
|
||||
switch pushMode {
|
||||
case "", "simple":
|
||||
brRemote, _ := g.Get(fmt.Sprintf("branch.%s.remote", left.Name))
|
||||
if brRemote == remote {
|
||||
// in centralized workflow, work like 'upstream' with an added safety to
|
||||
// refuse to push if the upstream branch’s name is different from the
|
||||
// local one.
|
||||
return trackingRef(g, left)
|
||||
}
|
||||
|
||||
// When pushing to a remote that is different from the remote you normally
|
||||
// pull from, work as current.
|
||||
return left
|
||||
case "upstream", "tracking":
|
||||
// push the current branch back to the branch whose changes are usually
|
||||
// integrated into the current branch
|
||||
return trackingRef(g, left)
|
||||
case "current":
|
||||
// push the current branch to update a branch with the same name on the
|
||||
// receiving end.
|
||||
return left
|
||||
default:
|
||||
tracerx.Printf("WARNING: %q push mode not supported", pushMode)
|
||||
return left
|
||||
}
|
||||
}
|
||||
|
||||
func trackingRef(g Env, left *Ref) *Ref {
|
||||
if merge, ok := g.Get(fmt.Sprintf("branch.%s.merge", left.Name)); ok {
|
||||
tracerx.Printf("DEBUG %q branch merge %q", left.Name, merge)
|
||||
return ParseRef(merge, "")
|
||||
}
|
||||
tracerx.Printf("DEBUG %q branch merge default %+v", left.Name, left)
|
||||
return left
|
||||
}
|
||||
|
||||
func (u *RefUpdate) RightCommitish() string {
|
||||
return refCommitish(u.Right())
|
||||
}
|
||||
|
||||
func refCommitish(r *Ref) string {
|
||||
if len(r.Sha) > 0 {
|
||||
return r.Sha
|
||||
}
|
||||
return r.Name
|
||||
}
|
||||
|
||||
// copy of env
|
||||
type Env interface {
|
||||
Get(key string) (val string, ok bool)
|
||||
GetAll(key string) (vals []string)
|
||||
Bool(key string, def bool) (val bool)
|
||||
Int(key string, def int) (val int)
|
||||
All() map[string][]string
|
||||
}
|
@ -3,6 +3,7 @@ package lfs
|
||||
import (
|
||||
"github.com/git-lfs/git-lfs/config"
|
||||
"github.com/git-lfs/git-lfs/fs"
|
||||
"github.com/git-lfs/git-lfs/git"
|
||||
)
|
||||
|
||||
// GitFilter provides clean and smudge capabilities
|
||||
@ -19,3 +20,7 @@ func NewGitFilter(cfg *config.Configuration) *GitFilter {
|
||||
func (f *GitFilter) ObjectPath(oid string) (string, error) {
|
||||
return f.fs.ObjectPath(oid)
|
||||
}
|
||||
|
||||
func (f *GitFilter) RemoteRef() *git.Ref {
|
||||
return git.NewRefUpdate(f.cfg.Git, f.cfg.PushRemote(), f.cfg.CurrentRef(), nil).Right()
|
||||
}
|
||||
|
@ -80,7 +80,10 @@ func (f *GitFilter) downloadFile(writer io.Writer, ptr *Pointer, workingfile, me
|
||||
// Either way, forward it into the *tq.TransferQueue so that updates are
|
||||
// sent over correctly.
|
||||
|
||||
q := tq.NewTransferQueue(tq.Download, manifest, f.cfg.Remote(), tq.WithProgressCallback(cb))
|
||||
q := tq.NewTransferQueue(tq.Download, manifest, f.cfg.Remote(),
|
||||
tq.WithProgressCallback(cb),
|
||||
tq.RemoteRef(f.RemoteRef()),
|
||||
)
|
||||
q.Add(filepath.Base(workingfile), mediafile, ptr.Oid, ptr.Size)
|
||||
q.Wait()
|
||||
|
||||
|
88
test/test-fetch-refspec.sh
Executable file
88
test/test-fetch-refspec.sh
Executable file
@ -0,0 +1,88 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
. "test/testlib.sh"
|
||||
|
||||
begin_test "fetch with good ref"
|
||||
(
|
||||
set -e
|
||||
|
||||
reponame="fetch-master-branch-required"
|
||||
setup_remote_repo "$reponame"
|
||||
clone_repo "$reponame" "$reponame"
|
||||
|
||||
git lfs track "*.dat"
|
||||
echo "a" > a.dat
|
||||
git add .gitattributes a.dat
|
||||
git commit -m "add a.dat"
|
||||
|
||||
git push origin master
|
||||
|
||||
# $ echo "a" | shasum -a 256
|
||||
oid="87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7"
|
||||
assert_local_object "$oid" 2
|
||||
assert_server_object "$reponame" "$oid" "refs/heads/master"
|
||||
|
||||
rm -rf .git/lfs/objects
|
||||
git lfs fetch --all
|
||||
assert_local_object "$oid" 2
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "fetch with tracked ref"
|
||||
(
|
||||
set -e
|
||||
|
||||
reponame="fetch-tracked-branch-required"
|
||||
setup_remote_repo "$reponame"
|
||||
clone_repo "$reponame" "$reponame"
|
||||
|
||||
git lfs track "*.dat"
|
||||
echo "a" > a.dat
|
||||
git add .gitattributes a.dat
|
||||
git commit -m "add a.dat"
|
||||
|
||||
git push origin master:tracked
|
||||
|
||||
# $ echo "a" | shasum -a 256
|
||||
oid="87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7"
|
||||
assert_local_object "$oid" 2
|
||||
assert_server_object "$reponame" "$oid" "refs/heads/tracked"
|
||||
|
||||
rm -rf .git/lfs/objects
|
||||
git config push.default upstream
|
||||
git config branch.master.merge refs/heads/tracked
|
||||
git lfs fetch --all
|
||||
assert_local_object "$oid" 2
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "fetch with bad ref"
|
||||
(
|
||||
set -e
|
||||
|
||||
reponame="fetch-other-branch-required"
|
||||
setup_remote_repo "$reponame"
|
||||
clone_repo "$reponame" "$reponame"
|
||||
|
||||
git lfs track "*.dat"
|
||||
echo "a" > a.dat
|
||||
git add .gitattributes a.dat
|
||||
git commit -m "add a.dat"
|
||||
|
||||
git push origin master:other
|
||||
|
||||
# $ echo "a" | shasum -a 256
|
||||
oid="87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7"
|
||||
assert_local_object "$oid" 2
|
||||
assert_server_object "$reponame" "$oid" "refs/heads/other"
|
||||
|
||||
rm -rf .git/lfs/objects
|
||||
GIT_CURL_VERBOSE=1 git lfs fetch --all 2>&1 | tee fetch.log
|
||||
if [ "0" -eq "${PIPESTATUS[0]}" ]; then
|
||||
echo >&2 "fatal: expected 'git lfs fetch' to fail"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
grep 'Expected ref "refs/heads/other", got "refs/heads/master"' fetch.log
|
||||
)
|
||||
end_test
|
@ -93,6 +93,62 @@ begin_test "happy path on non-origin remote"
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "happy path on good ref"
|
||||
(
|
||||
set -e
|
||||
|
||||
reponame="happy-path-master-branch-required"
|
||||
setup_remote_repo "$reponame"
|
||||
clone_repo "$reponame" "$reponame"
|
||||
|
||||
git lfs track "*.dat"
|
||||
echo "a" > a.dat
|
||||
git add .gitattributes a.dat
|
||||
git commit -m "add a.dat"
|
||||
|
||||
git push origin master
|
||||
|
||||
# $ echo "a" | shasum -a 256
|
||||
oid="87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7"
|
||||
assert_local_object "$oid" 2
|
||||
assert_server_object "$reponame" "$oid" "refs/heads/master"
|
||||
|
||||
clone_repo "$reponame" "$reponame-clone"
|
||||
assert_local_object "$oid" 2
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "happy path on tracked ref"
|
||||
(
|
||||
set -e
|
||||
|
||||
reponame="happy-path-tracked-branch-required"
|
||||
setup_remote_repo "$reponame"
|
||||
clone_repo "$reponame" "$reponame"
|
||||
|
||||
git lfs track "*.dat"
|
||||
echo "a" > a.dat
|
||||
git add .gitattributes a.dat
|
||||
git commit -m "add a.dat"
|
||||
|
||||
git push origin master:tracked
|
||||
|
||||
# $ echo "a" | shasum -a 256
|
||||
oid="87428fc522803d31065e7bce3cf03fe475096631e5e07bbd7a0fde60c4cf25c7"
|
||||
assert_local_object "$oid" 2
|
||||
assert_server_object "$reponame" "$oid" "refs/heads/tracked"
|
||||
|
||||
git lfs clone "$GITSERVER/$reponame" --exclude "*"
|
||||
|
||||
git config credential.helper lfstest
|
||||
git config push.default upstream
|
||||
git config branch.master.merge refs/heads/tracked
|
||||
|
||||
git checkout
|
||||
assert_local_object "$oid" 2
|
||||
)
|
||||
end_test
|
||||
|
||||
begin_test "clears local temp objects"
|
||||
(
|
||||
set -e
|
||||
|
Loading…
Reference in New Issue
Block a user