Skip to content

Commit a84a9ef

Browse files
authored
Merge branch 'main' into improve-dropdown-a11y
2 parents 82ff90e + 43809e6 commit a84a9ef

File tree

398 files changed

+875
-631
lines changed

Some content is hidden

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

398 files changed

+875
-631
lines changed

MAINTAINERS

-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ Kees de Vries <[email protected]> (@Bwko)
55
Kim Carlbäcker <[email protected]> (@bkcsoft)
66
LefsFlare <[email protected]> (@LefsFlarey)
77
Lunny Xiao <[email protected]> (@lunny)
8-
Matthias Loibl <[email protected]> (@metalmatze)
98
Rachid Zarouali <[email protected]> (@xinity)
109
Rémy Boulanouar <[email protected]> (@DblK)
1110
Sandro Santilli <[email protected]> (@strk)

build/generate-svg.js

+10-2
Original file line numberDiff line numberDiff line change
@@ -25,14 +25,22 @@ async function processFile(file, {prefix, fullName} = {}) {
2525
if (prefix === 'octicon') name = name.replace(/-[0-9]+$/, ''); // chop of '-16' on octicons
2626
}
2727

28+
// Set the `xmlns` attribute so that the files are displayable in standalone documents
29+
// The svg backend module will strip the attribute during startup for inline display
2830
const {data} = optimize(await readFile(file, 'utf8'), {
2931
plugins: [
3032
{name: 'preset-default'},
31-
{name: 'removeXMLNS'},
3233
{name: 'removeDimensions'},
3334
{name: 'prefixIds', params: {prefix: () => name}},
3435
{name: 'addClassesToSVGElement', params: {classNames: ['svg', name]}},
35-
{name: 'addAttributesToSVGElement', params: {attributes: [{'width': '16'}, {'height': '16'}, {'aria-hidden': 'true'}]}},
36+
{
37+
name: 'addAttributesToSVGElement', params: {
38+
attributes: [
39+
{'xmlns': 'http://www.w3.org/2000/svg'},
40+
{'width': '16'}, {'height': '16'}, {'aria-hidden': 'true'},
41+
]
42+
}
43+
},
3644
],
3745
});
3846

docs/content/doc/usage/pull-request.en-us.md

+37-1
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,45 @@ menu:
1515

1616
# Pull Request
1717

18+
A Pull Request (PR) is a way to propose changes to a repository.
19+
It is a request to merge one branch into another, accompanied by a description of the changes that were made.
20+
Pull Requests are commonly used as a way for contributors to propose changes and for maintainers to review and merge those changes.
21+
22+
## Creating a pull request
23+
24+
To create a PR, you'll need to follow these steps:
25+
26+
1. **Fork the repository** - If you don't have permission to make changes to the repository directly, you'll need to fork the repository to your own account.
27+
This creates a copy of the repository that you can make changes to.
28+
29+
2. **Create a branch (optional)** - Create a new branch on your forked repository that contains the changes you want to propose.
30+
Give the branch a descriptive name that indicates what the changes are for.
31+
32+
3. **Make your changes** - Make the changes you want, commit, and push them to your forked repository.
33+
34+
4. **Create the PR** - Go to the original repository and go to the "Pull Requests" tab. Click the "New Pull Request" button and select your new branch as the source branch.
35+
Enter a descriptive title and description for your Pull Request and click "Create Pull Request".
36+
37+
## Reviewing a pull request
38+
39+
When a PR is created, it triggers a review process. The maintainers of the repository are notified of the PR and can review the changes that were made.
40+
They can leave comments, request changes, or approve the changes.
41+
42+
If the maintainers request changes, you'll need to make those changes in your branch and push the changes to your forked repository.
43+
The PR will be updated automatically with the new changes.
44+
45+
If the maintainers approve the changes, they can merge the PR into the repository.
46+
47+
## Closing a pull request
48+
49+
If you decide that you no longer want to merge a PR, you can close it.
50+
To close a PR, go to the open PR and click the "Close Pull Request" button. This will close the PR without merging it.
51+
1852
## "Work In Progress" pull requests
1953

