Allow to mark files in a PR as viewed (#19007)
Users can now mark files in PRs as viewed, resulting in them not being shown again by default when they reopen the PR again.
This commit is contained in:
parent
59b30f060a
commit
5ca224a789
16 changed files with 492 additions and 44 deletions
|
@ -22,6 +22,7 @@ import (
|
|||
|
||||
"code.gitea.io/gitea/models"
|
||||
"code.gitea.io/gitea/models/db"
|
||||
pull_model "code.gitea.io/gitea/models/pull"
|
||||
user_model "code.gitea.io/gitea/models/user"
|
||||
"code.gitea.io/gitea/modules/analyze"
|
||||
"code.gitea.io/gitea/modules/charset"
|
||||
|
@ -602,25 +603,27 @@ func (diffSection *DiffSection) GetComputedInlineDiffFor(diffLine *DiffLine) Dif
|
|||
|
||||
// DiffFile represents a file diff.
|
||||
type DiffFile struct {
|
||||
Name string
|
||||
OldName string
|
||||
Index int
|
||||
Addition, Deletion int
|
||||
Type DiffFileType
|
||||
IsCreated bool
|
||||
IsDeleted bool
|
||||
IsBin bool
|
||||
IsLFSFile bool
|
||||
IsRenamed bool
|
||||
IsAmbiguous bool
|
||||
IsSubmodule bool
|
||||
Sections []*DiffSection
|
||||
IsIncomplete bool
|
||||
IsIncompleteLineTooLong bool
|
||||
IsProtected bool
|
||||
IsGenerated bool
|
||||
IsVendored bool
|
||||
Language string
|
||||
Name string
|
||||
OldName string
|
||||
Index int
|
||||
Addition, Deletion int
|
||||
Type DiffFileType
|
||||
IsCreated bool
|
||||
IsDeleted bool
|
||||
IsBin bool
|
||||
IsLFSFile bool
|
||||
IsRenamed bool
|
||||
IsAmbiguous bool
|
||||
IsSubmodule bool
|
||||
Sections []*DiffSection
|
||||
IsIncomplete bool
|
||||
IsIncompleteLineTooLong bool
|
||||
IsProtected bool
|
||||
IsGenerated bool
|
||||
IsVendored bool
|
||||
IsViewed bool // User specific
|
||||
HasChangedSinceLastReview bool // User specific
|
||||
Language string
|
||||
}
|
||||
|
||||
// GetType returns type of diff file.
|
||||
|
@ -663,6 +666,18 @@ func (diffFile *DiffFile) GetTailSection(gitRepo *git.Repository, leftCommitID,
|
|||
return tailSection
|
||||
}
|
||||
|
||||
// GetDiffFileName returns the name of the diff file, or its old name in case it was deleted
|
||||
func (diffFile *DiffFile) GetDiffFileName() string {
|
||||
if diffFile.Name == "" {
|
||||
return diffFile.OldName
|
||||
}
|
||||
return diffFile.Name
|
||||
}
|
||||
|
||||
func (diffFile *DiffFile) ShouldBeHidden() bool {
|
||||
return diffFile.IsGenerated || diffFile.IsViewed
|
||||
}
|
||||
|
||||
func getCommitFileLineCount(commit *git.Commit, filePath string) int {
|
||||
blob, err := commit.GetBlobByPath(filePath)
|
||||
if err != nil {
|
||||
|
@ -677,10 +692,12 @@ func getCommitFileLineCount(commit *git.Commit, filePath string) int {
|
|||
|
||||
// Diff represents a difference between two git trees.
|
||||
type Diff struct {
|
||||
Start, End string
|
||||
NumFiles, TotalAddition, TotalDeletion int
|
||||
Files []*DiffFile
|
||||
IsIncomplete bool
|
||||
Start, End string
|
||||
NumFiles int
|
||||
TotalAddition, TotalDeletion int
|
||||
Files []*DiffFile
|
||||
IsIncomplete bool
|
||||
NumViewedFiles int // user-specific
|
||||
}
|
||||
|
||||
// LoadComments loads comments into each line
|
||||
|
@ -1497,6 +1514,70 @@ func GetDiff(gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff
|
|||
return diff, nil
|
||||
}
|
||||
|
||||
// SyncAndGetUserSpecificDiff is like GetDiff, except that user specific data such as which files the given user has already viewed on the given PR will also be set
|
||||
// Additionally, the database asynchronously is updated if files have changed since the last review
|
||||
func SyncAndGetUserSpecificDiff(ctx context.Context, userID int64, pull *models.PullRequest, gitRepo *git.Repository, opts *DiffOptions, files ...string) (*Diff, error) {
|
||||
diff, err := GetDiff(gitRepo, opts, files...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
review, err := pull_model.GetNewestReviewState(ctx, userID, pull.ID)
|
||||
if err != nil || review == nil || review.UpdatedFiles == nil {
|
||||
return diff, err
|
||||
}
|
||||
|
||||
latestCommit := opts.AfterCommitID
|
||||
if latestCommit == "" {
|
||||
latestCommit = pull.HeadBranch // opts.AfterCommitID is preferred because it handles PRs from forks correctly and the branch name doesn't
|
||||
}
|
||||
|
||||
changedFiles, err := gitRepo.GetFilesChangedBetween(review.CommitSHA, latestCommit)
|
||||
if err != nil {
|
||||
return diff, err
|
||||
}
|
||||
|
||||
filesChangedSinceLastDiff := make(map[string]pull_model.ViewedState)
|
||||
outer:
|
||||
for _, diffFile := range diff.Files {
|
||||
fileViewedState := review.UpdatedFiles[diffFile.GetDiffFileName()]
|
||||
|
||||
// Check whether it was previously detected that the file has changed since the last review
|
||||
if fileViewedState == pull_model.HasChanged {
|
||||
diffFile.HasChangedSinceLastReview = true
|
||||
continue
|
||||
}
|
||||
|
||||
filename := diffFile.GetDiffFileName()
|
||||
|
||||
// Check explicitly whether the file has changed since the last review
|
||||
for _, changedFile := range changedFiles {
|
||||
diffFile.HasChangedSinceLastReview = filename == changedFile
|
||||
if diffFile.HasChangedSinceLastReview {
|
||||
filesChangedSinceLastDiff[filename] = pull_model.HasChanged
|
||||
continue outer // We don't want to check if the file is viewed here as that would fold the file, which is in this case unwanted
|
||||
}
|
||||
}
|
||||
// Check whether the file has already been viewed
|
||||
if fileViewedState == pull_model.Viewed {
|
||||
diffFile.IsViewed = true
|
||||
diff.NumViewedFiles++
|
||||
}
|
||||
}
|
||||
|
||||
// Explicitly store files that have changed in the database, if any is present at all.
|
||||
// This has the benefit that the "Has Changed" attribute will be present as long as the user does not explicitly mark this file as viewed, so it will even survive a page reload after marking another file as viewed.
|
||||
// On the other hand, this means that even if a commit reverting an unseen change is committed, the file will still be seen as changed.
|
||||
if len(filesChangedSinceLastDiff) > 0 {
|
||||
err := pull_model.UpdateReviewState(ctx, review.UserID, review.PullID, review.CommitSHA, filesChangedSinceLastDiff)
|
||||
if err != nil {
|
||||
log.Warn("Could not update review for user %d, pull %d, commit %s and the changed files %v: %v", review.UserID, review.PullID, review.CommitSHA, filesChangedSinceLastDiff, err)
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
return diff, err
|
||||
}
|
||||
|
||||
// CommentAsDiff returns c.Patch as *Diff
|
||||
func CommentAsDiff(c *models.Comment) (*Diff, error) {
|
||||
diff, err := ParsePatch(setting.Git.MaxGitDiffLines,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue