2014-06-03 15:08:58 +00:00
|
|
|
package commands
|
2013-10-04 17:09:03 +00:00
|
|
|
|
|
|
|
import (
|
2015-05-13 19:43:41 +00:00
|
|
|
"os"
|
|
|
|
|
2017-01-11 20:59:25 +00:00
|
|
|
"github.com/git-lfs/git-lfs/errors"
|
2016-11-15 17:01:18 +00:00
|
|
|
"github.com/git-lfs/git-lfs/git"
|
|
|
|
"github.com/git-lfs/git-lfs/lfs"
|
2018-01-05 18:12:57 +00:00
|
|
|
"github.com/git-lfs/git-lfs/tq"
|
2016-05-23 18:02:27 +00:00
|
|
|
"github.com/rubyist/tracerx"
|
|
|
|
"github.com/spf13/cobra"
|
2013-10-04 17:09:03 +00:00
|
|
|
)
|
|
|
|
|
2014-06-26 20:53:37 +00:00
|
|
|
var (
|
2016-03-31 15:02:01 +00:00
|
|
|
pushDryRun = false
|
|
|
|
pushObjectIDs = false
|
|
|
|
pushAll = false
|
|
|
|
useStdin = false
|
2015-04-24 16:41:11 +00:00
|
|
|
|
2015-10-01 19:39:30 +00:00
|
|
|
// 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
|
|
|
|
2017-11-02 18:33:57 +00:00
|
|
|
// pushCommand pushes local objects to a Git LFS server. It takes two
|
|
|
|
// arguments:
|
|
|
|
//
|
|
|
|
// `<remote> <remote ref>`
|
|
|
|
//
|
|
|
|
// Remote must be a remote name, not a URL
|
|
|
|
//
|
|
|
|
// pushCommand calculates the git objects to send by comparing the range
|
|
|
|
// of commits between the local and remote git servers.
|
|
|
|
func pushCommand(cmd *cobra.Command, args []string) {
|
|
|
|
if len(args) == 0 {
|
2021-02-01 21:37:32 +00:00
|
|
|
Print("Specify a remote and a remote branch name (`git lfs push origin main`)")
|
2017-11-02 18:33:57 +00:00
|
|
|
os.Exit(1)
|
|
|
|
}
|
|
|
|
|
|
|
|
requireGitVersion()
|
|
|
|
|
|
|
|
// Remote is first arg
|
2018-07-20 23:38:39 +00:00
|
|
|
if err := cfg.SetValidPushRemote(args[0]); err != nil {
|
2017-11-02 18:33:57 +00:00
|
|
|
Exit("Invalid remote name %q: %s", args[0], err)
|
|
|
|
}
|
|
|
|
|
|
|
|
ctx := newUploadContext(pushDryRun)
|
|
|
|
if pushObjectIDs {
|
|
|
|
if len(args) < 2 {
|
|
|
|
Print("Usage: git lfs push --object-id <remote> <lfs-object-id> [lfs-object-id] ...")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
uploadsWithObjectIDs(ctx, args[1:])
|
|
|
|
} else {
|
|
|
|
if len(args) < 1 {
|
|
|
|
Print("Usage: git lfs push --dry-run <remote> [ref]")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
uploadsBetweenRefAndRemote(ctx, args[1:])
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-04-06 19:06:34 +00:00
|
|
|
func uploadsBetweenRefAndRemote(ctx *uploadContext, refnames []string) {
|
2017-01-04 15:56:09 +00:00
|
|
|
tracerx.Printf("Upload refs %v to remote %v", refnames, ctx.Remote)
|
2015-09-08 20:51:38 +00:00
|
|
|
|
2017-11-02 18:33:57 +00:00
|
|
|
updates, err := lfsPushRefs(refnames, pushAll)
|
2016-04-06 19:06:34 +00:00
|
|
|
if err != nil {
|
|
|
|
Error(err.Error())
|
|
|
|
Exit("Error getting local refs.")
|
|
|
|
}
|
2015-09-09 20:18:51 +00:00
|
|
|
|
2017-11-03 16:08:08 +00:00
|
|
|
if err := uploadForRefUpdates(ctx, updates, pushAll); err != nil {
|
|
|
|
ExitWithError(err)
|
2016-11-16 20:51:36 +00:00
|
|
|
}
|
|
|
|
}
|
2015-09-09 20:18:51 +00:00
|
|
|
|
2016-04-06 19:06:34 +00:00
|
|
|
func uploadsWithObjectIDs(ctx *uploadContext, oids []string) {
|
2017-11-03 16:08:08 +00:00
|
|
|
pointers := make([]*lfs.WrappedPointer, len(oids))
|
|
|
|
for i, oid := range oids {
|
2017-10-25 17:31:15 +00:00
|
|
|
mp, err := ctx.gitfilter.ObjectPath(oid)
|
2017-01-11 20:59:25 +00:00
|
|
|
if err != nil {
|
|
|
|
ExitWithError(errors.Wrap(err, "Unable to find local media path:"))
|
|
|
|
}
|
|
|
|
|
|
|
|
stat, err := os.Stat(mp)
|
|
|
|
if err != nil {
|
|
|
|
ExitWithError(errors.Wrap(err, "Unable to stat local media path"))
|
|
|
|
}
|
|
|
|
|
2017-11-03 16:08:08 +00:00
|
|
|
pointers[i] = &lfs.WrappedPointer{
|
2017-01-11 20:59:25 +00:00
|
|
|
Name: mp,
|
|
|
|
Pointer: &lfs.Pointer{
|
|
|
|
Oid: oid,
|
|
|
|
Size: stat.Size(),
|
|
|
|
},
|
2017-11-03 16:08:08 +00:00
|
|
|
}
|
2015-06-28 15:13:44 +00:00
|
|
|
}
|
2016-12-29 21:30:58 +00:00
|
|
|
|
2018-01-05 18:12:57 +00:00
|
|
|
q := ctx.NewQueue(tq.RemoteRef(currentRemoteRef()))
|
2018-01-04 18:54:20 +00:00
|
|
|
ctx.UploadPointers(q, pointers...)
|
|
|
|
ctx.CollectErrors(q)
|
2018-01-04 17:57:33 +00:00
|
|
|
ctx.ReportErrors()
|
2015-06-28 15:13:44 +00:00
|
|
|
}
|
|
|
|
|
2017-11-02 18:33:57 +00:00
|
|
|
// lfsPushRefs returns valid ref updates from the given ref and --all arguments.
|
|
|
|
// Either one or more refs can be explicitly specified, or --all indicates all
|
|
|
|
// local refs are pushed.
|
2018-01-05 22:22:25 +00:00
|
|
|
func lfsPushRefs(refnames []string, pushAll bool) ([]*git.RefUpdate, error) {
|
2016-04-06 19:06:34 +00:00
|
|
|
localrefs, err := git.LocalRefs()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2015-07-06 13:49:52 +00:00
|
|
|
|
2016-04-06 19:06:34 +00:00
|
|
|
if pushAll && len(refnames) == 0 {
|
2018-01-05 22:22:25 +00:00
|
|
|
refs := make([]*git.RefUpdate, len(localrefs))
|
2017-11-02 18:33:57 +00:00
|
|
|
for i, lr := range localrefs {
|
2018-01-05 22:22:25 +00:00
|
|
|
refs[i] = git.NewRefUpdate(cfg.Git, cfg.PushRemote(), lr, nil)
|
2017-11-02 18:33:57 +00:00
|
|
|
}
|
|
|
|
return refs, nil
|
2015-07-27 20:41:57 +00:00
|
|
|
}
|
|
|
|
|
2016-04-06 19:06:34 +00:00
|
|
|
reflookup := make(map[string]*git.Ref, len(localrefs))
|
|
|
|
for _, ref := range localrefs {
|
|
|
|
reflookup[ref.Name] = ref
|
|
|
|
}
|
2015-07-27 20:41:57 +00:00
|
|
|
|
2018-01-05 22:22:25 +00:00
|
|
|
refs := make([]*git.RefUpdate, len(refnames))
|
2016-04-06 19:06:34 +00:00
|
|
|
for i, name := range refnames {
|
2017-11-02 18:33:57 +00:00
|
|
|
if left, ok := reflookup[name]; ok {
|
2018-01-05 22:22:25 +00:00
|
|
|
refs[i] = git.NewRefUpdate(cfg.Git, cfg.PushRemote(), left, nil)
|
2016-04-06 19:06:34 +00:00
|
|
|
} else {
|
2017-11-02 18:33:57 +00:00
|
|
|
left := &git.Ref{Name: name, Type: git.RefTypeOther, Sha: name}
|
2018-01-05 22:22:25 +00:00
|
|
|
refs[i] = git.NewRefUpdate(cfg.Git, cfg.PushRemote(), left, nil)
|
2016-04-06 19:06:34 +00:00
|
|
|
}
|
2015-06-28 15:13:44 +00:00
|
|
|
}
|
|
|
|
|
2016-04-06 19:06:34 +00:00
|
|
|
return refs, nil
|
2015-06-28 15:13:44 +00:00
|
|
|
}
|
|
|
|
|
2013-10-04 17:09:03 +00:00
|
|
|
func init() {
|
2016-09-01 16:09:38 +00:00
|
|
|
RegisterCommand("push", pushCommand, func(cmd *cobra.Command) {
|
2016-08-10 15:33:25 +00:00
|
|
|
cmd.Flags().BoolVarP(&pushDryRun, "dry-run", "d", false, "Do everything except actually send the updates")
|
|
|
|
cmd.Flags().BoolVarP(&pushObjectIDs, "object-id", "o", false, "Push LFS object ID(s)")
|
|
|
|
cmd.Flags().BoolVarP(&pushAll, "all", "a", false, "Push all objects for the current ref to the remote.")
|
|
|
|
})
|
2013-10-04 17:09:03 +00:00
|
|
|
}
|