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

Side by Side Diff: go/src/infra/tools/drover/main.go

Issue 662113003: Drover's back, baby! (Closed) Base URL: https://chromium.googlesource.com/infra/infra.git/+/master
Patch Set: Lots of fixes Created 6 years, 2 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 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 package main
5
6 import (
7 "bufio"
8 "flag"
9 "fmt"
10 "io/ioutil"
11 "os"
12 "strings"
13
14 "github.com/daviddengcn/go-colortext"
Vadim Sh. 2014/10/21 15:27:00 did you manage to add this to Goop file?
15
16 "infra/libs/git"
17 "infra/libs/gitiles"
18 )
19
20 var commitish = flag.String("commit", "", "The commit to process (or commit posi tion number).")
21 var action = flag.String("action", "", "The action to take. Must specify `cherry -pick|revert`.")
22 var ref = flag.String("ref", "", "The target ref to change.")
23 var workdir string
24
25 func getCodereviewSettings(g *gitiles.Gitiles, ref string) (ret map[string]strin g) {
26 crSettings, err := g.Text("+", ref, "codereview.settings")
27 if err == nil {
28 lines := strings.Split(string(crSettings), "\n")
29 ret = make(map[string]string, len(lines))
30 for _, line := range lines {
31 if len(line) == 0 || line[0] == '#' {
32 continue
33 }
34 keyVal := strings.Split(line, ":")
35 if len(keyVal) == 2 {
36 ret[keyVal[0]] = strings.TrimSpace(keyVal[1])
37 }
38 }
39 }
40 return ret
41 }
42
43 func getLandingCommit(g *gitiles.Gitiles, ref string, settings map[string]string ) (*git.Commit, string) {
44 prefix, ok := settings["PENDING_REF_PREFIX"]
45 if ok {
46 ref = strings.Replace(ref, "refs/", prefix, 1)
47 }
48 result, err := g.GetObjectFromPath(ref)
49 failIf(err)
50 if result.Type() != git.CommitType {
51 panic(fmt.Errorf("ref points at non-commit? %#v", result))
52 }
53 return result.(*git.Commit), ref
54 }
55
56 func confirmAction(URL, action, ref string, commit *git.Commit, diff string) {
57 verbPart := "to"
58 if action == "revert" {
59 verbPart = "from"
60 }
61
62 fmt.Printf("Planning to %s commit %s %s %s in %s:\n\n",
63 action, commit.ID(), verbPart, ref, URL)
64
65 ct.ChangeColor(ct.Yellow, false, ct.None, false)
66 fmt.Println("commit", commit.ID())
67 ct.ResetColor()
68 fmt.Printf("Author: %s <%s>\n", commit.Author().Name, commit.Author().Em ail)
69 fmt.Printf("Date: %s\n", commit.Author().Time)
70 fmt.Println()
71 for _, l := range commit.MessageLines() {
72 fmt.Printf(" %s\n", l)
73 }
74 fmt.Println()
75 for _, pair := range commit.FooterPairs() {
76 ct.ChangeColor(ct.White, true, ct.None, false)
77 fmt.Printf(" %s: ", pair.Key)
78 ct.ResetColor()
79 fmt.Println(pair.Value)
80 }
81 fmt.Println()
82 for _, line := range strings.Split(diff, "\n") {
83 if len(line) > 0 {
84 switch {
85 case strings.HasPrefix(line, "+++") || strings.HasPrefix (line, "---"):
86 ct.ChangeColor(ct.White, true, ct.None, false)
87 case line[0] == '@':
88 ct.ChangeColor(ct.Cyan, false, ct.None, false)
89 bits := strings.SplitN(line, "@@", 3)
90 fmt.Print("@@", bits[1], "@@")
91 ct.ResetColor()
92 fmt.Println(bits[2])
93 continue
94 case line[0] == '+':
95 ct.ChangeColor(ct.Green, false, ct.None, false)
96 case line[0] == '-':
97 ct.ChangeColor(ct.Red, false, ct.None, false)
98 case line[0] == ' ':
99 ct.ResetColor()
100 default:
101 ct.ChangeColor(ct.White, true, ct.None, false)
102 }
103 }
104 fmt.Println(line)
105 }
106 ct.ResetColor()
107
108 fmt.Println()
109 fmt.Printf("Continue? [y/N] ")
110 answerRaw, err := bufio.NewReader(os.Stdin).ReadBytes('\n')
111 failIf(err)
112
113 answer := strings.TrimSpace(string(answerRaw))
114
115 if len(answer) != 0 && strings.HasPrefix("yes", strings.ToLower(answer)) {
116 return
117 }
118
119 fmt.Println("Action aborted")
120 os.Exit(1)
121 }
122
123 func getCommitData(g *gitiles.Gitiles, gitSha string) (*git.Commit, git.TreeDiff ) {
124 commitRslt, err := g.GetObjectFromPath(gitSha)
125 failIf(err)
126
127 commit, ok := commitRslt.(*git.Commit)
128 if !ok {
129 failIf(fmt.Errorf("%s is not a commit?", gitSha))
130 }
131
132 commitDiffRslt, err := g.GetCommitDiff(gitSha)
133 failIf(err)
134
135 return commit, commitDiffRslt
136 }
137
138 func main() {
139 cwd, err := os.Getwd()
140 if err != nil {
141 panic(err)
142 }
143 flag.StringVar(&workdir, "workdir", cwd, "The work directory to use.")
144
145 flag.Usage = func() {
146 fmt.Println("Usage: git drover -commit deadbeef -action cherry-p ick -ref 2125")
147 flag.PrintDefaults()
148 }
149 flag.Parse()
150 if *commitish == "" || *action == "" || *ref == "" {
151 flag.PrintDefaults()
152 fmt.Println("must specify commitish, action and ref")
153 os.Exit(1)
154 }
155 if *action != "cherry-pick" && *action != "revert" {
156 flag.PrintDefaults()
157 fmt.Printf(
158 "must action must be 'cherry-pick' or 'revert'. Got '%s' .\n", *action)
159 os.Exit(1)
160 }
161
162 repo := &git.Repo{Path: workdir}
163 if repo.RunOk("rev-parse", "--git-dir") {
164 if !repo.RunOk("config", "drover.repo") {
165 fmt.Println("must be run from an empty directory or a dr over git repo")
166 os.Exit(1)
167 }
168 } else {
169 files, err := ioutil.ReadDir(workdir)
170 failIf(err)
171 if len(files) == 0 {
172 fmt.Println("Initializing current directory as a drover git repo")
173 if !repo.RunOk("init") {
174 flag.PrintDefaults()
175 panic("Couldn't initialize git repo!")
176 }
177 if !repo.RunOk("config", "drover.repo", "true") {
178 flag.PrintDefaults()
179 panic("Couldn't configure git repo to be owned b y drover!")
180 }
181 } else {
182 flag.PrintDefaults()
183 fmt.Println("must be run from an empty directory or a dr over git repo")
184 os.Exit(1)
185 }
186 }
187
188 gitSha, gitilesURL, err := disambiguateCommit(*commitish)
189 failIf(err)
190
191 g := gitiles.NewGitiles(gitilesURL, 8)
192
193 *ref, err = disambiguateRef(g, gitSha, *ref)
194 failIf(err)
195
196 commit, treeDiff := getCommitData(g, gitSha)
197 textDiff, err := g.GetTextCommitDiff(commit.ID())
198 failIf(err)
199
200 settings := getCodereviewSettings(g, *ref)
201 landCommit, real_ref := getLandingCommit(g, *ref, settings)
202
203 confirmAction(g.URL(), *action, *ref, commit, textDiff)
204
205 acquireObjects(repo, g, commit, landCommit, treeDiff)
206
207 var left, right git.ObjectID
208 if *action == "cherry-pick" {
209 left, right = commit.Parents()[0], commit.ID()
210 } else if *action == "revert" {
211 right, left = commit.Parents()[0], commit.ID()
212 }
213 toPush := createCommit(*action, repo, left, right, landCommit.ID())
214 id := toPush.ID().String()
215
216 diff, err := repo.GetTextDiff(id+"~", id)
217 failIf(err)
218
219 confirmAction(g.URL(), "push", real_ref, toPush, diff)
220 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698