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 affectedtags/v1.21.0-rc0
@@ -9,30 +9,31 @@ import ( | |||
"code.gitea.io/gitea/modules/private" | |||
"code.gitea.io/gitea/modules/setting" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
var ( | |||
// CmdActions represents the available actions sub-commands. | |||
CmdActions = cli.Command{ | |||
CmdActions = &cli.Command{ | |||
Name: "actions", | |||
Usage: "", | |||
Description: "Commands for managing Gitea Actions", | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
subcmdActionsGenRunnerToken, | |||
}, | |||
} | |||
subcmdActionsGenRunnerToken = cli.Command{ | |||
subcmdActionsGenRunnerToken = &cli.Command{ | |||
Name: "generate-runner-token", | |||
Usage: "Generate a new token for a runner to use to register with the server", | |||
Action: runGenerateActionsRunnerToken, | |||
Aliases: []string{"grt"}, | |||
Flags: []cli.Flag{ | |||
cli.StringFlag{ | |||
Name: "scope, s", | |||
Value: "", | |||
Usage: "{owner}[/{repo}] - leave empty for a global runner", | |||
&cli.StringFlag{ | |||
Name: "scope", | |||
Aliases: []string{"s"}, | |||
Value: "", | |||
Usage: "{owner}[/{repo}] - leave empty for a global runner", | |||
}, | |||
}, | |||
} |
@@ -26,15 +26,15 @@ import ( | |||
"code.gitea.io/gitea/services/auth/source/smtp" | |||
repo_service "code.gitea.io/gitea/services/repository" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
var ( | |||
// CmdAdmin represents the available admin sub-command. | |||
CmdAdmin = cli.Command{ | |||
CmdAdmin = &cli.Command{ | |||
Name: "admin", | |||
Usage: "Command line interface to perform common administrative operations", | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
subcmdUser, | |||
subcmdRepoSyncReleases, | |||
subcmdRegenerate, | |||
@@ -43,37 +43,37 @@ var ( | |||
}, | |||
} | |||
subcmdRepoSyncReleases = cli.Command{ | |||
subcmdRepoSyncReleases = &cli.Command{ | |||
Name: "repo-sync-releases", | |||
Usage: "Synchronize repository releases with tags", | |||
Action: runRepoSyncReleases, | |||
} | |||
subcmdRegenerate = cli.Command{ | |||
subcmdRegenerate = &cli.Command{ | |||
Name: "regenerate", | |||
Usage: "Regenerate specific files", | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
microcmdRegenHooks, | |||
microcmdRegenKeys, | |||
}, | |||
} | |||
microcmdRegenHooks = cli.Command{ | |||
microcmdRegenHooks = &cli.Command{ | |||
Name: "hooks", | |||
Usage: "Regenerate git-hooks", | |||
Action: runRegenerateHooks, | |||
} | |||
microcmdRegenKeys = cli.Command{ | |||
microcmdRegenKeys = &cli.Command{ | |||
Name: "keys", | |||
Usage: "Regenerate authorized_keys file", | |||
Action: runRegenerateKeys, | |||
} | |||
subcmdAuth = cli.Command{ | |||
subcmdAuth = &cli.Command{ | |||
Name: "auth", | |||
Usage: "Modify external auth providers", | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
microcmdAuthAddOauth, | |||
microcmdAuthUpdateOauth, | |||
cmdAuthAddLdapBindDn, | |||
@@ -87,44 +87,44 @@ var ( | |||
}, | |||
} | |||
microcmdAuthList = cli.Command{ | |||
microcmdAuthList = &cli.Command{ | |||
Name: "list", | |||
Usage: "List auth sources", | |||
Action: runListAuth, | |||
Flags: []cli.Flag{ | |||
cli.IntFlag{ | |||
&cli.IntFlag{ | |||
Name: "min-width", | |||
Usage: "Minimal cell width including any padding for the formatted table", | |||
Value: 0, | |||
}, | |||
cli.IntFlag{ | |||
&cli.IntFlag{ | |||
Name: "tab-width", | |||
Usage: "width of tab characters in formatted table (equivalent number of spaces)", | |||
Value: 8, | |||
}, | |||
cli.IntFlag{ | |||
&cli.IntFlag{ | |||
Name: "padding", | |||
Usage: "padding added to a cell before computing its width", | |||
Value: 1, | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
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)`, | |||
Value: "\t", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "vertical-bars", | |||
Usage: "Set to true to print vertical bars between columns", | |||
}, | |||
}, | |||
} | |||
idFlag = cli.Int64Flag{ | |||
idFlag = &cli.Int64Flag{ | |||
Name: "id", | |||
Usage: "ID of authentication source", | |||
} | |||
microcmdAuthDelete = cli.Command{ | |||
microcmdAuthDelete = &cli.Command{ | |||
Name: "delete", | |||
Usage: "Delete specific auth source", | |||
Flags: []cli.Flag{idFlag}, | |||
@@ -132,207 +132,208 @@ var ( | |||
} | |||
oauthCLIFlags = []cli.Flag{ | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "name", | |||
Value: "", | |||
Usage: "Application Name", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "provider", | |||
Value: "", | |||
Usage: "OAuth2 Provider", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "key", | |||
Value: "", | |||
Usage: "Client ID (Key)", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "secret", | |||
Value: "", | |||
Usage: "Client Secret", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "auto-discover-url", | |||
Value: "", | |||
Usage: "OpenID Connect Auto Discovery URL (only required when using OpenID Connect as provider)", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "use-custom-urls", | |||
Value: "false", | |||
Usage: "Use custom URLs for GitLab/GitHub OAuth endpoints", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "custom-tenant-id", | |||
Value: "", | |||
Usage: "Use custom Tenant ID for OAuth endpoints", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "custom-auth-url", | |||
Value: "", | |||
Usage: "Use a custom Authorization URL (option for GitLab/GitHub)", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "custom-token-url", | |||
Value: "", | |||
Usage: "Use a custom Token URL (option for GitLab/GitHub)", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "custom-profile-url", | |||
Value: "", | |||
Usage: "Use a custom Profile URL (option for GitLab/GitHub)", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "custom-email-url", | |||
Value: "", | |||
Usage: "Use a custom Email URL (option for GitHub)", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "icon-url", | |||
Value: "", | |||
Usage: "Custom icon URL for OAuth2 login source", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "skip-local-2fa", | |||
Usage: "Set to true to skip local 2fa for users authenticated by this source", | |||
}, | |||
cli.StringSliceFlag{ | |||
&cli.StringSliceFlag{ | |||
Name: "scopes", | |||
Value: nil, | |||
Usage: "Scopes to request when to authenticate against this OAuth2 source", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "required-claim-name", | |||
Value: "", | |||
Usage: "Claim name that has to be set to allow users to login with this source", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "required-claim-value", | |||
Value: "", | |||
Usage: "Claim value that has to be set to allow users to login with this source", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "group-claim-name", | |||
Value: "", | |||
Usage: "Claim name providing group names for this source", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "admin-group", | |||
Value: "", | |||
Usage: "Group Claim value for administrator users", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "restricted-group", | |||
Value: "", | |||
Usage: "Group Claim value for restricted users", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "group-team-map", | |||
Value: "", | |||
Usage: "JSON mapping between groups and org teams", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "group-team-map-removal", | |||
Usage: "Activate automatic team membership removal depending on groups", | |||
}, | |||
} | |||
microcmdAuthUpdateOauth = cli.Command{ | |||
microcmdAuthUpdateOauth = &cli.Command{ | |||
Name: "update-oauth", | |||
Usage: "Update existing Oauth authentication source", | |||
Action: runUpdateOauth, | |||
Flags: append(oauthCLIFlags[:1], append([]cli.Flag{idFlag}, oauthCLIFlags[1:]...)...), | |||
} | |||
microcmdAuthAddOauth = cli.Command{ | |||
microcmdAuthAddOauth = &cli.Command{ | |||
Name: "add-oauth", | |||
Usage: "Add new Oauth authentication source", | |||
Action: runAddOauth, | |||
Flags: oauthCLIFlags, | |||
} | |||
subcmdSendMail = cli.Command{ | |||
subcmdSendMail = &cli.Command{ | |||
Name: "sendmail", | |||
Usage: "Send a message to all users", | |||
Action: runSendMail, | |||
Flags: []cli.Flag{ | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "title", | |||
Usage: `a title of a message`, | |||
Value: "", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "content", | |||
Usage: "a content of a message", | |||
Value: "", | |||
}, | |||
cli.BoolFlag{ | |||
Name: "force,f", | |||
Usage: "A flag to bypass a confirmation step", | |||
&cli.BoolFlag{ | |||
Name: "force", | |||
Aliases: []string{"f"}, | |||
Usage: "A flag to bypass a confirmation step", | |||
}, | |||
}, | |||
} | |||
smtpCLIFlags = []cli.Flag{ | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "name", | |||
Value: "", | |||
Usage: "Application Name", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "auth-type", | |||
Value: "PLAIN", | |||
Usage: "SMTP Authentication Type (PLAIN/LOGIN/CRAM-MD5) default PLAIN", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "host", | |||
Value: "", | |||
Usage: "SMTP Host", | |||
}, | |||
cli.IntFlag{ | |||
&cli.IntFlag{ | |||
Name: "port", | |||
Usage: "SMTP Port", | |||
}, | |||
cli.BoolTFlag{ | |||
&cli.BoolFlag{ | |||
Name: "force-smtps", | |||
Usage: "SMTPS is always used on port 465. Set this to force SMTPS on other ports.", | |||
}, | |||
cli.BoolTFlag{ | |||
&cli.BoolFlag{ | |||
Name: "skip-verify", | |||
Usage: "Skip TLS verify.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "helo-hostname", | |||
Value: "", | |||
Usage: "Hostname sent with HELO. Leave blank to send current hostname", | |||
}, | |||
cli.BoolTFlag{ | |||
&cli.BoolFlag{ | |||
Name: "disable-helo", | |||
Usage: "Disable SMTP helo.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "allowed-domains", | |||
Value: "", | |||
Usage: "Leave empty to allow all domains. Separate multiple domains with a comma (',')", | |||
}, | |||
cli.BoolTFlag{ | |||
&cli.BoolFlag{ | |||
Name: "skip-local-2fa", | |||
Usage: "Skip 2FA to log on.", | |||
}, | |||
cli.BoolTFlag{ | |||
&cli.BoolFlag{ | |||
Name: "active", | |||
Usage: "This Authentication Source is Activated.", | |||
}, | |||
} | |||
microcmdAuthAddSMTP = cli.Command{ | |||
microcmdAuthAddSMTP = &cli.Command{ | |||
Name: "add-smtp", | |||
Usage: "Add new SMTP authentication source", | |||
Action: runAddSMTP, | |||
Flags: smtpCLIFlags, | |||
} | |||
microcmdAuthUpdateSMTP = cli.Command{ | |||
microcmdAuthUpdateSMTP = &cli.Command{ | |||
Name: "update-smtp", | |||
Usage: "Update existing SMTP authentication source", | |||
Action: runUpdateSMTP, | |||
@@ -611,19 +612,19 @@ func parseSMTPConfig(c *cli.Context, conf *smtp.Source) error { | |||
conf.AllowedDomains = c.String("allowed-domains") | |||
} | |||
if c.IsSet("force-smtps") { | |||
conf.ForceSMTPS = c.BoolT("force-smtps") | |||
conf.ForceSMTPS = c.Bool("force-smtps") | |||
} | |||
if c.IsSet("skip-verify") { | |||
conf.SkipVerify = c.BoolT("skip-verify") | |||
conf.SkipVerify = c.Bool("skip-verify") | |||
} | |||
if c.IsSet("helo-hostname") { | |||
conf.HeloHostname = c.String("helo-hostname") | |||
} | |||
if c.IsSet("disable-helo") { | |||
conf.DisableHelo = c.BoolT("disable-helo") | |||
conf.DisableHelo = c.Bool("disable-helo") | |||
} | |||
if c.IsSet("skip-local-2fa") { | |||
conf.SkipLocalTwoFA = c.BoolT("skip-local-2fa") | |||
conf.SkipLocalTwoFA = c.Bool("skip-local-2fa") | |||
} | |||
return nil | |||
} | |||
@@ -647,7 +648,7 @@ func runAddSMTP(c *cli.Context) error { | |||
} | |||
active := true | |||
if c.IsSet("active") { | |||
active = c.BoolT("active") | |||
active = c.Bool("active") | |||
} | |||
var smtpConfig smtp.Source | |||
@@ -696,7 +697,7 @@ func runUpdateSMTP(c *cli.Context) error { | |||
} | |||
if c.IsSet("active") { | |||
source.IsActive = c.BoolT("active") | |||
source.IsActive = c.Bool("active") | |||
} | |||
source.Cfg = smtpConfig |
@@ -11,7 +11,7 @@ import ( | |||
"code.gitea.io/gitea/models/auth" | |||
"code.gitea.io/gitea/services/auth/source/ldap" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
type ( | |||
@@ -25,117 +25,117 @@ type ( | |||
var ( | |||
commonLdapCLIFlags = []cli.Flag{ | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "name", | |||
Usage: "Authentication name.", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "not-active", | |||
Usage: "Deactivate the authentication source.", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "active", | |||
Usage: "Activate the authentication source.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "security-protocol", | |||
Usage: "Security protocol name.", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "skip-tls-verify", | |||
Usage: "Disable TLS verification.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "host", | |||
Usage: "The address where the LDAP server can be reached.", | |||
}, | |||
cli.IntFlag{ | |||
&cli.IntFlag{ | |||
Name: "port", | |||
Usage: "The port to use when connecting to the LDAP server.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "user-search-base", | |||
Usage: "The LDAP base at which user accounts will be searched for.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "user-filter", | |||
Usage: "An LDAP filter declaring how to find the user record that is attempting to authenticate.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "admin-filter", | |||
Usage: "An LDAP filter specifying if a user should be given administrator privileges.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "restricted-filter", | |||
Usage: "An LDAP filter specifying if a user should be given restricted status.", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "allow-deactivate-all", | |||
Usage: "Allow empty search results to deactivate all users.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "username-attribute", | |||
Usage: "The attribute of the user’s LDAP record containing the user name.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "firstname-attribute", | |||
Usage: "The attribute of the user’s LDAP record containing the user’s first name.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "surname-attribute", | |||
Usage: "The attribute of the user’s LDAP record containing the user’s surname.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "email-attribute", | |||
Usage: "The attribute of the user’s LDAP record containing the user’s email address.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "public-ssh-key-attribute", | |||
Usage: "The attribute of the user’s LDAP record containing the user’s public ssh key.", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "skip-local-2fa", | |||
Usage: "Set to true to skip local 2fa for users authenticated by this source", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "avatar-attribute", | |||
Usage: "The attribute of the user’s LDAP record containing the user’s avatar.", | |||
}, | |||
} | |||
ldapBindDnCLIFlags = append(commonLdapCLIFlags, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "bind-dn", | |||
Usage: "The DN to bind to the LDAP server with when searching for the user.", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "bind-password", | |||
Usage: "The password for the Bind DN, if any.", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "attributes-in-bind", | |||
Usage: "Fetch attributes in bind DN context.", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "synchronize-users", | |||
Usage: "Enable user synchronization.", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "disable-synchronize-users", | |||
Usage: "Disable user synchronization.", | |||
}, | |||
cli.UintFlag{ | |||
&cli.UintFlag{ | |||
Name: "page-size", | |||
Usage: "Search page size.", | |||
}) | |||
ldapSimpleAuthCLIFlags = append(commonLdapCLIFlags, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "user-dn", | |||
Usage: "The user’s DN.", | |||
}) | |||
cmdAuthAddLdapBindDn = cli.Command{ | |||
cmdAuthAddLdapBindDn = &cli.Command{ | |||
Name: "add-ldap", | |||
Usage: "Add new LDAP (via Bind DN) authentication source", | |||
Action: func(c *cli.Context) error { | |||
@@ -144,7 +144,7 @@ var ( | |||
Flags: ldapBindDnCLIFlags, | |||
} | |||
cmdAuthUpdateLdapBindDn = cli.Command{ | |||
cmdAuthUpdateLdapBindDn = &cli.Command{ | |||
Name: "update-ldap", | |||
Usage: "Update existing LDAP (via Bind DN) authentication source", | |||
Action: func(c *cli.Context) error { | |||
@@ -153,7 +153,7 @@ var ( | |||
Flags: append([]cli.Flag{idFlag}, ldapBindDnCLIFlags...), | |||
} | |||
cmdAuthAddLdapSimpleAuth = cli.Command{ | |||
cmdAuthAddLdapSimpleAuth = &cli.Command{ | |||
Name: "add-ldap-simple", | |||
Usage: "Add new LDAP (simple auth) authentication source", | |||
Action: func(c *cli.Context) error { | |||
@@ -162,7 +162,7 @@ var ( | |||
Flags: ldapSimpleAuthCLIFlags, | |||
} | |||
cmdAuthUpdateLdapSimpleAuth = cli.Command{ | |||
cmdAuthUpdateLdapSimpleAuth = &cli.Command{ | |||
Name: "update-ldap-simple", | |||
Usage: "Update existing LDAP (simple auth) authentication source", | |||
Action: func(c *cli.Context) error { |
@@ -11,7 +11,7 @@ import ( | |||
"code.gitea.io/gitea/services/auth/source/ldap" | |||
"github.com/stretchr/testify/assert" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
func TestAddLdapBindDn(t *testing.T) { |
@@ -4,13 +4,13 @@ | |||
package cmd | |||
import ( | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
var subcmdUser = cli.Command{ | |||
var subcmdUser = &cli.Command{ | |||
Name: "user", | |||
Usage: "Modify users", | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
microcmdUserCreate, | |||
microcmdUserList, | |||
microcmdUserChangePassword, |
@@ -12,23 +12,25 @@ import ( | |||
pwd "code.gitea.io/gitea/modules/auth/password" | |||
"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", | |||
Usage: "Change a user's password", | |||
Action: runChangePassword, | |||
Flags: []cli.Flag{ | |||
cli.StringFlag{ | |||
Name: "username,u", | |||
Value: "", | |||
Usage: "The user to change password for", | |||
&cli.StringFlag{ | |||
Name: "username", | |||
Aliases: []string{"u"}, | |||
Value: "", | |||
Usage: "The user to change password for", | |||
}, | |||
cli.StringFlag{ | |||
Name: "password,p", | |||
Value: "", | |||
Usage: "New password to set for user", | |||
&cli.StringFlag{ | |||
Name: "password", | |||
Aliases: []string{"p"}, | |||
Value: "", | |||
Usage: "New password to set for user", | |||
}, | |||
}, | |||
} |
@@ -14,52 +14,52 @@ import ( | |||
"code.gitea.io/gitea/modules/setting" | |||
"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", | |||
Usage: "Create a new user in database", | |||
Action: runCreateUser, | |||
Flags: []cli.Flag{ | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "name", | |||
Usage: "Username. DEPRECATED: use username instead", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "username", | |||
Usage: "Username", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "password", | |||
Usage: "User password", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "email", | |||
Usage: "User email address", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "admin", | |||
Usage: "User is an admin", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "random-password", | |||
Usage: "Generate a random password for the user", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "must-change-password", | |||
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", | |||
Usage: "Length of the random password to be generated", | |||
Value: 12, | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "access-token", | |||
Usage: "Generate access token for the user", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "restricted", | |||
Usage: "Make a restricted user account", | |||
}, |
@@ -11,26 +11,28 @@ import ( | |||
"code.gitea.io/gitea/modules/storage" | |||
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", | |||
Usage: "Delete specific user by id, name or email", | |||
Flags: []cli.Flag{ | |||
cli.Int64Flag{ | |||
&cli.Int64Flag{ | |||
Name: "id", | |||
Usage: "ID of user of the user to delete", | |||
}, | |||
cli.StringFlag{ | |||
Name: "username,u", | |||
Usage: "Username of the user to delete", | |||
&cli.StringFlag{ | |||
Name: "username", | |||
Aliases: []string{"u"}, | |||
Usage: "Username of the user to delete", | |||
}, | |||
cli.StringFlag{ | |||
Name: "email,e", | |||
Usage: "Email of the user to delete", | |||
&cli.StringFlag{ | |||
Name: "email", | |||
Aliases: []string{"e"}, | |||
Usage: "Email of the user to delete", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "purge", | |||
Usage: "Purge user, all their repositories, organizations and comments", | |||
}, |
@@ -9,27 +9,29 @@ import ( | |||
auth_model "code.gitea.io/gitea/models/auth" | |||
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", | |||
Usage: "Generate an access token for a specific user", | |||
Flags: []cli.Flag{ | |||
cli.StringFlag{ | |||
Name: "username,u", | |||
Usage: "Username", | |||
&cli.StringFlag{ | |||
Name: "username", | |||
Aliases: []string{"u"}, | |||
Usage: "Username", | |||
}, | |||
cli.StringFlag{ | |||
Name: "token-name,t", | |||
Usage: "Token name", | |||
Value: "gitea-admin", | |||
&cli.StringFlag{ | |||
Name: "token-name", | |||
Aliases: []string{"t"}, | |||
Usage: "Token name", | |||
Value: "gitea-admin", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "raw", | |||
Usage: "Display only the token value", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "scopes", | |||
Value: "", | |||
Usage: "Comma separated list of scopes to apply to access token", |
@@ -10,15 +10,15 @@ import ( | |||
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", | |||
Usage: "List users", | |||
Action: runListUsers, | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "admin", | |||
Usage: "List only admin users", | |||
}, |
@@ -9,23 +9,25 @@ import ( | |||
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", | |||
Usage: "Set the must change password flag for the provided users or all users", | |||
Action: runMustChangePassword, | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
Name: "all,A", | |||
Usage: "All users must change password, except those explicitly excluded with --exclude", | |||
&cli.BoolFlag{ | |||
Name: "all", | |||
Aliases: []string{"A"}, | |||
Usage: "All users must change password, except those explicitly excluded with --exclude", | |||
}, | |||
cli.StringSliceFlag{ | |||
Name: "exclude,e", | |||
Usage: "Do not change the must-change-password flag for these users", | |||
&cli.StringSliceFlag{ | |||
Name: "exclude", | |||
Aliases: []string{"e"}, | |||
Usage: "Do not change the must-change-password flag for these users", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "unset", | |||
Usage: "Instead of setting the must-change-password flag, unset it", | |||
}, | |||
@@ -48,7 +50,7 @@ func runMustChangePassword(c *cli.Context) error { | |||
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 { | |||
return err | |||
} |
@@ -20,43 +20,43 @@ import ( | |||
"strings" | |||
"time" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
// CmdCert represents the available cert sub-command. | |||
var CmdCert = cli.Command{ | |||
var CmdCert = &cli.Command{ | |||
Name: "cert", | |||
Usage: "Generate self-signed certificate", | |||
Description: `Generate a self-signed X.509 certificate for a TLS server. | |||
Outputs to 'cert.pem' and 'key.pem' and will overwrite existing files.`, | |||
Action: runCert, | |||
Flags: []cli.Flag{ | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "host", | |||
Value: "", | |||
Usage: "Comma-separated hostnames and IPs to generate a certificate for", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "ecdsa-curve", | |||
Value: "", | |||
Usage: "ECDSA curve to use to generate a key. Valid values are P224, P256, P384, P521", | |||
}, | |||
cli.IntFlag{ | |||
&cli.IntFlag{ | |||
Name: "rsa-bits", | |||
Value: 2048, | |||
Usage: "Size of RSA key to generate. Ignored if --ecdsa-curve is set", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "start-date", | |||
Value: "", | |||
Usage: "Creation date formatted as Jan 1 15:04:05 2011", | |||
}, | |||
cli.DurationFlag{ | |||
&cli.DurationFlag{ | |||
Name: "duration", | |||
Value: 365 * 24 * time.Hour, | |||
Usage: "Duration that certificate is valid for", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "ca", | |||
Usage: "whether this cert should be its own Certificate Authority", | |||
}, |
@@ -20,7 +20,7 @@ import ( | |||
"code.gitea.io/gitea/modules/setting" | |||
"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 | |||
@@ -109,15 +109,24 @@ func setupConsoleLogger(level log.Level, colorize bool, out io.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. | |||
// Any log appears in git stdout pipe will break the git protocol, eg: client can't push and hangs forever. | |||
func PrepareConsoleLoggerLevel(defaultLevel log.Level) func(*cli.Context) error { | |||
return func(c *cli.Context) error { | |||
level := defaultLevel | |||
if c.Bool("quiet") || c.GlobalBoolT("quiet") { | |||
if globalBool(c, "quiet") { | |||
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 | |||
} | |||
log.SetConsoleLogger(log.DEFAULT, "console-default", level) |
@@ -10,11 +10,11 @@ import ( | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/setting" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
// CmdConvert represents the available convert sub-command. | |||
var CmdConvert = cli.Command{ | |||
var CmdConvert = &cli.Command{ | |||
Name: "convert", | |||
Usage: "Convert the database", | |||
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" | |||
"strings" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
// CmdDocs represents the available docs sub-command. | |||
var CmdDocs = cli.Command{ | |||
var CmdDocs = &cli.Command{ | |||
Name: "docs", | |||
Usage: "Output CLI documentation", | |||
Description: "A command to output Gitea's CLI documentation, optionally to a file.", | |||
@@ -23,8 +23,9 @@ var CmdDocs = cli.Command{ | |||
Usage: "Output man pages instead", | |||
}, | |||
&cli.StringFlag{ | |||
Name: "output, o", | |||
Usage: "Path to output to instead of stdout (will overwrite if exists)", | |||
Name: "output", | |||
Aliases: []string{"o"}, | |||
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/setting" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
"xorm.io/xorm" | |||
) | |||
// CmdDoctor represents the available doctor sub-command. | |||
var CmdDoctor = cli.Command{ | |||
var CmdDoctor = &cli.Command{ | |||
Name: "doctor", | |||
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.", | |||
Action: runDoctor, | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "list", | |||
Usage: "List the available checks", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "default", | |||
Usage: "Run the default checks (if neither --run or --all is set, this is the default behaviour)", | |||
}, | |||
cli.StringSliceFlag{ | |||
&cli.StringSliceFlag{ | |||
Name: "run", | |||
Usage: "Run the provided checks - (if --default is set, the default checks will also run)", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "all", | |||
Usage: "Run all the available checks", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "fix", | |||
Usage: "Automatically fix what we can", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "log-file", | |||
Usage: `Name of the log file (default: "doctor.log"). Set to "-" to output to stdout, set to "" to disable`, | |||
}, | |||
cli.BoolFlag{ | |||
Name: "color, H", | |||
Usage: "Use color for outputted information", | |||
&cli.BoolFlag{ | |||
Name: "color", | |||
Aliases: []string{"H"}, | |||
Usage: "Use color for outputted information", | |||
}, | |||
}, | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
cmdRecreateTable, | |||
}, | |||
} | |||
var cmdRecreateTable = cli.Command{ | |||
var cmdRecreateTable = &cli.Command{ | |||
Name: "recreate-table", | |||
Usage: "Recreate tables from XORM definitions and copy the data.", | |||
ArgsUsage: "[TABLE]... : (TABLEs to recreate - leave blank for all)", | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
Usage: "Print SQL commands sent", | |||
}, |
@@ -22,7 +22,7 @@ import ( | |||
"gitea.com/go-chi/session" | |||
"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 { | |||
@@ -96,64 +96,71 @@ var outputTypeEnum = &outputType{ | |||
} | |||
// CmdDump represents the available dump sub-command. | |||
var CmdDump = cli.Command{ | |||
var CmdDump = &cli.Command{ | |||
Name: "dump", | |||
Usage: "Dump Gitea files and database", | |||
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`, | |||
Action: runDump, | |||
Flags: []cli.Flag{ | |||
cli.StringFlag{ | |||
Name: "file, f", | |||
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.", | |||
&cli.StringFlag{ | |||
Name: "file", | |||
Aliases: []string{"f"}, | |||
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.", | |||
}, | |||
cli.BoolFlag{ | |||
Name: "verbose, V", | |||
Usage: "Show process details", | |||
&cli.BoolFlag{ | |||
Name: "verbose", | |||
Aliases: []string{"V"}, | |||
Usage: "Show process details", | |||
}, | |||
cli.BoolFlag{ | |||
Name: "quiet, q", | |||
Usage: "Only display warnings and errors", | |||
&cli.BoolFlag{ | |||
Name: "quiet", | |||
Aliases: []string{"q"}, | |||
Usage: "Only display warnings and errors", | |||
}, | |||
cli.StringFlag{ | |||
Name: "tempdir, t", | |||
Value: os.TempDir(), | |||
Usage: "Temporary dir path", | |||
&cli.StringFlag{ | |||
Name: "tempdir", | |||
Aliases: []string{"t"}, | |||
Value: os.TempDir(), | |||
Usage: "Temporary dir path", | |||
}, | |||
cli.StringFlag{ | |||
Name: "database, d", | |||
Usage: "Specify the database SQL syntax", | |||
&cli.StringFlag{ | |||
Name: "database", | |||
Aliases: []string{"d"}, | |||
Usage: "Specify the database SQL syntax", | |||
}, | |||
cli.BoolFlag{ | |||
Name: "skip-repository, R", | |||
Usage: "Skip the repository dumping", | |||
&cli.BoolFlag{ | |||
Name: "skip-repository", | |||
Aliases: []string{"R"}, | |||
Usage: "Skip the repository dumping", | |||
}, | |||
cli.BoolFlag{ | |||
Name: "skip-log, L", | |||
Usage: "Skip the log dumping", | |||
&cli.BoolFlag{ | |||
Name: "skip-log", | |||
Aliases: []string{"L"}, | |||
Usage: "Skip the log dumping", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "skip-custom-dir", | |||
Usage: "Skip custom directory", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "skip-lfs-data", | |||
Usage: "Skip LFS data", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "skip-attachment-data", | |||
Usage: "Skip attachment data", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "skip-package-data", | |||
Usage: "Skip package data", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "skip-index", | |||
Usage: "Skip bleve index data", | |||
}, | |||
cli.GenericFlag{ | |||
&cli.GenericFlag{ | |||
Name: "type", | |||
Value: outputTypeEnum, | |||
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/migrations" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
// CmdDumpRepository represents the available dump repository sub-command. | |||
var CmdDumpRepository = cli.Command{ | |||
var CmdDumpRepository = &cli.Command{ | |||
Name: "dump-repo", | |||
Usage: "Dump the repository from git/github/gitea/gitlab", | |||
Description: "This is a command for dumping the repository data.", | |||
Action: runDumpRepository, | |||
Flags: []cli.Flag{ | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "git_service", | |||
Value: "", | |||
Usage: "Git service, git, github, gitea, gitlab. If clone_addr could be recognized, this could be ignored.", | |||
}, | |||
cli.StringFlag{ | |||
Name: "repo_dir, r", | |||
Value: "./data", | |||
Usage: "Repository dir path to store the data", | |||
&cli.StringFlag{ | |||
Name: "repo_dir", | |||
Aliases: []string{"r"}, | |||
Value: "./data", | |||
Usage: "Repository dir path to store the data", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "clone_addr", | |||
Value: "", | |||
Usage: "The URL will be clone, currently could be a git/github/gitea/gitlab http/https URL", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "auth_username", | |||
Value: "", | |||
Usage: "The username to visit the clone_addr", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "auth_password", | |||
Value: "", | |||
Usage: "The password to visit the clone_addr", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "auth_token", | |||
Value: "", | |||
Usage: "The personal token to visit the clone_addr", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "owner_name", | |||
Value: "", | |||
Usage: "The data will be stored on a directory with owner name if not empty", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "repo_name", | |||
Value: "", | |||
Usage: "The data will be stored on a directory with repository name if not empty", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "units", | |||
Value: "", | |||
Usage: `Which items will be migrated, one or more units should be separated as comma. |
@@ -19,70 +19,74 @@ import ( | |||
"code.gitea.io/gitea/modules/util" | |||
"github.com/gobwas/glob" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
// CmdEmbedded represents the available extract sub-command. | |||
var ( | |||
CmdEmbedded = cli.Command{ | |||
CmdEmbedded = &cli.Command{ | |||
Name: "embedded", | |||
Usage: "Extract embedded resources", | |||
Description: "A command for extracting embedded resources, like templates and images", | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
subcmdList, | |||
subcmdView, | |||
subcmdExtract, | |||
}, | |||
} | |||
subcmdList = cli.Command{ | |||
subcmdList = &cli.Command{ | |||
Name: "list", | |||
Usage: "List files matching the given pattern", | |||
Action: runList, | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
Name: "include-vendored,vendor", | |||
Usage: "Include files under public/vendor as well", | |||
&cli.BoolFlag{ | |||
Name: "include-vendored", | |||
Aliases: []string{"vendor"}, | |||
Usage: "Include files under public/vendor as well", | |||
}, | |||
}, | |||
} | |||
subcmdView = cli.Command{ | |||
subcmdView = &cli.Command{ | |||
Name: "view", | |||
Usage: "View a file matching the given pattern", | |||
Action: runView, | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
Name: "include-vendored,vendor", | |||
Usage: "Include files under public/vendor as well", | |||
&cli.BoolFlag{ | |||
Name: "include-vendored", | |||
Aliases: []string{"vendor"}, | |||
Usage: "Include files under public/vendor as well", | |||
}, | |||
}, | |||
} | |||
subcmdExtract = cli.Command{ | |||
subcmdExtract = &cli.Command{ | |||
Name: "extract", | |||
Usage: "Extract resources", | |||
Action: runExtract, | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
Name: "include-vendored,vendor", | |||
Usage: "Include files under public/vendor as well", | |||
&cli.BoolFlag{ | |||
Name: "include-vendored", | |||
Aliases: []string{"vendor"}, | |||
Usage: "Include files under public/vendor as well", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "overwrite", | |||
Usage: "Overwrite files if they already exist", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "rename", | |||
Usage: "Rename files as {name}.bak if they already exist (overwrites previous .bak)", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "custom", | |||
Usage: "Extract to the 'custom' directory as per app.ini", | |||
}, | |||
cli.StringFlag{ | |||
Name: "destination,dest-dir", | |||
Usage: "Extract to the specified directory", | |||
&cli.StringFlag{ | |||
Name: "destination", | |||
Aliases: []string{"dest-dir"}, | |||
Usage: "Extract to the specified directory", | |||
}, | |||
}, | |||
} | |||
@@ -99,7 +103,7 @@ type assetFile struct { | |||
func initEmbeddedExtractor(c *cli.Context) error { | |||
setupConsoleLogger(log.ERROR, log.CanColorStderr, os.Stderr) | |||
patterns, err := compileCollectPatterns(c.Args()) | |||
patterns, err := compileCollectPatterns(c.Args().Slice()) | |||
if err != nil { | |||
return err | |||
} | |||
@@ -175,7 +179,7 @@ func runExtractDo(c *cli.Context) error { | |||
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)") | |||
} | |||
@@ -11,43 +11,43 @@ import ( | |||
"code.gitea.io/gitea/modules/generate" | |||
"github.com/mattn/go-isatty" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
var ( | |||
// CmdGenerate represents the available generate sub-command. | |||
CmdGenerate = cli.Command{ | |||
CmdGenerate = &cli.Command{ | |||
Name: "generate", | |||
Usage: "Command line interface for running generators", | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
subcmdSecret, | |||
}, | |||
} | |||
subcmdSecret = cli.Command{ | |||
subcmdSecret = &cli.Command{ | |||
Name: "secret", | |||
Usage: "Generate a secret token", | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
microcmdGenerateInternalToken, | |||
microcmdGenerateLfsJwtSecret, | |||
microcmdGenerateSecretKey, | |||
}, | |||
} | |||
microcmdGenerateInternalToken = cli.Command{ | |||
microcmdGenerateInternalToken = &cli.Command{ | |||
Name: "INTERNAL_TOKEN", | |||
Usage: "Generate a new INTERNAL_TOKEN", | |||
Action: runGenerateInternalToken, | |||
} | |||
microcmdGenerateLfsJwtSecret = cli.Command{ | |||
microcmdGenerateLfsJwtSecret = &cli.Command{ | |||
Name: "JWT_SECRET", | |||
Aliases: []string{"LFS_JWT_SECRET"}, | |||
Usage: "Generate a new JWT_SECRET", | |||
Action: runGenerateLfsJwtSecret, | |||
} | |||
microcmdGenerateSecretKey = cli.Command{ | |||
microcmdGenerateSecretKey = &cli.Command{ | |||
Name: "SECRET_KEY", | |||
Usage: "Generate a new SECRET_KEY", | |||
Action: runGenerateSecretKey, |
@@ -20,7 +20,7 @@ import ( | |||
repo_module "code.gitea.io/gitea/modules/repository" | |||
"code.gitea.io/gitea/modules/setting" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
const ( | |||
@@ -29,12 +29,12 @@ const ( | |||
var ( | |||
// CmdHook represents the available hooks sub-command. | |||
CmdHook = cli.Command{ | |||
CmdHook = &cli.Command{ | |||
Name: "hook", | |||
Usage: "Delegate commands to corresponding Git hooks", | |||
Description: "This should only be called by Git", | |||
Before: PrepareConsoleLoggerLevel(log.FATAL), | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
subcmdHookPreReceive, | |||
subcmdHookUpdate, | |||
subcmdHookPostReceive, | |||
@@ -42,47 +42,47 @@ var ( | |||
}, | |||
} | |||
subcmdHookPreReceive = cli.Command{ | |||
subcmdHookPreReceive = &cli.Command{ | |||
Name: "pre-receive", | |||
Usage: "Delegate pre-receive Git hook", | |||
Description: "This command should only be called by Git", | |||
Action: runHookPreReceive, | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
}, | |||
} | |||
subcmdHookUpdate = cli.Command{ | |||
subcmdHookUpdate = &cli.Command{ | |||
Name: "update", | |||
Usage: "Delegate update Git hook", | |||
Description: "This command should only be called by Git", | |||
Action: runHookUpdate, | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
}, | |||
} | |||
subcmdHookPostReceive = cli.Command{ | |||
subcmdHookPostReceive = &cli.Command{ | |||
Name: "post-receive", | |||
Usage: "Delegate post-receive Git hook", | |||
Description: "This command should only be called by Git", | |||
Action: runHookPostReceive, | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
}, | |||
} | |||
// Note: new hook since git 2.29 | |||
subcmdHookProcReceive = cli.Command{ | |||
subcmdHookProcReceive = &cli.Command{ | |||
Name: "proc-receive", | |||
Usage: "Delegate proc-receive Git hook", | |||
Description: "This command should only be called by Git", | |||
Action: runHookProcReceive, | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
}, |
@@ -11,35 +11,39 @@ import ( | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/private" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
// CmdKeys represents the available keys sub-command | |||
var CmdKeys = cli.Command{ | |||
var CmdKeys = &cli.Command{ | |||
Name: "keys", | |||
Usage: "This command queries the Gitea database to get the authorized command for a given ssh key fingerprint", | |||
Before: PrepareConsoleLoggerLevel(log.FATAL), | |||
Action: runKeys, | |||
Flags: []cli.Flag{ | |||
cli.StringFlag{ | |||
Name: "expected, e", | |||
Value: "git", | |||
Usage: "Expected user for whom provide key commands", | |||
&cli.StringFlag{ | |||
Name: "expected", | |||
Aliases: []string{"e"}, | |||
Value: "git", | |||
Usage: "Expected user for whom provide key commands", | |||
}, | |||
cli.StringFlag{ | |||
Name: "username, u", | |||
Value: "", | |||
Usage: "Username trying to log in by SSH", | |||
&cli.StringFlag{ | |||
Name: "username", | |||
Aliases: []string{"u"}, | |||
Value: "", | |||
Usage: "Username trying to log in by SSH", | |||
}, | |||
cli.StringFlag{ | |||
Name: "type, t", | |||
Value: "", | |||
Usage: "Type of the SSH key provided to the SSH Server (requires content to be provided too)", | |||
&cli.StringFlag{ | |||
Name: "type", | |||
Aliases: []string{"t"}, | |||
Value: "", | |||
Usage: "Type of the SSH key provided to the SSH Server (requires content to be provided too)", | |||
}, | |||
cli.StringFlag{ | |||
Name: "content, k", | |||
Value: "", | |||
Usage: "Base64 encoded content of the SSH key provided to the SSH Server (requires type to be provided too)", | |||
&cli.StringFlag{ | |||
Name: "content", | |||
Aliases: []string{"k"}, | |||
Value: "", | |||
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 { | |||
return extra.Error | |||
} | |||
fmt.Println(strings.TrimSpace(authorizedString)) | |||
_, _ = fmt.Fprintln(c.App.Writer, strings.TrimSpace(authorizedString)) | |||
return nil | |||
} |
@@ -9,7 +9,7 @@ import ( | |||
"code.gitea.io/gitea/modules/private" | |||
"code.gitea.io/gitea/modules/setting" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
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 | |||
} |
@@ -4,9 +4,17 @@ | |||
package cmd | |||
import ( | |||
"fmt" | |||
"os" | |||
"path/filepath" | |||
"strings" | |||
"testing" | |||
"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) { | |||
@@ -14,3 +22,110 @@ func TestMain(m *testing.M) { | |||
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" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
var ( | |||
// CmdManager represents the manager command | |||
CmdManager = cli.Command{ | |||
CmdManager = &cli.Command{ | |||
Name: "manager", | |||
Usage: "Manage the running gitea process", | |||
Description: "This is a command for managing the running gitea process", | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
subcmdShutdown, | |||
subcmdRestart, | |||
subcmdReloadTemplates, | |||
@@ -27,80 +27,80 @@ var ( | |||
subCmdProcesses, | |||
}, | |||
} | |||
subcmdShutdown = cli.Command{ | |||
subcmdShutdown = &cli.Command{ | |||
Name: "shutdown", | |||
Usage: "Gracefully shutdown the running process", | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
}, | |||
Action: runShutdown, | |||
} | |||
subcmdRestart = cli.Command{ | |||
subcmdRestart = &cli.Command{ | |||
Name: "restart", | |||
Usage: "Gracefully restart the running process - (not implemented for windows servers)", | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
}, | |||
Action: runRestart, | |||
} | |||
subcmdReloadTemplates = cli.Command{ | |||
subcmdReloadTemplates = &cli.Command{ | |||
Name: "reload-templates", | |||
Usage: "Reload template files in the running process", | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
}, | |||
Action: runReloadTemplates, | |||
} | |||
subcmdFlushQueues = cli.Command{ | |||
subcmdFlushQueues = &cli.Command{ | |||
Name: "flush-queues", | |||
Usage: "Flush queues in the running process", | |||
Action: runFlushQueues, | |||
Flags: []cli.Flag{ | |||
cli.DurationFlag{ | |||
&cli.DurationFlag{ | |||
Name: "timeout", | |||
Value: 60 * time.Second, | |||
Usage: "Timeout for the flushing process", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "non-blocking", | |||
Usage: "Set to true to not wait for flush to complete before returning", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
}, | |||
} | |||
subCmdProcesses = cli.Command{ | |||
subCmdProcesses = &cli.Command{ | |||
Name: "processes", | |||
Usage: "Display running processes within the current process", | |||
Action: runProcesses, | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "flat", | |||
Usage: "Show processes as flat table rather than as tree", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "no-system", | |||
Usage: "Do not show system processes", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "stacktraces", | |||
Usage: "Show stacktraces", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "json", | |||
Usage: "Output as json", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "cancel", | |||
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/private" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
var ( | |||
defaultLoggingFlags = []cli.Flag{ | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "logger", | |||
Usage: `Logger name - will default to "default"`, | |||
}, cli.StringFlag{ | |||
}, | |||
&cli.StringFlag{ | |||
Name: "writer", | |||
Usage: "Name of the log writer - will default to mode", | |||
}, cli.StringFlag{ | |||
}, | |||
&cli.StringFlag{ | |||
Name: "level", | |||
Usage: "Logging level for the new logger", | |||
}, cli.StringFlag{ | |||
Name: "stacktrace-level, L", | |||
Usage: "Stacktrace logging level", | |||
}, cli.StringFlag{ | |||
Name: "flags, F", | |||
Usage: "Flags for the logger", | |||
}, cli.StringFlag{ | |||
Name: "expression, e", | |||
Usage: "Matching expression for the logger", | |||
}, cli.StringFlag{ | |||
Name: "prefix, p", | |||
Usage: "Prefix for the logger", | |||
}, cli.BoolFlag{ | |||
}, | |||
&cli.StringFlag{ | |||
Name: "stacktrace-level", | |||
Aliases: []string{"L"}, | |||
Usage: "Stacktrace logging level", | |||
}, | |||
&cli.StringFlag{ | |||
Name: "flags", | |||
Aliases: []string{"F"}, | |||
Usage: "Flags for the logger", | |||
}, | |||
&cli.StringFlag{ | |||
Name: "expression", | |||
Aliases: []string{"e"}, | |||
Usage: "Matching expression for the logger", | |||
}, | |||
&cli.StringFlag{ | |||
Name: "prefix", | |||
Aliases: []string{"p"}, | |||
Usage: "Prefix for the logger", | |||
}, | |||
&cli.BoolFlag{ | |||
Name: "color", | |||
Usage: "Use color in the logs", | |||
}, cli.BoolFlag{ | |||
}, | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
} | |||
subcmdLogging = cli.Command{ | |||
subcmdLogging = &cli.Command{ | |||
Name: "logging", | |||
Usage: "Adjust logging commands", | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
{ | |||
Name: "pause", | |||
Usage: "Pause logging (Gitea will buffer logs up to a certain point and will drop them after that point)", | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
}, | |||
@@ -61,7 +73,7 @@ var ( | |||
Name: "resume", | |||
Usage: "Resume logging", | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
}, | |||
@@ -70,7 +82,7 @@ var ( | |||
Name: "release-and-reopen", | |||
Usage: "Cause Gitea to release and re-open files used for logging", | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
}, | |||
@@ -80,9 +92,9 @@ var ( | |||
Usage: "Remove a logger", | |||
ArgsUsage: "[name] Name of logger to remove", | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, cli.StringFlag{ | |||
}, &cli.StringFlag{ | |||
Name: "logger", | |||
Usage: `Logger name - will default to "default"`, | |||
}, | |||
@@ -91,32 +103,45 @@ var ( | |||
}, { | |||
Name: "add", | |||
Usage: "Add a logger", | |||
Subcommands: []cli.Command{ | |||
Subcommands: []*cli.Command{ | |||
{ | |||
Name: "file", | |||
Usage: "Add a file logger", | |||
Flags: append(defaultLoggingFlags, []cli.Flag{ | |||
cli.StringFlag{ | |||
Name: "filename, f", | |||
Usage: "Filename for the logger - this must be set.", | |||
}, cli.BoolTFlag{ | |||
Name: "rotate, r", | |||
Usage: "Rotate logs", | |||
}, cli.Int64Flag{ | |||
Name: "max-size, s", | |||
Usage: "Maximum size in bytes before rotation", | |||
}, cli.BoolTFlag{ | |||
Name: "daily, d", | |||
Usage: "Rotate logs daily", | |||
}, cli.IntFlag{ | |||
Name: "max-days, D", | |||
Usage: "Maximum number of daily logs to keep", | |||
}, cli.BoolTFlag{ | |||
Name: "compress, z", | |||
Usage: "Compress rotated logs", | |||
}, cli.IntFlag{ | |||
Name: "compression-level, Z", | |||
Usage: "Compression level to use", | |||
&cli.StringFlag{ | |||
Name: "filename", | |||
Aliases: []string{"f"}, | |||
Usage: "Filename for the logger - this must be set.", | |||
}, | |||
&cli.BoolFlag{ | |||
Name: "rotate", | |||
Aliases: []string{"r"}, | |||
Usage: "Rotate logs", | |||
}, | |||
&cli.Int64Flag{ | |||
Name: "max-size", | |||
Aliases: []string{"s"}, | |||
Usage: "Maximum size in bytes before rotation", | |||
}, | |||
&cli.BoolFlag{ | |||
Name: "daily", | |||
Aliases: []string{"d"}, | |||
Usage: "Rotate logs daily", | |||
}, | |||
&cli.IntFlag{ | |||
Name: "max-days", | |||
Aliases: []string{"D"}, | |||
Usage: "Maximum number of daily logs to keep", | |||
}, | |||
&cli.BoolFlag{ | |||
Name: "compress", | |||
Aliases: []string{"z"}, | |||
Usage: "Compress rotated logs", | |||
}, | |||
&cli.IntFlag{ | |||
Name: "compression-level", | |||
Aliases: []string{"Z"}, | |||
Usage: "Compression level to use", | |||
}, | |||
}...), | |||
Action: runAddFileLogger, | |||
@@ -124,18 +149,25 @@ var ( | |||
Name: "conn", | |||
Usage: "Add a net conn logger", | |||
Flags: append(defaultLoggingFlags, []cli.Flag{ | |||
cli.BoolFlag{ | |||
Name: "reconnect-on-message, R", | |||
Usage: "Reconnect to host for every message", | |||
}, cli.BoolFlag{ | |||
Name: "reconnect, r", | |||
Usage: "Reconnect to host when connection is dropped", | |||
}, cli.StringFlag{ | |||
Name: "protocol, P", | |||
Usage: "Set protocol to use: tcp, unix, or udp (defaults to tcp)", | |||
}, cli.StringFlag{ | |||
Name: "address, a", | |||
Usage: "Host address and port to connect to (defaults to :7020)", | |||
&cli.BoolFlag{ | |||
Name: "reconnect-on-message", | |||
Aliases: []string{"R"}, | |||
Usage: "Reconnect to host for every message", | |||
}, | |||
&cli.BoolFlag{ | |||
Name: "reconnect", | |||
Aliases: []string{"r"}, | |||
Usage: "Reconnect to host when connection is dropped", | |||
}, | |||
&cli.StringFlag{ | |||
Name: "protocol", | |||
Aliases: []string{"P"}, | |||
Usage: "Set protocol to use: tcp, unix, or udp (defaults to tcp)", | |||
}, | |||
&cli.StringFlag{ | |||
Name: "address", | |||
Aliases: []string{"a"}, | |||
Usage: "Host address and port to connect to (defaults to :7020)", | |||
}, | |||
}...), | |||
Action: runAddConnLogger, | |||
@@ -145,9 +177,10 @@ var ( | |||
Name: "log-sql", | |||
Usage: "Set LogSQL", | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, cli.BoolFlag{ | |||
}, | |||
&cli.BoolFlag{ | |||
Name: "off", | |||
Usage: "Switch off SQL logging", | |||
}, |
@@ -11,11 +11,11 @@ import ( | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/setting" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
// CmdMigrate represents the available migrate sub-command. | |||
var CmdMigrate = cli.Command{ | |||
var CmdMigrate = &cli.Command{ | |||
Name: "migrate", | |||
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.", |
@@ -20,70 +20,73 @@ import ( | |||
"code.gitea.io/gitea/modules/setting" | |||
"code.gitea.io/gitea/modules/storage" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
// CmdMigrateStorage represents the available migrate storage sub-command. | |||
var CmdMigrateStorage = cli.Command{ | |||
var CmdMigrateStorage = &cli.Command{ | |||
Name: "migrate-storage", | |||
Usage: "Migrate the storage", | |||
Description: "Copies stored files from storage configured in app.ini to parameter-configured storage", | |||
Action: runMigrateStorage, | |||
Flags: []cli.Flag{ | |||
cli.StringFlag{ | |||
Name: "type, t", | |||
Value: "", | |||
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log'", | |||
&cli.StringFlag{ | |||
Name: "type", | |||
Aliases: []string{"t"}, | |||
Value: "", | |||
Usage: "Type of stored files to copy. Allowed types: 'attachments', 'lfs', 'avatars', 'repo-avatars', 'repo-archivers', 'packages', 'actions-log'", | |||
}, | |||
cli.StringFlag{ | |||
Name: "storage, s", | |||
Value: "", | |||
Usage: "New storage type: local (default) or minio", | |||
&cli.StringFlag{ | |||
Name: "storage", | |||
Aliases: []string{"s"}, | |||
Value: "", | |||
Usage: "New storage type: local (default) or minio", | |||
}, | |||
cli.StringFlag{ | |||
Name: "path, p", | |||
Value: "", | |||
Usage: "New storage placement if store is local (leave blank for default)", | |||
&cli.StringFlag{ | |||
Name: "path", | |||
Aliases: []string{"p"}, | |||
Value: "", | |||
Usage: "New storage placement if store is local (leave blank for default)", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "minio-endpoint", | |||
Value: "", | |||
Usage: "Minio storage endpoint", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "minio-access-key-id", | |||
Value: "", | |||
Usage: "Minio storage accessKeyID", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "minio-secret-access-key", | |||
Value: "", | |||
Usage: "Minio storage secretAccessKey", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "minio-bucket", | |||
Value: "", | |||
Usage: "Minio storage bucket", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "minio-location", | |||
Value: "", | |||
Usage: "Minio storage location to create bucket", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "minio-base-path", | |||
Value: "", | |||
Usage: "Minio storage base path on the bucket", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "minio-use-ssl", | |||
Usage: "Enable SSL for minio", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "minio-insecure-skip-verify", | |||
Usage: "Skip SSL verification", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "minio-checksum-algorithm", | |||
Value: "", | |||
Usage: "Minio checksum algorithm (default/md5)", |
@@ -9,38 +9,39 @@ import ( | |||
"code.gitea.io/gitea/modules/private" | |||
"code.gitea.io/gitea/modules/setting" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
// CmdRestoreRepository represents the available restore a repository sub-command. | |||
var CmdRestoreRepository = cli.Command{ | |||
var CmdRestoreRepository = &cli.Command{ | |||
Name: "restore-repo", | |||
Usage: "Restore the repository from disk", | |||
Description: "This is a command for restoring the repository data.", | |||
Action: runRestoreRepository, | |||
Flags: []cli.Flag{ | |||
cli.StringFlag{ | |||
Name: "repo_dir, r", | |||
Value: "./data", | |||
Usage: "Repository dir path to restore from", | |||
&cli.StringFlag{ | |||
Name: "repo_dir", | |||
Aliases: []string{"r"}, | |||
Value: "./data", | |||
Usage: "Repository dir path to restore from", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "owner_name", | |||
Value: "", | |||
Usage: "Restore destination owner name", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "repo_name", | |||
Value: "", | |||
Usage: "Restore destination repository name", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "units", | |||
Value: "", | |||
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.`, | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "validation", | |||
Usage: "Sanity check the content of the files before trying to load them", | |||
}, |
@@ -32,7 +32,7 @@ import ( | |||
"github.com/golang-jwt/jwt/v5" | |||
"github.com/kballard/go-shellquote" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
const ( | |||
@@ -40,17 +40,17 @@ const ( | |||
) | |||
// CmdServ represents the available serv sub-command. | |||
var CmdServ = cli.Command{ | |||
var CmdServ = &cli.Command{ | |||
Name: "serv", | |||
Usage: "This command should only be called by SSH shell", | |||
Description: "Serv provides access auth for repositories", | |||
Before: PrepareConsoleLoggerLevel(log.FATAL), | |||
Action: runServ, | |||
Flags: []cli.Flag{ | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "enable-pprof", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "debug", | |||
}, | |||
}, | |||
@@ -119,7 +119,7 @@ func fail(ctx context.Context, userMessage, logMsgFmt string, args ...any) error | |||
} | |||
_ = private.SSHLog(ctx, true, logMsg) | |||
} | |||
return cli.NewExitError("", 1) | |||
return cli.Exit("", 1) | |||
} | |||
// 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) | |||
} | |||
if extra.HasError() { | |||
return cli.NewExitError(extra.Error, 1) | |||
return cli.Exit(extra.Error, 1) | |||
} | |||
return nil | |||
} | |||
@@ -147,20 +147,20 @@ func runServ(c *cli.Context) error { | |||
return nil | |||
} | |||
if len(c.Args()) < 1 { | |||
if c.NArg() < 1 { | |||
if err := cli.ShowSubcommandHelp(c); err != nil { | |||
fmt.Printf("error showing subcommand help: %v\n", err) | |||
} | |||
return nil | |||
} | |||
keys := strings.Split(c.Args()[0], "-") | |||
keys := strings.Split(c.Args().First(), "-") | |||
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) | |||
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") |
@@ -23,14 +23,14 @@ import ( | |||
"code.gitea.io/gitea/routers/install" | |||
"github.com/felixge/fgprof" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
// PIDFile could be set from build tag | |||
var PIDFile = "/run/gitea.pid" | |||
// CmdWeb represents the available web sub-command. | |||
var CmdWeb = cli.Command{ | |||
var CmdWeb = &cli.Command{ | |||
Name: "web", | |||
Usage: "Start Gitea web server", | |||
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), | |||
Action: runWeb, | |||
Flags: []cli.Flag{ | |||
cli.StringFlag{ | |||
Name: "port, p", | |||
Value: "3000", | |||
Usage: "Temporary port number to prevent conflict", | |||
&cli.StringFlag{ | |||
Name: "port", | |||
Aliases: []string{"p"}, | |||
Value: "3000", | |||
Usage: "Temporary port number to prevent conflict", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "install-port", | |||
Value: "3000", | |||
Usage: "Temporary port number to run the install page on to prevent conflict", | |||
}, | |||
cli.StringFlag{ | |||
Name: "pid, P", | |||
Value: PIDFile, | |||
Usage: "Custom pid file path", | |||
&cli.StringFlag{ | |||
Name: "pid", | |||
Aliases: []string{"P"}, | |||
Value: PIDFile, | |||
Usage: "Custom pid file path", | |||
}, | |||
cli.BoolFlag{ | |||
Name: "quiet, q", | |||
Usage: "Only display Fatal logging errors until logging is set-up", | |||
&cli.BoolFlag{ | |||
Name: "quiet", | |||
Aliases: []string{"q"}, | |||
Usage: "Only display Fatal logging errors until logging is set-up", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "verbose", | |||
Usage: "Set initial logging to TRACE level until logging is properly set-up", | |||
}, |
@@ -18,7 +18,7 @@ import ( | |||
"syscall" | |||
"github.com/google/go-github/v53/github" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
"gopkg.in/yaml.v3" | |||
) | |||
@@ -32,55 +32,55 @@ func main() { | |||
app.ArgsUsage = "<PR-to-backport>" | |||
app.Flags = []cli.Flag{ | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "version", | |||
Usage: "Version branch to backport on to", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "upstream", | |||
Value: "origin", | |||
Usage: "Upstream remote for the Gitea upstream", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "release-branch", | |||
Value: "", | |||
Usage: "Release branch to backport on. Will default to release/<version>", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "cherry-pick", | |||
Usage: "SHA to cherry-pick as backport", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "backport-branch", | |||
Usage: "Backport branch to backport on to (default: backport-<pr>-<version>", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "remote", | |||
Value: "", | |||
Usage: "Remote for your fork of the Gitea upstream", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "fork-user", | |||
Value: "", | |||
Usage: "Forked user name on Github", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "no-fetch", | |||
Usage: "Set this flag to prevent fetch of remote branches", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "no-amend-message", | |||
Usage: "Set this flag to prevent automatic amendment of the commit message", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "no-push", | |||
Usage: "Set this flag to prevent pushing the backport up to your fork", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "no-xdg-open", | |||
Usage: "Set this flag to not use xdg-open to open the PR URL", | |||
}, | |||
cli.BoolFlag{ | |||
&cli.BoolFlag{ | |||
Name: "continue", | |||
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) | |||
args := c.Args() | |||
args := c.Args().Slice() | |||
if len(args) == 0 && pr == "" { | |||
return fmt.Errorf("no PR number provided\nProvide a PR number to backport") | |||
} else if len(args) != 1 && pr == "" { |
@@ -9,7 +9,7 @@ import ( | |||
"code.gitea.io/gitea/modules/log" | |||
"code.gitea.io/gitea/modules/setting" | |||
"github.com/urfave/cli" | |||
"github.com/urfave/cli/v2" | |||
) | |||
func main() { | |||
@@ -46,22 +46,22 @@ func main() { | |||
and "GITEA__LOG_0x2E_CONSOLE__STDERR=false". Other examples can be found | |||
on the configuration cheat sheet.` | |||
app.Flags = []cli.Flag{ | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "custom-path, C", | |||
Value: setting.CustomPath, | |||
Usage: "Custom path file path", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "config, c", | |||
Value: setting.CustomConf, | |||
Usage: "Custom configuration file path", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "work-path, w", | |||
Value: setting.AppWorkPath, | |||
Usage: "Set the gitea working path", | |||
}, | |||
cli.StringFlag{ | |||
&cli.StringFlag{ | |||
Name: "out, o", | |||
Value: "", | |||
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 | |||
;; 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. | |||
;; - _`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) | |||
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. | |||
- _`AppWorkPath`_: This refers to "working path" of the `gitea` binary. It is determined by using the first set thing in the following hierarchy: |
@@ -98,7 +98,7 @@ require ( | |||
github.com/syndtr/goleveldb v1.0.0 | |||
github.com/tstranex/u2f v1.0.0 | |||
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/xeipuuv/gojsonschema v1.2.0 | |||
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/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 // 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 | |||
go.etcd.io/bbolt v1.3.7 // indirect | |||
go.mongodb.org/mongo-driver v1.12.0 // indirect |
@@ -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/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU= | |||
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/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= | |||
@@ -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/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.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk= | |||
github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA= | |||
github.com/urfave/cli/v2 v2.25.7 h1:VAzn5oq403l5pHjc4OhD54+XGO9cdKVL/7lDjF+iKUs= | |||
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/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= | |||
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/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/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/go.mod h1:b/AvD03P0KHj4yuihb+VtLD6bYYgsy0zqBzPCRjkCNs= | |||
github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= |
@@ -2,8 +2,7 @@ | |||
// Copyright 2016 The Gitea Authors. All rights reserved. | |||
// SPDX-License-Identifier: MIT | |||
// Gitea (git with a cup of tea) is a painless self-hosted Git Service. | |||
package main // import "code.gitea.io/gitea" | |||
package main | |||
import ( | |||
"fmt" | |||
@@ -22,17 +21,13 @@ import ( | |||
_ "code.gitea.io/gitea/modules/markup/csv" | |||
_ "code.gitea.io/gitea/modules/markup/markdown" | |||
_ "code.gitea.io/gitea/modules/markup/orgmode" | |||
"github.com/urfave/cli" | |||
) | |||
// these flags will be set by the build flags | |||
var ( | |||
// Version holds the current Gitea version | |||
Version = "development" | |||
// Tags holds the build tags used | |||
Tags = "" | |||
// MakeVersion holds the current Make version if built with make | |||
MakeVersion = "" | |||
Version = "development" // program version for this build | |||
Tags = "" // the Golang build tags | |||
MakeVersion = "" // "make" program version if built with make | |||
) | |||
func init() { | |||
@@ -41,110 +36,12 @@ func init() { | |||
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() { | |||
app := cli.NewApp() | |||
app := cmd.NewMainApp() | |||
app.Name = "Gitea" | |||
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.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) | |||
if err != nil { | |||
@@ -154,45 +51,6 @@ func main() { | |||
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 { | |||
version := runtime.Version() | |||
if len(MakeVersion) > 0 { |
@@ -5,17 +5,15 @@ package integration | |||
import ( | |||
"bytes" | |||
"flag" | |||
"io" | |||
"net/url" | |||
"os" | |||
"testing" | |||
"code.gitea.io/gitea/cmd" | |||
"code.gitea.io/gitea/modules/setting" | |||
"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) { | |||
@@ -38,26 +36,18 @@ func Test_CmdKeys(t *testing.T) { | |||
} | |||
for _, tt := range tests { | |||
t.Run(tt.name, func(t *testing.T) { | |||
realStdout := os.Stdout // Backup Stdout | |||
r, w, _ := os.Pipe() | |||
os.Stdout = w | |||
set := flag.NewFlagSet("keys", 0) | |||
_ = set.Parse(tt.args) | |||
context := cli.NewContext(&cli.App{Writer: os.Stdout}, set, nil) | |||
err := cmd.CmdKeys.Run(context) | |||
if (err != nil) != tt.wantErr { | |||
t.Errorf("CmdKeys.Run() error = %v, wantErr %v", err, tt.wantErr) | |||
} | |||
w.Close() | |||
var buf bytes.Buffer | |||
io.Copy(&buf, r) | |||
commandOutput := buf.String() | |||
if tt.expectedOutput != commandOutput { | |||
t.Errorf("expectedOutput: %#v, commandOutput: %#v", tt.expectedOutput, commandOutput) | |||
out := new(bytes.Buffer) | |||
app := cli.NewApp() | |||
app.Writer = out | |||
app.Commands = []*cli.Command{cmd.CmdKeys} | |||
cmd.CmdKeys.HideHelp = true | |||
err := app.Run(append([]string{"prog"}, tt.args...)) | |||
if tt.wantErr { | |||
assert.Error(t, err) | |||
} else { | |||
assert.NoError(t, err) | |||
} | |||
// Restore stdout | |||
os.Stdout = realStdout | |||
assert.Equal(t, tt.expectedOutput, out.String()) | |||
}) | |||
} | |||
}) |