Repository: cli/cli
File: pkg/cmd/pr/merge/merge.go (Go)

Code before:
			_ = m.warnf("%s warning: not possible to fast-forward to: %q\n", m.cs.WarningIcon(), targetBranch)
		}

		switchedToBranch = targetBranch
	}

	if err := m.opts.GitClient.DeleteLocalBranch(ctx, m.pr.HeadRefName); err != nil {
		return fmt.Errorf("failed to delete local branch %s: %w", m.cs.Cyan(m.pr.HeadRefName), err)
	}

	switchedStatement := ""
	if switchedToBranch != "" {
		switchedStatement = fmt.Sprintf(" and switched to branch %s", m.cs.Cyan(switchedToBranch))
	}

	return m.infof("%s Deleted local branch %s%s\n", m.cs.SuccessIconWithColor(m.cs.Red), m.cs.Cyan(m.pr.HeadRefName), switchedStatement)
}

// Delete the remote branch if requested and if allowed.
func (m *mergeContext) deleteRemoteBranch() error {
	// the user was already asked if they want to delete the branch if they didn't provide the flag
	if !m.deleteBranch || m.crossRepoPR || m.autoMerge {
		return nil
	}

	if !m.merged {
		apiClient := api.NewClientFromHTTP(m.httpClient)
		err := api.BranchDeleteRemote(apiClient, m.baseRepo, m.pr.HeadRefName)
		if err != nil {
			// Normally, the API returns 422, with the message "Reference does not exist"
			// when the branch has already been deleted. It also returns returns 404
			// with the same message, but that rarely happens. In both cases, we should
			// not return an error because the goal is already achieved.

			var isAlreadyDeletedError bool
			if httpErr := (api.HTTPError{}); errors.As(err, &httpErr) {
				// TODO: since the API returns 422 for a couple of other reasons, for more accuracy
				// we might want to check the error message against "Reference does not exist".
				isAlreadyDeletedError = httpErr.StatusCode == http.StatusUnprocessableEntity || httpErr.StatusCode == http.StatusNotFound
			}

			if !isAlreadyDeletedError {
				return fmt.Errorf("failed to delete remote branch %s: %w", m.cs.Cyan(m.pr.HeadRefName), err)
			}
		}
	}

	return m.infof("%s Deleted remote branch %s\n", m.cs.SuccessIconWithColor(m.cs.Red), m.cs.Cyan(m.pr.HeadRefName))
}

// Add the Pull Request to a merge queue

Review comment (suggestion):
I tried to improve the code around this `if`-statement, because it's confusing, but at the end gave up due to tests breaking. The coupling among the methods on `mergeContext`, and their behaviour against the state fields make it very hard to understand/improve the code.

Code after:
			_ = m.warnf("%s warning: not possible to fast-forward to: %q\n", m.cs.WarningIcon(), targetBranch)
		}

		switchedToBranch = targetBranch
	}

	if err := m.opts.GitClient.DeleteLocalBranch(ctx, m.pr.HeadRefName); err != nil {
		return fmt.Errorf("failed to delete local branch %s: %w", m.cs.Cyan(m.pr.HeadRefName), err)
	}

	switchedStatement := ""
	if switchedToBranch != "" {
		switchedStatement = fmt.Sprintf(" and switched to branch %s", m.cs.Cyan(switchedToBranch))
	}

	return m.infof("%s Deleted local branch %s%s\n", m.cs.SuccessIconWithColor(m.cs.Red), m.cs.Cyan(m.pr.HeadRefName), switchedStatement)
}

// Delete the remote branch if requested and if allowed.
func (m *mergeContext) deleteRemoteBranch() error {
	// the user was already asked if they want to delete the branch if they didn't provide the flag
	if !m.deleteBranch || m.crossRepoPR || m.autoMerge {
		return nil
	}

	if !m.merged {
		apiClient := api.NewClientFromHTTP(m.httpClient)
		err := api.BranchDeleteRemote(apiClient, m.baseRepo, m.pr.HeadRefName)
		if err != nil {
			// Normally, the API returns 422, with the message "Reference does not exist"
			// when the branch has already been deleted. It also returns 404 with the same
			// message, but that rarely happens. In both cases, we should not return an
			// error because the goal is already achieved.

			var isAlreadyDeletedError bool
			if httpErr := (api.HTTPError{}); errors.As(err, &httpErr) {
				// TODO: since the API returns 422 for a couple of other reasons, for more accuracy
				// we might want to check the error message against "Reference does not exist".
				isAlreadyDeletedError = httpErr.StatusCode == http.StatusUnprocessableEntity || httpErr.StatusCode == http.StatusNotFound
			}

			if !isAlreadyDeletedError {
				return fmt.Errorf("failed to delete remote branch %s: %w", m.cs.Cyan(m.pr.HeadRefName), err)
			}
		}
	}

	return m.infof("%s Deleted remote branch %s\n", m.cs.SuccessIconWithColor(m.cs.Red), m.cs.Cyan(m.pr.HeadRefName))
}

// Add the Pull Request to a merge queue