* General refactor of the cmd package * Address breakage in runCreateUser * Place "common" functions into cmd.gotags/v1.21.12.1
| @@ -20,9 +20,7 @@ var ( | |||||
| // CmdAdmin represents the available admin sub-command. | // CmdAdmin represents the available admin sub-command. | ||||
| CmdAdmin = cli.Command{ | CmdAdmin = cli.Command{ | ||||
| Name: "admin", | Name: "admin", | ||||
| Usage: "Perform admin operations on command line", | |||||
| Description: `Allow using internal logic of Gitea without hacking into the source code | |||||
| to make automatic initialization process more smoothly`, | |||||
| Usage: "Command line interface to perform common administrative operations", | |||||
| Subcommands: []cli.Command{ | Subcommands: []cli.Command{ | ||||
| subcmdCreateUser, | subcmdCreateUser, | ||||
| subcmdChangePassword, | subcmdChangePassword, | ||||
| @@ -37,17 +35,14 @@ to make automatic initialization process more smoothly`, | |||||
| Flags: []cli.Flag{ | Flags: []cli.Flag{ | ||||
| cli.StringFlag{ | cli.StringFlag{ | ||||
| Name: "name", | Name: "name", | ||||
| Value: "", | |||||
| Usage: "Username", | Usage: "Username", | ||||
| }, | }, | ||||
| cli.StringFlag{ | cli.StringFlag{ | ||||
| Name: "password", | Name: "password", | ||||
| Value: "", | |||||
| Usage: "User password", | Usage: "User password", | ||||
| }, | }, | ||||
| cli.StringFlag{ | cli.StringFlag{ | ||||
| Name: "email", | Name: "email", | ||||
| Value: "", | |||||
| Usage: "User email address", | Usage: "User email address", | ||||
| }, | }, | ||||
| cli.BoolFlag{ | cli.BoolFlag{ | ||||
| @@ -88,56 +83,42 @@ to make automatic initialization process more smoothly`, | |||||
| ) | ) | ||||
| func runChangePassword(c *cli.Context) error { | func runChangePassword(c *cli.Context) error { | ||||
| if !c.IsSet("password") { | |||||
| return fmt.Errorf("Password is not specified") | |||||
| } else if !c.IsSet("username") { | |||||
| return fmt.Errorf("Username is not specified") | |||||
| if err := argsSet(c, "username", "password"); err != nil { | |||||
| return err | |||||
| } | } | ||||
| setting.NewContext() | |||||
| models.LoadConfigs() | |||||
| setting.NewXORMLogService(false) | |||||
| if err := models.SetEngine(); err != nil { | |||||
| return fmt.Errorf("models.SetEngine: %v", err) | |||||
| if err := initDB(); err != nil { | |||||
| return err | |||||
| } | } | ||||
| uname := c.String("username") | uname := c.String("username") | ||||
| user, err := models.GetUserByName(uname) | user, err := models.GetUserByName(uname) | ||||
| if err != nil { | if err != nil { | ||||
| return fmt.Errorf("%v", err) | |||||
| return err | |||||
| } | } | ||||
| if user.Salt, err = models.GetUserSalt(); err != nil { | if user.Salt, err = models.GetUserSalt(); err != nil { | ||||
| return fmt.Errorf("%v", err) | |||||
| return err | |||||
| } | } | ||||
| user.HashPassword(c.String("password")) | user.HashPassword(c.String("password")) | ||||
| if err := models.UpdateUserCols(user, "passwd", "salt"); err != nil { | if err := models.UpdateUserCols(user, "passwd", "salt"); err != nil { | ||||
| return fmt.Errorf("%v", err) | |||||
| return err | |||||
| } | } | ||||
| fmt.Printf("User '%s' password has been successfully updated!\n", uname) | |||||
| fmt.Printf("%s's password has been successfully updated!\n", user.Name) | |||||
| return nil | return nil | ||||
| } | } | ||||
| func runCreateUser(c *cli.Context) error { | func runCreateUser(c *cli.Context) error { | ||||
| if !c.IsSet("name") { | |||||
| return fmt.Errorf("Username is not specified") | |||||
| } else if !c.IsSet("password") { | |||||
| return fmt.Errorf("Password is not specified") | |||||
| } else if !c.IsSet("email") { | |||||
| return fmt.Errorf("Email is not specified") | |||||
| if err := argsSet(c, "name", "password", "email"); err != nil { | |||||
| return err | |||||
| } | } | ||||
| if c.IsSet("config") { | if c.IsSet("config") { | ||||
| setting.CustomConf = c.String("config") | setting.CustomConf = c.String("config") | ||||
| } | } | ||||
| setting.NewContext() | |||||
| models.LoadConfigs() | |||||
| setting.NewXORMLogService(false) | |||||
| if err := models.SetEngine(); err != nil { | |||||
| return fmt.Errorf("models.SetEngine: %v", err) | |||||
| if err := initDB(); err != nil { | |||||
| return err | |||||
| } | } | ||||
| if err := models.CreateUser(&models.User{ | if err := models.CreateUser(&models.User{ | ||||
| @@ -155,13 +136,8 @@ func runCreateUser(c *cli.Context) error { | |||||
| } | } | ||||
| func runRepoSyncReleases(c *cli.Context) error { | func runRepoSyncReleases(c *cli.Context) error { | ||||
| setting.NewContext() | |||||
| models.LoadConfigs() | |||||
| setting.NewXORMLogService(false) | |||||
| if err := models.SetEngine(); err != nil { | |||||
| return fmt.Errorf("models.SetEngine: %v", err) | |||||
| if err := initDB(); err != nil { | |||||
| return err | |||||
| } | } | ||||
| log.Trace("Synchronizing repository releases (this may take a while)") | log.Trace("Synchronizing repository releases (this may take a while)") | ||||
| @@ -172,8 +148,7 @@ func runRepoSyncReleases(c *cli.Context) error { | |||||
| Private: true, | Private: true, | ||||
| }) | }) | ||||
| if err != nil { | if err != nil { | ||||
| log.Fatal(4, "SearchRepositoryByName: %v", err) | |||||
| return err | |||||
| return fmt.Errorf("SearchRepositoryByName: %v", err) | |||||
| } | } | ||||
| if len(repos) == 0 { | if len(repos) == 0 { | ||||
| break | break | ||||
| @@ -187,11 +162,7 @@ func runRepoSyncReleases(c *cli.Context) error { | |||||
| continue | continue | ||||
| } | } | ||||
| oldnum, err := models.GetReleaseCountByRepoID(repo.ID, | |||||
| models.FindReleasesOptions{ | |||||
| IncludeDrafts: false, | |||||
| IncludeTags: true, | |||||
| }) | |||||
| oldnum, err := getReleaseCount(repo.ID) | |||||
| if err != nil { | if err != nil { | ||||
| log.Warn(" GetReleaseCountByRepoID: %v", err) | log.Warn(" GetReleaseCountByRepoID: %v", err) | ||||
| } | } | ||||
| @@ -202,11 +173,7 @@ func runRepoSyncReleases(c *cli.Context) error { | |||||
| continue | continue | ||||
| } | } | ||||
| count, err = models.GetReleaseCountByRepoID(repo.ID, | |||||
| models.FindReleasesOptions{ | |||||
| IncludeDrafts: false, | |||||
| IncludeTags: true, | |||||
| }) | |||||
| count, err = getReleaseCount(repo.ID) | |||||
| if err != nil { | if err != nil { | ||||
| log.Warn(" GetReleaseCountByRepoID: %v", err) | log.Warn(" GetReleaseCountByRepoID: %v", err) | ||||
| continue | continue | ||||
| @@ -219,3 +186,12 @@ func runRepoSyncReleases(c *cli.Context) error { | |||||
| return nil | return nil | ||||
| } | } | ||||
| func getReleaseCount(id int64) (int64, error) { | |||||
| return models.GetReleaseCountByRepoID( | |||||
| id, | |||||
| models.FindReleasesOptions{ | |||||
| IncludeTags: true, | |||||
| }, | |||||
| ) | |||||
| } | |||||
| @@ -90,16 +90,16 @@ func pemBlockForKey(priv interface{}) *pem.Block { | |||||
| } | } | ||||
| } | } | ||||
| func runCert(ctx *cli.Context) error { | |||||
| if len(ctx.String("host")) == 0 { | |||||
| log.Fatal("Missing required --host parameter") | |||||
| func runCert(c *cli.Context) error { | |||||
| if err := argsSet(c, "host"); err != nil { | |||||
| return err | |||||
| } | } | ||||
| var priv interface{} | var priv interface{} | ||||
| var err error | var err error | ||||
| switch ctx.String("ecdsa-curve") { | |||||
| switch c.String("ecdsa-curve") { | |||||
| case "": | case "": | ||||
| priv, err = rsa.GenerateKey(rand.Reader, ctx.Int("rsa-bits")) | |||||
| priv, err = rsa.GenerateKey(rand.Reader, c.Int("rsa-bits")) | |||||
| case "P224": | case "P224": | ||||
| priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) | priv, err = ecdsa.GenerateKey(elliptic.P224(), rand.Reader) | ||||
| case "P256": | case "P256": | ||||
| @@ -109,23 +109,23 @@ func runCert(ctx *cli.Context) error { | |||||
| case "P521": | case "P521": | ||||
| priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) | priv, err = ecdsa.GenerateKey(elliptic.P521(), rand.Reader) | ||||
| default: | default: | ||||
| log.Fatalf("Unrecognized elliptic curve: %q", ctx.String("ecdsa-curve")) | |||||
| log.Fatalf("Unrecognized elliptic curve: %q", c.String("ecdsa-curve")) | |||||
| } | } | ||||
| if err != nil { | if err != nil { | ||||
| log.Fatalf("Failed to generate private key: %v", err) | log.Fatalf("Failed to generate private key: %v", err) | ||||
| } | } | ||||
| var notBefore time.Time | var notBefore time.Time | ||||
| if len(ctx.String("start-date")) == 0 { | |||||
| notBefore = time.Now() | |||||
| } else { | |||||
| notBefore, err = time.Parse("Jan 2 15:04:05 2006", ctx.String("start-date")) | |||||
| if startDate := c.String("start-date"); startDate != "" { | |||||
| notBefore, err = time.Parse("Jan 2 15:04:05 2006", startDate) | |||||
| if err != nil { | if err != nil { | ||||
| log.Fatalf("Failed to parse creation date: %v", err) | log.Fatalf("Failed to parse creation date: %v", err) | ||||
| } | } | ||||
| } else { | |||||
| notBefore = time.Now() | |||||
| } | } | ||||
| notAfter := notBefore.Add(ctx.Duration("duration")) | |||||
| notAfter := notBefore.Add(c.Duration("duration")) | |||||
| serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) | serialNumberLimit := new(big.Int).Lsh(big.NewInt(1), 128) | ||||
| serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) | serialNumber, err := rand.Int(rand.Reader, serialNumberLimit) | ||||
| @@ -147,7 +147,7 @@ func runCert(ctx *cli.Context) error { | |||||
| BasicConstraintsValid: true, | BasicConstraintsValid: true, | ||||
| } | } | ||||
| hosts := strings.Split(ctx.String("host"), ",") | |||||
| hosts := strings.Split(c.String("host"), ",") | |||||
| for _, h := range hosts { | for _, h := range hosts { | ||||
| if ip := net.ParseIP(h); ip != nil { | if ip := net.ParseIP(h); ip != nil { | ||||
| template.IPAddresses = append(template.IPAddresses, ip) | template.IPAddresses = append(template.IPAddresses, ip) | ||||
| @@ -156,7 +156,7 @@ func runCert(ctx *cli.Context) error { | |||||
| } | } | ||||
| } | } | ||||
| if ctx.Bool("ca") { | |||||
| if c.Bool("ca") { | |||||
| template.IsCA = true | template.IsCA = true | ||||
| template.KeyUsage |= x509.KeyUsageCertSign | template.KeyUsage |= x509.KeyUsageCertSign | ||||
| } | } | ||||
| @@ -0,0 +1,38 @@ | |||||
| // Copyright 2018 The Gitea Authors. All rights reserved. | |||||
| // Use of this source code is governed by a MIT-style | |||||
| // license that can be found in the LICENSE file. | |||||
| // Package cmd provides subcommands to the gitea binary - such as "web" or | |||||
| // "admin". | |||||
| package cmd | |||||
| import ( | |||||
| "errors" | |||||
| "fmt" | |||||
| "code.gitea.io/gitea/models" | |||||
| "code.gitea.io/gitea/modules/setting" | |||||
| "github.com/urfave/cli" | |||||
| ) | |||||
| // argsSet checks that all the required arguments are set. args is a list of | |||||
| // arguments that must be set in the passed Context. | |||||
| func argsSet(c *cli.Context, args ...string) error { | |||||
| for _, a := range args { | |||||
| if !c.IsSet(a) { | |||||
| return errors.New(a + " is not set") | |||||
| } | |||||
| } | |||||
| return nil | |||||
| } | |||||
| func initDB() error { | |||||
| setting.NewContext() | |||||
| models.LoadConfigs() | |||||
| setting.NewXORMLogService(false) | |||||
| if err := models.SetEngine(); err != nil { | |||||
| return fmt.Errorf("models.SetEngine: %v", err) | |||||
| } | |||||
| return nil | |||||
| } | |||||
| @@ -68,19 +68,19 @@ func runDump(ctx *cli.Context) error { | |||||
| if _, err := os.Stat(tmpDir); os.IsNotExist(err) { | if _, err := os.Stat(tmpDir); os.IsNotExist(err) { | ||||
| log.Fatalf("Path does not exist: %s", tmpDir) | log.Fatalf("Path does not exist: %s", tmpDir) | ||||
| } | } | ||||
| TmpWorkDir, err := ioutil.TempDir(tmpDir, "gitea-dump-") | |||||
| tmpWorkDir, err := ioutil.TempDir(tmpDir, "gitea-dump-") | |||||
| if err != nil { | if err != nil { | ||||
| log.Fatalf("Failed to create tmp work directory: %v", err) | log.Fatalf("Failed to create tmp work directory: %v", err) | ||||
| } | } | ||||
| log.Printf("Creating tmp work dir: %s", TmpWorkDir) | |||||
| log.Printf("Creating tmp work dir: %s", tmpWorkDir) | |||||
| // work-around #1103 | // work-around #1103 | ||||
| if os.Getenv("TMPDIR") == "" { | if os.Getenv("TMPDIR") == "" { | ||||
| os.Setenv("TMPDIR", TmpWorkDir) | |||||
| os.Setenv("TMPDIR", tmpWorkDir) | |||||
| } | } | ||||
| reposDump := path.Join(TmpWorkDir, "gitea-repo.zip") | |||||
| dbDump := path.Join(TmpWorkDir, "gitea-db.sql") | |||||
| reposDump := path.Join(tmpWorkDir, "gitea-repo.zip") | |||||
| dbDump := path.Join(tmpWorkDir, "gitea-db.sql") | |||||
| log.Printf("Dumping local repositories...%s", setting.RepoRootPath) | log.Printf("Dumping local repositories...%s", setting.RepoRootPath) | ||||
| zip.Verbose = ctx.Bool("verbose") | zip.Verbose = ctx.Bool("verbose") | ||||
| @@ -146,10 +146,10 @@ func runDump(ctx *cli.Context) error { | |||||
| log.Printf("Can't change file access permissions mask to 0600: %v", err) | log.Printf("Can't change file access permissions mask to 0600: %v", err) | ||||
| } | } | ||||
| log.Printf("Removing tmp work dir: %s", TmpWorkDir) | |||||
| log.Printf("Removing tmp work dir: %s", tmpWorkDir) | |||||
| if err := os.RemoveAll(TmpWorkDir); err != nil { | |||||
| log.Fatalf("Failed to remove %s: %v", TmpWorkDir, err) | |||||
| if err := os.RemoveAll(tmpWorkDir); err != nil { | |||||
| log.Fatalf("Failed to remove %s: %v", tmpWorkDir, err) | |||||
| } | } | ||||
| log.Printf("Finish dumping in file %s", fileName) | log.Printf("Finish dumping in file %s", fileName) | ||||
| @@ -37,7 +37,7 @@ var ( | |||||
| }, | }, | ||||
| Subcommands: []cli.Command{ | Subcommands: []cli.Command{ | ||||
| subcmdHookPreReceive, | subcmdHookPreReceive, | ||||
| subcmdHookUpadte, | |||||
| subcmdHookUpdate, | |||||
| subcmdHookPostReceive, | subcmdHookPostReceive, | ||||
| }, | }, | ||||
| } | } | ||||
| @@ -48,7 +48,7 @@ var ( | |||||
| Description: "This command should only be called by Git", | Description: "This command should only be called by Git", | ||||
| Action: runHookPreReceive, | Action: runHookPreReceive, | ||||
| } | } | ||||
| subcmdHookUpadte = cli.Command{ | |||||
| subcmdHookUpdate = cli.Command{ | |||||
| Name: "update", | Name: "update", | ||||
| Usage: "Delegate update Git hook", | Usage: "Delegate update Git hook", | ||||
| Description: "This command should only be called by Git", | Description: "This command should only be called by Git", | ||||
| @@ -121,11 +121,9 @@ func runWeb(ctx *cli.Context) error { | |||||
| } | } | ||||
| } | } | ||||
| var listenAddr string | |||||
| if setting.Protocol == setting.UnixSocket { | |||||
| listenAddr = fmt.Sprintf("%s", setting.HTTPAddr) | |||||
| } else { | |||||
| listenAddr = fmt.Sprintf("%s:%s", setting.HTTPAddr, setting.HTTPPort) | |||||
| listenAddr := setting.HTTPAddr | |||||
| if setting.Protocol != setting.UnixSocket { | |||||
| listenAddr += ":" + setting.HTTPPort | |||||
| } | } | ||||
| log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubURL) | log.Info("Listen: %v://%s%s", setting.Protocol, listenAddr, setting.AppSubURL) | ||||
| @@ -135,6 +133,7 @@ func runWeb(ctx *cli.Context) error { | |||||
| if setting.EnablePprof { | if setting.EnablePprof { | ||||
| go func() { | go func() { | ||||
| log.Info("Starting pprof server on localhost:6060") | |||||
| log.Info("%v", http.ListenAndServe("localhost:6060", nil)) | log.Info("%v", http.ListenAndServe("localhost:6060", nil)) | ||||
| }() | }() | ||||
| } | } | ||||