2015-04-04 01:09:06 -07:00
|
|
|
// Copyright (C) 2015 The Syncthing Authors.
|
|
|
|
//
|
|
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
|
|
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
|
|
|
|
// +build ignore
|
|
|
|
|
|
|
|
// Generates the list of contributors in gui/index.html based on contents of
|
|
|
|
// AUTHORS.
|
|
|
|
|
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2016-03-13 07:38:13 -07:00
|
|
|
"bytes"
|
2015-04-04 01:09:06 -07:00
|
|
|
"io/ioutil"
|
|
|
|
"log"
|
2016-03-13 07:38:13 -07:00
|
|
|
"math"
|
2015-04-04 01:09:06 -07:00
|
|
|
"os"
|
2016-03-13 07:38:13 -07:00
|
|
|
"os/exec"
|
2015-04-04 01:09:06 -07:00
|
|
|
"regexp"
|
|
|
|
"sort"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
2016-01-10 08:37:31 -07:00
|
|
|
const htmlFile = "gui/default/syncthing/core/aboutModalView.html"
|
2015-08-01 23:27:05 -07:00
|
|
|
|
2016-03-13 07:38:13 -07:00
|
|
|
type author struct {
|
|
|
|
name string
|
|
|
|
emails []string
|
|
|
|
commits int
|
|
|
|
log10commits int
|
|
|
|
}
|
|
|
|
|
2015-04-04 01:09:06 -07:00
|
|
|
func main() {
|
2016-03-13 07:38:13 -07:00
|
|
|
authors := getAuthors()
|
|
|
|
getContributions(authors)
|
|
|
|
sort.Sort(byContributions(authors))
|
|
|
|
|
|
|
|
var lines []string
|
|
|
|
for _, author := range authors {
|
|
|
|
lines = append(lines, author.name)
|
|
|
|
}
|
|
|
|
replacement := strings.Join(lines, ", ")
|
|
|
|
|
|
|
|
authorsRe := regexp.MustCompile(`(?s)id="contributor-list">.*?</div>`)
|
|
|
|
bs := readAll(htmlFile)
|
|
|
|
bs = authorsRe.ReplaceAll(bs, []byte("id=\"contributor-list\">\n"+replacement+"\n </div>"))
|
|
|
|
|
|
|
|
if err := ioutil.WriteFile(htmlFile, bs, 0644); err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func getAuthors() []author {
|
2015-04-04 01:09:06 -07:00
|
|
|
bs := readAll("AUTHORS")
|
|
|
|
lines := strings.Split(string(bs), "\n")
|
2016-03-13 07:38:13 -07:00
|
|
|
var authors []author
|
2015-04-04 01:09:06 -07:00
|
|
|
nameRe := regexp.MustCompile(`(.+?)\s+<`)
|
2016-03-13 07:38:13 -07:00
|
|
|
authorRe := regexp.MustCompile(`<([^>]+)>`)
|
2015-04-04 01:09:06 -07:00
|
|
|
for _, line := range lines {
|
2016-03-13 07:38:13 -07:00
|
|
|
m := nameRe.FindStringSubmatch(line)
|
|
|
|
if len(m) < 2 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
name := m[1]
|
|
|
|
|
|
|
|
ms := authorRe.FindAllStringSubmatch(line, -1)
|
|
|
|
if len(ms) == 0 {
|
|
|
|
continue
|
2015-04-04 01:09:06 -07:00
|
|
|
}
|
|
|
|
|
2016-03-13 07:38:13 -07:00
|
|
|
var emails []string
|
|
|
|
for i := range ms {
|
|
|
|
emails = append(emails, ms[i][1])
|
|
|
|
}
|
2015-04-04 01:09:06 -07:00
|
|
|
|
2016-03-13 07:38:13 -07:00
|
|
|
a := author{
|
|
|
|
name: name,
|
|
|
|
emails: emails,
|
|
|
|
}
|
|
|
|
authors = append(authors, a)
|
2015-04-04 01:09:06 -07:00
|
|
|
}
|
2016-03-13 07:38:13 -07:00
|
|
|
return authors
|
2015-04-04 01:09:06 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
func readAll(path string) []byte {
|
|
|
|
fd, err := os.Open(path)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
defer fd.Close()
|
|
|
|
|
|
|
|
bs, err := ioutil.ReadAll(fd)
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
return bs
|
|
|
|
}
|
2016-03-13 07:38:13 -07:00
|
|
|
|
|
|
|
// Add number of commits per author to the author list.
|
|
|
|
func getContributions(authors []author) {
|
|
|
|
buf := new(bytes.Buffer)
|
|
|
|
cmd := exec.Command("git", "log", "--pretty=format:%ae")
|
|
|
|
cmd.Stdout = buf
|
|
|
|
err := cmd.Run()
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
next:
|
|
|
|
for _, line := range strings.Split(buf.String(), "\n") {
|
|
|
|
for i := range authors {
|
|
|
|
for _, email := range authors[i].emails {
|
|
|
|
if email == line {
|
|
|
|
authors[i].commits++
|
|
|
|
continue next
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := range authors {
|
|
|
|
authors[i].log10commits = int(math.Log10(float64(authors[i].commits + 1)))
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
type byContributions []author
|
|
|
|
|
|
|
|
func (l byContributions) Len() int { return len(l) }
|
|
|
|
|
|
|
|
// Sort first by log10(commits), then by name. This means that we first get
|
|
|
|
// an alphabetic list of people with >= 1000 commits, then a list of people
|
|
|
|
// with >= 100 commits, and so on.
|
|
|
|
func (l byContributions) Less(a, b int) bool {
|
|
|
|
if l[a].log10commits != l[b].log10commits {
|
|
|
|
return l[a].log10commits > l[b].log10commits
|
|
|
|
}
|
|
|
|
return l[a].name < l[b].name
|
|
|
|
}
|
|
|
|
|
|
|
|
func (l byContributions) Swap(a, b int) { l[a], l[b] = l[b], l[a] }
|