loading up the forgejo repo on tangled to test page performance
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at forgejo 226 lines 7.4 kB view raw
1// Copyright 2023 The Gitea Authors. All rights reserved. 2// SPDX-License-Identifier: MIT 3 4package cmd 5 6import ( 7 "context" 8 "fmt" 9 "os" 10 "path/filepath" 11 "strings" 12 13 "forgejo.org/cmd/forgejo" 14 "forgejo.org/modules/log" 15 "forgejo.org/modules/setting" 16 17 "github.com/urfave/cli/v2" 18) 19 20// cmdHelp is our own help subcommand with more information 21// Keep in mind that the "./gitea help"(subcommand) is different from "./gitea --help"(flag), the flag doesn't parse the config or output "DEFAULT CONFIGURATION:" information 22func cmdHelp() *cli.Command { 23 c := &cli.Command{ 24 Name: "help", 25 Aliases: []string{"h"}, 26 Usage: "Shows a list of commands or help for one command", 27 ArgsUsage: "[command]", 28 Action: func(c *cli.Context) (err error) { 29 lineage := c.Lineage() // The order is from child to parent: help, doctor, Gitea, {Command:nil} 30 targetCmdIdx := 0 31 if c.Command.Name == "help" { 32 targetCmdIdx = 1 33 } 34 if lineage[targetCmdIdx+1].Command != nil { 35 err = cli.ShowCommandHelp(lineage[targetCmdIdx+1], lineage[targetCmdIdx].Command.Name) 36 } else { 37 err = cli.ShowAppHelp(c) 38 } 39 _, _ = fmt.Fprintf(c.App.Writer, ` 40DEFAULT CONFIGURATION: 41 AppPath: %s 42 WorkPath: %s 43 CustomPath: %s 44 ConfigFile: %s 45 46`, setting.AppPath, setting.AppWorkPath, setting.CustomPath, setting.CustomConf) 47 return err 48 }, 49 } 50 return c 51} 52 53func appGlobalFlags() []cli.Flag { 54 return []cli.Flag{ 55 // make the builtin flags at the top 56 cli.HelpFlag, 57 58 // shared configuration flags, they are for global and for each sub-command at the same time 59 // eg: such command is valid: "./gitea --config /tmp/app.ini web --config /tmp/app.ini", while it's discouraged indeed 60 // keep in mind that the short flags like "-C", "-c" and "-w" are globally polluted, they can't be used for sub-commands anymore. 61 &cli.StringFlag{ 62 Name: "custom-path", 63 Aliases: []string{"C"}, 64 Usage: "Set custom path (defaults to '{WorkPath}/custom')", 65 }, 66 &cli.StringFlag{ 67 Name: "config", 68 Aliases: []string{"c"}, 69 Value: setting.CustomConf, 70 Usage: "Set custom config file (defaults to '{WorkPath}/custom/conf/app.ini')", 71 }, 72 &cli.StringFlag{ 73 Name: "work-path", 74 Aliases: []string{"w"}, 75 Usage: "Set Forgejo's working path (defaults to the directory of the Forgejo binary)", 76 }, 77 } 78} 79 80func prepareSubcommandWithConfig(command *cli.Command, globalFlags []cli.Flag) { 81 command.Flags = append(append([]cli.Flag{}, globalFlags...), command.Flags...) 82 command.Action = prepareWorkPathAndCustomConf(command.Action) 83 command.HideHelp = true 84 if command.Name != "help" { 85 command.Subcommands = append(command.Subcommands, cmdHelp()) 86 } 87 for i := range command.Subcommands { 88 prepareSubcommandWithConfig(command.Subcommands[i], globalFlags) 89 } 90} 91 92// prepareWorkPathAndCustomConf wraps the Action to prepare the work path and custom config 93// 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 94func prepareWorkPathAndCustomConf(action cli.ActionFunc) func(ctx *cli.Context) error { 95 return func(ctx *cli.Context) error { 96 var args setting.ArgWorkPathAndCustomConf 97 // from children to parent, check the global flags 98 for _, curCtx := range ctx.Lineage() { 99 if curCtx.IsSet("work-path") && args.WorkPath == "" { 100 args.WorkPath = curCtx.String("work-path") 101 } 102 if curCtx.IsSet("custom-path") && args.CustomPath == "" { 103 args.CustomPath = curCtx.String("custom-path") 104 } 105 if curCtx.IsSet("config") && args.CustomConf == "" { 106 args.CustomConf = curCtx.String("config") 107 } 108 } 109 setting.InitWorkPathAndCommonConfig(os.Getenv, args) 110 if ctx.Bool("help") || action == nil { 111 // the default behavior of "urfave/cli": "nil action" means "show help" 112 return cmdHelp().Action(ctx) 113 } 114 return action(ctx) 115 } 116} 117 118func NewMainApp(version, versionExtra string) *cli.App { 119 path, err := os.Executable() 120 if err != nil { 121 panic(err) 122 } 123 executable := filepath.Base(path) 124 125 subCmdsStandalone := make([]*cli.Command, 0, 10) 126 subCmdWithConfig := make([]*cli.Command, 0, 10) 127 globalFlags := make([]cli.Flag, 0, 10) 128 129 // 130 // If the executable is forgejo-cli, provide a Forgejo specific CLI 131 // that is NOT compatible with Gitea. 132 // 133 if executable == "forgejo-cli" { 134 subCmdsStandalone = append(subCmdsStandalone, forgejo.CmdActions(context.Background())) 135 subCmdWithConfig = append(subCmdWithConfig, forgejo.CmdF3(context.Background())) 136 globalFlags = append(globalFlags, []cli.Flag{ 137 &cli.BoolFlag{ 138 Name: "quiet", 139 }, 140 &cli.BoolFlag{ 141 Name: "verbose", 142 }, 143 }...) 144 } else { 145 // 146 // Otherwise provide a Gitea compatible CLI which includes Forgejo 147 // specific additions under the forgejo-cli subcommand. It allows 148 // admins to migration from Gitea to Forgejo by replacing the gitea 149 // binary and rename it to forgejo if they want. 150 // 151 subCmdsStandalone = append(subCmdsStandalone, forgejo.CmdForgejo(context.Background())) 152 subCmdWithConfig = append(subCmdWithConfig, CmdActions) 153 } 154 155 return innerNewMainApp(version, versionExtra, subCmdsStandalone, subCmdWithConfig, globalFlags) 156} 157 158func innerNewMainApp(version, versionExtra string, subCmdsStandaloneArgs, subCmdWithConfigArgs []*cli.Command, globalFlagsArgs []cli.Flag) *cli.App { 159 app := cli.NewApp() 160 app.HelpName = "forgejo" 161 app.Name = "Forgejo" 162 app.Usage = "Beyond coding. We forge." 163 app.Description = `By default, forgejo will start serving using the web-server with no argument, which can alternatively be run by running the subcommand "web".` 164 app.Version = version + versionExtra 165 app.EnableBashCompletion = true 166 167 // these sub-commands need to use config file 168 subCmdWithConfig := []*cli.Command{ 169 cmdHelp(), // the "help" sub-command was used to show the more information for "work path" and "custom config" 170 CmdWeb, 171 CmdServ, 172 CmdHook, 173 CmdKeys, 174 CmdDump, 175 CmdAdmin, 176 CmdMigrate, 177 CmdDoctor, 178 CmdManager, 179 CmdEmbedded, 180 CmdMigrateStorage, 181 CmdDumpRepository, 182 CmdRestoreRepository, 183 } 184 185 subCmdWithConfig = append(subCmdWithConfig, subCmdWithConfigArgs...) 186 187 // these sub-commands do not need the config file, and they do not depend on any path or environment variable. 188 subCmdStandalone := []*cli.Command{ 189 CmdCert, 190 CmdGenerate, 191 CmdDocs, 192 } 193 subCmdStandalone = append(subCmdStandalone, subCmdsStandaloneArgs...) 194 195 app.DefaultCommand = CmdWeb.Name 196 197 globalFlags := appGlobalFlags() 198 globalFlags = append(globalFlags, globalFlagsArgs...) 199 app.Flags = append(app.Flags, cli.VersionFlag) 200 app.Flags = append(app.Flags, globalFlags...) 201 app.HideHelp = true // use our own help action to show helps (with more information like default config) 202 app.Before = PrepareConsoleLoggerLevel(log.INFO) 203 for i := range subCmdWithConfig { 204 prepareSubcommandWithConfig(subCmdWithConfig[i], globalFlags) 205 } 206 app.Commands = append(app.Commands, subCmdWithConfig...) 207 app.Commands = append(app.Commands, subCmdStandalone...) 208 209 setting.InitGiteaEnvVars() 210 return app 211} 212 213func RunMainApp(app *cli.App, args ...string) error { 214 err := app.Run(args) 215 if err == nil { 216 return nil 217 } 218 if strings.HasPrefix(err.Error(), "flag provided but not defined:") { 219 // the cli package should already have output the error message, so just exit 220 cli.OsExiter(1) 221 return err 222 } 223 _, _ = fmt.Fprintf(app.ErrWriter, "Command error: %v\n", err) 224 cli.OsExiter(1) 225 return err 226}