20-
Marking a pull request as being a work in progress will prevent that pull request from being accidentally merged. To mark a pull request as being a work in progress, you must prefix its title by `WIP:` or `[WIP]` (case insensitive). Those values are configurable in your `app.ini` file :
54+
Marking a pull request as being a work in progress will prevent that pull request from being accidentally merged.
55+
To mark a pull request as being a work in progress, you must prefix its title by `WIP:` or `[WIP]` (case insensitive).
56+
Those values are configurable in your `app.ini` file:
2157

2258
```ini
2359
[repository.pull-request]

models/git/lfs_lock.go

+3-3
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ func init() {
3434

3535
// BeforeInsert is invoked from XORM before inserting an object of this type.
3636
func (l *LFSLock) BeforeInsert() {
37-
l.Path = util.CleanPath(l.Path)
37+
l.Path = util.PathJoinRel(l.Path)
3838
}
3939

4040
// CreateLFSLock creates a new lock.
@@ -49,7 +49,7 @@ func CreateLFSLock(ctx context.Context, repo *repo_model.Repository, lock *LFSLo
4949
return nil, err
5050
}
5151

52-
lock.Path = util.CleanPath(lock.Path)
52+
lock.Path = util.PathJoinRel(lock.Path)
5353
lock.RepoID = repo.ID
5454

5555
l, err := GetLFSLock(dbCtx, repo, lock.Path)
@@ -69,7 +69,7 @@ func CreateLFSLock(ctx context.Context, repo *repo_model.Repository, lock *LFSLo
6969

7070
// GetLFSLock returns release by given path.
7171
func GetLFSLock(ctx context.Context, repo *repo_model.Repository, path string) (*LFSLock, error) {
72-
path = util.CleanPath(path)
72+
path = util.PathJoinRel(path)
7373
rel := &LFSLock{RepoID: repo.ID}
7474
has, err := db.GetEngine(ctx).Where("lower(path) = ?", strings.ToLower(path)).Get(rel)
7575
if err != nil {

modules/context/context.go

+32
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,10 @@ import (
1616
"net/http"
1717
"net/url"
1818
"path"
19+
"regexp"
1920
"strconv"
2021
"strings"
22+
texttemplate "text/template"
2123
"time"
2224

2325
"code.gitea.io/gitea/models/db"
@@ -213,6 +215,8 @@ func (ctx *Context) RedirectToFirst(location ...string) {
213215
ctx.Redirect(setting.AppSubURL + "/")
214216
}
215217

218+
var templateExecutingErr = regexp.MustCompile(`^template: (.*):([1-9][0-9]*):([1-9][0-9]*): executing (?:"(.*)" at <(.*)>: )?`)
219+
216220
// HTML calls Context.HTML and renders the template to HTTP response
217221
func (ctx *Context) HTML(status int, name base.TplName) {
218222
log.Debug("Template: %s", name)
@@ -228,6 +232,34 @@ func (ctx *Context) HTML(status int, name base.TplName) {
228232
ctx.PlainText(http.StatusInternalServerError, "Unable to find status/500 template")
229233
return
230234
}
235+
if execErr, ok := err.(texttemplate.ExecError); ok {
236+
if groups := templateExecutingErr.FindStringSubmatch(err.Error()); len(groups) > 0 {
237+
errorTemplateName, lineStr, posStr := groups[1], groups[2], groups[3]
238+
target := ""
239+
if len(groups) == 6 {
240+
target = groups[5]
241+
}
242+
line, _ := strconv.Atoi(lineStr) // Cannot error out as groups[2] is [1-9][0-9]*
243+
pos, _ := strconv.Atoi(posStr) // Cannot error out as groups[3] is [1-9][0-9]*
244+
filename, filenameErr := templates.GetAssetFilename("templates/" + errorTemplateName + ".tmpl")
245+
if filenameErr != nil {
246+
filename = "(template) " + errorTemplateName
247+
}
248+
if errorTemplateName != string(name) {
249+
filename += " (subtemplate of " + string(name) + ")"
250+
}
251+
err = fmt.Errorf("%w\nin template file %s:\n%s", err, filename, templates.GetLineFromTemplate(errorTemplateName, line, target, pos))
252+
} else {
253+
filename, filenameErr := templates.GetAssetFilename("templates/" + execErr.Name + ".tmpl")
254+
if filenameErr != nil {
255+
filename = "(template) " + execErr.Name
256+
}
257+
if execErr.Name != string(name) {
258+
filename += " (subtemplate of " + string(name) + ")"
259+
}
260+
err = fmt.Errorf("%w\nin template file %s", err, filename)
261+
}
262+
}
231263
ctx.ServerError("Render failed", err)
232264
}
233265
}

modules/options/base.go

+53-14
Original file line numberDiff line numberDiff line change
@@ -7,36 +7,38 @@ import (
77
"fmt"
88
"io/fs"
99
"os"
10-
"path"
1110
"path/filepath"
1211

12+
"code.gitea.io/gitea/modules/log"
1313
"code.gitea.io/gitea/modules/setting"
1414
"code.gitea.io/gitea/modules/util"
1515
)
1616

17+
var directories = make(directorySet)
18+
1719
// Locale reads the content of a specific locale from static/bindata or custom path.
1820
func Locale(name string) ([]byte, error) {
19-
return fileFromDir(path.Join("locale", util.CleanPath(name)))
21+
return fileFromOptionsDir("locale", name)
2022
}
2123

2224
// Readme reads the content of a specific readme from static/bindata or custom path.
2325
func Readme(name string) ([]byte, error) {
24-
return fileFromDir(path.Join("readme", util.CleanPath(name)))
26+
return fileFromOptionsDir("readme", name)
2527
}
2628

2729
// Gitignore reads the content of a gitignore locale from static/bindata or custom path.
2830
func Gitignore(name string) ([]byte, error) {
29-
return fileFromDir(path.Join("gitignore", util.CleanPath(name)))
31+
return fileFromOptionsDir("gitignore", name)
3032
}
3133

3234
// License reads the content of a specific license from static/bindata or custom path.
3335
func License(name string) ([]byte, error) {
34-
return fileFromDir(path.Join("license", util.CleanPath(name)))
36+
return fileFromOptionsDir("license", name)
3537
}
3638

3739
// Labels reads the content of a specific labels from static/bindata or custom path.
3840
func Labels(name string) ([]byte, error) {
39-
return fileFromDir(path.Join("label", util.CleanPath(name)))
41+
return fileFromOptionsDir("label", name)
4042
}
4143

4244
// WalkLocales reads the content of a specific locale
@@ -79,17 +81,54 @@ func walkAssetDir(root string, callback func(path, name string, d fs.DirEntry, e
7981
return nil
8082
}
8183

82-
func statDirIfExist(dir string) ([]string, error) {
83-
isDir, err := util.IsDir(dir)
84+
// mustLocalPathAbs coverts a path to absolute path
85+
// FIXME: the old behavior (StaticRootPath might not be absolute), not ideal, just keep the same as before
86+
func mustLocalPathAbs(s string) string {
87+
abs, err := filepath.Abs(s)
8488
if err != nil {
85-
return nil, fmt.Errorf("unable to check if static directory %s is a directory. %w", dir, err)
89+
// This should never happen in a real system. If it happens, the user must have already been in trouble: the system is not able to resolve its own paths.
90+
log.Fatal("Unable to get absolute path for %q: %v", s, err)
8691
}
87-
if !isDir {
88-
return nil, nil
92+
return abs
93+
}
94+
95+
func joinLocalPaths(baseDirs []string, subDir string, elems ...string) (paths []string) {
96+
abs := make([]string, len(elems)+2)
97+
abs[1] = subDir
98+
copy(abs[2:], elems)
99+
for _, baseDir := range baseDirs {
100+
abs[0] = mustLocalPathAbs(baseDir)
101+
paths = append(paths, util.FilePathJoinAbs(abs...))
89102
}
90-
files, err := util.StatDir(dir, true)
91-
if err != nil {
92-
return nil, fmt.Errorf("unable to read directory %q. %w", dir, err)
103+
return paths
104+
}
105+
106+
func listLocalDirIfExist(baseDirs []string, subDir string, elems ...string) (files []string, err error) {
107+
for _, localPath := range joinLocalPaths(baseDirs, subDir, elems...) {
108+
isDir, err := util.IsDir(localPath)
109+
if err != nil {
110+
return nil, fmt.Errorf("unable to check if path %q is a directory. %w", localPath, err)
111+
} else if !isDir {
112+
continue
113+
}
114+
115+
dirFiles, err := util.StatDir(localPath, true)
116+
if err != nil {
117+
return nil, fmt.Errorf("unable to read directory %q. %w", localPath, err)
118+
}
119+
files = append(files, dirFiles...)
93120
}
94121
return files, nil
95122
}
123+
124+
func readLocalFile(baseDirs []string, subDir string, elems ...string) ([]byte, error) {
125+
for _, localPath := range joinLocalPaths(baseDirs, subDir, elems...) {
126+
data, err := os.ReadFile(localPath)
127+
if err == nil {
128+
return data, nil
129+
} else if !os.IsNotExist(err) {
130+
log.Error("Unable to read file %q. Error: %v", localPath, err)
131+
}
132+
}
133+
return nil, os.ErrNotExist
134+
}

modules/options/dynamic.go

+6-42
Original file line numberDiff line numberDiff line change
@@ -6,62 +6,26 @@
66
package options
77

88
import (
9-
"fmt"
10-
"os"
11-
"path"
12-
13-
"code.gitea.io/gitea/modules/log"
149
"code.gitea.io/gitea/modules/setting"
15-
"code.gitea.io/gitea/modules/util"
1610
)
1711

18-
var directories = make(directorySet)
19-
2012
// Dir returns all files from static or custom directory.
2113
func Dir(name string) ([]string, error) {
2214
if directories.Filled(name) {
2315
return directories.Get(name), nil
2416
}
2517

26-
var result []string
27-
28-
for _, dir := range []string{
29-
path.Join(setting.CustomPath, "options", name), // custom dir
30-
path.Join(setting.StaticRootPath, "options", name), // static dir
31-
} {
32-
files, err := statDirIfExist(dir)
33-
if err != nil {
34-
return nil, err
35-
}
36-
result = append(result, files...)
18+
result, err := listLocalDirIfExist([]string{setting.CustomPath, setting.StaticRootPath}, "options", name)
19+
if err != nil {
20+
return nil, err
3721
}
3822

3923
return directories.AddAndGet(name, result), nil
4024
}
4125

42-
// fileFromDir is a helper to read files from static or custom path.
43-
func fileFromDir(name string) ([]byte, error) {
44-
customPath := path.Join(setting.CustomPath, "options", name)
45-
46-
isFile, err := util.IsFile(customPath)
47-
if err != nil {
48-
log.Error("Unable to check if %s is a file. Error: %v", customPath, err)
49-
}
50-
if isFile {
51-
return os.ReadFile(customPath)
52-
}
53-
54-
staticPath := path.Join(setting.StaticRootPath, "options", name)
55-
56-
isFile, err = util.IsFile(staticPath)
57-
if err != nil {
58-
log.Error("Unable to check if %s is a file. Error: %v", staticPath, err)
59-
}
60-
if isFile {
61-
return os.ReadFile(staticPath)
62-
}
63-
64-
return []byte{}, fmt.Errorf("Asset file does not exist: %s", name)
26+
// fileFromOptionsDir is a helper to read files from custom or static path.
27+
func fileFromOptionsDir(elems ...string) ([]byte, error) {
28+
return readLocalFile([]string{setting.CustomPath, setting.StaticRootPath}, "options", elems...)
6529
}
6630

6731
// IsDynamic will return false when using embedded data (-tags bindata)

0 commit comments

Comments
 (0)