1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
package commands
import (
"fmt"
"os"
"path"
"path/filepath"
"strings"
"github.com/git-lfs/git-lfs/v3/subprocess"
"github.com/git-lfs/git-lfs/v3/tr"
"github.com/git-lfs/git-lfs/v3/git"
"github.com/git-lfs/git-lfs/v3/tools"
"github.com/spf13/cobra"
)
var (
cloneFlags git.CloneFlags
cloneSkipRepoInstall bool
)
func cloneCommand(cmd *cobra.Command, args []string) {
requireGitVersion()
if git.IsGitVersionAtLeast("2.15.0") {
// TRANSLATORS: Individual lines should not exceed 80
// characters, and any additional lines in the first message
// should be indented to align with the first line's text
// following the warning prefix and punctuation.
msg := fmt.Sprintf("%s\n\n%s",
tr.Tr.Get("WARNING: `git lfs clone` is deprecated and will not be updated\n with new flags from `git clone`"),
tr.Tr.Get("`git clone` has been updated in upstream Git to have comparable\nspeeds to `git lfs clone`."))
fmt.Fprintln(os.Stderr, msg)
}
// We pass all args to git clone
err := git.CloneWithoutFilters(cloneFlags, args)
if err != nil {
Exit("%s\n%v", tr.Tr.Get("Error(s) during clone:"), err)
}
// now execute pull (need to be inside dir)
cwd, err := tools.Getwd()
if err != nil {
Exit(tr.Tr.Get("Unable to derive current working dir: %v", err))
}
// 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])
if err != nil || !tools.DirExists(clonedir) {
// 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)
if !tools.DirExists(clonedir) {
Exit(tr.Tr.Get("Unable to find clone dir at %q", clonedir))
}
}
err = os.Chdir(clonedir)
if err != nil {
Exit(tr.Tr.Get("Unable to change directory to clone dir %q: %v", clonedir, err))
}
// Make sure we pop back to dir we started in at the end
defer os.Chdir(cwd)
setupRepository()
// Support --origin option to clone
if len(cloneFlags.Origin) > 0 {
cfg.SetRemote(cloneFlags.Origin)
}
if ref, err := git.CurrentRef(); err == nil {
includeArg, excludeArg := getIncludeExcludeArgs(cmd)
filter := buildFilepathFilter(cfg, includeArg, excludeArg, true)
if cloneFlags.NoCheckout || cloneFlags.Bare {
// If --no-checkout or --bare then we shouldn't check out, just fetch instead
fetchRef(ref.Name, filter)
} else {
pull(filter)
err := postCloneSubmodules(args)
if err != nil {
Exit(tr.Tr.Get("Error performing `git lfs pull` for submodules: %v", err))
}
}
}
if !cloneSkipRepoInstall {
// If --skip-repo wasn't given, install repo-level hooks while
// we're still in the checkout directory.
if err := installHooks(false); err != nil {
ExitWithError(err)
}
}
}
func postCloneSubmodules(args []string) error {
// In git 2.9+ the filter option will have been passed through to submodules
// So we need to lfs pull inside each
if !git.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
}
// 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, err := subprocess.ExecCommand("git", "submodule", "foreach", "--recursive",
"git lfs pull")
if err != nil {
return err
}
cmd.Stderr = os.Stderr
cmd.Stdin = os.Stdin
cmd.Stdout = os.Stdout
return cmd.Run()
}
func init() {
RegisterCommand("clone", cloneCommand, func(cmd *cobra.Command) {
cmd.PreRun = nil
// 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'")
cmd.Flags().StringVarP(&cloneFlags.ReferenceIfAble, "reference-if-able", "", "", "See 'git clone --help'")
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'")
cmd.Flags().BoolVarP(&cloneFlags.Verbose, "verbose", "v", false, "See 'git clone --help'")
cmd.Flags().BoolVarP(&cloneFlags.Ipv4, "ipv4", "", false, "See 'git clone --help'")
cmd.Flags().BoolVarP(&cloneFlags.Ipv6, "ipv6", "", false, "See 'git clone --help'")
cmd.Flags().StringVarP(&cloneFlags.ShallowSince, "shallow-since", "", "", "See 'git clone --help'")
cmd.Flags().StringVarP(&cloneFlags.ShallowExclude, "shallow-exclude", "", "", "See 'git clone --help'")
cmd.Flags().BoolVarP(&cloneFlags.ShallowSubmodules, "shallow-submodules", "", false, "See 'git clone --help'")
cmd.Flags().BoolVarP(&cloneFlags.NoShallowSubmodules, "no-shallow-submodules", "", false, "See 'git clone --help'")
cmd.Flags().Int64VarP(&cloneFlags.Jobs, "jobs", "j", -1, "See 'git clone --help'")
cmd.Flags().StringVarP(&includeArg, "include", "I", "", "Include a list of paths")
cmd.Flags().StringVarP(&excludeArg, "exclude", "X", "", "Exclude a list of paths")
cmd.Flags().BoolVar(&cloneSkipRepoInstall, "skip-repo", false, "Skip LFS repo setup")
})
}
|