@@ -3,7 +3,6 @@ package todos
33import (
44 "regexp"
55 "strings"
6- "time"
76
87 "github.com/augmentable-dev/tickgit/pkg/comments"
98 "github.com/dustin/go-humanize"
@@ -16,81 +15,18 @@ import (
1615type ToDo struct {
1716 comments.Comment
1817 String string
19- Added * time.Time
20- Author string
18+ Commit * object.Commit
2119}
2220
2321// ToDos represents a list of ToDo items
2422type ToDos []* ToDo
2523
26- // Count returns the number of todos
27- func (t ToDos ) Count () int {
28- return len (t )
29- }
30-
3124// TimeAgo returns a human readable string indicating the time since the todo was added
3225func (t * ToDo ) TimeAgo () string {
33- if t .Added == nil {
26+ if t .Commit == nil {
3427 return "<unknown>"
3528 }
36- return humanize .Time (* t .Added )
37- // dur := time.Now().Sub(*t.Added)
38-
39- // hours := dur.Hours()
40- // days := hours / 24
41- // weeks := days / 7
42- // months := days / 30
43- // years := months / 12
44-
45- // if hours <= 24 {
46- // return fmt.Sprintf("~%d hours ago", int(math.Round(hours)))
47- // } else if days <= 7 {
48- // return fmt.Sprintf("~%d days ago", int(math.Round(days)))
49- // } else if weeks <= 4 {
50- // return fmt.Sprintf("~%d weeks ago", int(math.Round(weeks)))
51- // } else if months <= 12 {
52- // return fmt.Sprintf("~%d months ago", int(math.Round(months)))
53- // } else {
54- // return fmt.Sprintf("~%d years ago", int(math.Round(years)))
55- // }
56- }
57-
58- // FindBlame sets the Added and Author fields on the ToDo
59- // TODO: find ways to optimize this, set a ceiling to stop searching the history after some time
60- // run this against a batch of todos so that git history is not traversed per-todo
61- func (t * ToDo ) FindBlame (repo * git.Repository , from * object.Commit ) error {
62- commitIter , err := repo .Log (& git.LogOptions {
63- From : from .Hash ,
64- })
65- if err != nil {
66- return err
67- }
68- defer commitIter .Close ()
69-
70- prevCommit := from
71- err = commitIter .ForEach (func (commit * object.Commit ) error {
72- prevCommit = commit
73- f , err := commit .File (t .FilePath )
74- if err != nil {
75- return err
76- }
77- c , err := f .Contents ()
78- if err != nil {
79- return err
80- }
81- todoPresent := strings .Contains (c , t .String )
82-
83- if ! todoPresent {
84- return storer .ErrStop
85- }
86- return nil
87- })
88- t .Author = prevCommit .Author .String ()
89- t .Added = & (prevCommit .Author .When )
90- if err != nil {
91- return nil
92- }
93- return nil
29+ return humanize .Time (t .Commit .Author .When )
9430}
9531
9632// NewToDo produces a pointer to a ToDo from a comment
@@ -118,3 +54,56 @@ func NewToDos(comments comments.Comments) ToDos {
11854 }
11955 return todos
12056}
57+
58+ func (t * ToDo ) existsInCommit (commit * object.Commit ) (bool , error ) {
59+ f , err := commit .File (t .FilePath )
60+ if err != nil {
61+ if err == object .ErrFileNotFound {
62+ return false , nil
63+ }
64+ return false , err
65+ }
66+ c , err := f .Contents ()
67+ if err != nil {
68+ return false , err
69+ }
70+ return strings .Contains (c , t .Comment .String ()), nil
71+ }
72+
73+ // FindBlame sets the blame information on each todo in a set of todos
74+ func (t * ToDos ) FindBlame (repo * git.Repository , from * object.Commit ) error {
75+ commitIter , err := repo .Log (& git.LogOptions {
76+ From : from .Hash ,
77+ })
78+ if err != nil {
79+ return err
80+ }
81+ defer commitIter .Close ()
82+
83+ remainingTodos := * t
84+ prevCommit := from
85+ err = commitIter .ForEach (func (commit * object.Commit ) error {
86+ if len (remainingTodos ) == 0 {
87+ return storer .ErrStop
88+ }
89+ newRemainingTodos := make (ToDos , 0 )
90+ for _ , todo := range remainingTodos {
91+ exists , err := todo .existsInCommit (commit )
92+ if err != nil {
93+ return err
94+ }
95+ if ! exists { // if the todo doesn't exist in this commit, it was added in the previous commit (previous wrt the iterator, more recent in time)
96+ todo .Commit = prevCommit
97+ } else { // if the todo does exist in this commit, add it to the new list of remaining todos
98+ newRemainingTodos = append (newRemainingTodos , todo )
99+ }
100+ }
101+ prevCommit = commit
102+ remainingTodos = newRemainingTodos
103+ return nil
104+ })
105+ if err != nil {
106+ return err
107+ }
108+ return nil
109+ }
0 commit comments