package git import ( "errors" "fmt" "os" "strconv" "github.com/badjware/gitlabfs/utils" ) type gitCloneParam struct { url string defaultBranch string dst string } func (c *gitClient) cloneWorker() { fmt.Println("Started git cloner worker routine") for gcp := range c.cloneChan { if _, err := os.Stat(gcp.dst); os.IsNotExist(err) { if err := c.clone(gcp); err != nil { fmt.Println(err) } } } } func (c *gitClient) clone(gcp *gitCloneParam) error { // branchRef := plumbing.NewBranchReferenceName(gcp.defaultBranch) if c.Clone { // Clone the repo // TODO: figure out why this operation is so memory intensive... fmt.Printf("Cloning %v into %v\n", gcp.url, gcp.dst) // fs := osfs.New(gcp.dst) // storer := filesystem.NewStorage(fs, cache.NewObjectLRU(0)) // _, err := git.PlainClone(gcp.dst, false, &git.CloneOptions{ // URL: gcp.url, // RemoteName: c.RemoteName, // ReferenceName: branchRef, // NoCheckout: !c.Checkout, // Depth: c.PullDepth, // }) _, err := utils.ExecProcess( "git", "clone", "--origin", c.RemoteName, "--depth", strconv.Itoa(c.PullDepth), "--", gcp.url, // repository gcp.dst, // directory ) if err != nil { return fmt.Errorf("failed to clone git repo %v to %v: %v", gcp.url, gcp.dst, err) } } else { // "Fake" cloning the repo by never actually talking to the git server // This skip a fetch operation that we would do if we where to do a proper clone // We can save a lot of time and network i/o doing it this way, at the cost of // resulting in a very barebone local copy fmt.Printf("Initializing %v into %v\n", gcp.url, gcp.dst) // r, err := git.PlainInit(gcp.dst, false) _, err := utils.ExecProcess( "git", "init", "--initial-branch", gcp.defaultBranch, "--", gcp.dst, // directory ) if err != nil { return fmt.Errorf("failed to init git repo %v to %v: %v", gcp.url, gcp.dst, err) } // Configure the remote // _, err = r.CreateRemote(&config.RemoteConfig{ // Name: c.RemoteName, // URLs: []string{gcp.url}, // }) _, err = utils.ExecProcessInDir( gcp.dst, // workdir "git", "remote", "add", "-t", gcp.defaultBranch, "--", c.RemoteName, // name gcp.url, // url ) if err != nil { return fmt.Errorf("failed to setup remote %v in git repo %v: %v", gcp.url, gcp.dst, err) } // Configure a local branch to track the remote branch // err = r.CreateBranch(&config.Branch{ // Name: gcp.defaultBranch, // Remote: c.RemoteName, // Merge: plumbing.ReferenceName(fmt.Sprintf("refs/heads/%s", gcp.defaultBranch)), // }) // if err != nil { // return fmt.Errorf("failed to create branch %v of git repo %v: %v", gcp.defaultBranch, gcp.dst, err) // } // Checkout the default branch // w, err := r.Worktree() // if err != nil { // return fmt.Errorf("failed to retrieve worktree of git repo %v: %v", gcp.dst, err) // } // w.Checkout(&git.CheckoutOptions{ // Branch: branchRef, // }) } if c.PullAfterClone { // Dispatch to pull worker select { case c.pullChan <- &gitPullParam{ repoPath: gcp.dst, defaultBranch: gcp.defaultBranch, }: default: return errors.New("failed to pull local repo after clone") } } return nil }