Compare commits

...

15 Commits

Author SHA1 Message Date
Thomas Sayen
f36c6c58f6
Merge 0bbfaef053a0e40924c70baec8ff4f43630a0a1a into 1d4ad5aa2b3a321a8d759bb91fc78e0aa6a89ed9 2025-07-01 14:00:44 -03:00
Thomas Sayen
0bbfaef053 Use tailwind style instead of inline style
Co-authored-by: silverwind <me@silverwind.io>
2025-06-23 10:16:33 +02:00
Thomas Sayen
0991eb3839 Replace location by window.location + removed useless .toString()
Co-authored-by: silverwind <me@silverwind.io>
2025-06-23 10:16:25 +02:00
Thomas Sayen
a9d4c149f6 Fixed go linting 2025-06-23 10:16:17 +02:00
Thomas Sayen
308119f1c7 Uses git rev-list when no rename follow 2025-06-23 10:16:10 +02:00
Thomas Sayen
2acc230cf0 Updated URL search params manipulation 2025-06-23 10:16:03 +02:00
Thomas Sayen
bb6778500f Removed jquery 2025-06-23 10:15:54 +02:00
Thomas Sayen
8cef3d3217 Fixed linting 2025-06-23 10:15:45 +02:00
Thomas Sayen
6c62a513e8 Add small spacing between checkbox and label 2025-06-23 10:15:38 +02:00
Thomas Sayen
5684f5e707 Localized history follow rename checkbox 2025-06-23 10:15:30 +02:00
Thomas Sayen
8c9518c130 Fixed command creation 2025-06-23 10:15:23 +02:00
Thomas Sayen
8de55d67c1 Added checkbox to follow renames in history 2025-06-23 10:15:16 +02:00
Thomas Sayen
88d70d305b Fixed commit count 2025-06-23 10:15:08 +02:00
Thomas Sayen
22f63d918f Fix last commit discarded 2025-06-23 10:14:40 +02:00
Thomas Sayen
19028303b1 Use git log instead of git rev-list 2025-06-23 10:14:27 +02:00
7 changed files with 83 additions and 27 deletions

View File

@ -169,11 +169,19 @@ type CommitsCountOptions struct {
RelPath []string RelPath []string
Since string Since string
Until string Until string
FollowRename bool
} }
// CommitsCount returns number of total commits of until given revision. // CommitsCount returns number of total commits of until given revision.
func CommitsCount(ctx context.Context, opts CommitsCountOptions) (int64, error) { func CommitsCount(ctx context.Context, opts CommitsCountOptions) (int64, error) {
cmd := NewCommand("rev-list", "--count") var cmd *Command
followRename := len(opts.RelPath) > 0 && opts.FollowRename
if followRename {
cmd = NewCommand("--no-pager", "log", "--pretty=format:%H")
} else {
cmd = NewCommand("rev-list", "--count")
}
cmd.AddDynamicArguments(opts.Revision...) cmd.AddDynamicArguments(opts.Revision...)
@ -182,6 +190,9 @@ func CommitsCount(ctx context.Context, opts CommitsCountOptions) (int64, error)
} }
if len(opts.RelPath) > 0 { if len(opts.RelPath) > 0 {
if opts.FollowRename {
cmd.AddOptionValues("--follow")
}
cmd.AddDashesAndList(opts.RelPath...) cmd.AddDashesAndList(opts.RelPath...)
} }
@ -189,7 +200,9 @@ func CommitsCount(ctx context.Context, opts CommitsCountOptions) (int64, error)
if err != nil { if err != nil {
return 0, err return 0, err
} }
if followRename {
return int64(len(strings.Split(stdout, "\n"))), nil
}
return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64) return strconv.ParseInt(strings.TrimSpace(stdout), 10, 64)
} }

View File

