1package cmd 2 3import ( 4 "fmt" 5 6 "github.com/git-town/git-town/src/cli" 7 "github.com/git-town/git-town/src/git" 8 "github.com/git-town/git-town/src/prompt" 9 "github.com/git-town/git-town/src/steps" 10 11 "github.com/spf13/cobra" 12) 13 14var promptForParent bool 15 16var hackCmd = &cobra.Command{ 17 Use: "hack <branch>", 18 Short: "Creates a new feature branch off the main development branch", 19 Long: `Creates a new feature branch off the main development branch 20 21Syncs the main branch, 22forks a new feature branch with the given name off the main branch, 23pushes the new feature branch to the remote repository 24(if and only if "new-branch-push-flag" is true), 25and brings over all uncommitted changes to the new feature branch. 26 27See "sync" for information regarding remote upstream.`, 28 Run: func(cmd *cobra.Command, args []string) { 29 config, err := getHackConfig(args, prodRepo) 30 if err != nil { 31 cli.Exit(err) 32 } 33 stepList, err := getAppendStepList(config, prodRepo) 34 if err != nil { 35 cli.Exit(err) 36 } 37 runState := steps.NewRunState("hack", stepList) 38 err = steps.Run(runState, prodRepo, nil) 39 if err != nil { 40 cli.Exit(err) 41 } 42 }, 43 Args: cobra.ExactArgs(1), 44 PreRunE: func(cmd *cobra.Command, args []string) error { 45 if err := ValidateIsRepository(prodRepo); err != nil { 46 return err 47 } 48 return validateIsConfigured(prodRepo) 49 }, 50} 51 52func getParentBranch(targetBranch string, repo *git.ProdRepo) (string, error) { 53 if promptForParent { 54 parentBranch, err := prompt.AskForBranchParent(targetBranch, repo.Config.GetMainBranch(), repo) 55 if err != nil { 56 return "", err 57 } 58 err = prompt.EnsureKnowsParentBranches([]string{parentBranch}, repo) 59 if err != nil { 60 return "", err 61 } 62 return parentBranch, nil 63 } 64 return repo.Config.GetMainBranch(), nil 65} 66 67func getHackConfig(args []string, repo *git.ProdRepo) (result appendConfig, err error) { 68 result.targetBranch = args[0] 69 result.parentBranch, err = getParentBranch(result.targetBranch, repo) 70 if err != nil { 71 return result, err 72 } 73 result.hasOrigin, err = repo.Silent.HasRemote("origin") 74 if err != nil { 75 return result, err 76 } 77 result.shouldNewBranchPush = repo.Config.ShouldNewBranchPush() 78 result.isOffline = repo.Config.IsOffline() 79 if result.hasOrigin && !repo.Config.IsOffline() { 80 err := repo.Logging.Fetch() 81 if err != nil { 82 return result, err 83 } 84 } 85 hasBranch, err := repo.Silent.HasLocalOrRemoteBranch(result.targetBranch) 86 if err != nil { 87 return result, err 88 } 89 if hasBranch { 90 return result, fmt.Errorf("a branch named %q already exists", result.targetBranch) 91 } 92 return 93} 94 95func init() { 96 hackCmd.Flags().BoolVarP(&promptForParent, "prompt", "p", false, "Prompt for the parent branch") 97 RootCmd.AddCommand(hackCmd) 98} 99