+
+func serveGopher() {
+ cfgPath := os.Args[2]
+ cfgRaw, err := ioutil.ReadFile(cfgPath)
+ if err != nil {
+ log.Fatalln(err)
+ }
+ var cfgGeneral map[string]interface{}
+ if err = hjson.Unmarshal(cfgRaw, &cfgGeneral); err != nil {
+ log.Fatalln(err)
+ }
+ cfgRaw, err = json.Marshal(cfgGeneral)
+ if err != nil {
+ log.Fatalln(err)
+ }
+ var cfg *Cfg
+ if err = json.Unmarshal(cfgRaw, &cfg); err != nil {
+ log.Fatalln(err)
+ }
+ if cfg.GopherDomain == "" {
+ log.Fatalln("GopherDomain is not configured")
+ }
+
+ headHash, err := initRepo(cfg)
+ if err != nil {
+ log.Fatalln(err)
+ }
+
+ scanner := bufio.NewScanner(io.LimitReader(os.Stdin, 1<<8))
+ if !scanner.Scan() {
+ log.Fatalln(errors.New("no CRLF found"))
+ }
+ selector := scanner.Text()
+ if selector == "" {
+ selector = "offset/0"
+ }
+ if strings.HasPrefix(selector, "offset/") {
+ offset, err := strconv.Atoi(selector[len("offset/"):])
+ if err != nil {
+ log.Fatalln(err)
+ }
+ repoLog, err := repo.Log(&git.LogOptions{From: *headHash})
+ if err != nil {
+ log.Fatalln(err)
+ }
+ commitN := 0
+ for i := 0; i < offset; i++ {
+ if _, err = repoLog.Next(); err != nil {
+ break
+ }
+ commitN++
+ }
+
+ logEnded := false
+ var menu bytes.Buffer
+ for i := 0; i < PageEntries; i++ {
+ commit, err := repoLog.Next()
+ if err != nil {
+ logEnded = true
+ break
+ }
+ commitN++
+ lines := msgSplit(commit.Message)
+
+ var commentsValue string
+ if l := len(parseComments(getNote(commentsTree, commit.Hash))); l > 0 {
+ commentsValue = fmt.Sprintf(" (%dC)", l)
+ }
+ menu.WriteString(fmt.Sprintf(
+ "0[%s] %s (%dL)%s\t/%s\t%s\t%d%s",
+ commit.Author.When.Format(sgblog.WhenFmt),
+ lines[0],
+ len(lines)-2,
+ commentsValue,
+ commit.Hash.String(),
+ cfg.GopherDomain, 70, CRLF,
+ ))
+ }
+
+ var links bytes.Buffer
+ if offset > 0 {
+ offsetPrev := offset - PageEntries
+ if offsetPrev < 0 {
+ offsetPrev = 0
+ }
+ links.WriteString(fmt.Sprintf(
+ "1Prev\toffset/%d\t%s\t%d%s",
+ offsetPrev,
+ cfg.GopherDomain, 70, CRLF,
+ ))
+ }
+ if !logEnded {
+ links.WriteString(fmt.Sprintf(
+ "1Next\toffset/%d\t%s\t%d%s",
+ offset+PageEntries,
+ cfg.GopherDomain, 70, CRLF,
+ ))
+ }
+
+ fmt.Printf(
+ "i%s (%d-%d)\t\tnull.host\t1%s",
+ cfg.Title,
+ offset,
+ offset+PageEntries,
+ CRLF,
+ )
+ if cfg.AboutURL != "" {
+ fmt.Printf("iAbout: %s\t\tnull.host\t1%s", cfg.AboutURL, CRLF)
+ }
+ fmt.Print(links.String())
+ fmt.Print(menu.String())
+ fmt.Print("." + CRLF)
+ } else if sha1DigestRe.MatchString(selector) {
+ commit, err := repo.CommitObject(plumbing.NewHash(selector[1:]))
+ if err != nil {
+ log.Fatalln(err)
+ }
+ fmt.Printf(
+ "What: %s\nWhen: %s\n%s\n%s",
+ commit.Hash.String(),
+ commit.Author.When.Format(sgblog.WhenFmt),
+ DashLine,
+ commit.Message,
+ )
+ notesRaw := getNote(notesTree, commit.Hash)
+ if len(notesRaw) > 0 {
+ fmt.Printf("%s\nNote:\n%s\n", DashLine, string(notesRaw))
+ }
+ for i, comment := range parseComments(getNote(commentsTree, commit.Hash)) {
+ fmt.Printf("%s\ncomment %d:\n%s\n", DashLine, i, comment)
+ }
+ } else {
+ log.Fatalln(errors.New("unknown selector"))
+ }
+}
+
+func main() {
+ if len(os.Args) == 3 && os.Args[1] == "-gopher" {
+ serveGopher()
+ } else {
+ serveHTTP()
+ }
+}