mirror of
				https://github.com/go-gitea/gitea.git
				synced 2025-10-27 00:23:41 +09:00 
			
		
		
		
	Add checkbox to delete pull branch after successful merge (#16049)
* Add checkbox to delete pull branch after successful merge * Omit DeleteBranchAfterMerge field in json * Log a warning instead of error when PR head branch deleted * Add DefaultDeleteBranchAfterMerge to PullRequestConfig * Add support for delete_branch_after_merge via API * Fix for API: the branch should be deleted from the HEAD repo If head and base repo are the same, reuse the already opened ctx.Repo.GitRepo * Don't delegate to CleanupBranch, only reuse branch deletion code CleanupBranch contains too much logic that has already been performed by the Merge * Reuse gitrepo in MergePullRequest Co-authored-by: Andrew Thornton <art27@cantab.net>
This commit is contained in:
		| @@ -91,14 +91,15 @@ func (cfg *IssuesConfig) ToDB() ([]byte, error) { | |||||||
|  |  | ||||||
| // PullRequestsConfig describes pull requests config | // PullRequestsConfig describes pull requests config | ||||||
| type PullRequestsConfig struct { | type PullRequestsConfig struct { | ||||||
| 	IgnoreWhitespaceConflicts bool | 	IgnoreWhitespaceConflicts     bool | ||||||
| 	AllowMerge                bool | 	AllowMerge                    bool | ||||||
| 	AllowRebase               bool | 	AllowRebase                   bool | ||||||
| 	AllowRebaseMerge          bool | 	AllowRebaseMerge              bool | ||||||
| 	AllowSquash               bool | 	AllowSquash                   bool | ||||||
| 	AllowManualMerge          bool | 	AllowManualMerge              bool | ||||||
| 	AutodetectManualMerge     bool | 	AutodetectManualMerge         bool | ||||||
| 	DefaultMergeStyle         MergeStyle | 	DefaultDeleteBranchAfterMerge bool | ||||||
|  | 	DefaultMergeStyle             MergeStyle | ||||||
| } | } | ||||||
|  |  | ||||||
| // FromDB fills up a PullRequestsConfig from serialized format. | // FromDB fills up a PullRequestsConfig from serialized format. | ||||||
|   | |||||||
| @@ -172,6 +172,8 @@ type EditRepoOption struct { | |||||||
| 	AllowManualMerge *bool `json:"allow_manual_merge,omitempty"` | 	AllowManualMerge *bool `json:"allow_manual_merge,omitempty"` | ||||||
| 	// either `true` to enable AutodetectManualMerge, or `false` to prevent it. `has_pull_requests` must be `true`, Note: In some special cases, misjudgments can occur. | 	// either `true` to enable AutodetectManualMerge, or `false` to prevent it. `has_pull_requests` must be `true`, Note: In some special cases, misjudgments can occur. | ||||||
| 	AutodetectManualMerge *bool `json:"autodetect_manual_merge,omitempty"` | 	AutodetectManualMerge *bool `json:"autodetect_manual_merge,omitempty"` | ||||||
|  | 	// set to `true` to delete pr branch after merge by default | ||||||
|  | 	DefaultDeleteBranchAfterMerge *bool `json:"default_delete_branch_after_merge,omitempty"` | ||||||
| 	// set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", or "squash". `has_pull_requests` must be `true`. | 	// set to a merge style to be used by this repository: "merge", "rebase", "rebase-merge", or "squash". `has_pull_requests` must be `true`. | ||||||
| 	DefaultMergeStyle *string `json:"default_merge_style,omitempty"` | 	DefaultMergeStyle *string `json:"default_merge_style,omitempty"` | ||||||
| 	// set to `true` to archive this repository. | 	// set to `true` to archive this repository. | ||||||
|   | |||||||
| @@ -1664,6 +1664,7 @@ settings.pulls.allow_rebase_merge_commit = Enable Rebasing with explicit merge c | |||||||
| settings.pulls.allow_squash_commits = Enable Squashing to Merge Commits | settings.pulls.allow_squash_commits = Enable Squashing to Merge Commits | ||||||
| settings.pulls.allow_manual_merge = Enable Mark PR as manually merged | settings.pulls.allow_manual_merge = Enable Mark PR as manually merged | ||||||
| settings.pulls.enable_autodetect_manual_merge = Enable autodetect manual merge (Note: In some special cases, misjudgments can occur) | settings.pulls.enable_autodetect_manual_merge = Enable autodetect manual merge (Note: In some special cases, misjudgments can occur) | ||||||
|  | settings.pulls.default_delete_branch_after_merge = Delete pull request branch after merge by default | ||||||
| settings.projects_desc = Enable Repository Projects | settings.projects_desc = Enable Repository Projects | ||||||
| settings.admin_settings = Administrator Settings | settings.admin_settings = Administrator Settings | ||||||
| settings.admin_enable_health_check = Enable Repository Health Checks (git fsck) | settings.admin_enable_health_check = Enable Repository Health Checks (git fsck) | ||||||
|   | |||||||
| @@ -5,6 +5,7 @@ | |||||||
| package repo | package repo | ||||||
|  |  | ||||||
| import ( | import ( | ||||||
|  | 	"errors" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"math" | 	"math" | ||||||
| 	"net/http" | 	"net/http" | ||||||
| @@ -25,6 +26,7 @@ import ( | |||||||
| 	"code.gitea.io/gitea/services/forms" | 	"code.gitea.io/gitea/services/forms" | ||||||
| 	issue_service "code.gitea.io/gitea/services/issue" | 	issue_service "code.gitea.io/gitea/services/issue" | ||||||
| 	pull_service "code.gitea.io/gitea/services/pull" | 	pull_service "code.gitea.io/gitea/services/pull" | ||||||
|  | 	repo_service "code.gitea.io/gitea/services/repository" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| // ListPullRequests returns a list of all PRs | // ListPullRequests returns a list of all PRs | ||||||
| @@ -878,6 +880,38 @@ func MergePullRequest(ctx *context.APIContext) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	log.Trace("Pull request merged: %d", pr.ID) | 	log.Trace("Pull request merged: %d", pr.ID) | ||||||
|  |  | ||||||
|  | 	if form.DeleteBranchAfterMerge { | ||||||
|  | 		var headRepo *git.Repository | ||||||
|  | 		if ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == pr.HeadRepoID && ctx.Repo.GitRepo != nil { | ||||||
|  | 			headRepo = ctx.Repo.GitRepo | ||||||
|  | 		} else { | ||||||
|  | 			headRepo, err = git.OpenRepository(pr.HeadRepo.RepoPath()) | ||||||
|  | 			if err != nil { | ||||||
|  | 				ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.RepoPath()), err) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			defer headRepo.Close() | ||||||
|  | 		} | ||||||
|  | 		if err := repo_service.DeleteBranch(ctx.User, pr.HeadRepo, headRepo, pr.HeadBranch); err != nil { | ||||||
|  | 			switch { | ||||||
|  | 			case git.IsErrBranchNotExist(err): | ||||||
|  | 				ctx.NotFound(err) | ||||||
|  | 			case errors.Is(err, repo_service.ErrBranchIsDefault): | ||||||
|  | 				ctx.Error(http.StatusForbidden, "DefaultBranch", fmt.Errorf("can not delete default branch")) | ||||||
|  | 			case errors.Is(err, repo_service.ErrBranchIsProtected): | ||||||
|  | 				ctx.Error(http.StatusForbidden, "IsProtectedBranch", fmt.Errorf("branch protected")) | ||||||
|  | 			default: | ||||||
|  | 				ctx.Error(http.StatusInternalServerError, "DeleteBranch", err) | ||||||
|  | 			} | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		if err := models.AddDeletePRBranchComment(ctx.User, pr.BaseRepo, pr.Issue.ID, pr.HeadBranch); err != nil { | ||||||
|  | 			// Do not fail here as branch has already been deleted | ||||||
|  | 			log.Error("DeleteBranch: %v", err) | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	ctx.Status(http.StatusOK) | 	ctx.Status(http.StatusOK) | ||||||
| } | } | ||||||
|  |  | ||||||
|   | |||||||
| @@ -833,14 +833,15 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { | |||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				// Unit type doesn't exist so we make a new config file with default values | 				// Unit type doesn't exist so we make a new config file with default values | ||||||
| 				config = &models.PullRequestsConfig{ | 				config = &models.PullRequestsConfig{ | ||||||
| 					IgnoreWhitespaceConflicts: false, | 					IgnoreWhitespaceConflicts:     false, | ||||||
| 					AllowMerge:                true, | 					AllowMerge:                    true, | ||||||
| 					AllowRebase:               true, | 					AllowRebase:                   true, | ||||||
| 					AllowRebaseMerge:          true, | 					AllowRebaseMerge:              true, | ||||||
| 					AllowSquash:               true, | 					AllowSquash:                   true, | ||||||
| 					AllowManualMerge:          true, | 					AllowManualMerge:              true, | ||||||
| 					AutodetectManualMerge:     false, | 					AutodetectManualMerge:         false, | ||||||
| 					DefaultMergeStyle:         models.MergeStyleMerge, | 					DefaultDeleteBranchAfterMerge: false, | ||||||
|  | 					DefaultMergeStyle:             models.MergeStyleMerge, | ||||||
| 				} | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				config = unit.PullRequestsConfig() | 				config = unit.PullRequestsConfig() | ||||||
| @@ -867,6 +868,9 @@ func updateRepoUnits(ctx *context.APIContext, opts api.EditRepoOption) error { | |||||||
| 			if opts.AutodetectManualMerge != nil { | 			if opts.AutodetectManualMerge != nil { | ||||||
| 				config.AutodetectManualMerge = *opts.AutodetectManualMerge | 				config.AutodetectManualMerge = *opts.AutodetectManualMerge | ||||||
| 			} | 			} | ||||||
|  | 			if opts.DefaultDeleteBranchAfterMerge != nil { | ||||||
|  | 				config.DefaultDeleteBranchAfterMerge = *opts.DefaultDeleteBranchAfterMerge | ||||||
|  | 			} | ||||||
| 			if opts.DefaultMergeStyle != nil { | 			if opts.DefaultMergeStyle != nil { | ||||||
| 				config.DefaultMergeStyle = models.MergeStyle(*opts.DefaultMergeStyle) | 				config.DefaultMergeStyle = models.MergeStyle(*opts.DefaultMergeStyle) | ||||||
| 			} | 			} | ||||||
|   | |||||||
| @@ -965,6 +965,22 @@ func MergePullRequest(ctx *context.Context) { | |||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	log.Trace("Pull request merged: %d", pr.ID) | 	log.Trace("Pull request merged: %d", pr.ID) | ||||||
|  |  | ||||||
|  | 	if form.DeleteBranchAfterMerge { | ||||||
|  | 		var headRepo *git.Repository | ||||||
|  | 		if ctx.Repo != nil && ctx.Repo.Repository != nil && pr.HeadRepoID == ctx.Repo.Repository.ID && ctx.Repo.GitRepo != nil { | ||||||
|  | 			headRepo = ctx.Repo.GitRepo | ||||||
|  | 		} else { | ||||||
|  | 			headRepo, err = git.OpenRepository(pr.HeadRepo.RepoPath()) | ||||||
|  | 			if err != nil { | ||||||
|  | 				ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.RepoPath()), err) | ||||||
|  | 				return | ||||||
|  | 			} | ||||||
|  | 			defer headRepo.Close() | ||||||
|  | 		} | ||||||
|  | 		deleteBranch(ctx, pr, headRepo) | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index)) | 	ctx.Redirect(ctx.Repo.RepoLink + "/pulls/" + fmt.Sprint(pr.Index)) | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -1170,19 +1186,35 @@ func CleanUpPullRequest(ctx *context.Context) { | |||||||
|  |  | ||||||
| 	fullBranchName := pr.HeadRepo.Owner.Name + "/" + pr.HeadBranch | 	fullBranchName := pr.HeadRepo.Owner.Name + "/" + pr.HeadBranch | ||||||
|  |  | ||||||
| 	gitRepo, err := git.OpenRepository(pr.HeadRepo.RepoPath()) | 	var gitBaseRepo *git.Repository | ||||||
| 	if err != nil { |  | ||||||
| 		ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.RepoPath()), err) |  | ||||||
| 		return |  | ||||||
| 	} |  | ||||||
| 	defer gitRepo.Close() |  | ||||||
|  |  | ||||||
| 	gitBaseRepo, err := git.OpenRepository(pr.BaseRepo.RepoPath()) | 	// Assume that the base repo is the current context (almost certainly) | ||||||
| 	if err != nil { | 	if ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == pr.BaseRepoID && ctx.Repo.GitRepo != nil { | ||||||
| 		ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.BaseRepo.RepoPath()), err) | 		gitBaseRepo = ctx.Repo.GitRepo | ||||||
| 		return | 	} else { | ||||||
|  | 		// If not just open it | ||||||
|  | 		gitBaseRepo, err = git.OpenRepository(pr.BaseRepo.RepoPath()) | ||||||
|  | 		if err != nil { | ||||||
|  | 			ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.BaseRepo.RepoPath()), err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		defer gitBaseRepo.Close() | ||||||
|  | 	} | ||||||
|  |  | ||||||
|  | 	// Now assume that the head repo is the same as the base repo (reasonable chance) | ||||||
|  | 	gitRepo := gitBaseRepo | ||||||
|  | 	// But if not: is it the same as the context? | ||||||
|  | 	if pr.BaseRepoID != pr.HeadRepoID && ctx.Repo != nil && ctx.Repo.Repository != nil && ctx.Repo.Repository.ID == pr.HeadRepoID && ctx.Repo.GitRepo != nil { | ||||||
|  | 		gitRepo = ctx.Repo.GitRepo | ||||||
|  | 	} else if pr.BaseRepoID != pr.HeadRepoID { | ||||||
|  | 		// Otherwise just load it up | ||||||
|  | 		gitRepo, err = git.OpenRepository(pr.HeadRepo.RepoPath()) | ||||||
|  | 		if err != nil { | ||||||
|  | 			ctx.ServerError(fmt.Sprintf("OpenRepository[%s]", pr.HeadRepo.RepoPath()), err) | ||||||
|  | 			return | ||||||
|  | 		} | ||||||
|  | 		defer gitRepo.Close() | ||||||
| 	} | 	} | ||||||
| 	defer gitBaseRepo.Close() |  | ||||||
|  |  | ||||||
| 	defer func() { | 	defer func() { | ||||||
| 		ctx.JSON(http.StatusOK, map[string]interface{}{ | 		ctx.JSON(http.StatusOK, map[string]interface{}{ | ||||||
| @@ -1208,6 +1240,11 @@ func CleanUpPullRequest(ctx *context.Context) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	deleteBranch(ctx, pr, gitRepo) | ||||||
|  | } | ||||||
|  |  | ||||||
|  | func deleteBranch(ctx *context.Context, pr *models.PullRequest, gitRepo *git.Repository) { | ||||||
|  | 	fullBranchName := pr.HeadRepo.Owner.Name + "/" + pr.HeadBranch | ||||||
| 	if err := repo_service.DeleteBranch(ctx.User, pr.HeadRepo, gitRepo, pr.HeadBranch); err != nil { | 	if err := repo_service.DeleteBranch(ctx.User, pr.HeadRepo, gitRepo, pr.HeadBranch); err != nil { | ||||||
| 		switch { | 		switch { | ||||||
| 		case git.IsErrBranchNotExist(err): | 		case git.IsErrBranchNotExist(err): | ||||||
| @@ -1223,7 +1260,7 @@ func CleanUpPullRequest(ctx *context.Context) { | |||||||
| 		return | 		return | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	if err := models.AddDeletePRBranchComment(ctx.User, pr.BaseRepo, issue.ID, pr.HeadBranch); err != nil { | 	if err := models.AddDeletePRBranchComment(ctx.User, pr.BaseRepo, pr.IssueID, pr.HeadBranch); err != nil { | ||||||
| 		// Do not fail here as branch has already been deleted | 		// Do not fail here as branch has already been deleted | ||||||
| 		log.Error("DeleteBranch: %v", err) | 		log.Error("DeleteBranch: %v", err) | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -416,14 +416,15 @@ func SettingsPost(ctx *context.Context) { | |||||||
| 				RepoID: repo.ID, | 				RepoID: repo.ID, | ||||||
| 				Type:   models.UnitTypePullRequests, | 				Type:   models.UnitTypePullRequests, | ||||||
| 				Config: &models.PullRequestsConfig{ | 				Config: &models.PullRequestsConfig{ | ||||||
| 					IgnoreWhitespaceConflicts: form.PullsIgnoreWhitespace, | 					IgnoreWhitespaceConflicts:     form.PullsIgnoreWhitespace, | ||||||
| 					AllowMerge:                form.PullsAllowMerge, | 					AllowMerge:                    form.PullsAllowMerge, | ||||||
| 					AllowRebase:               form.PullsAllowRebase, | 					AllowRebase:                   form.PullsAllowRebase, | ||||||
| 					AllowRebaseMerge:          form.PullsAllowRebaseMerge, | 					AllowRebaseMerge:              form.PullsAllowRebaseMerge, | ||||||
| 					AllowSquash:               form.PullsAllowSquash, | 					AllowSquash:                   form.PullsAllowSquash, | ||||||
| 					AllowManualMerge:          form.PullsAllowManualMerge, | 					AllowManualMerge:              form.PullsAllowManualMerge, | ||||||
| 					AutodetectManualMerge:     form.EnableAutodetectManualMerge, | 					AutodetectManualMerge:         form.EnableAutodetectManualMerge, | ||||||
| 					DefaultMergeStyle:         models.MergeStyle(form.PullsDefaultMergeStyle), | 					DefaultDeleteBranchAfterMerge: form.DefaultDeleteBranchAfterMerge, | ||||||
|  | 					DefaultMergeStyle:             models.MergeStyle(form.PullsDefaultMergeStyle), | ||||||
| 				}, | 				}, | ||||||
| 			}) | 			}) | ||||||
| 		} else if !models.UnitTypePullRequests.UnitGlobalDisabled() { | 		} else if !models.UnitTypePullRequests.UnitGlobalDisabled() { | ||||||
|   | |||||||
| @@ -151,6 +151,7 @@ type RepoSettingForm struct { | |||||||
| 	PullsAllowManualMerge                 bool | 	PullsAllowManualMerge                 bool | ||||||
| 	PullsDefaultMergeStyle                string | 	PullsDefaultMergeStyle                string | ||||||
| 	EnableAutodetectManualMerge           bool | 	EnableAutodetectManualMerge           bool | ||||||
|  | 	DefaultDeleteBranchAfterMerge         bool | ||||||
| 	EnableTimetracker                     bool | 	EnableTimetracker                     bool | ||||||
| 	AllowOnlyContributorsToTrackTime      bool | 	AllowOnlyContributorsToTrackTime      bool | ||||||
| 	EnableIssueDependencies               bool | 	EnableIssueDependencies               bool | ||||||
| @@ -551,11 +552,12 @@ func (f *InitializeLabelsForm) Validate(req *http.Request, errs binding.Errors) | |||||||
| type MergePullRequestForm struct { | type MergePullRequestForm struct { | ||||||
| 	// required: true | 	// required: true | ||||||
| 	// enum: merge,rebase,rebase-merge,squash,manually-merged | 	// enum: merge,rebase,rebase-merge,squash,manually-merged | ||||||
| 	Do                string `binding:"Required;In(merge,rebase,rebase-merge,squash,manually-merged)"` | 	Do                     string `binding:"Required;In(merge,rebase,rebase-merge,squash,manually-merged)"` | ||||||
| 	MergeTitleField   string | 	MergeTitleField        string | ||||||
| 	MergeMessageField string | 	MergeMessageField      string | ||||||
| 	MergeCommitID     string // only used for manually-merged | 	MergeCommitID          string // only used for manually-merged | ||||||
| 	ForceMerge        *bool  `json:"force_merge,omitempty"` | 	ForceMerge             *bool  `json:"force_merge,omitempty"` | ||||||
|  | 	DeleteBranchAfterMerge bool   `json:"delete_branch_after_merge,omitempty"` | ||||||
| } | } | ||||||
|  |  | ||||||
| // Validate validates the fields | // Validate validates the fields | ||||||
|   | |||||||
| @@ -303,7 +303,11 @@ func AddTestPullRequestTask(doer *models.User, repoID int64, branch string, isSy | |||||||
| 		for _, pr := range prs { | 		for _, pr := range prs { | ||||||
| 			divergence, err := GetDiverging(pr) | 			divergence, err := GetDiverging(pr) | ||||||
| 			if err != nil { | 			if err != nil { | ||||||
| 				log.Error("GetDiverging: %v", err) | 				if models.IsErrBranchDoesNotExist(err) && !git.IsBranchExist(pr.HeadRepo.RepoPath(), pr.HeadBranch) { | ||||||
|  | 					log.Warn("Cannot test PR %s/%d: head_branch %s no longer exists", pr.BaseRepo.Name, pr.IssueID, pr.HeadBranch) | ||||||
|  | 				} else { | ||||||
|  | 					log.Error("GetDiverging: %v", err) | ||||||
|  | 				} | ||||||
| 			} else { | 			} else { | ||||||
| 				err = pr.UpdateCommitDivergence(divergence.Ahead, divergence.Behind) | 				err = pr.UpdateCommitDivergence(divergence.Ahead, divergence.Behind) | ||||||
| 				if err != nil { | 				if err != nil { | ||||||
|   | |||||||
| @@ -141,10 +141,15 @@ func createTemporaryRepo(pr *models.PullRequest) (string, error) { | |||||||
| 	trackingBranch := "tracking" | 	trackingBranch := "tracking" | ||||||
| 	// Fetch head branch | 	// Fetch head branch | ||||||
| 	if err := git.NewCommand("fetch", "--no-tags", remoteRepoName, git.BranchPrefix+pr.HeadBranch+":"+trackingBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil { | 	if err := git.NewCommand("fetch", "--no-tags", remoteRepoName, git.BranchPrefix+pr.HeadBranch+":"+trackingBranch).RunInDirPipeline(tmpBasePath, &outbuf, &errbuf); err != nil { | ||||||
| 		log.Error("Unable to fetch head_repo head branch [%s:%s -> tracking in %s]: %v:\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, tmpBasePath, err, outbuf.String(), errbuf.String()) |  | ||||||
| 		if err := models.RemoveTemporaryPath(tmpBasePath); err != nil { | 		if err := models.RemoveTemporaryPath(tmpBasePath); err != nil { | ||||||
| 			log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err) | 			log.Error("CreateTempRepo: RemoveTemporaryPath: %s", err) | ||||||
| 		} | 		} | ||||||
|  | 		if !git.IsBranchExist(pr.HeadRepo.RepoPath(), pr.HeadBranch) { | ||||||
|  | 			return "", models.ErrBranchDoesNotExist{ | ||||||
|  | 				BranchName: pr.HeadBranch, | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 		log.Error("Unable to fetch head_repo head branch [%s:%s -> tracking in %s]: %v:\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, tmpBasePath, err, outbuf.String(), errbuf.String()) | ||||||
| 		return "", fmt.Errorf("Unable to fetch head_repo head branch [%s:%s -> tracking in tmpBasePath]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, err, outbuf.String(), errbuf.String()) | 		return "", fmt.Errorf("Unable to fetch head_repo head branch [%s:%s -> tracking in tmpBasePath]: %v\n%s\n%s", pr.HeadRepo.FullName(), pr.HeadBranch, err, outbuf.String(), errbuf.String()) | ||||||
| 	} | 	} | ||||||
| 	outbuf.Reset() | 	outbuf.Reset() | ||||||
|   | |||||||
| @@ -88,7 +88,9 @@ func GetDiverging(pr *models.PullRequest) (*git.DivergeObject, error) { | |||||||
|  |  | ||||||
| 	tmpRepo, err := createTemporaryRepo(pr) | 	tmpRepo, err := createTemporaryRepo(pr) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		log.Error("CreateTemporaryPath: %v", err) | 		if !models.IsErrBranchDoesNotExist(err) { | ||||||
|  | 			log.Error("CreateTemporaryRepo: %v", err) | ||||||
|  | 		} | ||||||
| 		return nil, err | 		return nil, err | ||||||
| 	} | 	} | ||||||
| 	defer func() { | 	defer func() { | ||||||
|   | |||||||
| @@ -315,6 +315,12 @@ | |||||||
| 									<button class="ui button merge-cancel"> | 									<button class="ui button merge-cancel"> | ||||||
| 										{{$.i18n.Tr "cancel"}} | 										{{$.i18n.Tr "cancel"}} | ||||||
| 									</button> | 									</button> | ||||||
|  | 									{{if .IsPullBranchDeletable}} | ||||||
|  | 										<div class="ui checkbox ml-2"> | ||||||
|  | 											<input name="delete_branch_after_merge" type="checkbox" {{if $prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge}}checked{{end}}> | ||||||
|  | 											<label>{{$.i18n.Tr "repo.branch.delete" .HeadTarget}}</label> | ||||||
|  | 										</div> | ||||||
|  | 									{{end}} | ||||||
| 								</form> | 								</form> | ||||||
| 							</div> | 							</div> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| @@ -328,6 +334,12 @@ | |||||||
| 									<button class="ui button merge-cancel"> | 									<button class="ui button merge-cancel"> | ||||||
| 										{{$.i18n.Tr "cancel"}} | 										{{$.i18n.Tr "cancel"}} | ||||||
| 									</button> | 									</button> | ||||||
|  | 									{{if .IsPullBranchDeletable}} | ||||||
|  | 										<div class="ui checkbox ml-2"> | ||||||
|  | 											<input name="delete_branch_after_merge" type="checkbox" {{if $prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge}}checked{{end}}> | ||||||
|  | 											<label>{{$.i18n.Tr "repo.branch.delete" .HeadTarget}}</label> | ||||||
|  | 										</div> | ||||||
|  | 									{{end}} | ||||||
| 								</form> | 								</form> | ||||||
| 							</div> | 							</div> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| @@ -347,6 +359,12 @@ | |||||||
| 									<button class="ui button merge-cancel"> | 									<button class="ui button merge-cancel"> | ||||||
| 										{{$.i18n.Tr "cancel"}} | 										{{$.i18n.Tr "cancel"}} | ||||||
| 									</button> | 									</button> | ||||||
|  | 									{{if .IsPullBranchDeletable}} | ||||||
|  | 										<div class="ui checkbox ml-2"> | ||||||
|  | 											<input name="delete_branch_after_merge" type="checkbox" {{if $prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge}}checked{{end}}> | ||||||
|  | 											<label>{{$.i18n.Tr "repo.branch.delete" .HeadTarget}}</label> | ||||||
|  | 										</div> | ||||||
|  | 									{{end}} | ||||||
| 								</form> | 								</form> | ||||||
| 							</div> | 							</div> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| @@ -366,6 +384,12 @@ | |||||||
| 									<button class="ui button merge-cancel"> | 									<button class="ui button merge-cancel"> | ||||||
| 										{{$.i18n.Tr "cancel"}} | 										{{$.i18n.Tr "cancel"}} | ||||||
| 									</button> | 									</button> | ||||||
|  | 									{{if .IsPullBranchDeletable}} | ||||||
|  | 										<div class="ui checkbox ml-2"> | ||||||
|  | 											<input name="delete_branch_after_merge" type="checkbox" {{if $prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge}}checked{{end}}> | ||||||
|  | 											<label>{{$.i18n.Tr "repo.branch.delete" .HeadTarget}}</label> | ||||||
|  | 										</div> | ||||||
|  | 									{{end}} | ||||||
| 								</form> | 								</form> | ||||||
| 							</div> | 							</div> | ||||||
| 							{{end}} | 							{{end}} | ||||||
| @@ -382,6 +406,12 @@ | |||||||
| 										<button class="ui button merge-cancel"> | 										<button class="ui button merge-cancel"> | ||||||
| 											{{$.i18n.Tr "cancel"}} | 											{{$.i18n.Tr "cancel"}} | ||||||
| 										</button> | 										</button> | ||||||
|  | 										{{if .IsPullBranchDeletable}} | ||||||
|  | 											<div class="ui checkbox ml-2"> | ||||||
|  | 												<input name="delete_branch_after_merge" type="checkbox" {{if $prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge}}checked{{end}}> | ||||||
|  | 												<label>{{$.i18n.Tr "repo.branch.delete" .HeadTarget}}</label> | ||||||
|  | 											</div> | ||||||
|  | 										{{end}} | ||||||
| 									</form> | 									</form> | ||||||
| 								</div> | 								</div> | ||||||
| 							{{end}} | 							{{end}} | ||||||
|   | |||||||
| @@ -445,6 +445,12 @@ | |||||||
| 								<label>{{.i18n.Tr "repo.settings.pulls.enable_autodetect_manual_merge"}}</label> | 								<label>{{.i18n.Tr "repo.settings.pulls.enable_autodetect_manual_merge"}}</label> | ||||||
| 							</div> | 							</div> | ||||||
| 						</div> | 						</div> | ||||||
|  | 						<div class="field"> | ||||||
|  | 							<div class="ui checkbox"> | ||||||
|  | 								<input name="default_delete_branch_after_merge" type="checkbox" {{if or (not $pullRequestEnabled) ($prUnit.PullRequestsConfig.DefaultDeleteBranchAfterMerge)}}checked{{end}}> | ||||||
|  | 								<label>{{.i18n.Tr "repo.settings.pulls.default_delete_branch_after_merge"}}</label> | ||||||
|  | 							</div> | ||||||
|  | 						</div> | ||||||
| 						<div class="field"> | 						<div class="field"> | ||||||
| 							<p> | 							<p> | ||||||
| 								{{.i18n.Tr "repo.settings.default_merge_style_desc"}} | 								{{.i18n.Tr "repo.settings.default_merge_style_desc"}} | ||||||
|   | |||||||
| @@ -14058,6 +14058,11 @@ | |||||||
|           "type": "string", |           "type": "string", | ||||||
|           "x-go-name": "DefaultBranch" |           "x-go-name": "DefaultBranch" | ||||||
|         }, |         }, | ||||||
|  |         "default_delete_branch_after_merge": { | ||||||
|  |           "description": "set to `true` to delete pr branch after merge by default", | ||||||
|  |           "type": "boolean", | ||||||
|  |           "x-go-name": "DefaultDeleteBranchAfterMerge" | ||||||
|  |         }, | ||||||
|         "default_merge_style": { |         "default_merge_style": { | ||||||
|           "description": "set to a merge style to be used by this repository: \"merge\", \"rebase\", \"rebase-merge\", or \"squash\". `has_pull_requests` must be `true`.", |           "description": "set to a merge style to be used by this repository: \"merge\", \"rebase\", \"rebase-merge\", or \"squash\". `has_pull_requests` must be `true`.", | ||||||
|           "type": "string", |           "type": "string", | ||||||
| @@ -15137,6 +15142,10 @@ | |||||||
|         "MergeTitleField": { |         "MergeTitleField": { | ||||||
|           "type": "string" |           "type": "string" | ||||||
|         }, |         }, | ||||||
|  |         "delete_branch_after_merge": { | ||||||
|  |           "type": "boolean", | ||||||
|  |           "x-go-name": "DeleteBranchAfterMerge" | ||||||
|  |         }, | ||||||
|         "force_merge": { |         "force_merge": { | ||||||
|           "type": "boolean", |           "type": "boolean", | ||||||
|           "x-go-name": "ForceMerge" |           "x-go-name": "ForceMerge" | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user