git-lfs/commands/command_push.go

224 lines
5.3 KiB
Go
Raw Normal View History

package commands
2013-10-04 17:09:03 +00:00
import (
2015-05-13 19:43:41 +00:00
"io/ioutil"
"os"
2015-03-19 19:30:55 +00:00
"github.com/github/git-lfs/lfs"
2015-05-25 18:20:50 +00:00
"github.com/github/git-lfs/vendor/_nuts/github.com/rubyist/tracerx"
"github.com/github/git-lfs/vendor/_nuts/github.com/spf13/cobra"
2013-10-04 17:09:03 +00:00
)
2014-06-26 20:53:37 +00:00
var (
pushCmd = &cobra.Command{
2015-09-17 22:08:28 +00:00
Use: "push",
Run: pushCommand,
2014-06-26 20:53:37 +00:00
}
2015-04-24 16:41:11 +00:00
pushDryRun = false
pushDeleteBranch = "(delete)"
pushObjectIDs = false
pushAll = false
2015-04-24 16:41:11 +00:00
useStdin = false
// shares some global vars and functions with command_pre_push.go
2014-06-26 20:53:37 +00:00
)
2013-10-04 17:09:03 +00:00
func uploadsBetweenRefs(left string, right string) *lfs.TransferQueue {
tracerx.Printf("Upload between %v and %v", left, right)
// Just use scanner here
2015-07-06 17:08:38 +00:00
pointers, err := lfs.ScanRefs(left, right, nil)
if err != nil {
Panic(err, "Error scanning for Git LFS files")
}
return uploadPointers(pointers)
}
func uploadsBetweenRefAndRemote(remote string, refs []string) *lfs.TransferQueue {
tracerx.Printf("Upload refs %v to remote %v", remote, refs)
2015-09-08 20:51:38 +00:00
scanOpt := &lfs.ScanRefsOptions{ScanMode: lfs.ScanLeftToRemoteMode, RemoteName: remote}
if pushAll {
if len(refs) == 0 {
pointers := scanAll()
Print("Pushing objects...")
return uploadPointers(pointers)
} else {
scanOpt.ScanMode = lfs.ScanRefsMode
}
2015-09-08 20:51:38 +00:00
}
// keep a unique set of pointers
oidPointerMap := make(map[string]*lfs.WrappedPointer)
for _, ref := range refs {
pointers, err := lfs.ScanRefs(ref, "", scanOpt)
if err != nil {
Panic(err, "Error scanning for Git LFS files in the %q ref", ref)
}
for _, p := range pointers {
oidPointerMap[p.Oid] = p
}
}
i := 0
pointers := make([]*lfs.WrappedPointer, len(oidPointerMap))
for _, pointer := range oidPointerMap {
pointers[i] = pointer
i += 1
}
return uploadPointers(pointers)
}
func uploadPointers(pointers []*lfs.WrappedPointer) *lfs.TransferQueue {
totalSize := int64(0)
for _, p := range pointers {
totalSize += p.Size
}
skipObjects := prePushCheckForMissingObjects(pointers)
uploadQueue := lfs.NewUploadQueue(len(pointers), totalSize, pushDryRun)
for i, pointer := range pointers {
if pushDryRun {
Print("push %s => %s", pointer.Oid, pointer.Name)
continue
}
if _, skip := skipObjects[pointer.Oid]; skip {
// object missing locally but on server, don't bother
continue
}
2015-07-06 13:49:21 +00:00
tracerx.Printf("prepare upload: %s %s %d/%d", pointer.Oid, pointer.Name, i+1, len(pointers))
2015-08-21 18:31:06 +00:00
u, err := lfs.NewUploadable(pointer.Oid, pointer.Name)
if err != nil {
if Debugging || lfs.IsFatalError(err) {
Panic(err, err.Error())
} else {
2015-08-21 18:31:06 +00:00
Exit(err.Error())
}
}
uploadQueue.Add(u)
}
return uploadQueue
}
func uploadsWithObjectIDs(oids []string) *lfs.TransferQueue {
uploads := []*lfs.Uploadable{}
totalSize := int64(0)
for i, oid := range oids {
2015-07-06 13:50:32 +00:00
if pushDryRun {
Print("push object ID %s", oid)
continue
}
tracerx.Printf("prepare upload: %s %d/%d", oid, i+1, len(oids))
2015-08-21 18:31:06 +00:00
u, err := lfs.NewUploadable(oid, "")
if err != nil {
if Debugging || lfs.IsFatalError(err) {
Panic(err, err.Error())
} else {
2015-08-21 18:31:06 +00:00
Exit(err.Error())
}
}
uploads = append(uploads, u)
}
uploadQueue := lfs.NewUploadQueue(len(oids), totalSize, pushDryRun)
for _, u := range uploads {
uploadQueue.Add(u)
}
return uploadQueue
}
2015-04-24 16:41:11 +00:00
// pushCommand pushes local objects to a Git LFS server. It takes two
// arguments:
2014-09-24 17:10:29 +00:00
//
2015-04-24 16:41:11 +00:00
// `<remote> <remote ref>`
2014-09-24 17:10:29 +00:00
//
2015-04-24 16:41:11 +00:00
// Both a remote name ("origin") or a remote URL are accepted.
2014-09-24 17:10:29 +00:00
//
2015-04-24 16:41:11 +00:00
// pushCommand calculates the git objects to send by looking comparing the range
// of commits between the local and remote git servers.
2014-06-26 20:53:37 +00:00
func pushCommand(cmd *cobra.Command, args []string) {
var uploadQueue *lfs.TransferQueue
2014-06-05 18:48:23 +00:00
if len(args) == 0 {
Print("Specify a remote and a remote branch name (`git lfs push origin master`)")
os.Exit(1)
}
2015-03-19 19:30:55 +00:00
lfs.Config.CurrentRemote = args[0]
if useStdin {
requireStdin("Run this command from the Git pre-push hook, or leave the --stdin flag off.")
2015-04-27 21:18:12 +00:00
2015-04-24 17:38:55 +00:00
// called from a pre-push hook! Update the existing pre-push hook if it's
// one that git-lfs set.
lfs.InstallHooks(false)
refsData, err := ioutil.ReadAll(os.Stdin)
if err != nil {
Panic(err, "Error reading refs on stdin")
}
if len(refsData) == 0 {
return
}
left, right := decodeRefs(string(refsData))
2015-04-24 16:41:11 +00:00
if left == pushDeleteBranch {
return
}
uploadQueue = uploadsBetweenRefs(left, right)
} else if pushObjectIDs {
if len(args) < 2 {
2015-07-06 13:48:39 +00:00
Print("Usage: git lfs push --object-id <remote> <lfs-object-id> [lfs-object-id] ...")
return
}
uploadQueue = uploadsWithObjectIDs(args[1:])
} else {
2014-09-29 16:52:24 +00:00
if len(args) < 1 {
2015-04-24 16:41:11 +00:00
Print("Usage: git lfs push --dry-run <remote> [ref]")
return
}
uploadQueue = uploadsBetweenRefAndRemote(args[0], args[1:])
2015-04-23 01:07:52 +00:00
}
if !pushDryRun {
uploadQueue.Wait()
2015-04-24 18:51:21 +00:00
for _, err := range uploadQueue.Errors() {
if Debugging || lfs.IsFatalError(err) {
LoggedError(err, err.Error())
} else {
2015-04-24 18:51:21 +00:00
Error(err.Error())
}
2015-04-23 01:07:52 +00:00
}
2015-04-24 18:51:21 +00:00
if len(uploadQueue.Errors()) > 0 {
os.Exit(2)
}
}
2013-10-04 17:09:03 +00:00
}
func init() {
2015-04-24 16:41:11 +00:00
pushCmd.Flags().BoolVarP(&pushDryRun, "dry-run", "d", false, "Do everything except actually send the updates")
pushCmd.Flags().BoolVarP(&useStdin, "stdin", "s", false, "Take refs on stdin (for pre-push hook)")
pushCmd.Flags().BoolVarP(&pushObjectIDs, "object-id", "o", false, "Push LFS object ID(s)")
pushCmd.Flags().BoolVarP(&pushAll, "all", "a", false, "Push all objects for the current ref to the remote.")
2015-09-08 20:51:38 +00:00
2014-06-26 20:53:37 +00:00
RootCmd.AddCommand(pushCmd)
2013-10-04 17:09:03 +00:00
}