| OLD | NEW |
| (Empty) | |
| 1 package commit_cache |
| 2 |
| 3 import ( |
| 4 "encoding/json" |
| 5 "fmt" |
| 6 "io" |
| 7 "sync" |
| 8 "time" |
| 9 |
| 10 "github.com/golang/glog" |
| 11 |
| 12 "skia.googlesource.com/buildbot.git/go/gitinfo" |
| 13 ) |
| 14 |
| 15 /* |
| 16 Utilities for caching commit data. |
| 17 */ |
| 18 |
| 19 // CommitCache is a struct used for caching commit data. Stores ALL commits in |
| 20 // the repository. |
| 21 type CommitCache struct { |
| 22 branchHeads []*gitinfo.GitBranch |
| 23 commits []*gitinfo.LongCommit |
| 24 repo *gitinfo.GitInfo |
| 25 mutex sync.RWMutex |
| 26 } |
| 27 |
| 28 // New creates and returns a new CommitCache which watches the given repo. |
| 29 // The initial Update will load ALL commits from the repository, so expect |
| 30 // this to be slow. |
| 31 func New(repo *gitinfo.GitInfo) (*CommitCache, error) { |
| 32 // Initially load the past week's worth of commits. |
| 33 c := CommitCache{ |
| 34 repo: repo, |
| 35 } |
| 36 if err := c.Update(); err != nil { |
| 37 return nil, err |
| 38 } |
| 39 return &c, nil |
| 40 } |
| 41 |
| 42 // Update syncs the source code repository and loads any new commits. |
| 43 func (c *CommitCache) Update() error { |
| 44 glog.Info("Reloading commits.") |
| 45 c.mutex.Lock() |
| 46 defer c.mutex.Unlock() |
| 47 if err := c.repo.Update(true, true); err != nil { |
| 48 return fmt.Errorf("Failed to update the repo: %v", err) |
| 49 } |
| 50 from := time.Time{} |
| 51 if len(c.commits) > 0 { |
| 52 from = c.commits[len(c.commits)-1].Timestamp |
| 53 } |
| 54 newCommitHashes := c.repo.From(from) |
| 55 glog.Infof("Processing %d new commits.", len(newCommitHashes)) |
| 56 newCommits := make([]*gitinfo.LongCommit, len(newCommitHashes)) |
| 57 if len(newCommitHashes) > 0 { |
| 58 for i, h := range newCommitHashes { |
| 59 d, err := c.repo.Details(h) |
| 60 if err != nil { |
| 61 return fmt.Errorf("Failed to obtain commit detai
ls for %s: %v", h, err) |
| 62 } |
| 63 newCommits[i] = d |
| 64 } |
| 65 } |
| 66 branchHeads, err := c.repo.GetBranches() |
| 67 if err != nil { |
| 68 return fmt.Errorf("Failed to read branch information from the re
po: %v", err) |
| 69 } |
| 70 // Update the cached values all at once at at the end. |
| 71 c.branchHeads = branchHeads |
| 72 c.commits = append(c.commits, newCommits...) |
| 73 return nil |
| 74 } |
| 75 |
| 76 // NumCommits returns the number of commits contained in the cache. |
| 77 func (c *CommitCache) NumCommits() int { |
| 78 return len(c.commits) |
| 79 } |
| 80 |
| 81 // asJson writes the given commit range along with the branch heads in JSON |
| 82 // format to the given Writer. |
| 83 func (c *CommitCache) asJson(w io.Writer, startIdx, endIdx int) error { |
| 84 c.mutex.RLock() |
| 85 defer c.mutex.RUnlock() |
| 86 data := struct { |
| 87 Commits []*gitinfo.LongCommit `json:"commits"` |
| 88 BranchHeads []*gitinfo.GitBranch `json:"branch_heads"` |
| 89 StartIdx int `json:"startIdx"` |
| 90 EndIdx int `json:"endIdx"` |
| 91 }{ |
| 92 Commits: c.commits[startIdx:endIdx], |
| 93 BranchHeads: c.branchHeads, |
| 94 StartIdx: startIdx, |
| 95 EndIdx: endIdx, |
| 96 } |
| 97 return json.NewEncoder(w).Encode(&data) |
| 98 } |
| 99 |
| 100 // LastNAsJson writes the last N commits along with the branch heads in JSON |
| 101 // format to the given Writer. |
| 102 func (c *CommitCache) LastNAsJson(w io.Writer, n int) error { |
| 103 c.mutex.RLock() |
| 104 end := len(c.commits) |
| 105 c.mutex.RUnlock() |
| 106 start := end - n |
| 107 if start < 0 { |
| 108 start = 0 |
| 109 } |
| 110 return c.asJson(w, start, end) |
| 111 } |
| 112 |
| 113 // RangeAsJson writes the given range of commits along with the branch heads |
| 114 // in JSON format to the given Writer. |
| 115 func (c *CommitCache) RangeAsJson(w io.Writer, startIdx, endIdx int) error { |
| 116 if startIdx < 0 || startIdx > len(c.commits) { |
| 117 return fmt.Errorf("startIdx is out of range [0, %d]: %d", len(c.
commits), startIdx) |
| 118 } |
| 119 if endIdx < 0 || endIdx > len(c.commits) { |
| 120 return fmt.Errorf("endIdx is out of range [0, %d]: %d", len(c.co
mmits), endIdx) |
| 121 } |
| 122 if endIdx < startIdx { |
| 123 return fmt.Errorf("endIdx < startIdx: %d, %d", endIdx, startIdx) |
| 124 } |
| 125 return c.asJson(w, startIdx, endIdx) |
| 126 } |
| OLD | NEW |