Merge branch 'push-other-branch' into fetch-recent

This commit is contained in:
Steve Streeting 2015-08-26 14:39:59 +01:00
commit aeca33c3ee
10 changed files with 173 additions and 29 deletions

@ -207,4 +207,12 @@ func fetchAndReportToChan(pointers []*lfs.WrappedPointer, include, exclude []str
processQueue := time.Now() processQueue := time.Now()
q.Wait() q.Wait()
tracerx.PerformanceSince("process queue", processQueue) tracerx.PerformanceSince("process queue", processQueue)
for _, err := range q.Errors() {
if Debugging || err.Panic {
LoggedError(err.Err, err.Error())
} else {
Error(err.Error())
}
}
} }

@ -90,7 +90,7 @@ func prePushCommand(cmd *cobra.Command, args []string) {
for _, pointer := range pointers { for _, pointer := range pointers {
if prePushDryRun { if prePushDryRun {
Print("push %s", pointer.Name) Print("push %s [%s]", pointer.Name, pointer.Oid)
continue continue
} }

@ -3,7 +3,6 @@ package commands
import ( import (
"io/ioutil" "io/ioutil"
"os" "os"
"strings"
"github.com/github/git-lfs/git" "github.com/github/git-lfs/git"
"github.com/github/git-lfs/lfs" "github.com/github/git-lfs/lfs"
@ -26,11 +25,29 @@ var (
) )
func uploadsBetweenRefs(left string, right string) *lfs.TransferQueue { func uploadsBetweenRefs(left string, right string) *lfs.TransferQueue {
tracerx.Printf("Upload between %v and %v", left, right)
// Just use scanner here // Just use scanner here
pointers, err := lfs.ScanRefs(left, right, nil) pointers, err := lfs.ScanRefs(left, right, nil)
if err != nil { if err != nil {
Panic(err, "Error scanning for Git LFS files") Panic(err, "Error scanning for Git LFS files")
} }
return uploadPointers(pointers)
}
func uploadsBetweenRefAndRemote(ref, remote string) *lfs.TransferQueue {
tracerx.Printf("Upload between %v and remote %v", ref, remote)
scanOpt := &lfs.ScanRefsOptions{ScanMode: lfs.ScanLeftToRemoteMode, RemoteName: remote}
pointers, err := lfs.ScanRefs(ref, "", scanOpt)
if err != nil {
Panic(err, "Error scanning for Git LFS files")
}
return uploadPointers(pointers)
}
func uploadPointers(pointers []*lfs.WrappedPointer) *lfs.TransferQueue {
totalSize := int64(0) totalSize := int64(0)
for _, p := range pointers { for _, p := range pointers {
@ -40,7 +57,7 @@ func uploadsBetweenRefs(left string, right string) *lfs.TransferQueue {
uploadQueue := lfs.NewUploadQueue(len(pointers), totalSize, pushDryRun) uploadQueue := lfs.NewUploadQueue(len(pointers), totalSize, pushDryRun)
for i, pointer := range pointers { for i, pointer := range pointers {
if pushDryRun { if pushDryRun {
Print("push %s", pointer.Name) Print("push %s [%s]", pointer.Name, pointer.Oid)
continue continue
} }
@ -101,7 +118,6 @@ func uploadsWithObjectIDs(oids []string) *lfs.TransferQueue {
// pushCommand calculates the git objects to send by looking comparing the range // pushCommand calculates the git objects to send by looking comparing the range
// of commits between the local and remote git servers. // of commits between the local and remote git servers.
func pushCommand(cmd *cobra.Command, args []string) { func pushCommand(cmd *cobra.Command, args []string) {
var left, right string
var uploadQueue *lfs.TransferQueue var uploadQueue *lfs.TransferQueue
if len(args) == 0 { if len(args) == 0 {
@ -127,7 +143,7 @@ func pushCommand(cmd *cobra.Command, args []string) {
return return
} }
left, right = decodeRefs(string(refsData)) left, right := decodeRefs(string(refsData))
if left == pushDeleteBranch { if left == pushDeleteBranch {
return return
} }
@ -141,34 +157,27 @@ func pushCommand(cmd *cobra.Command, args []string) {
uploadQueue = uploadsWithObjectIDs(args[1:]) uploadQueue = uploadsWithObjectIDs(args[1:])
} else { } else {
var remoteArg, refArg string
if len(args) < 1 { if len(args) < 1 {
Print("Usage: git lfs push --dry-run <remote> [ref]") Print("Usage: git lfs push --dry-run <remote> [ref]")
return return
} }
remoteArg = args[0] remote := args[0]
var ref string
if len(args) == 2 { if len(args) == 2 {
refArg = args[1] ref = args[1]
} }
if ref == "" {
localRef, err := git.CurrentRef() localRef, err := git.CurrentRef()
if err != nil { if err != nil {
Panic(err, "Error getting local ref") Panic(err, "Error getting local ref")
} }
left = localRef.Sha ref = localRef.Sha
remoteRef, err := git.LsRemote(remoteArg, refArg)
if err != nil {
Panic(err, "Error getting remote ref")
} }
if remoteRef != "" { uploadQueue = uploadsBetweenRefAndRemote(ref, remote)
right = "^" + strings.Split(remoteRef, "\t")[0]
}
uploadQueue = uploadsBetweenRefs(left, right)
} }
if !pushDryRun { if !pushDryRun {

@ -218,7 +218,7 @@ func Batch(objects []*objectResource, operation string) ([]*objectResource, *Wra
LogTransfer("lfs.api.batch", res) LogTransfer("lfs.api.batch", res)
if res.StatusCode != 200 { if res.StatusCode != 200 {
return nil, Errorf(nil, "Invalid status for %s %s: %d", req.Method, req.URL, res.StatusCode) return nil, Error(fmt.Errorf("Invalid status for %s %s: %d", req.Method, req.URL, res.StatusCode))
} }
return objs, nil return objs, nil

@ -1,10 +1,13 @@
package lfs package lfs
import ( import (
"errors"
"fmt" "fmt"
"runtime" "runtime"
) )
var genericError = errors.New("Git LFS client error")
type WrappedError struct { type WrappedError struct {
Err error Err error
Message string Message string
@ -19,7 +22,7 @@ func Error(err error) *WrappedError {
func Errorf(err error, format string, args ...interface{}) *WrappedError { func Errorf(err error, format string, args ...interface{}) *WrappedError {
if err == nil { if err == nil {
return nil err = genericError
} }
e := &WrappedError{ e := &WrappedError{

@ -176,7 +176,9 @@ func (q *TransferQueue) batchApiRoutine() {
go q.legacyFallback(batch) go q.legacyFallback(batch)
return return
} }
q.errorc <- err q.errorc <- err
q.wait.Add(-len(transfers))
continue continue
} }

@ -206,6 +206,11 @@ func lfsBatchHandler(w http.ResponseWriter, r *http.Request, repo string) {
return return
} }
if repo == "badbatch" {
w.WriteHeader(203)
return
}
type batchReq struct { type batchReq struct {
Operation string `json:"operation"` Operation string `json:"operation"`
Objects []lfsObject `json:"objects"` Objects []lfsObject `json:"objects"`

@ -0,0 +1,56 @@
#!/usr/bin/env bash
# This is a sample Git LFS test. See test/README.md and testhelpers.sh for
# more documentation.
. "test/testlib.sh"
begin_test "batch error handling"
(
set -e
# This initializes a new bare git repository in test/remote.
# These remote repositories are global to every test, so keep the names
# unique.
reponame="badbatch" # Server looks for the "badbatch" repo, returns a 203 status
setup_remote_repo "$reponame"
# Clone the repository from the test Git server. This is empty, and will be
# used to test a "git pull" below. The repo is cloned to $TRASHDIR/clone
clone_repo "$reponame" clone
# Clone the repository again to $TRASHDIR/repo. This will be used to commit
# and push objects.
clone_repo "$reponame" repo
# This executes Git LFS from the local repo that was just cloned.
git lfs track "*.dat" 2>&1 | tee track.log
grep "Tracking \*.dat" track.log
contents="a"
contents_oid=$(printf "$contents" | shasum -a 256 | cut -f 1 -d " ")
printf "$contents" > a.dat
git add a.dat
git add .gitattributes
git commit -m "add a.dat" 2>&1 | tee commit.log
grep "master (root-commit)" commit.log
grep "2 files changed" commit.log
grep "create mode 100644 a.dat" commit.log
grep "create mode 100644 .gitattributes" commit.log
[ "a" = "$(cat a.dat)" ]
# This is a small shell function that runs several git commands together.
assert_pointer "master" "a.dat" "$contents_oid" 1
refute_server_object "$reponame" "$contents_oid"
# Ensure batch transfer is turned on for this repo
git config --add --local lfs.batch true
# This pushes to the remote repository set up at the top of the test.
git push origin master 2>&1 | tee push.log
grep "Invalid status for POST" push.log
)
end_test

@ -41,7 +41,9 @@ begin_test "push dry-run"
git add .gitattributes a.dat git add .gitattributes a.dat
git commit -m "add a.dat" git commit -m "add a.dat"
[ "push a.dat" = "$(git lfs push --dry-run origin master 2>&1)" ] git lfs push --dry-run origin master 2>&1 | tee push.log
grep "push a.dat" push.log
[ $(wc -l < push.log) -eq 1 ]
git checkout -b push-b git checkout -b push-b
echo "push b" > b.dat echo "push b" > b.dat
@ -84,3 +86,62 @@ begin_test "push object id(s)"
grep "(2 of 2 files)" push.log grep "(2 of 2 files)" push.log
) )
end_test end_test
begin_test "push modified files"
(
set -e
reponame="$(basename "$0" ".sh")-modified"
setup_remote_repo "$reponame"
clone_repo "$reponame" "$reponame"
git lfs track "*.dat"
# generate content we'll use
content1="filecontent1"
content2="filecontent2"
content3="filecontent3"
content4="filecontent4"
content5="filecontent5"
oid1=$(printf "$content1" | shasum -a 256 | cut -f 1 -d " ")
oid2=$(printf "$content2" | shasum -a 256 | cut -f 1 -d " ")
oid3=$(printf "$content3" | shasum -a 256 | cut -f 1 -d " ")
oid4=$(printf "$content4" | shasum -a 256 | cut -f 1 -d " ")
oid5=$(printf "$content5" | shasum -a 256 | cut -f 1 -d " ")
echo "[
{
\"CommitDate\":\"$(get_date -6m)\",
\"Files\":[
{\"Filename\":\"file1.dat\",\"Size\":${#content1}, \"Data\":\"$content1\"}]
},
{
\"CommitDate\":\"$(get_date -3m)\",
\"Files\":[
{\"Filename\":\"file1.dat\",\"Size\":${#content2}, \"Data\":\"$content2\"}]
},
{
\"CommitDate\":\"$(get_date -1m)\",
\"NewBranch\":\"other_branch\",
\"Files\":[
{\"Filename\":\"file1.dat\",\"Size\":${#content5}, \"Data\":\"$content5\"}]
},
{
\"CommitDate\":\"$(get_date -1m)\",
\"ParentBranches\":[\"master\"],
\"Files\":[
{\"Filename\":\"file1.dat\",\"Size\":${#content3}, \"Data\":\"$content3\"},
{\"Filename\":\"file2.dat\",\"Size\":${#content4}, \"Data\":\"$content4\"}]
}
]" | lfstest-testutils addcommits
git lfs push origin master
git lfs push origin other_branch
assert_server_object "$reponame" "$oid1"
assert_server_object "$reponame" "$oid2"
assert_server_object "$reponame" "$oid3"
assert_server_object "$reponame" "$oid4"
assert_server_object "$reponame" "$oid5"
)
end_test