Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Show branches and tags that contain a commit #25180

Merged
merged 45 commits into from
Jul 27, 2023
Merged
Show file tree
Hide file tree
Changes from 35 commits
Commits
Show all changes
45 commits
Select commit Hold shift + click to select a range
60cc93e
Add barebones frontend structure
delvh Jun 6, 2023
1975e64
Add complete backend for loading tags and branches of a commit
delvh Jun 9, 2023
ff62d3c
Merge branch 'main' into feature/load-referencing-branches-and-tags
delvh Jun 9, 2023
8adb11b
Complete the frontend and backend functionality
delvh Jun 9, 2023
be8cd4e
Make all borders rounded, increase margin between tags and commits
delvh Jun 9, 2023
b311b53
Remove dead code
delvh Jun 9, 2023
0b39f9e
Move translation key and print error on browser console
delvh Jun 9, 2023
a433b56
Apparently, I don't like our too strict linter
delvh Jun 9, 2023
73f31f8
Hopefully, please linter this time
delvh Jun 9, 2023
9599991
Linter: 3, delvh: 0
delvh Jun 9, 2023
83b9251
Use a better icon for the button as per @silverwind
delvh Jun 9, 2023
ef53879
Linter: 4, delvh: 0
delvh Jun 9, 2023
c87b361
Align branches/tags on their respective icon as per @silverwind + @KN…
delvh Jun 13, 2023
4e80dca
Merge branch 'main' into feature/load-referencing-branches-and-tags
silverwind Jun 13, 2023
7962907
I guess that's why the linter fails?
delvh Jun 13, 2023
e1efe08
Do not show branch/tag icon when this commit is not contained anywhere
delvh Jun 13, 2023
2b55713
Rename `response` -> `res`
delvh Jun 13, 2023
6983dc4
Batch add classes
delvh Jun 13, 2023
f75db06
`text` -> `textContent`
delvh Jun 13, 2023
c8ea65b
Convert "load" button to an ellipsis-button
delvh Jun 13, 2023
82d3222
Let's hope the linter likes the line-splitting
delvh Jun 13, 2023
d37c790
Split even more lines
delvh Jun 13, 2023
8d011d2
Remove information that is now redundant
delvh Jun 30, 2023
e3002bc
Merge branch 'main' into feature/load-referencing-branches-and-tags
delvh Jul 14, 2023
42712b5
Apparently the merge went wrong
delvh Jul 14, 2023
48c225e
Fix typo in translated string
delvh Jul 14, 2023
c9eba48
Merge branch 'main' into feature/load-referencing-branches-and-tags
silverwind Jul 16, 2023
0969a39
Implement suggestions by @wxiaoguang
delvh Jul 21, 2023
b009c77
Separate ellipsis-button into ellipsis-button and ellipsis-js-button
delvh Jul 21, 2023
97956cf
Fix formatting
delvh Jul 21, 2023
7206f0f
Improve formatting
delvh Jul 21, 2023
6818614
Merge branch 'main' into feature/load-referencing-branches-and-tags
delvh Jul 21, 2023
f335dd1
Merge branch 'main' into feature/load-referencing-branches-and-tags
delvh Jul 22, 2023
0012681
Merge branch 'main' into feature/load-referencing-branches-and-tags
delvh Jul 23, 2023
b0f5f48
Merge branch 'main' into feature/load-referencing-branches-and-tags
wxiaoguang Jul 26, 2023
e91843a
temp fix
wxiaoguang Jul 26, 2023
666a019
fix
wxiaoguang Jul 26, 2023
672f0bb
fix
wxiaoguang Jul 26, 2023
bf96470
fix
wxiaoguang Jul 26, 2023
e5effc8
rename
wxiaoguang Jul 26, 2023
c573def
revert the "icon" position
wxiaoguang Jul 26, 2023
23319d6
Merge branch 'main' into feature/load-referencing-branches-and-tags
delvh Jul 26, 2023
f17c4d4
Merge branch 'main' into feature/load-referencing-branches-and-tags
GiteaBot Jul 27, 2023
07a31b9
Merge branch 'main' into feature/load-referencing-branches-and-tags
GiteaBot Jul 27, 2023
d52dbd4
Merge branch 'main' into feature/load-referencing-branches-and-tags
GiteaBot Jul 27, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 0 additions & 26 deletions modules/git/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ import (

// Commit represents a git commit.
type Commit struct {
Branch string // Branch this commit belongs to
Tree
ID SHA1 // The ID of this commit object
Author *Signature
Expand Down Expand Up @@ -432,31 +431,6 @@ func (c *Commit) GetBranchName() (string, error) {
return strings.SplitN(strings.TrimSpace(data), "~", 2)[0], nil
}

// LoadBranchName load branch name for commit
func (c *Commit) LoadBranchName() (err error) {
if len(c.Branch) != 0 {
return nil
}

c.Branch, err = c.GetBranchName()
return err
}

// GetTagName gets the current tag name for given commit
func (c *Commit) GetTagName() (string, error) {
data, _, err := NewCommand(c.repo.Ctx, "describe", "--exact-match", "--tags", "--always").AddDynamicArguments(c.ID.String()).RunStdString(&RunOpts{Dir: c.repo.Path})
if err != nil {
// handle special case where there is no tag for this commit
if strings.Contains(err.Error(), "no tag exactly matches") {
return "", nil
}

return "", err
}

return strings.TrimSpace(data), nil
}

// CommitFileStatus represents status of files in a commit.
type CommitFileStatus struct {
Added []string
Expand Down
49 changes: 49 additions & 0 deletions modules/git/repo_ref.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,56 @@

package git

import (
"context"
"strings"

"code.gitea.io/gitea/modules/util"
)

// GetRefs returns all references of the repository.
func (repo *Repository) GetRefs() ([]*Reference, error) {
return repo.GetRefsFiltered("")
}

// ListOccurrences lists all refs of the given refType the given commit appears in sorted by creation date DESC
// refType should only be a literal "branch" or "tag" and nothing else
func (repo *Repository) ListOccurrences(ctx context.Context, refType, commitSHA string) ([]string, error) {
if refType != "branch" && refType != "tag" {
return nil, util.NewInvalidArgumentErrorf("Can only use branch or 'tag' as 'refType'. Got '%s'", refType)
}
stdout, _, err := NewCommand(ctx, ToTrustedCmdArgs([]string{refType, "--no-color", "--sort=-creatordate", "--contains"})...).AddDynamicArguments(commitSHA).RunStdString(&RunOpts{Dir: repo.Path})
delvh marked this conversation as resolved.
Show resolved Hide resolved
if err != nil {
return nil, err
}

refs := strings.Split(strings.TrimSpace(stdout), "\n")
if refType == "branch" {
return parseBranches(refs), nil
}
return parseTags(refs), nil
}

func parseBranches(refs []string) []string {
results := make([]string, 0, len(refs))
for _, ref := range refs {
if strings.HasPrefix(ref, "* ") { // current branch (main branch)
results = append(results, ref[len("* "):])
} else if strings.HasPrefix(ref, " ") { // all other branches
results = append(results, ref[len(" "):])
} else if ref != "" {
results = append(results, ref)
}
}
return results
}

func parseTags(refs []string) []string {
results := make([]string, 0, len(refs))
for _, ref := range refs {
if ref != "" {
results = append(results, ref)
}
}
return results
}
3 changes: 3 additions & 0 deletions options/locale/locale_en-US.ini
Original file line number Diff line number Diff line change
Expand Up @@ -1170,6 +1170,9 @@ commit_graph.select = Select branches
commit_graph.hide_pr_refs = Hide Pull Requests
commit_graph.monochrome = Mono
commit_graph.color = Color
commit.contained_in = This commit is contained in:
commit.contained_in_default_branch = This commit is part of the default branch
commit.load_referencing_branches_and_tags = Load branches and tags referencing this commit
blame = Blame
download_file = Download file
normal_view = Normal View
Expand Down
16 changes: 11 additions & 5 deletions routers/web/repo/commit.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ import (
"code.gitea.io/gitea/modules/gitgraph"
"code.gitea.io/gitea/modules/log"
"code.gitea.io/gitea/modules/setting"
"code.gitea.io/gitea/modules/util"
"code.gitea.io/gitea/services/gitdiff"
git_service "code.gitea.io/gitea/services/repository"
)

const (
Expand Down Expand Up @@ -255,6 +257,15 @@ func FileHistory(ctx *context.Context) {
ctx.HTML(http.StatusOK, tplCommits)
}

func LoadBranchesAndTags(ctx *context.Context) {
response, err := git_service.LoadBranchesAndTags(ctx, ctx.Repo, ctx.Params("sha"))
if err == nil {
ctx.JSON(http.StatusOK, response)
return
}
ctx.NotFoundOrServerError(fmt.Sprintf("could not load branches and tags the commit %s belongs to", ctx.Params("sha")), func(err error) bool { return errors.Is(err, util.ErrNotExist) }, err)
}

// Diff show different from current commit to previous commit
func Diff(ctx *context.Context) {
ctx.Data["PageIsDiff"] = true
Expand Down Expand Up @@ -374,11 +385,6 @@ func Diff(ctx *context.Context) {
return
}

ctx.Data["TagName"], err = commit.GetTagName()
if err != nil {
ctx.ServerError("commit.GetTagName", err)
return
}
ctx.HTML(http.StatusOK, tplCommitPage)
}

Expand Down
1 change: 1 addition & 0 deletions routers/web/web.go
Original file line number Diff line number Diff line change
Expand Up @@ -1336,6 +1336,7 @@ func registerRoutes(m *web.Route) {
m.Group("", func() {
m.Get("/graph", repo.Graph)
m.Get("/commit/{sha:([a-f0-9]{7,40})$}", repo.SetEditorconfigIfExists, repo.SetDiffViewStyle, repo.SetWhitespaceBehavior, repo.Diff)
m.Get("/commit/{sha:([a-f0-9]{7,40})$}/load-branches-and-tags", repo.LoadBranchesAndTags)
m.Get("/cherry-pick/{sha:([a-f0-9]{7,40})$}", repo.SetEditorconfigIfExists, repo.CherryPick)
}, repo.MustBeNotEmpty, context.RepoRef(), reqRepoCodeReader)

Expand Down
49 changes: 49 additions & 0 deletions services/repository/commit.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// Copyright 2023 The Gitea Authors. All rights reserved.
// SPDX-License-Identifier: MIT

package repository

import (
"context"
"fmt"

gitea_ctx "code.gitea.io/gitea/modules/context"
"code.gitea.io/gitea/modules/util"
)

type ContainedLinks struct { // TODO: better name?
Branches []*namedLink `json:"branches"`
Tags []*namedLink `json:"tags"`
ContainedInDefaultBranch bool `json:"contained_in_default_branch"`
DefaultBranch string `json:"default_branch"`
}

type namedLink struct { // TODO: better name?
Name string `json:"name"`
WebLink string `json:"web_link"`
}

// CreateNewBranch creates a new repository branch
func LoadBranchesAndTags(ctx context.Context, baseRepo *gitea_ctx.Repository, commitSHA string) (*ContainedLinks, error) {
containedTags, err := baseRepo.GitRepo.ListOccurrences(ctx, "tag", commitSHA)
if err != nil {
return nil, fmt.Errorf("encountered a problem while querying %s: %w", "tags", err)
}
containedBranches, err := baseRepo.GitRepo.ListOccurrences(ctx, "branch", commitSHA)
if err != nil {
return nil, fmt.Errorf("encountered a problem while querying %s: %w", "branches", err)
}

result := &ContainedLinks{
ContainedInDefaultBranch: util.SliceContains(containedBranches, baseRepo.Repository.DefaultBranch), DefaultBranch: baseRepo.Repository.DefaultBranch,
Branches: make([]*namedLink, 0, len(containedBranches)), Tags: make([]*namedLink, 0, len(containedTags)),
}
for _, tag := range containedTags {
result.Tags = append(result.Tags, &namedLink{Name: tag, WebLink: fmt.Sprintf("%s/src/tag/%s", baseRepo.RepoLink, util.PathEscapeSegments(tag))}) // TODO: Use a common method to get the link to a branch/tag instead of hardcoding it here
}
for _, branch := range containedBranches {
result.Branches = append(result.Branches, &namedLink{Name: branch, WebLink: fmt.Sprintf("%s/src/branch/%s", baseRepo.RepoLink, util.PathEscapeSegments(branch))})
}

return result, nil
}
13 changes: 13 additions & 0 deletions templates/repo/commit_load_branches_and_tags.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
<div class="branch-and-tag-area">
<button class="ui button ellipsis-button gt-mt-3 load-tags-and-branches" data-fetch-url="{{.RepoLink}}/commit/{{.CommitID}}/load-branches-and-tags" data-tooltip-content="{{.locale.Tr "repo.commit.load_referencing_branches_and_tags"}}" data-contained-in-text="{{.locale.Tr "repo.commit.contained_in"}}" aria-expanded="false">...</button>
delvh marked this conversation as resolved.
Show resolved Hide resolved
<div class="ui divider branch-tag-area-divider gt-hidden"></div>
<div class="branch-tag-area-text gt-df"></div>
<div class="branch-area-parent gt-df gt-ac gt-my-3 gt-gap-2 gt-hidden">
{{svg "octicon-git-branch" 16 "gt-min-w-16"}}
<div class="branch-area gt-df gt-ac gt-fw gt-hidden" data-defaultbranch-tooltip="{{.locale.Tr "repo.commit.contained_in_default_branch"}}"></div>
</div>
<div class="tag-area-parent gt-df gt-ac gt-my-3 gt-gap-2 gt-hidden">
{{svg "octicon-tag" 16 "gt-min-w-16"}}
<div class="tag-area gt-df gt-ac gt-fw gt-hidden"></div>
</div>
</div>
7 changes: 1 addition & 6 deletions templates/repo/commit_page.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -137,12 +137,7 @@
{{if IsMultilineCommitMessage .Commit.Message}}
<pre class="commit-body gt-mt-0">{{RenderCommitBody $.Context .Commit.Message $.RepoLink $.Repository.ComposeMetas}}</pre>
{{end}}
{{if .BranchName}}
<span class="text grey gt-mr-3">{{svg "octicon-git-branch" 16 "gt-mr-2"}}{{.BranchName}}</span>
{{end}}
{{if .TagName}}
<span class="text grey gt-mr-3">{{svg "octicon-tag" 16 "gt-mr-2"}}{{.TagName}}</span>
{{end}}
{{template "repo/commit_load_branches_and_tags" .}}
</div>
<div class="ui attached segment gt-df gt-ac gt-sb gt-py-2 commit-header-row gt-fw {{$class}}">
<div class="gt-df gt-ac author">
Expand Down
2 changes: 1 addition & 1 deletion templates/repo/commits_list.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@
{{end}}
</span>
{{if IsMultilineCommitMessage .Message}}
<button class="ui button ellipsis-button" aria-expanded="false">...</button>
<button class="ui button ellipsis-js-button ellipsis-button" aria-expanded="false">...</button>
{{end}}
{{template "repo/commit_statuses" dict "Status" .Status "Statuses" .Statuses "root" $}}
{{if IsMultilineCommitMessage .Message}}
Expand Down
2 changes: 1 addition & 1 deletion templates/repo/commits_list_small.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@

<span class="gt-mono commit-summary {{if gt .ParentCount 1}} grey text{{end}}" title="{{.Summary}}">{{RenderCommitMessageLinkSubject $.root.Context .Message ($.comment.Issue.PullRequest.BaseRepo.Link|Escape) $commitLink $.comment.Issue.PullRequest.BaseRepo.ComposeMetas}}</span>
{{if IsMultilineCommitMessage .Message}}
<button class="ui button ellipsis-button" aria-expanded="false">...</button>
<button class="ui button ellipsis-js-button ellipsis-button" aria-expanded="false">...</button>
{{end}}
{{if IsMultilineCommitMessage .Message}}
<pre class="commit-body gt-hidden">{{RenderCommitBody $.root.Context .Message ($.comment.Issue.PullRequest.BaseRepo.Link|Escape) $.comment.Issue.PullRequest.BaseRepo.ComposeMetas}}</pre>
Expand Down
2 changes: 1 addition & 1 deletion templates/repo/view_list.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
{{$commitLink:= printf "%s/commit/%s" .RepoLink (PathEscape .LatestCommit.ID.String)}}
<span class="grey commit-summary" title="{{.LatestCommit.Summary}}"><span class="message-wrapper">{{RenderCommitMessageLinkSubject $.Context .LatestCommit.Message $.RepoLink $commitLink $.Repository.ComposeMetas}}</span>
{{if IsMultilineCommitMessage .LatestCommit.Message}}
<button class="ui button ellipsis-button" aria-expanded="false">...</button>
<button class="ui button ellipsis-js-button ellipsis-button" aria-expanded="false">...</button>
<pre class="commit-body gt-hidden">{{RenderCommitBody $.Context .LatestCommit.Message $.RepoLink $.Repository.ComposeMetas}}</pre>
{{end}}
</span>
Expand Down
3 changes: 3 additions & 0 deletions web_src/css/helpers.css
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ Gitea's private styles use `g-` prefix.
.gt-w-screen { width: 100vw !important; }
.gt-h-screen { height: 100vh !important; }

.gt-min-w-0 { min-width: 0 !important; }
.gt-min-w-16 { min-width: 16px !important; } /*There are some weird bugs with flexboxes and SVGs where the svgs shrink into oblivion*/

.gt-float-left { float: left !important; }
.gt-float-right { float: right !important; }
.gt-clear-both { clear: both !important; }
Expand Down
77 changes: 77 additions & 0 deletions web_src/js/features/load-branches-and-tags.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
import {showElem} from '../utils/dom.js';

async function loadBranchesAndTags(loadingButton, addHere) {
loadingButton.classList.add('disabled');
let res;
try {
res = await fetch(loadingButton.getAttribute('data-fetch-url'), {
method: 'GET',
});
} finally {
loadingButton.classList.remove('disabled');
}

if (!res.ok) {
return;
}

const data = await res.json();
showAreas('.branch-tag-area-divider');
loadingButton.classList.add('gt-hidden');
addHere.querySelector('.branch-tag-area-text').textContent =
loadingButton.getAttribute('data-contained-in-text');
addTags(data.tags, addHere.querySelector('.tag-area'));
const branchArea = addHere.querySelector('.branch-area');
addBranches(
data.branches,
data.default_branch,
branchArea.getAttribute('data-defaultbranch-tooltip'),
branchArea,
);
}

function addTags(tags, addHere) {
if (tags.length > 0) showAreas('.tag-area,.tag-area-parent');
for (const tag of tags) {
addLink(tag.web_link, tag.name, addHere);
}
}

function addBranches(branches, defaultBranch, defaultBranchTooltip, addHere) {
if (branches.length > 0) showAreas('.branch-area,.branch-area-parent');
for (const branch of branches) {
addLink(
branch.web_link,
branch.name,
addHere,
defaultBranch === branch.name ? defaultBranchTooltip : undefined,
);
}
}

function showAreas(selector) {
for (const branchArea of document.querySelectorAll(selector)) showElem(branchArea);
}

function addLink(href, text, addHere, tooltip) {
const link = document.createElement('a');
link.classList.add('muted', 'gt-px-3', 'gt-rounded');
if (tooltip) {
link.classList.add('gt-border-secondary');
link.setAttribute('data-tooltip-content', tooltip);
}
link.href = href;
link.textContent = text;
addHere.append(link);
}

export function initLoadBranchesAndTagsButton() {
for (const loadButton of document.querySelectorAll('.load-tags-and-branches')) {
wxiaoguang marked this conversation as resolved.
Show resolved Hide resolved
loadButton.addEventListener('click', () => {
loadBranchesAndTags(
loadButton,
document.querySelector('.branch-and-tag-area'),
);
});
}
}
2 changes: 1 addition & 1 deletion web_src/js/features/repo-commit.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {toggleElem} from '../utils/dom.js';
const {csrfToken} = window.config;

export function initRepoEllipsisButton() {
$('.ellipsis-button').on('click', function (e) {
$('.ellipsis-js-button').on('click', function (e) {
e.preventDefault();
const expanded = $(this).attr('aria-expanded') === 'true';
toggleElem($(this).parent().find('.commit-body'));
Expand Down
3 changes: 3 additions & 0 deletions web_src/js/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ import {initGiteaFomantic} from './modules/fomantic.js';
import {onDomReady} from './utils/dom.js';
import {initRepoIssueList} from './features/repo-issue-list.js';
import {initCommonIssueListQuickGoto} from './features/common-issue-list.js';
import {initLoadBranchesAndTagsButton} from './features/load-branches-and-tags.js';

// Init Gitea's Fomantic settings
initGiteaFomantic();
Expand Down Expand Up @@ -179,4 +180,6 @@ onDomReady(() => {
initRepoDiffView();
initPdfViewer();
initScopedAccessTokenCategories();
delvh marked this conversation as resolved.
Show resolved Hide resolved

initLoadBranchesAndTagsButton();
delvh marked this conversation as resolved.
Show resolved Hide resolved
});
Loading