Skip to content

Commit 774b37b

Browse files
authored
Introduce path Clean/Join helper functions, partially backport&refactor (#23495) (#23607)
Backport #23495, partially backport&refactor The `modules/options` files are just copied from 1.20 to 1.19
1 parent 9dfdfe2 commit 774b37b

File tree

5 files changed

+269
-171
lines changed

5 files changed

+269
-171
lines changed

modules/options/base.go

+95
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,52 @@ import (
99
"os"
1010
"path/filepath"
1111

12+
"code.gitea.io/gitea/modules/log"
13+
"code.gitea.io/gitea/modules/setting"
1214
"code.gitea.io/gitea/modules/util"
1315
)
1416

17+
var directories = make(directorySet)
18+
19+
// Locale reads the content of a specific locale from static/bindata or custom path.
20+
func Locale(name string) ([]byte, error) {
21+
return fileFromOptionsDir("locale", name)
22+
}
23+
24+
// Readme reads the content of a specific readme from static/bindata or custom path.
25+
func Readme(name string) ([]byte, error) {
26+
return fileFromOptionsDir("readme", name)
27+
}
28+
29+
// Gitignore reads the content of a gitignore locale from static/bindata or custom path.
30+
func Gitignore(name string) ([]byte, error) {
31+
return fileFromOptionsDir("gitignore", name)
32+
}
33+
34+
// License reads the content of a specific license from static/bindata or custom path.
35+
func License(name string) ([]byte, error) {
36+
return fileFromOptionsDir("license", name)
37+
}
38+
39+
// Labels reads the content of a specific labels from static/bindata or custom path.
40+
func Labels(name string) ([]byte, error) {
41+
return fileFromOptionsDir("label", name)
42+
}
43+
44+
// WalkLocales reads the content of a specific locale
45+
func WalkLocales(callback func(path, name string, d fs.DirEntry, err error) error) error {
46+
if IsDynamic() {
47+
if err := walkAssetDir(filepath.Join(setting.StaticRootPath, "options", "locale"), callback); err != nil && !os.IsNotExist(err) {
48+
return fmt.Errorf("failed to walk locales. Error: %w", err)
49+
}
50+
}
51+
52+
if err := walkAssetDir(filepath.Join(setting.CustomPath, "options", "locale"), callback); err != nil && !os.IsNotExist(err) {
53+
return fmt.Errorf("failed to walk locales. Error: %w", err)
54+
}
55+
return nil
56+
}
57+
1558
func walkAssetDir(root string, callback func(path, name string, d fs.DirEntry, err error) error) error {
1659
if err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
1760
// name is the path relative to the root
@@ -37,3 +80,55 @@ func walkAssetDir(root string, callback func(path, name string, d fs.DirEntry, e
3780
}
3881
return nil
3982
}
83+
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)
88+
if err != nil {
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)
91+
}
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...))
102+
}
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...)
120+
}
121+
return files, nil
122+
}
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

+5-99
Original file line numberDiff line numberDiff line change
@@ -6,120 +6,26 @@
66
package options
77

88
import (
9-
"fmt"
10-
"io/fs"
11-
"os"
12-
"path"
13-
"path/filepath"
14-
15-
"code.gitea.io/gitea/modules/log"
169
"code.gitea.io/gitea/modules/setting"
17-
"code.gitea.io/gitea/modules/util"
1810
)
1911

20-
var directories = make(directorySet)
21-
2212
// Dir returns all files from static or custom directory.
2313
func Dir(name string) ([]string, error) {
2414
if directories.Filled(name) {
2515
return directories.Get(name), nil
2616
}
2717

28-
var result []string
29-
30-
customDir := path.Join(setting.CustomPath, "options", name)
31-
32-
isDir, err := util.IsDir(customDir)
33-
if err != nil {
34-
return []string{}, fmt.Errorf("Unabe to check if custom directory %s is a directory. %w", customDir, err)
35-
}
36-
if isDir {
37-
files, err := util.StatDir(customDir, true)
38-
if err != nil {
39-
return []string{}, fmt.Errorf("Failed to read custom directory. %w", err)
40-
}
41-
42-
result = append(result, files...)
43-
}
44-
45-
staticDir := path.Join(setting.StaticRootPath, "options", name)
46-
47-
isDir, err = util.IsDir(staticDir)
18+
result, err := listLocalDirIfExist([]string{setting.CustomPath, setting.StaticRootPath}, "options", name)
4819
if err != nil {
49-
return []string{}, fmt.Errorf("unable to check if static directory %s is a directory. %w", staticDir, err)
50-
}
51-
if isDir {
52-
files, err := util.StatDir(staticDir, true)
53-
if err != nil {
54-
return []string{}, fmt.Errorf("Failed to read static directory. %w", err)
55-
}
56-
57-
result = append(result, files...)
20+
return nil, err
5821
}
5922

6023
return directories.AddAndGet(name, result), nil
6124
}
6225

