commands: extract refUpdate type
This commit is contained in:
parent
30d5ce83e5
commit
44832addfe
@ -2,6 +2,7 @@ package commands
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
@ -50,20 +51,38 @@ func prePushCommand(cmd *cobra.Command, args []string) {
|
||||
Exit("Invalid remote name %q: %s", args[0], err)
|
||||
}
|
||||
|
||||
updates := prePushRefs(os.Stdin)
|
||||
ctx := newUploadContext(prePushDryRun)
|
||||
|
||||
gitscanner, err := ctx.buildGitScanner()
|
||||
if err != nil {
|
||||
ExitWithError(err)
|
||||
}
|
||||
defer gitscanner.Close()
|
||||
|
||||
// We can be passed multiple lines of refs
|
||||
scanner := bufio.NewScanner(os.Stdin)
|
||||
for _, update := range updates {
|
||||
if err := uploadLeftOrAll(gitscanner, ctx, update); err != nil {
|
||||
Print("Error scanning for Git LFS files in %+v", update.Left())
|
||||
ExitWithError(err)
|
||||
}
|
||||
}
|
||||
|
||||
ctx.Await()
|
||||
}
|
||||
|
||||
// prePushRefs parses commit information that the pre-push git hook receives:
|
||||
//
|
||||
// <local ref> <local sha1> <remote ref> <remote sha1>
|
||||
//
|
||||
// Each line describes a proposed update of the remote ref at the remote sha to
|
||||
// the local sha. Multiple updates can be received on multiple lines (such as
|
||||
// from 'git push --all'). These updates are typically received over STDIN.
|
||||
func prePushRefs(r io.Reader) []*refUpdate {
|
||||
scanner := bufio.NewScanner(r)
|
||||
refs := make([]*refUpdate, 0, 1)
|
||||
|
||||
// We can be passed multiple lines of refs
|
||||
for scanner.Scan() {
|
||||
line := strings.TrimSpace(scanner.Text())
|
||||
|
||||
if len(line) == 0 {
|
||||
continue
|
||||
}
|
||||
@ -75,13 +94,10 @@ func prePushCommand(cmd *cobra.Command, args []string) {
|
||||
continue
|
||||
}
|
||||
|
||||
if err := uploadLeftOrAll(gitscanner, ctx, left, right); err != nil {
|
||||
Print("Error scanning for Git LFS files in %+v", left)
|
||||
ExitWithError(err)
|
||||
}
|
||||
refs = append(refs, newRefUpdate(cfg.Git, left, right))
|
||||
}
|
||||
|
||||
ctx.Await()
|
||||
return refs
|
||||
}
|
||||
|
||||
// decodeRefs pulls the sha1s out of the line read from the pre-push
|
||||
|
@ -19,6 +19,46 @@ var (
|
||||
// shares some global vars and functions with command_pre_push.go
|
||||
)
|
||||
|
||||
// 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 {
|
||||
Print("Specify a remote and a remote branch name (`git lfs push origin master`)")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
requireGitVersion()
|
||||
|
||||
// Remote is first arg
|
||||
if err := cfg.SetValidRemote(args[0]); err != nil {
|
||||
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:])
|
||||
}
|
||||
}
|
||||
|
||||
func uploadsBetweenRefAndRemote(ctx *uploadContext, refnames []string) {
|
||||
tracerx.Printf("Upload refs %v to remote %v", refnames, ctx.Remote)
|
||||
|
||||
@ -28,15 +68,15 @@ func uploadsBetweenRefAndRemote(ctx *uploadContext, refnames []string) {
|
||||
}
|
||||
defer gitscanner.Close()
|
||||
|
||||
refs, err := refsByNames(refnames)
|
||||
updates, err := lfsPushRefs(refnames, pushAll)
|
||||
if err != nil {
|
||||
Error(err.Error())
|
||||
Exit("Error getting local refs.")
|
||||
}
|
||||
|
||||
for _, ref := range refs {
|
||||
if err = uploadLeftOrAll(gitscanner, ctx, ref, nil); err != nil {
|
||||
Print("Error scanning for Git LFS files in the %q ref", ref.Name)
|
||||
for _, update := range updates {
|
||||
if err = uploadLeftOrAll(gitscanner, ctx, update); err != nil {
|
||||
Print("Error scanning for Git LFS files in the %q ref", update.Left().Name)
|
||||
ExitWithError(err)
|
||||
}
|
||||
}
|
||||
@ -68,14 +108,21 @@ func uploadsWithObjectIDs(ctx *uploadContext, oids []string) {
|
||||
ctx.Await()
|
||||
}
|
||||
|
||||
func refsByNames(refnames []string) ([]*git.Ref, error) {
|
||||
// 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.
|
||||
func lfsPushRefs(refnames []string, pushAll bool) ([]*refUpdate, error) {
|
||||
localrefs, err := git.LocalRefs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if pushAll && len(refnames) == 0 {
|
||||
return localrefs, nil
|
||||
refs := make([]*refUpdate, len(localrefs))
|
||||
for i, lr := range localrefs {
|
||||
refs[i] = newRefUpdate(cfg.Git, lr, nil)
|
||||
}
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
reflookup := make(map[string]*git.Ref, len(localrefs))
|
||||
@ -83,59 +130,19 @@ func refsByNames(refnames []string) ([]*git.Ref, error) {
|
||||
reflookup[ref.Name] = ref
|
||||
}
|
||||
|
||||
refs := make([]*git.Ref, len(refnames))
|
||||
refs := make([]*refUpdate, len(refnames))
|
||||
for i, name := range refnames {
|
||||
if ref, ok := reflookup[name]; ok {
|
||||
refs[i] = ref
|
||||
if left, ok := reflookup[name]; ok {
|
||||
refs[i] = newRefUpdate(cfg.Git, left, nil)
|
||||
} else {
|
||||
refs[i] = &git.Ref{Name: name, Type: git.RefTypeOther, Sha: name}
|
||||
left := &git.Ref{Name: name, Type: git.RefTypeOther, Sha: name}
|
||||
refs[i] = newRefUpdate(cfg.Git, left, nil)
|
||||
}
|
||||
}
|
||||
|
||||
return refs, nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
Print("Specify a remote and a remote branch name (`git lfs push origin master`)")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
requireGitVersion()
|
||||
|
||||
// Remote is first arg
|
||||
if err := cfg.SetValidRemote(args[0]); err != nil {
|
||||
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:])
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
RegisterCommand("push", pushCommand, func(cmd *cobra.Command) {
|
||||
cmd.Flags().BoolVarP(&pushDryRun, "dry-run", "d", false, "Do everything except actually send the updates")
|
||||
|
53
commands/refs.go
Normal file
53
commands/refs.go
Normal file
@ -0,0 +1,53 @@
|
||||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/git-lfs/git-lfs/config"
|
||||
"github.com/git-lfs/git-lfs/git"
|
||||
)
|
||||
|
||||
type refUpdate struct {
|
||||
git config.Environment
|
||||
left *git.Ref
|
||||
right *git.Ref
|
||||
}
|
||||
|
||||
func newRefUpdate(g config.Environment, l, r *git.Ref) *refUpdate {
|
||||
return &refUpdate{
|
||||
git: g,
|
||||
left: l,
|
||||
right: r,
|
||||
}
|
||||
}
|
||||
|
||||
func (u *refUpdate) Left() *git.Ref {
|
||||
return u.left
|
||||
}
|
||||
|
||||
func (u *refUpdate) LeftCommitish() string {
|
||||
return refCommitish(u.Left())
|
||||
}
|
||||
|
||||
func (u *refUpdate) Right() *git.Ref {
|
||||
if u.right == nil {
|
||||
l := u.Left()
|
||||
if merge, ok := u.git.Get(fmt.Sprintf("branch.%s.merge", l.Name)); ok {
|
||||
u.right = git.ParseRef(merge, "")
|
||||
} else {
|
||||
u.right = &git.Ref{Name: l.Name}
|
||||
}
|
||||
}
|
||||
return u.right
|
||||
}
|
||||
|
||||
func (u *refUpdate) RightCommitish() string {
|
||||
return refCommitish(u.Right())
|
||||
}
|
||||
|
||||
func refCommitish(r *git.Ref) string {
|
||||
if len(r.Sha) > 0 {
|
||||
return r.Sha
|
||||
}
|
||||
return r.Name
|
||||
}
|
@ -9,7 +9,6 @@ import (
|
||||
"sync"
|
||||
|
||||
"github.com/git-lfs/git-lfs/errors"
|
||||
"github.com/git-lfs/git-lfs/git"
|
||||
"github.com/git-lfs/git-lfs/lfs"
|
||||
"github.com/git-lfs/git-lfs/progress"
|
||||
"github.com/git-lfs/git-lfs/tools"
|
||||
@ -17,26 +16,14 @@ import (
|
||||
"github.com/rubyist/tracerx"
|
||||
)
|
||||
|
||||
func uploadLeftOrAll(g *lfs.GitScanner, ctx *uploadContext, left, right *git.Ref) error {
|
||||
leftName := left.Name
|
||||
if len(left.Sha) > 0 {
|
||||
leftName = left.Sha
|
||||
}
|
||||
|
||||
func uploadLeftOrAll(g *lfs.GitScanner, ctx *uploadContext, update *refUpdate) error {
|
||||
if pushAll {
|
||||
if err := g.ScanRefWithDeleted(leftName, nil); err != nil {
|
||||
if err := g.ScanRefWithDeleted(update.LeftCommitish(), nil); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if right == nil {
|
||||
if merge, ok := cfg.Git.Get(fmt.Sprintf("branch.%s.merge", left.Name)); ok {
|
||||
right = git.ParseRef(merge, "")
|
||||
} else {
|
||||
right = &git.Ref{Name: left.Name}
|
||||
}
|
||||
}
|
||||
tracerx.Printf("DEBUG LEFT to RIGHT: %+v => %+v", left, right)
|
||||
if err := g.ScanLeftToRemote(leftName, nil); err != nil {
|
||||
tracerx.Printf("DEBUG LEFT to RIGHT: %+v => %+v", update.Left(), update.Right())
|
||||
if err := g.ScanLeftToRemote(update.LeftCommitish(), nil); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user