func main() { log.Info("Go Walker %s", APP_VER) log.Info("Run Mode: %s", strings.Title(macaron.Env)) m := newMacaron() m.Get("/", routers.Home) m.Get("/search", routers.Search) m.Get("/search/json", routers.SearchJSON) m.Group("/api", func() { m.Group("/v1", func() { m.Get("/badge", apiv1.Badge) }) }) m.Get("/robots.txt", func() string { return `User-agent: * Disallow: /search` }) m.Get("/*", routers.Docs) listenAddr := fmt.Sprintf("0.0.0.0:%d", setting.HTTPPort) log.Info("Listen: http://%s", listenAddr) if err := http.ListenAndServe(listenAddr, m); err != nil { log.FatalD(4, "Fail to start server: %v", err) } }
func main() { // flag.Parse() log.Info("App Version: %s", APP_VER) var port string if port = os.Getenv(PortVar); port == "" { port = "8080" } log.Info("PORT: %s", port) m := macaron.Classic() m.Use(macaron.Renderer()) // m.Use(middleware.Contexter()) m.Get("/", func() string { return "Hello" }) m.Get("/fibonacci", v1.Fibonacci) // log.Info("PORT: %s", setting.HTTPPort) // _ = setting.HTTPPort http.ListenAndServe(":"+port, m) // http.ListenAndServe(fmt.Sprintf(":%d", *port), m) // http.ListenAndServe(":"+setting.HTTPPort, m) // m.Run(":" + setting.HTTPPort) }
func main() { log.Info("Peach %s", APP_VER) m := macaron.New() m.Use(macaron.Logger()) m.Use(macaron.Recovery()) m.Use(macaron.Statics(macaron.StaticOptions{ SkipLogging: setting.ProdMode, }, "custom/public", "public")) m.Use(i18n.I18n(i18n.Options{ Files: setting.Docs.Locales, })) tplDir := "templates" if setting.Page.UseCustomTpl { tplDir = "custom/templates" } m.Use(pongo2.Pongoer(pongo2.Options{ Directory: tplDir, })) m.Use(middleware.Contexter()) m.Get("/", routers.Home) m.Get("/docs", routers.Docs) m.Get("/docs/images/*", routers.DocsStatic) m.Get("/docs/*", routers.Docs) m.Post("/hook", routers.Hook) m.Get("/search", routers.Search) m.Get("/*", routers.Pages) m.NotFound(routers.NotFound) listenAddr := fmt.Sprintf("0.0.0.0:%d", setting.HTTPPort) log.Info("%s Listen on %s", setting.Site.Name, listenAddr) log.Fatal("Fail to start Peach: %v", http.ListenAndServe(listenAddr, m)) }
func sendFile(fileName string) { f, err := os.Open(fileName) if err != nil { log.Error("Fail to open file: %v", err) return } defer f.Close() fi, err := os.Stat(fileName) if err != nil { log.Error("Fail to stat file: %v", err) return } fileName = strings.Replace(fileName, "\\", "/", -1) //path.Base() log.Info("File name: %s; size: %s", fileName, com.HumaneFileSize(uint64(fi.Size()))) conn, err := net.Dial("tcp", setting.Cfg.Sync.RemoteAddr) if err != nil { log.Error("Fail to establish connection: %v", err) return } defer conn.Close() log.Info("Connection established") conn.Write([]byte(fileName)) p := make([]byte, 2) _, err = conn.Read(p) if err != nil { log.Error("Cannot get response from server: %v", err) return } else if string(p) != "ok" { log.Error("Invalid response: %s", string(p)) return } log.Info("Header sent") start := time.Now() _, err = io.Copy(conn, f) if err != nil { log.Error("Fail to send file(%s): %v", fileName, err) return } spend := time.Since(start) log.Info("File sent, speed: %s/s", com.HumaneFileSize(uint64((fi.Size()*1000000000/int64(spend))/1024))) }
func receiveHandler(conn net.Conn) { defer conn.Close() remoteAddr := conn.RemoteAddr().String() p := make([]byte, 1024) n, err := conn.Read(p) if err != nil { log.Error("Cannot read header(%s): %v", remoteAddr, err) return } else if n == 0 { log.Error("Empty header(%s)", remoteAddr) return } fileName := string(p[:n]) log.Info("File: %s", fileName) os.MkdirAll(path.Dir(fileName), os.ModePerm) f, err := os.Create(fileName) if err != nil { log.Error("Fail to create file(%s:%s): %v", remoteAddr, fileName, err) return } defer f.Close() conn.Write([]byte("ok")) _, err = io.Copy(f, conn) for { buffer := make([]byte, 1024*200) n, err := conn.Read(buffer) //blockSize := int64(n) _ = n if err != nil && err != io.EOF { log.Error("Cannot read(%s:%s): %v", remoteAddr, fileName, err) } else if err == io.EOF { break } } if err != nil { log.Error("Fail to receive file(%s:%s): %v\n", remoteAddr, fileName, err) return } log.Info("File received: %s", fileName) }
func main() { log.Info("App Version: %s", APP_VER) m := macaron.Classic() m.Use(macaron.Renderer()) m.Use(middleware.Contexter()) m.Get("/fibonacci", v1.Fibonacci) m.Run(setting.HTTPPort) }
func runWeb(ctx *cli.Context) { if ctx.IsSet("config") { setting.CustomConf = ctx.String("config") } setting.NewContext() models.NewContext() log.Info("Peach %s", setting.AppVer) m := macaron.New() m.Use(macaron.Logger()) m.Use(macaron.Recovery()) m.Use(macaron.Statics(macaron.StaticOptions{ SkipLogging: setting.ProdMode, }, "custom/public", "public", models.HTMLRoot)) m.Use(i18n.I18n(i18n.Options{ Files: setting.Docs.Locales, DefaultLang: setting.Docs.Langs[0], })) tplDir := "templates" if setting.Page.UseCustomTpl { tplDir = "custom/templates" } m.Use(pongo2.Pongoer(pongo2.Options{ Directory: tplDir, })) m.Use(middleware.Contexter()) m.Get("/", routers.Home) m.Get("/docs", routers.Docs) m.Get("/docs/images/*", routers.DocsStatic) m.Get("/docs/*", routers.Protect, routers.Docs) m.Post("/hook", routers.Hook) m.Get("/search", routers.Search) m.Get("/*", routers.Pages) m.NotFound(routers.NotFound) listenAddr := fmt.Sprintf("0.0.0.0:%d", setting.HTTPPort) log.Info("%s Listen on %s", setting.Site.Name, listenAddr) log.Fatal("Fail to start Peach: %v", http.ListenAndServe(listenAddr, m)) }
func Hook(ctx *middleware.Context) { if ctx.Query("secret") != setting.Docs.Secret { ctx.Error(403) return } log.Info("Incoming hook update request") if err := models.ReloadDocs(); err != nil { ctx.Error(500) return } ctx.Status(200) }
func main() { setting.AppVer = APP_VER log.Info("%s %s", setting.AppName, setting.AppVer) log.Info("Run Mode: %s", strings.Title(macaron.Env)) m := macaron.Classic() m.Use(macaron.Static(setting.ArchivePath, macaron.StaticOptions{ Prefix: "/archive", })) m.Use(pongo2.Pongoer()) m.Use(middleware.Contexter()) m.Get("/", func(ctx *middleware.Context) { ctx.Data["Targets"] = models.Targets ctx.HTML(200, "home") }) if setting.Webhook.Mode == "test" { m.Get("/hook", func(ctx *middleware.Context) { if err := models.Build(ctx.Query("ref")); err != nil { ctx.JSON(500, map[string]interface{}{ "error": err.Error(), }) return } ctx.Status(200) }) } else { m.Post("/hook", func(ctx *middleware.Context) { }) } listenAddr := "0.0.0.0:" + com.ToStr(setting.HTTPPort) log.Info("Listen on http://%s", listenAddr) fmt.Println(http.ListenAndServe(listenAddr, m)) }
func runClient(ctx *cli.Context) { if len(setting.Cfg.Sync.RemoteAddr) == 0 { log.Fatal("Remote address cannot be empty") } watcher, err := fsnotify.NewWatcher() if err != nil { log.Fatal("Fail to create new watcher: %v", err) } defer watcher.Close() go func() { for { select { case e := <-watcher.Events: if isTmpFile(e.Name) { continue } if e.Op&fsnotify.Create == fsnotify.Create || e.Op&fsnotify.Write == fsnotify.Write { if com.IsDir(e.Name) { log.Warn("Hasn't support directory yet") continue } sendFile(strings.TrimPrefix(e.Name, setting.WorkDir+"/")) } } } }() if err = watcher.Add(setting.WorkDir); err != nil { log.Fatal("Fail to watch directory(%s): %v", setting.WorkDir, err) } dirs, err := com.GetAllSubDirs(setting.WorkDir) if err != nil { log.Fatal("Fail to get subdirectories(%s): %v", setting.WorkDir, err) } for _, dir := range dirs { if err = watcher.Add(path.Join(setting.WorkDir, dir)); err != nil { log.Fatal("Fail to watch directory(%s): %v", path.Join(setting.WorkDir, dir), err) } } log.Info("Start watching...") select {} }
func gracefulKill() { // Given process a chance to exit itself. runningCmd.Process.Signal(os.Interrupt) // Wait for timeout, and force kill after that. for i := 0; i < setting.Cfg.Run.InterruptTimeout; i++ { time.Sleep(1 * time.Second) if runningCmd.ProcessState == nil || runningCmd.ProcessState.Exited() { return } } log.Info("Fail to graceful kill, force killing...") runningCmd.Process.Kill() }
func notify(cmds [][]string) { runningLock.Lock() defer func() { runningCmd = nil runningLock.Unlock() }() for _, cmd := range cmds { command := exec.Command(cmd[0], cmd[1:]...) command.Stdout = os.Stdout command.Stderr = os.Stderr if err := command.Start(); err != nil { log.Error("Fail to start command %v - %v", cmd, err) fmt.Print("\x07") return } log.Debug("Running %v", cmd) runningCmd = command done := make(chan error) go func() { done <- command.Wait() }() isShutdown := false select { case err := <-done: if isShutdown { return } else if err != nil { log.Warn("Fail to execute command %v - %v", cmd, err) fmt.Print("\x07") return } case <-shutdown: isShutdown = true gracefulKill() return } } log.Info("Notify operations are done!") }
func runServer(ctx *cli.Context) { if len(setting.Cfg.Sync.ListenAddr) == 0 { log.Fatal("Listen address cannot be empty") } l, err := net.Listen("tcp", setting.Cfg.Sync.ListenAddr) if err != nil { log.Fatal("Fail to start server on listening(%s): %v", setting.Cfg.Sync.ListenAddr, err) } log.Info("Listening on %s...", setting.Cfg.Sync.ListenAddr) for { conn, err := l.Accept() if err != nil { if ne, ok := err.(net.Error); !ok || !ne.Temporary() { log.Warn("Network error when accpet: %v", err) } continue } go receiveHandler(conn) } }
func notify(cmds [][]string) { runningLock.Lock() defer func() { runningCmd = nil runningLock.Unlock() }() for _, cmd := range cmds { command := exec.Command(cmd[0], cmd[1:]...) command.Stdout = os.Stdout command.Stderr = os.Stderr if err := command.Start(); err != nil { log.Error("Fail to start command %v", cmd) fmt.Print("\x07") return } runningCmd = command done := make(chan error) go func() { done <- command.Wait() }() select { case err := <-done: if err != nil { if strings.Contains(err.Error(), "signal: killed") { return } log.Warn("Fail to execute command %v", cmd) fmt.Print("\x07") return } } } log.Info("Notify operations are done!") }
// CheckGoPackage checks package by import path. func CheckPackage(importPath string, render macaron.Render, rt requestType) (*models.PkgInfo, error) { // Trim prefix of standard library. importPath = strings.TrimPrefix(importPath, "github.com/golang/go/tree/master/src") pinfo, err := models.GetPkgInfo(importPath) if rt != REQUEST_TYPE_REFRESH { if err == nil { fpath := setting.DocsGobPath + importPath + ".gob" if !setting.ProdMode && com.IsFile(fpath) { pdoc := new(Package) fr, err := os.Open(fpath) if err != nil { return nil, fmt.Errorf("read gob: %v", err) } else if err = gob.NewDecoder(fr).Decode(pdoc); err != nil { fr.Close() return nil, fmt.Errorf("decode gob: %v", err) } fr.Close() if err = renderDoc(render, pdoc, importPath); err != nil { return nil, fmt.Errorf("render cached doc: %v", err) } } pinfo.Views++ if err = models.SavePkgInfo(pinfo); err != nil { return nil, fmt.Errorf("update views: %v", err) } return pinfo, nil } } // Just in case, should never happen. if err == models.ErrEmptyPackagePath { return nil, err } var etag string if err != models.ErrPackageVersionTooOld && pinfo != nil { etag = pinfo.Etag } // Fetch package from VCS. c := make(chan crawlResult, 1) go func() { pdoc, err := crawlDoc(importPath, etag) c <- crawlResult{pdoc, err} }() var pdoc *Package err = nil // Reset. select { case cr := <-c: if cr.err == nil { pdoc = cr.pdoc } else { err = cr.err } case <-time.After(setting.FetchTimeout): err = ErrFetchTimeout } if err != nil { if err == ErrPackageNotModified { log.Debug("Package has not been modified: %s", pinfo.ImportPath) // Update time so cannot refresh too often. pinfo.Created = time.Now().UTC().Unix() return pinfo, models.SavePkgInfo(pinfo) } else if err == ErrInvalidRemotePath { return nil, ErrInvalidRemotePath // Allow caller to make redirect to search. } return nil, fmt.Errorf("check package: %v", err) } if !setting.ProdMode { fpath := setting.DocsGobPath + importPath + ".gob" os.MkdirAll(path.Dir(fpath), os.ModePerm) fw, err := os.Create(fpath) if err != nil { return nil, fmt.Errorf("create gob: %v", err) } defer fw.Close() if err = gob.NewEncoder(fw).Encode(pdoc); err != nil { return nil, fmt.Errorf("encode gob: %v", err) } } log.Info("Walked package: %s, Goroutine #%d", pdoc.ImportPath, runtime.NumGoroutine()) if err = renderDoc(render, pdoc, importPath); err != nil { return nil, fmt.Errorf("render doc: %v", err) } if pinfo != nil { pdoc.Id = pinfo.Id } pdoc.Created = time.Now().UTC().Unix() if err = models.SavePkgInfo(pdoc.PkgInfo); err != nil { return nil, fmt.Errorf("SavePkgInfo: %v", err) } return pdoc.PkgInfo, nil }
func runRun(ctx *cli.Context) { setup(ctx) go catchSignals() go notify(setting.Cfg.Run.InitCmds) watchPathes := append([]string{setting.WorkDir}, setting.Cfg.Run.WatchDirs...) if setting.Cfg.Run.WatchAll { subdirs := make([]string, 0, 10) for _, dir := range watchPathes[1:] { dirs, err := com.GetAllSubDirs(setting.UnpackPath(dir)) if err != nil { log.Fatal("Fail to get sub-directories: %v", err) } for i := range dirs { if !setting.IgnoreDir(dirs[i]) { subdirs = append(subdirs, path.Join(dir, dirs[i])) } } } watchPathes = append(watchPathes, subdirs...) } watcher, err := fsnotify.NewWatcher() if err != nil { log.Fatal("Fail to create new watcher: %v", err) } defer watcher.Close() go func() { for { select { case e := <-watcher.Events: needsNotify := true if isTmpFile(e.Name) || !hasWatchExt(e.Name) || setting.IgnoreFile(e.Name) { continue } // Prevent duplicated builds. if lastBuild.Add(time.Duration(setting.Cfg.Run.BuildDelay) * time.Millisecond). After(time.Now()) { continue } lastBuild = time.Now() showName := e.String() if !log.NonColor { showName = strings.Replace(showName, setting.WorkDir, "\033[47;30m$WORKDIR\033[0m", 1) } if e.Op&fsnotify.Remove != fsnotify.Remove { mt, err := com.FileMTime(e.Name) if err != nil { log.Error("Fail to get file modify time: %v", err) continue } if eventTime[e.Name] == mt { log.Debug("Skipped %s", showName) needsNotify = false } eventTime[e.Name] = mt } if needsNotify { log.Info(showName) if runningCmd != nil && runningCmd.Process != nil { if runningCmd.Args[0] == "sudo" && runtime.GOOS == "linux" { // 给父进程发送一个TERM信号,试图杀死它和它的子进程 rootCmd := exec.Command("sudo", "kill", "-TERM", com.ToStr(runningCmd.Process.Pid)) rootCmd.Stdout = os.Stdout rootCmd.Stderr = os.Stderr if err := rootCmd.Run(); err != nil { log.Error("Fail to start rootCmd %s", err.Error()) fmt.Print("\x07") } } else { shutdown <- true } } go notify(setting.Cfg.Run.Cmds) } } } }() log.Info("Following directories are monitored:") for i, p := range watchPathes { if err = watcher.Add(setting.UnpackPath(p)); err != nil { log.Fatal("Fail to watch diretory(%s): %v", p, err) } if i > 0 && !log.NonColor { p = strings.Replace(p, setting.WorkDir, "\033[47;30m$WORKDIR\033[0m", 1) p = strings.Replace(p, "$WORKDIR", "\033[47;30m$WORKDIR\033[0m", 1) } fmt.Printf("-> %s\n", p) } select {} }
func setup(ctx *cli.Context) { log.Info("App Version: %s", AppVer) setting.InitSetting() }