mirror of
https://github.com/go-gitea/gitea.git
synced 2025-12-17 02:10:23 +00:00
Compare commits
100 Commits
v1.20.0-rc
...
v1.20.1
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
221b90d289 | ||
|
|
81f5a87eb4 | ||
|
|
8b002b429d | ||
|
|
dfd371a363 | ||
|
|
54a516e9da | ||
|
|
ac129d4b4c | ||
|
|
4d5e3b9372 | ||
|
|
1ba0baa030 | ||
|
|
28e8c691a6 | ||
|
|
f81a612eb1 | ||
|
|
ee47face12 | ||
|
|
864bdd0ac8 | ||
|
|
037a3f0d8c | ||
|
|
227c3b67e0 | ||
|
|
5c3662b902 | ||
|
|
ab54310731 | ||
|
|
b7d054e4b5 | ||
|
|
d032500687 | ||
|
|
9159964ada | ||
|
|
9369b38315 | ||
|
|
6e82d0bb7c | ||
|
|
36b9a86bd8 | ||
|
|
e627f161c2 | ||
|
|
de8127e78b | ||
|
|
f7e271ff85 | ||
|
|
186f07bbf7 | ||
|
|
45b1f4dd3b | ||
|
|
026e745b9e | ||
|
|
c334be8284 | ||
|
|
353dcc5ad4 | ||
|
|
7811027ca1 | ||
|
|
abe9c641ce | ||
|
|
052e65e63f | ||
|
|
c1a10be07e | ||
|
|
2b79d3fd52 | ||
|
|
b4460cf541 | ||
|
|
a1bc2aa05e | ||
|
|
d713cf6150 | ||
|
|
012b804a9a | ||
|
|
372b622c2b | ||
|
|
06bcdfe77a | ||
|
|
a5a3c81412 | ||
|
|
ea2c9de3c4 | ||
|
|
348a6bf70d | ||
|
|
68a3961bf1 | ||
|
|
91dadedddf | ||
|
|
32eaba1b40 | ||
|
|
582dcaa12e | ||
|
|
917ca5ded9 | ||
|
|
e595dfeec7 | ||
|
|
03cacf971e | ||
|
|
68e0c802f7 | ||
|
|
09668b2e2e | ||
|
|
04eea29ecb | ||
|
|
511be9fe6e | ||
|
|
24e64fe372 | ||
|
|
4e310133f9 | ||
|
|
491f36d32a | ||
|
|
9111d2d037 | ||
|
|
5510ed34f1 | ||
|
|
39fce5750d | ||
|
|
1f90376041 | ||
|
|
0af6542a34 | ||
|
|
69bdcf41f3 | ||
|
|
e610b0389a | ||
|
|
13ffa287b1 | ||
|
|
e5b684e567 | ||
|
|
64ed262e18 | ||
|
|
f51c8e0008 | ||
|
|
d8a59d5f12 | ||
|
|
1ddfe03131 | ||
|
|
24cf06592e | ||
|
|
0b6f7fb607 | ||
|
|
c27a3af728 | ||
|
|
12aca3ef20 | ||
|
|
2390a46d0f | ||
|
|
51b6a78791 | ||
|
|
e6f62eea70 | ||
|
|
8981f6d0fc | ||
|
|
b2b5c80cb2 | ||
|
|
77db40e084 | ||
|
|
7222bac4e3 | ||
|
|
0eb4ab4246 | ||
|
|
102dcfa3a0 | ||
|
|
614d6df2d8 | ||
|
|
345a25d016 | ||
|
|
e8a7cd4a1d | ||
|
|
6c43b9f6f6 | ||
|
|
40744f8976 | ||
|
|
9d69a4758e | ||
|
|
53747a58a0 | ||
|
|
00ba826360 | ||
|
|
9bbb4d8d6d | ||
|
|
5703a0d3e3 | ||
|
|
85bad22ff8 | ||
|
|
71d2a6a41a | ||
|
|
d1f1f1142e | ||
|
|
2cd9d6b3f9 | ||
|
|
050c38ca19 | ||
|
|
51789ba12d |
1192
CHANGELOG.md
1192
CHANGELOG.md
File diff suppressed because it is too large
Load Diff
@@ -25,7 +25,7 @@ import (
|
|||||||
|
|
||||||
var optionLogVerbose bool
|
var optionLogVerbose bool
|
||||||
|
|
||||||
func logVerbose(msg string, args ...interface{}) {
|
func logVerbose(msg string, args ...any) {
|
||||||
if optionLogVerbose {
|
if optionLogVerbose {
|
||||||
log.Printf(msg, args...)
|
log.Printf(msg, args...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func publicKey(priv interface{}) interface{} {
|
func publicKey(priv any) any {
|
||||||
switch k := priv.(type) {
|
switch k := priv.(type) {
|
||||||
case *rsa.PrivateKey:
|
case *rsa.PrivateKey:
|
||||||
return &k.PublicKey
|
return &k.PublicKey
|
||||||
@@ -74,7 +74,7 @@ func publicKey(priv interface{}) interface{} {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func pemBlockForKey(priv interface{}) *pem.Block {
|
func pemBlockForKey(priv any) *pem.Block {
|
||||||
switch k := priv.(type) {
|
switch k := priv.(type) {
|
||||||
case *rsa.PrivateKey:
|
case *rsa.PrivateKey:
|
||||||
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
|
return &pem.Block{Type: "RSA PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(k)}
|
||||||
@@ -94,7 +94,7 @@ func runCert(c *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var priv interface{}
|
var priv any
|
||||||
var err error
|
var err error
|
||||||
switch c.String("ecdsa-curve") {
|
switch c.String("ecdsa-curve") {
|
||||||
case "":
|
case "":
|
||||||
|
|||||||
18
cmd/cmd.go
18
cmd/cmd.go
@@ -106,5 +106,21 @@ func setupConsoleLogger(level log.Level, colorize bool, out io.Writer) {
|
|||||||
WriterOption: log.WriterConsoleOption{Stderr: out == os.Stderr},
|
WriterOption: log.WriterConsoleOption{Stderr: out == os.Stderr},
|
||||||
}
|
}
|
||||||
writer := log.NewEventWriterConsole("console-default", writeMode)
|
writer := log.NewEventWriterConsole("console-default", writeMode)
|
||||||
log.GetManager().GetLogger(log.DEFAULT).RemoveAllWriters().AddWriters(writer)
|
log.GetManager().GetLogger(log.DEFAULT).ReplaceAllWriters(writer)
|
||||||
|
}
|
||||||
|
|
||||||
|
// PrepareConsoleLoggerLevel by default, use INFO level for console logger, but some sub-commands (for git/ssh protocol) shouldn't output any log to stdout.
|
||||||
|
// Any log appears in git stdout pipe will break the git protocol, eg: client can't push and hangs forever.
|
||||||
|
func PrepareConsoleLoggerLevel(defaultLevel log.Level) func(*cli.Context) error {
|
||||||
|
return func(c *cli.Context) error {
|
||||||
|
level := defaultLevel
|
||||||
|
if c.Bool("quiet") || c.GlobalBoolT("quiet") {
|
||||||
|
level = log.FATAL
|
||||||
|
}
|
||||||
|
if c.Bool("debug") || c.GlobalBool("debug") || c.Bool("verbose") || c.GlobalBool("verbose") {
|
||||||
|
level = log.TRACE
|
||||||
|
}
|
||||||
|
log.SetConsoleLogger(log.DEFAULT, "console-default", level)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ func setupDoctorDefaultLogger(ctx *cli.Context, colorize bool) {
|
|||||||
log.FallbackErrorf("unable to create file log writer: %v", err)
|
log.FallbackErrorf("unable to create file log writer: %v", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.GetManager().GetLogger(log.DEFAULT).RemoveAllWriters().AddWriters(writer)
|
log.GetManager().GetLogger(log.DEFAULT).ReplaceAllWriters(writer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -161,7 +161,7 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func fatal(format string, args ...interface{}) {
|
func fatal(format string, args ...any) {
|
||||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||||
log.Fatal(format, args...)
|
log.Fatal(format, args...)
|
||||||
}
|
}
|
||||||
@@ -236,7 +236,7 @@ func runDump(ctx *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
var iface interface{}
|
var iface any
|
||||||
if fileName == "-" {
|
if fileName == "-" {
|
||||||
iface, err = archiver.ByExtension(fmt.Sprintf(".%s", outType))
|
iface, err = archiver.ByExtension(fmt.Sprintf(".%s", outType))
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -22,9 +22,9 @@ import (
|
|||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Cmdembedded represents the available extract sub-command.
|
// CmdEmbedded represents the available extract sub-command.
|
||||||
var (
|
var (
|
||||||
Cmdembedded = cli.Command{
|
CmdEmbedded = cli.Command{
|
||||||
Name: "embedded",
|
Name: "embedded",
|
||||||
Usage: "Extract embedded resources",
|
Usage: "Extract embedded resources",
|
||||||
Description: "A command for extracting embedded resources, like templates and images",
|
Description: "A command for extracting embedded resources, like templates and images",
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
repo_module "code.gitea.io/gitea/modules/repository"
|
repo_module "code.gitea.io/gitea/modules/repository"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
@@ -32,6 +33,7 @@ var (
|
|||||||
Name: "hook",
|
Name: "hook",
|
||||||
Usage: "Delegate commands to corresponding Git hooks",
|
Usage: "Delegate commands to corresponding Git hooks",
|
||||||
Description: "This should only be called by Git",
|
Description: "This should only be called by Git",
|
||||||
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []cli.Command{
|
||||||
subcmdHookPreReceive,
|
subcmdHookPreReceive,
|
||||||
subcmdHookUpdate,
|
subcmdHookUpdate,
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
@@ -17,6 +18,7 @@ import (
|
|||||||
var CmdKeys = cli.Command{
|
var CmdKeys = cli.Command{
|
||||||
Name: "keys",
|
Name: "keys",
|
||||||
Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint",
|
||||||
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Action: runKeys,
|
Action: runKeys,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
|
|||||||
@@ -178,7 +178,7 @@ func runAddConnLogger(c *cli.Context) error {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
setup(ctx, c.Bool("debug"))
|
||||||
vals := map[string]interface{}{}
|
vals := map[string]any{}
|
||||||
mode := "conn"
|
mode := "conn"
|
||||||
vals["net"] = "tcp"
|
vals["net"] = "tcp"
|
||||||
if c.IsSet("protocol") {
|
if c.IsSet("protocol") {
|
||||||
@@ -208,7 +208,7 @@ func runAddFileLogger(c *cli.Context) error {
|
|||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
setup(ctx, c.Bool("debug"))
|
setup(ctx, c.Bool("debug"))
|
||||||
vals := map[string]interface{}{}
|
vals := map[string]any{}
|
||||||
mode := "file"
|
mode := "file"
|
||||||
if c.IsSet("filename") {
|
if c.IsSet("filename") {
|
||||||
vals["filename"] = c.String("filename")
|
vals["filename"] = c.String("filename")
|
||||||
@@ -236,7 +236,7 @@ func runAddFileLogger(c *cli.Context) error {
|
|||||||
return commonAddLogger(c, mode, vals)
|
return commonAddLogger(c, mode, vals)
|
||||||
}
|
}
|
||||||
|
|
||||||
func commonAddLogger(c *cli.Context, mode string, vals map[string]interface{}) error {
|
func commonAddLogger(c *cli.Context, mode string, vals map[string]any) error {
|
||||||
if len(c.String("level")) > 0 {
|
if len(c.String("level")) > 0 {
|
||||||
vals["level"] = log.LevelFromString(c.String("level")).String()
|
vals["level"] = log.LevelFromString(c.String("level")).String()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,6 +44,7 @@ var CmdServ = cli.Command{
|
|||||||
Name: "serv",
|
Name: "serv",
|
||||||
Usage: "This command should only be called by SSH shell",
|
Usage: "This command should only be called by SSH shell",
|
||||||
Description: "Serv provides access auth for repositories",
|
Description: "Serv provides access auth for repositories",
|
||||||
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Action: runServ,
|
Action: runServ,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
@@ -94,7 +95,7 @@ var (
|
|||||||
|
|
||||||
// fail prints message to stdout, it's mainly used for git serv and git hook commands.
|
// fail prints message to stdout, it's mainly used for git serv and git hook commands.
|
||||||
// The output will be passed to git client and shown to user.
|
// The output will be passed to git client and shown to user.
|
||||||
func fail(ctx context.Context, userMessage, logMsgFmt string, args ...interface{}) error {
|
func fail(ctx context.Context, userMessage, logMsgFmt string, args ...any) error {
|
||||||
if userMessage == "" {
|
if userMessage == "" {
|
||||||
userMessage = "Internal Server Error (no specific error)"
|
userMessage = "Internal Server Error (no specific error)"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,6 +35,7 @@ var CmdWeb = cli.Command{
|
|||||||
Usage: "Start Gitea web server",
|
Usage: "Start Gitea web server",
|
||||||
Description: `Gitea web server is the only thing you need to run,
|
Description: `Gitea web server is the only thing you need to run,
|
||||||
and it takes care of all the other things for you`,
|
and it takes care of all the other things for you`,
|
||||||
|
Before: PrepareConsoleLoggerLevel(log.INFO),
|
||||||
Action: runWeb,
|
Action: runWeb,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
@@ -206,11 +207,6 @@ func servePprof() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runWeb(ctx *cli.Context) error {
|
func runWeb(ctx *cli.Context) error {
|
||||||
if ctx.Bool("verbose") {
|
|
||||||
setupConsoleLogger(log.TRACE, log.CanColorStdout, os.Stdout)
|
|
||||||
} else if ctx.Bool("quiet") {
|
|
||||||
setupConsoleLogger(log.FATAL, log.CanColorStdout, os.Stdout)
|
|
||||||
}
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if panicked := recover(); panicked != nil {
|
if panicked := recover(); panicked != nil {
|
||||||
log.Fatal("PANIC: %v\n%s", panicked, log.Stack(2))
|
log.Fatal("PANIC: %v\n%s", panicked, log.Stack(2))
|
||||||
|
|||||||
@@ -5,7 +5,6 @@ package main
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
@@ -13,9 +12,6 @@ import (
|
|||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
|
|
||||||
// EnvironmentPrefix environment variables prefixed with this represent ini values to write
|
|
||||||
const EnvironmentPrefix = "GITEA"
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := cli.NewApp()
|
app := cli.NewApp()
|
||||||
app.Name = "environment-to-ini"
|
app.Name = "environment-to-ini"
|
||||||
@@ -70,15 +66,6 @@ func main() {
|
|||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Destination file to write to",
|
Usage: "Destination file to write to",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
|
||||||
Name: "clear",
|
|
||||||
Usage: "Clears the matched variables from the environment",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "prefix, p",
|
|
||||||
Value: EnvironmentPrefix,
|
|
||||||
Usage: "Environment prefix to look for - will be suffixed by __ (2 underscores)",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
app.Action = runEnvironmentToIni
|
app.Action = runEnvironmentToIni
|
||||||
err := app.Run(os.Args)
|
err := app.Run(os.Args)
|
||||||
@@ -88,7 +75,9 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runEnvironmentToIni(c *cli.Context) error {
|
func runEnvironmentToIni(c *cli.Context) error {
|
||||||
setting.InitWorkPathAndCommonConfig(os.Getenv, setting.ArgWorkPathAndCustomConf{
|
// the config system may change the environment variables, so get a copy first, to be used later
|
||||||
|
env := append([]string{}, os.Environ()...)
|
||||||
|
setting.InitWorkPathAndCfgProvider(os.Getenv, setting.ArgWorkPathAndCustomConf{
|
||||||
WorkPath: c.String("work-path"),
|
WorkPath: c.String("work-path"),
|
||||||
CustomPath: c.String("custom-path"),
|
CustomPath: c.String("custom-path"),
|
||||||
CustomConf: c.String("config"),
|
CustomConf: c.String("config"),
|
||||||
@@ -99,9 +88,7 @@ func runEnvironmentToIni(c *cli.Context) error {
|
|||||||
log.Fatal("Failed to load custom conf '%s': %v", setting.CustomConf, err)
|
log.Fatal("Failed to load custom conf '%s': %v", setting.CustomConf, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
prefixGitea := c.String("prefix") + "__"
|
changed := setting.EnvironmentToConfig(cfg, env)
|
||||||
suffixFile := "__FILE"
|
|
||||||
changed := setting.EnvironmentToConfig(cfg, prefixGitea, suffixFile, os.Environ())
|
|
||||||
|
|
||||||
// try to save the config file
|
// try to save the config file
|
||||||
destination := c.String("out")
|
destination := c.String("out")
|
||||||
@@ -116,19 +103,5 @@ func runEnvironmentToIni(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clear Gitea's specific environment variables if requested
|
|
||||||
if c.Bool("clear") {
|
|
||||||
for _, kv := range os.Environ() {
|
|
||||||
idx := strings.IndexByte(kv, '=')
|
|
||||||
if idx < 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
eKey := kv[:idx]
|
|
||||||
if strings.HasPrefix(eKey, prefixGitea) {
|
|
||||||
_ = os.Unsetenv(eKey)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,26 +16,23 @@
|
|||||||
;;
|
;;
|
||||||
;; - _`AppPath`_: This is the absolute path of the running gitea binary.
|
;; - _`AppPath`_: This is the absolute path of the running gitea binary.
|
||||||
;; - _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy:
|
;; - _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy:
|
||||||
|
;; - The "WORK_PATH" option in "app.ini" file
|
||||||
;; - The `--work-path` flag passed to the binary
|
;; - The `--work-path` flag passed to the binary
|
||||||
;; - The environment variable `$GITEA_WORK_DIR`
|
;; - The environment variable `$GITEA_WORK_DIR`
|
||||||
;; - A built-in value set at build time (see building from source)
|
;; - A built-in value set at build time (see building from source)
|
||||||
;; - Otherwise it defaults to the directory of the _`AppPath`_
|
;; - Otherwise it defaults to the directory of the _`AppPath`_
|
||||||
;; - If any of the above are relative paths then they are made absolute against
|
;; - If any of the above are relative paths then they are made absolute against the directory of the _`AppPath`_
|
||||||
;; the directory of the _`AppPath`_
|
;; - _`CustomPath`_: This is the base directory for custom templates and other options. It is determined by using the first set thing in the following hierarchy:
|
||||||
;; - _`CustomPath`_: This is the base directory for custom templates and other options.
|
|
||||||
;; It is determined by using the first set thing in the following hierarchy:
|
|
||||||
;; - The `--custom-path` flag passed to the binary
|
;; - The `--custom-path` flag passed to the binary
|
||||||
;; - The environment variable `$GITEA_CUSTOM`
|
;; - The environment variable `$GITEA_CUSTOM`
|
||||||
;; - A built-in value set at build time (see building from source)
|
;; - A built-in value set at build time (see building from source)
|
||||||
;; - Otherwise it defaults to _`AppWorkPath`_`/custom`
|
;; - Otherwise it defaults to _`AppWorkPath`_`/custom`
|
||||||
;; - If any of the above are relative paths then they are made absolute against the
|
;; - If any of the above are relative paths then they are made absolute against the directory of the _`AppWorkPath`_
|
||||||
;; the directory of the _`AppWorkPath`_
|
|
||||||
;; - _`CustomConf`_: This is the path to the `app.ini` file.
|
;; - _`CustomConf`_: This is the path to the `app.ini` file.
|
||||||
;; - The `--config` flag passed to the binary
|
;; - The `--config` flag passed to the binary
|
||||||
;; - A built-in value set at build time (see building from source)
|
;; - A built-in value set at build time (see building from source)
|
||||||
;; - Otherwise it defaults to _`CustomPath`_`/conf/app.ini`
|
;; - Otherwise it defaults to _`CustomPath`_`/conf/app.ini`
|
||||||
;; - If any of the above are relative paths then they are made absolute against the
|
;; - If any of the above are relative paths then they are made absolute against the directory of the _`CustomPath`_
|
||||||
;; the directory of the _`CustomPath`_
|
|
||||||
;;
|
;;
|
||||||
;; In addition there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
;; In addition there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
||||||
|
|
||||||
@@ -52,6 +49,9 @@ RUN_USER = ; git
|
|||||||
;; Application run mode, affects performance and debugging: "dev" or "prod", default is "prod"
|
;; Application run mode, affects performance and debugging: "dev" or "prod", default is "prod"
|
||||||
;; Mode "dev" makes Gitea easier to develop and debug, values other than "dev" are treated as "prod" which is for production use.
|
;; Mode "dev" makes Gitea easier to develop and debug, values other than "dev" are treated as "prod" which is for production use.
|
||||||
;RUN_MODE = prod
|
;RUN_MODE = prod
|
||||||
|
;;
|
||||||
|
;; The working directory, see the comment of AppWorkPath above
|
||||||
|
;WORK_PATH =
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
@@ -2541,8 +2541,8 @@ LEVEL = Info
|
|||||||
;; Enable/Disable actions capabilities
|
;; Enable/Disable actions capabilities
|
||||||
;ENABLED = false
|
;ENABLED = false
|
||||||
;;
|
;;
|
||||||
;; Default address to get action plugins, e.g. the default value means downloading from "https://gitea.com/actions/checkout" for "uses: actions/checkout@v3"
|
;; Default platform to get action plugins, `github` for `https://github.com`, `self` for the current Gitea instance.
|
||||||
;DEFAULT_ACTIONS_URL = https://gitea.com
|
;DEFAULT_ACTIONS_URL = github
|
||||||
|
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
|
|||||||
@@ -2,7 +2,15 @@
|
|||||||
|
|
||||||
if [ ! -d /data/git/.ssh ]; then
|
if [ ! -d /data/git/.ssh ]; then
|
||||||
mkdir -p /data/git/.ssh
|
mkdir -p /data/git/.ssh
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Set the correct permissions on the .ssh directory and authorized_keys file,
|
||||||
|
# or sshd will refuse to use them and lead to clone/push/pull failures.
|
||||||
|
# It could happen when users have copied their data to a new volume and changed the file permission by accident,
|
||||||
|
# and it would be very hard to troubleshoot unless users know how to check the logs of sshd which is started by s6.
|
||||||
chmod 700 /data/git/.ssh
|
chmod 700 /data/git/.ssh
|
||||||
|
if [ -f /data/git/.ssh/authorized_keys ]; then
|
||||||
|
chmod 600 /data/git/.ssh/authorized_keys
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! -f /data/git/.ssh/environment ]; then
|
if [ ! -f /data/git/.ssh/environment ]; then
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
#
|
#
|
||||||
# And place the original in /usr/lib/gitea with working files in /data/gitea
|
# And place the original in /usr/lib/gitea with working files in /data/gitea
|
||||||
GITEA="/app/gitea/gitea"
|
GITEA="/app/gitea/gitea"
|
||||||
WORK_DIR="/app/gitea"
|
WORK_DIR="/data/gitea"
|
||||||
CUSTOM_PATH="/data/gitea"
|
CUSTOM_PATH="/data/gitea"
|
||||||
|
|
||||||
# Provide docker defaults
|
# Provide docker defaults
|
||||||
|
|||||||
@@ -46,9 +46,9 @@ directory. There should be some output similar to the following:
|
|||||||
|
|
||||||
Inside the `gitea-dump-1482906742.zip` file, will be the following:
|
Inside the `gitea-dump-1482906742.zip` file, will be the following:
|
||||||
|
|
||||||
- `app.ini` - Optional copy of configuration file if originally stored outside of the default `custom/` directory
|
- `app.ini` - Optional copy of configuration file if originally stored outside the default `custom/` directory
|
||||||
- `custom` - All config or customization files in `custom/`.
|
- `custom` - All config or customization files in `custom/`.
|
||||||
- `data` - Data directory in <GITEA_WORK_DIR>, except sessions if you are using file session. This directory includes `attachments`, `avatars`, `lfs`, `indexers`, SQLite file if you are using SQLite.
|
- `data` - Data directory (APP_DATA_PATH), except sessions if you are using file session. This directory includes `attachments`, `avatars`, `lfs`, `indexers`, SQLite file if you are using SQLite.
|
||||||
- `gitea-db.sql` - SQL dump of database
|
- `gitea-db.sql` - SQL dump of database
|
||||||
- `gitea-repo.zip` - Complete copy of the repository directory.
|
- `gitea-repo.zip` - Complete copy of the repository directory.
|
||||||
- `log/` - Various logs. They are not needed for a recovery or migration.
|
- `log/` - Various logs. They are not needed for a recovery or migration.
|
||||||
@@ -139,16 +139,6 @@ chown -R git:git /data
|
|||||||
|
|
||||||
The default user in the gitea container is `git` (1000:1000). Please replace `2a83b293548e` with your gitea container id or name.
|
The default user in the gitea container is `git` (1000:1000). Please replace `2a83b293548e` with your gitea container id or name.
|
||||||
|
|
||||||
These are the default paths used in the container:
|
|
||||||
|
|
||||||
```text
|
|
||||||
DEFAULT CONFIGURATION:
|
|
||||||
CustomPath: /data/gitea (GITEA_CUSTOM)
|
|
||||||
CustomConf: /data/gitea/conf/app.ini
|
|
||||||
AppPath: /usr/local/bin/gitea
|
|
||||||
AppWorkPath: /usr/local/bin
|
|
||||||
```
|
|
||||||
|
|
||||||
### Using Docker-rootless (`restore`)
|
### Using Docker-rootless (`restore`)
|
||||||
|
|
||||||
The restore workflow in Docker-rootless containers differs only in the directories to be used:
|
The restore workflow in Docker-rootless containers differs only in the directories to be used:
|
||||||
|
|||||||
@@ -31,9 +31,9 @@ All global options can be placed at the command level.
|
|||||||
|
|
||||||
- `--help`, `-h`: Show help text and exit. Optional.
|
- `--help`, `-h`: Show help text and exit. Optional.
|
||||||
- `--version`, `-v`: Show version and exit. Optional. (example: `Gitea version 1.1.0+218-g7b907ed built with: bindata, sqlite`).
|
- `--version`, `-v`: Show version and exit. Optional. (example: `Gitea version 1.1.0+218-g7b907ed built with: bindata, sqlite`).
|
||||||
- `--custom-path path`, `-C path`: Location of the Gitea custom folder. Optional. (default: `AppWorkPath`/custom or `$GITEA_CUSTOM`).
|
- `--work-path path`, `-w path`: Gitea's work path. Optional. (default: the binary's path or `$GITEA_WORK_DIR`)
|
||||||
- `--config path`, `-c path`: Gitea configuration file path. Optional. (default: `custom`/conf/app.ini).
|
- `--custom-path path`, `-C path`: Gitea's custom folder path. Optional. (default: `WorkPath`/custom or `$GITEA_CUSTOM`).
|
||||||
- `--work-path path`, `-w path`: Gitea `AppWorkPath`. Optional. (default: LOCATION_OF_GITEA_BINARY or `$GITEA_WORK_DIR`)
|
- `--config path`, `-c path`: Gitea configuration file path. Optional. (default: `CustomPath`/conf/app.ini).
|
||||||
|
|
||||||
NB: The defaults custom-path, config and work-path can also be
|
NB: The defaults custom-path, config and work-path can also be
|
||||||
changed at build time (if preferred).
|
changed at build time (if preferred).
|
||||||
@@ -108,6 +108,14 @@ Admin operations:
|
|||||||
- `--all`, `-A`: Force a password change for all users
|
- `--all`, `-A`: Force a password change for all users
|
||||||
- `--exclude username`, `-e username`: Exclude the given user. Can be set multiple times.
|
- `--exclude username`, `-e username`: Exclude the given user. Can be set multiple times.
|
||||||
- `--unset`: Revoke forced password change for the given users
|
- `--unset`: Revoke forced password change for the given users
|
||||||
|
- `generate-access-token`:
|
||||||
|
- Options:
|
||||||
|
- `--username value`, `-u value`: Username. Required.
|
||||||
|
- `--token-name value`, `-t value`: Token name. Required.
|
||||||
|
- `--scopes value`: Comma-separated list of scopes. Scopes follow the format `[read|write]:<block>` or `all` where `<block>` is one of the available visual groups you can see when opening the API page showing the available routes (for example `repo`).
|
||||||
|
- Examples:
|
||||||
|
- `gitea admin user generate-access-token --username myname --token-name mytoken`
|
||||||
|
- `gitea admin user generate-access-token --help`
|
||||||
- `regenerate`
|
- `regenerate`
|
||||||
- Options:
|
- Options:
|
||||||
- `hooks`: Regenerate Git Hooks for all repositories
|
- `hooks`: Regenerate Git Hooks for all repositories
|
||||||
|
|||||||
@@ -44,28 +44,27 @@ reported as part of the default configuration when running `gitea --help` or on
|
|||||||
|
|
||||||
- _`AppPath`_: This is the absolute path of the running gitea binary.
|
- _`AppPath`_: This is the absolute path of the running gitea binary.
|
||||||
- _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy:
|
- _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy:
|
||||||
|
- The `WORK_PATH` option in `app.ini`
|
||||||
- The `--work-path` flag passed to the binary
|
- The `--work-path` flag passed to the binary
|
||||||
- The environment variable `$GITEA_WORK_DIR`
|
- The environment variable `$GITEA_WORK_DIR`
|
||||||
- A built-in value set at build time (see building from source)
|
- A built-in value set at build time (see building from source)
|
||||||
- Otherwise it defaults to the directory of the _`AppPath`_
|
- Otherwise, it defaults to the directory of the _`AppPath`_
|
||||||
- If any of the above are relative paths then they are made absolute against
|
- If any of the above are relative paths then they are made absolute against the directory of the _`AppPath`_
|
||||||
the directory of the _`AppPath`_
|
|
||||||
- _`CustomPath`_: This is the base directory for custom templates and other options.
|
- _`CustomPath`_: This is the base directory for custom templates and other options.
|
||||||
It is determined by using the first set thing in the following hierarchy:
|
It is determined by using the first set thing in the following hierarchy:
|
||||||
- The `--custom-path` flag passed to the binary
|
- The `--custom-path` flag passed to the binary
|
||||||
- The environment variable `$GITEA_CUSTOM`
|
- The environment variable `$GITEA_CUSTOM`
|
||||||
- A built-in value set at build time (see building from source)
|
- A built-in value set at build time (see building from source)
|
||||||
- Otherwise it defaults to _`AppWorkPath`_`/custom`
|
- Otherwise, it defaults to _`AppWorkPath`_`/custom`
|
||||||
- If any of the above are relative paths then they are made absolute against the
|
- If any of the above are relative paths then they are made absolute against the
|
||||||
the directory of the _`AppWorkPath`_
|
the directory of the _`AppWorkPath`_
|
||||||
- _`CustomConf`_: This is the path to the `app.ini` file.
|
- _`CustomConf`_: This is the path to the `app.ini` file.
|
||||||
- The `--config` flag passed to the binary
|
- The `--config` flag passed to the binary
|
||||||
- A built-in value set at build time (see building from source)
|
- A built-in value set at build time (see building from source)
|
||||||
- Otherwise it defaults to _`CustomPath`_`/conf/app.ini`
|
- Otherwise, it defaults to _`CustomPath`_`/conf/app.ini`
|
||||||
- If any of the above are relative paths then they are made absolute against the
|
- If any of the above are relative paths then they are made absolute against the directory of the _`CustomPath`_
|
||||||
the directory of the _`CustomPath`_
|
|
||||||
|
|
||||||
In addition there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
In addition, there is _`StaticRootPath`_ which can be set as a built-in at build time, but will otherwise default to _`AppWorkPath`_
|
||||||
|
|
||||||
## Overall (`DEFAULT`)
|
## Overall (`DEFAULT`)
|
||||||
|
|
||||||
@@ -74,6 +73,7 @@ In addition there is _`StaticRootPath`_ which can be set as a built-in at build
|
|||||||
This should be a dedicated system (non-user) account. Setting this incorrectly will cause Gitea
|
This should be a dedicated system (non-user) account. Setting this incorrectly will cause Gitea
|
||||||
to not start.
|
to not start.
|
||||||
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging: `dev` or `prod`, default is `prod`. Mode `dev` makes Gitea easier to develop and debug, values other than `dev` are treated as `prod` which is for production use.
|
- `RUN_MODE`: **prod**: Application run mode, affects performance and debugging: `dev` or `prod`, default is `prod`. Mode `dev` makes Gitea easier to develop and debug, values other than `dev` are treated as `prod` which is for production use.
|
||||||
|
- `WORK_PATH`: **_the-work-path_**: The working directory, see the comment of AppWorkPath above.
|
||||||
|
|
||||||
## Repository (`repository`)
|
## Repository (`repository`)
|
||||||
|
|
||||||
@@ -1374,39 +1374,22 @@ PROXY_HOSTS = *.github.com
|
|||||||
## Actions (`actions`)
|
## Actions (`actions`)
|
||||||
|
|
||||||
- `ENABLED`: **false**: Enable/Disable actions capabilities
|
- `ENABLED`: **false**: Enable/Disable actions capabilities
|
||||||
- `DEFAULT_ACTIONS_URL`: **https://gitea.com**: Default address to get action plugins, e.g. the default value means downloading from "<https://gitea.com/actions/checkout>" for "uses: actions/checkout@v3"
|
- `DEFAULT_ACTIONS_URL`: **github**: Default platform to get action plugins, `github` for `https://github.com`, `self` for the current Gitea instance.
|
||||||
- `STORAGE_TYPE`: **local**: Storage type for actions logs, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]`
|
- `STORAGE_TYPE`: **local**: Storage type for actions logs, `local` for local disk or `minio` for s3 compatible object storage service, default is `local` or other name defined with `[storage.xxx]`
|
||||||
- `MINIO_BASE_PATH`: **actions_log/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
|
- `MINIO_BASE_PATH`: **actions_log/**: Minio base path on the bucket only available when STORAGE_TYPE is `minio`
|
||||||
|
|
||||||
`DEFAULT_ACTIONS_URL` indicates where should we find the relative path action plugin. i.e. when use an action in a workflow file like
|
`DEFAULT_ACTIONS_URL` indicates where the Gitea Actions runners should find the actions with relative path.
|
||||||
|
For example, `uses: actions/checkout@v3` means `https://github.com/actions/checkout@v3` since the value of `DEFAULT_ACTIONS_URL` is `github`.
|
||||||
|
And it can be changed to `self` to make it `root_url_of_your_gitea/actions/checkout@v3`.
|
||||||
|
|
||||||
```yaml
|
Please note that using `self` is not recommended for most cases, as it could make names globally ambiguous.
|
||||||
name: versions
|
Additionally, it requires you to mirror all the actions you need to your Gitea instance, which may not be worth it.
|
||||||
on:
|
Therefore, please use `self` only if you understand what you are doing.
|
||||||
push:
|
|
||||||
branches:
|
|
||||||
- main
|
|
||||||
- releases/*
|
|
||||||
jobs:
|
|
||||||
build:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- uses: actions/checkout@v3
|
|
||||||
```
|
|
||||||
|
|
||||||
Now we need to know how to get actions/checkout, this configuration is the default git server to get it. That means we will get the repository via git clone ${DEFAULT_ACTIONS_URL}/actions/checkout and fetch tag v3.
|
In earlier versions (<= 1.19), `DEFAULT_ACTIONS_URL` cound be set to any custom URLs like `https://gitea.com` or `http://your-git-server,https://gitea.com`, and the default value was `https://gitea.com`.
|
||||||
|
However, later updates removed those options, and now the only options are `github` and `self`, with the default value being `github`.
|
||||||
To help people who don't want to mirror these actions in their git instances, the default value is https://gitea.com
|
However, if you want to use actions from other git server, you can use a complete URL in `uses` field, it's supported by Gitea (but not GitHub).
|
||||||
To help people run actions totally in their network, they can change the value and copy all necessary action repositories into their git server.
|
Like `uses: https://gitea.com/actions/checkout@v3` or `uses: http://your-git-server/actions/checkout@v3`.
|
||||||
|
|
||||||
Of course we should support the form in future PRs like
|
|
||||||
|
|
||||||
```yaml
|
|
||||||
steps:
|
|
||||||
- uses: gitea.com/actions/checkout@v3
|
|
||||||
```
|
|
||||||
|
|
||||||
although Github don't support this form.
|
|
||||||
|
|
||||||
## Other (`other`)
|
## Other (`other`)
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ menu:
|
|||||||
# Customizing Gitea
|
# Customizing Gitea
|
||||||
|
|
||||||
Customizing Gitea is typically done using the `CustomPath` folder - by default this is
|
Customizing Gitea is typically done using the `CustomPath` folder - by default this is
|
||||||
the `custom` folder from the running directory, but may be different if your build has
|
the `custom` folder from the working directory (WorkPath), but may be different if your build has
|
||||||
set this differently. This is the central place to override configuration settings,
|
set this differently. This is the central place to override configuration settings,
|
||||||
templates, etc. You can check the `CustomPath` using `gitea help`. You can also find
|
templates, etc. You can check the `CustomPath` using `gitea help`. You can also find
|
||||||
the path on the _Configuration_ tab in the _Site Administration_ page. You can override
|
the path on the _Configuration_ tab in the _Site Administration_ page. You can override
|
||||||
|
|||||||
@@ -43,10 +43,7 @@ For documentation about each of the variables available, refer to the
|
|||||||
## Gitea files
|
## Gitea files
|
||||||
|
|
||||||
- `GITEA_WORK_DIR`: Absolute path of working directory.
|
- `GITEA_WORK_DIR`: Absolute path of working directory.
|
||||||
- `GITEA_CUSTOM`: Gitea uses `GITEA_WORK_DIR`/custom folder by default. Use this variable
|
- `GITEA_CUSTOM`: Gitea uses `WorkPath`/custom folder by default. Use this variable to change _custom_ directory.
|
||||||
to change _custom_ directory.
|
|
||||||
- `GOGS_WORK_DIR`: Deprecated, use `GITEA_WORK_DIR`
|
|
||||||
- `GOGS_CUSTOM`: Deprecated, use `GITEA_CUSTOM`
|
|
||||||
|
|
||||||
## Operating system specifics
|
## Operating system specifics
|
||||||
|
|
||||||
|
|||||||
@@ -59,11 +59,12 @@ https://github.com/loganinak/MigrateGitlabToGogs
|
|||||||
## Where does Gitea store what file
|
## Where does Gitea store what file
|
||||||
|
|
||||||
- _`AppWorkPath`_
|
- _`AppWorkPath`_
|
||||||
- The `--work-path` flag
|
- The `WORK_PATH` option in `app.ini`
|
||||||
|
- Else the `--work-path` flag
|
||||||
- Else Environment variable `GITEA_WORK_DIR`
|
- Else Environment variable `GITEA_WORK_DIR`
|
||||||
- Else a built-in value set at build time
|
- Else a built-in value set at build time
|
||||||
- Else the directory that contains the Gitea binary
|
- Else the directory that contains the Gitea binary
|
||||||
- `%(APP_DATA_PATH)` (default for database, indexers, etc.)
|
- `AppDataPath` (default for database, indexers, etc.)
|
||||||
- `APP_DATA_PATH` from `app.ini`
|
- `APP_DATA_PATH` from `app.ini`
|
||||||
- Else _`AppWorkPath`_`/data`
|
- Else _`AppWorkPath`_`/data`
|
||||||
- _`CustomPath`_ (custom templates)
|
- _`CustomPath`_ (custom templates)
|
||||||
@@ -112,9 +113,6 @@ Gitea's custom templates must be added to the correct location or Gitea will not
|
|||||||
The correct path for the template(s) will be relative to the `CustomPath`
|
The correct path for the template(s) will be relative to the `CustomPath`
|
||||||
|
|
||||||
1. To find `CustomPath`, look for Custom File Root Path in Site Administration -> Configuration
|
1. To find `CustomPath`, look for Custom File Root Path in Site Administration -> Configuration
|
||||||
|
|
||||||
If that doesn't exist, you can try `echo $GITEA_CUSTOM`
|
|
||||||
|
|
||||||
2. If you are still unable to find a path, the default can be [calculated above](#where-does-gitea-store-what-file)
|
2. If you are still unable to find a path, the default can be [calculated above](#where-does-gitea-store-what-file)
|
||||||
3. Once you have figured out the correct custom path, you can refer to the [customizing Gitea]({{< relref "doc/administration/customizing-gitea.en-us.md" >}}) page to add your template to the correct location.
|
3. Once you have figured out the correct custom path, you can refer to the [customizing Gitea]({{< relref "doc/administration/customizing-gitea.en-us.md" >}}) page to add your template to the correct location.
|
||||||
|
|
||||||
|
|||||||
@@ -67,7 +67,7 @@ sudo chown 1000:1000 config/ data/
|
|||||||
|
|
||||||
> If you don't give the volume correct permissions, the container may not start.
|
> If you don't give the volume correct permissions, the container may not start.
|
||||||
|
|
||||||
For a stable release you could use `:latest-rootless`, `:1-rootless` or specify a certain release like `:{{< version >}}-rootless`, but if you'd like to use the latest development version then `:dev-rootless` would be an appropriate tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-dev-rootless` tag, where x is the minor version of Gitea. (e.g. `:1.16-dev-rootless`)
|
For a stable release you could use `:latest-rootless`, `:1-rootless` or specify a certain release like `:{{< version >}}-rootless`, but if you'd like to use the latest development version then `:nightly-rootless` would be an appropriate tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-nightly-rootless` tag, where x is the minor version of Gitea. (e.g. `:1.16-nightly-rootless`)
|
||||||
|
|
||||||
## Custom port
|
## Custom port
|
||||||
|
|
||||||
@@ -119,7 +119,7 @@ services:
|
|||||||
- /etc/localtime:/etc/localtime:ro
|
- /etc/localtime:/etc/localtime:ro
|
||||||
ports:
|
ports:
|
||||||
- "3000:3000"
|
- "3000:3000"
|
||||||
- "222:22"
|
- "2222:2222"
|
||||||
+ depends_on:
|
+ depends_on:
|
||||||
+ - db
|
+ - db
|
||||||
+
|
+
|
||||||
@@ -288,7 +288,7 @@ docker-compose up -d
|
|||||||
|
|
||||||
In addition to the environment variables above, any settings in `app.ini` can be set
|
In addition to the environment variables above, any settings in `app.ini` can be set
|
||||||
or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`.
|
or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`.
|
||||||
These settings are applied each time the docker container starts.
|
These settings are applied each time the docker container starts, and won't be passed into Gitea's sub-processes.
|
||||||
Full information [here](https://github.com/go-gitea/gitea/tree/main/contrib/environment-to-ini).
|
Full information [here](https://github.com/go-gitea/gitea/tree/main/contrib/environment-to-ini).
|
||||||
|
|
||||||
These environment variables can be passed to the docker container in `docker-compose.yml`.
|
These environment variables can be passed to the docker container in `docker-compose.yml`.
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ image as a service. Since there is no database available, one can be initialized
|
|||||||
Create a directory like `gitea` and paste the following content into a file named `docker-compose.yml`.
|
Create a directory like `gitea` and paste the following content into a file named `docker-compose.yml`.
|
||||||
Note that the volume should be owned by the user/group with the UID/GID specified in the config file.
|
Note that the volume should be owned by the user/group with the UID/GID specified in the config file.
|
||||||
If you don't give the volume correct permissions, the container may not start.
|
If you don't give the volume correct permissions, the container may not start.
|
||||||
For a stable release you can use `:latest`, `:1` or specify a certain release like `:{{< version >}}`, but if you'd like to use the latest development version of Gitea then you could use the `:dev` tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-dev` tag, where x is the minor version of Gitea. (e.g. `:1.16-dev`)
|
For a stable release you can use `:latest`, `:1` or specify a certain release like `:{{< version >}}`, but if you'd like to use the latest development version of Gitea then you could use the `:nightly` tag. If you'd like to run the latest commit from a release branch you can use the `:1.x-nightly` tag, where x is the minor version of Gitea. (e.g. `:1.16-nightly`)
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
version: "3"
|
version: "3"
|
||||||
@@ -289,7 +289,7 @@ docker-compose up -d
|
|||||||
|
|
||||||
In addition to the environment variables above, any settings in `app.ini` can be set
|
In addition to the environment variables above, any settings in `app.ini` can be set
|
||||||
or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`.
|
or overridden with an environment variable of the form: `GITEA__SECTION_NAME__KEY_NAME`.
|
||||||
These settings are applied each time the docker container starts.
|
These settings are applied each time the docker container starts, and won't be passed into Gitea's sub-processes.
|
||||||
Full information [here](https://github.com/go-gitea/gitea/tree/master/contrib/environment-to-ini).
|
Full information [here](https://github.com/go-gitea/gitea/tree/master/contrib/environment-to-ini).
|
||||||
|
|
||||||
These environment variables can be passed to the docker container in `docker-compose.yml`.
|
These environment variables can be passed to the docker container in `docker-compose.yml`.
|
||||||
|
|||||||
@@ -164,3 +164,23 @@ Although we would like to provide more options, our limited manpower means that
|
|||||||
However, both Gitea and act runner are completely open source, so anyone can create a new/better implementation.
|
However, both Gitea and act runner are completely open source, so anyone can create a new/better implementation.
|
||||||
We support your choice, no matter how you decide.
|
We support your choice, no matter how you decide.
|
||||||
In case you fork act runner to create your own version: Please contribute the changes back if you can and if you think your changes will help others as well.
|
In case you fork act runner to create your own version: Please contribute the changes back if you can and if you think your changes will help others as well.
|
||||||
|
|
||||||
|
## What workflow trigger events does Gitea support?
|
||||||
|
|
||||||
|
All events listed in this table are supported events and are compatible with GitHub.
|
||||||
|
For events supported only by GitHub, see GitHub's [documentation](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows).
|
||||||
|
|
||||||
|
| trigger event | activity types |
|
||||||
|
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| create | not applicable |
|
||||||
|
| delete | not applicable |
|
||||||
|
| fork | not applicable |
|
||||||
|
| gollum | not applicable |
|
||||||
|
| push | not applicable |
|
||||||
|
| issues | `opened`, `edited`, `closed`, `reopened`, `assigned`, `unassigned`, `milestoned`, `demilestoned`, `labeled`, `unlabeled` |
|
||||||
|
| issue_comment | `created`, `edited`, `deleted` |
|
||||||
|
| pull_request | `opened`, `edited`, `closed`, `reopened`, `assigned`, `unassigned`, `synchronize`, `labeled`, `unlabeled` |
|
||||||
|
| pull_request_review | `submitted`, `edited` |
|
||||||
|
| pull_request_review_comment | `created`, `edited` |
|
||||||
|
| release | `published`, `edited` |
|
||||||
|
| registry_package | `published` |
|
||||||
|
|||||||
@@ -164,3 +164,23 @@ defaults:
|
|||||||
然而,无论您如何决定,Gitea 和act runner都是完全开源的,所以任何人都可以创建一个新的/更好的实现。
|
然而,无论您如何决定,Gitea 和act runner都是完全开源的,所以任何人都可以创建一个新的/更好的实现。
|
||||||
我们支持您的选择,无论您如何决定。
|
我们支持您的选择,无论您如何决定。
|
||||||
如果您选择分支act runner来创建自己的版本,请在您认为您的更改对其他人也有帮助的情况下贡献这些更改。
|
如果您选择分支act runner来创建自己的版本,请在您认为您的更改对其他人也有帮助的情况下贡献这些更改。
|
||||||
|
|
||||||
|
## Gitea 支持哪些工作流触发事件?
|
||||||
|
|
||||||
|
表格中列出的所有事件都是支持的,并且与 GitHub 兼容。
|
||||||
|
对于仅 GitHub 支持的事件,请参阅 GitHub 的[文档](https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows)。
|
||||||
|
|
||||||
|
| 触发事件 | 活动类型 |
|
||||||
|
|-----------------------------|--------------------------------------------------------------------------------------------------------------------------|
|
||||||
|
| create | 不适用 |
|
||||||
|
| delete | 不适用 |
|
||||||
|
| fork | 不适用 |
|
||||||
|
| gollum | 不适用 |
|
||||||
|
| push | 不适用 |
|
||||||
|
| issues | `opened`, `edited`, `closed`, `reopened`, `assigned`, `unassigned`, `milestoned`, `demilestoned`, `labeled`, `unlabeled` |
|
||||||
|
| issue_comment | `created`, `edited`, `deleted` |
|
||||||
|
| pull_request | `opened`, `edited`, `closed`, `reopened`, `assigned`, `unassigned`, `synchronize`, `labeled`, `unlabeled` |
|
||||||
|
| pull_request_review | `submitted`, `edited` |
|
||||||
|
| pull_request_review_comment | `created`, `edited` |
|
||||||
|
| release | `published`, `edited` |
|
||||||
|
| registry_package | `published` |
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ The following package managers are currently supported:
|
|||||||
| [NuGet]({{< relref "doc/usage/packages/nuget.en-us.md" >}}) | .NET | `nuget` |
|
| [NuGet]({{< relref "doc/usage/packages/nuget.en-us.md" >}}) | .NET | `nuget` |
|
||||||
| [Pub]({{< relref "doc/usage/packages/pub.en-us.md" >}}) | Dart | `dart`, `flutter` |
|
| [Pub]({{< relref "doc/usage/packages/pub.en-us.md" >}}) | Dart | `dart`, `flutter` |
|
||||||
| [PyPI]({{< relref "doc/usage/packages/pypi.en-us.md" >}}) | Python | `pip`, `twine` |
|
| [PyPI]({{< relref "doc/usage/packages/pypi.en-us.md" >}}) | Python | `pip`, `twine` |
|
||||||
| [RPM]({{< relref "doc/usage/packages/rpm.en-us.md" >}}) | - | `yum`, `dnf` |
|
| [RPM]({{< relref "doc/usage/packages/rpm.en-us.md" >}}) | - | `yum`, `dnf`, `zypper` |
|
||||||
| [RubyGems]({{< relref "doc/usage/packages/rubygems.en-us.md" >}}) | Ruby | `gem`, `Bundler` |
|
| [RubyGems]({{< relref "doc/usage/packages/rubygems.en-us.md" >}}) | Ruby | `gem`, `Bundler` |
|
||||||
| [Swift]({{< relref "doc/usage/packages/rubygems.en-us.md" >}}) | Swift | `swift` |
|
| [Swift]({{< relref "doc/usage/packages/rubygems.en-us.md" >}}) | Swift | `swift` |
|
||||||
| [Vagrant]({{< relref "doc/usage/packages/vagrant.en-us.md" >}}) | - | `vagrant` |
|
| [Vagrant]({{< relref "doc/usage/packages/vagrant.en-us.md" >}}) | - | `vagrant` |
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ menu:
|
|||||||
| [NuGet]({{< relref "doc/usage/packages/nuget.zh-cn.md" >}}) | .NET | `nuget` |
|
| [NuGet]({{< relref "doc/usage/packages/nuget.zh-cn.md" >}}) | .NET | `nuget` |
|
||||||
| [Pub]({{< relref "doc/usage/packages/pub.zh-cn.md" >}}) | Dart | `dart`, `flutter` |
|
| [Pub]({{< relref "doc/usage/packages/pub.zh-cn.md" >}}) | Dart | `dart`, `flutter` |
|
||||||
| [PyPI]({{< relref "doc/usage/packages/pypi.zh-cn.md" >}}) | Python | `pip`, `twine` |
|
| [PyPI]({{< relref "doc/usage/packages/pypi.zh-cn.md" >}}) | Python | `pip`, `twine` |
|
||||||
| [RPM]({{< relref "doc/usage/packages/rpm.zh-cn.md" >}}) | - | `yum`, `dnf` |
|
| [RPM]({{< relref "doc/usage/packages/rpm.zh-cn.md" >}}) | - | `yum`, `dnf`, `zypper` |
|
||||||
| [RubyGems]({{< relref "doc/usage/packages/rubygems.zh-cn.md" >}}) | Ruby | `gem`, `Bundler` |
|
| [RubyGems]({{< relref "doc/usage/packages/rubygems.zh-cn.md" >}}) | Ruby | `gem`, `Bundler` |
|
||||||
| [Swift]({{< relref "doc/usage/packages/rubygems.zh-cn.md" >}}) | Swift | `swift` |
|
| [Swift]({{< relref "doc/usage/packages/rubygems.zh-cn.md" >}}) | Swift | `swift` |
|
||||||
| [Vagrant]({{< relref "doc/usage/packages/vagrant.zh-cn.md" >}}) | - | `vagrant` |
|
| [Vagrant]({{< relref "doc/usage/packages/vagrant.zh-cn.md" >}}) | - | `vagrant` |
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ Publish [RPM](https://rpm.org/) packages for your user or organization.
|
|||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
To work with the RPM registry, you need to use a package manager like `yum` or `dnf` to consume packages.
|
To work with the RPM registry, you need to use a package manager like `yum`, `dnf` or `zypper` to consume packages.
|
||||||
|
|
||||||
The following examples use `dnf`.
|
The following examples use `dnf`.
|
||||||
|
|
||||||
@@ -79,7 +79,7 @@ The server responds with the following HTTP Status codes.
|
|||||||
|
|
||||||
## Delete a package
|
## Delete a package
|
||||||
|
|
||||||
To delete a Debian package perform a HTTP DELETE operation. This will delete the package version too if there is no file left.
|
To delete an RPM package perform a HTTP DELETE operation. This will delete the package version too if there is no file left.
|
||||||
|
|
||||||
```
|
```
|
||||||
DELETE https://gitea.example.com/api/packages/{owner}/rpm/{package_name}/{package_version}/{architecture}
|
DELETE https://gitea.example.com/api/packages/{owner}/rpm/{package_name}/{package_version}/{architecture}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ menu:
|
|||||||
|
|
||||||
## 要求
|
## 要求
|
||||||
|
|
||||||
要使用RPM注册表,您需要使用像 `yum` 或 `dnf` 这样的软件包管理器来消费软件包。
|
要使用RPM注册表,您需要使用像 `yum`, `dnf` 或 `zypper` 这样的软件包管理器来消费软件包。
|
||||||
|
|
||||||
以下示例使用 `dnf`。
|
以下示例使用 `dnf`。
|
||||||
|
|
||||||
|
|||||||
12
go.mod
12
go.mod
@@ -76,7 +76,7 @@ require (
|
|||||||
github.com/mattn/go-sqlite3 v1.14.16
|
github.com/mattn/go-sqlite3 v1.14.16
|
||||||
github.com/meilisearch/meilisearch-go v0.24.0
|
github.com/meilisearch/meilisearch-go v0.24.0
|
||||||
github.com/mholt/archiver/v3 v3.5.1
|
github.com/mholt/archiver/v3 v3.5.1
|
||||||
github.com/microcosm-cc/bluemonday v1.0.24
|
github.com/microcosm-cc/bluemonday v1.0.25
|
||||||
github.com/minio/minio-go/v7 v7.0.52
|
github.com/minio/minio-go/v7 v7.0.52
|
||||||
github.com/minio/sha256-simd v1.0.0
|
github.com/minio/sha256-simd v1.0.0
|
||||||
github.com/msteinert/pam v1.1.0
|
github.com/msteinert/pam v1.1.0
|
||||||
@@ -107,12 +107,12 @@ require (
|
|||||||
github.com/yuin/goldmark v1.5.4
|
github.com/yuin/goldmark v1.5.4
|
||||||
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20220924101305-151362477c87
|
github.com/yuin/goldmark-highlighting/v2 v2.0.0-20220924101305-151362477c87
|
||||||
github.com/yuin/goldmark-meta v1.1.0
|
github.com/yuin/goldmark-meta v1.1.0
|
||||||
golang.org/x/crypto v0.9.0
|
golang.org/x/crypto v0.11.0
|
||||||
golang.org/x/image v0.7.0
|
golang.org/x/image v0.7.0
|
||||||
golang.org/x/net v0.10.0
|
golang.org/x/net v0.12.0
|
||||||
golang.org/x/oauth2 v0.8.0
|
golang.org/x/oauth2 v0.8.0
|
||||||
golang.org/x/sys v0.8.0
|
golang.org/x/sys v0.10.0
|
||||||
golang.org/x/text v0.9.0
|
golang.org/x/text v0.11.0
|
||||||
golang.org/x/tools v0.8.0
|
golang.org/x/tools v0.8.0
|
||||||
google.golang.org/grpc v1.53.0
|
google.golang.org/grpc v1.53.0
|
||||||
google.golang.org/protobuf v1.30.0
|
google.golang.org/protobuf v1.30.0
|
||||||
@@ -122,7 +122,7 @@ require (
|
|||||||
mvdan.cc/xurls/v2 v2.4.0
|
mvdan.cc/xurls/v2 v2.4.0
|
||||||
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
|
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251
|
||||||
xorm.io/builder v0.3.12
|
xorm.io/builder v0.3.12
|
||||||
xorm.io/xorm v1.3.3-0.20230219231735-056cecc97e9e
|
xorm.io/xorm v1.3.3-0.20230623150031-18f8e7a86c75
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
|||||||
25
go.sum
25
go.sum
@@ -877,8 +877,8 @@ github.com/mholt/acmez v1.1.0 h1:IQ9CGHKOHokorxnffsqDvmmE30mDenO1lptYZ1AYkHY=
|
|||||||
github.com/mholt/acmez v1.1.0/go.mod h1:zwo5+fbLLTowAX8o8ETfQzbDtwGEXnPhkmGdKIP+bgs=
|
github.com/mholt/acmez v1.1.0/go.mod h1:zwo5+fbLLTowAX8o8ETfQzbDtwGEXnPhkmGdKIP+bgs=
|
||||||
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
|
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
|
||||||
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.24 h1:NGQoPtwGVcbGkKfvyYk1yRqknzBuoMiUrO6R7uFTPlw=
|
github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.24/go.mod h1:ArQySAMps0790cHSkdPEJ7bGkF2VePWH773hsJNSHf8=
|
github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE=
|
||||||
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
|
||||||
github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI=
|
github.com/miekg/dns v1.1.54 h1:5jon9mWcb0sFJGpnI99tOMhCPyJ+RPVz5b63MQG0VWI=
|
||||||
github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
github.com/miekg/dns v1.1.54/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
||||||
@@ -1322,8 +1322,8 @@ golang.org/x/crypto v0.3.0/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4
|
|||||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/crypto v0.9.0 h1:LF6fAI+IutBocDJ2OT0Q1g8plpYljMZ4+lty+dsqw3g=
|
golang.org/x/crypto v0.11.0 h1:6Ewdq3tDic1mg5xRO4milcWCfMVQhI4NkqWWvqejpuA=
|
||||||
golang.org/x/crypto v0.9.0/go.mod h1:yrmDGqONDYtNj3tH8X9dzUun2m2lzPa9ngI6/RUPGR0=
|
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||||
@@ -1421,8 +1421,8 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||||
golang.org/x/net v0.10.0 h1:X2//UzNDwYmtCLn7To6G58Wr6f5ahEAQgKNzv9Y951M=
|
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||||
@@ -1534,8 +1534,8 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0 h1:EBmGv8NaZBZTWvrbjNoL6HVt+IVy3QDQpJs7VRIw3tU=
|
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
@@ -1545,7 +1545,7 @@ golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc=
|
|||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
||||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||||
golang.org/x/term v0.8.0 h1:n5xxQn2i3PC0yLAbjTpNT85q/Kgzcr2gIoX9OrJUols=
|
golang.org/x/term v0.10.0 h1:3R7pNqamzBraeqj/Tj8qt1aQ2HpmlC+Cx/qL/7hn4/c=
|
||||||
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
@@ -1558,8 +1558,9 @@ golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
|||||||
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
|
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
|
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
|
||||||
|
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
@@ -1923,5 +1924,5 @@ strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:
|
|||||||
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
xorm.io/builder v0.3.11-0.20220531020008-1bd24a7dc978/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||||
xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM=
|
xorm.io/builder v0.3.12 h1:ASZYX7fQmy+o8UJdhlLHSW57JDOkM8DNhcAF5d0LiJM=
|
||||||
xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
xorm.io/builder v0.3.12/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
|
||||||
xorm.io/xorm v1.3.3-0.20230219231735-056cecc97e9e h1:d5PY6mwuQK5/7T6VKfFswaKMzLmGTHkJ/ZS7+cUIAjk=
|
xorm.io/xorm v1.3.3-0.20230623150031-18f8e7a86c75 h1:ReBAlO50dCIXCWF8Gbi0ZRa62AGAwCJNCPaUNUa7JSg=
|
||||||
xorm.io/xorm v1.3.3-0.20230219231735-056cecc97e9e/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw=
|
xorm.io/xorm v1.3.3-0.20230623150031-18f8e7a86c75/go.mod h1:9NbjqdnjX6eyjRRhh01GHm64r6N9shTb/8Ak3YRt8Nw=
|
||||||
|
|||||||
45
main.go
45
main.go
@@ -47,7 +47,9 @@ func init() {
|
|||||||
// ./gitea -h
|
// ./gitea -h
|
||||||
// ./gitea web help
|
// ./gitea web help
|
||||||
// ./gitea web -h (due to cli lib limitation, this won't call our cmdHelp, so no extra info)
|
// ./gitea web -h (due to cli lib limitation, this won't call our cmdHelp, so no extra info)
|
||||||
// ./gitea admin help auth
|
// ./gitea admin
|
||||||
|
// ./gitea admin help
|
||||||
|
// ./gitea admin auth help
|
||||||
// ./gitea -c /tmp/app.ini -h
|
// ./gitea -c /tmp/app.ini -h
|
||||||
// ./gitea -c /tmp/app.ini help
|
// ./gitea -c /tmp/app.ini help
|
||||||
// ./gitea help -c /tmp/app.ini
|
// ./gitea help -c /tmp/app.ini
|
||||||
@@ -85,28 +87,36 @@ func main() {
|
|||||||
app.Description = `By default, Gitea will start serving using the web-server with no argument, which can alternatively be run by running the subcommand "web".`
|
app.Description = `By default, Gitea will start serving using the web-server with no argument, which can alternatively be run by running the subcommand "web".`
|
||||||
app.Version = Version + formatBuiltWith()
|
app.Version = Version + formatBuiltWith()
|
||||||
app.EnableBashCompletion = true
|
app.EnableBashCompletion = true
|
||||||
app.Commands = []cli.Command{
|
|
||||||
|
// these sub-commands need to use config file
|
||||||
|
subCmdWithIni := []cli.Command{
|
||||||
cmd.CmdWeb,
|
cmd.CmdWeb,
|
||||||
cmd.CmdServ,
|
cmd.CmdServ,
|
||||||
cmd.CmdHook,
|
cmd.CmdHook,
|
||||||
cmd.CmdDump,
|
cmd.CmdDump,
|
||||||
cmd.CmdCert,
|
|
||||||
cmd.CmdAdmin,
|
cmd.CmdAdmin,
|
||||||
cmd.CmdGenerate,
|
|
||||||
cmd.CmdMigrate,
|
cmd.CmdMigrate,
|
||||||
cmd.CmdKeys,
|
cmd.CmdKeys,
|
||||||
cmd.CmdConvert,
|
cmd.CmdConvert,
|
||||||
cmd.CmdDoctor,
|
cmd.CmdDoctor,
|
||||||
cmd.CmdManager,
|
cmd.CmdManager,
|
||||||
cmd.Cmdembedded,
|
cmd.CmdEmbedded,
|
||||||
cmd.CmdMigrateStorage,
|
cmd.CmdMigrateStorage,
|
||||||
cmd.CmdDocs,
|
|
||||||
cmd.CmdDumpRepository,
|
cmd.CmdDumpRepository,
|
||||||
cmd.CmdRestoreRepository,
|
cmd.CmdRestoreRepository,
|
||||||
cmd.CmdActions,
|
cmd.CmdActions,
|
||||||
|
cmdHelp, // TODO: the "help" sub-command was used to show the more information for "work path" and "custom config", in the future, it should avoid doing so
|
||||||
|
}
|
||||||
|
// these sub-commands do not need the config file, and they do not depend on any path or environment variable.
|
||||||
|
subCmdStandalone := []cli.Command{
|
||||||
|
cmd.CmdCert,
|
||||||
|
cmd.CmdGenerate,
|
||||||
|
cmd.CmdDocs,
|
||||||
}
|
}
|
||||||
|
|
||||||
// default configuration flags
|
// shared configuration flags, they are for global and for each sub-command at the same time
|
||||||
|
// eg: such command is valid: "./gitea --config /tmp/app.ini web --config /tmp/app.ini", while it's discouraged indeed
|
||||||
|
// keep in mind that the short flags like "-C", "-c" and "-w" are globally polluted, they can't be used for sub-commands anymore.
|
||||||
globalFlags := []cli.Flag{
|
globalFlags := []cli.Flag{
|
||||||
cli.HelpFlag,
|
cli.HelpFlag,
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
@@ -126,13 +136,15 @@ func main() {
|
|||||||
|
|
||||||
// Set the default to be equivalent to cmdWeb and add the default flags
|
// Set the default to be equivalent to cmdWeb and add the default flags
|
||||||
app.Flags = append(app.Flags, globalFlags...)
|
app.Flags = append(app.Flags, globalFlags...)
|
||||||
app.Flags = append(app.Flags, cmd.CmdWeb.Flags...)
|
app.Flags = append(app.Flags, cmd.CmdWeb.Flags...) // TODO: the web flags polluted the global flags, they are not really global flags
|
||||||
app.Action = prepareWorkPathAndCustomConf(cmd.CmdWeb.Action)
|
app.Action = prepareWorkPathAndCustomConf(cmd.CmdWeb.Action)
|
||||||
app.HideHelp = true // use our own help action to show helps (with more information like default config)
|
app.HideHelp = true // use our own help action to show helps (with more information like default config)
|
||||||
app.Commands = append(app.Commands, cmdHelp)
|
app.Before = cmd.PrepareConsoleLoggerLevel(log.INFO)
|
||||||
for i := range app.Commands {
|
for i := range subCmdWithIni {
|
||||||
prepareSubcommands(&app.Commands[i], globalFlags)
|
prepareSubcommands(&subCmdWithIni[i], globalFlags)
|
||||||
}
|
}
|
||||||
|
app.Commands = append(app.Commands, subCmdWithIni...)
|
||||||
|
app.Commands = append(app.Commands, subCmdStandalone...)
|
||||||
|
|
||||||
err := app.Run(os.Args)
|
err := app.Run(os.Args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -156,11 +168,7 @@ func prepareSubcommands(command *cli.Command, defaultFlags []cli.Flag) {
|
|||||||
|
|
||||||
// prepareWorkPathAndCustomConf wraps the Action to prepare the work path and custom config
|
// prepareWorkPathAndCustomConf wraps the Action to prepare the work path and custom config
|
||||||
// It can't use "Before", because each level's sub-command's Before will be called one by one, so the "init" would be done multiple times
|
// It can't use "Before", because each level's sub-command's Before will be called one by one, so the "init" would be done multiple times
|
||||||
func prepareWorkPathAndCustomConf(a any) func(ctx *cli.Context) error {
|
func prepareWorkPathAndCustomConf(action any) func(ctx *cli.Context) error {
|
||||||
if a == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
action := a.(func(*cli.Context) error)
|
|
||||||
return func(ctx *cli.Context) error {
|
return func(ctx *cli.Context) error {
|
||||||
var args setting.ArgWorkPathAndCustomConf
|
var args setting.ArgWorkPathAndCustomConf
|
||||||
curCtx := ctx
|
curCtx := ctx
|
||||||
@@ -177,10 +185,11 @@ func prepareWorkPathAndCustomConf(a any) func(ctx *cli.Context) error {
|
|||||||
curCtx = curCtx.Parent()
|
curCtx = curCtx.Parent()
|
||||||
}
|
}
|
||||||
setting.InitWorkPathAndCommonConfig(os.Getenv, args)
|
setting.InitWorkPathAndCommonConfig(os.Getenv, args)
|
||||||
if ctx.Bool("help") {
|
if ctx.Bool("help") || action == nil {
|
||||||
|
// the default behavior of "urfave/cli": "nil action" means "show help"
|
||||||
return cmdHelp.Action.(func(ctx *cli.Context) error)(ctx)
|
return cmdHelp.Action.(func(ctx *cli.Context) error)(ctx)
|
||||||
}
|
}
|
||||||
return action(ctx)
|
return action.(func(*cli.Context) error)(ctx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -346,6 +346,9 @@ func UpdateTask(ctx context.Context, task *ActionTask, cols ...string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UpdateTaskByState updates the task by the state.
|
||||||
|
// It will always update the task if the state is not final, even there is no change.
|
||||||
|
// So it will update ActionTask.Updated to avoid the task being judged as a zombie task.
|
||||||
func UpdateTaskByState(ctx context.Context, state *runnerv1.TaskState) (*ActionTask, error) {
|
func UpdateTaskByState(ctx context.Context, state *runnerv1.TaskState) (*ActionTask, error) {
|
||||||
stepStates := map[int64]*runnerv1.StepState{}
|
stepStates := map[int64]*runnerv1.StepState{}
|
||||||
for _, v := range state.Steps {
|
for _, v := range state.Steps {
|
||||||
@@ -386,6 +389,12 @@ func UpdateTaskByState(ctx context.Context, state *runnerv1.TaskState) (*ActionT
|
|||||||
}, nil); err != nil {
|
}, nil); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// Force update ActionTask.Updated to avoid the task being judged as a zombie task
|
||||||
|
task.Updated = timeutil.TimeStampNow()
|
||||||
|
if err := UpdateTask(ctx, task, "updated"); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := task.LoadAttributes(ctx); err != nil {
|
if err := task.LoadAttributes(ctx); err != nil {
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func init() {
|
|||||||
// TranslatableMessage represents JSON struct that can be translated with a Locale
|
// TranslatableMessage represents JSON struct that can be translated with a Locale
|
||||||
type TranslatableMessage struct {
|
type TranslatableMessage struct {
|
||||||
Format string
|
Format string
|
||||||
Args []interface{} `json:"omitempty"`
|
Args []any `json:"omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// LoadRepo loads repository of the task
|
// LoadRepo loads repository of the task
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ var sshOpLocker sync.Mutex
|
|||||||
// AuthorizedStringForKey creates the authorized keys string appropriate for the provided key
|
// AuthorizedStringForKey creates the authorized keys string appropriate for the provided key
|
||||||
func AuthorizedStringForKey(key *PublicKey) string {
|
func AuthorizedStringForKey(key *PublicKey) string {
|
||||||
sb := &strings.Builder{}
|
sb := &strings.Builder{}
|
||||||
_ = setting.SSH.AuthorizedKeysCommandTemplateTemplate.Execute(sb, map[string]interface{}{
|
_ = setting.SSH.AuthorizedKeysCommandTemplateTemplate.Execute(sb, map[string]any{
|
||||||
"AppPath": util.ShellEscape(setting.AppPath),
|
"AppPath": util.ShellEscape(setting.AppPath),
|
||||||
"AppWorkPath": util.ShellEscape(setting.AppWorkPath),
|
"AppWorkPath": util.ShellEscape(setting.AppWorkPath),
|
||||||
"CustomConf": util.ShellEscape(setting.CustomConf),
|
"CustomConf": util.ShellEscape(setting.CustomConf),
|
||||||
@@ -175,7 +175,7 @@ func RewriteAllPublicKeys() error {
|
|||||||
|
|
||||||
// RegeneratePublicKeys regenerates the authorized_keys file
|
// RegeneratePublicKeys regenerates the authorized_keys file
|
||||||
func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error {
|
func RegeneratePublicKeys(ctx context.Context, t io.StringWriter) error {
|
||||||
if err := db.GetEngine(ctx).Where("type != ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
|
if err := db.GetEngine(ctx).Where("type != ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean any) (err error) {
|
||||||
_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
|
_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
|
||||||
return err
|
return err
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ func RewriteAllPrincipalKeys(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func regeneratePrincipalKeys(ctx context.Context, t io.StringWriter) error {
|
func regeneratePrincipalKeys(ctx context.Context, t io.StringWriter) error {
|
||||||
if err := db.GetEngine(ctx).Where("type = ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean interface{}) (err error) {
|
if err := db.GetEngine(ctx).Where("type = ?", KeyTypePrincipal).Iterate(new(PublicKey), func(idx int, bean any) (err error) {
|
||||||
_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
|
_, err = t.WriteString((bean.(*PublicKey)).AuthorizedString())
|
||||||
return err
|
return err
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ func (ctx *Context) Engine() Engine {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Value shadows Value for context.Context but allows us to get ourselves and an Engined object
|
// Value shadows Value for context.Context but allows us to get ourselves and an Engined object
|
||||||
func (ctx *Context) Value(key interface{}) interface{} {
|
func (ctx *Context) Value(key any) any {
|
||||||
if key == enginedContextKey {
|
if key == enginedContextKey {
|
||||||
return ctx
|
return ctx
|
||||||
}
|
}
|
||||||
@@ -163,28 +163,28 @@ func txWithNoCheck(parentCtx context.Context, f func(ctx context.Context) error)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Insert inserts records into database
|
// Insert inserts records into database
|
||||||
func Insert(ctx context.Context, beans ...interface{}) error {
|
func Insert(ctx context.Context, beans ...any) error {
|
||||||
_, err := GetEngine(ctx).Insert(beans...)
|
_, err := GetEngine(ctx).Insert(beans...)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Exec executes a sql with args
|
// Exec executes a sql with args
|
||||||
func Exec(ctx context.Context, sqlAndArgs ...interface{}) (sql.Result, error) {
|
func Exec(ctx context.Context, sqlAndArgs ...any) (sql.Result, error) {
|
||||||
return GetEngine(ctx).Exec(sqlAndArgs...)
|
return GetEngine(ctx).Exec(sqlAndArgs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetByBean filled empty fields of the bean according non-empty fields to query in database.
|
// GetByBean filled empty fields of the bean according non-empty fields to query in database.
|
||||||
func GetByBean(ctx context.Context, bean interface{}) (bool, error) {
|
func GetByBean(ctx context.Context, bean any) (bool, error) {
|
||||||
return GetEngine(ctx).Get(bean)
|
return GetEngine(ctx).Get(bean)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteByBean deletes all records according non-empty fields of the bean as conditions.
|
// DeleteByBean deletes all records according non-empty fields of the bean as conditions.
|
||||||
func DeleteByBean(ctx context.Context, bean interface{}) (int64, error) {
|
func DeleteByBean(ctx context.Context, bean any) (int64, error) {
|
||||||
return GetEngine(ctx).Delete(bean)
|
return GetEngine(ctx).Delete(bean)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteByID deletes the given bean with the given ID
|
// DeleteByID deletes the given bean with the given ID
|
||||||
func DeleteByID(ctx context.Context, id int64, bean interface{}) (int64, error) {
|
func DeleteByID(ctx context.Context, id int64, bean any) (int64, error) {
|
||||||
return GetEngine(ctx).ID(id).NoAutoTime().Delete(bean)
|
return GetEngine(ctx).ID(id).NoAutoTime().Delete(bean)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -203,13 +203,13 @@ func FindIDs(ctx context.Context, tableName, idCol string, cond builder.Cond) ([
|
|||||||
|
|
||||||
// DecrByIDs decreases the given column for entities of the "bean" type with one of the given ids by one
|
// DecrByIDs decreases the given column for entities of the "bean" type with one of the given ids by one
|
||||||
// Timestamps of the entities won't be updated
|
// Timestamps of the entities won't be updated
|
||||||
func DecrByIDs(ctx context.Context, ids []int64, decrCol string, bean interface{}) error {
|
func DecrByIDs(ctx context.Context, ids []int64, decrCol string, bean any) error {
|
||||||
_, err := GetEngine(ctx).Decr(decrCol).In("id", ids).NoAutoCondition().NoAutoTime().Update(bean)
|
_, err := GetEngine(ctx).Decr(decrCol).In("id", ids).NoAutoCondition().NoAutoTime().Update(bean)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteBeans deletes all given beans, beans must contain delete conditions.
|
// DeleteBeans deletes all given beans, beans must contain delete conditions.
|
||||||
func DeleteBeans(ctx context.Context, beans ...interface{}) (err error) {
|
func DeleteBeans(ctx context.Context, beans ...any) (err error) {
|
||||||
e := GetEngine(ctx)
|
e := GetEngine(ctx)
|
||||||
for i := range beans {
|
for i := range beans {
|
||||||
if _, err = e.Delete(beans[i]); err != nil {
|
if _, err = e.Delete(beans[i]); err != nil {
|
||||||
@@ -220,7 +220,7 @@ func DeleteBeans(ctx context.Context, beans ...interface{}) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TruncateBeans deletes all given beans, beans may contain delete conditions.
|
// TruncateBeans deletes all given beans, beans may contain delete conditions.
|
||||||
func TruncateBeans(ctx context.Context, beans ...interface{}) (err error) {
|
func TruncateBeans(ctx context.Context, beans ...any) (err error) {
|
||||||
e := GetEngine(ctx)
|
e := GetEngine(ctx)
|
||||||
for i := range beans {
|
for i := range beans {
|
||||||
if _, err = e.Truncate(beans[i]); err != nil {
|
if _, err = e.Truncate(beans[i]); err != nil {
|
||||||
@@ -231,12 +231,12 @@ func TruncateBeans(ctx context.Context, beans ...interface{}) (err error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CountByBean counts the number of database records according non-empty fields of the bean as conditions.
|
// CountByBean counts the number of database records according non-empty fields of the bean as conditions.
|
||||||
func CountByBean(ctx context.Context, bean interface{}) (int64, error) {
|
func CountByBean(ctx context.Context, bean any) (int64, error) {
|
||||||
return GetEngine(ctx).Count(bean)
|
return GetEngine(ctx).Count(bean)
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableName returns the table name according a bean object
|
// TableName returns the table name according a bean object
|
||||||
func TableName(bean interface{}) string {
|
func TableName(bean any) string {
|
||||||
return x.TableName(bean)
|
return x.TableName(bean)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ import (
|
|||||||
|
|
||||||
var (
|
var (
|
||||||
x *xorm.Engine
|
x *xorm.Engine
|
||||||
tables []interface{}
|
tables []any
|
||||||
initFuncs []func() error
|
initFuncs []func() error
|
||||||
|
|
||||||
// HasEngine specifies if we have a xorm.Engine
|
// HasEngine specifies if we have a xorm.Engine
|
||||||
@@ -34,41 +34,41 @@ var (
|
|||||||
|
|
||||||
// Engine represents a xorm engine or session.
|
// Engine represents a xorm engine or session.
|
||||||
type Engine interface {
|
type Engine interface {
|
||||||
Table(tableNameOrBean interface{}) *xorm.Session
|
Table(tableNameOrBean any) *xorm.Session
|
||||||
Count(...interface{}) (int64, error)
|
Count(...any) (int64, error)
|
||||||
Decr(column string, arg ...interface{}) *xorm.Session
|
Decr(column string, arg ...any) *xorm.Session
|
||||||
Delete(...interface{}) (int64, error)
|
Delete(...any) (int64, error)
|
||||||
Truncate(...interface{}) (int64, error)
|
Truncate(...any) (int64, error)
|
||||||
Exec(...interface{}) (sql.Result, error)
|
Exec(...any) (sql.Result, error)
|
||||||
Find(interface{}, ...interface{}) error
|
Find(any, ...any) error
|
||||||
Get(beans ...interface{}) (bool, error)
|
Get(beans ...any) (bool, error)
|
||||||
ID(interface{}) *xorm.Session
|
ID(any) *xorm.Session
|
||||||
In(string, ...interface{}) *xorm.Session
|
In(string, ...any) *xorm.Session
|
||||||
Incr(column string, arg ...interface{}) *xorm.Session
|
Incr(column string, arg ...any) *xorm.Session
|
||||||
Insert(...interface{}) (int64, error)
|
Insert(...any) (int64, error)
|
||||||
Iterate(interface{}, xorm.IterFunc) error
|
Iterate(any, xorm.IterFunc) error
|
||||||
Join(joinOperator string, tablename, condition interface{}, args ...interface{}) *xorm.Session
|
Join(joinOperator string, tablename, condition any, args ...any) *xorm.Session
|
||||||
SQL(interface{}, ...interface{}) *xorm.Session
|
SQL(any, ...any) *xorm.Session
|
||||||
Where(interface{}, ...interface{}) *xorm.Session
|
Where(any, ...any) *xorm.Session
|
||||||
Asc(colNames ...string) *xorm.Session
|
Asc(colNames ...string) *xorm.Session
|
||||||
Desc(colNames ...string) *xorm.Session
|
Desc(colNames ...string) *xorm.Session
|
||||||
Limit(limit int, start ...int) *xorm.Session
|
Limit(limit int, start ...int) *xorm.Session
|
||||||
NoAutoTime() *xorm.Session
|
NoAutoTime() *xorm.Session
|
||||||
SumInt(bean interface{}, columnName string) (res int64, err error)
|
SumInt(bean any, columnName string) (res int64, err error)
|
||||||
Sync2(...interface{}) error
|
Sync2(...any) error
|
||||||
Select(string) *xorm.Session
|
Select(string) *xorm.Session
|
||||||
NotIn(string, ...interface{}) *xorm.Session
|
NotIn(string, ...any) *xorm.Session
|
||||||
OrderBy(interface{}, ...interface{}) *xorm.Session
|
OrderBy(any, ...any) *xorm.Session
|
||||||
Exist(...interface{}) (bool, error)
|
Exist(...any) (bool, error)
|
||||||
Distinct(...string) *xorm.Session
|
Distinct(...string) *xorm.Session
|
||||||
Query(...interface{}) ([]map[string][]byte, error)
|
Query(...any) ([]map[string][]byte, error)
|
||||||
Cols(...string) *xorm.Session
|
Cols(...string) *xorm.Session
|
||||||
Context(ctx context.Context) *xorm.Session
|
Context(ctx context.Context) *xorm.Session
|
||||||
Ping() error
|
Ping() error
|
||||||
}
|
}
|
||||||
|
|
||||||
// TableInfo returns table's information via an object
|
// TableInfo returns table's information via an object
|
||||||
func TableInfo(v interface{}) (*schemas.Table, error) {
|
func TableInfo(v any) (*schemas.Table, error) {
|
||||||
return x.TableInfo(v)
|
return x.TableInfo(v)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -78,7 +78,7 @@ func DumpTables(tables []*schemas.Table, w io.Writer, tp ...schemas.DBType) erro
|
|||||||
}
|
}
|
||||||
|
|
||||||
// RegisterModel registers model, if initfunc provided, it will be invoked after data model sync
|
// RegisterModel registers model, if initfunc provided, it will be invoked after data model sync
|
||||||
func RegisterModel(bean interface{}, initFunc ...func() error) {
|
func RegisterModel(bean any, initFunc ...func() error) {
|
||||||
tables = append(tables, bean)
|
tables = append(tables, bean)
|
||||||
if len(initFuncs) > 0 && initFunc[0] != nil {
|
if len(initFuncs) > 0 && initFunc[0] != nil {
|
||||||
initFuncs = append(initFuncs, initFunc[0])
|
initFuncs = append(initFuncs, initFunc[0])
|
||||||
@@ -123,7 +123,10 @@ func newXORMEngine() (*xorm.Engine, error) {
|
|||||||
|
|
||||||
// SyncAllTables sync the schemas of all tables, is required by unit test code
|
// SyncAllTables sync the schemas of all tables, is required by unit test code
|
||||||
func SyncAllTables() error {
|
func SyncAllTables() error {
|
||||||
return x.StoreEngine("InnoDB").Sync2(tables...)
|
_, err := x.StoreEngine("InnoDB").SyncWithOptions(xorm.SyncOptions{
|
||||||
|
WarnIfDatabaseColumnMissed: true,
|
||||||
|
}, tables...)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
// InitEngine initializes the xorm.Engine and sets it as db.DefaultContext
|
// InitEngine initializes the xorm.Engine and sets it as db.DefaultContext
|
||||||
@@ -206,14 +209,14 @@ func InitEngineWithMigration(ctx context.Context, migrateFunc func(*xorm.Engine)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NamesToBean return a list of beans or an error
|
// NamesToBean return a list of beans or an error
|
||||||
func NamesToBean(names ...string) ([]interface{}, error) {
|
func NamesToBean(names ...string) ([]any, error) {
|
||||||
beans := []interface{}{}
|
beans := []any{}
|
||||||
if len(names) == 0 {
|
if len(names) == 0 {
|
||||||
beans = append(beans, tables...)
|
beans = append(beans, tables...)
|
||||||
return beans, nil
|
return beans, nil
|
||||||
}
|
}
|
||||||
// Need to map provided names to beans...
|
// Need to map provided names to beans...
|
||||||
beanMap := make(map[string]interface{})
|
beanMap := make(map[string]any)
|
||||||
for _, bean := range tables {
|
for _, bean := range tables {
|
||||||
|
|
||||||
beanMap[strings.ToLower(reflect.Indirect(reflect.ValueOf(bean)).Type().Name())] = bean
|
beanMap[strings.ToLower(reflect.Indirect(reflect.ValueOf(bean)).Type().Name())] = bean
|
||||||
@@ -221,7 +224,7 @@ func NamesToBean(names ...string) ([]interface{}, error) {
|
|||||||
beanMap[strings.ToLower(x.TableName(bean, true))] = bean
|
beanMap[strings.ToLower(x.TableName(bean, true))] = bean
|
||||||
}
|
}
|
||||||
|
|
||||||
gotBean := make(map[interface{}]bool)
|
gotBean := make(map[any]bool)
|
||||||
for _, name := range names {
|
for _, name := range names {
|
||||||
bean, ok := beanMap[strings.ToLower(strings.TrimSpace(name))]
|
bean, ok := beanMap[strings.ToLower(strings.TrimSpace(name))]
|
||||||
if !ok {
|
if !ok {
|
||||||
@@ -263,7 +266,7 @@ func DumpDatabase(filePath, dbType string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MaxBatchInsertSize returns the table's max batch insert size
|
// MaxBatchInsertSize returns the table's max batch insert size
|
||||||
func MaxBatchInsertSize(bean interface{}) int {
|
func MaxBatchInsertSize(bean any) int {
|
||||||
t, err := x.TableInfo(bean)
|
t, err := x.TableInfo(bean)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return 50
|
return 50
|
||||||
@@ -283,7 +286,7 @@ func DeleteAllRecords(tableName string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GetMaxID will return max id of the table
|
// GetMaxID will return max id of the table
|
||||||
func GetMaxID(beanOrTableName interface{}) (maxID int64, err error) {
|
func GetMaxID(beanOrTableName any) (maxID int64, err error) {
|
||||||
_, err = x.Select("MAX(id)").Table(beanOrTableName).Get(&maxID)
|
_, err = x.Select("MAX(id)").Table(beanOrTableName).Get(&maxID)
|
||||||
return maxID, err
|
return maxID, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func (err ErrCancelled) Error() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// ErrCancelledf returns an ErrCancelled for the provided format and args
|
// ErrCancelledf returns an ErrCancelled for the provided format and args
|
||||||
func ErrCancelledf(format string, args ...interface{}) error {
|
func ErrCancelledf(format string, args ...any) error {
|
||||||
return ErrCancelled{
|
return ErrCancelled{
|
||||||
fmt.Sprintf(format, args...),
|
fmt.Sprintf(format, args...),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,47 +28,47 @@ func NewXORMLogger(showSQL bool) xormlog.Logger {
|
|||||||
const stackLevel = 8
|
const stackLevel = 8
|
||||||
|
|
||||||
// Log a message with defined skip and at logging level
|
// Log a message with defined skip and at logging level
|
||||||
func (l *XORMLogBridge) Log(skip int, level log.Level, format string, v ...interface{}) {
|
func (l *XORMLogBridge) Log(skip int, level log.Level, format string, v ...any) {
|
||||||
l.logger.Log(skip+1, level, format, v...)
|
l.logger.Log(skip+1, level, format, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debug show debug log
|
// Debug show debug log
|
||||||
func (l *XORMLogBridge) Debug(v ...interface{}) {
|
func (l *XORMLogBridge) Debug(v ...any) {
|
||||||
l.Log(stackLevel, log.DEBUG, "%s", fmt.Sprint(v...))
|
l.Log(stackLevel, log.DEBUG, "%s", fmt.Sprint(v...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Debugf show debug log
|
// Debugf show debug log
|
||||||
func (l *XORMLogBridge) Debugf(format string, v ...interface{}) {
|
func (l *XORMLogBridge) Debugf(format string, v ...any) {
|
||||||
l.Log(stackLevel, log.DEBUG, format, v...)
|
l.Log(stackLevel, log.DEBUG, format, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Error show error log
|
// Error show error log
|
||||||
func (l *XORMLogBridge) Error(v ...interface{}) {
|
func (l *XORMLogBridge) Error(v ...any) {
|
||||||
l.Log(stackLevel, log.ERROR, "%s", fmt.Sprint(v...))
|
l.Log(stackLevel, log.ERROR, "%s", fmt.Sprint(v...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Errorf show error log
|
// Errorf show error log
|
||||||
func (l *XORMLogBridge) Errorf(format string, v ...interface{}) {
|
func (l *XORMLogBridge) Errorf(format string, v ...any) {
|
||||||
l.Log(stackLevel, log.ERROR, format, v...)
|
l.Log(stackLevel, log.ERROR, format, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Info show information level log
|
// Info show information level log
|
||||||
func (l *XORMLogBridge) Info(v ...interface{}) {
|
func (l *XORMLogBridge) Info(v ...any) {
|
||||||
l.Log(stackLevel, log.INFO, "%s", fmt.Sprint(v...))
|
l.Log(stackLevel, log.INFO, "%s", fmt.Sprint(v...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Infof show information level log
|
// Infof show information level log
|
||||||
func (l *XORMLogBridge) Infof(format string, v ...interface{}) {
|
func (l *XORMLogBridge) Infof(format string, v ...any) {
|
||||||
l.Log(stackLevel, log.INFO, format, v...)
|
l.Log(stackLevel, log.INFO, format, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn show warning log
|
// Warn show warning log
|
||||||
func (l *XORMLogBridge) Warn(v ...interface{}) {
|
func (l *XORMLogBridge) Warn(v ...any) {
|
||||||
l.Log(stackLevel, log.WARN, "%s", fmt.Sprint(v...))
|
l.Log(stackLevel, log.WARN, "%s", fmt.Sprint(v...))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warnf show warnning log
|
// Warnf show warnning log
|
||||||
func (l *XORMLogBridge) Warnf(format string, v ...interface{}) {
|
func (l *XORMLogBridge) Warnf(format string, v ...any) {
|
||||||
l.Log(stackLevel, log.WARN, format, v...)
|
l.Log(stackLevel, log.WARN, format, v...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -21,6 +22,7 @@ var defaultFileBlockSize int64 = 32 * 1024
|
|||||||
type File interface {
|
type File interface {
|
||||||
io.ReadWriteCloser
|
io.ReadWriteCloser
|
||||||
io.Seeker
|
io.Seeker
|
||||||
|
fs.File
|
||||||
}
|
}
|
||||||
|
|
||||||
type file struct {
|
type file struct {
|
||||||
@@ -193,10 +195,26 @@ func (f *file) Close() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (f *file) Stat() (os.FileInfo, error) {
|
||||||
|
if f.metaID == 0 {
|
||||||
|
return nil, os.ErrInvalid
|
||||||
|
}
|
||||||
|
|
||||||
|
fileMeta, err := findFileMetaByID(f.ctx, f.metaID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return fileMeta, nil
|
||||||
|
}
|
||||||
|
|
||||||
func timeToFileTimestamp(t time.Time) int64 {
|
func timeToFileTimestamp(t time.Time) int64 {
|
||||||
return t.UnixMicro()
|
return t.UnixMicro()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func fileTimestampToTime(timestamp int64) time.Time {
|
||||||
|
return time.UnixMicro(timestamp)
|
||||||
|
}
|
||||||
|
|
||||||
func (f *file) loadMetaByPath() (*dbfsMeta, error) {
|
func (f *file) loadMetaByPath() (*dbfsMeta, error) {
|
||||||
var fileMeta dbfsMeta
|
var fileMeta dbfsMeta
|
||||||
if ok, err := db.GetEngine(f.ctx).Where("full_path = ?", f.fullPath).Get(&fileMeta); err != nil {
|
if ok, err := db.GetEngine(f.ctx).Where("full_path = ?", f.fullPath).Get(&fileMeta); err != nil {
|
||||||
|
|||||||
@@ -5,7 +5,10 @@ package dbfs
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"io/fs"
|
||||||
"os"
|
"os"
|
||||||
|
"path"
|
||||||
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
)
|
)
|
||||||
@@ -100,3 +103,29 @@ func Remove(ctx context.Context, name string) error {
|
|||||||
defer f.Close()
|
defer f.Close()
|
||||||
return f.delete()
|
return f.delete()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var _ fs.FileInfo = (*dbfsMeta)(nil)
|
||||||
|
|
||||||
|
func (m *dbfsMeta) Name() string {
|
||||||
|
return path.Base(m.FullPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *dbfsMeta) Size() int64 {
|
||||||
|
return m.FileSize
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *dbfsMeta) Mode() fs.FileMode {
|
||||||
|
return os.ModePerm
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *dbfsMeta) ModTime() time.Time {
|
||||||
|
return fileTimestampToTime(m.ModifyTimestamp)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *dbfsMeta) IsDir() bool {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *dbfsMeta) Sys() any {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -111,6 +111,19 @@ func TestDbfsBasic(t *testing.T) {
|
|||||||
|
|
||||||
_, err = OpenFile(db.DefaultContext, "test2.txt", os.O_RDONLY)
|
_, err = OpenFile(db.DefaultContext, "test2.txt", os.O_RDONLY)
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
// test stat
|
||||||
|
f, err = OpenFile(db.DefaultContext, "test/test.txt", os.O_RDWR|os.O_CREATE)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
stat, err := f.Stat()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, "test.txt", stat.Name())
|
||||||
|
assert.EqualValues(t, 0, stat.Size())
|
||||||
|
_, err = f.Write([]byte("0123456789"))
|
||||||
|
assert.NoError(t, err)
|
||||||
|
stat, err = f.Stat()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 10, stat.Size())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestDbfsReadWrite(t *testing.T) {
|
func TestDbfsReadWrite(t *testing.T) {
|
||||||
|
|||||||
49
models/fixtures/mirror.yml
Normal file
49
models/fixtures/mirror.yml
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
-
|
||||||
|
id: 1
|
||||||
|
repo_id: 5
|
||||||
|
interval: 3600
|
||||||
|
enable_prune: false
|
||||||
|
updated_unix: 0
|
||||||
|
next_update_unix: 0
|
||||||
|
lfs_enabled: false
|
||||||
|
lfs_endpoint: ""
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 2
|
||||||
|
repo_id: 25
|
||||||
|
interval: 3600
|
||||||
|
enable_prune: false
|
||||||
|
updated_unix: 0
|
||||||
|
next_update_unix: 0
|
||||||
|
lfs_enabled: false
|
||||||
|
lfs_endpoint: ""
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 3
|
||||||
|
repo_id: 26
|
||||||
|
interval: 3600
|
||||||
|
enable_prune: false
|
||||||
|
updated_unix: 0
|
||||||
|
next_update_unix: 0
|
||||||
|
lfs_enabled: false
|
||||||
|
lfs_endpoint: ""
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 4
|
||||||
|
repo_id: 27
|
||||||
|
interval: 3600
|
||||||
|
enable_prune: false
|
||||||
|
updated_unix: 0
|
||||||
|
next_update_unix: 0
|
||||||
|
lfs_enabled: false
|
||||||
|
lfs_endpoint: ""
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 5
|
||||||
|
repo_id: 28
|
||||||
|
interval: 3600
|
||||||
|
enable_prune: false
|
||||||
|
updated_unix: 0
|
||||||
|
next_update_unix: 0
|
||||||
|
lfs_enabled: false
|
||||||
|
lfs_endpoint: ""
|
||||||
@@ -81,3 +81,21 @@
|
|||||||
uid: 5
|
uid: 5
|
||||||
org_id: 23
|
org_id: 23
|
||||||
is_public: false
|
is_public: false
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 15
|
||||||
|
uid: 1
|
||||||
|
org_id: 35
|
||||||
|
is_public: true
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 16
|
||||||
|
uid: 1
|
||||||
|
org_id: 36
|
||||||
|
is_public: true
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 17
|
||||||
|
uid: 5
|
||||||
|
org_id: 36
|
||||||
|
is_public: true
|
||||||
|
|||||||
@@ -7,6 +7,8 @@
|
|||||||
creator_id: 2
|
creator_id: 2
|
||||||
board_type: 1
|
board_type: 1
|
||||||
type: 2
|
type: 2
|
||||||
|
created_unix: 1688973030
|
||||||
|
updated_unix: 1688973030
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 2
|
id: 2
|
||||||
@@ -17,6 +19,8 @@
|
|||||||
creator_id: 3
|
creator_id: 3
|
||||||
board_type: 1
|
board_type: 1
|
||||||
type: 2
|
type: 2
|
||||||
|
created_unix: 1688973010
|
||||||
|
updated_unix: 1688973010
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 3
|
id: 3
|
||||||
@@ -27,6 +31,8 @@
|
|||||||
creator_id: 5
|
creator_id: 5
|
||||||
board_type: 1
|
board_type: 1
|
||||||
type: 2
|
type: 2
|
||||||
|
created_unix: 1688973020
|
||||||
|
updated_unix: 1688973020
|
||||||
|
|
||||||
-
|
-
|
||||||
id: 4
|
id: 4
|
||||||
@@ -37,3 +43,5 @@
|
|||||||
creator_id: 2
|
creator_id: 2
|
||||||
board_type: 1
|
board_type: 1
|
||||||
type: 2
|
type: 2
|
||||||
|
created_unix: 1688973000
|
||||||
|
updated_unix: 1688973000
|
||||||
|
|||||||
@@ -141,7 +141,7 @@
|
|||||||
num_projects: 0
|
num_projects: 0
|
||||||
num_closed_projects: 0
|
num_closed_projects: 0
|
||||||
is_private: true
|
is_private: true
|
||||||
is_empty: true
|
is_empty: false
|
||||||
is_archived: false
|
is_archived: false
|
||||||
is_mirror: true
|
is_mirror: true
|
||||||
status: 0
|
status: 0
|
||||||
|
|||||||
@@ -184,3 +184,36 @@
|
|||||||
num_members: 1
|
num_members: 1
|
||||||
includes_all_repositories: false
|
includes_all_repositories: false
|
||||||
can_create_org_repo: true
|
can_create_org_repo: true
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 18
|
||||||
|
org_id: 35
|
||||||
|
lower_name: owners
|
||||||
|
name: Owners
|
||||||
|
authorize: 4 # owner
|
||||||
|
num_repos: 0
|
||||||
|
num_members: 1
|
||||||
|
includes_all_repositories: false
|
||||||
|
can_create_org_repo: true
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 19
|
||||||
|
org_id: 36
|
||||||
|
lower_name: owners
|
||||||
|
name: Owners
|
||||||
|
authorize: 4 # owner
|
||||||
|
num_repos: 0
|
||||||
|
num_members: 1
|
||||||
|
includes_all_repositories: false
|
||||||
|
can_create_org_repo: true
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 20
|
||||||
|
org_id: 36
|
||||||
|
lower_name: team20writepackage
|
||||||
|
name: team20writepackage
|
||||||
|
authorize: 1
|
||||||
|
num_repos: 0
|
||||||
|
num_members: 1
|
||||||
|
includes_all_repositories: false
|
||||||
|
can_create_org_repo: true
|
||||||
|
|||||||
@@ -273,4 +273,10 @@
|
|||||||
id: 46
|
id: 46
|
||||||
team_id: 17
|
team_id: 17
|
||||||
type: 9 # package
|
type: 9 # package
|
||||||
access_mode: 0
|
access_mode: 2
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 47
|
||||||
|
team_id: 20
|
||||||
|
type: 9 # package
|
||||||
|
access_mode: 2
|
||||||
|
|||||||
@@ -105,3 +105,21 @@
|
|||||||
org_id: 23
|
org_id: 23
|
||||||
team_id: 17
|
team_id: 17
|
||||||
uid: 5
|
uid: 5
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 19
|
||||||
|
org_id: 35
|
||||||
|
team_id: 18
|
||||||
|
uid: 1
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 20
|
||||||
|
org_id: 36
|
||||||
|
team_id: 19
|
||||||
|
uid: 1
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 21
|
||||||
|
org_id: 36
|
||||||
|
team_id: 20
|
||||||
|
uid: 5
|
||||||
|
|||||||
@@ -1258,3 +1258,77 @@
|
|||||||
repo_admin_change_team_access: false
|
repo_admin_change_team_access: false
|
||||||
theme: ""
|
theme: ""
|
||||||
keep_activity_private: false
|
keep_activity_private: false
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 35
|
||||||
|
lower_name: private_org35
|
||||||
|
name: private_org35
|
||||||
|
full_name: Private Org 35
|
||||||
|
email: private_org35@example.com
|
||||||
|
keep_email_private: false
|
||||||
|
email_notifications_preference: enabled
|
||||||
|
passwd: ZogKvWdyEx:password
|
||||||
|
passwd_hash_algo: dummy
|
||||||
|
must_change_password: false
|
||||||
|
login_source: 0
|
||||||
|
login_name: private_org35
|
||||||
|
type: 1
|
||||||
|
salt: ZogKvWdyEx
|
||||||
|
max_repo_creation: -1
|
||||||
|
is_active: true
|
||||||
|
is_admin: false
|
||||||
|
is_restricted: false
|
||||||
|
allow_git_hook: false
|
||||||
|
allow_import_local: false
|
||||||
|
allow_create_organization: true
|
||||||
|
prohibit_login: false
|
||||||
|
avatar: avatar35
|
||||||
|
avatar_email: private_org35@example.com
|
||||||
|
use_custom_avatar: false
|
||||||
|
num_followers: 0
|
||||||
|
num_following: 0
|
||||||
|
num_stars: 0
|
||||||
|
num_repos: 0
|
||||||
|
num_teams: 1
|
||||||
|
num_members: 1
|
||||||
|
visibility: 2
|
||||||
|
repo_admin_change_team_access: false
|
||||||
|
theme: ""
|
||||||
|
keep_activity_private: false
|
||||||
|
|
||||||
|
-
|
||||||
|
id: 36
|
||||||
|
lower_name: limited_org36
|
||||||
|
name: limited_org36
|
||||||
|
full_name: Limited Org 36
|
||||||
|
email: limited_org36@example.com
|
||||||
|
keep_email_private: false
|
||||||
|
email_notifications_preference: enabled
|
||||||
|
passwd: ZogKvWdyEx:password
|
||||||
|
passwd_hash_algo: dummy
|
||||||
|
must_change_password: false
|
||||||
|
login_source: 0
|
||||||
|
login_name: limited_org36
|
||||||
|
type: 1
|
||||||
|
salt: ZogKvWdyEx
|
||||||
|
max_repo_creation: -1
|
||||||
|
is_active: true
|
||||||
|
is_admin: false
|
||||||
|
is_restricted: false
|
||||||
|
allow_git_hook: false
|
||||||
|
allow_import_local: false
|
||||||
|
allow_create_organization: true
|
||||||
|
prohibit_login: false
|
||||||
|
avatar: avatar22
|
||||||
|
avatar_email: limited_org36@example.com
|
||||||
|
use_custom_avatar: false
|
||||||
|
num_followers: 0
|
||||||
|
num_following: 0
|
||||||
|
num_stars: 0
|
||||||
|
num_repos: 0
|
||||||
|
num_teams: 2
|
||||||
|
num_members: 2
|
||||||
|
visibility: 1
|
||||||
|
repo_admin_change_team_access: false
|
||||||
|
theme: ""
|
||||||
|
keep_activity_private: false
|
||||||
|
|||||||
@@ -172,7 +172,7 @@ func RenameBranch(ctx context.Context, repo *repo_model.Repository, from, to str
|
|||||||
// 3. Update all not merged pull request base branch name
|
// 3. Update all not merged pull request base branch name
|
||||||
_, err = sess.Table("pull_request").Where("base_repo_id=? AND base_branch=? AND has_merged=?",
|
_, err = sess.Table("pull_request").Where("base_repo_id=? AND base_branch=? AND has_merged=?",
|
||||||
repo.ID, from, false).
|
repo.ID, from, false).
|
||||||
Update(map[string]interface{}{"base_branch": to})
|
Update(map[string]any{"base_branch": to})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -264,7 +264,7 @@ func LFSAutoAssociate(ctx context.Context, metas []*LFSMetaObject, user *user_mo
|
|||||||
|
|
||||||
sess := db.GetEngine(ctx)
|
sess := db.GetEngine(ctx)
|
||||||
|
|
||||||
oids := make([]interface{}, len(metas))
|
oids := make([]any, len(metas))
|
||||||
oidMap := make(map[string]*LFSMetaObject, len(metas))
|
oidMap := make(map[string]*LFSMetaObject, len(metas))
|
||||||
for i, meta := range metas {
|
for i, meta := range metas {
|
||||||
oids[i] = meta.Oid
|
oids[i] = meta.Oid
|
||||||
|
|||||||
@@ -1131,7 +1131,7 @@ func DeleteComment(ctx context.Context, comment *Comment) error {
|
|||||||
}
|
}
|
||||||
if _, err := e.Table("action").
|
if _, err := e.Table("action").
|
||||||
Where("comment_id = ?", comment.ID).
|
Where("comment_id = ?", comment.ID).
|
||||||
Update(map[string]interface{}{
|
Update(map[string]any{
|
||||||
"is_deleted": true,
|
"is_deleted": true,
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -1156,7 +1156,7 @@ func UpdateCommentsMigrationsByType(tp structs.GitServiceType, originalAuthorID
|
|||||||
}),
|
}),
|
||||||
)).
|
)).
|
||||||
And("comment.original_author_id = ?", originalAuthorID).
|
And("comment.original_author_id = ?", originalAuthorID).
|
||||||
Update(map[string]interface{}{
|
Update(map[string]any{
|
||||||
"poster_id": posterID,
|
"poster_id": posterID,
|
||||||
"original_author": "",
|
"original_author": "",
|
||||||
"original_author_id": 0,
|
"original_author_id": 0,
|
||||||
|
|||||||
@@ -714,7 +714,7 @@ func (issue *Issue) Pin(ctx context.Context, user *user_model.User) error {
|
|||||||
|
|
||||||
_, err = db.GetEngine(ctx).Table("issue").
|
_, err = db.GetEngine(ctx).Table("issue").
|
||||||
Where("id = ?", issue.ID).
|
Where("id = ?", issue.ID).
|
||||||
Update(map[string]interface{}{
|
Update(map[string]any{
|
||||||
"pin_order": maxPin + 1,
|
"pin_order": maxPin + 1,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -750,7 +750,7 @@ func (issue *Issue) Unpin(ctx context.Context, user *user_model.User) error {
|
|||||||
|
|
||||||
_, err = db.GetEngine(ctx).Table("issue").
|
_, err = db.GetEngine(ctx).Table("issue").
|
||||||
Where("id = ?", issue.ID).
|
Where("id = ?", issue.ID).
|
||||||
Update(map[string]interface{}{
|
Update(map[string]any{
|
||||||
"pin_order": 0,
|
"pin_order": 0,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -822,7 +822,7 @@ func (issue *Issue) MovePin(ctx context.Context, newPosition int) error {
|
|||||||
|
|
||||||
_, err = db.GetEngine(dbctx).Table("issue").
|
_, err = db.GetEngine(dbctx).Table("issue").
|
||||||
Where("id = ?", issue.ID).
|
Where("id = ?", issue.ID).
|
||||||
Update(map[string]interface{}{
|
Update(map[string]any{
|
||||||
"pin_order": newPosition,
|
"pin_order": newPosition,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -229,39 +229,41 @@ func (issues IssueList) loadMilestones(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issues IssueList) getProjectIDs() []int64 {
|
func (issues IssueList) LoadProjects(ctx context.Context) error {
|
||||||
ids := make(container.Set[int64], len(issues))
|
issueIDs := issues.getIssueIDs()
|
||||||
for _, issue := range issues {
|
projectMaps := make(map[int64]*project_model.Project, len(issues))
|
||||||
ids.Add(issue.ProjectID())
|
left := len(issueIDs)
|
||||||
}
|
|
||||||
return ids.Values()
|
type projectWithIssueID struct {
|
||||||
|
*project_model.Project `xorm:"extends"`
|
||||||
|
IssueID int64
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issues IssueList) loadProjects(ctx context.Context) error {
|
|
||||||
projectIDs := issues.getProjectIDs()
|
|
||||||
if len(projectIDs) == 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
projectMaps := make(map[int64]*project_model.Project, len(projectIDs))
|
|
||||||
left := len(projectIDs)
|
|
||||||
for left > 0 {
|
for left > 0 {
|
||||||
limit := db.DefaultMaxInSize
|
limit := db.DefaultMaxInSize
|
||||||
if left < limit {
|
if left < limit {
|
||||||
limit = left
|
limit = left
|
||||||
}
|
}
|
||||||
|
|
||||||
|
projects := make([]*projectWithIssueID, 0, limit)
|
||||||
err := db.GetEngine(ctx).
|
err := db.GetEngine(ctx).
|
||||||
In("id", projectIDs[:limit]).
|
Table("project").
|
||||||
Find(&projectMaps)
|
Select("project.*, project_issue.issue_id").
|
||||||
|
Join("INNER", "project_issue", "project.id = project_issue.project_id").
|
||||||
|
In("project_issue.issue_id", issueIDs[:limit]).
|
||||||
|
Find(&projects)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
for _, project := range projects {
|
||||||
|
projectMaps[project.IssueID] = project.Project
|
||||||
|
}
|
||||||
left -= limit
|
left -= limit
|
||||||
projectIDs = projectIDs[limit:]
|
issueIDs = issueIDs[limit:]
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, issue := range issues {
|
for _, issue := range issues {
|
||||||
issue.Project = projectMaps[issue.ProjectID()]
|
issue.Project = projectMaps[issue.ID]
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -541,7 +543,7 @@ func (issues IssueList) loadAttributes(ctx context.Context) error {
|
|||||||
return fmt.Errorf("issue.loadAttributes: loadMilestones: %w", err)
|
return fmt.Errorf("issue.loadAttributes: loadMilestones: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := issues.loadProjects(ctx); err != nil {
|
if err := issues.LoadProjects(ctx); err != nil {
|
||||||
return fmt.Errorf("issue.loadAttributes: loadProjects: %w", err)
|
return fmt.Errorf("issue.loadAttributes: loadProjects: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -66,8 +66,10 @@ func TestIssueList_LoadAttributes(t *testing.T) {
|
|||||||
}
|
}
|
||||||
if issue.ID == int64(1) {
|
if issue.ID == int64(1) {
|
||||||
assert.Equal(t, int64(400), issue.TotalTrackedTime)
|
assert.Equal(t, int64(400), issue.TotalTrackedTime)
|
||||||
} else if issue.ID == int64(2) {
|
assert.NotNil(t, issue.Project)
|
||||||
assert.Equal(t, int64(3682), issue.TotalTrackedTime)
|
assert.Equal(t, int64(1), issue.Project.ID)
|
||||||
|
} else {
|
||||||
|
assert.Nil(t, issue.Project)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,20 +16,16 @@ import (
|
|||||||
func (issue *Issue) LoadProject(ctx context.Context) (err error) {
|
func (issue *Issue) LoadProject(ctx context.Context) (err error) {
|
||||||
if issue.Project == nil {
|
if issue.Project == nil {
|
||||||
var p project_model.Project
|
var p project_model.Project
|
||||||
if _, err = db.GetEngine(ctx).Table("project").
|
has, err := db.GetEngine(ctx).Table("project").
|
||||||
Join("INNER", "project_issue", "project.id=project_issue.project_id").
|
Join("INNER", "project_issue", "project.id=project_issue.project_id").
|
||||||
Where("project_issue.issue_id = ?", issue.ID).
|
Where("project_issue.issue_id = ?", issue.ID).Get(&p)
|
||||||
Get(&p); err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
} else if has {
|
||||||
issue.Project = &p
|
issue.Project = &p
|
||||||
}
|
}
|
||||||
return err
|
|
||||||
}
|
}
|
||||||
|
return err
|
||||||
// ProjectID return project id if issue was assigned to one
|
|
||||||
func (issue *Issue) ProjectID() int64 {
|
|
||||||
return issue.projectID(db.DefaultContext)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (issue *Issue) projectID(ctx context.Context) int64 {
|
func (issue *Issue) projectID(ctx context.Context) int64 {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
repo_model "code.gitea.io/gitea/models/repo"
|
repo_model "code.gitea.io/gitea/models/repo"
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
@@ -539,3 +540,47 @@ func TestCountIssues(t *testing.T) {
|
|||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.EqualValues(t, 18, count)
|
assert.EqualValues(t, 18, count)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIssueLoadAttributes(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
setting.Service.EnableTimetracking = true
|
||||||
|
|
||||||
|
issueList := issues_model.IssueList{
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 1}),
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &issues_model.Issue{ID: 4}),
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, issue := range issueList {
|
||||||
|
assert.NoError(t, issue.LoadAttributes(db.DefaultContext))
|
||||||
|
assert.EqualValues(t, issue.RepoID, issue.Repo.ID)
|
||||||
|
for _, label := range issue.Labels {
|
||||||
|
assert.EqualValues(t, issue.RepoID, label.RepoID)
|
||||||
|
unittest.AssertExistsAndLoadBean(t, &issues_model.IssueLabel{IssueID: issue.ID, LabelID: label.ID})
|
||||||
|
}
|
||||||
|
if issue.PosterID > 0 {
|
||||||
|
assert.EqualValues(t, issue.PosterID, issue.Poster.ID)
|
||||||
|
}
|
||||||
|
if issue.AssigneeID > 0 {
|
||||||
|
assert.EqualValues(t, issue.AssigneeID, issue.Assignee.ID)
|
||||||
|
}
|
||||||
|
if issue.MilestoneID > 0 {
|
||||||
|
assert.EqualValues(t, issue.MilestoneID, issue.Milestone.ID)
|
||||||
|
}
|
||||||
|
if issue.IsPull {
|
||||||
|
assert.EqualValues(t, issue.ID, issue.PullRequest.IssueID)
|
||||||
|
}
|
||||||
|
for _, attachment := range issue.Attachments {
|
||||||
|
assert.EqualValues(t, issue.ID, attachment.IssueID)
|
||||||
|
}
|
||||||
|
for _, comment := range issue.Comments {
|
||||||
|
assert.EqualValues(t, issue.ID, comment.IssueID)
|
||||||
|
}
|
||||||
|
if issue.ID == int64(1) {
|
||||||
|
assert.Equal(t, int64(400), issue.TotalTrackedTime)
|
||||||
|
assert.NotNil(t, issue.Project)
|
||||||
|
assert.Equal(t, int64(1), issue.Project.ID)
|
||||||
|
} else {
|
||||||
|
assert.Nil(t, issue.Project)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -511,7 +511,7 @@ func UpdateIssueDeadline(issue *Issue, deadlineUnix timeutil.TimeStamp, doer *us
|
|||||||
}
|
}
|
||||||
|
|
||||||
// DeleteInIssue delete records in beans with external key issue_id = ?
|
// DeleteInIssue delete records in beans with external key issue_id = ?
|
||||||
func DeleteInIssue(ctx context.Context, issueID int64, beans ...interface{}) error {
|
func DeleteInIssue(ctx context.Context, issueID int64, beans ...any) error {
|
||||||
e := db.GetEngine(ctx)
|
e := db.GetEngine(ctx)
|
||||||
for _, bean := range beans {
|
for _, bean := range beans {
|
||||||
if _, err := e.In("issue_id", issueID).Delete(bean); err != nil {
|
if _, err := e.In("issue_id", issueID).Delete(bean); err != nil {
|
||||||
@@ -673,7 +673,7 @@ func UpdateIssuesMigrationsByType(gitServiceType api.GitServiceType, originalAut
|
|||||||
_, err := db.GetEngine(db.DefaultContext).Table("issue").
|
_, err := db.GetEngine(db.DefaultContext).Table("issue").
|
||||||
Where("repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType).
|
Where("repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType).
|
||||||
And("original_author_id = ?", originalAuthorID).
|
And("original_author_id = ?", originalAuthorID).
|
||||||
Update(map[string]interface{}{
|
Update(map[string]any{
|
||||||
"poster_id": posterID,
|
"poster_id": posterID,
|
||||||
"original_author": "",
|
"original_author": "",
|
||||||
"original_author_id": 0,
|
"original_author_id": 0,
|
||||||
@@ -686,7 +686,7 @@ func UpdateReactionsMigrationsByType(gitServiceType api.GitServiceType, original
|
|||||||
_, err := db.GetEngine(db.DefaultContext).Table("reaction").
|
_, err := db.GetEngine(db.DefaultContext).Table("reaction").
|
||||||
Where("original_author_id = ?", originalAuthorID).
|
Where("original_author_id = ?", originalAuthorID).
|
||||||
And(migratedIssueCond(gitServiceType)).
|
And(migratedIssueCond(gitServiceType)).
|
||||||
Update(map[string]interface{}{
|
Update(map[string]any{
|
||||||
"user_id": userID,
|
"user_id": userID,
|
||||||
"original_author": "",
|
"original_author": "",
|
||||||
"original_author_id": 0,
|
"original_author_id": 0,
|
||||||
|
|||||||
@@ -1090,7 +1090,7 @@ func UpdateReviewsMigrationsByType(tp structs.GitServiceType, originalAuthorID s
|
|||||||
_, err := db.GetEngine(db.DefaultContext).Table("review").
|
_, err := db.GetEngine(db.DefaultContext).Table("review").
|
||||||
Where("original_author_id = ?", originalAuthorID).
|
Where("original_author_id = ?", originalAuthorID).
|
||||||
And(migratedIssueCond(tp)).
|
And(migratedIssueCond(tp)).
|
||||||
Update(map[string]interface{}{
|
Update(map[string]any{
|
||||||
"reviewer_id": posterID,
|
"reviewer_id": posterID,
|
||||||
"original_author": "",
|
"original_author": "",
|
||||||
"original_author_id": 0,
|
"original_author_id": 0,
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import (
|
|||||||
|
|
||||||
// RecreateTables will recreate the tables for the provided beans using the newly provided bean definition and move all data to that new table
|
// RecreateTables will recreate the tables for the provided beans using the newly provided bean definition and move all data to that new table
|
||||||
// WARNING: YOU MUST PROVIDE THE FULL BEAN DEFINITION
|
// WARNING: YOU MUST PROVIDE THE FULL BEAN DEFINITION
|
||||||
func RecreateTables(beans ...interface{}) func(*xorm.Engine) error {
|
func RecreateTables(beans ...any) func(*xorm.Engine) error {
|
||||||
return func(x *xorm.Engine) error {
|
return func(x *xorm.Engine) error {
|
||||||
sess := x.NewSession()
|
sess := x.NewSession()
|
||||||
defer sess.Close()
|
defer sess.Close()
|
||||||
@@ -48,7 +48,7 @@ func RecreateTables(beans ...interface{}) func(*xorm.Engine) error {
|
|||||||
// RecreateTable will recreate the table using the newly provided bean definition and move all data to that new table
|
// RecreateTable will recreate the table using the newly provided bean definition and move all data to that new table
|
||||||
// WARNING: YOU MUST PROVIDE THE FULL BEAN DEFINITION
|
// WARNING: YOU MUST PROVIDE THE FULL BEAN DEFINITION
|
||||||
// WARNING: YOU MUST COMMIT THE SESSION AT THE END
|
// WARNING: YOU MUST COMMIT THE SESSION AT THE END
|
||||||
func RecreateTable(sess *xorm.Session, bean interface{}) error {
|
func RecreateTable(sess *xorm.Session, bean any) error {
|
||||||
// TODO: This will not work if there are foreign keys
|
// TODO: This will not work if there are foreign keys
|
||||||
|
|
||||||
tableName := sess.Engine().TableName(bean)
|
tableName := sess.Engine().TableName(bean)
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ import (
|
|||||||
// Provide models to be sync'd with the database - in particular any models you expect fixtures to be loaded from.
|
// Provide models to be sync'd with the database - in particular any models you expect fixtures to be loaded from.
|
||||||
//
|
//
|
||||||
// fixtures in `models/migrations/fixtures/<TestName>` will be loaded automatically
|
// fixtures in `models/migrations/fixtures/<TestName>` will be loaded automatically
|
||||||
func PrepareTestEnv(t *testing.T, skip int, syncModels ...interface{}) (*xorm.Engine, func()) {
|
func PrepareTestEnv(t *testing.T, skip int, syncModels ...any) (*xorm.Engine, func()) {
|
||||||
t.Helper()
|
t.Helper()
|
||||||
ourSkip := 2
|
ourSkip := 2
|
||||||
ourSkip += skip
|
ourSkip += skip
|
||||||
|
|||||||
@@ -62,7 +62,7 @@ func UpdateMigrationServiceTypes(x *xorm.Engine) error {
|
|||||||
ExternalID string `xorm:"pk NOT NULL"`
|
ExternalID string `xorm:"pk NOT NULL"`
|
||||||
UserID int64 `xorm:"INDEX NOT NULL"`
|
UserID int64 `xorm:"INDEX NOT NULL"`
|
||||||
LoginSourceID int64 `xorm:"pk NOT NULL"`
|
LoginSourceID int64 `xorm:"pk NOT NULL"`
|
||||||
RawData map[string]interface{} `xorm:"TEXT JSON"`
|
RawData map[string]any `xorm:"TEXT JSON"`
|
||||||
Provider string `xorm:"index VARCHAR(25)"`
|
Provider string `xorm:"index VARCHAR(25)"`
|
||||||
Email string
|
Email string
|
||||||
Name string
|
Name string
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func UnwrapLDAPSourceCfg(x *xorm.Engine) error {
|
func UnwrapLDAPSourceCfg(x *xorm.Engine) error {
|
||||||
jsonUnmarshalHandleDoubleEncode := func(bs []byte, v interface{}) error {
|
jsonUnmarshalHandleDoubleEncode := func(bs []byte, v any) error {
|
||||||
err := json.Unmarshal(bs, v)
|
err := json.Unmarshal(bs, v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ok := true
|
ok := true
|
||||||
@@ -54,7 +54,7 @@ func UnwrapLDAPSourceCfg(x *xorm.Engine) error {
|
|||||||
const dldapType = 5
|
const dldapType = 5
|
||||||
|
|
||||||
type WrappedSource struct {
|
type WrappedSource struct {
|
||||||
Source map[string]interface{}
|
Source map[string]any
|
||||||
}
|
}
|
||||||
|
|
||||||
// change lower_email as unique
|
// change lower_email as unique
|
||||||
@@ -77,7 +77,7 @@ func UnwrapLDAPSourceCfg(x *xorm.Engine) error {
|
|||||||
|
|
||||||
for _, source := range sources {
|
for _, source := range sources {
|
||||||
wrapped := &WrappedSource{
|
wrapped := &WrappedSource{
|
||||||
Source: map[string]interface{}{},
|
Source: map[string]any{},
|
||||||
}
|
}
|
||||||
err := jsonUnmarshalHandleDoubleEncode([]byte(source.Cfg), &wrapped)
|
err := jsonUnmarshalHandleDoubleEncode([]byte(source.Cfg), &wrapped)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -62,8 +62,8 @@ func Test_UnwrapLDAPSourceCfg(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, source := range sources {
|
for _, source := range sources {
|
||||||
converted := map[string]interface{}{}
|
converted := map[string]any{}
|
||||||
expected := map[string]interface{}{}
|
expected := map[string]any{}
|
||||||
|
|
||||||
if err := json.Unmarshal([]byte(source.Cfg), &converted); err != nil {
|
if err := json.Unmarshal([]byte(source.Cfg), &converted); err != nil {
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ func Test_AddHeaderAuthorizationEncryptedColWebhook(t *testing.T) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, h := range hookTasks {
|
for _, h := range hookTasks {
|
||||||
var m map[string]interface{}
|
var m map[string]any
|
||||||
err := json.Unmarshal([]byte(h.PayloadContent), &m)
|
err := json.Unmarshal([]byte(h.PayloadContent), &m)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Nil(t, m["access_token"])
|
assert.Nil(t, m["access_token"])
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ func AddIssueDependencies(x *xorm.Engine) (err error) {
|
|||||||
ID int64
|
ID int64
|
||||||
RepoID int64 `xorm:"INDEX(s)"`
|
RepoID int64 `xorm:"INDEX(s)"`
|
||||||
Type int `xorm:"INDEX(s)"`
|
Type int `xorm:"INDEX(s)"`
|
||||||
Config map[string]interface{} `xorm:"JSON"`
|
Config map[string]any `xorm:"JSON"`
|
||||||
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
CreatedUnix int64 `xorm:"INDEX CREATED"`
|
||||||
Created time.Time `xorm:"-"`
|
Created time.Time `xorm:"-"`
|
||||||
}
|
}
|
||||||
@@ -96,7 +96,7 @@ func AddIssueDependencies(x *xorm.Engine) (err error) {
|
|||||||
}
|
}
|
||||||
for _, unit := range units {
|
for _, unit := range units {
|
||||||
if unit.Config == nil {
|
if unit.Config == nil {
|
||||||
unit.Config = make(map[string]interface{})
|
unit.Config = make(map[string]any)
|
||||||
}
|
}
|
||||||
if _, ok := unit.Config["EnableDependencies"]; !ok {
|
if _, ok := unit.Config["EnableDependencies"]; !ok {
|
||||||
unit.Config["EnableDependencies"] = setting.Service.DefaultEnableDependencies
|
unit.Config["EnableDependencies"] = setting.Service.DefaultEnableDependencies
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ func AddPullRequestRebaseWithMerge(x *xorm.Engine) error {
|
|||||||
ID int64
|
ID int64
|
||||||
RepoID int64 `xorm:"INDEX(s)"`
|
RepoID int64 `xorm:"INDEX(s)"`
|
||||||
Type int `xorm:"INDEX(s)"`
|
Type int `xorm:"INDEX(s)"`
|
||||||
Config map[string]interface{} `xorm:"JSON"`
|
Config map[string]any `xorm:"JSON"`
|
||||||
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
|
CreatedUnix timeutil.TimeStamp `xorm:"INDEX CREATED"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ func AddPullRequestRebaseWithMerge(x *xorm.Engine) error {
|
|||||||
}
|
}
|
||||||
for _, unit := range units {
|
for _, unit := range units {
|
||||||
if unit.Config == nil {
|
if unit.Config == nil {
|
||||||
unit.Config = make(map[string]interface{})
|
unit.Config = make(map[string]any)
|
||||||
}
|
}
|
||||||
// Allow the new merge style if all other merge styles are allowed
|
// Allow the new merge style if all other merge styles are allowed
|
||||||
allowMergeRebase := true
|
allowMergeRebase := true
|
||||||
|
|||||||
@@ -532,27 +532,6 @@ func GetOrgsCanCreateRepoByUserID(userID int64) ([]*Organization, error) {
|
|||||||
Find(&orgs)
|
Find(&orgs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetOrgUsersByUserID returns all organization-user relations by user ID.
|
|
||||||
func GetOrgUsersByUserID(uid int64, opts *SearchOrganizationsOptions) ([]*OrgUser, error) {
|
|
||||||
ous := make([]*OrgUser, 0, 10)
|
|
||||||
sess := db.GetEngine(db.DefaultContext).
|
|
||||||
Join("LEFT", "`user`", "`org_user`.org_id=`user`.id").
|
|
||||||
Where("`org_user`.uid=?", uid)
|
|
||||||
if !opts.All {
|
|
||||||
// Only show public organizations
|
|
||||||
sess.And("is_public=?", true)
|
|
||||||
}
|
|
||||||
|
|
||||||
if opts.PageSize != 0 {
|
|
||||||
sess = db.SetSessionPagination(sess, opts)
|
|
||||||
}
|
|
||||||
|
|
||||||
err := sess.
|
|
||||||
Asc("`user`.name").
|
|
||||||
Find(&ous)
|
|
||||||
return ous, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetOrgUsersByOrgID returns all organization-user relations by organization ID.
|
// GetOrgUsersByOrgID returns all organization-user relations by organization ID.
|
||||||
func GetOrgUsersByOrgID(ctx context.Context, opts *FindOrgMembersOpts) ([]*OrgUser, error) {
|
func GetOrgUsersByOrgID(ctx context.Context, opts *FindOrgMembersOpts) ([]*OrgUser, error) {
|
||||||
sess := db.GetEngine(ctx).Where("org_id=?", opts.OrgID)
|
sess := db.GetEngine(ctx).Where("org_id=?", opts.OrgID)
|
||||||
|
|||||||
@@ -207,42 +207,6 @@ func TestFindOrgs(t *testing.T) {
|
|||||||
assert.EqualValues(t, 1, total)
|
assert.EqualValues(t, 1, total)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetOrgUsersByUserID(t *testing.T) {
|
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
|
||||||
|
|
||||||
orgUsers, err := organization.GetOrgUsersByUserID(5, &organization.SearchOrganizationsOptions{All: true})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
if assert.Len(t, orgUsers, 3) {
|
|
||||||
assert.Equal(t, organization.OrgUser{
|
|
||||||
ID: orgUsers[0].ID,
|
|
||||||
OrgID: 23,
|
|
||||||
UID: 5,
|
|
||||||
IsPublic: false,
|
|
||||||
}, *orgUsers[0])
|
|
||||||
assert.Equal(t, organization.OrgUser{
|
|
||||||
ID: orgUsers[1].ID,
|
|
||||||
OrgID: 6,
|
|
||||||
UID: 5,
|
|
||||||
IsPublic: true,
|
|
||||||
}, *orgUsers[1])
|
|
||||||
assert.Equal(t, organization.OrgUser{
|
|
||||||
ID: orgUsers[2].ID,
|
|
||||||
OrgID: 7,
|
|
||||||
UID: 5,
|
|
||||||
IsPublic: false,
|
|
||||||
}, *orgUsers[2])
|
|
||||||
}
|
|
||||||
|
|
||||||
publicOrgUsers, err := organization.GetOrgUsersByUserID(5, &organization.SearchOrganizationsOptions{All: false})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, publicOrgUsers, 1)
|
|
||||||
assert.Equal(t, *orgUsers[1], *publicOrgUsers[0])
|
|
||||||
|
|
||||||
orgUsers, err = organization.GetOrgUsersByUserID(1, &organization.SearchOrganizationsOptions{All: true})
|
|
||||||
assert.NoError(t, err)
|
|
||||||
assert.Len(t, orgUsers, 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGetOrgUsersByOrgID(t *testing.T) {
|
func TestGetOrgUsersByOrgID(t *testing.T) {
|
||||||
assert.NoError(t, unittest.PrepareTestDatabase())
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ type PackageDescriptor struct {
|
|||||||
Creator *user_model.User
|
Creator *user_model.User
|
||||||
PackageProperties PackagePropertyList
|
PackageProperties PackagePropertyList
|
||||||
VersionProperties PackagePropertyList
|
VersionProperties PackagePropertyList
|
||||||
Metadata interface{}
|
Metadata any
|
||||||
Files []*PackageFileDescriptor
|
Files []*PackageFileDescriptor
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,7 +136,7 @@ func GetPackageDescriptor(ctx context.Context, pv *PackageVersion) (*PackageDesc
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var metadata interface{}
|
var metadata any
|
||||||
switch p.Type {
|
switch p.Type {
|
||||||
case TypeAlpine:
|
case TypeAlpine:
|
||||||
metadata = &alpine.VersionMetadata{}
|
metadata = &alpine.VersionMetadata{}
|
||||||
|
|||||||
@@ -5,11 +5,18 @@ package packages
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/db"
|
"code.gitea.io/gitea/models/db"
|
||||||
|
"code.gitea.io/gitea/models/perm"
|
||||||
|
"code.gitea.io/gitea/models/unit"
|
||||||
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
"code.gitea.io/gitea/modules/structs"
|
||||||
"code.gitea.io/gitea/modules/timeutil"
|
"code.gitea.io/gitea/modules/timeutil"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
|
"xorm.io/builder"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrPackageBlobNotExist indicates a package blob not exist error
|
// ErrPackageBlobNotExist indicates a package blob not exist error
|
||||||
@@ -98,3 +105,42 @@ func GetTotalUnreferencedBlobSize(ctx context.Context) (int64, error) {
|
|||||||
Where("package_file.id IS NULL").
|
Where("package_file.id IS NULL").
|
||||||
SumInt(&PackageBlob{}, "size")
|
SumInt(&PackageBlob{}, "size")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// IsBlobAccessibleForUser tests if the user has access to the blob
|
||||||
|
func IsBlobAccessibleForUser(ctx context.Context, blobID int64, user *user_model.User) (bool, error) {
|
||||||
|
if user.IsAdmin {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
maxTeamAuthorize := builder.
|
||||||
|
Select("max(team.authorize)").
|
||||||
|
From("team").
|
||||||
|
InnerJoin("team_user", "team_user.team_id = team.id").
|
||||||
|
Where(builder.Eq{"team_user.uid": user.ID}.And(builder.Expr("team_user.org_id = `user`.id")))
|
||||||
|
|
||||||
|
maxTeamUnitAccessMode := builder.
|
||||||
|
Select("max(team_unit.access_mode)").
|
||||||
|
From("team").
|
||||||
|
InnerJoin("team_user", "team_user.team_id = team.id").
|
||||||
|
InnerJoin("team_unit", "team_unit.team_id = team.id").
|
||||||
|
Where(builder.Eq{"team_user.uid": user.ID, "team_unit.type": unit.TypePackages}.And(builder.Expr("team_user.org_id = `user`.id")))
|
||||||
|
|
||||||
|
cond := builder.Eq{"package_blob.id": blobID}.And(
|
||||||
|
// owner = user
|
||||||
|
builder.Eq{"`user`.id": user.ID}.
|
||||||
|
// user can see owner
|
||||||
|
Or(builder.Eq{"`user`.visibility": structs.VisibleTypePublic}.Or(builder.Eq{"`user`.visibility": structs.VisibleTypeLimited})).
|
||||||
|
// owner is an organization and user has access to it
|
||||||
|
Or(builder.Eq{"`user`.type": user_model.UserTypeOrganization}.
|
||||||
|
And(builder.Lte{strconv.Itoa(int(perm.AccessModeRead)): maxTeamAuthorize}.Or(builder.Lte{strconv.Itoa(int(perm.AccessModeRead)): maxTeamUnitAccessMode}))),
|
||||||
|
)
|
||||||
|
|
||||||
|
return db.GetEngine(ctx).
|
||||||
|
Table("package_blob").
|
||||||
|
Join("INNER", "package_file", "package_file.blob_id = package_blob.id").
|
||||||
|
Join("INNER", "package_version", "package_version.id = package_file.version_id").
|
||||||
|
Join("INNER", "package", "package.id = package_version.package_id").
|
||||||
|
Join("INNER", "user", "`user`.id = package.owner_id").
|
||||||
|
Where(cond).
|
||||||
|
Exist(&PackageBlob{})
|
||||||
|
}
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ type SearchOptions struct {
|
|||||||
RepoID int64
|
RepoID int64
|
||||||
Page int
|
Page int
|
||||||
IsClosed util.OptionalBool
|
IsClosed util.OptionalBool
|
||||||
SortType string
|
OrderBy db.SearchOrderBy
|
||||||
Type Type
|
Type Type
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,26 +226,28 @@ func CountProjects(ctx context.Context, opts SearchOptions) (int64, error) {
|
|||||||
return db.GetEngine(ctx).Where(opts.toConds()).Count(new(Project))
|
return db.GetEngine(ctx).Where(opts.toConds()).Count(new(Project))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSearchOrderByBySortType(sortType string) db.SearchOrderBy {
|
||||||
|
switch sortType {
|
||||||
|
case "oldest":
|
||||||
|
return db.SearchOrderByOldest
|
||||||
|
case "recentupdate":
|
||||||
|
return db.SearchOrderByRecentUpdated
|
||||||
|
case "leastupdate":
|
||||||
|
return db.SearchOrderByLeastUpdated
|
||||||
|
default:
|
||||||
|
return db.SearchOrderByNewest
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// FindProjects returns a list of all projects that have been created in the repository
|
// FindProjects returns a list of all projects that have been created in the repository
|
||||||
func FindProjects(ctx context.Context, opts SearchOptions) ([]*Project, int64, error) {
|
func FindProjects(ctx context.Context, opts SearchOptions) ([]*Project, int64, error) {
|
||||||
e := db.GetEngine(ctx).Where(opts.toConds())
|
e := db.GetEngine(ctx).Where(opts.toConds()).OrderBy(opts.OrderBy.String())
|
||||||
projects := make([]*Project, 0, setting.UI.IssuePagingNum)
|
projects := make([]*Project, 0, setting.UI.IssuePagingNum)
|
||||||
|
|
||||||
if opts.Page > 0 {
|
if opts.Page > 0 {
|
||||||
e = e.Limit(setting.UI.IssuePagingNum, (opts.Page-1)*setting.UI.IssuePagingNum)
|
e = e.Limit(setting.UI.IssuePagingNum, (opts.Page-1)*setting.UI.IssuePagingNum)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch opts.SortType {
|
|
||||||
case "oldest":
|
|
||||||
e.Desc("created_unix")
|
|
||||||
case "recentupdate":
|
|
||||||
e.Desc("updated_unix")
|
|
||||||
case "leastupdate":
|
|
||||||
e.Asc("updated_unix")
|
|
||||||
default:
|
|
||||||
e.Asc("created_unix")
|
|
||||||
}
|
|
||||||
|
|
||||||
count, err := e.FindAndCount(&projects)
|
count, err := e.FindAndCount(&projects)
|
||||||
return projects, count, err
|
return projects, count, err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,3 +82,42 @@ func TestProject(t *testing.T) {
|
|||||||
|
|
||||||
assert.True(t, projectFromDB.IsClosed)
|
assert.True(t, projectFromDB.IsClosed)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestProjectsSort(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
sortType string
|
||||||
|
wants []int64
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
sortType: "default",
|
||||||
|
wants: []int64{1, 3, 2, 4},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sortType: "oldest",
|
||||||
|
wants: []int64{4, 2, 3, 1},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sortType: "recentupdate",
|
||||||
|
wants: []int64{1, 3, 2, 4},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
sortType: "leastupdate",
|
||||||
|
wants: []int64{4, 2, 3, 1},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
projects, count, err := FindProjects(db.DefaultContext, SearchOptions{
|
||||||
|
OrderBy: GetSearchOrderByBySortType(tt.sortType),
|
||||||
|
})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, int64(4), count)
|
||||||
|
if assert.Len(t, projects, 4) {
|
||||||
|
for i := range projects {
|
||||||
|
assert.EqualValues(t, tt.wants[i], projects[i].ID)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -456,7 +456,7 @@ func repoStatsCorrectNumClosedPulls(ctx context.Context, id int64) error {
|
|||||||
return repo_model.UpdateRepoIssueNumbers(ctx, id, true, true)
|
return repo_model.UpdateRepoIssueNumbers(ctx, id, true, true)
|
||||||
}
|
}
|
||||||
|
|
||||||
func statsQuery(args ...interface{}) func(context.Context) ([]map[string][]byte, error) {
|
func statsQuery(args ...any) func(context.Context) ([]map[string][]byte, error) {
|
||||||
return func(ctx context.Context) ([]map[string][]byte, error) {
|
return func(ctx context.Context) ([]map[string][]byte, error) {
|
||||||
return db.GetEngine(ctx).Query(args...)
|
return db.GetEngine(ctx).Query(args...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,13 +65,6 @@ func (a *Attachment) DownloadURL() string {
|
|||||||
return setting.AppURL + "attachments/" + url.PathEscape(a.UUID)
|
return setting.AppURL + "attachments/" + url.PathEscape(a.UUID)
|
||||||
}
|
}
|
||||||
|
|
||||||
// _____ __ __ .__ __
|
|
||||||
// / _ \_/ |__/ |______ ____ | |__ _____ ____ _____/ |_
|
|
||||||
// / /_\ \ __\ __\__ \ _/ ___\| | \ / \_/ __ \ / \ __\
|
|
||||||
// / | \ | | | / __ \\ \___| Y \ Y Y \ ___/| | \ |
|
|
||||||
// \____|__ /__| |__| (____ /\___ >___| /__|_| /\___ >___| /__|
|
|
||||||
// \/ \/ \/ \/ \/ \/ \/
|
|
||||||
|
|
||||||
// ErrAttachmentNotExist represents a "AttachmentNotExist" kind of error.
|
// ErrAttachmentNotExist represents a "AttachmentNotExist" kind of error.
|
||||||
type ErrAttachmentNotExist struct {
|
type ErrAttachmentNotExist struct {
|
||||||
ID int64
|
ID int64
|
||||||
|
|||||||
@@ -33,6 +33,19 @@ func TestRepository_GetCollaborators(t *testing.T) {
|
|||||||
test(2)
|
test(2)
|
||||||
test(3)
|
test(3)
|
||||||
test(4)
|
test(4)
|
||||||
|
|
||||||
|
// Test db.ListOptions
|
||||||
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 22})
|
||||||
|
|
||||||
|
collaborators1, err := repo_model.GetCollaborators(db.DefaultContext, repo.ID, db.ListOptions{PageSize: 1, Page: 1})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, collaborators1, 1)
|
||||||
|
|
||||||
|
collaborators2, err := repo_model.GetCollaborators(db.DefaultContext, repo.ID, db.ListOptions{PageSize: 1, Page: 2})
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Len(t, collaborators2, 1)
|
||||||
|
|
||||||
|
assert.NotEqualValues(t, collaborators1[0].ID, collaborators2[0].ID)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestRepository_IsCollaborator(t *testing.T) {
|
func TestRepository_IsCollaborator(t *testing.T) {
|
||||||
@@ -66,5 +79,80 @@ func TestRepository_ChangeCollaborationAccessMode(t *testing.T) {
|
|||||||
|
|
||||||
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, unittest.NonexistentID, perm.AccessModeAdmin))
|
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, unittest.NonexistentID, perm.AccessModeAdmin))
|
||||||
|
|
||||||
|
// Disvard invalid input.
|
||||||
|
assert.NoError(t, repo_model.ChangeCollaborationAccessMode(db.DefaultContext, repo, 4, perm.AccessMode(unittest.NonexistentID)))
|
||||||
|
|
||||||
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID})
|
unittest.CheckConsistencyFor(t, &repo_model.Repository{ID: repo.ID})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestRepository_CountCollaborators(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
||||||
|
count, err := repo_model.CountCollaborators(repo1.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 2, count)
|
||||||
|
|
||||||
|
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 22})
|
||||||
|
count, err = repo_model.CountCollaborators(repo2.ID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 2, count)
|
||||||
|
|
||||||
|
// Non-existent repository.
|
||||||
|
count, err = repo_model.CountCollaborators(unittest.NonexistentID)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.EqualValues(t, 0, count)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRepository_IsOwnerMemberCollaborator(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
repo1 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 3})
|
||||||
|
|
||||||
|
// Organisation owner.
|
||||||
|
actual, err := repo_model.IsOwnerMemberCollaborator(repo1, 2)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, actual)
|
||||||
|
|
||||||
|
// Team member.
|
||||||
|
actual, err = repo_model.IsOwnerMemberCollaborator(repo1, 4)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, actual)
|
||||||
|
|
||||||
|
// Normal user.
|
||||||
|
actual, err = repo_model.IsOwnerMemberCollaborator(repo1, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.False(t, actual)
|
||||||
|
|
||||||
|
repo2 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
||||||
|
|
||||||
|
// Collaborator.
|
||||||
|
actual, err = repo_model.IsOwnerMemberCollaborator(repo2, 4)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, actual)
|
||||||
|
|
||||||
|
repo3 := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 15})
|
||||||
|
|
||||||
|
// Repository owner.
|
||||||
|
actual, err = repo_model.IsOwnerMemberCollaborator(repo3, 2)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, actual)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestRepo_GetCollaboration(t *testing.T) {
|
||||||
|
assert.NoError(t, unittest.PrepareTestDatabase())
|
||||||
|
|
||||||
|
repo := unittest.AssertExistsAndLoadBean(t, &repo_model.Repository{ID: 4})
|
||||||
|
|
||||||
|
// Existing collaboration.
|
||||||
|
collab, err := repo_model.GetCollaboration(db.DefaultContext, repo.ID, 4)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, collab)
|
||||||
|
assert.EqualValues(t, 4, collab.UserID)
|
||||||
|
assert.EqualValues(t, 4, collab.RepoID)
|
||||||
|
|
||||||
|
// Non-existing collaboration.
|
||||||
|
collab, err = repo_model.GetCollaboration(db.DefaultContext, repo.ID, 1)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Nil(t, collab)
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ type MergeStyle string
|
|||||||
const (
|
const (
|
||||||
// MergeStyleMerge create merge commit
|
// MergeStyleMerge create merge commit
|
||||||
MergeStyleMerge MergeStyle = "merge"
|
MergeStyleMerge MergeStyle = "merge"
|
||||||
// MergeStyleRebase rebase before merging
|
// MergeStyleRebase rebase before merging, and fast-forward
|
||||||
MergeStyleRebase MergeStyle = "rebase"
|
MergeStyleRebase MergeStyle = "rebase"
|
||||||
// MergeStyleRebaseMerge rebase before merging with merge commit (--no-ff)
|
// MergeStyleRebaseMerge rebase before merging with merge commit (--no-ff)
|
||||||
MergeStyleRebaseMerge MergeStyle = "rebase-merge"
|
MergeStyleRebaseMerge MergeStyle = "rebase-merge"
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ func DeleteMirrorByRepoID(repoID int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// MirrorsIterate iterates all mirror repositories.
|
// MirrorsIterate iterates all mirror repositories.
|
||||||
func MirrorsIterate(limit int, f func(idx int, bean interface{}) error) error {
|
func MirrorsIterate(limit int, f func(idx int, bean any) error) error {
|
||||||
sess := db.GetEngine(db.DefaultContext).
|
sess := db.GetEngine(db.DefaultContext).
|
||||||
Where("next_update_unix<=?", time.Now().Unix()).
|
Where("next_update_unix<=?", time.Now().Unix()).
|
||||||
And("next_update_unix!=0").
|
And("next_update_unix!=0").
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ func GetPushMirrorsSyncedOnCommit(ctx context.Context, repoID int64) ([]*PushMir
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PushMirrorsIterate iterates all push-mirror repositories.
|
// PushMirrorsIterate iterates all push-mirror repositories.
|
||||||
func PushMirrorsIterate(ctx context.Context, limit int, f func(idx int, bean interface{}) error) error {
|
func PushMirrorsIterate(ctx context.Context, limit int, f func(idx int, bean any) error) error {
|
||||||
sess := db.GetEngine(ctx).
|
sess := db.GetEngine(ctx).
|
||||||
Where("last_update + (`interval` / ?) <= ?", time.Second, time.Now().Unix()).
|
Where("last_update + (`interval` / ?) <= ?", time.Second, time.Now().Unix()).
|
||||||
And("`interval` != 0").
|
And("`interval` != 0").
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func TestPushMirrorsIterate(t *testing.T) {
|
|||||||
|
|
||||||
time.Sleep(1 * time.Millisecond)
|
time.Sleep(1 * time.Millisecond)
|
||||||
|
|
||||||
repo_model.PushMirrorsIterate(db.DefaultContext, 1, func(idx int, bean interface{}) error {
|
repo_model.PushMirrorsIterate(db.DefaultContext, 1, func(idx int, bean any) error {
|
||||||
m, ok := bean.(*repo_model.PushMirror)
|
m, ok := bean.(*repo_model.PushMirror)
|
||||||
assert.True(t, ok)
|
assert.True(t, ok)
|
||||||
assert.Equal(t, "test-1", m.RemoteName)
|
assert.Equal(t, "test-1", m.RemoteName)
|
||||||
|
|||||||
@@ -442,7 +442,7 @@ func UpdateReleasesMigrationsByType(gitServiceType structs.GitServiceType, origi
|
|||||||
_, err := db.GetEngine(db.DefaultContext).Table("release").
|
_, err := db.GetEngine(db.DefaultContext).Table("release").
|
||||||
Where("repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType).
|
Where("repo_id IN (SELECT id FROM repository WHERE original_service_type = ?)", gitServiceType).
|
||||||
And("original_author_id = ?", originalAuthorID).
|
And("original_author_id = ?", originalAuthorID).
|
||||||
Update(map[string]interface{}{
|
Update(map[string]any{
|
||||||
"publisher_id": posterID,
|
"publisher_id": posterID,
|
||||||
"original_author": "",
|
"original_author": "",
|
||||||
"original_author_id": 0,
|
"original_author_id": 0,
|
||||||
|
|||||||
@@ -560,7 +560,7 @@ func searchRepositoryByCondition(ctx context.Context, opts *SearchRepoOptions, c
|
|||||||
opts.OrderBy = db.SearchOrderByAlphabetically
|
opts.OrderBy = db.SearchOrderByAlphabetically
|
||||||
}
|
}
|
||||||
|
|
||||||
args := make([]interface{}, 0)
|
args := make([]any, 0)
|
||||||
if opts.PriorityOwnerID > 0 {
|
if opts.PriorityOwnerID > 0 {
|
||||||
opts.OrderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_id = ? THEN 0 ELSE owner_id END, %s", opts.OrderBy))
|
opts.OrderBy = db.SearchOrderBy(fmt.Sprintf("CASE WHEN owner_id = ? THEN 0 ELSE owner_id END, %s", opts.OrderBy))
|
||||||
args = append(args, opts.PriorityOwnerID)
|
args = append(args, opts.PriorityOwnerID)
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ func (n *Notice) TrStr() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateNotice creates new system notice.
|
// CreateNotice creates new system notice.
|
||||||
func CreateNotice(ctx context.Context, tp NoticeType, desc string, args ...interface{}) error {
|
func CreateNotice(ctx context.Context, tp NoticeType, desc string, args ...any) error {
|
||||||
if len(args) > 0 {
|
if len(args) > 0 {
|
||||||
desc = fmt.Sprintf(desc, args...)
|
desc = fmt.Sprintf(desc, args...)
|
||||||
}
|
}
|
||||||
@@ -55,7 +55,7 @@ func CreateNotice(ctx context.Context, tp NoticeType, desc string, args ...inter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// CreateRepositoryNotice creates new system notice with type NoticeRepository.
|
// CreateRepositoryNotice creates new system notice with type NoticeRepository.
|
||||||
func CreateRepositoryNotice(desc string, args ...interface{}) error {
|
func CreateRepositoryNotice(desc string, args ...any) error {
|
||||||
// Note we use the db.DefaultContext here rather than passing in a context as the context may be cancelled
|
// Note we use the db.DefaultContext here rather than passing in a context as the context may be cancelled
|
||||||
return CreateNotice(db.DefaultContext, NoticeRepository, desc, args...)
|
return CreateNotice(db.DefaultContext, NoticeRepository, desc, args...)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,10 +21,10 @@ const (
|
|||||||
modelsCommentTypeComment = 0
|
modelsCommentTypeComment = 0
|
||||||
)
|
)
|
||||||
|
|
||||||
var consistencyCheckMap = make(map[string]func(t assert.TestingT, bean interface{}))
|
var consistencyCheckMap = make(map[string]func(t assert.TestingT, bean any))
|
||||||
|
|
||||||
// CheckConsistencyFor test that all matching database entries are consistent
|
// CheckConsistencyFor test that all matching database entries are consistent
|
||||||
func CheckConsistencyFor(t assert.TestingT, beansToCheck ...interface{}) {
|
func CheckConsistencyFor(t assert.TestingT, beansToCheck ...any) {
|
||||||
for _, bean := range beansToCheck {
|
for _, bean := range beansToCheck {
|
||||||
sliceType := reflect.SliceOf(reflect.TypeOf(bean))
|
sliceType := reflect.SliceOf(reflect.TypeOf(bean))
|
||||||
sliceValue := reflect.MakeSlice(sliceType, 0, 10)
|
sliceValue := reflect.MakeSlice(sliceType, 0, 10)
|
||||||
@@ -42,7 +42,7 @@ func CheckConsistencyFor(t assert.TestingT, beansToCheck ...interface{}) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func checkForConsistency(t assert.TestingT, bean interface{}) {
|
func checkForConsistency(t assert.TestingT, bean any) {
|
||||||
tb, err := db.TableInfo(bean)
|
tb, err := db.TableInfo(bean)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
f := consistencyCheckMap[tb.Name]
|
f := consistencyCheckMap[tb.Name]
|
||||||
@@ -63,7 +63,7 @@ func init() {
|
|||||||
return i
|
return i
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForUserConsistency := func(t assert.TestingT, bean interface{}) {
|
checkForUserConsistency := func(t assert.TestingT, bean any) {
|
||||||
user := reflectionWrap(bean)
|
user := reflectionWrap(bean)
|
||||||
AssertCountByCond(t, "repository", builder.Eq{"owner_id": user.int("ID")}, user.int("NumRepos"))
|
AssertCountByCond(t, "repository", builder.Eq{"owner_id": user.int("ID")}, user.int("NumRepos"))
|
||||||
AssertCountByCond(t, "star", builder.Eq{"uid": user.int("ID")}, user.int("NumStars"))
|
AssertCountByCond(t, "star", builder.Eq{"uid": user.int("ID")}, user.int("NumStars"))
|
||||||
@@ -77,7 +77,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForRepoConsistency := func(t assert.TestingT, bean interface{}) {
|
checkForRepoConsistency := func(t assert.TestingT, bean any) {
|
||||||
repo := reflectionWrap(bean)
|
repo := reflectionWrap(bean)
|
||||||
assert.Equal(t, repo.str("LowerName"), strings.ToLower(repo.str("Name")), "repo: %+v", repo)
|
assert.Equal(t, repo.str("LowerName"), strings.ToLower(repo.str("Name")), "repo: %+v", repo)
|
||||||
AssertCountByCond(t, "star", builder.Eq{"repo_id": repo.int("ID")}, repo.int("NumStars"))
|
AssertCountByCond(t, "star", builder.Eq{"repo_id": repo.int("ID")}, repo.int("NumStars"))
|
||||||
@@ -113,7 +113,7 @@ func init() {
|
|||||||
"Unexpected number of closed milestones for repo id: %d", repo.int("ID"))
|
"Unexpected number of closed milestones for repo id: %d", repo.int("ID"))
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForIssueConsistency := func(t assert.TestingT, bean interface{}) {
|
checkForIssueConsistency := func(t assert.TestingT, bean any) {
|
||||||
issue := reflectionWrap(bean)
|
issue := reflectionWrap(bean)
|
||||||
typeComment := modelsCommentTypeComment
|
typeComment := modelsCommentTypeComment
|
||||||
actual := GetCountByCond(t, "comment", builder.Eq{"`type`": typeComment, "issue_id": issue.int("ID")})
|
actual := GetCountByCond(t, "comment", builder.Eq{"`type`": typeComment, "issue_id": issue.int("ID")})
|
||||||
@@ -124,14 +124,14 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForPullRequestConsistency := func(t assert.TestingT, bean interface{}) {
|
checkForPullRequestConsistency := func(t assert.TestingT, bean any) {
|
||||||
pr := reflectionWrap(bean)
|
pr := reflectionWrap(bean)
|
||||||
issueRow := AssertExistsAndLoadMap(t, "issue", builder.Eq{"id": pr.int("IssueID")})
|
issueRow := AssertExistsAndLoadMap(t, "issue", builder.Eq{"id": pr.int("IssueID")})
|
||||||
assert.True(t, parseBool(issueRow["is_pull"]))
|
assert.True(t, parseBool(issueRow["is_pull"]))
|
||||||
assert.EqualValues(t, parseInt(issueRow["index"]), pr.int("Index"), "Unexpected index for pull request id: %d", pr.int("ID"))
|
assert.EqualValues(t, parseInt(issueRow["index"]), pr.int("Index"), "Unexpected index for pull request id: %d", pr.int("ID"))
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForMilestoneConsistency := func(t assert.TestingT, bean interface{}) {
|
checkForMilestoneConsistency := func(t assert.TestingT, bean any) {
|
||||||
milestone := reflectionWrap(bean)
|
milestone := reflectionWrap(bean)
|
||||||
AssertCountByCond(t, "issue", builder.Eq{"milestone_id": milestone.int("ID")}, milestone.int("NumIssues"))
|
AssertCountByCond(t, "issue", builder.Eq{"milestone_id": milestone.int("ID")}, milestone.int("NumIssues"))
|
||||||
|
|
||||||
@@ -145,7 +145,7 @@ func init() {
|
|||||||
assert.Equal(t, completeness, milestone.int("Completeness"))
|
assert.Equal(t, completeness, milestone.int("Completeness"))
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForLabelConsistency := func(t assert.TestingT, bean interface{}) {
|
checkForLabelConsistency := func(t assert.TestingT, bean any) {
|
||||||
label := reflectionWrap(bean)
|
label := reflectionWrap(bean)
|
||||||
issueLabels, err := db.GetEngine(db.DefaultContext).Table("issue_label").
|
issueLabels, err := db.GetEngine(db.DefaultContext).Table("issue_label").
|
||||||
Where(builder.Eq{"label_id": label.int("ID")}).
|
Where(builder.Eq{"label_id": label.int("ID")}).
|
||||||
@@ -166,13 +166,13 @@ func init() {
|
|||||||
assert.EqualValues(t, expected, label.int("NumClosedIssues"), "Unexpected number of closed issues for label id: %d", label.int("ID"))
|
assert.EqualValues(t, expected, label.int("NumClosedIssues"), "Unexpected number of closed issues for label id: %d", label.int("ID"))
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForTeamConsistency := func(t assert.TestingT, bean interface{}) {
|
checkForTeamConsistency := func(t assert.TestingT, bean any) {
|
||||||
team := reflectionWrap(bean)
|
team := reflectionWrap(bean)
|
||||||
AssertCountByCond(t, "team_user", builder.Eq{"team_id": team.int("ID")}, team.int("NumMembers"))
|
AssertCountByCond(t, "team_user", builder.Eq{"team_id": team.int("ID")}, team.int("NumMembers"))
|
||||||
AssertCountByCond(t, "team_repo", builder.Eq{"team_id": team.int("ID")}, team.int("NumRepos"))
|
AssertCountByCond(t, "team_repo", builder.Eq{"team_id": team.int("ID")}, team.int("NumRepos"))
|
||||||
}
|
}
|
||||||
|
|
||||||
checkForActionConsistency := func(t assert.TestingT, bean interface{}) {
|
checkForActionConsistency := func(t assert.TestingT, bean any) {
|
||||||
action := reflectionWrap(bean)
|
action := reflectionWrap(bean)
|
||||||
if action.int("RepoID") != 1700 { // dangling intentional
|
if action.int("RepoID") != 1700 { // dangling intentional
|
||||||
repoRow := AssertExistsAndLoadMap(t, "repository", builder.Eq{"id": action.int("RepoID")})
|
repoRow := AssertExistsAndLoadMap(t, "repository", builder.Eq{"id": action.int("RepoID")})
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ type reflectionValue struct {
|
|||||||
v reflect.Value
|
v reflect.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
func reflectionWrap(v interface{}) *reflectionValue {
|
func reflectionWrap(v any) *reflectionValue {
|
||||||
return &reflectionValue{v: reflect.ValueOf(v)}
|
return &reflectionValue{v: reflect.ValueOf(v)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func FixturesDir() string {
|
|||||||
return fixturesDir
|
return fixturesDir
|
||||||
}
|
}
|
||||||
|
|
||||||
func fatalTestError(fmtStr string, args ...interface{}) {
|
func fatalTestError(fmtStr string, args ...any) {
|
||||||
_, _ = fmt.Fprintf(os.Stderr, fmtStr, args...)
|
_, _ = fmt.Fprintf(os.Stderr, fmtStr, args...)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ type ExternalLoginUser struct {
|
|||||||
ExternalID string `xorm:"pk NOT NULL"`
|
ExternalID string `xorm:"pk NOT NULL"`
|
||||||
UserID int64 `xorm:"INDEX NOT NULL"`
|
UserID int64 `xorm:"INDEX NOT NULL"`
|
||||||
LoginSourceID int64 `xorm:"pk NOT NULL"`
|
LoginSourceID int64 `xorm:"pk NOT NULL"`
|
||||||
RawData map[string]interface{} `xorm:"TEXT JSON"`
|
RawData map[string]any `xorm:"TEXT JSON"`
|
||||||
Provider string `xorm:"index VARCHAR(25)"`
|
Provider string `xorm:"index VARCHAR(25)"`
|
||||||
Email string
|
Email string
|
||||||
Name string
|
Name string
|
||||||
|
|||||||
@@ -64,6 +64,10 @@ func NewUserRedirect(ctx context.Context, ID int64, oldUserName, newUserName str
|
|||||||
oldUserName = strings.ToLower(oldUserName)
|
oldUserName = strings.ToLower(oldUserName)
|
||||||
newUserName = strings.ToLower(newUserName)
|
newUserName = strings.ToLower(newUserName)
|
||||||
|
|
||||||
|
if err := DeleteUserRedirect(ctx, oldUserName); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
if err := DeleteUserRedirect(ctx, newUserName); err != nil {
|
if err := DeleteUserRedirect(ctx, newUserName); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ func (t *HookTask) AfterLoad() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *HookTask) simpleMarshalJSON(v interface{}) string {
|
func (t *HookTask) simpleMarshalJSON(v any) string {
|
||||||
p, err := json.Marshal(v)
|
p, err := json.Marshal(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error("Marshal [%d]: %v", t.ID, err)
|
log.Error("Marshal [%d]: %v", t.ID, err)
|
||||||
|
|||||||
@@ -29,12 +29,28 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func WriteLogs(ctx context.Context, filename string, offset int64, rows []*runnerv1.LogRow) ([]int, error) {
|
func WriteLogs(ctx context.Context, filename string, offset int64, rows []*runnerv1.LogRow) ([]int, error) {
|
||||||
|
flag := os.O_WRONLY
|
||||||
|
if offset == 0 {
|
||||||
|
// Create file only if offset is 0, or it could result in content holes if the file doesn't exist.
|
||||||
|
flag |= os.O_CREATE
|
||||||
|
}
|
||||||
name := DBFSPrefix + filename
|
name := DBFSPrefix + filename
|
||||||
f, err := dbfs.OpenFile(ctx, name, os.O_WRONLY|os.O_CREATE)
|
f, err := dbfs.OpenFile(ctx, name, flag)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("dbfs OpenFile %q: %w", name, err)
|
return nil, fmt.Errorf("dbfs OpenFile %q: %w", name, err)
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
|
|
||||||
|
stat, err := f.Stat()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("dbfs Stat %q: %w", name, err)
|
||||||
|
}
|
||||||
|
if stat.Size() < offset {
|
||||||
|
// If the size is less than offset, refuse to write, or it could result in content holes.
|
||||||
|
// However, if the size is greater than offset, we can still write to overwrite the content.
|
||||||
|
return nil, fmt.Errorf("size of %q is less than offset", name)
|
||||||
|
}
|
||||||
|
|
||||||
if _, err := f.Seek(offset, io.SeekStart); err != nil {
|
if _, err := f.Seek(offset, io.SeekStart); err != nil {
|
||||||
return nil, fmt.Errorf("dbfs Seek %q: %w", name, err)
|
return nil, fmt.Errorf("dbfs Seek %q: %w", name, err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
model.OnDecodeNodeError = func(node yaml.Node, out interface{}, err error) {
|
model.OnDecodeNodeError = func(node yaml.Node, out any, err error) {
|
||||||
// Log the error instead of panic or fatal.
|
// Log the error instead of panic or fatal.
|
||||||
// It will be a big job to refactor act/pkg/model to return decode error,
|
// It will be a big job to refactor act/pkg/model to return decode error,
|
||||||
// so we just log the error and return empty value, and improve it later.
|
// so we just log the error and return empty value, and improve it later.
|
||||||
@@ -321,18 +321,15 @@ func matchIssuesEvent(commit *git.Commit, issuePayload *api.IssuePayload, evt *j
|
|||||||
}
|
}
|
||||||
|
|
||||||
func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
|
func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload, evt *jobparser.Event) bool {
|
||||||
// with no special filter parameters
|
acts := evt.Acts()
|
||||||
if len(evt.Acts()) == 0 {
|
activityTypeMatched := false
|
||||||
|
matchTimes := 0
|
||||||
|
|
||||||
|
if vals, ok := acts["types"]; !ok {
|
||||||
// defaultly, only pull request `opened`, `reopened` and `synchronized` will trigger workflow
|
// defaultly, only pull request `opened`, `reopened` and `synchronized` will trigger workflow
|
||||||
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
||||||
return prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
|
activityTypeMatched = prPayload.Action == api.HookIssueSynchronized || prPayload.Action == api.HookIssueOpened || prPayload.Action == api.HookIssueReOpened
|
||||||
}
|
} else {
|
||||||
|
|
||||||
matchTimes := 0
|
|
||||||
// all acts conditions should be satisfied
|
|
||||||
for cond, vals := range evt.Acts() {
|
|
||||||
switch cond {
|
|
||||||
case "types":
|
|
||||||
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
// See https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request
|
||||||
// Actions with the same name:
|
// Actions with the same name:
|
||||||
// opened, edited, closed, reopened, assigned, unassigned
|
// opened, edited, closed, reopened, assigned, unassigned
|
||||||
@@ -355,10 +352,16 @@ func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload
|
|||||||
log.Trace("matching pull_request %s with %v", action, vals)
|
log.Trace("matching pull_request %s with %v", action, vals)
|
||||||
for _, val := range vals {
|
for _, val := range vals {
|
||||||
if glob.MustCompile(val, '/').Match(string(action)) {
|
if glob.MustCompile(val, '/').Match(string(action)) {
|
||||||
|
activityTypeMatched = true
|
||||||
matchTimes++
|
matchTimes++
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// all acts conditions should be satisfied
|
||||||
|
for cond, vals := range acts {
|
||||||
|
switch cond {
|
||||||
case "branches":
|
case "branches":
|
||||||
refName := git.RefName(prPayload.PullRequest.Base.Ref)
|
refName := git.RefName(prPayload.PullRequest.Base.Ref)
|
||||||
patterns, err := workflowpattern.CompilePatterns(vals...)
|
patterns, err := workflowpattern.CompilePatterns(vals...)
|
||||||
@@ -407,7 +410,7 @@ func matchPullRequestEvent(commit *git.Commit, prPayload *api.PullRequestPayload
|
|||||||
log.Warn("pull request event unsupported condition %q", cond)
|
log.Warn("pull request event unsupported condition %q", cond)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return matchTimes == len(evt.Acts())
|
return activityTypeMatched && matchTimes == len(evt.Acts())
|
||||||
}
|
}
|
||||||
|
|
||||||
func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCommentPayload, evt *jobparser.Event) bool {
|
func matchIssueCommentEvent(commit *git.Commit, issueCommentPayload *api.IssueCommentPayload, evt *jobparser.Event) bool {
|
||||||
|
|||||||
@@ -57,6 +57,25 @@ func TestDetectMatched(t *testing.T) {
|
|||||||
yamlOn: "on: pull_request",
|
yamlOn: "on: pull_request",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
desc: "HookEventPullRequest(pull_request) `closed` action doesn't match GithubEventPullRequest(pull_request) with no activity type",
|
||||||
|
triggedEvent: webhook_module.HookEventPullRequest,
|
||||||
|
payload: &api.PullRequestPayload{Action: api.HookIssueClosed},
|
||||||
|
yamlOn: "on: pull_request",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
desc: "HookEventPullRequest(pull_request) `closed` action doesn't match GithubEventPullRequest(pull_request) with branches",
|
||||||
|
triggedEvent: webhook_module.HookEventPullRequest,
|
||||||
|
payload: &api.PullRequestPayload{
|
||||||
|
Action: api.HookIssueClosed,
|
||||||
|
PullRequest: &api.PullRequest{
|
||||||
|
Base: &api.PRBranchInfo{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
yamlOn: "on:\n pull_request:\n branches: [main]",
|
||||||
|
expected: false,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
desc: "HookEventPullRequest(pull_request) `label_updated` action matches githubEventPullRequest(pull_request) with `label` activity type",
|
desc: "HookEventPullRequest(pull_request) `label_updated` action matches githubEventPullRequest(pull_request) with `label` activity type",
|
||||||
triggedEvent: webhook_module.HookEventPullRequest,
|
triggedEvent: webhook_module.HookEventPullRequest,
|
||||||
|
|||||||
@@ -215,8 +215,9 @@ func (l *LayeredFS) WatchLocalChanges(ctx context.Context, callback func()) {
|
|||||||
log.Error("Unable to list directories for asset local file-system %q: %v", layer.localPath, err)
|
log.Error("Unable to list directories for asset local file-system %q: %v", layer.localPath, err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
layerDirs = append(layerDirs, ".")
|
||||||
for _, dir := range layerDirs {
|
for _, dir := range layerDirs {
|
||||||
if err = watcher.Add(util.FilePathJoinAbs(layer.localPath, dir)); err != nil {
|
if err = watcher.Add(util.FilePathJoinAbs(layer.localPath, dir)); err != nil && !os.IsNotExist(err) {
|
||||||
log.Error("Unable to watch directory %s: %v", dir, err)
|
log.Error("Unable to watch directory %s: %v", dir, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ const TimeLimitCodeLength = 12 + 6 + 40
|
|||||||
|
|
||||||
// CreateTimeLimitCode create a time limit code
|
// CreateTimeLimitCode create a time limit code
|
||||||
// code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string
|
// code format: 12 length date time string + 6 minutes string + 40 sha1 encoded string
|
||||||
func CreateTimeLimitCode(data string, minutes int, startInf interface{}) string {
|
func CreateTimeLimitCode(data string, minutes int, startInf any) string {
|
||||||
format := "200601021504"
|
format := "200601021504"
|
||||||
|
|
||||||
var start, end time.Time
|
var start, end time.Time
|
||||||
@@ -245,7 +245,7 @@ func SetupGiteaRoot() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// FormatNumberSI format a number
|
// FormatNumberSI format a number
|
||||||
func FormatNumberSI(data interface{}) string {
|
func FormatNumberSI(data any) string {
|
||||||
var num int64
|
var num int64
|
||||||
if num1, ok := data.(int64); ok {
|
if num1, ok := data.(int64); ok {
|
||||||
num = num1
|
num = num1
|
||||||
|
|||||||
6
modules/cache/cache_redis.go
vendored
6
modules/cache/cache_redis.go
vendored
@@ -24,7 +24,7 @@ type RedisCacher struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// toStr convert string/int/int64 interface to string. it's only used by the RedisCacher.Put internally
|
// toStr convert string/int/int64 interface to string. it's only used by the RedisCacher.Put internally
|
||||||
func toStr(v interface{}) string {
|
func toStr(v any) string {
|
||||||
if v == nil {
|
if v == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@@ -44,7 +44,7 @@ func toStr(v interface{}) string {
|
|||||||
|
|
||||||
// Put puts value (string type) into cache with key and expire time.
|
// Put puts value (string type) into cache with key and expire time.
|
||||||
// If expired is 0, it lives forever.
|
// If expired is 0, it lives forever.
|
||||||
func (c *RedisCacher) Put(key string, val interface{}, expire int64) error {
|
func (c *RedisCacher) Put(key string, val any, expire int64) error {
|
||||||
// this function is not well-designed, it only puts string values into cache
|
// this function is not well-designed, it only puts string values into cache
|
||||||
key = c.prefix + key
|
key = c.prefix + key
|
||||||
if expire == 0 {
|
if expire == 0 {
|
||||||
@@ -65,7 +65,7 @@ func (c *RedisCacher) Put(key string, val interface{}, expire int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get gets cached value by given key.
|
// Get gets cached value by given key.
|
||||||
func (c *RedisCacher) Get(key string) interface{} {
|
func (c *RedisCacher) Get(key string) any {
|
||||||
val, err := c.c.Get(graceful.GetManager().HammerContext(), c.prefix+key).Result()
|
val, err := c.c.Get(graceful.GetManager().HammerContext(), c.prefix+key).Result()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
|
|||||||
8
modules/cache/cache_twoqueue.go
vendored
8
modules/cache/cache_twoqueue.go
vendored
@@ -30,7 +30,7 @@ type TwoQueueCacheConfig struct {
|
|||||||
|
|
||||||
// MemoryItem represents a memory cache item.
|
// MemoryItem represents a memory cache item.
|
||||||
type MemoryItem struct {
|
type MemoryItem struct {
|
||||||
Val interface{}
|
Val any
|
||||||
Created int64
|
Created int64
|
||||||
Timeout int64
|
Timeout int64
|
||||||
}
|
}
|
||||||
@@ -43,7 +43,7 @@ func (item *MemoryItem) hasExpired() bool {
|
|||||||
var _ mc.Cache = &TwoQueueCache{}
|
var _ mc.Cache = &TwoQueueCache{}
|
||||||
|
|
||||||
// Put puts value into cache with key and expire time.
|
// Put puts value into cache with key and expire time.
|
||||||
func (c *TwoQueueCache) Put(key string, val interface{}, timeout int64) error {
|
func (c *TwoQueueCache) Put(key string, val any, timeout int64) error {
|
||||||
item := &MemoryItem{
|
item := &MemoryItem{
|
||||||
Val: val,
|
Val: val,
|
||||||
Created: time.Now().Unix(),
|
Created: time.Now().Unix(),
|
||||||
@@ -56,7 +56,7 @@ func (c *TwoQueueCache) Put(key string, val interface{}, timeout int64) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Get gets cached value by given key.
|
// Get gets cached value by given key.
|
||||||
func (c *TwoQueueCache) Get(key string) interface{} {
|
func (c *TwoQueueCache) Get(key string) any {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
cached, ok := c.cache.Get(key)
|
cached, ok := c.cache.Get(key)
|
||||||
@@ -146,7 +146,7 @@ func (c *TwoQueueCache) Flush() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *TwoQueueCache) checkAndInvalidate(key interface{}) {
|
func (c *TwoQueueCache) checkAndInvalidate(key any) {
|
||||||
c.lock.Lock()
|
c.lock.Lock()
|
||||||
defer c.lock.Unlock()
|
defer c.lock.Unlock()
|
||||||
cached, ok := c.cache.Peek(key)
|
cached, ok := c.cache.Peek(key)
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ Usage: %[1]s [-v] [-o output.go] ambiguous.json
|
|||||||
sort.Slice(tables, func(i, j int) bool {
|
sort.Slice(tables, func(i, j int) bool {
|
||||||
return tables[i].Locale < tables[j].Locale
|
return tables[i].Locale < tables[j].Locale
|
||||||
})
|
})
|
||||||
data := map[string]interface{}{
|
data := map[string]any{
|
||||||
"Tables": tables,
|
"Tables": tables,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +99,7 @@ Usage: %[1]s [-v] [-o output.go] ambiguous.json
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func runTemplate(t *template.Template, filename string, data interface{}) error {
|
func runTemplate(t *template.Template, filename string, data any) error {
|
||||||
buf := bytes.NewBuffer(nil)
|
buf := bytes.NewBuffer(nil)
|
||||||
if err := t.Execute(buf, data); err != nil {
|
if err := t.Execute(buf, data); err != nil {
|
||||||
return fmt.Errorf("unable to execute template: %w", err)
|
return fmt.Errorf("unable to execute template: %w", err)
|
||||||
@@ -172,17 +172,17 @@ var AmbiguousCharacters = map[string]*AmbiguousTable{
|
|||||||
|
|
||||||
`))
|
`))
|
||||||
|
|
||||||
func logf(format string, args ...interface{}) {
|
func logf(format string, args ...any) {
|
||||||
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
fmt.Fprintf(os.Stderr, format+"\n", args...)
|
||||||
}
|
}
|
||||||
|
|
||||||
func verbosef(format string, args ...interface{}) {
|
func verbosef(format string, args ...any) {
|
||||||
if verbose {
|
if verbose {
|
||||||
logf(format, args...)
|
logf(format, args...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func fatalf(format string, args ...interface{}) {
|
func fatalf(format string, args ...any) {
|
||||||
logf("fatal: "+format+"\n", args...)
|
logf("fatal: "+format+"\n", args...)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user