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

Side by Side Diff: git_rebase_update.py

Issue 184253003: Add git-reup and friends (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@freeze_thaw
Patch Set: Created 6 years, 9 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 #!/usr/bin/python
2 # Copyright (c) 2014 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
5 import logging
Ryan Tseng 2014/02/28 21:22:05 2 lines before line 5 + sort
6 import sys
7 import collections
8
9 from pprint import pformat
10
11 from subprocess2 import CalledProcessError
12
13 from git_squash_branch import squash
14
agable 2014/02/28 20:14:16 No newline here, and put git_squash_branch bellow
15 from git_common import run, root, upstream
16 from git_common import branches, current_branch, get_or_create_merge_base_tag
17 from git_common import clean_refs, hash_one
18
19 RebaseRet = collections.namedtuple('TryRebaseRet', 'success message')
20
21
22 def bclean():
Ryan Tseng 2014/02/28 21:22:05 What does this stand for?
23 merged = list(branches('--merged', root()))
24
25 logging.debug('merged: %s', merged)
26
27 upstreams = {}
28 downstreams = collections.defaultdict(list)
29 for branch in branches():
30 try:
31 parent = upstream(branch)
32 upstreams[branch] = parent
33 downstreams[parent].append(branch)
34 except CalledProcessError:
35 pass
36
37 logging.debug('upstreams: %s', upstreams)
38 logging.debug('downstreams: %s', downstreams)
39
40 if current_branch() in merged:
41 run('checkout', root())
42 for branch in merged:
43 for down in downstreams[branch]:
44 if down not in merged:
45 run('branch', '--set-upstream-to', upstreams[branch], down)
46 print ('Reparented %s to track %s (was tracking %s)'
47 % (down, upstreams[branch], branch))
48 print run('branch', '-d', branch)
49
50 return 0
51
52
53 def rebase(parent, start, branch, abort=False):
54 try:
55 run('rebase', '--onto', parent, start, branch)
56 return RebaseRet(True, '')
57 except CalledProcessError as cpe:
58 if abort:
59 run('rebase', '--abort')
60 return RebaseRet(False, cpe.output)
61
62
63 def clean_branch(branch, parent, starting_ref):
64 if (hash_one(parent) != hash_one(starting_ref)
agable 2014/02/28 20:14:16 Main line of code should be at top level. Reverse
65 and hash_one(branch) != hash_one(starting_ref)):
66 print 'Rebasing:', branch
67
68 # Try a plain rebase first
69 if rebase(parent, starting_ref, branch, abort=True).success:
70 return
71
72 # Maybe squashing will help?
73 print "Failed! Attempting to squash", branch, "...",
74 squash_branch = branch+"_squash_attempt"
75 run('checkout', '-b', squash_branch)
76 squash()
77
78 squash_ret = rebase(parent, starting_ref, squash_branch, abort=True)
79 run('checkout', branch)
80 run('branch', '-D', squash_branch)
81
82 if squash_ret.success:
83 print 'Success!'
84 squash()
85 final_rebase = rebase(parent, starting_ref, branch)
86 assert final_rebase.success == squash_ret.success
agable 2014/02/28 20:14:16 Add error message here.
87
88 if not squash_ret.success:
89 print squash_ret.message
90 print 'Failure :('
91 print 'Your working copy is in mid-rebase. Please completely resolve and'
Ryan Tseng 2014/02/28 21:22:05 Does this leave HEAD mid rebase? I think we'll nee
iannucci 2014/03/20 10:59:37 It also prints the standard git rebase boilerplate
92 print 'run `git reup` again.'
93 sys.exit(1)
94
95
96 def main():
97 # TODO(iannucci): use argparse
agable 2014/02/28 20:14:16 Probably do this now (less important than the othe
Ryan Tseng 2014/02/28 21:22:05 We at least need a usage string behind --help. "r
98 # TODO(iannucci): have a way to set log level
99 if '--clean' in sys.argv:
100 clean_refs()
101 return 0
102
103 # TODO(iannucci): check for a clean working dir
104 # TODO(iannucci): Tag merge bases more intelligently
105 # TODO(iannucci): Find collapsible branches in a smarter way
106
107 # TODO(iannucci): Allow for root() to be a tag
108 # * update all remotes + tags
109 # * rebase to tag instead of to branch
110 # * when creating a new branch, use the tag as the ref
111 # * still need 'upstream' to be origin/master?
112 # * configurable?
113
114 orig_branch = current_branch()
115 if orig_branch == 'HEAD':
116 orig_branch = hash_one('HEAD')
117
118 if 'origin' in run('remote').splitlines():
Ryan Tseng 2014/02/28 21:22:05 splitlines() is probably unnecessary.
119 run('fetch', 'origin', stderr=None)
Ryan Tseng 2014/02/28 21:22:05 This might take a while, can we stream the output?
120 else:
121 run('svn', 'fetch', stderr=None)
122 branch_tree = {}
123 for branch in branches():
124 parent = upstream(branch)
125 if not parent:
126 print 'Skipping %s: No upstream specified' % branch
127 continue
128 branch_tree[branch] = parent
129
130 starting_refs = {}
131 for branch, parent in branch_tree.iteritems():
132 starting_refs[branch] = get_or_create_merge_base_tag(branch, parent)
133
134 logging.debug('branch_tree: %s', pformat(branch_tree))
135 logging.debug('starting_refs: %s', pformat(starting_refs))
136
137 # XXX There is a more efficient way to do this, but for now...
Ryan Tseng 2014/02/28 21:22:05 XXX?
138 while branch_tree:
139 this_pass = [i for i in branch_tree.items() if i[1] not in branch_tree]
140 for branch, parent in this_pass:
141 clean_branch(branch, parent, starting_refs[branch])
142 del branch_tree[branch]
143
144 clean_refs()
145
146 bclean()
147
148 if orig_branch in branches():
149 run('checkout', orig_branch)
150 else:
151 run('checkout', root())
152
153 return 0
154
155
156 if __name__ == '__main__':
157 sys.exit(main())
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698