Restore deleted branches when syncing (#29898)

Regression of #29493. If a branch has been deleted, repushing it won't
restore it.

Lunny may have noticed that, but I didn't delve into the comment then
overlooked it:
https://github.com/go-gitea/gitea/pull/29493#discussion_r1509046867

The additional comments added are to explain the issue I found during
testing, which are unrelated to the fixes.
This commit is contained in:
Jason Song 2024-03-20 09:45:27 +08:00 committed by GitHub
parent 6ed2c29b14
commit f371f84fa3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 24 additions and 5 deletions

View File

@ -75,6 +75,10 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
updates = append(updates, option) updates = append(updates, option)
if repo.IsEmpty && (refFullName.BranchName() == "master" || refFullName.BranchName() == "main") { if repo.IsEmpty && (refFullName.BranchName() == "master" || refFullName.BranchName() == "main") {
// put the master/main branch first // put the master/main branch first
// FIXME: It doesn't always work, since the master/main branch may not be the first batch of updates.
// If the user pushes many branches at once, the Git hook will call the internal API in batches, rather than all at once.
// See https://github.com/go-gitea/gitea/blob/cb52b17f92e2d2293f7c003649743464492bca48/cmd/hook.go#L27
// If the user executes `git push origin --all` and pushes more than 30 branches, the master/main may not be the default branch.
copy(updates[1:], updates) copy(updates[1:], updates)
updates[0] = option updates[0] = option
} }
@ -129,9 +133,7 @@ func HookPostReceive(ctx *gitea_context.PrivateContext) {
commitIDs = append(commitIDs, update.NewCommitID) commitIDs = append(commitIDs, update.NewCommitID)
} }
if err := repo_service.SyncBranchesToDB(ctx, repo.ID, opts.UserID, branchNames, commitIDs, func(commitID string) (*git.Commit, error) { if err := repo_service.SyncBranchesToDB(ctx, repo.ID, opts.UserID, branchNames, commitIDs, gitRepo.GetCommit); err != nil {
return gitRepo.GetCommit(commitID)
}); err != nil {
ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{ ctx.JSON(http.StatusInternalServerError, private.HookPostReceiveResult{
Err: fmt.Sprintf("Failed to sync branch to DB in repository: %s/%s Error: %v", ownerName, repoName, err), Err: fmt.Sprintf("Failed to sync branch to DB in repository: %s/%s Error: %v", ownerName, repoName, err),
}) })

View File

@ -318,11 +318,11 @@ func SyncBranchesToDB(ctx context.Context, repoID, pusherID int64, branchNames,
for i, branchName := range branchNames { for i, branchName := range branchNames {
commitID := commitIDs[i] commitID := commitIDs[i]
branch, exist := branchMap[branchName] branch, exist := branchMap[branchName]
if exist && branch.CommitID == commitID { if exist && branch.CommitID == commitID && !branch.IsDeleted {
continue continue
} }
commit, err := getCommit(branchName) commit, err := getCommit(commitID)
if err != nil { if err != nil {
return fmt.Errorf("get commit of %s failed: %v", branchName, err) return fmt.Errorf("get commit of %s failed: %v", branchName, err)
} }

View File

@ -69,6 +69,23 @@ func testGitPush(t *testing.T, u *url.URL) {
return pushed, deleted return pushed, deleted
}) })
}) })
t.Run("Push to deleted branch", func(t *testing.T) {
runTestGitPush(t, u, func(t *testing.T, gitPath string) (pushed, deleted []string) {
doGitPushTestRepository(gitPath, "origin", "master")(t) // make sure master is the default branch instead of a branch we are going to delete
pushed = append(pushed, "master")
doGitCreateBranch(gitPath, "branch-1")(t)
doGitPushTestRepository(gitPath, "origin", "branch-1")(t)
pushed = append(pushed, "branch-1")
// delete and restore
doGitPushTestRepository(gitPath, "origin", "--delete", "branch-1")(t)
doGitPushTestRepository(gitPath, "origin", "branch-1")(t)
return pushed, deleted
})
})
} }
func runTestGitPush(t *testing.T, u *url.URL, gitOperation func(t *testing.T, gitPath string) (pushed, deleted []string)) { func runTestGitPush(t *testing.T, u *url.URL, gitOperation func(t *testing.T, gitPath string) (pushed, deleted []string)) {