changelog.go 1.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. // Copyright (C) 2014 The Syncthing Authors.
  2. //
  3. // This Source Code Form is subject to the terms of the Mozilla Public
  4. // License, v. 2.0. If a copy of the MPL was not distributed with this file,
  5. // You can obtain one at http://mozilla.org/MPL/2.0/.
  6. package main
  7. import (
  8. "bytes"
  9. "flag"
  10. "fmt"
  11. "log"
  12. "os/exec"
  13. "regexp"
  14. )
  15. var (
  16. subjectIssues = regexp.MustCompile(`^([^(]+)\s+\((?:fixes|ref) ([^)]+)\)(?:[^\w])?$`)
  17. issueNumbers = regexp.MustCompile(`(#\d+)`)
  18. )
  19. func main() {
  20. flag.Parse()
  21. // Display changelog since the version given on the command line, or
  22. // figure out the last release if there were no arguments.
  23. var prevRel string
  24. if flag.NArg() > 0 {
  25. prevRel = flag.Arg(0)
  26. } else {
  27. bs, err := runError("git", "describe", "--abbrev=0", "HEAD^")
  28. if err != nil {
  29. log.Fatal(err)
  30. }
  31. prevRel = string(bs)
  32. }
  33. // Get the git log with subject and author nickname
  34. bs, err := runError("git", "log", "--reverse", "--pretty=format:%s|%aN", prevRel+"..")
  35. if err != nil {
  36. log.Fatal(err)
  37. }
  38. // Split into lines
  39. for _, line := range bytes.Split(bs, []byte{'\n'}) {
  40. // Split into subject and author
  41. fields := bytes.Split(line, []byte{'|'})
  42. subj := fields[0]
  43. author := fields[1]
  44. // Check if subject contains a "(fixes ...)" or "(ref ...)""
  45. if m := subjectIssues.FindSubmatch(subj); len(m) > 0 {
  46. // Find all issue numbers
  47. issues := issueNumbers.FindAll(m[2], -1)
  48. // Format a changelog entry
  49. fmt.Printf("* %s (%s, @%s)\n", m[1], bytes.Join(issues, []byte(", ")), author)
  50. }
  51. }
  52. }
  53. func runError(cmd string, args ...string) ([]byte, error) {
  54. ecmd := exec.Command(cmd, args...)
  55. bs, err := ecmd.CombinedOutput()
  56. if err != nil {
  57. return nil, err
  58. }
  59. return bytes.TrimSpace(bs), nil
  60. }