@ -205,12 +205,18 @@ func (repo *Repository) FileChangedBetweenCommits(filename, id1, id2 string) (bo
} }
// FileCommitsCount return the number of files at a revision // FileCommitsCount return the number of files at a revision
func (repo *Repository) FileCommitsCount(revision, file string) (int64, error) { func (repo *Repository) FileCommitsCount(revision, file string, followRename ...bool) (int64, error) {
_followRename := false
if len(followRename) > 0 {
_followRename = followRename[0]
}
return CommitsCount(repo.Ctx, return CommitsCount(repo.Ctx,
CommitsCountOptions{ CommitsCountOptions{
RepoPath: repo.Path, RepoPath: repo.Path,
Revision: []string{revision}, Revision: []string{revision},
RelPath: []string{file}, RelPath: []string{file},
FollowRename: _followRename,
}) })
} }
@ -221,6 +227,7 @@ type CommitsByFileAndRangeOptions struct {
Page int Page int
Since string Since string
Until string Until string
FollowRename bool
} }
// CommitsByFileAndRange return the commits according revision file and the page // CommitsByFileAndRange return the commits according revision file and the page
@ -232,9 +239,18 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions)
}() }()
go func() { go func() {
stderr := strings.Builder{} stderr := strings.Builder{}
gitCmd := NewCommand("rev-list"). var gitCmd *Command
AddOptionFormat("--max-count=%d", setting.Git.CommitsRangeSize).
if !opts.FollowRename {
gitCmd = NewCommand("rev-list")
} else {
gitCmd = NewCommand("--no-pager", "log").
AddOptionFormat("--pretty=format:%%H").
AddOptionFormat("--follow")
}
gitCmd.AddOptionFormat("--max-count=%d", setting.Git.CommitsRangeSize).
AddOptionFormat("--skip=%d", (opts.Page-1)*setting.Git.CommitsRangeSize) AddOptionFormat("--skip=%d", (opts.Page-1)*setting.Git.CommitsRangeSize)
gitCmd.AddDynamicArguments(opts.Revision) gitCmd.AddDynamicArguments(opts.Revision)
if opts.Not != "" { if opts.Not != "" {
@ -253,7 +269,8 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions)
Stdout: stdoutWriter, Stdout: stdoutWriter,
Stderr: &stderr, Stderr: &stderr,
}) })
if err != nil {
if err != nil && !(opts.FollowRename && err == io.ErrUnexpectedEOF) {
_ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String())) _ = stdoutWriter.CloseWithError(ConcatenateError(err, (&stderr).String()))
} else { } else {
_ = stdoutWriter.Close() _ = stdoutWriter.Close()
@ -270,7 +287,7 @@ func (repo *Repository) CommitsByFileAndRange(opts CommitsByFileAndRangeOptions)
shaline := make([]byte, length+1) shaline := make([]byte, length+1)
for { for {
n, err := io.ReadFull(stdoutReader, shaline) n, err := io.ReadFull(stdoutReader, shaline)
if err != nil || n < length { if (err != nil && !(opts.FollowRename && err == io.ErrUnexpectedEOF)) || n < length {
if err == io.EOF { if err == io.EOF {
err = nil err = nil
} }

View File

@ -1408,6 +1408,7 @@ editor.fork_branch_exists = Branch "%s" already exists in your fork, please choo
commits.desc = Browse source code change history. commits.desc = Browse source code change history.
commits.commits = Commits commits.commits = Commits
commits.history_follow_rename = Include renames
commits.no_commits = No commits in common. "%s" and "%s" have entirely different histories. commits.no_commits = No commits in common. "%s" and "%s" have entirely different histories.
commits.nothing_to_compare = These branches are equal. commits.nothing_to_compare = These branches are equal.
commits.search.tooltip = You can prefix keywords with "author:", "committer:", "after:", or "before:", e.g. "revert author:Alice before:2019-01-13". commits.search.tooltip = You can prefix keywords with "author:", "committer:", "after:", or "before:", e.g. "revert author:Alice before:2019-01-13".

View File

@ -213,12 +213,14 @@ func SearchCommits(ctx *context.Context) {
// FileHistory show a file's reversions // FileHistory show a file's reversions
func FileHistory(ctx *context.Context) { func FileHistory(ctx *context.Context) {
followRename := strings.Contains(ctx.Req.RequestURI, "history_follow_rename=true")
if ctx.Repo.TreePath == "" { if ctx.Repo.TreePath == "" {
Commits(ctx) Commits(ctx)
return return
} }
commitsCount, err := ctx.Repo.GitRepo.FileCommitsCount(ctx.Repo.RefFullName.ShortName(), ctx.Repo.TreePath) commitsCount, err := ctx.Repo.GitRepo.FileCommitsCount(ctx.Repo.RefFullName.ShortName(), ctx.Repo.TreePath, followRename)
if err != nil { if err != nil {
ctx.ServerError("FileCommitsCount", err) ctx.ServerError("FileCommitsCount", err)
return return
@ -234,6 +236,7 @@ func FileHistory(ctx *context.Context) {
Revision: ctx.Repo.RefFullName.ShortName(), // FIXME: legacy code used ShortName Revision: ctx.Repo.RefFullName.ShortName(), // FIXME: legacy code used ShortName
File: ctx.Repo.TreePath, File: ctx.Repo.TreePath,
Page: page, Page: page,
FollowRename: followRename,
}) })
if err != nil { if err != nil {
ctx.ServerError("CommitsByFileAndRange", err) ctx.ServerError("CommitsByFileAndRange", err)

View File

@ -8,6 +8,10 @@
{{ctx.Locale.Tr "repo.commits.no_commits" $.BaseBranch $.HeadBranch}} {{ctx.Locale.Tr "repo.commits.no_commits" $.BaseBranch $.HeadBranch}}
{{end}} {{end}}
</div> </div>
<div class="commits-table-left tw-flex tw-items-center">
<input type="checkbox" name="history-enable-follow-renames" class="tw-mr-[5px]"/>
<label for="history-enable-follow-renames">{{ctx.Locale.Tr "repo.commits.history_follow_rename"}}</label>
</div>
{{if .IsDiffCompare}} {{if .IsDiffCompare}}
<div class="commits-table-right tw-whitespace-nowrap"> <div class="commits-table-right tw-whitespace-nowrap">
<a href="{{$.CommitRepoLink}}/commit/{{.BeforeCommitID | PathEscape}}" class="ui green sha label tw-mx-0">{{if not .BaseIsCommit}}{{if .BaseIsBranch}}{{svg "octicon-git-branch"}}{{else if .BaseIsTag}}{{svg "octicon-tag"}}{{end}}{{.BaseBranch}}{{else}}{{ShortSha .BaseBranch}}{{end}}</a> <a href="{{$.CommitRepoLink}}/commit/{{.BeforeCommitID | PathEscape}}" class="ui green sha label tw-mx-0">{{if not .BaseIsCommit}}{{if .BaseIsBranch}}{{svg "octicon-git-branch"}}{{else if .BaseIsTag}}{{svg "octicon-tag"}}{{end}}{{.BaseBranch}}{{else}}{{ShortSha .BaseBranch}}{{end}}</a>

View File

@ -24,3 +24,20 @@ export function initCommitStatuses() {
}); });
}); });
} }
export function initCommitFileHistoryFollowRename() {
const checkbox : HTMLInputElement | null = document.querySelector('input[name=history-enable-follow-renames]');
if (!checkbox) {
return;
}
const url = new URL(window.location.toString());
checkbox.checked = url.searchParams.has('history_follow_rename', 'true');
checkbox.addEventListener('change', () => {
const url = new URL(window.location);
url.searchParams.set('history_follow_rename', `${checkbox.checked}`);
window.location.replace(url);
});
}

