From 0773065a772261da2cd409a4f3a154f578fef44a Mon Sep 17 00:00:00 2001 From: Emil Ingerslev Date: Tue, 9 Oct 2018 13:20:37 +0200 Subject: [PATCH] Add --skip-pull and git-plan command - Use `--skip-pull` to forcefully skip the pull step using a git plan - Use `git-plan` command to do git commands inside the plan directory --- cmd/git-plan.go | 24 ++++++++++++++++++++++++ cmd/root.go | 16 +++++++++------- pkg/config/shuttleconfig.go | 4 ++-- pkg/config/shuttleplan.go | 4 ++-- pkg/git/main.go | 30 +++++++++++++++++++++++++++++- 5 files changed, 66 insertions(+), 12 deletions(-) create mode 100644 cmd/git-plan.go diff --git a/cmd/git-plan.go b/cmd/git-plan.go new file mode 100644 index 0000000..6524728 --- /dev/null +++ b/cmd/git-plan.go @@ -0,0 +1,24 @@ +package cmd + +import ( + "strings" + + "github.com/lunarway/shuttle/pkg/git" + "github.com/spf13/cobra" +) + +var ( + gitPlanCmd = &cobra.Command{ + Use: "git-plan [...git_args]", + Short: "Run a git command for the plan", + Run: func(cmd *cobra.Command, args []string) { + skipGitPlanPulling = true + context := getProjectContext() + git.RunGitPlanCommand(strings.Join(args, " "), context.LocalPlanPath, context.UI) + }, + } +) + +func init() { + rootCmd.AddCommand(gitPlanCmd) +} diff --git a/cmd/root.go b/cmd/root.go index 7b8b0a4..23ed9c1 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -13,12 +13,13 @@ import ( ) var ( - projectPath string - uii ui.UI - verboseFlag bool - clean bool - version = "" - commit = "" + projectPath string + uii ui.UI + verboseFlag bool + clean bool + skipGitPlanPulling bool + version = "" + commit = "" ) // rootCmd represents the base command when called without any subcommands @@ -54,6 +55,7 @@ func Execute() { func init() { rootCmd.PersistentFlags().StringVarP(&projectPath, "project", "p", ".", "Project path") rootCmd.PersistentFlags().BoolVarP(&clean, "clean", "c", false, "Start from clean setup") + rootCmd.PersistentFlags().BoolVar(&skipGitPlanPulling, "skip-pull", false, "Skip git plan pulling step") rootCmd.PersistentFlags().BoolVarP(&verboseFlag, "verbose", "v", false, "Print verbose output") } @@ -66,6 +68,6 @@ func getProjectContext() config.ShuttleProjectContext { var fullProjectPath = path.Join(dir, projectPath) var c config.ShuttleProjectContext - c.Setup(fullProjectPath, uii, clean) + c.Setup(fullProjectPath, uii, clean, skipGitPlanPulling) return c } diff --git a/pkg/config/shuttleconfig.go b/pkg/config/shuttleconfig.go index 0bbf7d3..9f0ce72 100644 --- a/pkg/config/shuttleconfig.go +++ b/pkg/config/shuttleconfig.go @@ -34,7 +34,7 @@ type ShuttleProjectContext struct { } // Setup the ShuttleProjectContext for a specific path -func (c *ShuttleProjectContext) Setup(projectPath string, uii ui.UI, clean bool) *ShuttleProjectContext { +func (c *ShuttleProjectContext) Setup(projectPath string, uii ui.UI, clean bool, skipGitPlanPulling bool) *ShuttleProjectContext { c.Config.getConf(projectPath) c.UI = uii c.ProjectPath = projectPath @@ -47,7 +47,7 @@ func (c *ShuttleProjectContext) Setup(projectPath string, uii ui.UI, clean bool) os.MkdirAll(c.LocalShuttleDirectoryPath, os.ModePerm) c.TempDirectoryPath = path.Join(c.LocalShuttleDirectoryPath, "temp") - c.LocalPlanPath = FetchPlan(c.Config.Plan, projectPath, c.LocalShuttleDirectoryPath, uii) + c.LocalPlanPath = FetchPlan(c.Config.Plan, projectPath, c.LocalShuttleDirectoryPath, uii, skipGitPlanPulling) c.Plan.Load(c.LocalPlanPath) c.Scripts = make(map[string]ShuttlePlanScript) for scriptName, script := range c.Plan.Scripts { diff --git a/pkg/config/shuttleplan.go b/pkg/config/shuttleplan.go index b404dfc..023804b 100644 --- a/pkg/config/shuttleplan.go +++ b/pkg/config/shuttleplan.go @@ -66,14 +66,14 @@ func (p *ShuttlePlanConfiguration) Load(planPath string) *ShuttlePlanConfigurati } // FetchPlan so it exists locally and return path to that plan -func FetchPlan(plan string, projectPath string, localShuttleDirectoryPath string, uii ui.UI) string { +func FetchPlan(plan string, projectPath string, localShuttleDirectoryPath string, uii ui.UI, skipGitPlanPulling bool) string { switch { case plan == "": uii.VerboseLn("Using no plan") return "" case git.IsGitPlan(plan): uii.VerboseLn("Using git plan at '%s'", plan) - return git.GetGitPlan(plan, localShuttleDirectoryPath, uii) + return git.GetGitPlan(plan, localShuttleDirectoryPath, uii, skipGitPlanPulling) case isMatching("^http://|^https://", plan): panic("plan not valid: http is not supported yet") case isFilePath(plan, true): diff --git a/pkg/git/main.go b/pkg/git/main.go index b789db5..eb7652b 100644 --- a/pkg/git/main.go +++ b/pkg/git/main.go @@ -64,7 +64,7 @@ func IsGitPlan(plan string) bool { } // GetGitPlan will pull git repository and return its path -func GetGitPlan(plan string, localShuttleDirectoryPath string, uii ui.UI) string { +func GetGitPlan(plan string, localShuttleDirectoryPath string, uii ui.UI, skipGitPlanPulling bool) string { parsedGitPlan := parseGitPlan(plan) planPath := path.Join(localShuttleDirectoryPath, "plan") @@ -77,6 +77,11 @@ func GetGitPlan(plan string, localShuttleDirectoryPath string, uii ui.UI) string } if fileAvailable(planPath) { + if skipGitPlanPulling { + uii.VerboseLn("Skipping git plan pulling") + return planPath + } + status := getStatus(planPath) if status.mergeState { @@ -88,6 +93,7 @@ func GetGitPlan(plan string, localShuttleDirectoryPath string, uii ui.UI) string uii.InfoLn("Pulling latest plan changes") gitCmd("pull origin", planPath, uii) } + return planPath } else { os.MkdirAll(localShuttleDirectoryPath, os.ModePerm) @@ -107,6 +113,28 @@ func GetGitPlan(plan string, localShuttleDirectoryPath string, uii ui.UI) string return planPath } +func RunGitPlanCommand(command string, plan string, uii ui.UI) { + cmdOptions := go_cmd.Options{ + Streaming: true, + } + execCmd := go_cmd.NewCmdOptions(cmdOptions, "sh", "-c", "cd '"+plan+"'; git "+command) + execCmd.Env = os.Environ() + go func() { + for { + select { + case line := <-execCmd.Stdout: + uii.InfoLn(line) + case line := <-execCmd.Stderr: + uii.InfoLn(line) + } + } + }() + status := <-execCmd.Start() + if status.Exit > 0 { + os.Exit(status.Exit) + } +} + func isMatching(r string, content string) bool { match, err := regexp.MatchString(r, content) if err != nil {