func stackSync()

in commands/stack/sync/stack_sync.go [92:195]


func stackSync(f *cmdutils.Factory, iostream *iostreams.IOStreams, opts *Options, gr git.GitRunner) error {
	client, err := auth.GetAuthenticatedClient(f)
	if err != nil {
		return fmt.Errorf("error authorizing with GitLab: %v", err)
	}
	opts.LabClient = client

	iostream.StopSpinner("")

	repo, err := f.BaseRepo()
	if err != nil {
		return fmt.Errorf("error determining base repo: %v", err)
	}

	// This prompts the user for the head repo if they're in a fork,
	// allowing them to choose between their fork and the original repository
	source, err := create.ResolvedHeadRepo(f)()
	if err != nil {
		return fmt.Errorf("error determining head repo: %v", err)
	}

	iostream.StartSpinner("Syncing")

	stack, err := getStack()
	if err != nil {
		return fmt.Errorf("error getting current stack: %v", err)
	}

	user, _, err := client.Users.CurrentUser()
	if err != nil {
		return fmt.Errorf("error getting current user: %v", err)
	}

	opts.stack = stack
	opts.target = repo
	opts.source = source
	opts.user = *user

	err = fetchOrigin(gr)
	if err != nil {
		return err
	}

	pushAfterSync := false

	for ref := range stack.Iter() {
		status, err := branchStatus(&ref, gr)
		if err != nil {
			return fmt.Errorf("error getting branch status: %v", err)
		}

		switch {
		case strings.Contains(status, BranchIsBehind):
			err = branchBehind(&ref, gr)
			if err != nil {
				return err
			}
		case strings.Contains(status, BranchHasDiverged):
			needsPush, err := branchDiverged(&ref, &stack, gr)
			if err != nil {
				return err
			}

			if needsPush {
				pushAfterSync = true
			}
		case strings.Contains(status, NothingToCommit):
			// this is fine. we can just move on.
		default:
			return fmt.Errorf("your Git branch is ahead, but it shouldn't be. You might need to squash your commits.")
		}

		if ref.MR == "" {
			err := populateMR(&ref, opts, client, gr)
			if err != nil {
				return err
			}
		} else {
			// we found an MR. let's get the status:
			mr, _, err := mrutils.MRFromArgsWithOpts(f, []string{ref.Branch}, nil, "any")
			if err != nil {
				return fmt.Errorf("error getting merge request from branch: %v. Does it still exist?", err)
			}

			// remove the MR from the stack if it's merged
			// do not remove the MR from the stack if it is closed,
			// but alert the user
			err = removeOldMrs(&ref, mr, &stack, gr)
			if err != nil {
				return fmt.Errorf("error removing merged merge request: %v", err)
			}
		}
	}

	if pushAfterSync {
		err := forcePushAllWithLease(&stack, gr)
		if err != nil {
			return fmt.Errorf("error pushing branches to remote: %v", err)
		}
	}

	fmt.Print(progressString("Sync finished!"))
	return nil
}