2016-02-05 17:45:12 +00:00
|
|
|
package commands
|
|
|
|
|
|
|
|
import (
|
|
|
|
"os"
|
|
|
|
"path"
|
|
|
|
"path/filepath"
|
|
|
|
"strings"
|
|
|
|
|
2017-03-23 16:54:52 +00:00
|
|
|
"github.com/git-lfs/git-lfs/lfs"
|
2016-11-15 17:01:18 +00:00
|
|
|
"github.com/git-lfs/git-lfs/localstorage"
|
|
|
|
"github.com/git-lfs/git-lfs/subprocess"
|
2016-07-14 16:12:57 +00:00
|
|
|
|
2016-11-15 17:01:18 +00:00
|
|
|
"github.com/git-lfs/git-lfs/git"
|
|
|
|
"github.com/git-lfs/git-lfs/tools"
|
2016-05-23 18:02:27 +00:00
|
|
|
"github.com/spf13/cobra"
|
2016-02-05 17:45:12 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
2016-08-02 16:37:16 +00:00
|
|
|
cloneFlags git.CloneFlags
|
2017-03-23 16:54:52 +00:00
|
|
|
|
|
|
|
cloneSkipRepoInstall bool
|
2016-02-05 17:45:12 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func cloneCommand(cmd *cobra.Command, args []string) {
|
2016-08-17 22:13:36 +00:00
|
|
|
requireGitVersion()
|
2016-02-05 17:45:12 +00:00
|
|
|
|
|
|
|
// We pass all args to git clone
|
2016-04-19 10:52:21 +00:00
|
|
|
err := git.CloneWithoutFilters(cloneFlags, args)
|
2016-02-05 17:45:12 +00:00
|
|
|
if err != nil {
|
2016-02-11 17:52:20 +00:00
|
|
|
Exit("Error(s) during clone:\n%v", err)
|
2016-02-05 17:45:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// now execute pull (need to be inside dir)
|
2017-02-20 22:22:28 +00:00
|
|
|
cwd, err := tools.Getwd()
|
2016-02-05 17:45:12 +00:00
|
|
|
if err != nil {
|
2016-02-11 17:52:20 +00:00
|
|
|
Exit("Unable to derive current working dir: %v", err)
|
2016-02-05 17:45:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Either the last argument was a relative or local dir, or we have to
|
|
|
|
// derive it from the clone URL
|
|
|
|
clonedir, err := filepath.Abs(args[len(args)-1])
|
2016-05-13 16:38:06 +00:00
|
|
|
if err != nil || !tools.DirExists(clonedir) {
|
2016-02-05 17:45:12 +00:00
|
|
|
// Derive from clone URL instead
|
|
|
|
base := path.Base(args[len(args)-1])
|
|
|
|
if strings.HasSuffix(base, ".git") {
|
|
|
|
base = base[:len(base)-4]
|
|
|
|
}
|
|
|
|
clonedir, _ = filepath.Abs(base)
|
2016-05-13 16:38:06 +00:00
|
|
|
if !tools.DirExists(clonedir) {
|
2016-02-05 17:45:12 +00:00
|
|
|
Exit("Unable to find clone dir at %q", clonedir)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
err = os.Chdir(clonedir)
|
|
|
|
if err != nil {
|
2016-02-11 17:52:20 +00:00
|
|
|
Exit("Unable to change directory to clone dir %q: %v", clonedir, err)
|
2016-02-05 17:45:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Make sure we pop back to dir we started in at the end
|
|
|
|
defer os.Chdir(cwd)
|
|
|
|
|
|
|
|
// Also need to derive dirs now
|
2016-05-17 09:28:42 +00:00
|
|
|
localstorage.ResolveDirs()
|
2016-02-05 17:45:12 +00:00
|
|
|
requireInRepo()
|
|
|
|
|
|
|
|
// Now just call pull with default args
|
2016-04-19 14:13:36 +00:00
|
|
|
// Support --origin option to clone
|
2017-01-04 15:56:09 +00:00
|
|
|
var remote string
|
2016-04-19 14:13:36 +00:00
|
|
|
if len(cloneFlags.Origin) > 0 {
|
2017-01-04 15:56:09 +00:00
|
|
|
remote = cloneFlags.Origin
|
2016-04-19 14:13:36 +00:00
|
|
|
} else {
|
2017-01-04 15:56:09 +00:00
|
|
|
remote = "origin"
|
2016-04-19 14:13:36 +00:00
|
|
|
}
|
2016-04-19 11:42:00 +00:00
|
|
|
|
2016-08-02 16:37:16 +00:00
|
|
|
includeArg, excludeArg := getIncludeExcludeArgs(cmd)
|
2016-11-21 22:14:33 +00:00
|
|
|
filter := buildFilepathFilter(cfg, includeArg, excludeArg)
|
2016-04-19 14:10:58 +00:00
|
|
|
if cloneFlags.NoCheckout || cloneFlags.Bare {
|
|
|
|
// If --no-checkout or --bare then we shouldn't check out, just fetch instead
|
2017-01-04 15:56:09 +00:00
|
|
|
cfg.CurrentRemote = remote
|
2016-12-06 23:52:28 +00:00
|
|
|
fetchRef("HEAD", filter)
|
2016-04-19 11:42:00 +00:00
|
|
|
} else {
|
2017-01-04 15:56:09 +00:00
|
|
|
pull(remote, filter)
|
2016-07-14 16:12:57 +00:00
|
|
|
err := postCloneSubmodules(args)
|
|
|
|
if err != nil {
|
|
|
|
Exit("Error performing 'git lfs pull' for submodules: %v", err)
|
|
|
|
}
|
|
|
|
}
|
2017-03-23 16:54:52 +00:00
|
|
|
|
|
|
|
if !cloneSkipRepoInstall {
|
|
|
|
// If --skip-repo wasn't given, install repo-level hooks while
|
|
|
|
// we're still in the checkout directory.
|
|
|
|
|
|
|
|
if err := lfs.InstallHooks(false); err != nil {
|
|
|
|
ExitWithError(err)
|
|
|
|
}
|
|
|
|
}
|
2016-07-14 16:12:57 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func postCloneSubmodules(args []string) error {
|
|
|
|
// In git 2.9+ the filter option will have been passed through to submodules
|
2016-07-15 10:02:50 +00:00
|
|
|
// So we need to lfs pull inside each
|
2016-07-14 16:12:57 +00:00
|
|
|
if !git.Config.IsGitVersionAtLeast("2.9.0") {
|
|
|
|
// In earlier versions submodules would have used smudge filter
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
// Also we only do this if --recursive or --recurse-submodules was provided
|
|
|
|
if !cloneFlags.Recursive && !cloneFlags.RecurseSubmodules {
|
|
|
|
return nil
|
2016-04-19 11:42:00 +00:00
|
|
|
}
|
2016-02-05 17:45:12 +00:00
|
|
|
|
2016-07-14 16:12:57 +00:00
|
|
|
// Use `git submodule foreach --recursive` to cascade into nested submodules
|
|
|
|
// Also good to call a new instance of git-lfs rather than do things
|
|
|
|
// inside this instance, since that way we get a clean env in that subrepo
|
|
|
|
cmd := subprocess.ExecCommand("git", "submodule", "foreach", "--recursive",
|
|
|
|
"git lfs pull")
|
|
|
|
cmd.Stderr = os.Stderr
|
|
|
|
cmd.Stdin = os.Stdin
|
|
|
|
cmd.Stdout = os.Stdout
|
|
|
|
return cmd.Run()
|
2016-02-05 17:45:12 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func init() {
|
2016-09-01 16:09:38 +00:00
|
|
|
RegisterCommand("clone", cloneCommand, func(cmd *cobra.Command) {
|
2016-08-31 22:50:01 +00:00
|
|
|
cmd.PreRun = nil
|
2016-08-10 15:33:25 +00:00
|
|
|
|
|
|
|
// Mirror all git clone flags
|
|
|
|
cmd.Flags().StringVarP(&cloneFlags.TemplateDirectory, "template", "", "", "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.Local, "local", "l", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.Shared, "shared", "s", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.NoHardlinks, "no-hardlinks", "", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.Quiet, "quiet", "q", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.NoCheckout, "no-checkout", "n", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.Progress, "progress", "", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.Bare, "bare", "", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.Mirror, "mirror", "", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().StringVarP(&cloneFlags.Origin, "origin", "o", "", "See 'git clone --help'")
|
|
|
|
cmd.Flags().StringVarP(&cloneFlags.Branch, "branch", "b", "", "See 'git clone --help'")
|
|
|
|
cmd.Flags().StringVarP(&cloneFlags.Upload, "upload-pack", "u", "", "See 'git clone --help'")
|
|
|
|
cmd.Flags().StringVarP(&cloneFlags.Reference, "reference", "", "", "See 'git clone --help'")
|
2017-05-22 15:24:14 +00:00
|
|
|
cmd.Flags().StringVarP(&cloneFlags.ReferenceIfAble, "reference-if-able", "", "", "See 'git clone --help'")
|
2016-08-10 15:33:25 +00:00
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.Dissociate, "dissociate", "", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().StringVarP(&cloneFlags.SeparateGit, "separate-git-dir", "", "", "See 'git clone --help'")
|
|
|
|
cmd.Flags().StringVarP(&cloneFlags.Depth, "depth", "", "", "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.Recursive, "recursive", "", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.RecurseSubmodules, "recurse-submodules", "", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().StringVarP(&cloneFlags.Config, "config", "c", "", "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.SingleBranch, "single-branch", "", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.NoSingleBranch, "no-single-branch", "", false, "See 'git clone --help'")
|
2017-05-22 15:04:17 +00:00
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.Verbose, "verbose", "v", false, "See 'git clone --help'")
|
2016-08-10 15:33:25 +00:00
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.Ipv4, "ipv4", "", false, "See 'git clone --help'")
|
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.Ipv6, "ipv6", "", false, "See 'git clone --help'")
|
2017-05-22 15:24:54 +00:00
|
|
|
cmd.Flags().StringVarP(&cloneFlags.ShallowSince, "shallow-since", "", "", "See 'git clone --help'")
|
2017-05-22 15:25:20 +00:00
|
|
|
cmd.Flags().StringVarP(&cloneFlags.ShallowExclude, "shallow-exclude", "", "", "See 'git clone --help'")
|
2017-05-22 15:25:46 +00:00
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.ShallowSubmodules, "shallow-submodules", "", false, "See 'git clone --help'")
|
2017-05-22 15:26:07 +00:00
|
|
|
cmd.Flags().BoolVarP(&cloneFlags.NoShallowSubmodules, "no-shallow-submodules", "", false, "See 'git clone --help'")
|
2017-06-29 20:41:00 +00:00
|
|
|
cmd.Flags().Int64VarP(&cloneFlags.Jobs, "jobs", "j", -1, "See 'git clone --help'")
|
2016-08-10 15:33:25 +00:00
|
|
|
|
|
|
|
cmd.Flags().StringVarP(&includeArg, "include", "I", "", "Include a list of paths")
|
|
|
|
cmd.Flags().StringVarP(&excludeArg, "exclude", "X", "", "Exclude a list of paths")
|
2017-03-23 16:54:52 +00:00
|
|
|
|
|
|
|
cmd.Flags().BoolVar(&cloneSkipRepoInstall, "skip-repo", false, "Skip LFS repo setup")
|
2016-08-10 15:33:25 +00:00
|
|
|
})
|
2016-02-05 17:45:12 +00:00
|
|
|
}
|