// checkVersion checks if binary matches the version of templates files. func checkVersion() { // Templates. data, err := ioutil.ReadFile(setting.StaticRootPath + "/templates/.VERSION") if err != nil { log.Fatal(4, "Fail to read 'templates/.VERSION': %v", err) } if string(data) != setting.AppVer { //log.Fatal(4, "Binary和templates文件版本不匹配,你是不是忘了重新编译?") } // 检查依赖版本 checkers := []VerChecker{ {"github.com/go-xorm/xorm", func() string { return xorm.Version }, "0.5.2.0304"}, {"github.com/go-macaron/binding", binding.Version, "0.2.1"}, {"github.com/go-macaron/cache", cache.Version, "0.1.2"}, {"github.com/go-macaron/csrf", csrf.Version, "0.1.0"}, {"github.com/go-macaron/i18n", i18n.Version, "0.2.0"}, {"github.com/go-macaron/session", session.Version, "0.1.6"}, {"github.com/go-macaron/toolbox", toolbox.Version, "0.1.0"}, {"gopkg.in/ini.v1", ini.Version, "1.8.4"}, {"gopkg.in/macaron.v1", macaron.Version, "1.1.2"}, {"github.com/gogits/git-module", git.Version, "0.2.9"}, {"github.com/gogits/go-gogs-client", gogs.Version, "0.7.4"}, } for _, c := range checkers { if !version.Compare(c.Version(), c.Expected, ">=") { log.Fatal(4, "Package '%s' version is too old (%s -> %s), did you forget to update?", c.ImportPath, c.Version(), c.Expected) } } }
func newCacheService() { CacheAdapter = Cfg.Section("cache").Key("ADAPTER").In("memory", []string{"memory", "redis", "memcache"}) switch CacheAdapter { case "memory": CacheInternal = Cfg.Section("cache").Key("INTERVAL").MustInt(60) case "redis", "memcache": CacheConn = strings.Trim(Cfg.Section("cache").Key("HOST").String(), "\" ") default: log.Fatal(4, "Unknown cache adapter: %s", CacheAdapter) } log.Info("Cache Service Enabled") }
func init() { IsWindows = runtime.GOOS == "windows" log.NewLogger(0, "console", `{"level": 0}`) var err error if AppPath, err = execPath(); err != nil { log.Fatal(4, "fail to get app path: %v\n", err) } // Note: we don't use path.Dir here because it does not handle case // which path starts with two "/" in Windows: "//psf/Home/..." AppPath = strings.Replace(AppPath, "\\", "/", -1) }
func newMacaron() *macaron.Macaron { m := macaron.New() // DISABLE_ROUTER_LOG: 激活该选项来禁止打印路由日志 // 判断是否禁用,如果禁用则引入macaron日志 if !setting.DisableRouterLog { m.Use(macaron.Logger()) } // 引入macaron恢复机制 m.Use(macaron.Recovery()) if setting.Protocol == setting.FCGI { m.SetURLPrefix(setting.AppSubUrl) } // 设定静态资源路径 m.Use(macaron.Static( path.Join(setting.StaticRootPath, "public"), macaron.StaticOptions{ SkipLogging: setting.DisableRouterLog, }, )) m.Use(macaron.Static( setting.AvatarUploadPath, macaron.StaticOptions{ Prefix: "avatars", SkipLogging: setting.DisableRouterLog, }, )) // 设置渲染模板 m.Use(macaron.Renderer(macaron.RenderOptions{ Directory: path.Join(setting.StaticRootPath, "templates"), AppendDirectories: []string{path.Join(setting.CustomPath, "templates")}, Funcs: template.NewFuncMap(), IndentJSON: macaron.Env != macaron.PROD, })) // 指定国际化目录 localeNames, err := bindata.AssetDir("conf/locale") if err != nil { log.Fatal(4, "Fail to list locale files: %v", err) } localFiles := make(map[string][]byte) for _, name := range localeNames { localFiles[name] = bindata.MustAsset("conf/locale/" + name) } 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, })) m.Use(cache.Cacher(cache.Options{ Adapter: setting.CacheAdapter, AdapterConfig: setting.CacheConn, Interval: setting.CacheInternal, })) m.Use(captcha.Captchaer(captcha.Options{ SubURL: setting.AppSubUrl, })) m.Use(session.Sessioner(setting.SessionConfig)) m.Use(csrf.Csrfer(csrf.Options{ Secret: setting.SecretKey, Cookie: setting.CSRFCookieName, SetCookie: true, Header: "X-Csrf-Token", CookiePath: setting.AppSubUrl, })) m.Use(toolbox.Toolboxer(m, toolbox.Options{ HealthCheckFuncs: []*toolbox.HealthCheckFuncDesc{ &toolbox.HealthCheckFuncDesc{ Desc: "Database connection", Func: models.Ping, }, }, })) //m.Use(context.Contexter()) return m }
func newLogService() { log.Info("%s %s", AppName, AppVer) if len(BuildTime) > 0 { log.Info("Build Time: %s", BuildTime) log.Info("Build Git Hash: %s", BuildGitHash) } // Get and check log mode. LogModes = strings.Split(Cfg.Section("log").Key("MODE").MustString("console"), ",") LogConfigs = make([]string, len(LogModes)) for i, mode := range LogModes { mode = strings.TrimSpace(mode) sec, err := Cfg.GetSection("log." + mode) if err != nil { log.Fatal(4, "Unknown log mode: %s", mode) } validLevels := []string{"Trace", "Debug", "Info", "Warn", "Error", "Critical"} // Log level. levelName := Cfg.Section("log."+mode).Key("LEVEL").In( Cfg.Section("log").Key("LEVEL").In("Trace", validLevels), validLevels) level, ok := logLevels[levelName] if !ok { log.Fatal(4, "Unknown log level: %s", levelName) } // Generate log configuration. switch mode { case "console": LogConfigs[i] = fmt.Sprintf(`{"level":%s}`, level) case "file": logPath := sec.Key("FILE_NAME").MustString(path.Join(LogRootPath, "gogs.log")) if err = os.MkdirAll(path.Dir(logPath), os.ModePerm); err != nil { panic(err.Error()) } LogConfigs[i] = fmt.Sprintf( `{"level":%s,"filename":"%s","rotate":%v,"maxlines":%d,"maxsize":%d,"daily":%v,"maxdays":%d}`, level, logPath, sec.Key("LOG_ROTATE").MustBool(true), sec.Key("MAX_LINES").MustInt(1000000), 1<<uint(sec.Key("MAX_SIZE_SHIFT").MustInt(28)), sec.Key("DAILY_ROTATE").MustBool(true), sec.Key("MAX_DAYS").MustInt(7)) case "conn": LogConfigs[i] = fmt.Sprintf(`{"level":%s,"reconnectOnMsg":%v,"reconnect":%v,"net":"%s","addr":"%s"}`, level, sec.Key("RECONNECT_ON_MSG").MustBool(), sec.Key("RECONNECT").MustBool(), sec.Key("PROTOCOL").In("tcp", []string{"tcp", "unix", "udp"}), sec.Key("ADDR").MustString(":7020")) case "smtp": LogConfigs[i] = fmt.Sprintf(`{"level":%s,"username":"******","password":"******","host":"%s","sendTos":"%s","subject":"%s"}`, level, sec.Key("USER").MustString("*****@*****.**"), sec.Key("PASSWD").MustString("******"), sec.Key("HOST").MustString("127.0.0.1:25"), sec.Key("RECEIVERS").MustString("[]"), sec.Key("SUBJECT").MustString("Diagnostic message from serve")) case "database": LogConfigs[i] = fmt.Sprintf(`{"level":%s,"driver":"%s","conn":"%s"}`, level, sec.Key("DRIVER").String(), sec.Key("CONN").String()) } log.NewLogger(Cfg.Section("log").Key("BUFFER_LEN").MustInt64(10000), mode, LogConfigs[i]) log.Info("Log Mode: %s(%s)", strings.Title(mode), levelName) } }
// NewContext initializes configuration context. // NOTE: do not print any log except error. func NewContext() { workDir, err := WorkDir() if err != nil { log.Fatal(4, "Fail to get work directory: %v", err) } Cfg, err = ini.Load(bindata.MustAsset("conf/app.ini")) if err != nil { log.Fatal(4, "Fail to parse 'conf/app.ini': %v", err) } CustomPath = os.Getenv("GOGS_CUSTOM") if len(CustomPath) == 0 { CustomPath = workDir + "/custom" } if len(CustomConf) == 0 { CustomConf = CustomPath + "/conf/app.ini" } if com.IsFile(CustomConf) { if err = Cfg.Append(CustomConf); err != nil { log.Fatal(4, "Fail to load custom conf '%s': %v", CustomConf, err) } } else { log.Warn("Custom config '%s' not found, ignore this if you're running first time", CustomConf) } Cfg.NameMapper = ini.AllCapsUnderscore homeDir, err := com.HomeDir() if err != nil { log.Fatal(4, "Fail to get home directory: %v", err) } homeDir = strings.Replace(homeDir, "\\", "/", -1) LogRootPath = Cfg.Section("log").Key("ROOT_PATH").MustString(path.Join(workDir, "log")) forcePathSeparator(LogRootPath) sec := Cfg.Section("server") AppName = Cfg.Section("").Key("APP_NAME").MustString("Gogs: Go Git Service") AppUrl = sec.Key("ROOT_URL").MustString("http://localhost:3000/") if AppUrl[len(AppUrl)-1] != '/' { AppUrl += "/" } // Check if has app suburl. url, err := url.Parse(AppUrl) if err != nil { log.Fatal(4, "Invalid ROOT_URL '%s': %s", AppUrl, err) } // Suburl should start with '/' and end without '/', such as '/{subpath}'. AppSubUrl = strings.TrimSuffix(url.Path, "/") AppSubUrlDepth = strings.Count(AppSubUrl, "/") Protocol = HTTP if sec.Key("PROTOCOL").String() == "https" { Protocol = HTTPS CertFile = sec.Key("CERT_FILE").String() KeyFile = sec.Key("KEY_FILE").String() } else if sec.Key("PROTOCOL").String() == "fcgi" { Protocol = FCGI } Domain = sec.Key("DOMAIN").MustString("localhost") HttpAddr = sec.Key("HTTP_ADDR").MustString("0.0.0.0") HttpPort = sec.Key("HTTP_PORT").MustString("3000") LocalURL = sec.Key("LOCAL_ROOT_URL").MustString("http://localhost:" + HttpPort + "/") OfflineMode = sec.Key("OFFLINE_MODE").MustBool() DisableRouterLog = sec.Key("DISABLE_ROUTER_LOG").MustBool() StaticRootPath = sec.Key("STATIC_ROOT_PATH").MustString(workDir) AppDataPath = sec.Key("APP_DATA_PATH").MustString("data") EnableGzip = sec.Key("ENABLE_GZIP").MustBool() switch sec.Key("LANDING_PAGE").MustString("home") { case "explore": LandingPageUrl = LANDING_PAGE_EXPLORE default: LandingPageUrl = LANDING_PAGE_HOME } SSH.RootPath = path.Join(homeDir, ".ssh") SSH.KeyTestPath = os.TempDir() if err = Cfg.Section("server").MapTo(&SSH); err != nil { log.Fatal(4, "Fail to map SSH settings: %v", err) } // When disable SSH, start builtin server value is ignored. if SSH.Disabled { SSH.StartBuiltinServer = false } if !SSH.Disabled && !SSH.StartBuiltinServer { if err := os.MkdirAll(SSH.RootPath, 0700); err != nil { log.Fatal(4, "Fail to create '%s': %v", SSH.RootPath, err) } else if err = os.MkdirAll(SSH.KeyTestPath, 0644); err != nil { log.Fatal(4, "Fail to create '%s': %v", SSH.KeyTestPath, err) } } SSH.MinimumKeySizeCheck = sec.Key("MINIMUM_KEY_SIZE_CHECK").MustBool() SSH.MinimumKeySizes = map[string]int{} minimumKeySizes := Cfg.Section("ssh.minimum_key_sizes").Keys() for _, key := range minimumKeySizes { if key.MustInt() != -1 { SSH.MinimumKeySizes[strings.ToLower(key.Name())] = key.MustInt() } } sec = Cfg.Section("security") InstallLock = sec.Key("INSTALL_LOCK").MustBool() SecretKey = sec.Key("SECRET_KEY").String() LogInRememberDays = sec.Key("LOGIN_REMEMBER_DAYS").MustInt() CookieUserName = sec.Key("COOKIE_USERNAME").String() CookieRememberName = sec.Key("COOKIE_REMEMBER_NAME").String() ReverseProxyAuthUser = sec.Key("REVERSE_PROXY_AUTHENTICATION_USER").MustString("X-WEBAUTH-USER") sec = Cfg.Section("attachment") AttachmentPath = sec.Key("PATH").MustString(path.Join(AppDataPath, "attachments")) if !filepath.IsAbs(AttachmentPath) { AttachmentPath = path.Join(workDir, AttachmentPath) } AttachmentAllowedTypes = strings.Replace(sec.Key("ALLOWED_TYPES").MustString("image/jpeg,image/png"), "|", ",", -1) AttachmentMaxSize = sec.Key("MAX_SIZE").MustInt64(4) AttachmentMaxFiles = sec.Key("MAX_FILES").MustInt(5) AttachmentEnabled = sec.Key("ENABLE").MustBool(true) TimeFormat = map[string]string{ "ANSIC": time.ANSIC, "UnixDate": time.UnixDate, "RubyDate": time.RubyDate, "RFC822": time.RFC822, "RFC822Z": time.RFC822Z, "RFC850": time.RFC850, "RFC1123": time.RFC1123, "RFC1123Z": time.RFC1123Z, "RFC3339": time.RFC3339, "RFC3339Nano": time.RFC3339Nano, "Kitchen": time.Kitchen, "Stamp": time.Stamp, "StampMilli": time.StampMilli, "StampMicro": time.StampMicro, "StampNano": time.StampNano, }[Cfg.Section("time").Key("FORMAT").MustString("RFC1123")] RunUser = Cfg.Section("").Key("RUN_USER").String() curUser := user.CurrentUsername() // Does not check run user when the install lock is off. if InstallLock && RunUser != curUser { log.Fatal(4, "Expect user(%s) but current user is: %s", RunUser, curUser) } // Determine and create root git repository path. sec = Cfg.Section("repository") RepoRootPath = sec.Key("ROOT").MustString(path.Join(homeDir, "gogs-repositories")) forcePathSeparator(RepoRootPath) if !filepath.IsAbs(RepoRootPath) { RepoRootPath = path.Join(workDir, RepoRootPath) } else { RepoRootPath = path.Clean(RepoRootPath) } ScriptType = sec.Key("SCRIPT_TYPE").MustString("bash") if err = Cfg.Section("repository").MapTo(&Repository); err != nil { log.Fatal(4, "Fail to map Repository settings: %v", err) } // UI settings. sec = Cfg.Section("ui") ExplorePagingNum = sec.Key("EXPLORE_PAGING_NUM").MustInt(20) IssuePagingNum = sec.Key("ISSUE_PAGING_NUM").MustInt(10) FeedMaxCommitNum = sec.Key("FEED_MAX_COMMIT_NUM").MustInt(5) sec = Cfg.Section("ui.admin") AdminUserPagingNum = sec.Key("USER_PAGING_NUM").MustInt(50) AdminRepoPagingNum = sec.Key("REPO_PAGING_NUM").MustInt(50) AdminNoticePagingNum = sec.Key("NOTICE_PAGING_NUM").MustInt(50) AdminOrgPagingNum = sec.Key("ORG_PAGING_NUM").MustInt(50) ThemeColorMetaTag = sec.Key("THEME_COLOR_META_TAG").MustString("#ff5343") sec = Cfg.Section("picture") AvatarUploadPath = sec.Key("AVATAR_UPLOAD_PATH").MustString(path.Join(AppDataPath, "avatars")) forcePathSeparator(AvatarUploadPath) if !filepath.IsAbs(AvatarUploadPath) { AvatarUploadPath = path.Join(workDir, AvatarUploadPath) } switch source := sec.Key("GRAVATAR_SOURCE").MustString("gravatar"); source { case "duoshuo": GravatarSource = "http://gravatar.duoshuo.com/avatar/" case "gravatar": GravatarSource = "https://secure.gravatar.com/avatar/" default: GravatarSource = source } DisableGravatar = sec.Key("DISABLE_GRAVATAR").MustBool() if OfflineMode { DisableGravatar = true } if err = Cfg.Section("markdown").MapTo(&Markdown); err != nil { log.Fatal(4, "Fail to map Markdown settings: %v", err) } else if err = Cfg.Section("git").MapTo(&Git); err != nil { log.Fatal(4, "Fail to map Git settings: %v", err) } else if err = Cfg.Section("cron").MapTo(&Cron); err != nil { log.Fatal(4, "Fail to map Cron settings: %v", err) } Langs = Cfg.Section("i18n").Key("LANGS").Strings(",") Names = Cfg.Section("i18n").Key("NAMES").Strings(",") dateLangs = Cfg.Section("i18n.datelang").KeysHash() ShowFooterBranding = Cfg.Section("other").Key("SHOW_FOOTER_BRANDING").MustBool() ShowFooterVersion = Cfg.Section("other").Key("SHOW_FOOTER_VERSION").MustBool() HasRobotsTxt = com.IsFile(path.Join(CustomPath, "robots.txt")) }
func forcePathSeparator(path string) { if strings.Contains(path, "\\") { log.Fatal(4, "Do not use '\\' or '\\\\' in paths, instead, please use '/' in all places") } }