Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions server/events/mock_workingdir_test.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

35 changes: 35 additions & 0 deletions server/events/mocks/mock_comment_building.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions server/events/mocks/mock_working_dir.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions server/events/project_command_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -528,6 +528,7 @@ func (p *DefaultProjectCommandRunner) doPlan(ctx command.ProjectContext) (*model
}
defer unlockFn()

p.WorkingDir.SetSafeToReClone()
// Clone is idempotent so okay to run even if the repo was already cloned.
repoDir, hasDiverged, cloneErr := p.WorkingDir.Clone(ctx.Log, ctx.HeadRepo, ctx.Pull, ctx.Workspace)
if cloneErr != nil {
Expand Down
42 changes: 27 additions & 15 deletions server/events/working_dir.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ type WorkingDir interface {
// Delete deletes the workspace for this repo and pull.
Delete(r models.Repo, p models.PullRequest) error
DeleteForWorkspace(r models.Repo, p models.PullRequest, workspace string) error
// Set a flag in the workingdir so Clone() can know that it is safe to re-clone the workingdir if
// the upstream branch has been modified. This is only safe after grabbing the project lock
// and before running any plans
SetSafeToReClone()
}

// FileWorkspace implements WorkingDir with the file system.
Expand All @@ -75,6 +79,8 @@ type FileWorkspace struct {
GithubAppEnabled bool
// use the global setting without overriding
GpgNoSigningEnabled bool
// flag indicating if a re-clone will be safe (project lock held, about to run plan)
SafeToReClone bool
}

// Clone git clones headRepo, checks out the branch and then returns the absolute
Expand All @@ -90,6 +96,7 @@ func (w *FileWorkspace) Clone(
workspace string) (string, bool, error) {
cloneDir := w.cloneDir(p.BaseRepo, p, workspace)
hasDiverged := false
defer func() { w.SafeToReClone = false }()

// If the directory already exists, check if it's at the right commit.
// If so, then we do nothing.
Expand Down Expand Up @@ -117,7 +124,7 @@ func (w *FileWorkspace) Clone(
// We're prefix matching here because BitBucket doesn't give us the full
// commit, only a 12 character prefix.
if strings.HasPrefix(currCommit, p.HeadCommit) {
if w.CheckoutMerge && w.recheckDiverged(log, p, headRepo, cloneDir) {
if w.SafeToReClone && w.CheckoutMerge && w.recheckDiverged(log, p, headRepo, cloneDir) {
log.Info("base branch has been updated, using merge strategy and will clone again")
hasDiverged = true
} else {
Expand Down Expand Up @@ -260,17 +267,17 @@ func (w *FileWorkspace) forceClone(log logging.SimpleLogging,
if !w.CheckoutMerge {
return runGit("clone", "--depth=1", "--branch", p.HeadBranch, "--single-branch", headCloneURL, cloneDir)
}

// if merge strategy...

// if no checkout depth, omit depth arg
if w.CheckoutDepth == 0 {
if err := runGit("clone", "--branch", p.BaseBranch, "--single-branch", baseCloneURL, cloneDir); err != nil {
return err
return err
}
} else {
if err := runGit("clone", "--depth", fmt.Sprint(w.CheckoutDepth), "--branch", p.BaseBranch, "--single-branch", baseCloneURL, cloneDir); err != nil {
return err
if err := runGit("clone", "--depth", fmt.Sprint(w.CheckoutDepth), "--branch", p.BaseBranch, "--single-branch", baseCloneURL, cloneDir); err != nil {
return err
}
}

Expand All @@ -285,16 +292,16 @@ func (w *FileWorkspace) forceClone(log logging.SimpleLogging,
fetchRemote = "origin"
}

// if no checkout depth, omit depth arg
if w.CheckoutDepth == 0 {
if err := runGit("fetch", fetchRemote, fetchRef); err != nil {
return err
}
} else {
if err := runGit("fetch", "--depth", fmt.Sprint(w.CheckoutDepth), fetchRemote, fetchRef); err != nil {
return err
}
}
// if no checkout depth, omit depth arg
if w.CheckoutDepth == 0 {
if err := runGit("fetch", fetchRemote, fetchRef); err != nil {
return err
}
} else {
if err := runGit("fetch", "--depth", fmt.Sprint(w.CheckoutDepth), fetchRemote, fetchRef); err != nil {
return err
}
}

if w.GpgNoSigningEnabled {
if err := runGit("config", "--local", "commit.gpgsign", "false"); err != nil {
Expand Down Expand Up @@ -361,3 +368,8 @@ func (w *FileWorkspace) sanitizeGitCredentials(s string, base models.Repo, head
baseReplaced := strings.Replace(s, base.CloneURL, base.SanitizedCloneURL, -1)
return strings.Replace(baseReplaced, head.CloneURL, head.SanitizedCloneURL, -1)
}

// Set the flag that indicates it is safe to re-clone if necessary
func (w *FileWorkspace) SetSafeToReClone() {
w.SafeToReClone = true
}
2 changes: 2 additions & 0 deletions server/events/working_dir_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -480,6 +480,7 @@ func TestClone_MasterHasDiverged(t *testing.T) {
Assert(t, hasDiverged == false, "Clone with CheckoutMerge=false should not merge")

wd.CheckoutMerge = true
wd.SetSafeToReClone()
// Run the clone twice with the merge strategy, the first run should
// return true for hasDiverged, subsequent runs should
// return false since the first call is supposed to merge.
Expand All @@ -491,6 +492,7 @@ func TestClone_MasterHasDiverged(t *testing.T) {
Ok(t, err)
Assert(t, hasDiverged == true, "First clone with CheckoutMerge=true with diverged base should have merged")

wd.SetSafeToReClone()
_, hasDiverged, err = wd.Clone(logging.NewNoopLogger(t), models.Repo{CloneURL: repoDir}, models.PullRequest{
BaseRepo: models.Repo{CloneURL: repoDir},
HeadBranch: "second-pr",
Expand Down