View File

@ -22,7 +22,7 @@ import {initMarkupContent} from './markup/content.ts';
import {initRepoFileView} from './features/file-view.ts'; import {initRepoFileView} from './features/file-view.ts';
import {initUserAuthOauth2, initUserCheckAppUrl} from './features/user-auth.ts'; import {initUserAuthOauth2, initUserCheckAppUrl} from './features/user-auth.ts';
import {initRepoPullRequestAllowMaintainerEdit, initRepoPullRequestReview, initRepoIssueSidebarDependency, initRepoIssueFilterItemLabel} from './features/repo-issue.ts'; import {initRepoPullRequestAllowMaintainerEdit, initRepoPullRequestReview, initRepoIssueSidebarDependency, initRepoIssueFilterItemLabel} from './features/repo-issue.ts';
import {initRepoEllipsisButton, initCommitStatuses} from './features/repo-commit.ts'; import {initRepoEllipsisButton, initCommitStatuses, initCommitFileHistoryFollowRename} from './features/repo-commit.ts';
import {initRepoTopicBar} from './features/repo-home.ts'; import {initRepoTopicBar} from './features/repo-home.ts';
import {initAdminCommon} from './features/admin/common.ts'; import {initAdminCommon} from './features/admin/common.ts';
import {initRepoCodeView} from './features/repo-code.ts'; import {initRepoCodeView} from './features/repo-code.ts';
@ -151,6 +151,7 @@ onDomReady(() => {
initRepoRecentCommits, initRepoRecentCommits,
initCommitStatuses, initCommitStatuses,
initCommitFileHistoryFollowRename,
initCaptcha, initCaptcha,
initUserCheckAppUrl, initUserCheckAppUrl,