\n| When | Title | Comment of |
\n")
log, err := repo.Log(&git.LogOptions{From: head.Hash()})
if err != nil {
makeErr(err)
}
- errOccured := false
+ commentN := 0
for i := 0; i < offset; i++ {
- commit, err = log.Next()
- if err != nil {
+ if _, err = log.Next(); err != nil {
break
}
+ commentN++
+ }
+
+ entries := make([]TableEntry, 0, PageEntries)
+ logEnded := false
+ for _, data := range etagHashForWeb {
+ etagHash.Write(data)
}
+ etagHash.Write([]byte("INDEX"))
for i := 0; i < PageEntries; i++ {
- commit, err = log.Next()
+ commit, err := log.Next()
if err != nil {
- errOccured = true
+ logEnded = true
break
}
- if i == 0 {
- etagHash.Write(commit.Hash[:])
- checkETag(etagHash)
- }
- lines := msgSplit(commit.Message)
+ etagHash.Write(commit.Hash[:])
+ commentsRaw := getCommentsRaw(commit.Hash)
+ etagHash.Write(commentsRaw)
+ entries = append(entries, TableEntry{commit, commentsRaw})
+ }
+ checkETag(etagHash)
+
+ var table bytes.Buffer
+ table.WriteString(
+ "\n" +
+ "| N | " +
+ "When | " +
+ "Title | " +
+ "L | " +
+ "C | " +
+ "Linked to |
\n")
+ for _, entry := range entries {
+ commentN++
+ lines := msgSplit(entry.commit.Message)
domains := []string{}
for _, line := range lines[2:] {
if u := urlParse(line); u == nil {
@@ -325,67 +365,73 @@ } else {
domains = append(domains, makeA(line, u.Host))
}
}
- entry := []string{
- makeA(urlPrefix+"/"+commit.Hash.String(), lines[0]),
- fmt.Sprintf("(%dL)", len(lines)-2),
- }
- if note := getNote(commit.Hash); note != "" {
- entry = append(entry, "(N)")
+ var commentsValue string
+ if l := len(parseComments(entry.commentsRaw)); l > 0 {
+ commentsValue = strconv.Itoa(l)
+ } else {
+ commentsValue = " "
}
table.WriteString(fmt.Sprintf(
- "| %s | %s | %s |
\n",
- commit.Author.When.Format(WhenFmt),
- strings.Join(entry, " "),
+ "| %d | %s | "+
+ "%s | "+
+ "%d | %s | "+
+ "%s |
\n",
+ commentN, entry.commit.Author.When.Format(WhenFmt),
+ makeA(cfg.URLPrefix+"/"+entry.commit.Hash.String(), lines[0]),
+ len(lines)-2,
+ commentsValue,
strings.Join(domains, " "),
))
}
table.WriteString("
")
+
+ var href string
var links []string
var refs bytes.Buffer
if offset > 0 {
- offsetPrev := offset - PageEntries
- if offsetPrev < 0 {
- offsetPrev = 0
+ if offsetPrev := offset - PageEntries; offsetPrev > 0 {
+ href = cfg.URLPrefix + "/?offset=" + strconv.Itoa(offsetPrev)
+ } else {
+ href = cfg.URLPrefix + "/"
}
- href := urlPrefix + "/?offset=" + strconv.Itoa(offsetPrev)
- links = append(links, fmt.Sprintf(
- ``, href,
- ))
- refs.WriteString(makeA(href, "[prev]"))
+ links = append(links, ``)
+ refs.WriteString(makeA(href, " [prev]"))
}
- if !errOccured {
- href := urlPrefix + "/?offset=" + strconv.Itoa(offset+PageEntries)
- links = append(links, fmt.Sprintf(
- ``, href,
- ))
- refs.WriteString(makeA(href, "[next]"))
+ if !logEnded {
+ href = cfg.URLPrefix + "/?offset=" + strconv.Itoa(offset+PageEntries)
+ links = append(links, ``)
+ refs.WriteString(makeA(href, " [next]"))
}
+
os.Stdout.Write([]byte(startHeader(etagHash, gzipWriter != nil)))
out.Write([]byte(startHTML(
- fmt.Sprintf("%s (%d-%d)", blogTitle, offset, offset+PageEntries),
+ fmt.Sprintf("%s (%d-%d)", cfg.Title, offset, offset+PageEntries),
links,
)))
+ if cfg.AboutURL != "" {
+ out.Write([]byte(fmt.Sprintf("[%s]", makeA(cfg.AboutURL, "about"))))
+ }
out.Write(refs.Bytes())
out.Write(table.Bytes())
out.Write(refs.Bytes())
out.Write([]byte("\n"))
} else if pathInfo == "/"+AtomFeed {
- commit, err = repo.CommitObject(head.Hash())
+ commit, err := repo.CommitObject(head.Hash())
if err != nil {
makeErr(err)
}
- etagHash.Write(commit.Hash[:])
etagHash.Write([]byte("ATOM"))
+ etagHash.Write(commit.Hash[:])
checkETag(etagHash)
feed := atom.Feed{
- Title: blogTitle,
- ID: atomId,
+ Title: cfg.Title,
+ ID: cfg.AtomId,
Updated: atom.Time(commit.Author.When),
Link: []atom.Link{{
Rel: "self",
- Href: atomUrl,
+ Href: atomURL,
}},
- Author: &atom.Person{Name: atomAuthorName},
+ Author: &atom.Person{Name: cfg.AtomAuthor},
}
log, err := repo.Log(&git.LogOptions{From: head.Hash()})
if err != nil {
@@ -396,17 +442,26 @@ commit, err = log.Next()
if err != nil {
break
}
+
+ feedIdRaw := new([16]byte)
+ copy(feedIdRaw[:], commit.Hash[:])
+ feedIdRaw[6] = (feedIdRaw[6] & 0x0F) | uint8(4<<4) // version 4
+ feedId := fmt.Sprintf(
+ "%x-%x-%x-%x-%x",
+ feedIdRaw[0:4],
+ feedIdRaw[4:6],
+ feedIdRaw[6:8],
+ feedIdRaw[8:10],
+ feedIdRaw[10:],
+ )
+
lines := msgSplit(commit.Message)
- feedId, err := uuid.FromBytes(commit.Hash[:16])
- if err != nil {
- panic(err)
- }
feed.Entry = append(feed.Entry, &atom.Entry{
Title: lines[0],
- ID: "urn:uuid:" + feedId.String(),
+ ID: "urn:uuid:" + feedId,
Link: []atom.Link{{
Rel: "alternate",
- Href: blogBaseURL + urlPrefix + "/" + commit.Hash.String(),
+ Href: cfg.BaseURL + cfg.URLPrefix + "/" + commit.Hash.String(),
}},
Published: atom.Time(commit.Author.When),
Updated: atom.Time(commit.Author.When),
@@ -435,11 +490,17 @@ os.Stdout.WriteString("\n")
os.Stdout.Write(outBuf.Bytes())
return
} else if sha1DigestRe.MatchString(pathInfo[1:]) {
- commit, err = repo.CommitObject(plumbing.NewHash(pathInfo[1:]))
+ commit, err := repo.CommitObject(plumbing.NewHash(pathInfo[1:]))
if err != nil {
makeErr(err)
}
+ for _, data := range etagHashForWeb {
+ etagHash.Write(data)
+ }
+ etagHash.Write([]byte("ENTRY"))
etagHash.Write(commit.Hash[:])
+ commentsRaw := getCommentsRaw(commit.Hash)
+ etagHash.Write(commentsRaw)
checkETag(etagHash)
lines := msgSplit(commit.Message)
title := lines[0]
@@ -449,48 +510,55 @@ links := []string{}
var parent string
if len(commit.ParentHashes) > 0 {
parent = commit.ParentHashes[0].String()
- links = append(links, fmt.Sprintf(
- ``,
- urlPrefix+"/"+parent,
- ))
+ links = append(links, ``)
}
out.Write([]byte(startHTML(fmt.Sprintf("%s (%s)", title, when), links)))
+ if cfg.AboutURL != "" {
+ out.Write([]byte(fmt.Sprintf("[%s] ", makeA(cfg.AboutURL, "about"))))
+ }
if parent != "" {
out.Write([]byte(fmt.Sprintf(
- "[%s] [%s]\n
\n",
- makeA(urlPrefix+"/"+parent, "older"),
- when,
+ "[%s] ",
+ makeA(cfg.URLPrefix+"/"+parent, "older"),
)))
}
- out.Write([]byte(fmt.Sprintf("%s
\n\n", title)))
+ out.Write([]byte(fmt.Sprintf(
+ "[%s] [%s]
\n%s
\n\n",
+ when, commit.Hash.String(), title,
+ )))
for _, line := range lines[2:] {
- line = strings.ReplaceAll(line, "&", "&")
- line = strings.ReplaceAll(line, "<", "<")
- line = strings.ReplaceAll(line, ">", ">")
+ line = html.EscapeString(line)
cols := strings.Split(line, " ")
for i, col := range cols {
if u := urlParse(col); u != nil {
cols[i] = makeA(col, col)
continue
}
- cols[i] = sha1DigestRe.ReplaceAllString(col, makeA(urlPrefix+"/$1", "$1"))
+ cols[i] = sha1DigestRe.ReplaceAllString(col, makeA(
+ cfg.URLPrefix+"/$1", "$1",
+ ))
}
line = strings.Join(cols, " ")
out.Write([]byte(line + "\n"))
}
- out.Write([]byte("\n"))
- if note := getNote(commit.Hash); note != "" {
- out.Write([]byte(fmt.Sprintf("Note:\n\n%s
\n", note)))
+ out.Write([]byte("
\n
\n"))
+ if cfg.CommentsEmail != "" {
+ out.Write([]byte("[" + makeA(
+ "mailto:"+cfg.CommentsEmail+"?subject="+commit.Hash.String(),
+ "write comment",
+ ) + "]\n"))
}
+ out.Write([]byte("\n"))
+ for i, comment := range parseComments(commentsRaw) {
+ out.Write([]byte(fmt.Sprintf(
+ "- comment %d:"+
+ "
\n\n%s\n
\n",
+ i, i, i, html.EscapeString(comment),
+ )))
+ }
+ out.Write([]byte("
\n"))
} else {
makeErr(errors.New("unknown URL action"))
- }
- if aboutUrl != "" {
- out.Write([]byte(fmt.Sprintf(
- "
%s %s\n",
- makeA(aboutUrl, "About"),
- blogTitle,
- )))
}
out.Write([]byte("