headers. @code{From} is a name of email sender (with email address
stripped off).
-Technically comments are stored in concatenated
-@url{https://en.wikipedia.org/wiki/Netstring, netstring}. Only
-@code{text/plain} or @code{multipart/signed+text/plain} email messages
-are accepted and only with UTF-8, US-ASCII, ISO-8859-1 character sets.
-Sane people won't send HTML email anyway, but this is just a precaution.
+Only @code{text/plain} or @code{multipart/signed+text/plain} email
+messages are accepted and only with UTF-8, US-ASCII, ISO-8859-1
+character sets. Sane people won't send HTML email anyway, but this is
+just a precaution.
+
+Comments are stored in @dfn{recfiles} --
+@url{https://www.gnu.org/software/recutils/, GNU recutils}
+human-editable plaintext database format. But they do not contain
+records description:
+
+@verbatim
+%rec: Comment
+%doc: SGBlog's comment
+%mandatory: From Date Body
+%type: Date date
+@end verbatim
@node Topics
@unnumbered Topics
"syscall"
"time"
- "go.cypherpunks.ru/netstring/v2"
"go.stargrave.org/sgblog"
)
// Remove various whitespaces and excess lines, because git-notes-add
// will remove and we have to know exact bytes count
-func cleanupBody(body string) string {
+func cleanupBody(body string) []string {
lines := strings.Split(string(body), "\n")
for i, line := range lines {
line = strings.ReplaceAll(line, " ", " ")
}
withoutDups = append(withoutDups, line)
}
- return strings.Join(withoutDups, "\n")
+ return withoutDups
}
func main() {
note = bytes.TrimRight(note, "\r\n")
buf := bytes.NewBuffer(note)
- w := netstring.NewWriter(buf)
- w.WriteChunk([]byte(fmt.Sprintf(
- "From: %s\nDate: %s\n\n%s",
+ buf.WriteString(fmt.Sprintf(
+ "\n\nFrom: %s\nDate: %s\nBody:\n",
from,
time.Now().UTC().Format(sgblog.WhenFmt),
- cleanupBody(string(body)),
- )))
+ ))
+ for _, s := range cleanupBody(string(body)) {
+ buf.WriteString("+ ")
+ buf.WriteString(s)
+ buf.WriteString("\n")
+ }
if *dryRun {
fmt.Print(buf.String())
"github.com/go-git/go-git/v5"
"github.com/go-git/go-git/v5/plumbing"
"github.com/go-git/go-git/v5/plumbing/object"
- "go.cypherpunks.ru/netstring/v2"
)
const (
func parseComments(data []byte) []string {
comments := []string{}
- nsr := netstring.NewReader(bytes.NewReader(data))
- for {
- if _, err := nsr.Next(); err != nil {
- break
+ isBody := false
+ comment := make([]string, 0, 4)
+ lines := strings.Split(strings.TrimSuffix(string(data), "\n"), "\n")
+ if len(lines) == 1 {
+ return comments
+ }
+ for _, s := range lines {
+ if s == "" {
+ comments = append(comments, strings.Join(comment, "\n"))
+ comment = make([]string, 0, 4)
+ isBody = false
+ continue
}
- if comment, err := ioutil.ReadAll(nsr); err == nil {
- comments = append(comments, string(comment))
+ if s == "Body:" {
+ isBody = true
+ comment = append(comment, "")
+ continue
}
+ if isBody {
+ if s == "+" {
+ comment = append(comment, "")
+ } else {
+ comment = append(comment, strings.TrimPrefix(s, "+ "))
+ }
+ continue
+ }
+ comment = append(comment, s)
+ }
+ if len(comment) > 1 {
+ comments = append(comments, strings.Join(comment, "\n"))
}
return comments
}
package sgblog
const (
- Version = "0.8.0"
+ Version = "0.9.0"
WhenFmt = "2006-01-02 15:04:05Z07:00"
)
github.com/go-git/go-git/v5 v5.1.0
github.com/hjson/hjson-go v3.0.1+incompatible
github.com/imdario/mergo v0.3.11 // indirect
- go.cypherpunks.ru/netstring/v2 v2.0.0
golang.org/x/crypto v0.0.0-20200820211705-5c72a883971a
golang.org/x/net v0.0.0-20200925080053-05aa5d4ee321 // indirect
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d // indirect
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/xanzy/ssh-agent v0.2.1 h1:TCbipTQL2JiiCprBWx9frJ2eJlCYT00NmctrHxVAr70=
github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4=
-go.cypherpunks.ru/netstring/v2 v2.0.0 h1:or1LDZO3fSd6iITGR3jJUfUrjvRgeNlUpEYI13qaRBk=
-go.cypherpunks.ru/netstring/v2 v2.0.0/go.mod h1:6YDx4gW414SmHdvSBMKbHaB2/7w9WZ04NQb7XIUV/pA=
golang.org/x/crypto v0.0.0-20190219172222-a4c6cb3142f2/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=