github.com/Cloud-Foundations/Dominator@v0.3.4/lib/gitutil/shallowClone.go (about)

     1  package gitutil
     2  
     3  import (
     4  	"bufio"
     5  	"fmt"
     6  	"io"
     7  	"os"
     8  	"os/exec"
     9  	"path"
    10  	"path/filepath"
    11  	"strings"
    12  	"time"
    13  
    14  	"github.com/Cloud-Foundations/Dominator/lib/format"
    15  	"github.com/Cloud-Foundations/Dominator/lib/fsutil"
    16  	"github.com/Cloud-Foundations/Dominator/lib/log"
    17  	"github.com/Cloud-Foundations/Dominator/lib/stringutil"
    18  )
    19  
    20  func gitGrab(topdir string, gitBranch string, logger log.DebugLogger) error {
    21  	if gitBranch == "" {
    22  		return runCommand(logger, topdir, "git", "pull", "--depth=1", "origin",
    23  			"")
    24  	}
    25  	err := runCommand(logger, topdir, "git", "fetch", "--depth=1", "origin")
    26  	if err != nil {
    27  		return err
    28  	}
    29  	branchList, err := fsutil.ReadDirnames(filepath.Join(topdir, ".git", "refs",
    30  		"remotes", "origin"), false)
    31  	if err != nil {
    32  		return err
    33  	}
    34  	branchMap := stringutil.ConvertListToMap(branchList, false)
    35  	var branchToMerge string
    36  	if _, ok := branchMap[gitBranch]; ok {
    37  		branchToMerge = gitBranch
    38  	} else {
    39  		branchToMerge = branchList[0]
    40  	}
    41  	err = runCommand(logger, topdir, "git", "merge",
    42  		path.Join("origin", branchToMerge))
    43  	if err != nil {
    44  		return err
    45  	}
    46  	if gitBranch != "" && branchToMerge != gitBranch {
    47  		err := runCommand(logger, topdir, "git", "fetch", "--unshallow",
    48  			"origin")
    49  		if err != nil {
    50  			return err
    51  		}
    52  		err = runCommand(logger, topdir, "git", "checkout", gitBranch)
    53  		if err != nil {
    54  			return err
    55  		}
    56  	}
    57  	return nil
    58  }
    59  
    60  func runCommand(logger log.DebugLogger, cwd string, args ...string) error {
    61  	cmd := exec.Command(args[0], args[1:]...)
    62  	cmd.Dir = cwd
    63  	if writer, ok := logger.(io.Writer); ok {
    64  		cmd.Stdout = writer
    65  		cmd.Stderr = writer
    66  		return cmd.Run()
    67  	}
    68  	if _output, err := cmd.CombinedOutput(); err != nil {
    69  		output := strings.TrimSpace(string(_output))
    70  		if len(output) < 1 {
    71  			return fmt.Errorf("error running: %s %s: %s", args[0], args[1], err)
    72  		}
    73  		return fmt.Errorf("error running: %s %s: %s: %s",
    74  			args[0], args[1], err, output)
    75  	}
    76  	return nil
    77  }
    78  
    79  func shallowClone(topdir string, params ShallowCloneParams,
    80  	logger log.DebugLogger) error {
    81  	if params.PublicURL == "" {
    82  		params.PublicURL = params.RepoURL
    83  	}
    84  	if params.GitBranch != "" {
    85  		logger.Debugf(0, "Cloning repository: %s branch: %s\n",
    86  			params.PublicURL, params.GitBranch)
    87  	} else {
    88  		logger.Debugf(0, "Cloning repository: %s\n", params.PublicURL)
    89  	}
    90  	startTime := time.Now()
    91  	err := runCommand(logger, "", "git", "init", "-b", "master", topdir)
    92  	if err != nil {
    93  		return err
    94  	}
    95  	err = runCommand(logger, topdir, "git", "remote", "add", "origin",
    96  		params.RepoURL)
    97  	if err != nil {
    98  		return err
    99  	}
   100  	if len(params.Patterns) > 0 {
   101  		err := runCommand(logger, topdir, "git", "config",
   102  			"core.sparsecheckout", "true")
   103  		if err != nil {
   104  			return err
   105  		}
   106  		file, err := os.Create(
   107  			filepath.Join(topdir, ".git", "info", "sparse-checkout"))
   108  		if err != nil {
   109  			return err
   110  		}
   111  		defer file.Close()
   112  		writer := bufio.NewWriter(file)
   113  		defer writer.Flush()
   114  		for _, pattern := range params.Patterns {
   115  			fmt.Fprintln(writer, pattern)
   116  		}
   117  		if err := writer.Flush(); err != nil {
   118  			return err
   119  		}
   120  	}
   121  	if err := gitGrab(topdir, params.GitBranch, logger); err != nil {
   122  		return err
   123  	}
   124  	loadTime := time.Since(startTime)
   125  	repoSize, err := fsutil.GetTreeSize(topdir)
   126  	if err != nil {
   127  		return err
   128  	}
   129  	speed := float64(repoSize) / loadTime.Seconds()
   130  	logger.Debugf(0,
   131  		"Downloaded partial repository in %s, size: %s (%s/s)\n",
   132  		format.Duration(loadTime), format.FormatBytes(repoSize),
   133  		format.FormatBytes(uint64(speed)))
   134  	return nil
   135  }