Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(400)

Side by Side Diff: milo/git/history.go

Issue 2979153002: [milo] initial call to get git history (Closed)
Patch Set: Created 3 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2017 The LUCI Authors.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 package git
16
17 import (
18 "bytes"
19 "compress/gzip"
20 "encoding/hex"
21 "fmt"
22 "io/ioutil"
23 "regexp"
24
25 "golang.org/x/net/context"
26
27 "github.com/golang/protobuf/proto"
28
29 "github.com/luci/gae/service/memcache"
30
31 "github.com/luci/luci-go/common/api/gitiles"
32 "github.com/luci/luci-go/common/errors"
33 "github.com/luci/luci-go/common/logging"
34 "github.com/luci/luci-go/common/proto/google"
35
36 milo "github.com/luci/luci-go/milo/api/proto"
37 )
38
39 var gitHash = regexp.MustCompile("[0-9a-fA-F]{40}")
40
41 // Resolve resolves a commitish to a git commit hash.
42 //
43 // This operation will assumed to be either fully local (in the case that
44 // commitish is already a git-hash-looking-thing), or local to the datastore (in
45 // the case that commitish is a fully-qualified-ref, ref tables are populated by
46 // a backend cron).
47 //
48 // If commitish is some other pattern (e.g. "HEAD~"), this will return the
49 // commitish as-is.
50 //
51 // `resolved` will be true if `commit` is, in fact, a git hash; if it's false,
52 // then higher layers should be careful about using it as part of a cache key.
53 func Resolve(c context.Context, url, commitish string) (commit string, resolved bool, err error) {
54 if gitHash.MatchString(commitish) {
55 return commitish, true, nil
56 }
57
58 // TODO(iannucci): actually do lookup and cache it. Maybe have a backend cron
59 // which refreshes the entire refs space?
60 return commitish, false, nil
61 }
62
63 func protoCache(c context.Context, enabled bool, key string, out proto.Message, get func() error) error {
Ryan Tseng 2017/07/17 20:25:51 comments plz Also this is fairly specific and int
iannucci 2017/07/17 21:54:39 Done.
64 if !enabled {
65 return get()
66 }
67
68 cacheEntry := memcache.NewItem(c, key+"|gz")
69 // try reading from cache
70 ok := func() bool {
71 switch err := memcache.Get(c, cacheEntry); err {
72 case nil:
73 r, err := gzip.NewReader(bytes.NewReader(cacheEntry.Valu e()))
74 if err != nil {
75 logging.WithError(err).Warningf(c, "making ungzi p reader for memcache entry")
76 return false
77 }
78
79 data, err := ioutil.ReadAll(r)
80 if err != nil {
81 logging.WithError(err).Warningf(c, "ungziping me mcache entry")
82 return false
83 }
84
85 if err := proto.Unmarshal(data, out); err != nil {
86 logging.WithError(err).Warningf(c, "unmarshallin g cache entry")
87 return false
88 }
89
90 return true
91 case memcache.ErrCacheMiss:
92 default:
93 logging.WithError(err).Warningf(c, "memcache lookup")
94 }
95 return false
96 }()
97 if ok {
98 return nil
99 }
100
101 if err := get(); err != nil {
102 return err
103 }
104
105 data, err := proto.Marshal(out)
106 if err != nil {
107 logging.WithError(err).Warningf(c, "marshaling proto")
108 return nil
109 }
110
111 var buf bytes.Buffer
112 wr := gzip.NewWriter(&buf)
113 _, _ = wr.Write(data) // err is buffered on the writer till Close
Ryan Tseng 2017/07/17 20:25:51 might as well skip assignment
iannucci 2017/07/17 21:54:39 Done.
114 if err := wr.Close(); err != nil {
115 logging.WithError(err).Warningf(c, "gziping proto")
Ryan Tseng 2017/07/17 20:25:51 nit: gzipping
iannucci 2017/07/17 21:54:39 Done.
116 return nil
117 }
118
119 cacheEntry.SetValue(buf.Bytes())
120 if err := memcache.Set(c, cacheEntry); err != nil {
121 logging.WithError(err).Warningf(c, "memcache set")
122 }
123
124 return nil
125 }
126
127 // GetHistory makes a (cached) call to gitiles to obtain the ConsoleGitInfo for
128 // the given url, commitish and limit.
129 func GetHistory(c context.Context, url, commitish string, limit int) (*milo.Cons oleGitInfo, error) {
130 commitish, useCache, err := Resolve(c, url, commitish)
131 if err != nil {
132 return nil, errors.Annotate(err, "resolving %q", commitish).Err( )
133 }
134
135 ret := &milo.ConsoleGitInfo{}
136 cacheKey := fmt.Sprintf("GetHistory|%s|%s|%d", url, commitish, limit)
137 err = protoCache(c, useCache, cacheKey, ret, func() error {
138 rawEntries, err := gitiles.Log(c, url, commitish, limit)
139 if err != nil {
140 return errors.Annotate(err, "GetHistory").Err()
141 }
142
143 ret.Commits = make([]*milo.ConsoleGitInfo_Commit, len(rawEntries ))
144
145 for i, e := range rawEntries {
146 commit := &milo.ConsoleGitInfo_Commit{}
147 if commit.Id, err = hex.DecodeString(e.Commit); err != n il {
148 return errors.Annotate(err, "commit is not hex ( %q)", e.Commit).Err()
149 }
150
151 commit.AuthorName = e.Author.Name
152 commit.AuthorEmail = e.Author.Email
153
154 ts, err := e.Committer.GetTime()
155 if err != nil {
156 return errors.Annotate(err, "commit time unparsi ble (%q)", e.Committer.Time).Err()
157 }
158
159 commit.CommitTime = google.NewTimestamp(ts)
160 commit.Msg = e.Message
161
162 ret.Commits[i] = commit
163 }
164 return nil
165 })
166 return ret, err
167 }
OLDNEW
« milo/api/proto/console_git_info.proto ('K') | « milo/api/proto/pb.discovery.go ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698