Make logging and exec members of the git struct
Otherwise they are floating global pointers, which sucks in tests.
This commit is contained in:
parent
0075df238c
commit
dc02fd98c0
|
|
@ -155,9 +155,6 @@ func init() {
|
|||
pflag.CommandLine.MarkDeprecated("sync-hook-command", "use --exechook-command instead")
|
||||
}
|
||||
|
||||
var cmdRunner *cmd.Runner
|
||||
var log *logging.Logger
|
||||
|
||||
// Total pull/error, summary on pull duration
|
||||
var (
|
||||
// TODO: have a marker for "which" servergroup
|
||||
|
|
@ -252,11 +249,11 @@ func envDuration(key string, def time.Duration) time.Duration {
|
|||
return def
|
||||
}
|
||||
|
||||
func setGlogFlags() {
|
||||
func setGlogFlags(v int, log *logging.Logger) {
|
||||
// Force logging to stderr.
|
||||
stderrFlag := stdflag.Lookup("logtostderr")
|
||||
if stderrFlag == nil {
|
||||
handleError(false, "ERROR: can't find glog flag 'logtostderr'")
|
||||
handleError(log, false, "ERROR: can't find glog flag 'logtostderr'")
|
||||
}
|
||||
stderrFlag.Value.Set("true")
|
||||
|
||||
|
|
@ -266,7 +263,7 @@ func setGlogFlags() {
|
|||
fmt.Fprintf(os.Stderr, "ERROR: can't find glog flag 'v'\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
vFlag.Value.Set(strconv.Itoa(*flVerbose))
|
||||
vFlag.Value.Set(strconv.Itoa(v))
|
||||
}
|
||||
|
||||
// repoSync represents the remote repo and the local sync of it.
|
||||
|
|
@ -283,6 +280,8 @@ type repoSync struct {
|
|||
authURL string // a URL to re-fetch credentials, or ""
|
||||
sparseFile string // path to a sparse-checkout file
|
||||
syncHookCmd string // command to run after each sync
|
||||
log *logging.Logger
|
||||
run *cmd.Runner
|
||||
}
|
||||
|
||||
func main() {
|
||||
|
|
@ -303,10 +302,12 @@ func main() {
|
|||
|
||||
pflag.Parse()
|
||||
stdflag.CommandLine.Parse(nil) // Otherwise glog complains
|
||||
setGlogFlags()
|
||||
|
||||
log = logging.New(*flRoot, *flErrorFile)
|
||||
cmdRunner = cmd.NewRunner(log)
|
||||
// Needs to happen very early for errors to be written to a file.
|
||||
log := logging.New(*flRoot, *flErrorFile)
|
||||
cmdRunner := cmd.NewRunner(log)
|
||||
|
||||
setGlogFlags(*flVerbose, log)
|
||||
|
||||
if *flVersion {
|
||||
fmt.Println(version.VERSION)
|
||||
|
|
@ -323,21 +324,21 @@ func main() {
|
|||
}
|
||||
|
||||
if *flRepo == "" {
|
||||
handleError(true, "ERROR: --repo must be specified")
|
||||
handleError(log, true, "ERROR: --repo must be specified")
|
||||
}
|
||||
|
||||
if *flDepth < 0 { // 0 means "no limit"
|
||||
handleError(true, "ERROR: --depth must be greater than or equal to 0")
|
||||
handleError(log, true, "ERROR: --depth must be greater than or equal to 0")
|
||||
}
|
||||
|
||||
switch submodulesMode(*flSubmodules) {
|
||||
case submodulesRecursive, submodulesShallow, submodulesOff:
|
||||
default:
|
||||
handleError(true, "ERROR: --submodules must be one of %q, %q, or %q", submodulesRecursive, submodulesShallow, submodulesOff)
|
||||
handleError(log, true, "ERROR: --submodules must be one of %q, %q, or %q", submodulesRecursive, submodulesShallow, submodulesOff)
|
||||
}
|
||||
|
||||
if *flRoot == "" {
|
||||
handleError(true, "ERROR: --root must be specified")
|
||||
handleError(log, true, "ERROR: --root must be specified")
|
||||
}
|
||||
|
||||
if *flDest != "" {
|
||||
|
|
@ -348,24 +349,24 @@ func main() {
|
|||
*flLink = parts[len(parts)-1]
|
||||
}
|
||||
if strings.Contains(*flLink, "/") {
|
||||
handleError(true, "ERROR: --link must not contain '/'")
|
||||
handleError(log, true, "ERROR: --link must not contain '/'")
|
||||
}
|
||||
if strings.HasPrefix(*flLink, ".") {
|
||||
handleError(true, "ERROR: --link must not start with '.'")
|
||||
handleError(log, true, "ERROR: --link must not start with '.'")
|
||||
}
|
||||
|
||||
if *flWait != 0 {
|
||||
*flPeriod = time.Duration(int(*flWait*1000)) * time.Millisecond
|
||||
}
|
||||
if *flPeriod < 10*time.Millisecond {
|
||||
handleError(true, "ERROR: --period must be at least 10ms")
|
||||
handleError(log, true, "ERROR: --period must be at least 10ms")
|
||||
}
|
||||
|
||||
if *flTimeout != 0 {
|
||||
*flSyncTimeout = time.Duration(*flTimeout) * time.Second
|
||||
}
|
||||
if *flSyncTimeout < 10*time.Millisecond {
|
||||
handleError(true, "ERROR: --sync-timeout must be at least 10ms")
|
||||
handleError(log, true, "ERROR: --sync-timeout must be at least 10ms")
|
||||
}
|
||||
|
||||
if *flSyncHookCommand != "" {
|
||||
|
|
@ -373,56 +374,56 @@ func main() {
|
|||
}
|
||||
if *flExechookCommand != "" {
|
||||
if *flExechookTimeout < time.Second {
|
||||
handleError(true, "ERROR: --exechook-timeout must be at least 1s")
|
||||
handleError(log, true, "ERROR: --exechook-timeout must be at least 1s")
|
||||
}
|
||||
if *flExechookBackoff < time.Second {
|
||||
handleError(true, "ERROR: --exechook-backoff must be at least 1s")
|
||||
handleError(log, true, "ERROR: --exechook-backoff must be at least 1s")
|
||||
}
|
||||
}
|
||||
|
||||
if *flWebhookURL != "" {
|
||||
if *flWebhookStatusSuccess < -1 {
|
||||
handleError(true, "ERROR: --webhook-success-status must be a valid HTTP code or -1")
|
||||
handleError(log, true, "ERROR: --webhook-success-status must be a valid HTTP code or -1")
|
||||
}
|
||||
if *flWebhookTimeout < time.Second {
|
||||
handleError(true, "ERROR: --webhook-timeout must be at least 1s")
|
||||
handleError(log, true, "ERROR: --webhook-timeout must be at least 1s")
|
||||
}
|
||||
if *flWebhookBackoff < time.Second {
|
||||
handleError(true, "ERROR: --webhook-backoff must be at least 1s")
|
||||
handleError(log, true, "ERROR: --webhook-backoff must be at least 1s")
|
||||
}
|
||||
}
|
||||
|
||||
if *flPassword != "" && *flPasswordFile != "" {
|
||||
handleError(false, "ERROR: only one of --password and --password-file may be specified")
|
||||
handleError(log, false, "ERROR: only one of --password and --password-file may be specified")
|
||||
}
|
||||
if *flUsername != "" {
|
||||
if *flPassword == "" && *flPasswordFile == "" {
|
||||
handleError(true, "ERROR: --password or --password-file must be set when --username is specified")
|
||||
handleError(log, true, "ERROR: --password or --password-file must be set when --username is specified")
|
||||
}
|
||||
}
|
||||
|
||||
if *flSSH {
|
||||
if *flUsername != "" {
|
||||
handleError(false, "ERROR: only one of --ssh and --username may be specified")
|
||||
handleError(log, false, "ERROR: only one of --ssh and --username may be specified")
|
||||
}
|
||||
if *flPassword != "" {
|
||||
handleError(false, "ERROR: only one of --ssh and --password may be specified")
|
||||
handleError(log, false, "ERROR: only one of --ssh and --password may be specified")
|
||||
}
|
||||
if *flPasswordFile != "" {
|
||||
handleError(false, "ERROR: only one of --ssh and --password-file may be specified")
|
||||
handleError(log, false, "ERROR: only one of --ssh and --password-file may be specified")
|
||||
}
|
||||
if *flAskPassURL != "" {
|
||||
handleError(false, "ERROR: only one of --ssh and --askpass-url may be specified")
|
||||
handleError(log, false, "ERROR: only one of --ssh and --askpass-url may be specified")
|
||||
}
|
||||
if *flCookieFile {
|
||||
handleError(false, "ERROR: only one of --ssh and --cookie-file may be specified")
|
||||
handleError(log, false, "ERROR: only one of --ssh and --cookie-file may be specified")
|
||||
}
|
||||
if *flSSHKeyFile == "" {
|
||||
handleError(true, "ERROR: --ssh-key-file must be specified when --ssh is specified")
|
||||
handleError(log, true, "ERROR: --ssh-key-file must be specified when --ssh is specified")
|
||||
}
|
||||
if *flSSHKnownHosts {
|
||||
if *flSSHKnownHostsFile == "" {
|
||||
handleError(true, "ERROR: --ssh-known-hosts-file must be specified when --ssh-known-hosts is specified")
|
||||
handleError(log, true, "ERROR: --ssh-known-hosts-file must be specified when --ssh-known-hosts is specified")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -477,6 +478,8 @@ func main() {
|
|||
authURL: *flAskPassURL,
|
||||
sparseFile: *flSparseCheckoutFile,
|
||||
syncHookCmd: *flSyncHookCommand,
|
||||
log: log,
|
||||
run: cmdRunner,
|
||||
}
|
||||
|
||||
// This context is used only for git credentials initialization. There are no long-running operations like
|
||||
|
|
@ -499,7 +502,7 @@ func main() {
|
|||
}
|
||||
|
||||
if *flSSH {
|
||||
if err := setupGitSSH(*flSSHKnownHosts, *flSSHKeyFile, *flSSHKnownHostsFile); err != nil {
|
||||
if err := git.SetupGitSSH(*flSSHKnownHosts, *flSSHKeyFile, *flSSHKnownHostsFile); err != nil {
|
||||
log.Error(err, "ERROR: can't set up git SSH")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
@ -683,17 +686,17 @@ func (git *repoSync) InitRepo(ctx context.Context) error {
|
|||
|
||||
// Make sure the directory we found is actually usable.
|
||||
if git.SanityCheck(ctx) {
|
||||
log.V(0).Info("root directory is valid", "path", git.root)
|
||||
git.log.V(0).Info("root directory is valid", "path", git.root)
|
||||
return nil
|
||||
}
|
||||
|
||||
// Maybe a previous run crashed? Git won't use this dir.
|
||||
log.V(0).Info("root directory exists but failed checks, cleaning up", "path", git.root)
|
||||
git.log.V(0).Info("root directory exists but failed checks, cleaning up", "path", git.root)
|
||||
|
||||
// We remove the contents rather than the dir itself, because a common
|
||||
// use-case is to have a volume mounted at git.root, which makes removing
|
||||
// it impossible.
|
||||
if err := removeDirContents(git.root); err != nil {
|
||||
if err := removeDirContents(git.root, git.log); err != nil {
|
||||
return fmt.Errorf("can't remove unusable git root: %w", err)
|
||||
}
|
||||
|
||||
|
|
@ -702,32 +705,32 @@ func (git *repoSync) InitRepo(ctx context.Context) error {
|
|||
|
||||
// sanityCheck tries to make sure that the dir is a valid git repository.
|
||||
func (git *repoSync) SanityCheck(ctx context.Context) bool {
|
||||
log.V(0).Info("sanity-checking git repo", "repo", git.root)
|
||||
git.log.V(0).Info("sanity-checking git repo", "repo", git.root)
|
||||
|
||||
// If it is empty, we are done.
|
||||
if empty, err := dirIsEmpty(git.root); err != nil {
|
||||
log.Error(err, "can't list repo directory", "repo", git.root)
|
||||
git.log.Error(err, "can't list repo directory", "repo", git.root)
|
||||
return false
|
||||
} else if empty {
|
||||
log.V(0).Info("git repo is empty", "repo", git.root)
|
||||
git.log.V(0).Info("git repo is empty", "repo", git.root)
|
||||
return true
|
||||
}
|
||||
|
||||
// Check that this is actually the root of the repo.
|
||||
if root, err := cmdRunner.Run(ctx, git.root, git.cmd, "rev-parse", "--show-toplevel"); err != nil {
|
||||
log.Error(err, "can't get repo toplevel", "repo", git.root)
|
||||
if root, err := git.run.Run(ctx, git.root, git.cmd, "rev-parse", "--show-toplevel"); err != nil {
|
||||
git.log.Error(err, "can't get repo toplevel", "repo", git.root)
|
||||
return false
|
||||
} else {
|
||||
root = strings.TrimSpace(root)
|
||||
if root != git.root {
|
||||
log.V(0).Info("git repo is under another repo", "repo", git.root, "parent", root)
|
||||
git.log.V(0).Info("git repo is under another repo", "repo", git.root, "parent", root)
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
// Consistency-check the repo.
|
||||
if _, err := cmdRunner.Run(ctx, git.root, git.cmd, "fsck", "--no-progress", "--connectivity-only"); err != nil {
|
||||
log.Error(err, "repo sanity check failed", "repo", git.root)
|
||||
if _, err := git.run.Run(ctx, git.root, git.cmd, "fsck", "--no-progress", "--connectivity-only"); err != nil {
|
||||
git.log.Error(err, "repo sanity check failed", "repo", git.root)
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
@ -742,7 +745,7 @@ func dirIsEmpty(dir string) (bool, error) {
|
|||
return len(dirents) == 0, nil
|
||||
}
|
||||
|
||||
func removeDirContents(dir string) error {
|
||||
func removeDirContents(dir string, log *logging.Logger) error {
|
||||
dirents, err := ioutil.ReadDir(dir)
|
||||
if err != nil {
|
||||
return err
|
||||
|
|
@ -750,7 +753,9 @@ func removeDirContents(dir string) error {
|
|||
|
||||
for _, fi := range dirents {
|
||||
p := filepath.Join(dir, fi.Name())
|
||||
log.V(2).Info("removing path recursively", "path", p, "isDir", fi.IsDir())
|
||||
if log != nil {
|
||||
log.V(2).Info("removing path recursively", "path", p, "isDir", fi.IsDir())
|
||||
}
|
||||
if err := os.RemoveAll(p); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -775,7 +780,7 @@ func sleepForever() {
|
|||
|
||||
// handleError prints the error to the standard error, prints the usage if the `printUsage` flag is true,
|
||||
// exports the error to the error file and exits the process with the exit code.
|
||||
func handleError(printUsage bool, format string, a ...interface{}) {
|
||||
func handleError(log *logging.Logger, printUsage bool, format string, a ...interface{}) {
|
||||
s := fmt.Sprintf(format, a...)
|
||||
fmt.Fprintln(os.Stderr, s)
|
||||
if printUsage {
|
||||
|
|
@ -827,13 +832,13 @@ func (git *repoSync) UpdateSymlink(ctx context.Context, newDir string) (string,
|
|||
}
|
||||
|
||||
const tmplink = "tmp-link"
|
||||
log.V(1).Info("creating tmp symlink", "root", git.root, "dst", newDirRelative, "src", tmplink)
|
||||
if _, err := cmdRunner.Run(ctx, git.root, "ln", "-snf", newDirRelative, tmplink); err != nil {
|
||||
git.log.V(1).Info("creating tmp symlink", "root", git.root, "dst", newDirRelative, "src", tmplink)
|
||||
if _, err := git.run.Run(ctx, git.root, "ln", "-snf", newDirRelative, tmplink); err != nil {
|
||||
return "", fmt.Errorf("error creating symlink: %v", err)
|
||||
}
|
||||
|
||||
log.V(1).Info("renaming symlink", "root", git.root, "oldName", tmplink, "newName", git.link)
|
||||
if _, err := cmdRunner.Run(ctx, git.root, "mv", "-T", tmplink, git.link); err != nil {
|
||||
git.log.V(1).Info("renaming symlink", "root", git.root, "oldName", tmplink, "newName", git.link)
|
||||
if _, err := git.run.Run(ctx, git.root, "mv", "-T", tmplink, git.link); err != nil {
|
||||
return "", fmt.Errorf("error replacing symlink: %v", err)
|
||||
}
|
||||
|
||||
|
|
@ -856,13 +861,13 @@ func setRepoReady() {
|
|||
repoReady = true
|
||||
}
|
||||
|
||||
// cleanupWorkTree() is used to remove a worktree and its folder
|
||||
func cleanupWorkTree(ctx context.Context, gitRoot, worktree string) error {
|
||||
// CleanupWorkTree() is used to remove a worktree and its folder
|
||||
func (git *repoSync) CleanupWorkTree(ctx context.Context, gitRoot, worktree string) error {
|
||||
// Clean up worktree(s)
|
||||
log.V(1).Info("removing worktree", "path", worktree)
|
||||
git.log.V(1).Info("removing worktree", "path", worktree)
|
||||
if err := os.RemoveAll(worktree); err != nil {
|
||||
return fmt.Errorf("error removing directory: %v", err)
|
||||
} else if _, err := cmdRunner.Run(ctx, gitRoot, *flGitCmd, "worktree", "prune"); err != nil {
|
||||
} else if _, err := git.run.Run(ctx, gitRoot, git.cmd, "worktree", "prune"); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
|
|
@ -870,7 +875,7 @@ func cleanupWorkTree(ctx context.Context, gitRoot, worktree string) error {
|
|||
|
||||
// AddWorktreeAndSwap creates a new worktree and calls UpdateSymlink to swap the symlink to point to the new worktree
|
||||
func (git *repoSync) AddWorktreeAndSwap(ctx context.Context, hash string) error {
|
||||
log.V(0).Info("syncing git", "rev", git.rev, "hash", hash)
|
||||
git.log.V(0).Info("syncing git", "rev", git.rev, "hash", hash)
|
||||
|
||||
args := []string{"fetch", "-f", "--tags"}
|
||||
if git.depth != 0 {
|
||||
|
|
@ -879,7 +884,7 @@ func (git *repoSync) AddWorktreeAndSwap(ctx context.Context, hash string) error
|
|||
args = append(args, "origin", git.branch)
|
||||
|
||||
// Update from the remote.
|
||||
if _, err := cmdRunner.Run(ctx, git.root, git.cmd, args...); err != nil {
|
||||
if _, err := git.run.Run(ctx, git.root, git.cmd, args...); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -887,12 +892,12 @@ func (git *repoSync) AddWorktreeAndSwap(ctx context.Context, hash string) error
|
|||
// end up NOT fetching the hash we wanted. If we can't resolve that hash
|
||||
// to a commit we can just end early and leave it for the next sync period.
|
||||
if _, err := git.ResolveRef(ctx, hash); err != nil {
|
||||
log.Error(err, "can't resolve commit, will retry", "rev", git.rev, "hash", hash)
|
||||
git.log.Error(err, "can't resolve commit, will retry", "rev", git.rev, "hash", hash)
|
||||
return nil
|
||||
}
|
||||
|
||||
// GC clone
|
||||
if _, err := cmdRunner.Run(ctx, git.root, git.cmd, "gc", "--prune=all"); err != nil {
|
||||
if _, err := git.run.Run(ctx, git.root, git.cmd, "gc", "--prune=all"); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
|
@ -903,12 +908,12 @@ func (git *repoSync) AddWorktreeAndSwap(ctx context.Context, hash string) error
|
|||
// error'd without cleaning up. The next time thru the sync loop fails to
|
||||
// create the worktree and bails out. This manifests as:
|
||||
// "fatal: '/repo/root/rev-nnnn' already exists"
|
||||
if err := cleanupWorkTree(ctx, git.root, worktreePath); err != nil {
|
||||
if err := git.CleanupWorkTree(ctx, git.root, worktreePath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := cmdRunner.Run(ctx, git.root, git.cmd, "worktree", "add", worktreePath, "origin/"+git.branch, "--no-checkout")
|
||||
log.V(0).Info("adding worktree", "path", worktreePath, "branch", fmt.Sprintf("origin/%s", git.branch))
|
||||
_, err := git.run.Run(ctx, git.root, git.cmd, "worktree", "add", worktreePath, "origin/"+git.branch, "--no-checkout")
|
||||
git.log.V(0).Info("adding worktree", "path", worktreePath, "branch", fmt.Sprintf("origin/%s", git.branch))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -930,7 +935,7 @@ func (git *repoSync) AddWorktreeAndSwap(ctx context.Context, hash string) error
|
|||
if git.sparseFile != "" {
|
||||
// This is required due to the undocumented behavior outlined here:
|
||||
// https://public-inbox.org/git/CAPig+cSP0UiEBXSCi7Ua099eOdpMk8R=JtAjPuUavRF4z0R0Vg@mail.gmail.com/t/
|
||||
log.V(0).Info("configuring worktree sparse checkout")
|
||||
git.log.V(0).Info("configuring worktree sparse checkout")
|
||||
checkoutFile := git.sparseFile
|
||||
|
||||
gitInfoPath := filepath.Join(git.root, fmt.Sprintf(".git/worktrees/%s/info", hash))
|
||||
|
|
@ -962,23 +967,23 @@ func (git *repoSync) AddWorktreeAndSwap(ctx context.Context, hash string) error
|
|||
}
|
||||
|
||||
args := []string{"sparse-checkout", "init"}
|
||||
_, err = cmdRunner.Run(ctx, worktreePath, git.cmd, args...)
|
||||
_, err = git.run.Run(ctx, worktreePath, git.cmd, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the worktree's working copy to the specific rev.
|
||||
_, err = cmdRunner.Run(ctx, worktreePath, git.cmd, "reset", "--hard", hash, "--")
|
||||
_, err = git.run.Run(ctx, worktreePath, git.cmd, "reset", "--hard", hash, "--")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.V(0).Info("reset worktree to hash", "path", worktreePath, "hash", hash)
|
||||
git.log.V(0).Info("reset worktree to hash", "path", worktreePath, "hash", hash)
|
||||
|
||||
// Update submodules
|
||||
// NOTE: this works for repo with or without submodules.
|
||||
if git.submodules != submodulesOff {
|
||||
log.V(0).Info("updating submodules")
|
||||
git.log.V(0).Info("updating submodules")
|
||||
submodulesArgs := []string{"submodule", "update", "--init"}
|
||||
if git.submodules == submodulesRecursive {
|
||||
submodulesArgs = append(submodulesArgs, "--recursive")
|
||||
|
|
@ -986,7 +991,7 @@ func (git *repoSync) AddWorktreeAndSwap(ctx context.Context, hash string) error
|
|||
if git.depth != 0 {
|
||||
submodulesArgs = append(submodulesArgs, "--depth", strconv.Itoa(git.depth))
|
||||
}
|
||||
_, err = cmdRunner.Run(ctx, worktreePath, git.cmd, submodulesArgs...)
|
||||
_, err = git.run.Run(ctx, worktreePath, git.cmd, submodulesArgs...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -995,19 +1000,19 @@ func (git *repoSync) AddWorktreeAndSwap(ctx context.Context, hash string) error
|
|||
// Change the file permissions, if requested.
|
||||
if git.chmod != 0 {
|
||||
mode := fmt.Sprintf("%#o", git.chmod)
|
||||
log.V(0).Info("changing file permissions", "mode", mode)
|
||||
_, err = cmdRunner.Run(ctx, "", "chmod", "-R", mode, worktreePath)
|
||||
git.log.V(0).Info("changing file permissions", "mode", mode)
|
||||
_, err = git.run.Run(ctx, "", "chmod", "-R", mode, worktreePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Reset the root's rev (so we can prune and so we can rely on it later).
|
||||
_, err = cmdRunner.Run(ctx, git.root, git.cmd, "reset", "--hard", hash, "--")
|
||||
_, err = git.run.Run(ctx, git.root, git.cmd, "reset", "--hard", hash, "--")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.V(0).Info("reset root to hash", "path", git.root, "hash", hash)
|
||||
git.log.V(0).Info("reset root to hash", "path", git.root, "hash", hash)
|
||||
|
||||
// Flip the symlink.
|
||||
oldWorktree, err := git.UpdateSymlink(ctx, worktreePath)
|
||||
|
|
@ -1021,7 +1026,7 @@ func (git *repoSync) AddWorktreeAndSwap(ctx context.Context, hash string) error
|
|||
// Clean up previous worktrees.
|
||||
var cleanupErr error
|
||||
if oldWorktree != "" {
|
||||
cleanupErr = cleanupWorkTree(ctx, git.root, oldWorktree)
|
||||
cleanupErr = git.CleanupWorkTree(ctx, git.root, oldWorktree)
|
||||
}
|
||||
|
||||
if cleanupErr != nil {
|
||||
|
|
@ -1037,18 +1042,18 @@ func (git *repoSync) CloneRepo(ctx context.Context) error {
|
|||
args = append(args, "--depth", strconv.Itoa(git.depth))
|
||||
}
|
||||
args = append(args, git.repo, git.root)
|
||||
log.V(0).Info("cloning repo", "origin", git.repo, "path", git.root)
|
||||
git.log.V(0).Info("cloning repo", "origin", git.repo, "path", git.root)
|
||||
|
||||
_, err := cmdRunner.Run(ctx, "", git.cmd, args...)
|
||||
_, err := git.run.Run(ctx, "", git.cmd, args...)
|
||||
if err != nil {
|
||||
if strings.Contains(err.Error(), "already exists and is not an empty directory") {
|
||||
// Maybe a previous run crashed? Git won't use this dir.
|
||||
log.V(0).Info("git root exists and is not empty (previous crash?), cleaning up", "path", git.root)
|
||||
git.log.V(0).Info("git root exists and is not empty (previous crash?), cleaning up", "path", git.root)
|
||||
err := os.RemoveAll(git.root)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = cmdRunner.Run(ctx, "", git.cmd, args...)
|
||||
_, err = git.run.Run(ctx, "", git.cmd, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -1059,7 +1064,7 @@ func (git *repoSync) CloneRepo(ctx context.Context) error {
|
|||
|
||||
// If sparse checkout is requested, configure git for it.
|
||||
if git.sparseFile != "" {
|
||||
log.V(0).Info("configuring sparse checkout")
|
||||
git.log.V(0).Info("configuring sparse checkout")
|
||||
checkoutFile := git.sparseFile
|
||||
|
||||
// TODO: capture this as a function (mostly duplicated above)
|
||||
|
|
@ -1093,7 +1098,7 @@ func (git *repoSync) CloneRepo(ctx context.Context) error {
|
|||
}
|
||||
|
||||
args := []string{"sparse-checkout", "init"}
|
||||
_, err = cmdRunner.Run(ctx, git.root, git.cmd, args...)
|
||||
_, err = git.run.Run(ctx, git.root, git.cmd, args...)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
@ -1104,7 +1109,7 @@ func (git *repoSync) CloneRepo(ctx context.Context) error {
|
|||
|
||||
// LocalHashForRev returns the locally known hash for a given rev.
|
||||
func (git *repoSync) LocalHashForRev(ctx context.Context, rev string) (string, error) {
|
||||
output, err := cmdRunner.Run(ctx, git.root, git.cmd, "rev-parse", rev)
|
||||
output, err := git.run.Run(ctx, git.root, git.cmd, "rev-parse", rev)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -1113,7 +1118,7 @@ func (git *repoSync) LocalHashForRev(ctx context.Context, rev string) (string, e
|
|||
|
||||
// RemoteHashForRef returns the upstream hash for a given ref.
|
||||
func (git *repoSync) RemoteHashForRef(ctx context.Context, ref string) (string, error) {
|
||||
output, err := cmdRunner.Run(ctx, git.root, git.cmd, "ls-remote", "-q", "origin", ref)
|
||||
output, err := git.run.Run(ctx, git.root, git.cmd, "ls-remote", "-q", "origin", ref)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -1131,7 +1136,7 @@ func (git *repoSync) RevIsHash(ctx context.Context) (bool, error) {
|
|||
|
||||
func (git *repoSync) ResolveRef(ctx context.Context, ref string) (string, error) {
|
||||
// If git doesn't identify rev as a commit, we're done.
|
||||
output, err := cmdRunner.Run(ctx, git.root, git.cmd, "cat-file", "-t", ref)
|
||||
output, err := git.run.Run(ctx, git.root, git.cmd, "cat-file", "-t", ref)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
|
@ -1188,10 +1193,10 @@ func (git *repoSync) SyncRepo(ctx context.Context) (bool, string, error) {
|
|||
return false, "", err
|
||||
}
|
||||
if local == remote {
|
||||
log.V(1).Info("no update required", "rev", git.rev, "local", local, "remote", remote)
|
||||
git.log.V(1).Info("no update required", "rev", git.rev, "local", local, "remote", remote)
|
||||
return false, "", nil
|
||||
}
|
||||
log.V(0).Info("update required", "rev", git.rev, "local", local, "remote", remote)
|
||||
git.log.V(0).Info("update required", "rev", git.rev, "local", local, "remote", remote)
|
||||
hash = remote
|
||||
}
|
||||
|
||||
|
|
@ -1226,15 +1231,15 @@ func (git *repoSync) GetRevs(ctx context.Context) (string, string, error) {
|
|||
// SetupAuth configures the local git repo to use a username and password when
|
||||
// accessing the repo.
|
||||
func (git *repoSync) SetupAuth(ctx context.Context, username, password string) error {
|
||||
log.V(1).Info("setting up git credential store")
|
||||
git.log.V(1).Info("setting up git credential store")
|
||||
|
||||
_, err := cmdRunner.Run(ctx, "", git.cmd, "config", "--global", "credential.helper", "store")
|
||||
_, err := git.run.Run(ctx, "", git.cmd, "config", "--global", "credential.helper", "store")
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't configure git credential helper: %w", err)
|
||||
}
|
||||
|
||||
creds := fmt.Sprintf("url=%v\nusername=%v\npassword=%v\n", git.repo, username, password)
|
||||
_, err = cmdRunner.RunWithStdin(ctx, "", creds, git.cmd, "credential", "approve")
|
||||
_, err = git.run.RunWithStdin(ctx, "", creds, git.cmd, "credential", "approve")
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't configure git credentials: %w", err)
|
||||
}
|
||||
|
|
@ -1242,8 +1247,8 @@ func (git *repoSync) SetupAuth(ctx context.Context, username, password string) e
|
|||
return nil
|
||||
}
|
||||
|
||||
func setupGitSSH(setupKnownHosts bool, pathToSSHSecret, pathToSSHKnownHosts string) error {
|
||||
log.V(1).Info("setting up git SSH credentials")
|
||||
func (git *repoSync) SetupGitSSH(setupKnownHosts bool, pathToSSHSecret, pathToSSHKnownHosts string) error {
|
||||
git.log.V(1).Info("setting up git SSH credentials")
|
||||
|
||||
_, err := os.Stat(pathToSSHSecret)
|
||||
if err != nil {
|
||||
|
|
@ -1269,7 +1274,7 @@ func setupGitSSH(setupKnownHosts bool, pathToSSHSecret, pathToSSHKnownHosts stri
|
|||
}
|
||||
|
||||
func (git *repoSync) SetupCookieFile(ctx context.Context) error {
|
||||
log.V(1).Info("configuring git cookie file")
|
||||
git.log.V(1).Info("configuring git cookie file")
|
||||
|
||||
var pathToCookieFile = "/etc/git-secret/cookie_file"
|
||||
|
||||
|
|
@ -1278,7 +1283,7 @@ func (git *repoSync) SetupCookieFile(ctx context.Context) error {
|
|||
return fmt.Errorf("can't access git cookiefile: %w", err)
|
||||
}
|
||||
|
||||
if _, err = cmdRunner.Run(ctx, "", git.cmd, "config", "--global", "http.cookiefile", pathToCookieFile); err != nil {
|
||||
if _, err = git.run.Run(ctx, "", git.cmd, "config", "--global", "http.cookiefile", pathToCookieFile); err != nil {
|
||||
return fmt.Errorf("can't configure git cookiefile: %w", err)
|
||||
}
|
||||
|
||||
|
|
@ -1293,7 +1298,7 @@ func (git *repoSync) SetupCookieFile(ctx context.Context) error {
|
|||
// username=xxx@example.com
|
||||
// password=xxxyyyzzz
|
||||
func (git *repoSync) CallAskPassURL(ctx context.Context) error {
|
||||
log.V(1).Info("calling GIT_ASKPASS URL to get credentials")
|
||||
git.log.V(1).Info("calling GIT_ASKPASS URL to get credentials")
|
||||
|
||||
var netClient = &http.Client{
|
||||
Timeout: time.Second * 1,
|
||||
|
|
@ -1347,14 +1352,14 @@ func (git *repoSync) CallAskPassURL(ctx context.Context) error {
|
|||
}
|
||||
|
||||
func (git *repoSync) setupExtraGitConfigs(ctx context.Context, configsFlag string) error {
|
||||
log.V(1).Info("setting additional git configs")
|
||||
git.log.V(1).Info("setting additional git configs")
|
||||
|
||||
configs, err := parseGitConfigs(configsFlag)
|
||||
if err != nil {
|
||||
return fmt.Errorf("can't parse --git-config flag: %v", err)
|
||||
}
|
||||
for _, kv := range configs {
|
||||
if _, err := cmdRunner.Run(ctx, "", git.cmd, "config", "--global", kv.key, kv.val); err != nil {
|
||||
if _, err := git.run.Run(ctx, "", git.cmd, "config", "--global", kv.key, kv.val); err != nil {
|
||||
return fmt.Errorf("error configuring additional git configs %q %q: %v", kv.key, kv.val, err)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -326,7 +326,7 @@ func TestRemoveDirContents(t *testing.T) {
|
|||
}
|
||||
|
||||
// Test removal.
|
||||
if err := removeDirContents(root); err != nil {
|
||||
if err := removeDirContents(root, nil); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
|
|
@ -352,12 +352,12 @@ func TestRemoveDirContents(t *testing.T) {
|
|||
}
|
||||
|
||||
// Test removal.
|
||||
if err := removeDirContents(root); err != nil {
|
||||
if err := removeDirContents(root, nil); err != nil {
|
||||
t.Errorf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
// Test error path.
|
||||
if err := removeDirContents(filepath.Join(root, "does-not-exist")); err == nil {
|
||||
if err := removeDirContents(filepath.Join(root, "does-not-exist"), nil); err == nil {
|
||||
t.Errorf("unexpected success for non-existent dir")
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue