Skip to content

Commit c36e6ad

Browse files
committed
Merge branch 'main' into add-file-tree-to-file-view-page
2 parents daa8282 + 0dfa94e commit c36e6ad

File tree

182 files changed

+15462
-29321
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

182 files changed

+15462
-29321
lines changed

.dockerignore

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -79,18 +79,6 @@ cpu.out
7979
/public/assets/fonts
8080
/public/assets/img/avatar
8181
/vendor
82-
/web_src/fomantic/node_modules
83-
/web_src/fomantic/build/*
84-
!/web_src/fomantic/build/semantic.js
85-
!/web_src/fomantic/build/semantic.css
86-
!/web_src/fomantic/build/themes
87-
/web_src/fomantic/build/themes/*
88-
!/web_src/fomantic/build/themes/default
89-
/web_src/fomantic/build/themes/default/assets/*
90-
!/web_src/fomantic/build/themes/default/assets/fonts
91-
/web_src/fomantic/build/themes/default/assets/fonts/*
92-
!/web_src/fomantic/build/themes/default/assets/fonts/icons.woff2
93-
!/web_src/fomantic/build/themes/default/assets/fonts/outline-icons.woff2
9482
/VERSION
9583
/.air
9684
/.go-licenses

.gitattributes

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,5 @@
55
/public/assets/img/svg/*.svg linguist-generated
66
/templates/swagger/v1_json.tmpl linguist-generated
77
/vendor/** -text -eol linguist-vendored
8-
/web_src/fomantic/build/** linguist-generated
9-
/web_src/fomantic/_site/globals/site.variables linguist-language=Less
108
/web_src/js/vendor/** -text -eol linguist-vendored
119
Dockerfile.* linguist-language=Dockerfile

.gitignore

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -84,18 +84,6 @@ cpu.out
8484
/public/assets/fonts
8585
/public/assets/licenses.txt
8686
/vendor
87-
/web_src/fomantic/node_modules
88-
/web_src/fomantic/build/*
89-
!/web_src/fomantic/build/semantic.js
90-
!/web_src/fomantic/build/semantic.css
91-
!/web_src/fomantic/build/themes
92-
/web_src/fomantic/build/themes/*
93-
!/web_src/fomantic/build/themes/default
94-
/web_src/fomantic/build/themes/default/assets/*
95-
!/web_src/fomantic/build/themes/default/assets/fonts
96-
/web_src/fomantic/build/themes/default/assets/fonts/*
97-
!/web_src/fomantic/build/themes/default/assets/fonts/icons.woff2
98-
!/web_src/fomantic/build/themes/default/assets/fonts/outline-icons.woff2
9987
/VERSION
10088
/.air
10189
/.go-licenses

Makefile

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -115,8 +115,6 @@ LINUX_ARCHS ?= linux/amd64,linux/386,linux/arm-5,linux/arm-6,linux/arm64
115115
GO_TEST_PACKAGES ?= $(filter-out $(shell $(GO) list code.gitea.io/gitea/models/migrations/...) code.gitea.io/gitea/tests/integration/migration-test code.gitea.io/gitea/tests code.gitea.io/gitea/tests/integration code.gitea.io/gitea/tests/e2e,$(shell $(GO) list ./... | grep -v /vendor/))
116116
MIGRATE_TEST_PACKAGES ?= $(shell $(GO) list code.gitea.io/gitea/models/migrations/...)
117117

118-
FOMANTIC_WORK_DIR := web_src/fomantic
119-
120118
WEBPACK_SOURCES := $(shell find web_src/js web_src/css -type f)
121119
WEBPACK_CONFIGS := webpack.config.js tailwind.config.js
122120
WEBPACK_DEST := public/assets/js/index.js public/assets/css/index.css
@@ -140,7 +138,7 @@ TAGS_EVIDENCE := $(MAKE_EVIDENCE_DIR)/tags
140138

141139
TEST_TAGS ?= $(TAGS_SPLIT) sqlite sqlite_unlock_notify
142140

143-
TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(FOMANTIC_WORK_DIR)/node_modules $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR) $(GO_LICENSE_TMP_DIR)
141+
TAR_EXCLUDES := .git data indexers queues log node_modules $(EXECUTABLE) $(DIST) $(MAKE_EVIDENCE_DIR) $(AIR_TMP_DIR) $(GO_LICENSE_TMP_DIR)
144142

145143
GO_DIRS := build cmd models modules routers services tests
146144
WEB_DIRS := web_src/js web_src/css
@@ -847,19 +845,6 @@ update-py: node-check | node_modules ## update py dependencies
847845
poetry install
848846
@touch .venv
849847

850-
.PHONY: fomantic
851-
fomantic: ## build fomantic files
852-
rm -rf $(FOMANTIC_WORK_DIR)/build
853-
cd $(FOMANTIC_WORK_DIR) && npm install --no-save
854-
cp -f $(FOMANTIC_WORK_DIR)/theme.config.less $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/theme.config
855-
cp -rf $(FOMANTIC_WORK_DIR)/_site $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/src/
856-
$(SED_INPLACE) -e 's/ overrideBrowserslist\r/ overrideBrowserslist: ["defaults"]\r/g' $(FOMANTIC_WORK_DIR)/node_modules/fomantic-ui/tasks/config/tasks.js
857-
cd $(FOMANTIC_WORK_DIR) && npx gulp -f node_modules/fomantic-ui/gulpfile.js build
858-
# fomantic uses "touchstart" as click event for some browsers, it's not ideal, so we force fomantic to always use "click" as click event
859-
$(SED_INPLACE) -e 's/clickEvent[ \t]*=/clickEvent = "click", unstableClickEvent =/g' $(FOMANTIC_WORK_DIR)/build/semantic.js
860-
$(SED_INPLACE) -e 's/\r//g' $(FOMANTIC_WORK_DIR)/build/semantic.css $(FOMANTIC_WORK_DIR)/build/semantic.js
861-
rm -f $(FOMANTIC_WORK_DIR)/build/*.min.*
862-
863848
.PHONY: webpack
864849
webpack: $(WEBPACK_DEST) ## build webpack files
865850

models/actions/run.go

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ func updateRepoRunsNumbers(ctx context.Context, repo *repo_model.Repository) err
194194

195195
// CancelPreviousJobs cancels all previous jobs of the same repository, reference, workflow, and event.
196196
// It's useful when a new run is triggered, and all previous runs needn't be continued anymore.
197-
func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) error {
197+
func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID string, event webhook_module.HookEventType) ([]*ActionRunJob, error) {
198198
// Find all runs in the specified repository, reference, and workflow with non-final status
199199
runs, total, err := db.FindAndCount[ActionRun](ctx, FindRunOptions{
200200
RepoID: repoID,
@@ -204,22 +204,24 @@ func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID strin
204204
Status: []Status{StatusRunning, StatusWaiting, StatusBlocked},
205205
})
206206
if err != nil {
207-
return err
207+
return nil, err
208208
}
209209

210210
// If there are no runs found, there's no need to proceed with cancellation, so return nil.
211211
if total == 0 {
212-
return nil
212+
return nil, nil
213213
}
214214

215+
cancelledJobs := make([]*ActionRunJob, 0, total)
216+
215217
// Iterate over each found run and cancel its associated jobs.
216218
for _, run := range runs {
217219
// Find all jobs associated with the current run.
218220
jobs, err := db.Find[ActionRunJob](ctx, FindRunJobOptions{
219221
RunID: run.ID,
220222
})
221223
if err != nil {
222-
return err
224+
return cancelledJobs, err
223225
}
224226

225227
// Iterate over each job and attempt to cancel it.
@@ -238,27 +240,29 @@ func CancelPreviousJobs(ctx context.Context, repoID int64, ref, workflowID strin
238240
// Update the job's status and stopped time in the database.
239241
n, err := UpdateRunJob(ctx, job, builder.Eq{"task_id": 0}, "status", "stopped")
240242
if err != nil {
241-
return err
243+
return cancelledJobs, err
242244
}
243245

244246
// If the update affected 0 rows, it means the job has changed in the meantime, so we need to try again.
245247
if n == 0 {
246-
return fmt.Errorf("job has changed, try again")
248+
return cancelledJobs, fmt.Errorf("job has changed, try again")
247249
}
248250

251+
cancelledJobs = append(cancelledJobs, job)
249252
// Continue with the next job.
250253
continue
251254
}
252255

253256
// If the job has an associated task, try to stop the task, effectively cancelling the job.
254257
if err := StopTask(ctx, job.TaskID, StatusCancelled); err != nil {
255-
return err
258+
return cancelledJobs, err
256259
}
260+
cancelledJobs = append(cancelledJobs, job)
257261
}
258262
}
259263

260264
// Return nil to indicate successful cancellation of all running and waiting jobs.
261-
return nil
265+
return cancelledJobs, nil
262266
}
263267

264268
// InsertRun inserts a run

models/actions/schedule.go

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -117,21 +117,22 @@ func DeleteScheduleTaskByRepo(ctx context.Context, id int64) error {
117117
return committer.Commit()
118118
}
119119

120-
func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) error {
120+
func CleanRepoScheduleTasks(ctx context.Context, repo *repo_model.Repository) ([]*ActionRunJob, error) {
121121
// If actions disabled when there is schedule task, this will remove the outdated schedule tasks
122122
// There is no other place we can do this because the app.ini will be changed manually
123123
if err := DeleteScheduleTaskByRepo(ctx, repo.ID); err != nil {
124-
return fmt.Errorf("DeleteCronTaskByRepo: %v", err)
124+
return nil, fmt.Errorf("DeleteCronTaskByRepo: %v", err)
125125
}
126126
// cancel running cron jobs of this repository and delete old schedules
127-
if err := CancelPreviousJobs(
127+
jobs, err := CancelPreviousJobs(
128128
ctx,
129129
repo.ID,
130130
repo.DefaultBranch,
131131
"",
132132
webhook_module.HookEventSchedule,
133-
); err != nil {
134-
return fmt.Errorf("CancelPreviousJobs: %v", err)
133+
)
134+
if err != nil {
135+
return jobs, fmt.Errorf("CancelPreviousJobs: %v", err)
135136
}
136-
return nil
137+
return jobs, nil
137138
}

models/webhook/webhook_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func TestWebhook_EventsArray(t *testing.T) {
7373
"pull_request", "pull_request_assign", "pull_request_label", "pull_request_milestone",
7474
"pull_request_comment", "pull_request_review_approved", "pull_request_review_rejected",
7575
"pull_request_review_comment", "pull_request_sync", "pull_request_review_request", "wiki", "repository", "release",
76-
"package", "status",
76+
"package", "status", "workflow_job",
7777
},
7878
(&Webhook{
7979
HookEvent: &webhook_module.HookEvent{SendEverything: true},

modules/fileicon/material.go

Lines changed: 48 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,6 @@ import (
1818
)
1919

2020
type materialIconRulesData struct {
21-
IconDefinitions map[string]*struct {
22-
IconPath string `json:"iconPath"`
23-
} `json:"iconDefinitions"`
2421
FileNames map[string]string `json:"fileNames"`
2522
FolderNames map[string]string `json:"folderNames"`
2623
FileExtensions map[string]string `json:"fileExtensions"`
@@ -36,6 +33,7 @@ type MaterialIconProvider struct {
3633
var materialIconProvider MaterialIconProvider
3734

3835
func DefaultMaterialIconProvider() *MaterialIconProvider {
36+
materialIconProvider.once.Do(materialIconProvider.loadData)
3937
return &materialIconProvider
4038
}
4139

@@ -64,7 +62,7 @@ func (m *MaterialIconProvider) loadData() {
6462
log.Debug("Loaded material icon rules and SVG images")
6563
}
6664

67-
func (m *MaterialIconProvider) renderFileIconSVG(ctx reqctx.RequestContext, name, svg string) template.HTML {
65+
func (m *MaterialIconProvider) renderFileIconSVG(ctx reqctx.RequestContext, name, svg, extraClass string) template.HTML {
6866
data := ctx.GetData()
6967
renderedSVGs, _ := data["_RenderedSVGs"].(map[string]bool)
7068
if renderedSVGs == nil {
@@ -77,7 +75,7 @@ func (m *MaterialIconProvider) renderFileIconSVG(ctx reqctx.RequestContext, name
7775
panic("Invalid SVG icon")
7876
}
7977
svgID := "svg-mfi-" + name
80-
svgCommonAttrs := `class="svg fileicon" width="16" height="16" aria-hidden="true"`
78+
svgCommonAttrs := `class="svg git-entry-icon ` + extraClass + `" width="16" height="16" aria-hidden="true"`
8179
posOuterBefore := strings.IndexByte(svg, '>')
8280
if renderedSVGs[svgID] && posOuterBefore != -1 {
8381
return template.HTML(`<svg ` + svgCommonAttrs + `><use xlink:href="#` + svgID + `"></use></svg>`)
@@ -88,63 +86,82 @@ func (m *MaterialIconProvider) renderFileIconSVG(ctx reqctx.RequestContext, name
8886
}
8987

9088
func (m *MaterialIconProvider) FileIcon(ctx reqctx.RequestContext, entry *git.TreeEntry) template.HTML {
91-
m.once.Do(m.loadData)
92-
9389
if m.rules == nil {
9490
return BasicThemeIcon(entry)
9591
}
9692

9793
if entry.IsLink() {
9894
if te, err := entry.FollowLink(); err == nil && te.IsDir() {
99-
return svg.RenderHTML("material-folder-symlink")
95+
// keep the old "octicon-xxx" class name to make some "theme plugin selector" could still work
96+
return svg.RenderHTML("material-folder-symlink", 16, "octicon-file-directory-symlink")
10097
}
10198
return svg.RenderHTML("octicon-file-symlink-file") // TODO: find some better icons for them
10299
}
103100

104-
name := m.findIconName(entry)
101+
name := m.findIconNameByGit(entry)
105102
if name == "folder" {
106103
// the material icon pack's "folder" icon doesn't look good, so use our built-in one
107-
return svg.RenderHTML("material-folder-generic")
104+
// keep the old "octicon-xxx" class name to make some "theme plugin selector" could still work
105+
return svg.RenderHTML("material-folder-generic", 16, "octicon-file-directory-fill")
108106
}
109107
if iconSVG, ok := m.svgs[name]; ok && iconSVG != "" {
110-
return m.renderFileIconSVG(ctx, name, iconSVG)
108+
// keep the old "octicon-xxx" class name to make some "theme plugin selector" could still work
109+
extraClass := "octicon-file"
110+
switch {
111+
case entry.IsDir():
112+
extraClass = "octicon-file-directory-fill"
113+
case entry.IsSubModule():
114+
extraClass = "octicon-file-submodule"
115+
}
116+
return m.renderFileIconSVG(ctx, name, iconSVG, extraClass)
111117
}
112118
return svg.RenderHTML("octicon-file")
113119
}
114120

115-
func (m *MaterialIconProvider) findIconName(entry *git.TreeEntry) string {
116-
if entry.IsSubModule() {
117-
return "folder-git"
121+
func (m *MaterialIconProvider) findIconNameWithLangID(s string) string {
122+
if _, ok := m.svgs[s]; ok {
123+
return s
118124
}
119-
120-
iconsData := m.rules
121-
fileName := path.Base(entry.Name())
122-
123-
if entry.IsDir() {
124-
if s, ok := iconsData.FolderNames[fileName]; ok {
125+
if s, ok := m.rules.LanguageIDs[s]; ok {
126+
if _, ok = m.svgs[s]; ok {
125127
return s
126128
}
127-
if s, ok := iconsData.FolderNames[strings.ToLower(fileName)]; ok {
129+
}
130+
return ""
131+
}
132+
133+
func (m *MaterialIconProvider) FindIconName(name string, isDir bool) string {
134+
fileNameLower := strings.ToLower(path.Base(name))
135+
if isDir {
136+
if s, ok := m.rules.FolderNames[fileNameLower]; ok {
128137
return s
129138
}
130139
return "folder"
131140
}
132141

133-
if s, ok := iconsData.FileNames[fileName]; ok {
134-
return s
135-
}
136-
if s, ok := iconsData.FileNames[strings.ToLower(fileName)]; ok {
137-
return s
142+
if s, ok := m.rules.FileNames[fileNameLower]; ok {
143+
if s = m.findIconNameWithLangID(s); s != "" {
144+
return s
145+
}
138146
}
139147

140-
for i := len(fileName) - 1; i >= 0; i-- {
141-
if fileName[i] == '.' {
142-
ext := fileName[i+1:]
143-
if s, ok := iconsData.FileExtensions[ext]; ok {
144-
return s
148+
for i := len(fileNameLower) - 1; i >= 0; i-- {
149+
if fileNameLower[i] == '.' {
150+
ext := fileNameLower[i+1:]
151+
if s, ok := m.rules.FileExtensions[ext]; ok {
152+
if s = m.findIconNameWithLangID(s); s != "" {
153+
return s
154+
}
145155
}
146156
}
147157
}
148158

149159
return "file"
150160
}
161+
162+
func (m *MaterialIconProvider) findIconNameByGit(entry *git.TreeEntry) string {
163+
if entry.IsSubModule() {
164+
return "folder-git"
165+
}
166+
return m.FindIconName(entry.Name(), entry.IsDir())
167+
}

modules/fileicon/material_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
// Copyright 2025 The Gitea Authors. All rights reserved.
2+
// SPDX-License-Identifier: MIT
3+
4+
package fileicon_test
5+
6+
import (
7+
"testing"
8+
9+
"code.gitea.io/gitea/models/unittest"
10+
"code.gitea.io/gitea/modules/fileicon"
11+
12+
"github.com/stretchr/testify/assert"
13+
)
14+
15+
func TestMain(m *testing.M) {
16+
unittest.MainTest(m, &unittest.TestOptions{FixtureFiles: []string{}})
17+
}
18+
19+
func TestFindIconName(t *testing.T) {
20+
unittest.PrepareTestEnv(t)
21+
p := fileicon.DefaultMaterialIconProvider()
22+
assert.Equal(t, "php", p.FindIconName("foo.php", false))
23+
assert.Equal(t, "php", p.FindIconName("foo.PHP", false))
24+
assert.Equal(t, "javascript", p.FindIconName("foo.js", false))
25+
assert.Equal(t, "visualstudio", p.FindIconName("foo.vba", false))
26+
}

modules/git/commit_info_nogogit.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath
6565
log.Debug("missing commit for %s", entry.Name())
6666
}
6767

68-
// If the entry if a submodule add a submodule file for this
68+
// If the entry is a submodule add a submodule file for this
6969
if entry.IsSubModule() {
7070
subModuleURL := ""
7171
var fullPath string
@@ -85,8 +85,8 @@ func (tes Entries) GetCommitsInfo(ctx context.Context, commit *Commit, treePath
8585
}
8686

8787
// Retrieve the commit for the treePath itself (see above). We basically
88-
// get it for free during the tree traversal and it's used for listing
89-
// pages to display information about newest commit for a given path.
88+
// get it for free during the tree traversal, and it's used for listing
89+
// pages to display information about the newest commit for a given path.
9090
var treeCommit *Commit
9191
var ok bool
9292
if treePath == "" {

0 commit comments

Comments
 (0)