Refactor to use urfave/cli/v2 (#25959)
Replace #10912 And there are many new tests to cover the CLI behavior There were some concerns about the "option order in hook scripts" (https://github.com/go-gitea/gitea/pull/10912#issuecomment-1137543314), it's not a problem now. Because the hook script uses `/gitea hook --config=/app.ini pre-receive` format. The "config" is a global option, it can appear anywhere. ---- ## ⚠️ BREAKING ⚠️ This PR does it best to avoid breaking anything. The major changes are: * `gitea` itself won't accept web's options: `--install-port` / `--pid` / `--port` / `--quiet` / `--verbose` .... They are `web` sub-command's options. * Use `./gitea web --pid ....` instead * `./gitea` can still run the `web` sub-command as shorthand, with default options * The sub-command's options must follow the sub-command * Before: `./gitea --sub-opt subcmd` might equal to `./gitea subcmd --sub-opt` (well, might not ...) * After: only `./gitea subcmd --sub-opt` could be used * The global options like `--config` are not affected
This commit is contained in:
parent
840830b655
commit
d0dbe52e76
File diff suppressed because one or more lines are too long
|
@ -9,28 +9,29 @@ import (
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// CmdActions represents the available actions sub-commands.
|
// CmdActions represents the available actions sub-commands.
|
||||||
CmdActions = cli.Command{
|
CmdActions = &cli.Command{
|
||||||
Name: "actions",
|
Name: "actions",
|
||||||
Usage: "",
|
Usage: "",
|
||||||
Description: "Commands for managing Gitea Actions",
|
Description: "Commands for managing Gitea Actions",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
subcmdActionsGenRunnerToken,
|
subcmdActionsGenRunnerToken,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmdActionsGenRunnerToken = cli.Command{
|
subcmdActionsGenRunnerToken = &cli.Command{
|
||||||
Name: "generate-runner-token",
|
Name: "generate-runner-token",
|
||||||
Usage: "Generate a new token for a runner to use to register with the server",
|
Usage: "Generate a new token for a runner to use to register with the server",
|
||||||
Action: runGenerateActionsRunnerToken,
|
Action: runGenerateActionsRunnerToken,
|
||||||
Aliases: []string{"grt"},
|
Aliases: []string{"grt"},
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "scope, s",
|
Name: "scope",
|
||||||
|
Aliases: []string{"s"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "{owner}[/{repo}] - leave empty for a global runner",
|
Usage: "{owner}[/{repo}] - leave empty for a global runner",
|
||||||
},
|
},
|
||||||
|
|
131
cmd/admin.go
131
cmd/admin.go
|
@ -26,15 +26,15 @@ import (
|
||||||
"code.gitea.io/gitea/services/auth/source/smtp"
|
"code.gitea.io/gitea/services/auth/source/smtp"
|
||||||
repo_service "code.gitea.io/gitea/services/repository"
|
repo_service "code.gitea.io/gitea/services/repository"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// CmdAdmin represents the available admin sub-command.
|
// CmdAdmin represents the available admin sub-command.
|
||||||
CmdAdmin = cli.Command{
|
CmdAdmin = &cli.Command{
|
||||||
Name: "admin",
|
Name: "admin",
|
||||||
Usage: "Command line interface to perform common administrative operations",
|
Usage: "Command line interface to perform common administrative operations",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
subcmdUser,
|
subcmdUser,
|
||||||
subcmdRepoSyncReleases,
|
subcmdRepoSyncReleases,
|
||||||
subcmdRegenerate,
|
subcmdRegenerate,
|
||||||
|
@ -43,37 +43,37 @@ var (
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmdRepoSyncReleases = cli.Command{
|
subcmdRepoSyncReleases = &cli.Command{
|
||||||
Name: "repo-sync-releases",
|
Name: "repo-sync-releases",
|
||||||
Usage: "Synchronize repository releases with tags",
|
Usage: "Synchronize repository releases with tags",
|
||||||
Action: runRepoSyncReleases,
|
Action: runRepoSyncReleases,
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmdRegenerate = cli.Command{
|
subcmdRegenerate = &cli.Command{
|
||||||
Name: "regenerate",
|
Name: "regenerate",
|
||||||
Usage: "Regenerate specific files",
|
Usage: "Regenerate specific files",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
microcmdRegenHooks,
|
microcmdRegenHooks,
|
||||||
microcmdRegenKeys,
|
microcmdRegenKeys,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
microcmdRegenHooks = cli.Command{
|
microcmdRegenHooks = &cli.Command{
|
||||||
Name: "hooks",
|
Name: "hooks",
|
||||||
Usage: "Regenerate git-hooks",
|
Usage: "Regenerate git-hooks",
|
||||||
Action: runRegenerateHooks,
|
Action: runRegenerateHooks,
|
||||||
}
|
}
|
||||||
|
|
||||||
microcmdRegenKeys = cli.Command{
|
microcmdRegenKeys = &cli.Command{
|
||||||
Name: "keys",
|
Name: "keys",
|
||||||
Usage: "Regenerate authorized_keys file",
|
Usage: "Regenerate authorized_keys file",
|
||||||
Action: runRegenerateKeys,
|
Action: runRegenerateKeys,
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmdAuth = cli.Command{
|
subcmdAuth = &cli.Command{
|
||||||
Name: "auth",
|
Name: "auth",
|
||||||
Usage: "Modify external auth providers",
|
Usage: "Modify external auth providers",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
microcmdAuthAddOauth,
|
microcmdAuthAddOauth,
|
||||||
microcmdAuthUpdateOauth,
|
microcmdAuthUpdateOauth,
|
||||||
cmdAuthAddLdapBindDn,
|
cmdAuthAddLdapBindDn,
|
||||||
|
@ -87,44 +87,44 @@ var (
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
microcmdAuthList = cli.Command{
|
microcmdAuthList = &cli.Command{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "List auth sources",
|
Usage: "List auth sources",
|
||||||
Action: runListAuth,
|
Action: runListAuth,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.IntFlag{
|
&cli.IntFlag{
|
||||||
Name: "min-width",
|
Name: "min-width",
|
||||||
Usage: "Minimal cell width including any padding for the formatted table",
|
Usage: "Minimal cell width including any padding for the formatted table",
|
||||||
Value: 0,
|
Value: 0,
|
||||||
},
|
},
|
||||||
cli.IntFlag{
|
&cli.IntFlag{
|
||||||
Name: "tab-width",
|
Name: "tab-width",
|
||||||
Usage: "width of tab characters in formatted table (equivalent number of spaces)",
|
Usage: "width of tab characters in formatted table (equivalent number of spaces)",
|
||||||
Value: 8,
|
Value: 8,
|
||||||
},
|
},
|
||||||
cli.IntFlag{
|
&cli.IntFlag{
|
||||||
Name: "padding",
|
Name: "padding",
|
||||||
Usage: "padding added to a cell before computing its width",
|
Usage: "padding added to a cell before computing its width",
|
||||||
Value: 1,
|
Value: 1,
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "pad-char",
|
Name: "pad-char",
|
||||||
Usage: `ASCII char used for padding if padchar == '\\t', the Writer will assume that the width of a '\\t' in the formatted output is tabwidth, and cells are left-aligned independent of align_left (for correct-looking results, tabwidth must correspond to the tab width in the viewer displaying the result)`,
|
Usage: `ASCII char used for padding if padchar == '\\t', the Writer will assume that the width of a '\\t' in the formatted output is tabwidth, and cells are left-aligned independent of align_left (for correct-looking results, tabwidth must correspond to the tab width in the viewer displaying the result)`,
|
||||||
Value: "\t",
|
Value: "\t",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "vertical-bars",
|
Name: "vertical-bars",
|
||||||
Usage: "Set to true to print vertical bars between columns",
|
Usage: "Set to true to print vertical bars between columns",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
idFlag = cli.Int64Flag{
|
idFlag = &cli.Int64Flag{
|
||||||
Name: "id",
|
Name: "id",
|
||||||
Usage: "ID of authentication source",
|
Usage: "ID of authentication source",
|
||||||
}
|
}
|
||||||
|
|
||||||
microcmdAuthDelete = cli.Command{
|
microcmdAuthDelete = &cli.Command{
|
||||||
Name: "delete",
|
Name: "delete",
|
||||||
Usage: "Delete specific auth source",
|
Usage: "Delete specific auth source",
|
||||||
Flags: []cli.Flag{idFlag},
|
Flags: []cli.Flag{idFlag},
|
||||||
|
@ -132,207 +132,208 @@ var (
|
||||||
}
|
}
|
||||||
|
|
||||||
oauthCLIFlags = []cli.Flag{
|
oauthCLIFlags = []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Application Name",
|
Usage: "Application Name",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "provider",
|
Name: "provider",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "OAuth2 Provider",
|
Usage: "OAuth2 Provider",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "key",
|
Name: "key",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Client ID (Key)",
|
Usage: "Client ID (Key)",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "secret",
|
Name: "secret",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Client Secret",
|
Usage: "Client Secret",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "auto-discover-url",
|
Name: "auto-discover-url",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "OpenID Connect Auto Discovery URL (only required when using OpenID Connect as provider)",
|
Usage: "OpenID Connect Auto Discovery URL (only required when using OpenID Connect as provider)",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "use-custom-urls",
|
Name: "use-custom-urls",
|
||||||
Value: "false",
|
Value: "false",
|
||||||
Usage: "Use custom URLs for GitLab/GitHub OAuth endpoints",
|
Usage: "Use custom URLs for GitLab/GitHub OAuth endpoints",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "custom-tenant-id",
|
Name: "custom-tenant-id",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Use custom Tenant ID for OAuth endpoints",
|
Usage: "Use custom Tenant ID for OAuth endpoints",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "custom-auth-url",
|
Name: "custom-auth-url",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Use a custom Authorization URL (option for GitLab/GitHub)",
|
Usage: "Use a custom Authorization URL (option for GitLab/GitHub)",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "custom-token-url",
|
Name: "custom-token-url",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Use a custom Token URL (option for GitLab/GitHub)",
|
Usage: "Use a custom Token URL (option for GitLab/GitHub)",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "custom-profile-url",
|
Name: "custom-profile-url",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Use a custom Profile URL (option for GitLab/GitHub)",
|
Usage: "Use a custom Profile URL (option for GitLab/GitHub)",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "custom-email-url",
|
Name: "custom-email-url",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Use a custom Email URL (option for GitHub)",
|
Usage: "Use a custom Email URL (option for GitHub)",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "icon-url",
|
Name: "icon-url",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Custom icon URL for OAuth2 login source",
|
Usage: "Custom icon URL for OAuth2 login source",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-local-2fa",
|
Name: "skip-local-2fa",
|
||||||
Usage: "Set to true to skip local 2fa for users authenticated by this source",
|
Usage: "Set to true to skip local 2fa for users authenticated by this source",
|
||||||
},
|
},
|
||||||
cli.StringSliceFlag{
|
&cli.StringSliceFlag{
|
||||||
Name: "scopes",
|
Name: "scopes",
|
||||||
Value: nil,
|
Value: nil,
|
||||||
Usage: "Scopes to request when to authenticate against this OAuth2 source",
|
Usage: "Scopes to request when to authenticate against this OAuth2 source",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "required-claim-name",
|
Name: "required-claim-name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Claim name that has to be set to allow users to login with this source",
|
Usage: "Claim name that has to be set to allow users to login with this source",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "required-claim-value",
|
Name: "required-claim-value",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Claim value that has to be set to allow users to login with this source",
|
Usage: "Claim value that has to be set to allow users to login with this source",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "group-claim-name",
|
Name: "group-claim-name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Claim name providing group names for this source",
|
Usage: "Claim name providing group names for this source",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "admin-group",
|
Name: "admin-group",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Group Claim value for administrator users",
|
Usage: "Group Claim value for administrator users",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "restricted-group",
|
Name: "restricted-group",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Group Claim value for restricted users",
|
Usage: "Group Claim value for restricted users",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "group-team-map",
|
Name: "group-team-map",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "JSON mapping between groups and org teams",
|
Usage: "JSON mapping between groups and org teams",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "group-team-map-removal",
|
Name: "group-team-map-removal",
|
||||||
Usage: "Activate automatic team membership removal depending on groups",
|
Usage: "Activate automatic team membership removal depending on groups",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
microcmdAuthUpdateOauth = cli.Command{
|
microcmdAuthUpdateOauth = &cli.Command{
|
||||||
Name: "update-oauth",
|
Name: "update-oauth",
|
||||||
Usage: "Update existing Oauth authentication source",
|
Usage: "Update existing Oauth authentication source",
|
||||||
Action: runUpdateOauth,
|
Action: runUpdateOauth,
|
||||||
Flags: append(oauthCLIFlags[:1], append([]cli.Flag{idFlag}, oauthCLIFlags[1:]...)...),
|
Flags: append(oauthCLIFlags[:1], append([]cli.Flag{idFlag}, oauthCLIFlags[1:]...)...),
|
||||||
}
|
}
|
||||||
|
|
||||||
microcmdAuthAddOauth = cli.Command{
|
microcmdAuthAddOauth = &cli.Command{
|
||||||
Name: "add-oauth",
|
Name: "add-oauth",
|
||||||
Usage: "Add new Oauth authentication source",
|
Usage: "Add new Oauth authentication source",
|
||||||
Action: runAddOauth,
|
Action: runAddOauth,
|
||||||
Flags: oauthCLIFlags,
|
Flags: oauthCLIFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmdSendMail = cli.Command{
|
subcmdSendMail = &cli.Command{
|
||||||
Name: "sendmail",
|
Name: "sendmail",
|
||||||
Usage: "Send a message to all users",
|
Usage: "Send a message to all users",
|
||||||
Action: runSendMail,
|
Action: runSendMail,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "title",
|
Name: "title",
|
||||||
Usage: `a title of a message`,
|
Usage: `a title of a message`,
|
||||||
Value: "",
|
Value: "",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "content",
|
Name: "content",
|
||||||
Usage: "a content of a message",
|
Usage: "a content of a message",
|
||||||
Value: "",
|
Value: "",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "force,f",
|
Name: "force",
|
||||||
|
Aliases: []string{"f"},
|
||||||
Usage: "A flag to bypass a confirmation step",
|
Usage: "A flag to bypass a confirmation step",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
smtpCLIFlags = []cli.Flag{
|
smtpCLIFlags = []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Application Name",
|
Usage: "Application Name",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "auth-type",
|
Name: "auth-type",
|
||||||
Value: "PLAIN",
|
Value: "PLAIN",
|
||||||
Usage: "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN",
|
Usage: "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "host",
|
Name: "host",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "SMTP Host",
|
Usage: "SMTP Host",
|
||||||
},
|
},
|
||||||
cli.IntFlag{
|
&cli.IntFlag{
|
||||||
Name: "port",
|
Name: "port",
|
||||||
Usage: "SMTP Port",
|
Usage: "SMTP Port",
|
||||||
},
|
},
|
||||||
cli.BoolTFlag{
|
&cli.BoolFlag{
|
||||||
Name: "force-smtps",
|
Name: "force-smtps",
|
||||||
Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.",
|
Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.",
|
||||||
},
|
},
|
||||||
cli.BoolTFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-verify",
|
Name: "skip-verify",
|
||||||
Usage: "Skip TLS verify.",
|
Usage: "Skip TLS verify.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "helo-hostname",
|
Name: "helo-hostname",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Hostname sent with HELO. Leave blank to send current hostname",
|
Usage: "Hostname sent with HELO. Leave blank to send current hostname",
|
||||||
},
|
},
|
||||||
cli.BoolTFlag{
|
&cli.BoolFlag{
|
||||||
Name: "disable-helo",
|
Name: "disable-helo",
|
||||||
Usage: "Disable SMTP helo.",
|
Usage: "Disable SMTP helo.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "allowed-domains",
|
Name: "allowed-domains",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Leave empty to allow all domains. Separate multiple domains with a comma (',')",
|
Usage: "Leave empty to allow all domains. Separate multiple domains with a comma (',')",
|
||||||
},
|
},
|
||||||
cli.BoolTFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-local-2fa",
|
Name: "skip-local-2fa",
|
||||||
Usage: "Skip 2FA to log on.",
|
Usage: "Skip 2FA to log on.",
|
||||||
},
|
},
|
||||||
cli.BoolTFlag{
|
&cli.BoolFlag{
|
||||||
Name: "active",
|
Name: "active",
|
||||||
Usage: "This Authentication Source is Activated.",
|
Usage: "This Authentication Source is Activated.",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
microcmdAuthAddSMTP = cli.Command{
|
microcmdAuthAddSMTP = &cli.Command{
|
||||||
Name: "add-smtp",
|
Name: "add-smtp",
|
||||||
Usage: "Add new SMTP authentication source",
|
Usage: "Add new SMTP authentication source",
|
||||||
Action: runAddSMTP,
|
Action: runAddSMTP,
|
||||||
Flags: smtpCLIFlags,
|
Flags: smtpCLIFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
microcmdAuthUpdateSMTP = cli.Command{
|
microcmdAuthUpdateSMTP = &cli.Command{
|
||||||
Name: "update-smtp",
|
Name: "update-smtp",
|
||||||
Usage: "Update existing SMTP authentication source",
|
Usage: "Update existing SMTP authentication source",
|
||||||
Action: runUpdateSMTP,
|
Action: runUpdateSMTP,
|
||||||
|
@ -611,19 +612,19 @@ func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error {
|
||||||
conf.AllowedDomains = c.String("allowed-domains")
|
conf.AllowedDomains = c.String("allowed-domains")
|
||||||
}
|
}
|
||||||
if c.IsSet("force-smtps") {
|
if c.IsSet("force-smtps") {
|
||||||
conf.ForceSMTPS = c.BoolT("force-smtps")
|
conf.ForceSMTPS = c.Bool("force-smtps")
|
||||||
}
|
}
|
||||||
if c.IsSet("skip-verify") {
|
if c.IsSet("skip-verify") {
|
||||||
conf.SkipVerify = c.BoolT("skip-verify")
|
conf.SkipVerify = c.Bool("skip-verify")
|
||||||
}
|
}
|
||||||
if c.IsSet("helo-hostname") {
|
if c.IsSet("helo-hostname") {
|
||||||
conf.HeloHostname = c.String("helo-hostname")
|
conf.HeloHostname = c.String("helo-hostname")
|
||||||
}
|
}
|
||||||
if c.IsSet("disable-helo") {
|
if c.IsSet("disable-helo") {
|
||||||
conf.DisableHelo = c.BoolT("disable-helo")
|
conf.DisableHelo = c.Bool("disable-helo")
|
||||||
}
|
}
|
||||||
if c.IsSet("skip-local-2fa") {
|
if c.IsSet("skip-local-2fa") {
|
||||||
conf.SkipLocalTwoFA = c.BoolT("skip-local-2fa")
|
conf.SkipLocalTwoFA = c.Bool("skip-local-2fa")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -647,7 +648,7 @@ func runAddSMTP(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
active := true
|
active := true
|
||||||
if c.IsSet("active") {
|
if c.IsSet("active") {
|
||||||
active = c.BoolT("active")
|
active = c.Bool("active")
|
||||||
}
|
}
|
||||||
|
|
||||||
var smtpConfig smtp.Source
|
var smtpConfig smtp.Source
|
||||||
|
@ -696,7 +697,7 @@ func runUpdateSMTP(c *cli.Context) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsSet("active") {
|
if c.IsSet("active") {
|
||||||
source.IsActive = c.BoolT("active")
|
source.IsActive = c.Bool("active")
|
||||||
}
|
}
|
||||||
|
|
||||||
source.Cfg = smtpConfig
|
source.Cfg = smtpConfig
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"code.gitea.io/gitea/models/auth"
|
"code.gitea.io/gitea/models/auth"
|
||||||
"code.gitea.io/gitea/services/auth/source/ldap"
|
"code.gitea.io/gitea/services/auth/source/ldap"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
type (
|
type (
|
||||||
|
@ -25,117 +25,117 @@ type (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
commonLdapCLIFlags = []cli.Flag{
|
commonLdapCLIFlags = []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Usage: "Authentication name.",
|
Usage: "Authentication name.",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "not-active",
|
Name: "not-active",
|
||||||
Usage: "Deactivate the authentication source.",
|
Usage: "Deactivate the authentication source.",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "active",
|
Name: "active",
|
||||||
Usage: "Activate the authentication source.",
|
Usage: "Activate the authentication source.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "security-protocol",
|
Name: "security-protocol",
|
||||||
Usage: "Security protocol name.",
|
Usage: "Security protocol name.",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-tls-verify",
|
Name: "skip-tls-verify",
|
||||||
Usage: "Disable TLS verification.",
|
Usage: "Disable TLS verification.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "host",
|
Name: "host",
|
||||||
Usage: "The address where the LDAP server can be reached.",
|
Usage: "The address where the LDAP server can be reached.",
|
||||||
},
|
},
|
||||||
cli.IntFlag{
|
&cli.IntFlag{
|
||||||
Name: "port",
|
Name: "port",
|
||||||
Usage: "The port to use when connecting to the LDAP server.",
|
Usage: "The port to use when connecting to the LDAP server.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "user-search-base",
|
Name: "user-search-base",
|
||||||
Usage: "The LDAP base at which user accounts will be searched for.",
|
Usage: "The LDAP base at which user accounts will be searched for.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "user-filter",
|
Name: "user-filter",
|
||||||
Usage: "An LDAP filter declaring how to find the user record that is attempting to authenticate.",
|
Usage: "An LDAP filter declaring how to find the user record that is attempting to authenticate.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "admin-filter",
|
Name: "admin-filter",
|
||||||
Usage: "An LDAP filter specifying if a user should be given administrator privileges.",
|
Usage: "An LDAP filter specifying if a user should be given administrator privileges.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "restricted-filter",
|
Name: "restricted-filter",
|
||||||
Usage: "An LDAP filter specifying if a user should be given restricted status.",
|
Usage: "An LDAP filter specifying if a user should be given restricted status.",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "allow-deactivate-all",
|
Name: "allow-deactivate-all",
|
||||||
Usage: "Allow empty search results to deactivate all users.",
|
Usage: "Allow empty search results to deactivate all users.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "username-attribute",
|
Name: "username-attribute",
|
||||||
Usage: "The attribute of the user’s LDAP record containing the user name.",
|
Usage: "The attribute of the user’s LDAP record containing the user name.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "firstname-attribute",
|
Name: "firstname-attribute",
|
||||||
Usage: "The attribute of the user’s LDAP record containing the user’s first name.",
|
Usage: "The attribute of the user’s LDAP record containing the user’s first name.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "surname-attribute",
|
Name: "surname-attribute",
|
||||||
Usage: "The attribute of the user’s LDAP record containing the user’s surname.",
|
Usage: "The attribute of the user’s LDAP record containing the user’s surname.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "email-attribute",
|
Name: "email-attribute",
|
||||||
Usage: "The attribute of the user’s LDAP record containing the user’s email address.",
|
Usage: "The attribute of the user’s LDAP record containing the user’s email address.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "public-ssh-key-attribute",
|
Name: "public-ssh-key-attribute",
|
||||||
Usage: "The attribute of the user’s LDAP record containing the user’s public ssh key.",
|
Usage: "The attribute of the user’s LDAP record containing the user’s public ssh key.",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-local-2fa",
|
Name: "skip-local-2fa",
|
||||||
Usage: "Set to true to skip local 2fa for users authenticated by this source",
|
Usage: "Set to true to skip local 2fa for users authenticated by this source",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "avatar-attribute",
|
Name: "avatar-attribute",
|
||||||
Usage: "The attribute of the user’s LDAP record containing the user’s avatar.",
|
Usage: "The attribute of the user’s LDAP record containing the user’s avatar.",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
ldapBindDnCLIFlags = append(commonLdapCLIFlags,
|
ldapBindDnCLIFlags = append(commonLdapCLIFlags,
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "bind-dn",
|
Name: "bind-dn",
|
||||||
Usage: "The DN to bind to the LDAP server with when searching for the user.",
|
Usage: "The DN to bind to the LDAP server with when searching for the user.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "bind-password",
|
Name: "bind-password",
|
||||||
Usage: "The password for the Bind DN, if any.",
|
Usage: "The password for the Bind DN, if any.",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "attributes-in-bind",
|
Name: "attributes-in-bind",
|
||||||
Usage: "Fetch attributes in bind DN context.",
|
Usage: "Fetch attributes in bind DN context.",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "synchronize-users",
|
Name: "synchronize-users",
|
||||||
Usage: "Enable user synchronization.",
|
Usage: "Enable user synchronization.",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "disable-synchronize-users",
|
Name: "disable-synchronize-users",
|
||||||
Usage: "Disable user synchronization.",
|
Usage: "Disable user synchronization.",
|
||||||
},
|
},
|
||||||
cli.UintFlag{
|
&cli.UintFlag{
|
||||||
Name: "page-size",
|
Name: "page-size",
|
||||||
Usage: "Search page size.",
|
Usage: "Search page size.",
|
||||||
})
|
})
|
||||||
|
|
||||||
ldapSimpleAuthCLIFlags = append(commonLdapCLIFlags,
|
ldapSimpleAuthCLIFlags = append(commonLdapCLIFlags,
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "user-dn",
|
Name: "user-dn",
|
||||||
Usage: "The user’s DN.",
|
Usage: "The user’s DN.",
|
||||||
})
|
})
|
||||||
|
|
||||||
cmdAuthAddLdapBindDn = cli.Command{
|
cmdAuthAddLdapBindDn = &cli.Command{
|
||||||
Name: "add-ldap",
|
Name: "add-ldap",
|
||||||
Usage: "Add new LDAP (via Bind DN) authentication source",
|
Usage: "Add new LDAP (via Bind DN) authentication source",
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
|
@ -144,7 +144,7 @@ var (
|
||||||
Flags: ldapBindDnCLIFlags,
|
Flags: ldapBindDnCLIFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdAuthUpdateLdapBindDn = cli.Command{
|
cmdAuthUpdateLdapBindDn = &cli.Command{
|
||||||
Name: "update-ldap",
|
Name: "update-ldap",
|
||||||
Usage: "Update existing LDAP (via Bind DN) authentication source",
|
Usage: "Update existing LDAP (via Bind DN) authentication source",
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
|
@ -153,7 +153,7 @@ var (
|
||||||
Flags: append([]cli.Flag{idFlag}, ldapBindDnCLIFlags...),
|
Flags: append([]cli.Flag{idFlag}, ldapBindDnCLIFlags...),
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdAuthAddLdapSimpleAuth = cli.Command{
|
cmdAuthAddLdapSimpleAuth = &cli.Command{
|
||||||
Name: "add-ldap-simple",
|
Name: "add-ldap-simple",
|
||||||
Usage: "Add new LDAP (simple auth) authentication source",
|
Usage: "Add new LDAP (simple auth) authentication source",
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
|
@ -162,7 +162,7 @@ var (
|
||||||
Flags: ldapSimpleAuthCLIFlags,
|
Flags: ldapSimpleAuthCLIFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
cmdAuthUpdateLdapSimpleAuth = cli.Command{
|
cmdAuthUpdateLdapSimpleAuth = &cli.Command{
|
||||||
Name: "update-ldap-simple",
|
Name: "update-ldap-simple",
|
||||||
Usage: "Update existing LDAP (simple auth) authentication source",
|
Usage: "Update existing LDAP (simple auth) authentication source",
|
||||||
Action: func(c *cli.Context) error {
|
Action: func(c *cli.Context) error {
|
||||||
|
|
|
@ -11,7 +11,7 @@ import (
|
||||||
"code.gitea.io/gitea/services/auth/source/ldap"
|
"code.gitea.io/gitea/services/auth/source/ldap"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestAddLdapBindDn(t *testing.T) {
|
func TestAddLdapBindDn(t *testing.T) {
|
||||||
|
|
|
@ -4,13 +4,13 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var subcmdUser = cli.Command{
|
var subcmdUser = &cli.Command{
|
||||||
Name: "user",
|
Name: "user",
|
||||||
Usage: "Modify users",
|
Usage: "Modify users",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
microcmdUserCreate,
|
microcmdUserCreate,
|
||||||
microcmdUserList,
|
microcmdUserList,
|
||||||
microcmdUserChangePassword,
|
microcmdUserChangePassword,
|
||||||
|
|
|
@ -12,21 +12,23 @@ import (
|
||||||
pwd "code.gitea.io/gitea/modules/auth/password"
|
pwd "code.gitea.io/gitea/modules/auth/password"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var microcmdUserChangePassword = cli.Command{
|
var microcmdUserChangePassword = &cli.Command{
|
||||||
Name: "change-password",
|
Name: "change-password",
|
||||||
Usage: "Change a user's password",
|
Usage: "Change a user's password",
|
||||||
Action: runChangePassword,
|
Action: runChangePassword,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "username,u",
|
Name: "username",
|
||||||
|
Aliases: []string{"u"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The user to change password for",
|
Usage: "The user to change password for",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "password,p",
|
Name: "password",
|
||||||
|
Aliases: []string{"p"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "New password to set for user",
|
Usage: "New password to set for user",
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,52 +14,52 @@ import (
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var microcmdUserCreate = cli.Command{
|
var microcmdUserCreate = &cli.Command{
|
||||||
Name: "create",
|
Name: "create",
|
||||||
Usage: "Create a new user in database",
|
Usage: "Create a new user in database",
|
||||||
Action: runCreateUser,
|
Action: runCreateUser,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Usage: "Username. DEPRECATED: use username instead",
|
Usage: "Username. DEPRECATED: use username instead",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "username",
|
Name: "username",
|
||||||
Usage: "Username",
|
Usage: "Username",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "password",
|
Name: "password",
|
||||||
Usage: "User password",
|
Usage: "User password",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "email",
|
Name: "email",
|
||||||
Usage: "User email address",
|
Usage: "User email address",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "admin",
|
Name: "admin",
|
||||||
Usage: "User is an admin",
|
Usage: "User is an admin",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "random-password",
|
Name: "random-password",
|
||||||
Usage: "Generate a random password for the user",
|
Usage: "Generate a random password for the user",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "must-change-password",
|
Name: "must-change-password",
|
||||||
Usage: "Set this option to false to prevent forcing the user to change their password after initial login, (Default: true)",
|
Usage: "Set this option to false to prevent forcing the user to change their password after initial login, (Default: true)",
|
||||||
},
|
},
|
||||||
cli.IntFlag{
|
&cli.IntFlag{
|
||||||
Name: "random-password-length",
|
Name: "random-password-length",
|
||||||
Usage: "Length of the random password to be generated",
|
Usage: "Length of the random password to be generated",
|
||||||
Value: 12,
|
Value: 12,
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "access-token",
|
Name: "access-token",
|
||||||
Usage: "Generate access token for the user",
|
Usage: "Generate access token for the user",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "restricted",
|
Name: "restricted",
|
||||||
Usage: "Make a restricted user account",
|
Usage: "Make a restricted user account",
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,26 +11,28 @@ import (
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
user_service "code.gitea.io/gitea/services/user"
|
user_service "code.gitea.io/gitea/services/user"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var microcmdUserDelete = cli.Command{
|
var microcmdUserDelete = &cli.Command{
|
||||||
Name: "delete",
|
Name: "delete",
|
||||||
Usage: "Delete specific user by id, name or email",
|
Usage: "Delete specific user by id, name or email",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.Int64Flag{
|
&cli.Int64Flag{
|
||||||
Name: "id",
|
Name: "id",
|
||||||
Usage: "ID of user of the user to delete",
|
Usage: "ID of user of the user to delete",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "username,u",
|
Name: "username",
|
||||||
|
Aliases: []string{"u"},
|
||||||
Usage: "Username of the user to delete",
|
Usage: "Username of the user to delete",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "email,e",
|
Name: "email",
|
||||||
|
Aliases: []string{"e"},
|
||||||
Usage: "Email of the user to delete",
|
Usage: "Email of the user to delete",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "purge",
|
Name: "purge",
|
||||||
Usage: "Purge user, all their repositories, organizations and comments",
|
Usage: "Purge user, all their repositories, organizations and comments",
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,27 +9,29 @@ import (
|
||||||
auth_model "code.gitea.io/gitea/models/auth"
|
auth_model "code.gitea.io/gitea/models/auth"
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var microcmdUserGenerateAccessToken = cli.Command{
|
var microcmdUserGenerateAccessToken = &cli.Command{
|
||||||
Name: "generate-access-token",
|
Name: "generate-access-token",
|
||||||
Usage: "Generate an access token for a specific user",
|
Usage: "Generate an access token for a specific user",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "username,u",
|
Name: "username",
|
||||||
|
Aliases: []string{"u"},
|
||||||
Usage: "Username",
|
Usage: "Username",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "token-name,t",
|
Name: "token-name",
|
||||||
|
Aliases: []string{"t"},
|
||||||
Usage: "Token name",
|
Usage: "Token name",
|
||||||
Value: "gitea-admin",
|
Value: "gitea-admin",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "raw",
|
Name: "raw",
|
||||||
Usage: "Display only the token value",
|
Usage: "Display only the token value",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "scopes",
|
Name: "scopes",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Comma separated list of scopes to apply to access token",
|
Usage: "Comma separated list of scopes to apply to access token",
|
||||||
|
|
|
@ -10,15 +10,15 @@ import (
|
||||||
|
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var microcmdUserList = cli.Command{
|
var microcmdUserList = &cli.Command{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "List users",
|
Usage: "List users",
|
||||||
Action: runListUsers,
|
Action: runListUsers,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "admin",
|
Name: "admin",
|
||||||
Usage: "List only admin users",
|
Usage: "List only admin users",
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,23 +9,25 @@ import (
|
||||||
|
|
||||||
user_model "code.gitea.io/gitea/models/user"
|
user_model "code.gitea.io/gitea/models/user"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var microcmdUserMustChangePassword = cli.Command{
|
var microcmdUserMustChangePassword = &cli.Command{
|
||||||
Name: "must-change-password",
|
Name: "must-change-password",
|
||||||
Usage: "Set the must change password flag for the provided users or all users",
|
Usage: "Set the must change password flag for the provided users or all users",
|
||||||
Action: runMustChangePassword,
|
Action: runMustChangePassword,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "all,A",
|
Name: "all",
|
||||||
|
Aliases: []string{"A"},
|
||||||
Usage: "All users must change password, except those explicitly excluded with --exclude",
|
Usage: "All users must change password, except those explicitly excluded with --exclude",
|
||||||
},
|
},
|
||||||
cli.StringSliceFlag{
|
&cli.StringSliceFlag{
|
||||||
Name: "exclude,e",
|
Name: "exclude",
|
||||||
|
Aliases: []string{"e"},
|
||||||
Usage: "Do not change the must-change-password flag for these users",
|
Usage: "Do not change the must-change-password flag for these users",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "unset",
|
Name: "unset",
|
||||||
Usage: "Instead of setting the must-change-password flag, unset it",
|
Usage: "Instead of setting the must-change-password flag, unset it",
|
||||||
},
|
},
|
||||||
|
@ -48,7 +50,7 @@ func runMustChangePassword(c *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
n, err := user_model.SetMustChangePassword(ctx, all, mustChangePassword, c.Args(), exclude)
|
n, err := user_model.SetMustChangePassword(ctx, all, mustChangePassword, c.Args().Slice(), exclude)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
16
cmd/cert.go
16
cmd/cert.go
|
@ -20,43 +20,43 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdCert represents the available cert sub-command.
|
// CmdCert represents the available cert sub-command.
|
||||||
var CmdCert = cli.Command{
|
var CmdCert = &cli.Command{
|
||||||
Name: "cert",
|
Name: "cert",
|
||||||
Usage: "Generate self-signed certificate",
|
Usage: "Generate self-signed certificate",
|
||||||
Description: `Generate a self-signed X.509 certificate for a TLS server.
|
Description: `Generate a self-signed X.509 certificate for a TLS server.
|
||||||
Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
|
Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`,
|
||||||
Action: runCert,
|
Action: runCert,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "host",
|
Name: "host",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Comma-separated hostnames and IPs to generate a certificate for",
|
Usage: "Comma-separated hostnames and IPs to generate a certificate for",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "ecdsa-curve",
|
Name: "ecdsa-curve",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521",
|
Usage: "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521",
|
||||||
},
|
},
|
||||||
cli.IntFlag{
|
&cli.IntFlag{
|
||||||
Name: "rsa-bits",
|
Name: "rsa-bits",
|
||||||
Value: 2048,
|
Value: 2048,
|
||||||
Usage: "Size of RSA key to generate. Ignored if --ecdsa-curve is set",
|
Usage: "Size of RSA key to generate. Ignored if --ecdsa-curve is set",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "start-date",
|
Name: "start-date",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Creation date formatted as Jan 1 15:04:05 2011",
|
Usage: "Creation date formatted as Jan 1 15:04:05 2011",
|
||||||
},
|
},
|
||||||
cli.DurationFlag{
|
&cli.DurationFlag{
|
||||||
Name: "duration",
|
Name: "duration",
|
||||||
Value: 365 * 24 * time.Hour,
|
Value: 365 * 24 * time.Hour,
|
||||||
Usage: "Duration that certificate is valid for",
|
Usage: "Duration that certificate is valid for",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "ca",
|
Name: "ca",
|
||||||
Usage: "whether this cert should be its own Certificate Authority",
|
Usage: "whether this cert should be its own Certificate Authority",
|
||||||
},
|
},
|
||||||
|
|
15
cmd/cmd.go
15
cmd/cmd.go
|
@ -20,7 +20,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// argsSet checks that all the required arguments are set. args is a list of
|
// argsSet checks that all the required arguments are set. args is a list of
|
||||||
|
@ -109,15 +109,24 @@ func setupConsoleLogger(level log.Level, colorize bool, out io.Writer) {
|
||||||
log.GetManager().GetLogger(log.DEFAULT).ReplaceAllWriters(writer)
|
log.GetManager().GetLogger(log.DEFAULT).ReplaceAllWriters(writer)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func globalBool(c *cli.Context, name string) bool {
|
||||||
|
for _, ctx := range c.Lineage() {
|
||||||
|
if ctx.Bool(name) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// PrepareConsoleLoggerLevel by default, use INFO level for console logger, but some sub-commands (for git/ssh protocol) shouldn't output any log to stdout.
|
// 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.
|
// 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 {
|
func PrepareConsoleLoggerLevel(defaultLevel log.Level) func(*cli.Context) error {
|
||||||
return func(c *cli.Context) error {
|
return func(c *cli.Context) error {
|
||||||
level := defaultLevel
|
level := defaultLevel
|
||||||
if c.Bool("quiet") || c.GlobalBoolT("quiet") {
|
if globalBool(c, "quiet") {
|
||||||
level = log.FATAL
|
level = log.FATAL
|
||||||
}
|
}
|
||||||
if c.Bool("debug") || c.GlobalBool("debug") || c.Bool("verbose") || c.GlobalBool("verbose") {
|
if globalBool(c, "debug") || globalBool(c, "verbose") {
|
||||||
level = log.TRACE
|
level = log.TRACE
|
||||||
}
|
}
|
||||||
log.SetConsoleLogger(log.DEFAULT, "console-default", level)
|
log.SetConsoleLogger(log.DEFAULT, "console-default", level)
|
||||||
|
|
|
@ -10,11 +10,11 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdConvert represents the available convert sub-command.
|
// CmdConvert represents the available convert sub-command.
|
||||||
var CmdConvert = cli.Command{
|
var CmdConvert = &cli.Command{
|
||||||
Name: "convert",
|
Name: "convert",
|
||||||
Usage: "Convert the database",
|
Usage: "Convert the database",
|
||||||
Description: "A command to convert an existing MySQL database from utf8 to utf8mb4 or MSSQL database from varchar to nvarchar",
|
Description: "A command to convert an existing MySQL database from utf8 to utf8mb4 or MSSQL database from varchar to nvarchar",
|
||||||
|
|
|
@ -8,11 +8,11 @@ import (
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdDocs represents the available docs sub-command.
|
// CmdDocs represents the available docs sub-command.
|
||||||
var CmdDocs = cli.Command{
|
var CmdDocs = &cli.Command{
|
||||||
Name: "docs",
|
Name: "docs",
|
||||||
Usage: "Output CLI documentation",
|
Usage: "Output CLI documentation",
|
||||||
Description: "A command to output Gitea's CLI documentation, optionally to a file.",
|
Description: "A command to output Gitea's CLI documentation, optionally to a file.",
|
||||||
|
@ -23,7 +23,8 @@ var CmdDocs = cli.Command{
|
||||||
Usage: "Output man pages instead",
|
Usage: "Output man pages instead",
|
||||||
},
|
},
|
||||||
&cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "output, o",
|
Name: "output",
|
||||||
|
Aliases: []string{"o"},
|
||||||
Usage: "Path to output to instead of stdout (will overwrite if exists)",
|
Usage: "Path to output to instead of stdout (will overwrite if exists)",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,57 +18,58 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
"xorm.io/xorm"
|
"xorm.io/xorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdDoctor represents the available doctor sub-command.
|
// CmdDoctor represents the available doctor sub-command.
|
||||||
var CmdDoctor = cli.Command{
|
var CmdDoctor = &cli.Command{
|
||||||
Name: "doctor",
|
Name: "doctor",
|
||||||
Usage: "Diagnose and optionally fix problems",
|
Usage: "Diagnose and optionally fix problems",
|
||||||
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
|
Description: "A command to diagnose problems with the current Gitea instance according to the given configuration. Some problems can optionally be fixed by modifying the database or data storage.",
|
||||||
Action: runDoctor,
|
Action: runDoctor,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "List the available checks",
|
Usage: "List the available checks",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "default",
|
Name: "default",
|
||||||
Usage: "Run the default checks (if neither --run or --all is set, this is the default behaviour)",
|
Usage: "Run the default checks (if neither --run or --all is set, this is the default behaviour)",
|
||||||
},
|
},
|
||||||
cli.StringSliceFlag{
|
&cli.StringSliceFlag{
|
||||||
Name: "run",
|
Name: "run",
|
||||||
Usage: "Run the provided checks - (if --default is set, the default checks will also run)",
|
Usage: "Run the provided checks - (if --default is set, the default checks will also run)",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "all",
|
Name: "all",
|
||||||
Usage: "Run all the available checks",
|
Usage: "Run all the available checks",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "fix",
|
Name: "fix",
|
||||||
Usage: "Automatically fix what we can",
|
Usage: "Automatically fix what we can",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "log-file",
|
Name: "log-file",
|
||||||
Usage: `Name of the log file (default: "doctor.log"). Set to "-" to output to stdout, set to "" to disable`,
|
Usage: `Name of the log file (default: "doctor.log"). Set to "-" to output to stdout, set to "" to disable`,
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "color, H",
|
Name: "color",
|
||||||
|
Aliases: []string{"H"},
|
||||||
Usage: "Use color for outputted information",
|
Usage: "Use color for outputted information",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
cmdRecreateTable,
|
cmdRecreateTable,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
var cmdRecreateTable = cli.Command{
|
var cmdRecreateTable = &cli.Command{
|
||||||
Name: "recreate-table",
|
Name: "recreate-table",
|
||||||
Usage: "Recreate tables from XORM definitions and copy the data.",
|
Usage: "Recreate tables from XORM definitions and copy the data.",
|
||||||
ArgsUsage: "[TABLE]... : (TABLEs to recreate - leave blank for all)",
|
ArgsUsage: "[TABLE]... : (TABLEs to recreate - leave blank for all)",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
Usage: "Print SQL commands sent",
|
Usage: "Print SQL commands sent",
|
||||||
},
|
},
|
||||||
|
|
51
cmd/dump.go
51
cmd/dump.go
|
@ -22,7 +22,7 @@ import (
|
||||||
|
|
||||||
"gitea.com/go-chi/session"
|
"gitea.com/go-chi/session"
|
||||||
"github.com/mholt/archiver/v3"
|
"github.com/mholt/archiver/v3"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func addReader(w archiver.Writer, r io.ReadCloser, info os.FileInfo, customName string, verbose bool) error {
|
func addReader(w archiver.Writer, r io.ReadCloser, info os.FileInfo, customName string, verbose bool) error {
|
||||||
|
@ -96,64 +96,71 @@ var outputTypeEnum = &outputType{
|
||||||
}
|
}
|
||||||
|
|
||||||
// CmdDump represents the available dump sub-command.
|
// CmdDump represents the available dump sub-command.
|
||||||
var CmdDump = cli.Command{
|
var CmdDump = &cli.Command{
|
||||||
Name: "dump",
|
Name: "dump",
|
||||||
Usage: "Dump Gitea files and database",
|
Usage: "Dump Gitea files and database",
|
||||||
Description: `Dump compresses all related files and database into zip file.
|
Description: `Dump compresses all related files and database into zip file.
|
||||||
It can be used for backup and capture Gitea server image to send to maintainer`,
|
It can be used for backup and capture Gitea server image to send to maintainer`,
|
||||||
Action: runDump,
|
Action: runDump,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "file, f",
|
Name: "file",
|
||||||
|
Aliases: []string{"f"},
|
||||||
Value: fmt.Sprintf("gitea-dump-%d.zip", time.Now().Unix()),
|
Value: fmt.Sprintf("gitea-dump-%d.zip", time.Now().Unix()),
|
||||||
Usage: "Name of the dump file which will be created. Supply '-' for stdout. See type for available types.",
|
Usage: "Name of the dump file which will be created. Supply '-' for stdout. See type for available types.",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "verbose, V",
|
Name: "verbose",
|
||||||
|
Aliases: []string{"V"},
|
||||||
Usage: "Show process details",
|
Usage: "Show process details",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "quiet, q",
|
Name: "quiet",
|
||||||
|
Aliases: []string{"q"},
|
||||||
Usage: "Only display warnings and errors",
|
Usage: "Only display warnings and errors",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "tempdir, t",
|
Name: "tempdir",
|
||||||
|
Aliases: []string{"t"},
|
||||||
Value: os.TempDir(),
|
Value: os.TempDir(),
|
||||||
Usage: "Temporary dir path",
|
Usage: "Temporary dir path",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "database, d",
|
Name: "database",
|
||||||
|
Aliases: []string{"d"},
|
||||||
Usage: "Specify the database SQL syntax",
|
Usage: "Specify the database SQL syntax",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-repository, R",
|
Name: "skip-repository",
|
||||||
|
Aliases: []string{"R"},
|
||||||
Usage: "Skip the repository dumping",
|
Usage: "Skip the repository dumping",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-log, L",
|
Name: "skip-log",
|
||||||
|
Aliases: []string{"L"},
|
||||||
Usage: "Skip the log dumping",
|
Usage: "Skip the log dumping",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-custom-dir",
|
Name: "skip-custom-dir",
|
||||||
Usage: "Skip custom directory",
|
Usage: "Skip custom directory",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-lfs-data",
|
Name: "skip-lfs-data",
|
||||||
Usage: "Skip LFS data",
|
Usage: "Skip LFS data",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-attachment-data",
|
Name: "skip-attachment-data",
|
||||||
Usage: "Skip attachment data",
|
Usage: "Skip attachment data",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-package-data",
|
Name: "skip-package-data",
|
||||||
Usage: "Skip package data",
|
Usage: "Skip package data",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "skip-index",
|
Name: "skip-index",
|
||||||
Usage: "Skip bleve index data",
|
Usage: "Skip bleve index data",
|
||||||
},
|
},
|
||||||
cli.GenericFlag{
|
&cli.GenericFlag{
|
||||||
Name: "type",
|
Name: "type",
|
||||||
Value: outputTypeEnum,
|
Value: outputTypeEnum,
|
||||||
Usage: fmt.Sprintf("Dump output format: %s", outputTypeEnum.Join()),
|
Usage: fmt.Sprintf("Dump output format: %s", outputTypeEnum.Join()),
|
||||||
|
|
|
@ -19,57 +19,58 @@ import (
|
||||||
"code.gitea.io/gitea/services/convert"
|
"code.gitea.io/gitea/services/convert"
|
||||||
"code.gitea.io/gitea/services/migrations"
|
"code.gitea.io/gitea/services/migrations"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdDumpRepository represents the available dump repository sub-command.
|
// CmdDumpRepository represents the available dump repository sub-command.
|
||||||
var CmdDumpRepository = cli.Command{
|
var CmdDumpRepository = &cli.Command{
|
||||||
Name: "dump-repo",
|
Name: "dump-repo",
|
||||||
Usage: "Dump the repository from git/github/gitea/gitlab",
|
Usage: "Dump the repository from git/github/gitea/gitlab",
|
||||||
Description: "This is a command for dumping the repository data.",
|
Description: "This is a command for dumping the repository data.",
|
||||||
Action: runDumpRepository,
|
Action: runDumpRepository,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "git_service",
|
Name: "git_service",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Git service, git, github, gitea, gitlab. If clone_addr could be recognized, this could be ignored.",
|
Usage: "Git service, git, github, gitea, gitlab. If clone_addr could be recognized, this could be ignored.",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "repo_dir, r",
|
Name: "repo_dir",
|
||||||
|
Aliases: []string{"r"},
|
||||||
Value: "./data",
|
Value: "./data",
|
||||||
Usage: "Repository dir path to store the data",
|
Usage: "Repository dir path to store the data",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "clone_addr",
|
Name: "clone_addr",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The URL will be clone, currently could be a git/github/gitea/gitlab http/https URL",
|
Usage: "The URL will be clone, currently could be a git/github/gitea/gitlab http/https URL",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "auth_username",
|
Name: "auth_username",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The username to visit the clone_addr",
|
Usage: "The username to visit the clone_addr",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "auth_password",
|
Name: "auth_password",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The password to visit the clone_addr",
|
Usage: "The password to visit the clone_addr",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "auth_token",
|
Name: "auth_token",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The personal token to visit the clone_addr",
|
Usage: "The personal token to visit the clone_addr",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "owner_name",
|
Name: "owner_name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The data will be stored on a directory with owner name if not empty",
|
Usage: "The data will be stored on a directory with owner name if not empty",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "repo_name",
|
Name: "repo_name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "The data will be stored on a directory with repository name if not empty",
|
Usage: "The data will be stored on a directory with repository name if not empty",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "units",
|
Name: "units",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: `Which items will be migrated, one or more units should be separated as comma.
|
Usage: `Which items will be migrated, one or more units should be separated as comma.
|
||||||
|
|
|
@ -19,69 +19,73 @@ import (
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/gobwas/glob"
|
"github.com/gobwas/glob"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 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",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
subcmdList,
|
subcmdList,
|
||||||
subcmdView,
|
subcmdView,
|
||||||
subcmdExtract,
|
subcmdExtract,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmdList = cli.Command{
|
subcmdList = &cli.Command{
|
||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "List files matching the given pattern",
|
Usage: "List files matching the given pattern",
|
||||||
Action: runList,
|
Action: runList,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "include-vendored,vendor",
|
Name: "include-vendored",
|
||||||
|
Aliases: []string{"vendor"},
|
||||||
Usage: "Include files under public/vendor as well",
|
Usage: "Include files under public/vendor as well",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmdView = cli.Command{
|
subcmdView = &cli.Command{
|
||||||
Name: "view",
|
Name: "view",
|
||||||
Usage: "View a file matching the given pattern",
|
Usage: "View a file matching the given pattern",
|
||||||
Action: runView,
|
Action: runView,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "include-vendored,vendor",
|
Name: "include-vendored",
|
||||||
|
Aliases: []string{"vendor"},
|
||||||
Usage: "Include files under public/vendor as well",
|
Usage: "Include files under public/vendor as well",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmdExtract = cli.Command{
|
subcmdExtract = &cli.Command{
|
||||||
Name: "extract",
|
Name: "extract",
|
||||||
Usage: "Extract resources",
|
Usage: "Extract resources",
|
||||||
Action: runExtract,
|
Action: runExtract,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "include-vendored,vendor",
|
Name: "include-vendored",
|
||||||
|
Aliases: []string{"vendor"},
|
||||||
Usage: "Include files under public/vendor as well",
|
Usage: "Include files under public/vendor as well",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "overwrite",
|
Name: "overwrite",
|
||||||
Usage: "Overwrite files if they already exist",
|
Usage: "Overwrite files if they already exist",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "rename",
|
Name: "rename",
|
||||||
Usage: "Rename files as {name}.bak if they already exist (overwrites previous .bak)",
|
Usage: "Rename files as {name}.bak if they already exist (overwrites previous .bak)",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "custom",
|
Name: "custom",
|
||||||
Usage: "Extract to the 'custom' directory as per app.ini",
|
Usage: "Extract to the 'custom' directory as per app.ini",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "destination,dest-dir",
|
Name: "destination",
|
||||||
|
Aliases: []string{"dest-dir"},
|
||||||
Usage: "Extract to the specified directory",
|
Usage: "Extract to the specified directory",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -99,7 +103,7 @@ type assetFile struct {
|
||||||
func initEmbeddedExtractor(c *cli.Context) error {
|
func initEmbeddedExtractor(c *cli.Context) error {
|
||||||
setupConsoleLogger(log.ERROR, log.CanColorStderr, os.Stderr)
|
setupConsoleLogger(log.ERROR, log.CanColorStderr, os.Stderr)
|
||||||
|
|
||||||
patterns, err := compileCollectPatterns(c.Args())
|
patterns, err := compileCollectPatterns(c.Args().Slice())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -175,7 +179,7 @@ func runExtractDo(c *cli.Context) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.Args()) == 0 {
|
if c.NArg() == 0 {
|
||||||
return fmt.Errorf("a list of pattern of files to extract is mandatory (e.g. '**' for all)")
|
return fmt.Errorf("a list of pattern of files to extract is mandatory (e.g. '**' for all)")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,43 +11,43 @@ import (
|
||||||
"code.gitea.io/gitea/modules/generate"
|
"code.gitea.io/gitea/modules/generate"
|
||||||
|
|
||||||
"github.com/mattn/go-isatty"
|
"github.com/mattn/go-isatty"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// CmdGenerate represents the available generate sub-command.
|
// CmdGenerate represents the available generate sub-command.
|
||||||
CmdGenerate = cli.Command{
|
CmdGenerate = &cli.Command{
|
||||||
Name: "generate",
|
Name: "generate",
|
||||||
Usage: "Command line interface for running generators",
|
Usage: "Command line interface for running generators",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
subcmdSecret,
|
subcmdSecret,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmdSecret = cli.Command{
|
subcmdSecret = &cli.Command{
|
||||||
Name: "secret",
|
Name: "secret",
|
||||||
Usage: "Generate a secret token",
|
Usage: "Generate a secret token",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
microcmdGenerateInternalToken,
|
microcmdGenerateInternalToken,
|
||||||
microcmdGenerateLfsJwtSecret,
|
microcmdGenerateLfsJwtSecret,
|
||||||
microcmdGenerateSecretKey,
|
microcmdGenerateSecretKey,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
microcmdGenerateInternalToken = cli.Command{
|
microcmdGenerateInternalToken = &cli.Command{
|
||||||
Name: "INTERNAL_TOKEN",
|
Name: "INTERNAL_TOKEN",
|
||||||
Usage: "Generate a new INTERNAL_TOKEN",
|
Usage: "Generate a new INTERNAL_TOKEN",
|
||||||
Action: runGenerateInternalToken,
|
Action: runGenerateInternalToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
microcmdGenerateLfsJwtSecret = cli.Command{
|
microcmdGenerateLfsJwtSecret = &cli.Command{
|
||||||
Name: "JWT_SECRET",
|
Name: "JWT_SECRET",
|
||||||
Aliases: []string{"LFS_JWT_SECRET"},
|
Aliases: []string{"LFS_JWT_SECRET"},
|
||||||
Usage: "Generate a new JWT_SECRET",
|
Usage: "Generate a new JWT_SECRET",
|
||||||
Action: runGenerateLfsJwtSecret,
|
Action: runGenerateLfsJwtSecret,
|
||||||
}
|
}
|
||||||
|
|
||||||
microcmdGenerateSecretKey = cli.Command{
|
microcmdGenerateSecretKey = &cli.Command{
|
||||||
Name: "SECRET_KEY",
|
Name: "SECRET_KEY",
|
||||||
Usage: "Generate a new SECRET_KEY",
|
Usage: "Generate a new SECRET_KEY",
|
||||||
Action: runGenerateSecretKey,
|
Action: runGenerateSecretKey,
|
||||||
|
|
22
cmd/hook.go
22
cmd/hook.go
|
@ -20,7 +20,7 @@ import (
|
||||||
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"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -29,12 +29,12 @@ const (
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// CmdHook represents the available hooks sub-command.
|
// CmdHook represents the available hooks sub-command.
|
||||||
CmdHook = cli.Command{
|
CmdHook = &cli.Command{
|
||||||
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),
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
subcmdHookPreReceive,
|
subcmdHookPreReceive,
|
||||||
subcmdHookUpdate,
|
subcmdHookUpdate,
|
||||||
subcmdHookPostReceive,
|
subcmdHookPostReceive,
|
||||||
|
@ -42,47 +42,47 @@ var (
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmdHookPreReceive = cli.Command{
|
subcmdHookPreReceive = &cli.Command{
|
||||||
Name: "pre-receive",
|
Name: "pre-receive",
|
||||||
Usage: "Delegate pre-receive Git hook",
|
Usage: "Delegate pre-receive Git hook",
|
||||||
Description: "This command should only be called by Git",
|
Description: "This command should only be called by Git",
|
||||||
Action: runHookPreReceive,
|
Action: runHookPreReceive,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
subcmdHookUpdate = cli.Command{
|
subcmdHookUpdate = &cli.Command{
|
||||||
Name: "update",
|
Name: "update",
|
||||||
Usage: "Delegate update Git hook",
|
Usage: "Delegate update Git hook",
|
||||||
Description: "This command should only be called by Git",
|
Description: "This command should only be called by Git",
|
||||||
Action: runHookUpdate,
|
Action: runHookUpdate,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
subcmdHookPostReceive = cli.Command{
|
subcmdHookPostReceive = &cli.Command{
|
||||||
Name: "post-receive",
|
Name: "post-receive",
|
||||||
Usage: "Delegate post-receive Git hook",
|
Usage: "Delegate post-receive Git hook",
|
||||||
Description: "This command should only be called by Git",
|
Description: "This command should only be called by Git",
|
||||||
Action: runHookPostReceive,
|
Action: runHookPostReceive,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
// Note: new hook since git 2.29
|
// Note: new hook since git 2.29
|
||||||
subcmdHookProcReceive = cli.Command{
|
subcmdHookProcReceive = &cli.Command{
|
||||||
Name: "proc-receive",
|
Name: "proc-receive",
|
||||||
Usage: "Delegate proc-receive Git hook",
|
Usage: "Delegate proc-receive Git hook",
|
||||||
Description: "This command should only be called by Git",
|
Description: "This command should only be called by Git",
|
||||||
Action: runHookProcReceive,
|
Action: runHookProcReceive,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
26
cmd/keys.go
26
cmd/keys.go
|
@ -11,33 +11,37 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"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/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdKeys represents the available keys sub-command
|
// CmdKeys represents the available keys sub-command
|
||||||
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),
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Action: runKeys,
|
Action: runKeys,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "expected, e",
|
Name: "expected",
|
||||||
|
Aliases: []string{"e"},
|
||||||
Value: "git",
|
Value: "git",
|
||||||
Usage: "Expected user for whom provide key commands",
|
Usage: "Expected user for whom provide key commands",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "username, u",
|
Name: "username",
|
||||||
|
Aliases: []string{"u"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Username trying to log in by SSH",
|
Usage: "Username trying to log in by SSH",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "type, t",
|
Name: "type",
|
||||||
|
Aliases: []string{"t"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Type of the SSH key provided to the SSH Server (requires content to be provided too)",
|
Usage: "Type of the SSH key provided to the SSH Server (requires content to be provided too)",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "content, k",
|
Name: "content",
|
||||||
|
Aliases: []string{"k"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Base64 encoded content of the SSH key provided to the SSH Server (requires type to be provided too)",
|
Usage: "Base64 encoded content of the SSH key provided to the SSH Server (requires type to be provided too)",
|
||||||
},
|
},
|
||||||
|
@ -73,6 +77,6 @@ func runKeys(c *cli.Context) error {
|
||||||
if extra.Error != nil {
|
if extra.Error != nil {
|
||||||
return extra.Error
|
return extra.Error
|
||||||
}
|
}
|
||||||
fmt.Println(strings.TrimSpace(authorizedString))
|
_, _ = fmt.Fprintln(c.App.Writer, strings.TrimSpace(authorizedString))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func runSendMail(c *cli.Context) error {
|
func runSendMail(c *cli.Context) error {
|
||||||
|
|
|
@ -0,0 +1,196 @@
|
||||||
|
// Copyright 2023 The Gitea Authors. All rights reserved.
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
package cmd
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"reflect"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"code.gitea.io/gitea/modules/log"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
// cmdHelp is our own help subcommand with more information
|
||||||
|
func cmdHelp() *cli.Command {
|
||||||
|
c := &cli.Command{
|
||||||
|
Name: "help",
|
||||||
|
Aliases: []string{"h"},
|
||||||
|
Usage: "Shows a list of commands or help for one command",
|
||||||
|
ArgsUsage: "[command]",
|
||||||
|
Action: func(c *cli.Context) (err error) {
|
||||||
|
args := c.Args()
|
||||||
|
if args.Present() {
|
||||||
|
err = cli.ShowCommandHelp(c, args.First())
|
||||||
|
} else {
|
||||||
|
err = cli.ShowAppHelp(c)
|
||||||
|
}
|
||||||
|
_, _ = fmt.Fprintf(c.App.Writer, `
|
||||||
|
DEFAULT CONFIGURATION:
|
||||||
|
AppPath: %s
|
||||||
|
WorkPath: %s
|
||||||
|
CustomPath: %s
|
||||||
|
ConfigFile: %s
|
||||||
|
|
||||||
|
`, setting.AppPath, setting.AppWorkPath, setting.CustomPath, setting.CustomConf)
|
||||||
|
return err
|
||||||
|
},
|
||||||
|
}
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
var helpFlag = cli.HelpFlag
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// cli.HelpFlag = nil TODO: after https://github.com/urfave/cli/issues/1794 we can use this
|
||||||
|
}
|
||||||
|
|
||||||
|
func appGlobalFlags() []cli.Flag {
|
||||||
|
return []cli.Flag{
|
||||||
|
// make the builtin flags at the top
|
||||||
|
helpFlag,
|
||||||
|
cli.VersionFlag,
|
||||||
|
|
||||||
|
// 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.
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "custom-path",
|
||||||
|
Aliases: []string{"C"},
|
||||||
|
Usage: "Set custom path (defaults to '{WorkPath}/custom')",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "config",
|
||||||
|
Aliases: []string{"c"},
|
||||||
|
Value: setting.CustomConf,
|
||||||
|
Usage: "Set custom config file (defaults to '{WorkPath}/custom/conf/app.ini')",
|
||||||
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
|
Name: "work-path",
|
||||||
|
Aliases: []string{"w"},
|
||||||
|
Usage: "Set Gitea's working path (defaults to the Gitea's binary directory)",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func prepareSubcommandWithConfig(command *cli.Command, globalFlags []cli.Flag) {
|
||||||
|
command.Flags = append(append([]cli.Flag{}, globalFlags...), command.Flags...)
|
||||||
|
command.Action = prepareWorkPathAndCustomConf(command.Action)
|
||||||
|
command.HideHelp = true
|
||||||
|
if command.Name != "help" {
|
||||||
|
command.Subcommands = append(command.Subcommands, cmdHelp())
|
||||||
|
}
|
||||||
|
for i := range command.Subcommands {
|
||||||
|
prepareSubcommandWithConfig(command.Subcommands[i], globalFlags)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
|
func prepareWorkPathAndCustomConf(action cli.ActionFunc) func(ctx *cli.Context) error {
|
||||||
|
return func(ctx *cli.Context) error {
|
||||||
|
var args setting.ArgWorkPathAndCustomConf
|
||||||
|
ctxLineage := ctx.Lineage()
|
||||||
|
for i := len(ctxLineage) - 1; i >= 0; i-- {
|
||||||
|
curCtx := ctxLineage[i]
|
||||||
|
if curCtx.IsSet("work-path") && args.WorkPath == "" {
|
||||||
|
args.WorkPath = curCtx.String("work-path")
|
||||||
|
}
|
||||||
|
if curCtx.IsSet("custom-path") && args.CustomPath == "" {
|
||||||
|
args.CustomPath = curCtx.String("custom-path")
|
||||||
|
}
|
||||||
|
if curCtx.IsSet("config") && args.CustomConf == "" {
|
||||||
|
args.CustomConf = curCtx.String("config")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
setting.InitWorkPathAndCommonConfig(os.Getenv, args)
|
||||||
|
if ctx.Bool("help") || action == nil {
|
||||||
|
// the default behavior of "urfave/cli": "nil action" means "show help"
|
||||||
|
return cmdHelp().Action(ctx)
|
||||||
|
}
|
||||||
|
return action(ctx)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func reflectGet(v any, fieldName string) any {
|
||||||
|
e := reflect.ValueOf(v).Elem()
|
||||||
|
return e.FieldByName(fieldName).Interface()
|
||||||
|
}
|
||||||
|
|
||||||
|
// https://cli.urfave.org/migrate-v1-to-v2/#flag-aliases-are-done-differently
|
||||||
|
// Sadly v2 doesn't warn you if a comma is in the name. (https://github.com/urfave/cli/issues/1103)
|
||||||
|
func checkCommandFlags(c any) bool {
|
||||||
|
var cmds []*cli.Command
|
||||||
|
if app, ok := c.(*cli.App); ok {
|
||||||
|
cmds = app.Commands
|
||||||
|
} else {
|
||||||
|
cmds = c.(*cli.Command).Subcommands
|
||||||
|
}
|
||||||
|
ok := true
|
||||||
|
for _, cmd := range cmds {
|
||||||
|
for _, flag := range cmd.Flags {
|
||||||
|
flagName := reflectGet(flag, "Name").(string)
|
||||||
|
if strings.Contains(flagName, ",") {
|
||||||
|
ok = false
|
||||||
|
log.Error("cli.Flag can't have comma in its Name: %q, use Aliases instead", flagName)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !checkCommandFlags(cmd) {
|
||||||
|
ok = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ok
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMainApp() *cli.App {
|
||||||
|
app := cli.NewApp()
|
||||||
|
app.EnableBashCompletion = true
|
||||||
|
|
||||||
|
// these sub-commands need to use config file
|
||||||
|
subCmdWithConfig := []*cli.Command{
|
||||||
|
CmdWeb,
|
||||||
|
CmdServ,
|
||||||
|
CmdHook,
|
||||||
|
CmdDump,
|
||||||
|
CmdAdmin,
|
||||||
|
CmdMigrate,
|
||||||
|
CmdKeys,
|
||||||
|
CmdConvert,
|
||||||
|
CmdDoctor,
|
||||||
|
CmdManager,
|
||||||
|
CmdEmbedded,
|
||||||
|
CmdMigrateStorage,
|
||||||
|
CmdDumpRepository,
|
||||||
|
CmdRestoreRepository,
|
||||||
|
CmdActions,
|
||||||
|
cmdHelp(), // the "help" sub-command was used to show the more information for "work path" and "custom config"
|
||||||
|
}
|
||||||
|
|
||||||
|
// these sub-commands do not need the config file, and they do not depend on any path or environment variable.
|
||||||
|
subCmdStandalone := []*cli.Command{
|
||||||
|
CmdCert,
|
||||||
|
CmdGenerate,
|
||||||
|
CmdDocs,
|
||||||
|
}
|
||||||
|
|
||||||
|
app.DefaultCommand = CmdWeb.Name
|
||||||
|
|
||||||
|
globalFlags := appGlobalFlags()
|
||||||
|
app.Flags = append(app.Flags, globalFlags...)
|
||||||
|
app.HideHelp = true // use our own help action to show helps (with more information like default config)
|
||||||
|
app.Before = PrepareConsoleLoggerLevel(log.INFO)
|
||||||
|
for i := range subCmdWithConfig {
|
||||||
|
prepareSubcommandWithConfig(subCmdWithConfig[i], globalFlags)
|
||||||
|
}
|
||||||
|
app.Commands = append(app.Commands, subCmdWithConfig...)
|
||||||
|
app.Commands = append(app.Commands, subCmdStandalone...)
|
||||||
|
|
||||||
|
if !checkCommandFlags(app) {
|
||||||
|
panic("some flags are incorrect") // this is a runtime check to help developers
|
||||||
|
}
|
||||||
|
return app
|
||||||
|
}
|
115
cmd/main_test.go
115
cmd/main_test.go
|
@ -4,9 +4,17 @@
|
||||||
package cmd
|
package cmd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models/unittest"
|
"code.gitea.io/gitea/models/unittest"
|
||||||
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestMain(m *testing.M) {
|
func TestMain(m *testing.M) {
|
||||||
|
@ -14,3 +22,110 @@ func TestMain(m *testing.M) {
|
||||||
GiteaRootPath: "..",
|
GiteaRootPath: "..",
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func makePathOutput(workPath, customPath, customConf string) string {
|
||||||
|
return fmt.Sprintf("WorkPath=%s\nCustomPath=%s\nCustomConf=%s", workPath, customPath, customConf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func newTestApp() *cli.App {
|
||||||
|
app := NewMainApp()
|
||||||
|
testCmd := &cli.Command{
|
||||||
|
Name: "test-cmd",
|
||||||
|
Action: func(ctx *cli.Context) error {
|
||||||
|
_, _ = fmt.Fprint(app.Writer, makePathOutput(setting.AppWorkPath, setting.CustomPath, setting.CustomConf))
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
prepareSubcommandWithConfig(testCmd, appGlobalFlags())
|
||||||
|
app.Commands = append(app.Commands, testCmd)
|
||||||
|
app.DefaultCommand = testCmd.Name
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestCliCmd(t *testing.T) {
|
||||||
|
defaultWorkPath := filepath.Dir(setting.AppPath)
|
||||||
|
defaultCustomPath := filepath.Join(defaultWorkPath, "custom")
|
||||||
|
defaultCustomConf := filepath.Join(defaultCustomPath, "conf/app.ini")
|
||||||
|
|
||||||
|
cli.CommandHelpTemplate = "(command help template)"
|
||||||
|
cli.AppHelpTemplate = "(app help template)"
|
||||||
|
cli.SubcommandHelpTemplate = "(subcommand help template)"
|
||||||
|
|
||||||
|
cases := []struct {
|
||||||
|
env map[string]string
|
||||||
|
cmd string
|
||||||
|
exp string
|
||||||
|
}{
|
||||||
|
// main command help
|
||||||
|
{
|
||||||
|
cmd: "./gitea help",
|
||||||
|
exp: "DEFAULT CONFIGURATION:",
|
||||||
|
},
|
||||||
|
|
||||||
|
// parse paths
|
||||||
|
{
|
||||||
|
cmd: "./gitea test-cmd",
|
||||||
|
exp: makePathOutput(defaultWorkPath, defaultCustomPath, defaultCustomConf),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cmd: "./gitea -c /tmp/app.ini test-cmd",
|
||||||
|
exp: makePathOutput(defaultWorkPath, defaultCustomPath, "/tmp/app.ini"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
cmd: "./gitea test-cmd -c /tmp/app.ini",
|
||||||
|
exp: makePathOutput(defaultWorkPath, defaultCustomPath, "/tmp/app.ini"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
|
||||||
|
cmd: "./gitea test-cmd",
|
||||||
|
exp: makePathOutput("/tmp", "/tmp/custom", "/tmp/custom/conf/app.ini"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
|
||||||
|
cmd: "./gitea test-cmd --work-path /tmp/other",
|
||||||
|
exp: makePathOutput("/tmp/other", "/tmp/other/custom", "/tmp/other/custom/conf/app.ini"),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
env: map[string]string{"GITEA_WORK_DIR": "/tmp"},
|
||||||
|
cmd: "./gitea test-cmd --config /tmp/app-other.ini",
|
||||||
|
exp: makePathOutput("/tmp", "/tmp/custom", "/tmp/app-other.ini"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
app := newTestApp()
|
||||||
|
var envBackup []string
|
||||||
|
for _, s := range os.Environ() {
|
||||||
|
if strings.HasPrefix(s, "GITEA_") && strings.Contains(s, "=") {
|
||||||
|
envBackup = append(envBackup, s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
clearGiteaEnv := func() {
|
||||||
|
for _, s := range os.Environ() {
|
||||||
|
if strings.HasPrefix(s, "GITEA_") {
|
||||||
|
_ = os.Unsetenv(s)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
defer func() {
|
||||||
|
clearGiteaEnv()
|
||||||
|
for _, s := range envBackup {
|
||||||
|
k, v, _ := strings.Cut(s, "=")
|
||||||
|
_ = os.Setenv(k, v)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
clearGiteaEnv()
|
||||||
|
for k, v := range c.env {
|
||||||
|
_ = os.Setenv(k, v)
|
||||||
|
}
|
||||||
|
args := strings.Split(c.cmd, " ") // for test only, "split" is good enough
|
||||||
|
out := new(strings.Builder)
|
||||||
|
app.Writer = out
|
||||||
|
err := app.Run(args)
|
||||||
|
assert.NoError(t, err, c.cmd)
|
||||||
|
assert.NotEmpty(t, c.exp, c.cmd)
|
||||||
|
outStr := out.String()
|
||||||
|
assert.Contains(t, outStr, c.exp, c.cmd)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -9,16 +9,16 @@ import (
|
||||||
|
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
// CmdManager represents the manager command
|
// CmdManager represents the manager command
|
||||||
CmdManager = cli.Command{
|
CmdManager = &cli.Command{
|
||||||
Name: "manager",
|
Name: "manager",
|
||||||
Usage: "Manage the running gitea process",
|
Usage: "Manage the running gitea process",
|
||||||
Description: "This is a command for managing the running gitea process",
|
Description: "This is a command for managing the running gitea process",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
subcmdShutdown,
|
subcmdShutdown,
|
||||||
subcmdRestart,
|
subcmdRestart,
|
||||||
subcmdReloadTemplates,
|
subcmdReloadTemplates,
|
||||||
|
@ -27,80 +27,80 @@ var (
|
||||||
subCmdProcesses,
|
subCmdProcesses,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
subcmdShutdown = cli.Command{
|
subcmdShutdown = &cli.Command{
|
||||||
Name: "shutdown",
|
Name: "shutdown",
|
||||||
Usage: "Gracefully shutdown the running process",
|
Usage: "Gracefully shutdown the running process",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Action: runShutdown,
|
Action: runShutdown,
|
||||||
}
|
}
|
||||||
subcmdRestart = cli.Command{
|
subcmdRestart = &cli.Command{
|
||||||
Name: "restart",
|
Name: "restart",
|
||||||
Usage: "Gracefully restart the running process - (not implemented for windows servers)",
|
Usage: "Gracefully restart the running process - (not implemented for windows servers)",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Action: runRestart,
|
Action: runRestart,
|
||||||
}
|
}
|
||||||
subcmdReloadTemplates = cli.Command{
|
subcmdReloadTemplates = &cli.Command{
|
||||||
Name: "reload-templates",
|
Name: "reload-templates",
|
||||||
Usage: "Reload template files in the running process",
|
Usage: "Reload template files in the running process",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
Action: runReloadTemplates,
|
Action: runReloadTemplates,
|
||||||
}
|
}
|
||||||
subcmdFlushQueues = cli.Command{
|
subcmdFlushQueues = &cli.Command{
|
||||||
Name: "flush-queues",
|
Name: "flush-queues",
|
||||||
Usage: "Flush queues in the running process",
|
Usage: "Flush queues in the running process",
|
||||||
Action: runFlushQueues,
|
Action: runFlushQueues,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.DurationFlag{
|
&cli.DurationFlag{
|
||||||
Name: "timeout",
|
Name: "timeout",
|
||||||
Value: 60 * time.Second,
|
Value: 60 * time.Second,
|
||||||
Usage: "Timeout for the flushing process",
|
Usage: "Timeout for the flushing process",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "non-blocking",
|
Name: "non-blocking",
|
||||||
Usage: "Set to true to not wait for flush to complete before returning",
|
Usage: "Set to true to not wait for flush to complete before returning",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
subCmdProcesses = cli.Command{
|
subCmdProcesses = &cli.Command{
|
||||||
Name: "processes",
|
Name: "processes",
|
||||||
Usage: "Display running processes within the current process",
|
Usage: "Display running processes within the current process",
|
||||||
Action: runProcesses,
|
Action: runProcesses,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "flat",
|
Name: "flat",
|
||||||
Usage: "Show processes as flat table rather than as tree",
|
Usage: "Show processes as flat table rather than as tree",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "no-system",
|
Name: "no-system",
|
||||||
Usage: "Do not show system processes",
|
Usage: "Do not show system processes",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "stacktraces",
|
Name: "stacktraces",
|
||||||
Usage: "Show stacktraces",
|
Usage: "Show stacktraces",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "json",
|
Name: "json",
|
||||||
Usage: "Output as json",
|
Usage: "Output as json",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "cancel",
|
Name: "cancel",
|
||||||
Usage: "Process PID to cancel. (Only available for non-system processes.)",
|
Usage: "Process PID to cancel. (Only available for non-system processes.)",
|
||||||
},
|
},
|
||||||
|
|
|
@ -10,49 +10,61 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"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/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaultLoggingFlags = []cli.Flag{
|
defaultLoggingFlags = []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "logger",
|
Name: "logger",
|
||||||
Usage: `Logger name - will default to "default"`,
|
Usage: `Logger name - will default to "default"`,
|
||||||
}, cli.StringFlag{
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
Name: "writer",
|
Name: "writer",
|
||||||
Usage: "Name of the log writer - will default to mode",
|
Usage: "Name of the log writer - will default to mode",
|
||||||
}, cli.StringFlag{
|
},
|
||||||
|
&cli.StringFlag{
|
||||||
Name: "level",
|
Name: "level",
|
||||||
Usage: "Logging level for the new logger",
|
Usage: "Logging level for the new logger",
|
||||||
}, cli.StringFlag{
|
},
|
||||||
Name: "stacktrace-level, L",
|
&cli.StringFlag{
|
||||||
|
Name: "stacktrace-level",
|
||||||
|
Aliases: []string{"L"},
|
||||||
Usage: "Stacktrace logging level",
|
Usage: "Stacktrace logging level",
|
||||||
}, cli.StringFlag{
|
},
|
||||||
Name: "flags, F",
|
&cli.StringFlag{
|
||||||
|
Name: "flags",
|
||||||
|
Aliases: []string{"F"},
|
||||||
Usage: "Flags for the logger",
|
Usage: "Flags for the logger",
|
||||||
}, cli.StringFlag{
|
},
|
||||||
Name: "expression, e",
|
&cli.StringFlag{
|
||||||
|
Name: "expression",
|
||||||
|
Aliases: []string{"e"},
|
||||||
Usage: "Matching expression for the logger",
|
Usage: "Matching expression for the logger",
|
||||||
}, cli.StringFlag{
|
},
|
||||||
Name: "prefix, p",
|
&cli.StringFlag{
|
||||||
|
Name: "prefix",
|
||||||
|
Aliases: []string{"p"},
|
||||||
Usage: "Prefix for the logger",
|
Usage: "Prefix for the logger",
|
||||||
}, cli.BoolFlag{
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
Name: "color",
|
Name: "color",
|
||||||
Usage: "Use color in the logs",
|
Usage: "Use color in the logs",
|
||||||
}, cli.BoolFlag{
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmdLogging = cli.Command{
|
subcmdLogging = &cli.Command{
|
||||||
Name: "logging",
|
Name: "logging",
|
||||||
Usage: "Adjust logging commands",
|
Usage: "Adjust logging commands",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
{
|
{
|
||||||
Name: "pause",
|
Name: "pause",
|
||||||
Usage: "Pause logging (Gitea will buffer logs up to a certain point and will drop them after that point)",
|
Usage: "Pause logging (Gitea will buffer logs up to a certain point and will drop them after that point)",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -61,7 +73,7 @@ var (
|
||||||
Name: "resume",
|
Name: "resume",
|
||||||
Usage: "Resume logging",
|
Usage: "Resume logging",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -70,7 +82,7 @@ var (
|
||||||
Name: "release-and-reopen",
|
Name: "release-and-reopen",
|
||||||
Usage: "Cause Gitea to release and re-open files used for logging",
|
Usage: "Cause Gitea to release and re-open files used for logging",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -80,9 +92,9 @@ var (
|
||||||
Usage: "Remove a logger",
|
Usage: "Remove a logger",
|
||||||
ArgsUsage: "[name] Name of logger to remove",
|
ArgsUsage: "[name] Name of logger to remove",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
}, cli.StringFlag{
|
}, &cli.StringFlag{
|
||||||
Name: "logger",
|
Name: "logger",
|
||||||
Usage: `Logger name - will default to "default"`,
|
Usage: `Logger name - will default to "default"`,
|
||||||
},
|
},
|
||||||
|
@ -91,31 +103,44 @@ var (
|
||||||
}, {
|
}, {
|
||||||
Name: "add",
|
Name: "add",
|
||||||
Usage: "Add a logger",
|
Usage: "Add a logger",
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []*cli.Command{
|
||||||
{
|
{
|
||||||
Name: "file",
|
Name: "file",
|
||||||
Usage: "Add a file logger",
|
Usage: "Add a file logger",
|
||||||
Flags: append(defaultLoggingFlags, []cli.Flag{
|
Flags: append(defaultLoggingFlags, []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "filename, f",
|
Name: "filename",
|
||||||
|
Aliases: []string{"f"},
|
||||||
Usage: "Filename for the logger - this must be set.",
|
Usage: "Filename for the logger - this must be set.",
|
||||||
}, cli.BoolTFlag{
|
},
|
||||||
Name: "rotate, r",
|
&cli.BoolFlag{
|
||||||
|
Name: "rotate",
|
||||||
|
Aliases: []string{"r"},
|
||||||
Usage: "Rotate logs",
|
Usage: "Rotate logs",
|
||||||
}, cli.Int64Flag{
|
},
|
||||||
Name: "max-size, s",
|
&cli.Int64Flag{
|
||||||
|
Name: "max-size",
|
||||||
|
Aliases: []string{"s"},
|
||||||
Usage: "Maximum size in bytes before rotation",
|
Usage: "Maximum size in bytes before rotation",
|
||||||
}, cli.BoolTFlag{
|
},
|
||||||
Name: "daily, d",
|
&cli.BoolFlag{
|
||||||
|
Name: "daily",
|
||||||
|
Aliases: []string{"d"},
|
||||||
Usage: "Rotate logs daily",
|
Usage: "Rotate logs daily",
|
||||||
}, cli.IntFlag{
|
},
|
||||||
Name: "max-days, D",
|
&cli.IntFlag{
|
||||||
|
Name: "max-days",
|
||||||
|
Aliases: []string{"D"},
|
||||||
Usage: "Maximum number of daily logs to keep",
|
Usage: "Maximum number of daily logs to keep",
|
||||||
}, cli.BoolTFlag{
|
},
|
||||||
Name: "compress, z",
|
&cli.BoolFlag{
|
||||||
|
Name: "compress",
|
||||||
|
Aliases: []string{"z"},
|
||||||
Usage: "Compress rotated logs",
|
Usage: "Compress rotated logs",
|
||||||
}, cli.IntFlag{
|
},
|
||||||
Name: "compression-level, Z",
|
&cli.IntFlag{
|
||||||
|
Name: "compression-level",
|
||||||
|
Aliases: []string{"Z"},
|
||||||
Usage: "Compression level to use",
|
Usage: "Compression level to use",
|
||||||
},
|
},
|
||||||
}...),
|
}...),
|
||||||
|
@ -124,17 +149,24 @@ var (
|
||||||
Name: "conn",
|
Name: "conn",
|
||||||
Usage: "Add a net conn logger",
|
Usage: "Add a net conn logger",
|
||||||
Flags: append(defaultLoggingFlags, []cli.Flag{
|
Flags: append(defaultLoggingFlags, []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "reconnect-on-message, R",
|
Name: "reconnect-on-message",
|
||||||
|
Aliases: []string{"R"},
|
||||||
Usage: "Reconnect to host for every message",
|
Usage: "Reconnect to host for every message",
|
||||||
}, cli.BoolFlag{
|
},
|
||||||
Name: "reconnect, r",
|
&cli.BoolFlag{
|
||||||
|
Name: "reconnect",
|
||||||
|
Aliases: []string{"r"},
|
||||||
Usage: "Reconnect to host when connection is dropped",
|
Usage: "Reconnect to host when connection is dropped",
|
||||||
}, cli.StringFlag{
|
},
|
||||||
Name: "protocol, P",
|
&cli.StringFlag{
|
||||||
|
Name: "protocol",
|
||||||
|
Aliases: []string{"P"},
|
||||||
Usage: "Set protocol to use: tcp, unix, or udp (defaults to tcp)",
|
Usage: "Set protocol to use: tcp, unix, or udp (defaults to tcp)",
|
||||||
}, cli.StringFlag{
|
},
|
||||||
Name: "address, a",
|
&cli.StringFlag{
|
||||||
|
Name: "address",
|
||||||
|
Aliases: []string{"a"},
|
||||||
Usage: "Host address and port to connect to (defaults to :7020)",
|
Usage: "Host address and port to connect to (defaults to :7020)",
|
||||||
},
|
},
|
||||||
}...),
|
}...),
|
||||||
|
@ -145,9 +177,10 @@ var (
|
||||||
Name: "log-sql",
|
Name: "log-sql",
|
||||||
Usage: "Set LogSQL",
|
Usage: "Set LogSQL",
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
}, cli.BoolFlag{
|
},
|
||||||
|
&cli.BoolFlag{
|
||||||
Name: "off",
|
Name: "off",
|
||||||
Usage: "Switch off SQL logging",
|
Usage: "Switch off SQL logging",
|
||||||
},
|
},
|
||||||
|
|
|
@ -11,11 +11,11 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdMigrate represents the available migrate sub-command.
|
// CmdMigrate represents the available migrate sub-command.
|
||||||
var CmdMigrate = cli.Command{
|
var CmdMigrate = &cli.Command{
|
||||||
Name: "migrate",
|
Name: "migrate",
|
||||||
Usage: "Migrate the database",
|
Usage: "Migrate the database",
|
||||||
Description: "This is a command for migrating the database, so that you can run gitea admin create-user before starting the server.",
|
Description: "This is a command for migrating the database, so that you can run gitea admin create-user before starting the server.",
|
||||||
|
|
|
@ -20,70 +20,73 @@ import (
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/storage"
|
"code.gitea.io/gitea/modules/storage"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdMigrateStorage represents the available migrate storage sub-command.
|
// CmdMigrateStorage represents the available migrate storage sub-command.
|
||||||
var CmdMigrateStorage = cli.Command{
|
var CmdMigrateStorage = &cli.Command{
|
||||||
Name: "migrate-storage",
|
Name: "migrate-storage",
|
||||||
Usage: "Migrate the storage",
|
Usage: "Migrate the storage",
|
||||||
Description: "Copies stored files from storage configured in app.ini to parameter-configured storage",
|
Description: "Copies stored files from storage configured in app.ini to parameter-configured storage",
|
||||||
Action: runMigrateStorage,
|
Action: runMigrateStorage,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "type, t",
|
Name: "type",
|
||||||
|
Aliases: []string{"t"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log'",
|
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log'",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "storage, s",
|
Name: "storage",
|
||||||
|
Aliases: []string{"s"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "New storage type: local (default) or minio",
|
Usage: "New storage type: local (default) or minio",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "path, p",
|
Name: "path",
|
||||||
|
Aliases: []string{"p"},
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "New storage placement if store is local (leave blank for default)",
|
Usage: "New storage placement if store is local (leave blank for default)",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "minio-endpoint",
|
Name: "minio-endpoint",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Minio storage endpoint",
|
Usage: "Minio storage endpoint",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "minio-access-key-id",
|
Name: "minio-access-key-id",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Minio storage accessKeyID",
|
Usage: "Minio storage accessKeyID",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "minio-secret-access-key",
|
Name: "minio-secret-access-key",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Minio storage secretAccessKey",
|
Usage: "Minio storage secretAccessKey",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "minio-bucket",
|
Name: "minio-bucket",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Minio storage bucket",
|
Usage: "Minio storage bucket",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "minio-location",
|
Name: "minio-location",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Minio storage location to create bucket",
|
Usage: "Minio storage location to create bucket",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "minio-base-path",
|
Name: "minio-base-path",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Minio storage base path on the bucket",
|
Usage: "Minio storage base path on the bucket",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "minio-use-ssl",
|
Name: "minio-use-ssl",
|
||||||
Usage: "Enable SSL for minio",
|
Usage: "Enable SSL for minio",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "minio-insecure-skip-verify",
|
Name: "minio-insecure-skip-verify",
|
||||||
Usage: "Skip SSL verification",
|
Usage: "Skip SSL verification",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "minio-checksum-algorithm",
|
Name: "minio-checksum-algorithm",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Minio checksum algorithm (default/md5)",
|
Usage: "Minio checksum algorithm (default/md5)",
|
||||||
|
|
|
@ -9,38 +9,39 @@ import (
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdRestoreRepository represents the available restore a repository sub-command.
|
// CmdRestoreRepository represents the available restore a repository sub-command.
|
||||||
var CmdRestoreRepository = cli.Command{
|
var CmdRestoreRepository = &cli.Command{
|
||||||
Name: "restore-repo",
|
Name: "restore-repo",
|
||||||
Usage: "Restore the repository from disk",
|
Usage: "Restore the repository from disk",
|
||||||
Description: "This is a command for restoring the repository data.",
|
Description: "This is a command for restoring the repository data.",
|
||||||
Action: runRestoreRepository,
|
Action: runRestoreRepository,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "repo_dir, r",
|
Name: "repo_dir",
|
||||||
|
Aliases: []string{"r"},
|
||||||
Value: "./data",
|
Value: "./data",
|
||||||
Usage: "Repository dir path to restore from",
|
Usage: "Repository dir path to restore from",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "owner_name",
|
Name: "owner_name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Restore destination owner name",
|
Usage: "Restore destination owner name",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "repo_name",
|
Name: "repo_name",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Restore destination repository name",
|
Usage: "Restore destination repository name",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "units",
|
Name: "units",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: `Which items will be restored, one or more units should be separated as comma.
|
Usage: `Which items will be restored, one or more units should be separated as comma.
|
||||||
wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments are allowed. Empty means all units.`,
|
wiki, issues, labels, releases, release_assets, milestones, pull_requests, comments are allowed. Empty means all units.`,
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "validation",
|
Name: "validation",
|
||||||
Usage: "Sanity check the content of the files before trying to load them",
|
Usage: "Sanity check the content of the files before trying to load them",
|
||||||
},
|
},
|
||||||
|
|
20
cmd/serv.go
20
cmd/serv.go
|
@ -32,7 +32,7 @@ import (
|
||||||
|
|
||||||
"github.com/golang-jwt/jwt/v5"
|
"github.com/golang-jwt/jwt/v5"
|
||||||
"github.com/kballard/go-shellquote"
|
"github.com/kballard/go-shellquote"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -40,17 +40,17 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
// CmdServ represents the available serv sub-command.
|
// CmdServ represents the available serv sub-command.
|
||||||
var CmdServ = cli.Command{
|
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),
|
Before: PrepareConsoleLoggerLevel(log.FATAL),
|
||||||
Action: runServ,
|
Action: runServ,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "enable-pprof",
|
Name: "enable-pprof",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "debug",
|
Name: "debug",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -119,7 +119,7 @@ func fail(ctx context.Context, userMessage, logMsgFmt string, args ...any) error
|
||||||
}
|
}
|
||||||
_ = private.SSHLog(ctx, true, logMsg)
|
_ = private.SSHLog(ctx, true, logMsg)
|
||||||
}
|
}
|
||||||
return cli.NewExitError("", 1)
|
return cli.Exit("", 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
// handleCliResponseExtra handles the extra response from the cli sub-commands
|
// handleCliResponseExtra handles the extra response from the cli sub-commands
|
||||||
|
@ -130,7 +130,7 @@ func handleCliResponseExtra(extra private.ResponseExtra) error {
|
||||||
_, _ = fmt.Fprintln(os.Stdout, extra.UserMsg)
|
_, _ = fmt.Fprintln(os.Stdout, extra.UserMsg)
|
||||||
}
|
}
|
||||||
if extra.HasError() {
|
if extra.HasError() {
|
||||||
return cli.NewExitError(extra.Error, 1)
|
return cli.Exit(extra.Error, 1)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -147,20 +147,20 @@ func runServ(c *cli.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(c.Args()) < 1 {
|
if c.NArg() < 1 {
|
||||||
if err := cli.ShowSubcommandHelp(c); err != nil {
|
if err := cli.ShowSubcommandHelp(c); err != nil {
|
||||||
fmt.Printf("error showing subcommand help: %v\n", err)
|
fmt.Printf("error showing subcommand help: %v\n", err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
keys := strings.Split(c.Args()[0], "-")
|
keys := strings.Split(c.Args().First(), "-")
|
||||||
if len(keys) != 2 || keys[0] != "key" {
|
if len(keys) != 2 || keys[0] != "key" {
|
||||||
return fail(ctx, "Key ID format error", "Invalid key argument: %s", c.Args()[0])
|
return fail(ctx, "Key ID format error", "Invalid key argument: %s", c.Args().First())
|
||||||
}
|
}
|
||||||
keyID, err := strconv.ParseInt(keys[1], 10, 64)
|
keyID, err := strconv.ParseInt(keys[1], 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fail(ctx, "Key ID parsing error", "Invalid key argument: %s", c.Args()[1])
|
return fail(ctx, "Key ID parsing error", "Invalid key argument: %s", c.Args().Get(1))
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
|
cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
|
||||||
|
|
23
cmd/web.go
23
cmd/web.go
|
@ -23,14 +23,14 @@ import (
|
||||||
"code.gitea.io/gitea/routers/install"
|
"code.gitea.io/gitea/routers/install"
|
||||||
|
|
||||||
"github.com/felixge/fgprof"
|
"github.com/felixge/fgprof"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
// PIDFile could be set from build tag
|
// PIDFile could be set from build tag
|
||||||
var PIDFile = "/run/gitea.pid"
|
var PIDFile = "/run/gitea.pid"
|
||||||
|
|
||||||
// CmdWeb represents the available web sub-command.
|
// CmdWeb represents the available web sub-command.
|
||||||
var CmdWeb = cli.Command{
|
var CmdWeb = &cli.Command{
|
||||||
Name: "web",
|
Name: "web",
|
||||||
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,
|
||||||
|
@ -38,26 +38,29 @@ and it takes care of all the other things for you`,
|
||||||
Before: PrepareConsoleLoggerLevel(log.INFO),
|
Before: PrepareConsoleLoggerLevel(log.INFO),
|
||||||
Action: runWeb,
|
Action: runWeb,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "port, p",
|
Name: "port",
|
||||||
|
Aliases: []string{"p"},
|
||||||
Value: "3000",
|
Value: "3000",
|
||||||
Usage: "Temporary port number to prevent conflict",
|
Usage: "Temporary port number to prevent conflict",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "install-port",
|
Name: "install-port",
|
||||||
Value: "3000",
|
Value: "3000",
|
||||||
Usage: "Temporary port number to run the install page on to prevent conflict",
|
Usage: "Temporary port number to run the install page on to prevent conflict",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "pid, P",
|
Name: "pid",
|
||||||
|
Aliases: []string{"P"},
|
||||||
Value: PIDFile,
|
Value: PIDFile,
|
||||||
Usage: "Custom pid file path",
|
Usage: "Custom pid file path",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "quiet, q",
|
Name: "quiet",
|
||||||
|
Aliases: []string{"q"},
|
||||||
Usage: "Only display Fatal logging errors until logging is set-up",
|
Usage: "Only display Fatal logging errors until logging is set-up",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "verbose",
|
Name: "verbose",
|
||||||
Usage: "Set initial logging to TRACE level until logging is properly set-up",
|
Usage: "Set initial logging to TRACE level until logging is properly set-up",
|
||||||
},
|
},
|
||||||
|
|
|
@ -18,7 +18,7 @@ import (
|
||||||
"syscall"
|
"syscall"
|
||||||
|
|
||||||
"github.com/google/go-github/v53/github"
|
"github.com/google/go-github/v53/github"
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -32,55 +32,55 @@ func main() {
|
||||||
app.ArgsUsage = "<PR-to-backport>"
|
app.ArgsUsage = "<PR-to-backport>"
|
||||||
|
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "version",
|
Name: "version",
|
||||||
Usage: "Version branch to backport on to",
|
Usage: "Version branch to backport on to",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "upstream",
|
Name: "upstream",
|
||||||
Value: "origin",
|
Value: "origin",
|
||||||
Usage: "Upstream remote for the Gitea upstream",
|
Usage: "Upstream remote for the Gitea upstream",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "release-branch",
|
Name: "release-branch",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Release branch to backport on. Will default to release/<version>",
|
Usage: "Release branch to backport on. Will default to release/<version>",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "cherry-pick",
|
Name: "cherry-pick",
|
||||||
Usage: "SHA to cherry-pick as backport",
|
Usage: "SHA to cherry-pick as backport",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "backport-branch",
|
Name: "backport-branch",
|
||||||
Usage: "Backport branch to backport on to (default: backport-<pr>-<version>",
|
Usage: "Backport branch to backport on to (default: backport-<pr>-<version>",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "remote",
|
Name: "remote",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Remote for your fork of the Gitea upstream",
|
Usage: "Remote for your fork of the Gitea upstream",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "fork-user",
|
Name: "fork-user",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Forked user name on Github",
|
Usage: "Forked user name on Github",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "no-fetch",
|
Name: "no-fetch",
|
||||||
Usage: "Set this flag to prevent fetch of remote branches",
|
Usage: "Set this flag to prevent fetch of remote branches",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "no-amend-message",
|
Name: "no-amend-message",
|
||||||
Usage: "Set this flag to prevent automatic amendment of the commit message",
|
Usage: "Set this flag to prevent automatic amendment of the commit message",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "no-push",
|
Name: "no-push",
|
||||||
Usage: "Set this flag to prevent pushing the backport up to your fork",
|
Usage: "Set this flag to prevent pushing the backport up to your fork",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "no-xdg-open",
|
Name: "no-xdg-open",
|
||||||
Usage: "Set this flag to not use xdg-open to open the PR URL",
|
Usage: "Set this flag to not use xdg-open to open the PR URL",
|
||||||
},
|
},
|
||||||
cli.BoolFlag{
|
&cli.BoolFlag{
|
||||||
Name: "continue",
|
Name: "continue",
|
||||||
Usage: "Set this flag to continue from a git cherry-pick that has broken",
|
Usage: "Set this flag to continue from a git cherry-pick that has broken",
|
||||||
},
|
},
|
||||||
|
@ -151,7 +151,7 @@ func runBackport(c *cli.Context) error {
|
||||||
|
|
||||||
localReleaseBranch := path.Join(upstream, upstreamReleaseBranch)
|
localReleaseBranch := path.Join(upstream, upstreamReleaseBranch)
|
||||||
|
|
||||||
args := c.Args()
|
args := c.Args().Slice()
|
||||||
if len(args) == 0 && pr == "" {
|
if len(args) == 0 && pr == "" {
|
||||||
return fmt.Errorf("no PR number provided\nProvide a PR number to backport")
|
return fmt.Errorf("no PR number provided\nProvide a PR number to backport")
|
||||||
} else if len(args) != 1 && pr == "" {
|
} else if len(args) != 1 && pr == "" {
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
@ -46,22 +46,22 @@ func main() {
|
||||||
and "GITEA__LOG_0x2E_CONSOLE__STDERR=false". Other examples can be found
|
and "GITEA__LOG_0x2E_CONSOLE__STDERR=false". Other examples can be found
|
||||||
on the configuration cheat sheet.`
|
on the configuration cheat sheet.`
|
||||||
app.Flags = []cli.Flag{
|
app.Flags = []cli.Flag{
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "custom-path, C",
|
Name: "custom-path, C",
|
||||||
Value: setting.CustomPath,
|
Value: setting.CustomPath,
|
||||||
Usage: "Custom path file path",
|
Usage: "Custom path file path",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "config, c",
|
Name: "config, c",
|
||||||
Value: setting.CustomConf,
|
Value: setting.CustomConf,
|
||||||
Usage: "Custom configuration file path",
|
Usage: "Custom configuration file path",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "work-path, w",
|
Name: "work-path, w",
|
||||||
Value: setting.AppWorkPath,
|
Value: setting.AppWorkPath,
|
||||||
Usage: "Set the gitea working path",
|
Usage: "Set the gitea working path",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
&cli.StringFlag{
|
||||||
Name: "out, o",
|
Name: "out, o",
|
||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Destination file to write to",
|
Usage: "Destination file to write to",
|
||||||
|
|
|
@ -12,7 +12,7 @@
|
||||||
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||||||
;;
|
;;
|
||||||
;; These values are environment-dependent but form the basis of a lot of values. They will be
|
;; These values are environment-dependent but form the basis of a lot of values. They will be
|
||||||
;; reported as part of the default configuration when running `gitea --help` or on start-up. The order they are emitted there is slightly different but we will list them here in the order they are set-up.
|
;; reported as part of the default configuration when running `gitea help` or on start-up. The order they are emitted there is slightly different but we will list them here in the order they are set-up.
|
||||||
;;
|
;;
|
||||||
;; - _`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:
|
||||||
|
|
|
@ -40,7 +40,7 @@ Values containing `#` or `;` must be quoted using `` ` `` or `"""`.
|
||||||
## Default Configuration (non-`app.ini` configuration)
|
## Default Configuration (non-`app.ini` configuration)
|
||||||
|
|
||||||
These values are environment-dependent but form the basis of a lot of values. They will be
|
These values are environment-dependent but form the basis of a lot of values. They will be
|
||||||
reported as part of the default configuration when running `gitea --help` or on start-up. The order they are emitted there is slightly different but we will list them here in the order they are set-up.
|
reported as part of the default configuration when running `gitea help` or on start-up. The order they are emitted there is slightly different but we will list them here in the order they are set-up.
|
||||||
|
|
||||||
- _`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:
|
||||||
|
|
3
go.mod
3
go.mod
|
@ -98,7 +98,7 @@ require (
|
||||||
github.com/syndtr/goleveldb v1.0.0
|
github.com/syndtr/goleveldb v1.0.0
|
||||||
github.com/tstranex/u2f v1.0.0
|
github.com/tstranex/u2f v1.0.0
|
||||||
github.com/ulikunitz/xz v0.5.11
|
github.com/ulikunitz/xz v0.5.11
|
||||||
github.com/urfave/cli v1.22.14
|
github.com/urfave/cli/v2 v2.25.7
|
||||||
github.com/xanzy/go-gitlab v0.86.0
|
github.com/xanzy/go-gitlab v0.86.0
|
||||||
github.com/xeipuuv/gojsonschema v1.2.0
|
github.com/xeipuuv/gojsonschema v1.2.0
|
||||||
github.com/yohcop/openid-go v1.0.1
|
github.com/yohcop/openid-go v1.0.1
|
||||||
|
@ -278,6 +278,7 @@ require (
|
||||||
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb // indirect
|
||||||
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // indirect
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect
|
||||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||||
go.etcd.io/bbolt v1.3.7 // indirect
|
go.etcd.io/bbolt v1.3.7 // indirect
|
||||||
go.mongodb.org/mongo-driver v1.12.0 // indirect
|
go.mongodb.org/mongo-driver v1.12.0 // indirect
|
||||||
|
|
7
go.sum
7
go.sum
|
@ -80,7 +80,6 @@ github.com/Azure/azure-sdk-for-go/sdk/internal v0.7.0/go.mod h1:yqy467j36fJxcRV2
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
||||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
|
||||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||||
github.com/ClickHouse/ch-go v0.57.0 h1:X/QmUmFhpUvLgPSQb7fWOSi1wvqGn6tJ7w2a59c4xsg=
|
github.com/ClickHouse/ch-go v0.57.0 h1:X/QmUmFhpUvLgPSQb7fWOSi1wvqGn6tJ7w2a59c4xsg=
|
||||||
github.com/ClickHouse/ch-go v0.57.0/go.mod h1:DR3iBn7OrrDj+KeUp1LbdxLEUDbW+5Qwdl/qkc+PQ+Y=
|
github.com/ClickHouse/ch-go v0.57.0/go.mod h1:DR3iBn7OrrDj+KeUp1LbdxLEUDbW+5Qwdl/qkc+PQ+Y=
|
||||||
|
@ -1162,8 +1161,8 @@ github.com/unknwon/com v1.0.1 h1:3d1LTxD+Lnf3soQiD4Cp/0BRB+Rsa/+RTvz8GMMzIXs=
|
||||||
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
|
github.com/unknwon/com v1.0.1/go.mod h1:tOOxU81rwgoCLoOVVPHb6T/wt8HZygqH5id+GNnlCXM=
|
||||||
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
|
||||||
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
|
||||||
github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk=
|
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs=
|
||||||
github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA=
|
github.com/urfave/cli/v2 v2.25.7/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasthttp v1.37.1-0.20220607072126-8a320890c08d/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
|
github.com/valyala/fasthttp v1.37.1-0.20220607072126-8a320890c08d/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
|
||||||
|
@ -1198,6 +1197,8 @@ github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofm
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
||||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU=
|
||||||
|
github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8=
|
||||||
github.com/yohcop/openid-go v1.0.1 h1:DPRd3iPO5F6O5zX2e62XpVAbPT6wV51cuucH0z9g3js=
|
github.com/yohcop/openid-go v1.0.1 h1:DPRd3iPO5F6O5zX2e62XpVAbPT6wV51cuucH0z9g3js=
|
||||||
github.com/yohcop/openid-go v1.0.1/go.mod h1:b/AvD03P0KHj4yuihb+VtLD6bYYgsy0zqBzPCRjkCNs=
|
github.com/yohcop/openid-go v1.0.1/go.mod h1:b/AvD03P0KHj4yuihb+VtLD6bYYgsy0zqBzPCRjkCNs=
|
||||||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
|
||||||
|
|
154
main.go
154
main.go
|
@ -2,8 +2,7 @@
|
||||||
// Copyright 2016 The Gitea Authors. All rights reserved.
|
// Copyright 2016 The Gitea Authors. All rights reserved.
|
||||||
// SPDX-License-Identifier: MIT
|
// SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
// Gitea (git with a cup of tea) is a painless self-hosted Git Service.
|
package main
|
||||||
package main // import "code.gitea.io/gitea"
|
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
@ -22,17 +21,13 @@ import (
|
||||||
_ "code.gitea.io/gitea/modules/markup/csv"
|
_ "code.gitea.io/gitea/modules/markup/csv"
|
||||||
_ "code.gitea.io/gitea/modules/markup/markdown"
|
_ "code.gitea.io/gitea/modules/markup/markdown"
|
||||||
_ "code.gitea.io/gitea/modules/markup/orgmode"
|
_ "code.gitea.io/gitea/modules/markup/orgmode"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// these flags will be set by the build flags
|
||||||
var (
|
var (
|
||||||
// Version holds the current Gitea version
|
Version = "development" // program version for this build
|
||||||
Version = "development"
|
Tags = "" // the Golang build tags
|
||||||
// Tags holds the build tags used
|
MakeVersion = "" // "make" program version if built with make
|
||||||
Tags = ""
|
|
||||||
// MakeVersion holds the current Make version if built with make
|
|
||||||
MakeVersion = ""
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
@ -41,110 +36,12 @@ func init() {
|
||||||
setting.AppStartTime = time.Now().UTC()
|
setting.AppStartTime = time.Now().UTC()
|
||||||
}
|
}
|
||||||
|
|
||||||
// cmdHelp is our own help subcommand with more information
|
|
||||||
// test cases:
|
|
||||||
// ./gitea help
|
|
||||||
// ./gitea -h
|
|
||||||
// ./gitea web help
|
|
||||||
// ./gitea web -h (due to cli lib limitation, this won't call our cmdHelp, so no extra info)
|
|
||||||
// ./gitea admin
|
|
||||||
// ./gitea admin help
|
|
||||||
// ./gitea admin auth help
|
|
||||||
// ./gitea -c /tmp/app.ini -h
|
|
||||||
// ./gitea -c /tmp/app.ini help
|
|
||||||
// ./gitea help -c /tmp/app.ini
|
|
||||||
// GITEA_WORK_DIR=/tmp ./gitea help
|
|
||||||
// GITEA_WORK_DIR=/tmp ./gitea help --work-path /tmp/other
|
|
||||||
// GITEA_WORK_DIR=/tmp ./gitea help --config /tmp/app-other.ini
|
|
||||||
var cmdHelp = cli.Command{
|
|
||||||
Name: "help",
|
|
||||||
Aliases: []string{"h"},
|
|
||||||
Usage: "Shows a list of commands or help for one command",
|
|
||||||
ArgsUsage: "[command]",
|
|
||||||
Action: func(c *cli.Context) (err error) {
|
|
||||||
args := c.Args()
|
|
||||||
if args.Present() {
|
|
||||||
err = cli.ShowCommandHelp(c, args.First())
|
|
||||||
} else {
|
|
||||||
err = cli.ShowAppHelp(c)
|
|
||||||
}
|
|
||||||
_, _ = fmt.Fprintf(c.App.Writer, `
|
|
||||||
DEFAULT CONFIGURATION:
|
|
||||||
AppPath: %s
|
|
||||||
WorkPath: %s
|
|
||||||
CustomPath: %s
|
|
||||||
ConfigFile: %s
|
|
||||||
|
|
||||||
`, setting.AppPath, setting.AppWorkPath, setting.CustomPath, setting.CustomConf)
|
|
||||||
return err
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
app := cli.NewApp()
|
app := cmd.NewMainApp()
|
||||||
app.Name = "Gitea"
|
app.Name = "Gitea"
|
||||||
app.Usage = "A painless self-hosted Git service"
|
app.Usage = "A painless self-hosted Git service"
|
||||||
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
|
|
||||||
|
|
||||||
// these sub-commands need to use config file
|
|
||||||
subCmdWithIni := []cli.Command{
|
|
||||||
cmd.CmdWeb,
|
|
||||||
cmd.CmdServ,
|
|
||||||
cmd.CmdHook,
|
|
||||||
cmd.CmdDump,
|
|
||||||
cmd.CmdAdmin,
|
|
||||||
cmd.CmdMigrate,
|
|
||||||
cmd.CmdKeys,
|
|
||||||
cmd.CmdConvert,
|
|
||||||
cmd.CmdDoctor,
|
|
||||||
cmd.CmdManager,
|
|
||||||
cmd.CmdEmbedded,
|
|
||||||
cmd.CmdMigrateStorage,
|
|
||||||
cmd.CmdDumpRepository,
|
|
||||||
cmd.CmdRestoreRepository,
|
|
||||||
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,
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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{
|
|
||||||
cli.HelpFlag,
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "custom-path, C",
|
|
||||||
Usage: "Set custom path (defaults to '{WorkPath}/custom')",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: setting.CustomConf,
|
|
||||||
Usage: "Set custom config file (defaults to '{WorkPath}/custom/conf/app.ini')",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "work-path, w",
|
|
||||||
Usage: "Set Gitea's working path (defaults to the Gitea's binary directory)",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set the default to be equivalent to cmdWeb and add the default flags
|
|
||||||
app.Flags = append(app.Flags, globalFlags...)
|
|
||||||
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.HideHelp = true // use our own help action to show helps (with more information like default config)
|
|
||||||
app.Before = cmd.PrepareConsoleLoggerLevel(log.INFO)
|
|
||||||
for i := range subCmdWithIni {
|
|
||||||
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 {
|
||||||
|
@ -154,45 +51,6 @@ func main() {
|
||||||
log.GetManager().Close()
|
log.GetManager().Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
func prepareSubcommands(command *cli.Command, defaultFlags []cli.Flag) {
|
|
||||||
command.Flags = append(command.Flags, defaultFlags...)
|
|
||||||
command.Action = prepareWorkPathAndCustomConf(command.Action)
|
|
||||||
command.HideHelp = true
|
|
||||||
if command.Name != "help" {
|
|
||||||
command.Subcommands = append(command.Subcommands, cmdHelp)
|
|
||||||
}
|
|
||||||
for i := range command.Subcommands {
|
|
||||||
prepareSubcommands(&command.Subcommands[i], defaultFlags)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 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
|
|
||||||
func prepareWorkPathAndCustomConf(action any) func(ctx *cli.Context) error {
|
|
||||||
return func(ctx *cli.Context) error {
|
|
||||||
var args setting.ArgWorkPathAndCustomConf
|
|
||||||
curCtx := ctx
|
|
||||||
for curCtx != nil {
|
|
||||||
if curCtx.IsSet("work-path") && args.WorkPath == "" {
|
|
||||||
args.WorkPath = curCtx.String("work-path")
|
|
||||||
}
|
|
||||||
if curCtx.IsSet("custom-path") && args.CustomPath == "" {
|
|
||||||
args.CustomPath = curCtx.String("custom-path")
|
|
||||||
}
|
|
||||||
if curCtx.IsSet("config") && args.CustomConf == "" {
|
|
||||||
args.CustomConf = curCtx.String("config")
|
|
||||||
}
|
|
||||||
curCtx = curCtx.Parent()
|
|
||||||
}
|
|
||||||
setting.InitWorkPathAndCommonConfig(os.Getenv, args)
|
|
||||||
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 action.(func(*cli.Context) error)(ctx)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatBuiltWith() string {
|
func formatBuiltWith() string {
|
||||||
version := runtime.Version()
|
version := runtime.Version()
|
||||||
if len(MakeVersion) > 0 {
|
if len(MakeVersion) > 0 {
|
||||||
|
|
|
@ -5,17 +5,15 @@ package integration
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"flag"
|
|
||||||
"io"
|
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"code.gitea.io/gitea/cmd"
|
"code.gitea.io/gitea/cmd"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
"code.gitea.io/gitea/modules/setting"
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/urfave/cli/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func Test_CmdKeys(t *testing.T) {
|
func Test_CmdKeys(t *testing.T) {
|
||||||
|
@ -38,26 +36,18 @@ func Test_CmdKeys(t *testing.T) {
|
||||||
}
|
}
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
realStdout := os.Stdout // Backup Stdout
|
out := new(bytes.Buffer)
|
||||||
r, w, _ := os.Pipe()
|
app := cli.NewApp()
|
||||||
os.Stdout = w
|
app.Writer = out
|
||||||
|
app.Commands = []*cli.Command{cmd.CmdKeys}
|
||||||
set := flag.NewFlagSet("keys", 0)
|
cmd.CmdKeys.HideHelp = true
|
||||||
_ = set.Parse(tt.args)
|
err := app.Run(append([]string{"prog"}, tt.args...))
|
||||||
context := cli.NewContext(&cli.App{Writer: os.Stdout}, set, nil)
|
if tt.wantErr {
|
||||||
err := cmd.CmdKeys.Run(context)
|
assert.Error(t, err)
|
||||||
if (err != nil) != tt.wantErr {
|
} else {
|
||||||
t.Errorf("CmdKeys.Run() error = %v, wantErr %v", err, tt.wantErr)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
w.Close()
|
assert.Equal(t, tt.expectedOutput, out.String())
|
||||||
var buf bytes.Buffer
|
|
||||||
io.Copy(&buf, r)
|
|
||||||
commandOutput := buf.String()
|
|
||||||
if tt.expectedOutput != commandOutput {
|
|
||||||
t.Errorf("expectedOutput: %#v, commandOutput: %#v", tt.expectedOutput, commandOutput)
|
|
||||||
}
|
|
||||||
// Restore stdout
|
|
||||||
os.Stdout = realStdout
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
Loading…
Reference in New Issue