// prePushCommand is run through Git's pre-push hook. The pre-push hook passes // two arguments on the command line: // // 1. Name of the remote to which the push is being done // 2. URL to which the push is being done // // The hook receives commit information on stdin in the form: // <local ref> <local sha1> <remote ref> <remote sha1> // // In the typical case, prePushCommand will get a list of git objects being // pushed by using the following: // // git rev-list --objects <local sha1> ^<remote sha1> // // If any of those git objects are associated with Git LFS objects, those // objects will be pushed to the Git LFS API. // // In the case of pushing a new branch, the list of git objects will be all of // the git objects in this branch. // // In the case of deleting a branch, no attempts to push Git LFS objects will be // made. func prePushCommand(cmd *cobra.Command, args []string) { if len(args) == 0 { Print("This should be run through Git's pre-push hook. Run `git lfs update` to install it.") os.Exit(1) } // Remote is first arg if err := git.ValidateRemote(args[0]); err != nil { Exit("Invalid remote name %q", args[0]) } lfs.Config.CurrentRemote = args[0] // We can be passed multiple lines of refs scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if len(line) == 0 { continue } left, right := decodeRefs(line) if left == prePushDeleteBranch { continue } prePushRef(left, right) } }
func pullCommand(cmd *cobra.Command, args []string) { requireInRepo() if len(args) > 0 { // Remote is first arg if err := git.ValidateRemote(args[0]); err != nil { Panic(err, fmt.Sprintf("Invalid remote name '%v'", args[0])) } lfs.Config.CurrentRemote = args[0] } else { // Actively find the default remote, don't just assume origin defaultRemote, err := git.DefaultRemote() if err != nil { Panic(err, "No default remote") } lfs.Config.CurrentRemote = defaultRemote } ref, err := git.CurrentRef() if err != nil { Panic(err, "Could not pull") } includePaths, excludePaths := determineIncludeExcludePaths(pullIncludeArg, pullExcludeArg) c := fetchRefToChan(ref.Sha, includePaths, excludePaths) checkoutFromFetchChan(includePaths, excludePaths, c) }
// 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 looking 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 := git.ValidateRemote(args[0]); err != nil { Exit("Invalid remote name %q", args[0]) } cfg.CurrentRemote = args[0] ctx := newUploadContext(pushDryRun) if useStdin { requireStdin("Run this command from the Git pre-push hook, or leave the --stdin flag off.") // 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)) if left == prePushDeleteBranch { return } uploadsBetweenRefs(ctx, left, right) } else 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:]) } }
// GitRemoteUrl returns the git clone/push url for a given remote (blank if not found) // the forpush argument is to cater for separate remote.name.pushurl settings func (c *Configuration) GitRemoteUrl(remote string, forpush bool) string { if forpush { if u, ok := c.Git.Get("remote." + remote + ".pushurl"); ok { return u } } if u, ok := c.Git.Get("remote." + remote + ".url"); ok { return u } if err := git.ValidateRemote(remote); err == nil { return remote } return "" }
// prePushCommand is run through Git's pre-push hook. The pre-push hook passes // two arguments on the command line: // // 1. Name of the remote to which the push is being done // 2. URL to which the push is being done // // The hook receives commit information on stdin in the form: // <local ref> <local sha1> <remote ref> <remote sha1> // // In the typical case, prePushCommand will get a list of git objects being // pushed by using the following: // // git rev-list --objects <local sha1> ^<remote sha1> // // If any of those git objects are associated with Git LFS objects, those // objects will be pushed to the Git LFS API. // // In the case of pushing a new branch, the list of git objects will be all of // the git objects in this branch. // // In the case of deleting a branch, no attempts to push Git LFS objects will be // made. func prePushCommand(cmd *cobra.Command, args []string) { if len(args) == 0 { Print("This should be run through Git's pre-push hook. Run `git lfs update` to install it.") os.Exit(1) } requireGitVersion() // Remote is first arg if err := git.ValidateRemote(args[0]); err != nil { Exit("Invalid remote name %q", args[0]) } cfg.CurrentRemote = args[0] ctx := newUploadContext(prePushDryRun) scanOpt := lfs.NewScanRefsOptions() scanOpt.ScanMode = lfs.ScanLeftToRemoteMode scanOpt.RemoteName = cfg.CurrentRemote // We can be passed multiple lines of refs scanner := bufio.NewScanner(os.Stdin) for scanner.Scan() { line := strings.TrimSpace(scanner.Text()) if len(line) == 0 { continue } left, right := decodeRefs(line) if left == prePushDeleteBranch { continue } pointers, err := lfs.ScanRefs(left, right, scanOpt) if err != nil { Panic(err, "Error scanning for Git LFS files") } upload(ctx, pointers) } }
func pullCommand(cmd *cobra.Command, args []string) { requireInRepo() if len(args) > 0 { // Remote is first arg if err := git.ValidateRemote(args[0]); err != nil { Panic(err, fmt.Sprintf("Invalid remote name '%v'", args[0])) } config.Config.CurrentRemote = args[0] } else { // Actively find the default remote, don't just assume origin defaultRemote, err := git.DefaultRemote() if err != nil { Panic(err, "No default remote") } config.Config.CurrentRemote = defaultRemote } pull(determineIncludeExcludePaths(config.Config, pullIncludeArg, pullExcludeArg)) }
func fetchCommand(cmd *cobra.Command, args []string) { requireInRepo() var refs []*git.Ref if len(args) > 0 { // Remote is first arg if err := git.ValidateRemote(args[0]); err != nil { Exit("Invalid remote name %q", args[0]) } lfs.Config.CurrentRemote = args[0] } else { // Actively find the default remote, don't just assume origin defaultRemote, err := git.DefaultRemote() if err != nil { Exit("No default remote") } lfs.Config.CurrentRemote = defaultRemote } if len(args) > 1 { for _, r := range args[1:] { ref, err := git.ResolveRef(r) if err != nil { Panic(err, "Invalid ref argument") } refs = append(refs, ref) } } else { ref, err := git.CurrentRef() if err != nil { Panic(err, "Could not fetch") } refs = []*git.Ref{ref} } success := true if fetchAllArg { if fetchRecentArg || len(args) > 1 { Exit("Cannot combine --all with ref arguments or --recent") } if fetchIncludeArg != "" || fetchExcludeArg != "" { Exit("Cannot combine --all with --include or --exclude") } if len(lfs.Config.FetchIncludePaths()) > 0 || len(lfs.Config.FetchExcludePaths()) > 0 { Print("Ignoring global include / exclude paths to fulfil --all") } success = fetchAll() } else { // !all includePaths, excludePaths := determineIncludeExcludePaths(fetchIncludeArg, fetchExcludeArg) // Fetch refs sequentially per arg order; duplicates in later refs will be ignored for _, ref := range refs { Print("Fetching %v", ref.Name) s := fetchRef(ref.Sha, includePaths, excludePaths) success = success && s } if fetchRecentArg || lfs.Config.FetchPruneConfig().FetchRecentAlways { s := fetchRecent(refs, includePaths, excludePaths) success = success && s } } if fetchPruneArg { verify := lfs.Config.FetchPruneConfig().PruneVerifyRemoteAlways // no dry-run or verbose options in fetch, assume false prune(verify, false, false) } if !success { Exit("Warning: errors occurred") } }
// pushCommand pushes local objects to a Git LFS server. It takes two // arguments: // // `<remote> <remote ref>` // // Both a remote name ("origin") or a remote URL are accepted. // // pushCommand calculates the git objects to send by looking comparing the range // of commits between the local and remote git servers. func pushCommand(cmd *cobra.Command, args []string) { var uploadQueue *lfs.TransferQueue if len(args) == 0 { Print("Specify a remote and a remote branch name (`git lfs push origin master`)") os.Exit(1) } // Remote is first arg if err := git.ValidateRemote(args[0]); err != nil { Exit("Invalid remote name %q", args[0]) } lfs.Config.CurrentRemote = args[0] if useStdin { requireStdin("Run this command from the Git pre-push hook, or leave the --stdin flag off.") // 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)) if left == pushDeleteBranch { return } uploadQueue = uploadsBetweenRefs(left, right) } else if pushObjectIDs { if len(args) < 2 { Print("Usage: git lfs push --object-id <remote> <lfs-object-id> [lfs-object-id] ...") return } uploadQueue = uploadsWithObjectIDs(args[1:]) } else { if len(args) < 1 { Print("Usage: git lfs push --dry-run <remote> [ref]") return } uploadQueue = uploadsBetweenRefAndRemote(args[0], args[1:]) } if !pushDryRun { uploadQueue.Wait() for _, err := range uploadQueue.Errors() { if Debugging || lfs.IsFatalError(err) { LoggedError(err, err.Error()) } else { Error(err.Error()) } } if len(uploadQueue.Errors()) > 0 { os.Exit(2) } } }
func fetchCommand(cmd *cobra.Command, args []string) { requireInRepo() var refs []*git.Ref if len(args) > 0 { // Remote is first arg if err := git.ValidateRemote(args[0]); err != nil { Exit("Invalid remote name %q", args[0]) } cfg.CurrentRemote = args[0] } else { cfg.CurrentRemote = "" } if len(args) > 1 { resolvedrefs, err := git.ResolveRefs(args[1:]) if err != nil { Panic(err, "Invalid ref argument: %v", args[1:]) } refs = resolvedrefs } else if !fetchAllArg { ref, err := git.CurrentRef() if err != nil { Panic(err, "Could not fetch") } refs = []*git.Ref{ref} } success := true include, exclude := getIncludeExcludeArgs(cmd) if fetchAllArg { if fetchRecentArg || len(args) > 1 { Exit("Cannot combine --all with ref arguments or --recent") } if include != nil || exclude != nil { Exit("Cannot combine --all with --include or --exclude") } if len(cfg.FetchIncludePaths()) > 0 || len(cfg.FetchExcludePaths()) > 0 { Print("Ignoring global include / exclude paths to fulfil --all") } success = fetchAll() } else { // !all includePaths, excludePaths := determineIncludeExcludePaths(cfg, include, exclude) // Fetch refs sequentially per arg order; duplicates in later refs will be ignored for _, ref := range refs { Print("Fetching %v", ref.Name) s := fetchRef(ref.Sha, includePaths, excludePaths) success = success && s } if fetchRecentArg || cfg.FetchPruneConfig().FetchRecentAlways { s := fetchRecent(refs, includePaths, excludePaths) success = success && s } } if fetchPruneArg { fetchconf := cfg.FetchPruneConfig() verify := fetchconf.PruneVerifyRemoteAlways // no dry-run or verbose options in fetch, assume false prune(fetchconf, verify, false, false) } if !success { Exit("Warning: errors occurred") } }