浏览代码

Add sampling and commits settings

Vadim Markovtsev 8 年之前
父节点
当前提交
af9ddc0db7
共有 3 个文件被更改,包括 59 次插入11 次删除
  1. 1 0
      README.md
  2. 10 8
      analyser.go
  3. 48 3
      cmd/hercules/main.go

+ 1 - 0
README.md

@@ -9,6 +9,7 @@ This tool calculates the weekly lines burnout in a Git repository.
 hercules https://github.com/src-d/go-git | python3 labours.py
 hercules /path/to/cloned/go-git | python3 labours.py
 hercules https://github.com/torvalds/linux /tmp/linux_cache | python3 labours.py
+git rev-list HEAD | tac | hercules -commits -sampling 7 - https://github.com/src-d/go-git | python3 labours.py
 ```
 
 ###License

+ 10 - 8
analyser.go

@@ -17,6 +17,7 @@ import (
 type Analyser struct {
 	Repository  *git.Repository
 	Granularity int
+	Sampling    int
 	OnProgress  func(int, int)
 }
 
@@ -166,7 +167,7 @@ func (analyser *Analyser) handleRename(from, to string, files map[string]*File)
 	delete(files, from)
 }
 
-func (analyser *Analyser) commits() []*git.Commit {
+func (analyser *Analyser) Commits() []*git.Commit {
 	result := []*git.Commit{}
 	repository := analyser.Repository
 	head, err := repository.Head()
@@ -193,6 +194,9 @@ func (analyser *Analyser) commits() []*git.Commit {
 
 func (analyser *Analyser) groupStatus(status map[int]int64, day int) []int64 {
 	granularity := analyser.Granularity
+	if granularity == 0 {
+		granularity = 1
+	}
 	result := make([]int64, day/granularity)
 	var group int64
 	for i := 0; i < day; i++ {
@@ -205,10 +209,10 @@ func (analyser *Analyser) groupStatus(status map[int]int64, day int) []int64 {
 	return result
 }
 
-func (analyser *Analyser) Analyse() [][]int64 {
-	granularity := analyser.Granularity
-	if granularity == 0 {
-		granularity = 1
+func (analyser *Analyser) Analyse(commits []*git.Commit) [][]int64 {
+	sampling := analyser.Sampling
+	if sampling == 0 {
+		sampling = 1
 	}
 	onProgress := analyser.OnProgress
 	if onProgress == nil {
@@ -222,8 +226,6 @@ func (analyser *Analyser) Analyse() [][]int64 {
 	statuses := [][]int64{}
 	// mapping <file path> -> hercules.File
 	files := map[string]*File{}
-	// list of commits belonging to the default branch, from oldest to newest
-	commits := analyser.commits()
 
 	var day0 time.Time // will be initialized in the first iteration
 	var prev_tree *git.Tree = nil
@@ -257,7 +259,7 @@ func (analyser *Analyser) Analyse() [][]int64 {
 			}()
 		} else {
 			day := int(commit.Author.When.Sub(day0).Hours() / 24)
-			delta := (day / granularity) - (prev_day / granularity)
+			delta := (day / sampling) - (prev_day / sampling)
 			if delta > 0 {
 				prev_day = day
 				statuses = append(statuses, analyser.groupStatus(status, day))

+ 48 - 3
cmd/hercules/main.go

@@ -1,29 +1,65 @@
 package main
 
 import (
+	"bufio"
 	"flag"
 	"fmt"
+	"io"
 	"os"
 	"runtime/pprof"
 	"strconv"
 	"strings"
 
 	"gopkg.in/src-d/go-git.v4"
+	"gopkg.in/src-d/go-git.v4/plumbing"
 	"gopkg.in/src-d/hercules.v1"
 )
 
+func loadCommitsFromFile(path string, repositry *git.Repository) []*git.Commit {
+	var file io.Reader
+	if path != "-" {
+		file, err := os.Open(path)
+		if err != nil {
+			panic(err)
+		}
+		defer file.Close()
+	} else {
+		file = os.Stdin
+	}
+	scanner := bufio.NewScanner(file)
+	commits := []*git.Commit{}
+	for scanner.Scan() {
+		hash := plumbing.NewHash(scanner.Text())
+		if len(hash) != 20 {
+			panic("invalid commit hash " + scanner.Text())
+		}
+		commit, err := repositry.Commit(hash)
+		if err != nil {
+			panic(err)
+		}
+		commits = append(commits, commit)
+	}
+	return commits
+}
+
 func main() {
 	var profile bool
-	var granularity int
+	var granularity, sampling int
+	var commitsFile string
 	flag.BoolVar(&profile, "profile", false, "Collect the profile to hercules.pprof.")
 	flag.IntVar(&granularity, "granularity", 30, "Report granularity in days.")
+	flag.IntVar(&sampling, "sampling", 30, "Report sampling in days.")
+	flag.StringVar(&commitsFile, "commits", "", "Path to the text file with the " +
+	    "commit history to follow instead of the default rev-list " +
+			"--first-parent. The format is the list of hashes, each hash on a " +
+			"separate line. The first hash is the root.")
 	flag.Parse()
 	if (granularity <= 0) {
 		fmt.Fprint(os.Stderr, "Warning: adjusted the granularity to 1 day\n")
 		granularity = 1
 	}
 	if profile {
-		prof, _ := os.Create("profile")
+		prof, _ := os.Create("hercules.pprof")
 		pprof.StartCPUProfile(prof)
 		defer pprof.StopCPUProfile()
 	}
@@ -68,8 +104,17 @@ func main() {
 		  fmt.Fprintf(os.Stderr, "%d / %d\r", commit, length)
 	  },
 		Granularity: granularity,
+		Sampling: sampling,
+	}
+	// list of commits belonging to the default branch, from oldest to newest
+	// rev-list --first-parent
+	var commits []*git.Commit
+	if commitsFile == "" {
+		commits = analyser.Commits()
+	} else {
+		commits = loadCommitsFromFile(commitsFile, repository)
 	}
-	statuses := analyser.Analyse()
+	statuses := analyser.Analyse(commits)
 	fmt.Fprint(os.Stderr, "        \r")
 	if len(statuses) == 0 {
 		return