diff --git a/models/fixtures/repo_unit.yml b/models/fixtures/repo_unit.yml index c22eb8c2a2f..98b1f474010 100644 --- a/models/fixtures/repo_unit.yml +++ b/models/fixtures/repo_unit.yml @@ -649,3 +649,10 @@ repo_id: 49 type: 2 created_unix: 946684810 + +- + id: 98 + repo_id: 59 + type: 1 + config: "{}" + created_unix: 946684810 diff --git a/models/fixtures/repository.yml b/models/fixtures/repository.yml index 373c1caa625..f4e83767354 100644 --- a/models/fixtures/repository.yml +++ b/models/fixtures/repository.yml @@ -1693,3 +1693,16 @@ size: 0 is_fsck_enabled: true close_issues_via_commit_in_any_branch: false + +- + id: 59 + owner_id: 2 + owner_name: user2 + lower_name: test_commit_revert + name: test_commit_revert + default_branch: main + is_empty: false + is_archived: false + is_private: true + status: 0 + num_issues: 0 diff --git a/models/fixtures/user.yml b/models/fixtures/user.yml index fd513798167..79fbb981f64 100644 --- a/models/fixtures/user.yml +++ b/models/fixtures/user.yml @@ -66,7 +66,7 @@ num_followers: 2 num_following: 1 num_stars: 2 - num_repos: 14 + num_repos: 15 num_teams: 0 num_members: 0 visibility: 0 diff --git a/services/packages/cargo/index.go b/services/packages/cargo/index.go index 8164ffb01cb..e580de2fe0d 100644 --- a/services/packages/cargo/index.go +++ b/services/packages/cargo/index.go @@ -267,7 +267,7 @@ func alterRepositoryContent(ctx context.Context, doer *user_model.User, repo *re defer t.Close() var lastCommitID string - if err := t.Clone(repo.DefaultBranch); err != nil { + if err := t.Clone(repo.DefaultBranch, true); err != nil { if !git.IsErrBranchNotExist(err) || !repo.IsEmpty { return err } diff --git a/services/repository/files/cherry_pick.go b/services/repository/files/cherry_pick.go index c1c5bfb6176..5e9a0900a76 100644 --- a/services/repository/files/cherry_pick.go +++ b/services/repository/files/cherry_pick.go @@ -31,12 +31,15 @@ func CherryPick(ctx context.Context, repo *repo_model.Repository, doer *user_mod log.Error("%v", err) } defer t.Close() - if err := t.Clone(opts.OldBranch); err != nil { + if err := t.Clone(opts.OldBranch, false); err != nil { return nil, err } if err := t.SetDefaultIndex(); err != nil { return nil, err } + if err := t.RefreshIndex(); err != nil { + return nil, err + } // Get the commit of the original branch commit, err := t.GetBranchCommit(opts.OldBranch) diff --git a/services/repository/files/diff.go b/services/repository/files/diff.go index 373249b1145..bf8b938e217 100644 --- a/services/repository/files/diff.go +++ b/services/repository/files/diff.go @@ -21,7 +21,7 @@ func GetDiffPreview(ctx context.Context, repo *repo_model.Repository, branch, tr return nil, err } defer t.Close() - if err := t.Clone(branch); err != nil { + if err := t.Clone(branch, true); err != nil { return nil, err } if err := t.SetDefaultIndex(); err != nil { diff --git a/services/repository/files/patch.go b/services/repository/files/patch.go index fdf0b32f1a1..5bd59251df3 100644 --- a/services/repository/files/patch.go +++ b/services/repository/files/patch.go @@ -108,7 +108,7 @@ func ApplyDiffPatch(ctx context.Context, repo *repo_model.Repository, doer *user log.Error("%v", err) } defer t.Close() - if err := t.Clone(opts.OldBranch); err != nil { + if err := t.Clone(opts.OldBranch, true); err != nil { return nil, err } if err := t.SetDefaultIndex(); err != nil { diff --git a/services/repository/files/temp_repo.go b/services/repository/files/temp_repo.go index 7f6b8137ae1..4c8cfb24819 100644 --- a/services/repository/files/temp_repo.go +++ b/services/repository/files/temp_repo.go @@ -51,8 +51,13 @@ func (t *TemporaryUploadRepository) Close() { } // Clone the base repository to our path and set branch as the HEAD -func (t *TemporaryUploadRepository) Clone(branch string) error { - if _, _, err := git.NewCommand(t.ctx, "clone", "-s", "--bare", "-b").AddDynamicArguments(branch, t.repo.RepoPath(), t.basePath).RunStdString(nil); err != nil { +func (t *TemporaryUploadRepository) Clone(branch string, bare bool) error { + cmd := git.NewCommand(t.ctx, "clone", "-s", "-b").AddDynamicArguments(branch, t.repo.RepoPath(), t.basePath) + if bare { + cmd.AddArguments("--bare") + } + + if _, _, err := cmd.RunStdString(nil); err != nil { stderr := err.Error() if matched, _ := regexp.MatchString(".*Remote branch .* not found in upstream origin.*", stderr); matched { return git.ErrBranchNotExist{ @@ -98,6 +103,14 @@ func (t *TemporaryUploadRepository) SetDefaultIndex() error { return nil } +// RefreshIndex looks at the current index and checks to see if merges or updates are needed by checking stat() information. +func (t *TemporaryUploadRepository) RefreshIndex() error { + if _, _, err := git.NewCommand(t.ctx, "update-index", "--refresh").RunStdString(&git.RunOpts{Dir: t.basePath}); err != nil { + return fmt.Errorf("RefreshIndex: %w", err) + } + return nil +} + // LsFiles checks if the given filename arguments are in the index func (t *TemporaryUploadRepository) LsFiles(filenames ...string) ([]string, error) { stdOut := new(bytes.Buffer) diff --git a/services/repository/files/update.go b/services/repository/files/update.go index f01092d360d..9d32876eff2 100644 --- a/services/repository/files/update.go +++ b/services/repository/files/update.go @@ -141,7 +141,7 @@ func ChangeRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use } defer t.Close() hasOldBranch := true - if err := t.Clone(opts.OldBranch); err != nil { + if err := t.Clone(opts.OldBranch, true); err != nil { for _, file := range opts.Files { if file.Operation == "delete" { return nil, err diff --git a/services/repository/files/upload.go b/services/repository/files/upload.go index f4e1da7bb1a..c893c5c43e1 100644 --- a/services/repository/files/upload.go +++ b/services/repository/files/upload.go @@ -87,7 +87,7 @@ func UploadRepoFiles(ctx context.Context, repo *repo_model.Repository, doer *use defer t.Close() hasOldBranch := true - if err = t.Clone(opts.OldBranch); err != nil { + if err = t.Clone(opts.OldBranch, true); err != nil { if !git.IsErrBranchNotExist(err) || !repo.IsEmpty { return err } diff --git a/tests/gitea-repositories-meta/user2/test_commit_revert.git/HEAD b/tests/gitea-repositories-meta/user2/test_commit_revert.git/HEAD new file mode 100644 index 00000000000..b870d82622c --- /dev/null +++ b/tests/gitea-repositories-meta/user2/test_commit_revert.git/HEAD @@ -0,0 +1 @@ +ref: refs/heads/main diff --git a/tests/gitea-repositories-meta/user2/test_commit_revert.git/config b/tests/gitea-repositories-meta/user2/test_commit_revert.git/config new file mode 100644 index 00000000000..57bbcba5bee --- /dev/null +++ b/tests/gitea-repositories-meta/user2/test_commit_revert.git/config @@ -0,0 +1,8 @@ +[core] + repositoryformatversion = 0 + filemode = true + bare = true + ignorecase = true + precomposeunicode = true +[remote "origin"] + url = https://try.gitea.io/me-heer/test_commit_revert.git diff --git a/tests/gitea-repositories-meta/user2/test_commit_revert.git/description b/tests/gitea-repositories-meta/user2/test_commit_revert.git/description new file mode 100644 index 00000000000..498b267a8c7 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/test_commit_revert.git/description @@ -0,0 +1 @@ +Unnamed repository; edit this file 'description' to name the repository. diff --git a/tests/gitea-repositories-meta/user2/test_commit_revert.git/info/exclude b/tests/gitea-repositories-meta/user2/test_commit_revert.git/info/exclude new file mode 100644 index 00000000000..a5196d1be8f --- /dev/null +++ b/tests/gitea-repositories-meta/user2/test_commit_revert.git/info/exclude @@ -0,0 +1,6 @@ +# git ls-files --others --exclude-from=.git/info/exclude +# Lines that start with '#' are comments. +# For a project mostly in C, the following would be a good set of +# exclude patterns (uncomment them if you want to use them): +# *.[oa] +# *~ diff --git a/tests/gitea-repositories-meta/user2/test_commit_revert.git/objects/pack/pack-91200c8e6707636a6cc3e0d8101fba08b19dcb91.idx b/tests/gitea-repositories-meta/user2/test_commit_revert.git/objects/pack/pack-91200c8e6707636a6cc3e0d8101fba08b19dcb91.idx new file mode 100644 index 00000000000..77bcbe7fb4c Binary files /dev/null and b/tests/gitea-repositories-meta/user2/test_commit_revert.git/objects/pack/pack-91200c8e6707636a6cc3e0d8101fba08b19dcb91.idx differ diff --git a/tests/gitea-repositories-meta/user2/test_commit_revert.git/objects/pack/pack-91200c8e6707636a6cc3e0d8101fba08b19dcb91.pack b/tests/gitea-repositories-meta/user2/test_commit_revert.git/objects/pack/pack-91200c8e6707636a6cc3e0d8101fba08b19dcb91.pack new file mode 100644 index 00000000000..7271cdaeb87 Binary files /dev/null and b/tests/gitea-repositories-meta/user2/test_commit_revert.git/objects/pack/pack-91200c8e6707636a6cc3e0d8101fba08b19dcb91.pack differ diff --git a/tests/gitea-repositories-meta/user2/test_commit_revert.git/packed-refs b/tests/gitea-repositories-meta/user2/test_commit_revert.git/packed-refs new file mode 100644 index 00000000000..1f546d7fd51 --- /dev/null +++ b/tests/gitea-repositories-meta/user2/test_commit_revert.git/packed-refs @@ -0,0 +1,3 @@ +# pack-refs with: peeled fully-peeled sorted +46aa6ab2c881ae90e15d9ccfc947d1625c892ce5 refs/heads/develop +deebcbc752e540bab4ce3ee713d3fc8fdc35b2f7 refs/heads/main diff --git a/tests/integration/repo_mergecommit_revert_test.go b/tests/integration/repo_mergecommit_revert_test.go new file mode 100644 index 00000000000..4d612bdcdb6 --- /dev/null +++ b/tests/integration/repo_mergecommit_revert_test.go @@ -0,0 +1,34 @@ +package integration + +import ( + "net/http" + "testing" + + "code.gitea.io/gitea/tests" + + "github.com/stretchr/testify/assert" +) + +func TestRepoMergeCommitRevert(t *testing.T) { + defer tests.PrepareTestEnv(t)() + session := loginUser(t, "user2") + + req := NewRequest(t, "GET", "/user2/test_commit_revert/_cherrypick/deebcbc752e540bab4ce3ee713d3fc8fdc35b2f7/main?ref=main&refType=branch&cherry-pick-type=revert") + resp := session.MakeRequest(t, req, http.StatusOK) + + htmlDoc := NewHTMLParser(t, resp.Body) + req = NewRequestWithValues(t, "POST", "/user2/test_commit_revert/_cherrypick/deebcbc752e540bab4ce3ee713d3fc8fdc35b2f7/main", map[string]string{ + "_csrf": htmlDoc.GetCSRF(), + "last_commit": "deebcbc752e540bab4ce3ee713d3fc8fdc35b2f7", + "page_has_posted": "true", + "revert": "true", + "commit_summary": "reverting test commit", + "commit_message": "test message", + "commit_choice": "direct", + "new_branch_name": "test-revert-branch-1", + }) + resp = session.MakeRequest(t, req, http.StatusSeeOther) + + // A successful revert redirects to the main branch + assert.EqualValues(t, "/user2/test_commit_revert/src/branch/main", resp.Header().Get("Location")) +}