func NewCmdSaveStack()

in commands/stack/save/stack_save.go [24:149]


func NewCmdSaveStack(f *cmdutils.Factory, gr git.GitRunner, getText cmdutils.GetTextUsingEditor) *cobra.Command {
	stackSaveCmd := &cobra.Command{
		Use:   "save",
		Short: `Save your progress within a stacked diff. (EXPERIMENTAL.)`,
		Long: `Save your current progress with a diff on the stack.
` + text.ExperimentalString,
		Example: heredoc.Doc(`
			$ glab stack save added_file
			$ glab stack save . -m "added a function"
			$ glab stack save -m "added a function"`),
		RunE: func(cmd *cobra.Command, args []string) error {
			if cmd.Flags().Changed("message") && cmd.Flags().Changed("description") {
				return &cmdutils.FlagError{Err: errors.New("specify either of --message or --description.")}
			}

			// check if there are even any changes before we start
			err := checkForChanges()
			if err != nil {
				return fmt.Errorf("could not save: %v", err)
			}

			// a description is required, so ask if one is not provided
			if description == "" {
				description, err = promptForCommit(f, getText, "")
				if err != nil {
					return fmt.Errorf("error getting commit message: %v", err)
				}
			}

			s := spinner.New(spinner.CharSets[11], 100*time.Millisecond)

			// git add files
			_, err = addFiles(args[0:])
			if err != nil {
				return fmt.Errorf("error adding files: %v", err)
			}

			// get stack title
			title, err := git.GetCurrentStackTitle()
			if err != nil {
				return fmt.Errorf("error running Git command: %v", err)
			}

			author, err := git.GitUserName()
			if err != nil {
				return fmt.Errorf("error getting Git author: %v", err)
			}

			// generate a SHA based on: commit message, stack title, Git author name
			sha, err := generateStackSha(description, title, string(author), time.Now())
			if err != nil {
				return fmt.Errorf("error generating hash for stack branch name: %v", err)
			}

			// create branch name from SHA
			branch, err := createShaBranch(f, sha, title)
			if err != nil {
				return fmt.Errorf("error creating branch name: %v", err)
			}

			// create the branch prefix-stack_title-SHA
			err = git.CheckoutNewBranch(branch)
			if err != nil {
				return fmt.Errorf("error running branch checkout: %v", err)
			}

			// commit files to branch
			_, err = commitFiles(description)
			if err != nil {
				return fmt.Errorf("error committing files: %v", err)
			}

			stack, err := git.GatherStackRefs(title)
			if err != nil {
				return fmt.Errorf("error getting refs from file system: %v", err)
			}

			var stackRef git.StackRef
			if !stack.Empty() {
				lastRef := stack.Last()

				// update the ref before it (the current last ref)
				err = git.UpdateStackRefFile(title, git.StackRef{
					Prev:        lastRef.Prev,
					MR:          lastRef.MR,
					Description: lastRef.Description,
					SHA:         lastRef.SHA,
					Branch:      lastRef.Branch,
					Next:        sha,
				})
				if err != nil {
					return fmt.Errorf("error updating old ref: %v", err)
				}

				stackRef = git.StackRef{Prev: lastRef.SHA, SHA: sha, Branch: branch, Description: description}
			} else {
				stackRef = git.StackRef{SHA: sha, Branch: branch, Description: description}
			}

			err = git.AddStackRefFile(title, stackRef)
			if err != nil {
				return fmt.Errorf("error creating stack file: %v", err)
			}

			if f.IO.IsOutputTTY() {
				color := f.IO.Color()

				fmt.Fprintf(
					f.IO.StdOut,
					"%s %s: Saved with message: \"%s\".\n",
					color.ProgressIcon(),
					color.Blue(title),
					description,
				)
			}

			s.Stop()

			return nil
		},
	}
	stackSaveCmd.Flags().StringVarP(&description, "description", "d", "", "Description of the change.")
	stackSaveCmd.Flags().StringVarP(&description, "message", "m", "", "Alias for the description flag.")

	return stackSaveCmd
}