63-
// Locale reads the content of a specific locale from static or custom path.
64-
func Locale(name string) ([]byte, error) {
65-
return fileFromDir(path.Join("locale", name))
66-
}
67-
68-
// WalkLocales reads the content of a specific locale from static or custom path.
69-
func WalkLocales(callback func(path, name string, d fs.DirEntry, err error) error) error {
70-
if err := walkAssetDir(filepath.Join(setting.StaticRootPath, "options", "locale"), callback); err != nil && !os.IsNotExist(err) {
71-
return fmt.Errorf("failed to walk locales. Error: %w", err)
72-
}
73-
74-
if err := walkAssetDir(filepath.Join(setting.CustomPath, "options", "locale"), callback); err != nil && !os.IsNotExist(err) {
75-
return fmt.Errorf("failed to walk locales. Error: %w", err)
76-
}
77-
return nil
78-
}
79-
80-
// Readme reads the content of a specific readme from static or custom path.
81-
func Readme(name string) ([]byte, error) {
82-
return fileFromDir(path.Join("readme", name))
83-
}
84-
85-
// Gitignore reads the content of a specific gitignore from static or custom path.
86-
func Gitignore(name string) ([]byte, error) {
87-
return fileFromDir(path.Join("gitignore", name))
88-
}
89-
90-
// License reads the content of a specific license from static or custom path.
91-
func License(name string) ([]byte, error) {
92-
return fileFromDir(path.Join("license", name))
93-
}
94-
95-
// Labels reads the content of a specific labels from static or custom path.
96-
func Labels(name string) ([]byte, error) {
97-
return fileFromDir(path.Join("label", name))
98-
}
99-
100-
// fileFromDir is a helper to read files from static or custom path.
101-
func fileFromDir(name string) ([]byte, error) {
102-
customPath := path.Join(setting.CustomPath, "options", name)
103-
104-
isFile, err := util.IsFile(customPath)
105-
if err != nil {
106-
log.Error("Unable to check if %s is a file. Error: %v", customPath, err)
107-
}
108-
if isFile {
109-
return os.ReadFile(customPath)
110-
}
111-
112-
staticPath := path.Join(setting.StaticRootPath, "options", name)
113-
114-
isFile, err = util.IsFile(staticPath)
115-
if err != nil {
116-
log.Error("Unable to check if %s is a file. Error: %v", staticPath, err)
117-
}
118-
if isFile {
119-
return os.ReadFile(staticPath)
120-
}
121-
122-
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...)
12329
}
12430

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

modules/options/static.go

+9-66
Original file line numberDiff line numberDiff line change
@@ -8,38 +8,20 @@ package options
88
import (
99
"fmt"
1010
"io"
11-
"io/fs"
12-
"os"
13-
"path"
14-
"path/filepath"
1511

16-
"code.gitea.io/gitea/modules/log"
1712
"code.gitea.io/gitea/modules/setting"
1813
"code.gitea.io/gitea/modules/util"
1914
)
2015

21-
var directories = make(directorySet)
22-
23-
// Dir returns all files from bindata or custom directory.
16+
// Dir returns all files from custom directory or bindata.
2417
func Dir(name string) ([]string, error) {
2518
if directories.Filled(name) {
2619
return directories.Get(name), nil
2720
}
2821

29-
var result []string
30-
31-
customDir := path.Join(setting.CustomPath, "options", name)
32-
isDir, err := util.IsDir(customDir)
22+
result, err := listLocalDirIfExist([]string{setting.CustomPath}, "options", name)
3323
if err != nil {
34-
return []string{}, fmt.Errorf("unable to check if custom directory %q is a directory. %w", customDir, err)
35-
}
36-
if isDir {
37-
files, err := util.StatDir(customDir, true)
38-
if err != nil {
39-
return []string{}, fmt.Errorf("unable to read custom directory %q. %w", customDir, err)
40-
}
41-
42-
result = append(result, files...)
24+
return nil, err
4325
}
4426

4527
files, err := AssetDir(name)
@@ -69,57 +51,18 @@ func AssetDir(dirName string) ([]string, error) {
6951
return results, nil
7052
}
7153

72-
// Locale reads the content of a specific locale from bindata or custom path.
73-
func Locale(name string) ([]byte, error) {
74-
return fileFromDir(path.Join("locale", name))
75-
}
76-
77-
// WalkLocales reads the content of a specific locale from static or custom path.
78-
func WalkLocales(callback func(path, name string, d fs.DirEntry, err error) error) error {
79-
if err := walkAssetDir(filepath.Join(setting.CustomPath, "options", "locale"), callback); err != nil && !os.IsNotExist(err) {
80-
return fmt.Errorf("failed to walk locales. Error: %w", err)
54+
// fileFromOptionsDir is a helper to read files from custom path or bindata.
55+
func fileFromOptionsDir(elems ...string) ([]byte, error) {
56+
// only try custom dir, no static dir
57+
if data, err := readLocalFile([]string{setting.CustomPath}, "options", elems...); err == nil {
58+
return data, nil
8159
}
82-
return nil
83-
}
8460

85-
// Readme reads the content of a specific readme from bindata or custom path.
86-
func Readme(name string) ([]byte, error) {
87-
return fileFromDir(path.Join("readme", name))
88-
}
89-
90-
// Gitignore reads the content of a gitignore locale from bindata or custom path.
91-
func Gitignore(name string) ([]byte, error) {
92-
return fileFromDir(path.Join("gitignore", name))
93-
}
94-
95-
// License reads the content of a specific license from bindata or custom path.
96-
func License(name string) ([]byte, error) {
97-
return fileFromDir(path.Join("license", name))
98-
}
99-
100-
// Labels reads the content of a specific labels from static or custom path.
101-
func Labels(name string) ([]byte, error) {
102-
return fileFromDir(path.Join("label", name))
103-
}
104-
105-
// fileFromDir is a helper to read files from bindata or custom path.
106-
func fileFromDir(name string) ([]byte, error) {
107-
customPath := path.Join(setting.CustomPath, "options", name)
108-
109-
isFile, err := util.IsFile(customPath)
110-
if err != nil {
111-
log.Error("Unable to check if %s is a file. Error: %v", customPath, err)
112-
}
113-
if isFile {
114-
return os.ReadFile(customPath)
115-
}
116-
117-
f, err := Assets.Open(name)
61+
f, err := Assets.Open(util.PathJoinRelX(elems...))
11862
if err != nil {
11963
return nil, err
12064
}
12165
defer f.Close()
122-
12366
return io.ReadAll(f)
12467
}
12568

0 commit comments

Comments
 (0)