Use full-file highlighting for diff sections (#36561)

* Fix #35252
* Fix #35999
* Improve diff rendering, don't add unnecessary "added"/"removed" tags for a full-line change
* Also fix a "space trimming" bug in #36539 and add tests
* Use chroma "SQL" lexer instead of "MySQL" to workaround a bug (35999)
This commit is contained in:
wxiaoguang
2026-02-10 11:29:28 +08:00
committed by GitHub
parent 269bc1b112
commit 8cc8150922
15 changed files with 391 additions and 192 deletions
+3 -3
View File
@@ -12,7 +12,7 @@ import (
)
// GetDiffPreview produces and returns diff result of a file which is not yet committed.
func GetDiffPreview(ctx context.Context, repo *repo_model.Repository, branch, treePath, content string) (*gitdiff.Diff, error) {
func GetDiffPreview(ctx context.Context, repo *repo_model.Repository, branch, treePath, oldContent, newContent string) (*gitdiff.Diff, error) {
if branch == "" {
branch = repo.DefaultBranch
}
@@ -29,7 +29,7 @@ func GetDiffPreview(ctx context.Context, repo *repo_model.Repository, branch, tr
}
// Add the object to the database
objectHash, err := t.HashObjectAndWrite(ctx, strings.NewReader(content))
objectHash, err := t.HashObjectAndWrite(ctx, strings.NewReader(newContent))
if err != nil {
return nil, err
}
@@ -38,5 +38,5 @@ func GetDiffPreview(ctx context.Context, repo *repo_model.Repository, branch, tr
if err := t.AddObjectToIndex(ctx, "100644", objectHash, treePath); err != nil {
return nil, err
}
return t.DiffIndex(ctx)
return t.DiffIndex(ctx, oldContent, newContent)
}
+26 -38
View File
@@ -27,8 +27,30 @@ func TestGetDiffPreview(t *testing.T) {
branch := ctx.Repo.Repository.DefaultBranch
treePath := "README.md"
oldContent := "# repo1\n\nDescription for repo1"
content := "# repo1\n\nDescription for repo1\nthis is a new line"
t.Run("Errors", func(t *testing.T) {
t.Run("empty repo", func(t *testing.T) {
diff, err := GetDiffPreview(ctx, &repo_model.Repository{}, branch, treePath, oldContent, content)
assert.Nil(t, diff)
assert.EqualError(t, err, "repository does not exist [id: 0, uid: 0, owner_name: , name: ]")
})
t.Run("bad branch", func(t *testing.T) {
badBranch := "bad_branch"
diff, err := GetDiffPreview(ctx, ctx.Repo.Repository, badBranch, treePath, oldContent, content)
assert.Nil(t, diff)
assert.EqualError(t, err, "branch does not exist [name: "+badBranch+"]")
})
t.Run("empty treePath", func(t *testing.T) {
diff, err := GetDiffPreview(ctx, ctx.Repo.Repository, branch, "", oldContent, content)
assert.Nil(t, diff)
assert.EqualError(t, err, "path is invalid [path: ]")
})
})
expectedDiff := &gitdiff.Diff{
Files: []*gitdiff.DiffFile{
{
@@ -112,56 +134,22 @@ func TestGetDiffPreview(t *testing.T) {
}
t.Run("with given branch", func(t *testing.T) {
diff, err := GetDiffPreview(ctx, ctx.Repo.Repository, branch, treePath, content)
diff, err := GetDiffPreview(ctx, ctx.Repo.Repository, branch, treePath, oldContent, content)
assert.NoError(t, err)
expectedBs, err := json.Marshal(expectedDiff)
assert.NoError(t, err)
bs, err := json.Marshal(diff)
assert.NoError(t, err)
assert.Equal(t, string(expectedBs), string(bs))
assert.JSONEq(t, string(expectedBs), string(bs))
})
t.Run("empty branch, same results", func(t *testing.T) {
diff, err := GetDiffPreview(ctx, ctx.Repo.Repository, "", treePath, content)
diff, err := GetDiffPreview(ctx, ctx.Repo.Repository, "", treePath, oldContent, content)
assert.NoError(t, err)
expectedBs, err := json.Marshal(expectedDiff)
assert.NoError(t, err)
bs, err := json.Marshal(diff)
assert.NoError(t, err)
assert.Equal(t, expectedBs, bs)
})
}
func TestGetDiffPreviewErrors(t *testing.T) {
unittest.PrepareTestEnv(t)
ctx, _ := contexttest.MockContext(t, "user2/repo1")
ctx.SetPathParam("id", "1")
contexttest.LoadRepo(t, ctx, 1)
contexttest.LoadRepoCommit(t, ctx)
contexttest.LoadUser(t, ctx, 2)
contexttest.LoadGitRepo(t, ctx)
defer ctx.Repo.GitRepo.Close()
branch := ctx.Repo.Repository.DefaultBranch
treePath := "README.md"
content := "# repo1\n\nDescription for repo1\nthis is a new line"
t.Run("empty repo", func(t *testing.T) {
diff, err := GetDiffPreview(ctx, &repo_model.Repository{}, branch, treePath, content)
assert.Nil(t, diff)
assert.EqualError(t, err, "repository does not exist [id: 0, uid: 0, owner_name: , name: ]")
})
t.Run("bad branch", func(t *testing.T) {
badBranch := "bad_branch"
diff, err := GetDiffPreview(ctx, ctx.Repo.Repository, badBranch, treePath, content)
assert.Nil(t, diff)
assert.EqualError(t, err, "branch does not exist [name: "+badBranch+"]")
})
t.Run("empty treePath", func(t *testing.T) {
diff, err := GetDiffPreview(ctx, ctx.Repo.Repository, branch, "", content)
assert.Nil(t, diff)
assert.EqualError(t, err, "path is invalid [path: ]")
assert.JSONEq(t, string(expectedBs), string(bs))
})
}
+4 -1
View File
@@ -361,7 +361,7 @@ func (t *TemporaryUploadRepository) Push(ctx context.Context, doer *user_model.U
}
// DiffIndex returns a Diff of the current index to the head
func (t *TemporaryUploadRepository) DiffIndex(ctx context.Context) (*gitdiff.Diff, error) {
func (t *TemporaryUploadRepository) DiffIndex(ctx context.Context, oldContent, newContent string) (*gitdiff.Diff, error) {
var diff *gitdiff.Diff
cmd := gitcmd.NewCommand("diff-index", "--src-prefix=\\a/", "--dst-prefix=\\b/", "--cached", "-p", "HEAD")
stdoutReader, stdoutReaderClose := cmd.MakeStdoutPipe()
@@ -383,6 +383,9 @@ func (t *TemporaryUploadRepository) DiffIndex(ctx context.Context) (*gitdiff.Dif
return nil, fmt.Errorf("unable to run diff-index pipeline in temporary repo: %w", err)
}
if len(diff.Files) > 0 {
gitdiff.FillDiffFileHighlightLinesByContent(diff.Files[0], util.UnsafeStringToBytes(oldContent), util.UnsafeStringToBytes(newContent))
}
return diff, nil
}