diff options
author | wxiaoguang <wxiaoguang@gmail.com> | 2023-04-12 18:16:45 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-04-12 18:16:45 +0800 |
commit | 50a72e7a83a16d183a264e969a73cdbc7fb808f4 (patch) | |
tree | 013456110621c36edb3fa0d1bb77906ba8d4e013 /modules/util | |
parent | 42919ccb7cd32ab67d0878baf2bac6cd007899a8 (diff) | |
download | gitea-50a72e7a83a16d183a264e969a73cdbc7fb808f4.tar.gz gitea-50a72e7a83a16d183a264e969a73cdbc7fb808f4.zip |
Use a general approach to access custom/static/builtin assets (#24022)
The idea is to use a Layered Asset File-system (modules/assetfs/layered.go)
For example: when there are 2 layers: "custom", "builtin", when access
to asset "my/page.tmpl", the Layered Asset File-system will first try to
use "custom" assets, if not found, then use "builtin" assets.
This approach will hugely simplify a lot of code, make them testable.
Other changes:
* Simplify the AssetsHandlerFunc code
* Simplify the `gitea embedded` sub-command code
---------
Co-authored-by: Jason Song <i@wolfogre.com>
Co-authored-by: Lunny Xiao <xiaolunwen@gmail.com>
Diffstat (limited to 'modules/util')
-rw-r--r-- | modules/util/path.go | 19 | ||||
-rw-r--r-- | modules/util/path_test.go | 2 | ||||
-rw-r--r-- | modules/util/timer.go | 28 | ||||
-rw-r--r-- | modules/util/timer_test.go | 30 |
4 files changed, 68 insertions, 11 deletions
diff --git a/modules/util/path.go b/modules/util/path.go index 37d06e9813..1a68bc7488 100644 --- a/modules/util/path.go +++ b/modules/util/path.go @@ -74,29 +74,28 @@ const pathSeparator = string(os.PathSeparator) // // {`/foo`, ``, `bar`} => `/foo/bar` // {`/foo`, `..`, `bar`} => `/foo/bar` -func FilePathJoinAbs(elem ...string) string { - elems := make([]string, len(elem)) +func FilePathJoinAbs(base string, sub ...string) string { + elems := make([]string, 1, len(sub)+1) - // POISX filesystem can have `\` in file names. Windows: `\` and `/` are both used for path separators + // POSIX filesystem can have `\` in file names. Windows: `\` and `/` are both used for path separators // to keep the behavior consistent, we do not allow `\` in file names, replace all `\` with `/` if isOSWindows() { - elems[0] = filepath.Clean(elem[0]) + elems[0] = filepath.Clean(base) } else { - elems[0] = filepath.Clean(strings.ReplaceAll(elem[0], "\\", pathSeparator)) + elems[0] = filepath.Clean(strings.ReplaceAll(base, "\\", pathSeparator)) } if !filepath.IsAbs(elems[0]) { // This shouldn't happen. If there is really necessary to pass in relative path, return the full path with filepath.Abs() instead panic(fmt.Sprintf("FilePathJoinAbs: %q (for path %v) is not absolute, do not guess a relative path based on current working directory", elems[0], elems)) } - - for i := 1; i < len(elem); i++ { - if elem[i] == "" { + for _, s := range sub { + if s == "" { continue } if isOSWindows() { - elems[i] = filepath.Clean(pathSeparator + elem[i]) + elems = append(elems, filepath.Clean(pathSeparator+s)) } else { - elems[i] = filepath.Clean(pathSeparator + strings.ReplaceAll(elem[i], "\\", pathSeparator)) + elems = append(elems, filepath.Clean(pathSeparator+strings.ReplaceAll(s, "\\", pathSeparator))) } } // the elems[0] must be an absolute path, just join them together diff --git a/modules/util/path_test.go b/modules/util/path_test.go index 1d27c9bf0c..6a38bf4ace 100644 --- a/modules/util/path_test.go +++ b/modules/util/path_test.go @@ -207,6 +207,6 @@ func TestCleanPath(t *testing.T) { } } for _, c := range cases { - assert.Equal(t, c.expected, FilePathJoinAbs(c.elems...), "case: %v", c.elems) + assert.Equal(t, c.expected, FilePathJoinAbs(c.elems[0], c.elems[1:]...), "case: %v", c.elems) } } diff --git a/modules/util/timer.go b/modules/util/timer.go index daf96bda7e..d598fde73a 100644 --- a/modules/util/timer.go +++ b/modules/util/timer.go @@ -4,6 +4,7 @@ package util import ( + "sync" "time" ) @@ -18,3 +19,30 @@ func StopTimer(t *time.Timer) bool { } return stopped } + +func Debounce(d time.Duration) func(f func()) { + type debouncer struct { + mu sync.Mutex + t *time.Timer + } + db := &debouncer{} + + return func(f func()) { + db.mu.Lock() + defer db.mu.Unlock() + + if db.t != nil { + db.t.Stop() + } + var trigger *time.Timer + trigger = time.AfterFunc(d, func() { + db.mu.Lock() + defer db.mu.Unlock() + if trigger == db.t { + f() + db.t = nil + } + }) + db.t = trigger + } +} diff --git a/modules/util/timer_test.go b/modules/util/timer_test.go new file mode 100644 index 0000000000..602800c248 --- /dev/null +++ b/modules/util/timer_test.go @@ -0,0 +1,30 @@ +// Copyright 2023 The Gitea Authors. All rights reserved. +// SPDX-License-Identifier: MIT + +package util + +import ( + "sync/atomic" + "testing" + "time" + + "github.com/stretchr/testify/assert" +) + +func TestDebounce(t *testing.T) { + var c int64 + d := Debounce(50 * time.Millisecond) + d(func() { atomic.AddInt64(&c, 1) }) + assert.EqualValues(t, 0, atomic.LoadInt64(&c)) + d(func() { atomic.AddInt64(&c, 1) }) + d(func() { atomic.AddInt64(&c, 1) }) + time.Sleep(100 * time.Millisecond) + assert.EqualValues(t, 1, atomic.LoadInt64(&c)) + d(func() { atomic.AddInt64(&c, 1) }) + assert.EqualValues(t, 1, atomic.LoadInt64(&c)) + d(func() { atomic.AddInt64(&c, 1) }) + d(func() { atomic.AddInt64(&c, 1) }) + d(func() { atomic.AddInt64(&c, 1) }) + time.Sleep(100 * time.Millisecond) + assert.EqualValues(t, 2, atomic.LoadInt64(&c)) +} |