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

Side by Side Diff: tools/revert.py

Issue 10388020: Add a revert script. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 7 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 import optparse
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 + #!/usr/bin/env python + # Copyright ...
Emily Fortuna 2012/05/08 17:33:27 Done.
2 import os
3 import platform
4 import subprocess
5 import sys
6
7 """A script used to revert one or a sequence of consecutive CLs, for svn and
8 git-svn users."""
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 wrap """ to next line (not sure if this is in the
Emily Fortuna 2012/05/08 17:33:27 Done.
9
10 def parse_args():
11 parser = optparse.OptionParser()
12 parser.add_option('--range', '-r', dest='rev_range', action='store',
Emily Fortuna 2012/05/08 00:40:01 Yes, this could/should have been a positional argu
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 maybe rename it to --revisions instead of range?
Emily Fortuna 2012/05/08 17:33:27 Done.
13 default=None, help='The revision number(s) of the commits '
14 'you wish to undo. An individual number, or a range 8-10.')
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 in git it's common to specify a range as A..B, may
Emily Fortuna 2012/05/08 17:33:27 Done.
15 args, _ = parser.parse_args()
16 revision_range = args.rev_range
17 if revision_range == None:
18 fail('You must specify at least one revision number to revert.')
19 if revision_range.find('-') > -1 or revision_range.find(':') > -1:
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 oh - I guess I'm suggesting a third syntax :). Ei
Emily Fortuna 2012/05/08 17:33:27 Done. Yes, the colon version is svn-like, so I'll
20 # We have a range of commits to revert.
21 split = revision_range.split('-')
22 if len(revision_range.split('-')) == 1:
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 len(revision_range.split('-')) => len(split)
Emily Fortuna 2012/05/08 17:33:27 Done.
23 split = revision_range.split(':')
24 start = int(split[0])
25 end = int(split[1])
26 if start > end:
27 temp = start
28 start = end
29 end = temp
30 fail('Warning: are you sure you want to revert a range of revisions? If '
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 maybe check if start != end (if they are equal, we
Emily Fortuna 2012/05/08 17:33:27 Done, though it will be strange if someone specifi
31 'you just want to revert one CL, only specify one revision number.',
32 user_input=True)
33 else:
34 start = end = int(revision_range)
35 return start, end
36
37 def fail(error_msg, user_input=False):
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 fail => maybe_fail? or prompt_user?
Emily Fortuna 2012/05/08 17:33:27 Done.
Emily Fortuna 2012/05/08 17:33:27 Done.
38 """Determine if we have encountered a condition upon which our script cannot
39 continue, and abort if so.
40 Args:
41 - error_msg: The error message to print.
42 - user_input: True if we require user confirmation to continue. We assume
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 in this case, the message is not necessarily an er
Emily Fortuna 2012/05/08 17:33:27 Done.
43 that the user must enter y to proceed.
44 """
45 if user_input:
46 force = raw_input(error_msg + ' (y/N)')
47 if force != 'y':
48 sys.exit(0)
49 else:
50 print error_msg
51 sys.exit(1)
52
53 def has_new_code(is_git):
54 """Tests if there are any newer versions of files on the server.
55 Args:
56 - is_git: True if we are working in a git repository.
57 """
58 os.chdir(os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 join seems unnecessary?
Emily Fortuna 2012/05/08 17:33:27 Oops, that was a refactoring gone wrong that I mis
59 __file__)))))
60 if not is_git:
61 results = run_cmd(['svn', 'st'])
62 else:
63 results = run_cmd(['git', 'status'])
64 for line in results.split('\n'):
65 if not is_git and (not line.strip().startswith('?') and line != ''):
66 return True
67 elif is_git and ('Changes to be committed' in line or
68 'Changes not staged for commit:' in line):
69 return True
70 if is_git:
71 p = subprocess.Popen(['git', 'log'], stdout=subprocess.PIPE)
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 should we add here '-1' to this git log command? I
Emily Fortuna 2012/05/08 17:33:27 When there are local commits, a commit name is lis
72 output, _ = p.communicate()
73 if find_git_info(output) == None:
74 return True
75 return False
76
77 def run_cmd(cmd_list):
78 """Run the specified command and print out any output to stdout."""
79 print ' '.join(cmd_list)
80 out = subprocess.PIPE
81 p = subprocess.Popen(cmd_list, stdout=out, stderr=subprocess.PIPE,
82 stdin=subprocess.PIPE,
83 shell=(platform.system()=='Windows'))
84 output, stderr = p.communicate()
85 if output:
86 print output
87 if stderr:
88 print stderr
89 return output
90
91 def runs_git():
92 """Returns True if we're standing in an svn-git repository."""
93 p = subprocess.Popen(['svn', 'info'], stdout=subprocess.PIPE,
94 stderr=subprocess.PIPE)
95 output, err = p.communicate()
96 if err != None and 'is not a working copy' in err:
97 p = subprocess.Popen(['git', 'status'], stdout=subprocess.PIPE)
98 output, _ = p.communicate()
99 if 'fatal: Not a git repository' in output:
100 fail('Error: not running git or svn.')
101 else:
102 return True
103 return False
104
105 def find_git_info(git_log, rev_num=None):
106 """Determine the latest svn revision number if rev_num = None, or find the
107 git commit_id that corresponds to a particular svn revision number."""
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 wrap """ to next line
Emily Fortuna 2012/05/08 17:33:27 Done.
108 for line in git_log.split('\n'):
109 tokens = line.split()
110 if len(tokens) == 2 and tokens[0] == 'commit':
111 current_commit_id = tokens[1]
112 elif len(tokens) > 0 and tokens[0] == 'git-svn-id:':
113 revision_number = int(tokens[1].split('@')[1])
114 if revision_number == rev_num:
115 return current_commit_id
116 if rev_num == None:
117 return revision_number
118
119 def revert(start, end, is_git):
120 """Revert the sequence of CLs.
121 Args:
122 - start: The first CL to revert.
123 - end: The last CL to revert.
124 - is_git: True if we are in a git-svn checkout.
125 """
126 if not is_git:
127 run_cmd(['svn', 'merge', '-r', '%d:%d' % (end, start-1), '.'])
128 else:
129 # If we're running git, we have to use the log feature to find the commit
130 # id(s) that correspond to the particular revision number(s).
131 output = run_cmd(['git', 'log', '-1'])
132 current_revision = find_git_info(output)
133 distance = (current_revision-start) + 1
134 reverts = [start]
135 commit_msg = '"Reverting %d"' % start
136 if end != start:
137 reverts = range(start, end + 1)
138 reverts.reverse()
Emily Fortuna 2012/05/08 00:40:01 these two lines (137-138) could certainly be done
139 commit_msg = '%s-%d"' % (commit_msg[:-1], end)
140 for revert in reverts:
141 git_commit_id = find_git_info(output, revert)
142 run_cmd(['git', 'revert', '-n', git_commit_id])
143 run_cmd(['git', 'commit', '-m', commit_msg])
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 this command shouldn't be necessary (there shouldn
Emily Fortuna 2012/05/08 17:33:27 This is done because when I run git revert, I pass
Siggi Cherem (dart-lang) 2012/05/08 17:48:23 Ah - got it. It might be better to do it without t
144
145 def main():
146 revisions = parse_args()
147 git_user = runs_git()
148 if has_new_code(git_user):
149 fail('WARNING: This checkout has local modifications!! This could result '
150 'in a CL that is not just a revert and/or you could lose your local '
151 'changes! Are you **SURE** you want to continue? ', user_input=True)
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 In the case of git, I feel that we should just not
152 if git_user:
153 run_cmd(['git', 'cl', 'rebase'])
154 run_cmd(['gclient', 'sync'])
155 revert(revisions[0], revisions[1], git_user)
Siggi Cherem (dart-lang) 2012/05/08 01:16:07 after this, should we print a message saying: now
Emily Fortuna 2012/05/08 17:33:27 Done.
Emily Fortuna 2012/05/08 17:33:27 Done.
156
157 if __name__ == '__main__':
158 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698