Make CustomPath, CustomConf and AppWorkPath configurable at build (#6631)
This commit is contained in:
parent
ccf4783980
commit
8d0d7bc28d
12
Makefile
12
Makefile
@ -9,9 +9,9 @@ SHASUM ?= shasum -a 256
|
|||||||
export PATH := $($(GO) env GOPATH)/bin:$(PATH)
|
export PATH := $($(GO) env GOPATH)/bin:$(PATH)
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
ifeq ($(OS), Windows_NT)
|
||||||
EXECUTABLE := gitea.exe
|
EXECUTABLE ?= gitea.exe
|
||||||
else
|
else
|
||||||
EXECUTABLE := gitea
|
EXECUTABLE ?= gitea
|
||||||
UNAME_S := $(shell uname -s)
|
UNAME_S := $(shell uname -s)
|
||||||
ifeq ($(UNAME_S),Darwin)
|
ifeq ($(UNAME_S),Darwin)
|
||||||
SED_INPLACE := sed -i ''
|
SED_INPLACE := sed -i ''
|
||||||
@ -39,7 +39,7 @@ else
|
|||||||
GITEA_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
GITEA_VERSION ?= $(shell git describe --tags --always | sed 's/-/+/' | sed 's/^v//')
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LDFLAGS := -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
LDFLAGS := $(LDFLAGS) -X "main.MakeVersion=$(MAKE_VERSION)" -X "main.Version=$(GITEA_VERSION)" -X "main.Tags=$(TAGS)"
|
||||||
|
|
||||||
PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations/migration-test,$(filter-out code.gitea.io/gitea/integrations,$(shell $(GO) list ./... | grep -v /vendor/)))
|
PACKAGES ?= $(filter-out code.gitea.io/gitea/integrations/migration-test,$(filter-out code.gitea.io/gitea/integrations,$(shell $(GO) list ./... | grep -v /vendor/)))
|
||||||
SOURCES ?= $(shell find . -name "*.go" -type f)
|
SOURCES ?= $(shell find . -name "*.go" -type f)
|
||||||
@ -70,12 +70,6 @@ TEST_MSSQL_DBNAME ?= gitea
|
|||||||
TEST_MSSQL_USERNAME ?= sa
|
TEST_MSSQL_USERNAME ?= sa
|
||||||
TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1
|
TEST_MSSQL_PASSWORD ?= MwantsaSecurePassword1
|
||||||
|
|
||||||
ifeq ($(OS), Windows_NT)
|
|
||||||
EXECUTABLE := gitea.exe
|
|
||||||
else
|
|
||||||
EXECUTABLE := gitea
|
|
||||||
endif
|
|
||||||
|
|
||||||
# $(call strip-suffix,filename)
|
# $(call strip-suffix,filename)
|
||||||
strip-suffix = $(firstword $(subst ., ,$(1)))
|
strip-suffix = $(firstword $(subst ., ,$(1)))
|
||||||
|
|
||||||
|
76
cmd/admin.go
76
cmd/admin.go
@ -60,11 +60,6 @@ var (
|
|||||||
Name: "admin",
|
Name: "admin",
|
||||||
Usage: "User is an admin",
|
Usage: "User is an admin",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "random-password",
|
Name: "random-password",
|
||||||
Usage: "Generate a random password for the user",
|
Usage: "Generate a random password for the user",
|
||||||
@ -96,11 +91,6 @@ var (
|
|||||||
Value: "",
|
Value: "",
|
||||||
Usage: "New password to set for user",
|
Usage: "New password to set for user",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -123,26 +113,12 @@ var (
|
|||||||
Name: "hooks",
|
Name: "hooks",
|
||||||
Usage: "Regenerate git-hooks",
|
Usage: "Regenerate git-hooks",
|
||||||
Action: runRegenerateHooks,
|
Action: runRegenerateHooks,
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
microcmdRegenKeys = cli.Command{
|
microcmdRegenKeys = cli.Command{
|
||||||
Name: "keys",
|
Name: "keys",
|
||||||
Usage: "Regenerate authorized_keys file",
|
Usage: "Regenerate authorized_keys file",
|
||||||
Action: runRegenerateKeys,
|
Action: runRegenerateKeys,
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
subcmdAuth = cli.Command{
|
subcmdAuth = cli.Command{
|
||||||
@ -160,13 +136,6 @@ var (
|
|||||||
Name: "list",
|
Name: "list",
|
||||||
Usage: "List auth sources",
|
Usage: "List auth sources",
|
||||||
Action: runListAuth,
|
Action: runListAuth,
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
idFlag = cli.Int64Flag{
|
idFlag = cli.Int64Flag{
|
||||||
@ -178,22 +147,9 @@ var (
|
|||||||
Name: "delete",
|
Name: "delete",
|
||||||
Usage: "Delete specific auth source",
|
Usage: "Delete specific auth source",
|
||||||
Action: runDeleteAuth,
|
Action: runDeleteAuth,
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
idFlag,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
oauthCLIFlags = []cli.Flag{
|
oauthCLIFlags = []cli.Flag{
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "name",
|
Name: "name",
|
||||||
Value: "",
|
Value: "",
|
||||||
@ -266,10 +222,6 @@ func runChangePassword(c *cli.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := initDB(); err != nil {
|
if err := initDB(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -331,10 +283,6 @@ func runCreateUser(c *cli.Context) error {
|
|||||||
return errors.New("must set either password or random-password flag")
|
return errors.New("must set either password or random-password flag")
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := initDB(); err != nil {
|
if err := initDB(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -430,10 +378,6 @@ func getReleaseCount(id int64) (int64, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runRegenerateHooks(c *cli.Context) error {
|
func runRegenerateHooks(c *cli.Context) error {
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := initDB(); err != nil {
|
if err := initDB(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -441,10 +385,6 @@ func runRegenerateHooks(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runRegenerateKeys(c *cli.Context) error {
|
func runRegenerateKeys(c *cli.Context) error {
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := initDB(); err != nil {
|
if err := initDB(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -473,10 +413,6 @@ func parseOAuth2Config(c *cli.Context) *models.OAuth2Config {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runAddOauth(c *cli.Context) error {
|
func runAddOauth(c *cli.Context) error {
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := initDB(); err != nil {
|
if err := initDB(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -490,10 +426,6 @@ func runAddOauth(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runUpdateOauth(c *cli.Context) error {
|
func runUpdateOauth(c *cli.Context) error {
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.IsSet("id") {
|
if !c.IsSet("id") {
|
||||||
return fmt.Errorf("--id flag is missing")
|
return fmt.Errorf("--id flag is missing")
|
||||||
}
|
}
|
||||||
@ -561,10 +493,6 @@ func runUpdateOauth(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runListAuth(c *cli.Context) error {
|
func runListAuth(c *cli.Context) error {
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := initDB(); err != nil {
|
if err := initDB(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -587,10 +515,6 @@ func runListAuth(c *cli.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runDeleteAuth(c *cli.Context) error {
|
func runDeleteAuth(c *cli.Context) error {
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.IsSet("id") {
|
if !c.IsSet("id") {
|
||||||
return fmt.Errorf("--id flag is missing")
|
return fmt.Errorf("--id flag is missing")
|
||||||
}
|
}
|
||||||
|
@ -30,11 +30,6 @@ var CmdDump = cli.Command{
|
|||||||
It can be used for backup and capture Gitea server image to send to maintainer`,
|
It can be used for backup and capture Gitea server image to send to maintainer`,
|
||||||
Action: runDump,
|
Action: runDump,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "file, f",
|
Name: "file, f",
|
||||||
Value: fmt.Sprintf("gitea-dump-%d.zip", time.Now().Unix()),
|
Value: fmt.Sprintf("gitea-dump-%d.zip", time.Now().Unix()),
|
||||||
@ -61,9 +56,6 @@ It can be used for backup and capture Gitea server image to send to maintainer`,
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runDump(ctx *cli.Context) error {
|
func runDump(ctx *cli.Context) error {
|
||||||
if ctx.IsSet("config") {
|
|
||||||
setting.CustomConf = ctx.String("config")
|
|
||||||
}
|
|
||||||
setting.NewContext()
|
setting.NewContext()
|
||||||
setting.NewServices() // cannot access session settings otherwise
|
setting.NewServices() // cannot access session settings otherwise
|
||||||
models.LoadConfigs()
|
models.LoadConfigs()
|
||||||
|
26
cmd/hook.go
26
cmd/hook.go
@ -16,7 +16,6 @@ import (
|
|||||||
"code.gitea.io/gitea/modules/git"
|
"code.gitea.io/gitea/modules/git"
|
||||||
"code.gitea.io/gitea/modules/log"
|
"code.gitea.io/gitea/modules/log"
|
||||||
"code.gitea.io/gitea/modules/private"
|
"code.gitea.io/gitea/modules/private"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
"code.gitea.io/gitea/modules/util"
|
"code.gitea.io/gitea/modules/util"
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
@ -28,13 +27,6 @@ var (
|
|||||||
Name: "hook",
|
Name: "hook",
|
||||||
Usage: "Delegate commands to corresponding Git hooks",
|
Usage: "Delegate commands to corresponding Git hooks",
|
||||||
Description: "This should only be called by Git",
|
Description: "This should only be called by Git",
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []cli.Command{
|
||||||
subcmdHookPreReceive,
|
subcmdHookPreReceive,
|
||||||
subcmdHookUpdate,
|
subcmdHookUpdate,
|
||||||
@ -67,12 +59,6 @@ func runHookPreReceive(c *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
} else if c.GlobalIsSet("config") {
|
|
||||||
setting.CustomConf = c.GlobalString("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
setup("hooks/pre-receive.log")
|
setup("hooks/pre-receive.log")
|
||||||
|
|
||||||
// the environment setted on serv command
|
// the environment setted on serv command
|
||||||
@ -143,12 +129,6 @@ func runHookUpdate(c *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
} else if c.GlobalIsSet("config") {
|
|
||||||
setting.CustomConf = c.GlobalString("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
setup("hooks/update.log")
|
setup("hooks/update.log")
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@ -159,12 +139,6 @@ func runHookPostReceive(c *cli.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
} else if c.GlobalIsSet("config") {
|
|
||||||
setting.CustomConf = c.GlobalString("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
setup("hooks/post-receive.log")
|
setup("hooks/post-receive.log")
|
||||||
|
|
||||||
// the environment setted on serv command
|
// the environment setted on serv command
|
||||||
|
10
cmd/keys.go
10
cmd/keys.go
@ -10,7 +10,6 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"code.gitea.io/gitea/models"
|
"code.gitea.io/gitea/models"
|
||||||
"code.gitea.io/gitea/modules/setting"
|
|
||||||
|
|
||||||
"github.com/urfave/cli"
|
"github.com/urfave/cli"
|
||||||
)
|
)
|
||||||
@ -41,19 +40,10 @@ var CmdKeys = cli.Command{
|
|||||||
Value: "",
|
Value: "",
|
||||||
Usage: "Base64 encoded content of the SSH key provided to the SSH Server (requires type to be provided too)",
|
Usage: "Base64 encoded content of the SSH key provided to the SSH Server (requires type to be provided too)",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
func runKeys(c *cli.Context) error {
|
func runKeys(c *cli.Context) error {
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if !c.IsSet("username") {
|
if !c.IsSet("username") {
|
||||||
return errors.New("No username provided")
|
return errors.New("No username provided")
|
||||||
}
|
}
|
||||||
|
@ -19,20 +19,9 @@ var CmdMigrate = cli.Command{
|
|||||||
Usage: "Migrate the database",
|
Usage: "Migrate the database",
|
||||||
Description: "This is a command for migrating the database, so that you can run gitea admin create-user before starting the server.",
|
Description: "This is a command for migrating the database, so that you can run gitea admin create-user before starting the server.",
|
||||||
Action: runMigrate,
|
Action: runMigrate,
|
||||||
Flags: []cli.Flag{
|
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func runMigrate(ctx *cli.Context) error {
|
func runMigrate(ctx *cli.Context) error {
|
||||||
if ctx.IsSet("config") {
|
|
||||||
setting.CustomConf = ctx.String("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if err := initDB(); err != nil {
|
if err := initDB(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
@ -39,11 +39,6 @@ var CmdServ = cli.Command{
|
|||||||
Description: `Serv provide access auth for repositories`,
|
Description: `Serv provide access auth for repositories`,
|
||||||
Action: runServ,
|
Action: runServ,
|
||||||
Flags: []cli.Flag{
|
Flags: []cli.Flag{
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
cli.BoolFlag{
|
cli.BoolFlag{
|
||||||
Name: "enable-pprof",
|
Name: "enable-pprof",
|
||||||
},
|
},
|
||||||
@ -109,9 +104,6 @@ func fail(userMessage, logMessage string, args ...interface{}) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runServ(c *cli.Context) error {
|
func runServ(c *cli.Context) error {
|
||||||
if c.IsSet("config") {
|
|
||||||
setting.CustomConf = c.String("config")
|
|
||||||
}
|
|
||||||
setup("serv.log")
|
setup("serv.log")
|
||||||
|
|
||||||
if setting.SSH.Disabled {
|
if setting.SSH.Disabled {
|
||||||
|
@ -40,11 +40,6 @@ and it takes care of all the other things for you`,
|
|||||||
Value: "3000",
|
Value: "3000",
|
||||||
Usage: "Temporary port number to prevent conflict",
|
Usage: "Temporary port number to prevent conflict",
|
||||||
},
|
},
|
||||||
cli.StringFlag{
|
|
||||||
Name: "config, c",
|
|
||||||
Value: "custom/conf/app.ini",
|
|
||||||
Usage: "Custom configuration file path",
|
|
||||||
},
|
|
||||||
cli.StringFlag{
|
cli.StringFlag{
|
||||||
Name: "pid, P",
|
Name: "pid, P",
|
||||||
Value: "/var/run/gitea.pid",
|
Value: "/var/run/gitea.pid",
|
||||||
@ -110,10 +105,6 @@ func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func runWeb(ctx *cli.Context) error {
|
func runWeb(ctx *cli.Context) error {
|
||||||
if ctx.IsSet("config") {
|
|
||||||
setting.CustomConf = ctx.String("config")
|
|
||||||
}
|
|
||||||
|
|
||||||
if ctx.IsSet("pid") {
|
if ctx.IsSet("pid") {
|
||||||
setting.CustomPID = ctx.String("pid")
|
setting.CustomPID = ctx.String("pid")
|
||||||
}
|
}
|
||||||
|
@ -43,6 +43,7 @@ func runPR() {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
|
setting.SetCustomPathAndConf("", "")
|
||||||
setting.NewContext()
|
setting.NewContext()
|
||||||
|
|
||||||
setting.RepoRootPath, err = ioutil.TempDir(os.TempDir(), "repos")
|
setting.RepoRootPath, err = ioutil.TempDir(os.TempDir(), "repos")
|
||||||
|
3
docker/Makefile
vendored
3
docker/Makefile
vendored
@ -4,7 +4,6 @@ DOCKER_IMAGE ?= gitea/gitea
|
|||||||
DOCKER_TAG ?= latest
|
DOCKER_TAG ?= latest
|
||||||
DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
|
DOCKER_REF := $(DOCKER_IMAGE):$(DOCKER_TAG)
|
||||||
|
|
||||||
|
|
||||||
.PHONY: docker
|
.PHONY: docker
|
||||||
docker:
|
docker:
|
||||||
docker build --disable-content-trust=false -t $(DOCKER_REF) .
|
docker build --disable-content-trust=false -t $(DOCKER_REF) .
|
||||||
@ -12,4 +11,4 @@ docker:
|
|||||||
|
|
||||||
.PHONY: docker-build
|
.PHONY: docker-build
|
||||||
docker-build:
|
docker-build:
|
||||||
docker run -ti --rm -v $(CURDIR):/srv/app/src/code.gitea.io/gitea -w /srv/app/src/code.gitea.io/gitea -e TAGS="bindata $(TAGS)" webhippie/golang:edge make clean generate build
|
docker run -ti --rm -v $(CURDIR):/srv/app/src/code.gitea.io/gitea -w /srv/app/src/code.gitea.io/gitea -e TAGS="bindata $(TAGS)" LDFLAGS="$(LDFLAGS)" webhippie/golang:edge make clean generate build
|
||||||
|
@ -15,19 +15,28 @@ menu:
|
|||||||
|
|
||||||
# Customizing Gitea
|
# Customizing Gitea
|
||||||
|
|
||||||
Customizing Gitea is typically done using the `custom` folder. This is the central
|
Customizing Gitea is typically done using the `CustomPath` folder - by default this is
|
||||||
place to override configuration settings, templates, etc.
|
the `custom` folder from the running directory, but may be different if your build has
|
||||||
|
set this differently. This is the central place to override configuration settings,
|
||||||
|
templates, etc. You can check the `CustomPath` using `gitea help`. You can override
|
||||||
|
the `CustomPath` by setting either the `GITEA_CUSTOM` environment variable or by
|
||||||
|
using the `--custom-path` option on the `gitea` binary. (The option will override the
|
||||||
|
environment variable.)
|
||||||
|
|
||||||
If Gitea is deployed from binary, all default paths will be relative to the Gitea
|
If Gitea is deployed from binary, all default paths will be relative to the Gitea
|
||||||
binary. If installed from a distribution, these paths will likely be modified to
|
binary. If installed from a distribution, these paths will likely be modified to
|
||||||
the Linux Filesystem Standard. Gitea will create required folders, including `custom/`.
|
the Linux Filesystem Standard. Gitea will attempt to create required folders, including
|
||||||
Application settings are configured in `custom/conf/app.ini`. Distributions may
|
`custom/`. Distributions may provide a symlink for `custom` using `/etc/gitea/`.
|
||||||
provide a symlink for `custom` using `/etc/gitea/`.
|
|
||||||
|
Application settings can be found in file `CustomConf` which is by default,
|
||||||
|
`CustomPath/conf/app.ini` but may be different if your build has set this differently.
|
||||||
|
Again `gitea help` will allow you review this variable and you can override it using the
|
||||||
|
`--config` option on the `gitea` binary.
|
||||||
|
|
||||||
- [Quick Cheat Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/)
|
- [Quick Cheat Sheet](https://docs.gitea.io/en-us/config-cheat-sheet/)
|
||||||
- [Complete List](https://github.com/go-gitea/gitea/blob/master/custom/conf/app.ini.sample)
|
- [Complete List](https://github.com/go-gitea/gitea/blob/master/custom/conf/app.ini.sample)
|
||||||
|
|
||||||
If the `custom` folder can't be found next to the binary, check the `GITEA_CUSTOM`
|
If the `CustomPath` folder can't be found despite checking `gitea help`, check the `GITEA_CUSTOM`
|
||||||
environment variable; this can be used to override the default path to something else.
|
environment variable; this can be used to override the default path to something else.
|
||||||
`GITEA_CUSTOM` might, for example, be set by an init script.
|
`GITEA_CUSTOM` might, for example, be set by an init script.
|
||||||
|
|
||||||
@ -38,7 +47,8 @@ environment variable; this can be used to override the default path to something
|
|||||||
## Customizing /robots.txt
|
## Customizing /robots.txt
|
||||||
|
|
||||||
To make Gitea serve a custom `/robots.txt` (default: empty 404), create a file called
|
To make Gitea serve a custom `/robots.txt` (default: empty 404), create a file called
|
||||||
`robots.txt` in the `custom` folder with [expected contents](http://www.robotstxt.org/).
|
`robots.txt` in the `custom` folder (or `CustomPath`) with
|
||||||
|
[expected contents](http://www.robotstxt.org/).
|
||||||
|
|
||||||
## Serving custom public files
|
## Serving custom public files
|
||||||
|
|
||||||
|
@ -117,3 +117,26 @@ launched manually from command line, it can be killed by pressing `Ctrl + C`.
|
|||||||
```bash
|
```bash
|
||||||
./gitea web
|
./gitea web
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Changing the default CustomPath, CustomConf and AppWorkDir
|
||||||
|
|
||||||
|
Gitea will search for a number of things from the `CustomPath`. By default this is
|
||||||
|
the `custom/` directory in the current working directory when running Gitea. It will also
|
||||||
|
look for its configuration file `CustomConf` in `$CustomPath/conf/app.ini`, and will use the
|
||||||
|
current working directory as the relative base path `AppWorkDir` for a number configurable
|
||||||
|
values.
|
||||||
|
|
||||||
|
These values, although useful when developing, may conflict with downstream users preferences.
|
||||||
|
|
||||||
|
One option is to use a script file to shadow the `gitea` binary and create an appropriate
|
||||||
|
environment before running Gitea. However, when building you can change these defaults
|
||||||
|
using the `LDFLAGS` environment variable for `make`. The appropriate settings are as follows
|
||||||
|
|
||||||
|
* To set the `CustomPath` use `LDFLAGS="-X \"code.gitea.io/gitea/modules/setting.CustomPath=custom-path\""`
|
||||||
|
* For `CustomConf` you should use `-X \"code.gitea.io/gitea/modules/setting.CustomConf=conf.ini\"`
|
||||||
|
* For `AppWorkDir` you should use `-X \"code.gitea.io/gitea/modules/setting.AppWorkDir=working-directory\"`
|
||||||
|
|
||||||
|
Add as many of the strings with their preceding `-X` to the `LDFLAGS` variable and run `make build`
|
||||||
|
with the appropriate `TAGS` as above.
|
||||||
|
|
||||||
|
Running `gitea help` will allow you to review what the computed settings will be for your `gitea`.
|
||||||
|
@ -17,13 +17,16 @@ menu:
|
|||||||
|
|
||||||
### Usage
|
### Usage
|
||||||
|
|
||||||
`gitea [global options] command [command options] [arguments...]`
|
`gitea [global options] command [command or global options] [arguments...]`
|
||||||
|
|
||||||
### Global options
|
### Global options
|
||||||
- `--help`, `-h`: Show help text and exit. Optional. This can be used with any of the
|
|
||||||
subcommands to see help text for it.
|
All global options can be placed at the command level.
|
||||||
- `--version`, `-v`: Show version and exit. Optional. (example: `Gitea version
|
|
||||||
1.1.0+218-g7b907ed built with: bindata, sqlite`).
|
- `--help`, `-h`: Show help text and exit. Optional.
|
||||||
|
- `--version`, `-v`: Show version and exit. Optional. (example: `Gitea version 1.1.0+218-g7b907ed built with: bindata, sqlite`).
|
||||||
|
- `--custom-path path`, `-C path`: Location of the Gitea custom folder. Optional. (default: $PWD/custom).
|
||||||
|
- `--config path`, `-c path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
||||||
|
|
||||||
### Commands
|
### Commands
|
||||||
|
|
||||||
@ -33,7 +36,6 @@ Starts the server:
|
|||||||
|
|
||||||
- Options:
|
- Options:
|
||||||
- `--port number`, `-p number`: Port number. Optional. (default: 3000). Overrides configuration file.
|
- `--port number`, `-p number`: Port number. Optional. (default: 3000). Overrides configuration file.
|
||||||
- `--config path`, `-c path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
|
||||||
- `--pid path`, `-P path`: Pidfile path. Optional.
|
- `--pid path`, `-P path`: Pidfile path. Optional.
|
||||||
- Examples:
|
- Examples:
|
||||||
- `gitea web`
|
- `gitea web`
|
||||||
@ -56,7 +58,6 @@ Admin operations:
|
|||||||
- `--password value`: Password. Required.
|
- `--password value`: Password. Required.
|
||||||
- `--email value`: Email. Required.
|
- `--email value`: Email. Required.
|
||||||
- `--admin`: If provided, this makes the user an admin. Optional.
|
- `--admin`: If provided, this makes the user an admin. Optional.
|
||||||
- `--config path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
|
||||||
- `--must-change-password`: If provided, the created user will be required to choose a newer password after
|
- `--must-change-password`: If provided, the created user will be required to choose a newer password after
|
||||||
the initial login. Optional. (default: true).
|
the initial login. Optional. (default: true).
|
||||||
- ``--random-password``: If provided, a randomly generated password will be used as the password of
|
- ``--random-password``: If provided, a randomly generated password will be used as the password of
|
||||||
@ -69,7 +70,6 @@ Admin operations:
|
|||||||
- Options:
|
- Options:
|
||||||
- `--username value`, `-u value`: Username. Required.
|
- `--username value`, `-u value`: Username. Required.
|
||||||
- `--password value`, `-p value`: New password. Required.
|
- `--password value`, `-p value`: New password. Required.
|
||||||
- `--config path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
|
||||||
- Examples:
|
- Examples:
|
||||||
- `gitea admin change-password --username myname --password asecurepassword`
|
- `gitea admin change-password --username myname --password asecurepassword`
|
||||||
- `regenerate`
|
- `regenerate`
|
||||||
@ -82,19 +82,15 @@ Admin operations:
|
|||||||
- `auth`:
|
- `auth`:
|
||||||
- `list`:
|
- `list`:
|
||||||
- Description: lists all external authentication sources that exist
|
- Description: lists all external authentication sources that exist
|
||||||
- Options:
|
|
||||||
- `--config path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
|
||||||
- Examples:
|
- Examples:
|
||||||
- `gitea admin auth list`
|
- `gitea admin auth list`
|
||||||
- `delete`:
|
- `delete`:
|
||||||
- Options:
|
- Options:
|
||||||
- `--id`: ID of source to be deleted. Required.
|
- `--id`: ID of source to be deleted. Required.
|
||||||
- `--config path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
|
||||||
- Examples:
|
- Examples:
|
||||||
- `gitea admin auth delete --id 1`
|
- `gitea admin auth delete --id 1`
|
||||||
- `add-oauth`:
|
- `add-oauth`:
|
||||||
- Options:
|
- Options:
|
||||||
- `--config path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
|
||||||
- `--name`: Application Name.
|
- `--name`: Application Name.
|
||||||
- `--provider`: OAuth2 Provider.
|
- `--provider`: OAuth2 Provider.
|
||||||
- `--key`: Client ID (Key).
|
- `--key`: Client ID (Key).
|
||||||
@ -110,7 +106,6 @@ Admin operations:
|
|||||||
- `update-oauth`:
|
- `update-oauth`:
|
||||||
- Options:
|
- Options:
|
||||||
- `--id`: ID of source to be updated. Required.
|
- `--id`: ID of source to be updated. Required.
|
||||||
- `--config path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
|
||||||
- `--name`: Application Name.
|
- `--name`: Application Name.
|
||||||
- `--provider`: OAuth2 Provider.
|
- `--provider`: OAuth2 Provider.
|
||||||
- `--key`: Client ID (Key).
|
- `--key`: Client ID (Key).
|
||||||
@ -148,7 +143,6 @@ Dumps all files and databases into a zip file. Outputs into a file like `gitea-d
|
|||||||
in the current directory.
|
in the current directory.
|
||||||
|
|
||||||
- Options:
|
- Options:
|
||||||
- `--config path`, `-c path`: Gitea configuration file path. Optional. (default: custom/conf/app.ini).
|
|
||||||
- `--file name`, `-f name`: Name of the dump file with will be created. Optional. (default: gitea-dump-[timestamp].zip).
|
- `--file name`, `-f name`: Name of the dump file with will be created. Optional. (default: gitea-dump-[timestamp].zip).
|
||||||
- `--tempdir path`, `-t path`: Path to the temporary directory used. Optional. (default: /tmp).
|
- `--tempdir path`, `-t path`: Path to the temporary directory used. Optional. (default: /tmp).
|
||||||
- `--skip-repository`, `-R`: Skip the repository dumping. Optional.
|
- `--skip-repository`, `-R`: Skip the repository dumping. Optional.
|
||||||
|
@ -118,6 +118,7 @@ func initIntegrationTest() {
|
|||||||
setting.CustomConf = giteaConf
|
setting.CustomConf = giteaConf
|
||||||
}
|
}
|
||||||
|
|
||||||
|
setting.SetCustomPathAndConf("", "")
|
||||||
setting.NewContext()
|
setting.NewContext()
|
||||||
setting.CheckLFSVersion()
|
setting.CheckLFSVersion()
|
||||||
models.LoadConfigs()
|
models.LoadConfigs()
|
||||||
|
103
main.go
103
main.go
@ -7,6 +7,7 @@
|
|||||||
package main // import "code.gitea.io/gitea"
|
package main // import "code.gitea.io/gitea"
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
@ -30,11 +31,20 @@ var (
|
|||||||
Tags = ""
|
Tags = ""
|
||||||
// MakeVersion holds the current Make version if built with make
|
// MakeVersion holds the current Make version if built with make
|
||||||
MakeVersion = ""
|
MakeVersion = ""
|
||||||
|
|
||||||
|
originalAppHelpTemplate = ""
|
||||||
|
originalCommandHelpTemplate = ""
|
||||||
|
originalSubcommandHelpTemplate = ""
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
setting.AppVer = Version
|
setting.AppVer = Version
|
||||||
setting.AppBuiltWith = formatBuiltWith(Tags)
|
setting.AppBuiltWith = formatBuiltWith(Tags)
|
||||||
|
|
||||||
|
// Grab the original help templates
|
||||||
|
originalAppHelpTemplate = cli.AppHelpTemplate
|
||||||
|
originalCommandHelpTemplate = cli.CommandHelpTemplate
|
||||||
|
originalSubcommandHelpTemplate = cli.SubcommandHelpTemplate
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
@ -55,14 +65,107 @@ arguments - which can alternatively be run by running the subcommand web.`
|
|||||||
cmd.CmdMigrate,
|
cmd.CmdMigrate,
|
||||||
cmd.CmdKeys,
|
cmd.CmdKeys,
|
||||||
}
|
}
|
||||||
|
// Now adjust these commands to add our global configuration options
|
||||||
|
|
||||||
|
// First calculate the default paths and set the AppHelpTemplates in this context
|
||||||
|
setting.SetCustomPathAndConf("", "")
|
||||||
|
setAppHelpTemplates()
|
||||||
|
|
||||||
|
// default configuration flags
|
||||||
|
defaultFlags := []cli.Flag{
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "custom-path, C",
|
||||||
|
Value: setting.CustomPath,
|
||||||
|
Usage: "Custom path file path",
|
||||||
|
},
|
||||||
|
cli.StringFlag{
|
||||||
|
Name: "config, c",
|
||||||
|
Value: setting.CustomConf,
|
||||||
|
Usage: "Custom configuration file path",
|
||||||
|
},
|
||||||
|
cli.VersionFlag,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the default to be equivalent to cmdWeb and add the default flags
|
||||||
app.Flags = append(app.Flags, cmd.CmdWeb.Flags...)
|
app.Flags = append(app.Flags, cmd.CmdWeb.Flags...)
|
||||||
|
app.Flags = append(app.Flags, defaultFlags...)
|
||||||
app.Action = cmd.CmdWeb.Action
|
app.Action = cmd.CmdWeb.Action
|
||||||
|
|
||||||
|
// Add functions to set these paths and these flags to the commands
|
||||||
|
app.Before = establishCustomPath
|
||||||
|
for i := range app.Commands {
|
||||||
|
setFlagsAndBeforeOnSubcommands(&app.Commands[i], defaultFlags, establishCustomPath)
|
||||||
|
}
|
||||||
|
|
||||||
err := app.Run(os.Args)
|
err := app.Run(os.Args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to run app with %s: %v", os.Args, err)
|
log.Fatal("Failed to run app with %s: %v", os.Args, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func setFlagsAndBeforeOnSubcommands(command *cli.Command, defaultFlags []cli.Flag, before cli.BeforeFunc) {
|
||||||
|
command.Flags = append(command.Flags, defaultFlags...)
|
||||||
|
command.Before = establishCustomPath
|
||||||
|
for i := range command.Subcommands {
|
||||||
|
setFlagsAndBeforeOnSubcommands(&command.Subcommands[i], defaultFlags, before)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func establishCustomPath(ctx *cli.Context) error {
|
||||||
|
var providedCustom string
|
||||||
|
var providedConf string
|
||||||
|
|
||||||
|
currentCtx := ctx
|
||||||
|
for {
|
||||||
|
if len(providedCustom) != 0 && len(providedConf) != 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if currentCtx == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if currentCtx.IsSet("custom-path") && len(providedCustom) == 0 {
|
||||||
|
providedCustom = currentCtx.String("custom-path")
|
||||||
|
}
|
||||||
|
if currentCtx.IsSet("config") && len(providedConf) == 0 {
|
||||||
|
providedConf = currentCtx.String("config")
|
||||||
|
}
|
||||||
|
currentCtx = currentCtx.Parent()
|
||||||
|
|
||||||
|
}
|
||||||
|
setting.SetCustomPathAndConf(providedCustom, providedConf)
|
||||||
|
|
||||||
|
setAppHelpTemplates()
|
||||||
|
|
||||||
|
if ctx.IsSet("version") {
|
||||||
|
cli.ShowVersion(ctx)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func setAppHelpTemplates() {
|
||||||
|
cli.AppHelpTemplate = adjustHelpTemplate(originalAppHelpTemplate)
|
||||||
|
cli.CommandHelpTemplate = adjustHelpTemplate(originalCommandHelpTemplate)
|
||||||
|
cli.SubcommandHelpTemplate = adjustHelpTemplate(originalSubcommandHelpTemplate)
|
||||||
|
}
|
||||||
|
|
||||||
|
func adjustHelpTemplate(originalTemplate string) string {
|
||||||
|
overrided := ""
|
||||||
|
if _, ok := os.LookupEnv("GITEA_CUSTOM"); ok {
|
||||||
|
overrided = "(GITEA_CUSTOM)"
|
||||||
|
}
|
||||||
|
|
||||||
|
return fmt.Sprintf(`%s
|
||||||
|
DEFAULT CONFIGURATION:
|
||||||
|
CustomPath: %s %s
|
||||||
|
CustomConf: %s
|
||||||
|
AppPath: %s
|
||||||
|
AppWorkPath: %s
|
||||||
|
|
||||||
|
`, originalTemplate, setting.CustomPath, overrided, setting.CustomConf, setting.AppPath, setting.AppWorkPath)
|
||||||
|
}
|
||||||
|
|
||||||
func formatBuiltWith(makeTags string) string {
|
func formatBuiltWith(makeTags string) string {
|
||||||
var version = runtime.Version()
|
var version = runtime.Version()
|
||||||
if len(MakeVersion) > 0 {
|
if len(MakeVersion) > 0 {
|
||||||
|
@ -14,6 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
|
setting.SetCustomPathAndConf("", "")
|
||||||
setting.NewContext()
|
setting.NewContext()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -391,12 +391,12 @@ func getAppPath() (string, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getWorkPath(appPath string) string {
|
func getWorkPath(appPath string) string {
|
||||||
workPath := ""
|
workPath := AppWorkPath
|
||||||
giteaWorkPath := os.Getenv("GITEA_WORK_DIR")
|
|
||||||
|
|
||||||
if len(giteaWorkPath) > 0 {
|
if giteaWorkPath, ok := os.LookupEnv("GITEA_WORK_DIR"); ok {
|
||||||
workPath = giteaWorkPath
|
workPath = giteaWorkPath
|
||||||
} else {
|
}
|
||||||
|
if len(workPath) == 0 {
|
||||||
i := strings.LastIndex(appPath, "/")
|
i := strings.LastIndex(appPath, "/")
|
||||||
if i == -1 {
|
if i == -1 {
|
||||||
workPath = appPath
|
workPath = appPath
|
||||||
@ -475,27 +475,40 @@ func CheckLFSVersion() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewContext initializes configuration context.
|
// SetCustomPathAndConf will set CustomPath and CustomConf with reference to the
|
||||||
// NOTE: do not print any log except error.
|
// GITEA_CUSTOM environment variable and with provided overrides before stepping
|
||||||
func NewContext() {
|
// back to the default
|
||||||
Cfg = ini.Empty()
|
func SetCustomPathAndConf(providedCustom, providedConf string) {
|
||||||
|
if giteaCustom, ok := os.LookupEnv("GITEA_CUSTOM"); ok {
|
||||||
CustomPath = os.Getenv("GITEA_CUSTOM")
|
CustomPath = giteaCustom
|
||||||
|
}
|
||||||
|
if len(providedCustom) != 0 {
|
||||||
|
CustomPath = providedCustom
|
||||||
|
}
|
||||||
if len(CustomPath) == 0 {
|
if len(CustomPath) == 0 {
|
||||||
CustomPath = path.Join(AppWorkPath, "custom")
|
CustomPath = path.Join(AppWorkPath, "custom")
|
||||||
} else if !filepath.IsAbs(CustomPath) {
|
} else if !filepath.IsAbs(CustomPath) {
|
||||||
CustomPath = path.Join(AppWorkPath, CustomPath)
|
CustomPath = path.Join(AppWorkPath, CustomPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(CustomPID) > 0 {
|
if len(providedConf) != 0 {
|
||||||
createPIDFile(CustomPID)
|
CustomConf = providedConf
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(CustomConf) == 0 {
|
if len(CustomConf) == 0 {
|
||||||
CustomConf = path.Join(CustomPath, "conf/app.ini")
|
CustomConf = path.Join(CustomPath, "conf/app.ini")
|
||||||
} else if !filepath.IsAbs(CustomConf) {
|
} else if !filepath.IsAbs(CustomConf) {
|
||||||
CustomConf = path.Join(CustomPath, CustomConf)
|
CustomConf = path.Join(CustomPath, CustomConf)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewContext initializes configuration context.
|
||||||
|
// NOTE: do not print any log except error.
|
||||||
|
func NewContext() {
|
||||||
|
Cfg = ini.Empty()
|
||||||
|
|
||||||
|
if len(CustomPID) > 0 {
|
||||||
|
createPIDFile(CustomPID)
|
||||||
|
}
|
||||||
|
|
||||||
if com.IsFile(CustomConf) {
|
if com.IsFile(CustomConf) {
|
||||||
if err := Cfg.Append(CustomConf); err != nil {
|
if err := Cfg.Append(CustomConf); err != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user