1package steps
2
3import (
4	"fmt"
5
6	"github.com/git-town/git-town/src/git"
7)
8
9// GetSyncBranchSteps returns the steps to sync the branch with the given name.
10func GetSyncBranchSteps(branchName string, pushBranch bool, repo *git.ProdRepo) (result StepList, err error) {
11	isFeature := repo.Config.IsFeatureBranch(branchName)
12	hasRemoteOrigin, err := repo.Silent.HasRemote("origin")
13	if err != nil {
14		return result, err
15	}
16	if !hasRemoteOrigin && !isFeature {
17		return
18	}
19	result.Append(&CheckoutBranchStep{BranchName: branchName})
20	if isFeature {
21		steps, err := getSyncFeatureBranchSteps(branchName, repo)
22		if err != nil {
23			return result, err
24		}
25		result.AppendList(steps)
26	} else {
27		steps, err := getSyncNonFeatureBranchSteps(branchName, repo)
28		if err != nil {
29			return result, err
30		}
31		result.AppendList(steps)
32	}
33	if pushBranch && hasRemoteOrigin && !repo.Config.IsOffline() {
34		hasTrackingBranch, err := repo.Silent.HasTrackingBranch(branchName)
35		if err != nil {
36			return result, err
37		}
38		if hasTrackingBranch {
39			result.Append(&PushBranchStep{BranchName: branchName})
40		} else {
41			result.Append(&CreateTrackingBranchStep{BranchName: branchName})
42		}
43	}
44	return result, nil
45}
46
47// Helpers
48
49func getSyncFeatureBranchSteps(branchName string, repo *git.ProdRepo) (result StepList, err error) {
50	hasTrackingBranch, err := repo.Silent.HasTrackingBranch(branchName)
51	if err != nil {
52		return result, err
53	}
54	if hasTrackingBranch {
55		result.Append(&MergeBranchStep{BranchName: repo.Silent.TrackingBranchName(branchName)})
56	}
57	result.Append(&MergeBranchStep{BranchName: repo.Config.GetParentBranch(branchName)})
58	return
59}
60
61func getSyncNonFeatureBranchSteps(branchName string, repo *git.ProdRepo) (result StepList, err error) {
62	hasTrackingBranch, err := repo.Silent.HasTrackingBranch(branchName)
63	if err != nil {
64		return result, err
65	}
66	if hasTrackingBranch {
67		if repo.Config.GetPullBranchStrategy() == "rebase" {
68			result.Append(&RebaseBranchStep{BranchName: repo.Silent.TrackingBranchName(branchName)})
69		} else {
70			result.Append(&MergeBranchStep{BranchName: repo.Silent.TrackingBranchName(branchName)})
71		}
72	}
73
74	mainBranchName := repo.Config.GetMainBranch()
75	hasUpstream, err := repo.Silent.HasRemote("upstream")
76	if err != nil {
77		return result, err
78	}
79	if mainBranchName == branchName && hasUpstream && repo.Config.ShouldSyncUpstream() {
80		result.Append(&FetchUpstreamStep{BranchName: mainBranchName})
81		result.Append(&RebaseBranchStep{BranchName: fmt.Sprintf("upstream/%s", mainBranchName)})
82	}
83	return
84}
85