* Moved conf assets into options folder * Dropped old bindata * Started to integrate options bindata and accessors * Do not enforce a builtin app.ini * Replaced bindata calls with options * Dropped bindata task from makefile, it's the generate task now * Always embedd app.ini to provide sane config defaults * Use sane defaults for the configuration * Defined default value for SSH_KEYGEN_PATH * Dropped "NEVER EVER MODIFY THIS FILE" header from app.ini * Fixed new paths in latest test additions * Drop bindata with make clean task * Set more proper default valuestags/v1.0.0
coverage.out | coverage.out | ||||
/modules/options/bindata.go | |||||
/modules/public/bindata.go | /modules/public/bindata.go | ||||
/modules/templates/bindata.go | /modules/templates/bindata.go | ||||
EXECUTABLE := gitea | EXECUTABLE := gitea | ||||
IMPORT := code.gitea.io/gitea | IMPORT := code.gitea.io/gitea | ||||
SHA := $(shell git rev-parse --short HEAD) | |||||
DATE := $(shell date -u '+%Y-%m-%d %I:%M:%S %Z') | |||||
BINDATA := $(shell find conf | sed 's/ /\\ /g') | |||||
BINDATA := modules/{options,public,templates}/bindata.go | |||||
STYLESHEETS := $(wildcard public/less/index.less public/less/_*.less) | STYLESHEETS := $(wildcard public/less/index.less public/less/_*.less) | ||||
JAVASCRIPTS := | JAVASCRIPTS := | ||||
.PHONY: clean | .PHONY: clean | ||||
clean: | clean: | ||||
go clean -i ./... | go clean -i ./... | ||||
rm -rf $(EXECUTABLE) $(DIST) | |||||
rm -rf $(EXECUTABLE) $(DIST) $(BINDATA) | |||||
.PHONY: fmt | .PHONY: fmt | ||||
fmt: | fmt: | ||||
release-check: | release-check: | ||||
cd $(DIST)/release; $(foreach file,$(wildcard $(DIST)/release/$(EXECUTABLE)-*),sha256sum $(notdir $(file)) > $(notdir $(file)).sha256;) | cd $(DIST)/release; $(foreach file,$(wildcard $(DIST)/release/$(EXECUTABLE)-*),sha256sum $(notdir $(file)) > $(notdir $(file)).sha256;) | ||||
.PHONY: bindata | |||||
bindata: modules/bindata/bindata.go | |||||
.IGNORE: modules/bindata/bindata.go | |||||
modules/bindata/bindata.go: $(BINDATA) | |||||
@which go-bindata > /dev/null; if [ $$? -ne 0 ]; then \ | |||||
go get -u github.com/jteeuwen/go-bindata/...; \ | |||||
fi | |||||
go-bindata -o=$@ -ignore="\\.go|README.md|TRANSLATORS" -pkg=bindata conf/... | |||||
go fmt $@ | |||||
sed -i.bak 's/confLocaleLocale_/confLocaleLocale/' $@ | |||||
rm $@.bak | |||||
.PHONY: javascripts | .PHONY: javascripts | ||||
javascripts: public/js/index.js | javascripts: public/js/index.js | ||||
lessc $< $@ | lessc $< $@ | ||||
.PHONY: assets | .PHONY: assets | ||||
assets: bindata javascripts stylesheets | |||||
assets: javascripts stylesheets |
"code.gitea.io/gitea/models" | "code.gitea.io/gitea/models" | ||||
"code.gitea.io/gitea/modules/auth" | "code.gitea.io/gitea/modules/auth" | ||||
"code.gitea.io/gitea/modules/bindata" | |||||
"code.gitea.io/gitea/modules/context" | "code.gitea.io/gitea/modules/context" | ||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/options" | |||||
"code.gitea.io/gitea/modules/public" | "code.gitea.io/gitea/modules/public" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/templates" | "code.gitea.io/gitea/modules/templates" | ||||
m.Use(templates.Renderer()) | m.Use(templates.Renderer()) | ||||
models.InitMailRender(templates.Mailer()) | models.InitMailRender(templates.Mailer()) | ||||
localeNames, err := bindata.AssetDir("conf/locale") | |||||
localeNames, err := options.Dir("locale") | |||||
if err != nil { | if err != nil { | ||||
log.Fatal(4, "Fail to list locale files: %v", err) | log.Fatal(4, "Fail to list locale files: %v", err) | ||||
} | } | ||||
localFiles := make(map[string][]byte) | localFiles := make(map[string][]byte) | ||||
for _, name := range localeNames { | for _, name := range localeNames { | ||||
localFiles[name] = bindata.MustAsset("conf/locale/" + name) | |||||
localFiles[name], err = options.Locale(name) | |||||
if err != nil { | |||||
log.Fatal(4, "Failed to load %s locale file. %v", name, err) | |||||
} | |||||
} | } | ||||
m.Use(i18n.I18n(i18n.Options{ | m.Use(i18n.I18n(i18n.Options{ | ||||
SubURL: setting.AppSubURL, | |||||
Files: localFiles, | |||||
CustomDirectory: path.Join(setting.CustomPath, "conf/locale"), | |||||
Langs: setting.Langs, | |||||
Names: setting.Names, | |||||
DefaultLang: "en-US", | |||||
Redirect: true, | |||||
SubURL: setting.AppSubURL, | |||||
Files: localFiles, | |||||
Langs: setting.Langs, | |||||
Names: setting.Names, | |||||
DefaultLang: "en-US", | |||||
Redirect: true, | |||||
})) | })) | ||||
m.Use(cache.Cacher(cache.Options{ | m.Use(cache.Cacher(cache.Options{ | ||||
Adapter: setting.CacheAdapter, | Adapter: setting.CacheAdapter, |
Execute following command in ROOT directory when anything is changed: | |||||
$ make bindata |
# NEVER EVER MODIFY THIS FILE | |||||
# PLEASE MAKE CHANGES ON CORRESPONDING CUSTOM CONFIG FILE | |||||
; App name that shows on every page title | ; App name that shows on every page title | ||||
APP_NAME = Gitea: Git with a cup of tea | APP_NAME = Gitea: Git with a cup of tea | ||||
; Change it if you run locally | ; Change it if you run locally |
"time" | "time" | ||||
"code.gitea.io/git" | "code.gitea.io/git" | ||||
"code.gitea.io/gitea/modules/bindata" | |||||
"code.gitea.io/gitea/modules/log" | "code.gitea.io/gitea/modules/log" | ||||
"code.gitea.io/gitea/modules/markdown" | "code.gitea.io/gitea/modules/markdown" | ||||
"code.gitea.io/gitea/modules/options" | |||||
"code.gitea.io/gitea/modules/process" | "code.gitea.io/gitea/modules/process" | ||||
"code.gitea.io/gitea/modules/setting" | "code.gitea.io/gitea/modules/setting" | ||||
"code.gitea.io/gitea/modules/sync" | "code.gitea.io/gitea/modules/sync" | ||||
types := []string{"gitignore", "license", "readme", "label"} | types := []string{"gitignore", "license", "readme", "label"} | ||||
typeFiles := make([][]string, 4) | typeFiles := make([][]string, 4) | ||||
for i, t := range types { | for i, t := range types { | ||||
files, err := bindata.AssetDir("conf/" + t) | |||||
files, err := options.Dir(t) | |||||
if err != nil { | if err != nil { | ||||
log.Fatal(4, "Fail to get %s files: %v", t, err) | log.Fatal(4, "Fail to get %s files: %v", t, err) | ||||
} | } | ||||
customPath := path.Join(setting.CustomPath, "conf", t) | |||||
customPath := path.Join(setting.CustomPath, "options", t) | |||||
if com.IsDir(customPath) { | if com.IsDir(customPath) { | ||||
customFiles, err := com.StatDir(customPath) | customFiles, err := com.StatDir(customPath) | ||||
if err != nil { | if err != nil { | ||||
} | } | ||||
func getRepoInitFile(tp, name string) ([]byte, error) { | func getRepoInitFile(tp, name string) ([]byte, error) { | ||||
relPath := path.Join("conf", tp, strings.TrimLeft(name, "./")) | |||||
cleanedName := strings.TrimLeft(name, "./") | |||||
relPath := path.Join("options", tp, cleanedName) | |||||
// Use custom file when available. | // Use custom file when available. | ||||
customPath := path.Join(setting.CustomPath, relPath) | customPath := path.Join(setting.CustomPath, relPath) | ||||
if com.IsFile(customPath) { | if com.IsFile(customPath) { | ||||
return ioutil.ReadFile(customPath) | return ioutil.ReadFile(customPath) | ||||
} | } | ||||
return bindata.Asset(relPath) | |||||
switch tp { | |||||
case "readme": | |||||
return options.Readme(cleanedName) | |||||
case "gitignore": | |||||
return options.Gitignore(cleanedName) | |||||
case "license": | |||||
return options.License(cleanedName) | |||||
default: | |||||
return []byte{}, fmt.Errorf("Invalid init file type") | |||||
} | |||||
} | } | ||||
func prepareRepoCommit(repo *Repository, tmpDir, repoPath string, opts CreateRepoOptions) error { | func prepareRepoCommit(repo *Repository, tmpDir, repoPath string, opts CreateRepoOptions) error { |
func TestMain(m *testing.M) { | func TestMain(m *testing.M) { | ||||
// setup | // setup | ||||
macaroni18n.I18n(macaroni18n.Options{ | macaroni18n.I18n(macaroni18n.Options{ | ||||
Directory: "../../conf/locale/", | |||||
Directory: "../../options/locale/", | |||||
DefaultLang: "en-US", | DefaultLang: "en-US", | ||||
Langs: []string{"en-US"}, | Langs: []string{"en-US"}, | ||||
Names: []string{"english"}, | Names: []string{"english"}, |
// +build !bindata | |||||
// Copyright 2016 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 options | |||||
import ( | |||||
"fmt" | |||||
"io/ioutil" | |||||
"path" | |||||
"code.gitea.io/gitea/modules/setting" | |||||
"github.com/Unknwon/com" | |||||
) | |||||
var ( | |||||
directories = make(directorySet) | |||||
) | |||||
// Dir returns all files from static or custom directory. | |||||
func Dir(name string) ([]string, error) { | |||||
if directories.Filled(name) { | |||||
return directories.Get(name), nil | |||||
} | |||||
var ( | |||||
result []string | |||||
) | |||||
customDir := path.Join(setting.CustomPath, "options", name) | |||||
if com.IsDir(customDir) { | |||||
files, err := com.StatDir(customDir, true) | |||||
if err != nil { | |||||
return []string{}, fmt.Errorf("Failed to read custom directory. %v", err) | |||||
} | |||||
result = append(result, files...) | |||||
} | |||||
staticDir := path.Join(setting.StaticRootPath, "options", name) | |||||
if com.IsDir(staticDir) { | |||||
files, err := com.StatDir(staticDir, true) | |||||
if err != nil { | |||||
return []string{}, fmt.Errorf("Failed to read static directory. %v", err) | |||||
} | |||||
result = append(result, files...) | |||||
} | |||||
return directories.AddAndGet(name, result), nil | |||||
} | |||||
// Locale reads the content of a specific locale from static or custom path. | |||||
func Locale(name string) ([]byte, error) { | |||||
return fileFromDir(path.Join("locale", name)) | |||||
} | |||||
// Readme reads the content of a specific readme from static or custom path. | |||||
func Readme(name string) ([]byte, error) { | |||||
return fileFromDir(path.Join("readme", name)) | |||||
} | |||||
// Gitignore reads the content of a specific gitignore from static or custom path. | |||||
func Gitignore(name string) ([]byte, error) { | |||||
return fileFromDir(path.Join("gitignore", name)) | |||||
} | |||||
// License reads the content of a specific license from static or custom path. | |||||
func License(name string) ([]byte, error) { | |||||
return fileFromDir(path.Join("license", name)) | |||||
} | |||||
// fileFromDir is a helper to read files from static or custom path. | |||||
func fileFromDir(name string) ([]byte, error) { | |||||
customPath := path.Join(setting.CustomPath, "options", name) | |||||
if com.IsFile(customPath) { | |||||
return ioutil.ReadFile(customPath) | |||||
} | |||||
staticPath := path.Join(setting.StaticRootPath, "options", name) | |||||
if com.IsFile(staticPath) { | |||||
return ioutil.ReadFile(staticPath) | |||||
} | |||||
return []byte{}, fmt.Errorf("Asset file does not exist: %s", name) | |||||
} |
// Copyright 2016 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 options | |||||
//go:generate go-bindata -tags "bindata" -ignore "TRANSLATORS" -pkg "options" -o "bindata.go" ../../options/... | |||||
//go:generate go fmt bindata.go | |||||
//go:generate sed -i.bak s/..\/..\/options\/// bindata.go | |||||
//go:generate rm -f bindata.go.bak | |||||
type directorySet map[string][]string | |||||
func (s directorySet) Add(key string, value []string) { | |||||
_, ok := s[key] | |||||
if !ok { | |||||
s[key] = make([]string, 0, len(value)) | |||||
} | |||||
s[key] = append(s[key], value...) | |||||
} | |||||
func (s directorySet) Get(key string) []string { | |||||
_, ok := s[key] | |||||
if ok { | |||||
result := []string{} | |||||
seen := map[string]string{} | |||||
for _, val := range s[key] { | |||||
if _, ok := seen[val]; !ok { | |||||
result = append(result, val) | |||||
seen[val] = val | |||||
} | |||||
} | |||||
return result | |||||
} | |||||
return []string{} | |||||
} | |||||
func (s directorySet) AddAndGet(key string, value []string) []string { | |||||
s.Add(key, value) | |||||
return s.Get(key) | |||||
} | |||||
func (s directorySet) Filled(key string) bool { | |||||
return len(s[key]) > 0 | |||||
} |
// +build bindata | |||||
// Copyright 2016 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 options | |||||
import ( | |||||
"fmt" | |||||
"io/ioutil" | |||||
"path" | |||||
"code.gitea.io/gitea/modules/setting" | |||||
"github.com/Unknwon/com" | |||||
) | |||||
var ( | |||||
directories = make(directorySet) | |||||
) | |||||
// Dir returns all files from bindata or custom directory. | |||||
func Dir(name string) ([]string, error) { | |||||
if directories.Filled(name) { | |||||
return directories.Get(name), nil | |||||
} | |||||
var ( | |||||
result []string | |||||
) | |||||
customDir := path.Join(setting.CustomPath, "options", name) | |||||
if com.IsDir(customDir) { | |||||
files, err := com.StatDir(customDir, true) | |||||
if err != nil { | |||||
return []string{}, fmt.Errorf("Failed to read custom directory. %v", err) | |||||
} | |||||
result = append(result, files...) | |||||
} | |||||
files, err := AssetDir(path.Join("..", "..", "options", name)) | |||||
if err != nil { | |||||
return []string{}, fmt.Errorf("Failed to read embedded directory. %v", err) | |||||
} | |||||
result = append(result, files...) | |||||
return directories.AddAndGet(name, result), nil | |||||
} | |||||
// Locale reads the content of a specific locale from bindata or custom path. | |||||
func Locale(name string) ([]byte, error) { | |||||
return fileFromDir(path.Join("locale", name)) | |||||
} | |||||
// Readme reads the content of a specific readme from bindata or custom path. | |||||
func Readme(name string) ([]byte, error) { | |||||
return fileFromDir(path.Join("readme", name)) | |||||
} | |||||
// Gitignore reads the content of a gitignore locale from bindata or custom path. | |||||
func Gitignore(name string) ([]byte, error) { | |||||
return fileFromDir(path.Join("gitignore", name)) | |||||
} | |||||
// License reads the content of a specific license from bindata or custom path. | |||||
func License(name string) ([]byte, error) { | |||||
return fileFromDir(path.Join("license", name)) | |||||
} | |||||
// fileFromDir is a helper to read files from bindata or custom path. | |||||
func fileFromDir(name string) ([]byte, error) { | |||||
customPath := path.Join(setting.CustomPath, "options", name) | |||||
if com.IsFile(customPath) { | |||||
return ioutil.ReadFile(customPath) | |||||
} | |||||
return Asset(name) | |||||
} |
"strings" | "strings" | ||||
"time" | "time" | ||||
"code.gitea.io/gitea/modules/log" | |||||
"code.gitea.io/gitea/modules/user" | |||||
"github.com/Unknwon/com" | "github.com/Unknwon/com" | ||||
_ "github.com/go-macaron/cache/memcache" // memcache plugin for cache | _ "github.com/go-macaron/cache/memcache" // memcache plugin for cache | ||||
_ "github.com/go-macaron/cache/redis" | _ "github.com/go-macaron/cache/redis" | ||||
_ "github.com/kardianos/minwinsvc" // import minwinsvc for windows services | _ "github.com/kardianos/minwinsvc" // import minwinsvc for windows services | ||||
"gopkg.in/ini.v1" | "gopkg.in/ini.v1" | ||||
"strk.kbt.io/projects/go/libravatar" | "strk.kbt.io/projects/go/libravatar" | ||||
"code.gitea.io/gitea/modules/bindata" | |||||
"code.gitea.io/gitea/modules/log" | |||||
"code.gitea.io/gitea/modules/user" | |||||
) | ) | ||||
// Scheme describes protocol types | // Scheme describes protocol types | ||||
log.Fatal(4, "Fail to get work directory: %v", err) | log.Fatal(4, "Fail to get work directory: %v", err) | ||||
} | } | ||||
Cfg, err = ini.Load(bindata.MustAsset("conf/app.ini")) | |||||
Cfg = ini.Empty() | |||||
if err != nil { | if err != nil { | ||||
log.Fatal(4, "Fail to parse 'conf/app.ini': %v", err) | |||||
log.Fatal(4, "Fail to parse 'app.ini': %v", err) | |||||
} | } | ||||
CustomPath = os.Getenv("GITEA_CUSTOM") | CustomPath = os.Getenv("GITEA_CUSTOM") | ||||
if err = Cfg.Section("server").MapTo(&SSH); err != nil { | if err = Cfg.Section("server").MapTo(&SSH); err != nil { | ||||
log.Fatal(4, "Fail to map SSH settings: %v", err) | log.Fatal(4, "Fail to map SSH settings: %v", err) | ||||
} | } | ||||
SSH.KeygenPath = sec.Key("SSH_KEYGEN_PATH").MustString("ssh-keygen") | |||||
SSH.Port = sec.Key("SSH_PORT").MustInt(22) | |||||
// When disable SSH, start builtin server value is ignored. | // When disable SSH, start builtin server value is ignored. | ||||
if SSH.Disabled { | if SSH.Disabled { | ||||
SSH.StartBuiltinServer = false | SSH.StartBuiltinServer = false | ||||
"StampNano": time.StampNano, | "StampNano": time.StampNano, | ||||
}[Cfg.Section("time").Key("FORMAT").MustString("RFC1123")] | }[Cfg.Section("time").Key("FORMAT").MustString("RFC1123")] | ||||
RunUser = Cfg.Section("").Key("RUN_USER").String() | |||||
RunUser = Cfg.Section("").Key("RUN_USER").MustString(user.CurrentUsername()) | |||||
// Does not check run user when the install lock is off. | // Does not check run user when the install lock is off. | ||||
if InstallLock { | if InstallLock { | ||||
currentUser, match := IsRunUserMatchCurrentUser(RunUser) | currentUser, match := IsRunUserMatchCurrentUser(RunUser) | ||||
} | } | ||||
Langs = Cfg.Section("i18n").Key("LANGS").Strings(",") | Langs = Cfg.Section("i18n").Key("LANGS").Strings(",") | ||||
if len(Langs) == 0 { | |||||
Langs = []string{ | |||||
"en-US", | |||||
} | |||||
} | |||||
Names = Cfg.Section("i18n").Key("NAMES").Strings(",") | Names = Cfg.Section("i18n").Key("NAMES").Strings(",") | ||||
if len(Names) == 0 { | |||||
Names = []string{ | |||||
"English", | |||||
} | |||||
} | |||||
dateLangs = Cfg.Section("i18n.datelang").KeysHash() | dateLangs = Cfg.Section("i18n.datelang").KeysHash() | ||||
ShowFooterBranding = Cfg.Section("other").Key("SHOW_FOOTER_BRANDING").MustBool() | ShowFooterBranding = Cfg.Section("other").Key("SHOW_FOOTER_BRANDING").MustBool() | ||||
} | } | ||||
func newLogService() { | func newLogService() { | ||||
log.Info("%s %s", AppName, AppVer) | |||||
log.Info("Gitea v%s", AppVer) | |||||
// Get and check log mode. | |||||
LogModes = strings.Split(Cfg.Section("log").Key("MODE").MustString("console"), ",") | LogModes = strings.Split(Cfg.Section("log").Key("MODE").MustString("console"), ",") | ||||
LogConfigs = make([]string, len(LogModes)) | LogConfigs = make([]string, len(LogModes)) | ||||
for i, mode := range LogModes { | for i, mode := range LogModes { | ||||
mode = strings.TrimSpace(mode) | mode = strings.TrimSpace(mode) | ||||
sec, err := Cfg.GetSection("log." + mode) | sec, err := Cfg.GetSection("log." + mode) | ||||
if err != nil { | if err != nil { | ||||
log.Fatal(4, "Unknown log mode: %s", mode) | |||||
sec, _ = Cfg.NewSection("log." + mode) | |||||
} | } | ||||
validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"} | validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"} |