OLD | NEW |
1 #!/bin/sh | 1 #!/usr/bin/python |
2 # Copyright (c) 2009 The Chromium Authors. All rights reserved. | 2 |
3 # Use of this source code is governed by a BSD-style license that can be | 3 # Repo lives in ~evanm/projects/git-try -- feel free to send patches. |
4 # found in the LICENSE file. | 4 |
5 | 5 import getpass |
6 base_dir=$(dirname "$0") | 6 import optparse |
7 | 7 import os |
8 if [ ! -f "$base_dir/git-try-repo/git-try" ]; then | 8 import subprocess |
9 git clone git://neugierig.org/git-try.git $base_dir/git-try-repo -q | 9 import tempfile |
10 fi | 10 import traceback |
11 | 11 import urllib |
12 $base_dir/git-try-repo/git-try "$@" | 12 import sys |
| 13 |
| 14 |
| 15 def Backquote(cmd): |
| 16 """Like running `cmd` in a shell script.""" |
| 17 return subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0].strip() |
| 18 |
| 19 |
| 20 def GetTryServerConfig(): |
| 21 """Returns the dictionary of try server options or None if they |
| 22 cannot be found.""" |
| 23 script_path = 'tools/tryserver/tryserver.py' |
| 24 root_dir = Backquote(['git', 'rev-parse', '--show-cdup']) |
| 25 try: |
| 26 script_file = open(os.path.join(root_dir, script_path)) |
| 27 except IOError: |
| 28 return None |
| 29 locals = {} |
| 30 try: |
| 31 exec(script_file, locals) |
| 32 except Exception, e: |
| 33 return None |
| 34 return locals |
| 35 |
| 36 |
| 37 def GetBranchName(): |
| 38 """Return name of current git branch.""" |
| 39 branch = Backquote(['git', 'symbolic-ref', 'HEAD']) |
| 40 if not branch.startswith('refs/heads/'): |
| 41 raise "Couldn't figure out branch name" |
| 42 branch = branch[len('refs/heads/'):] |
| 43 return branch |
| 44 |
| 45 |
| 46 def GetPatchName(): |
| 47 """Construct a name for this patch.""" |
| 48 short_sha = Backquote(['git', 'rev-parse', '--short=4', 'HEAD']) |
| 49 return GetBranchName() + '-' + short_sha |
| 50 |
| 51 |
| 52 def GetRevision(): |
| 53 """Get the latest Subversion revision number.""" |
| 54 for line in Backquote(['git', 'svn', 'info']).split('\n'): |
| 55 if line.startswith('Revision:'): |
| 56 return line[len('Revision:'):].strip() |
| 57 raise "Couldn't figure out latest revision" |
| 58 |
| 59 |
| 60 def GetRietveldIssueNumber(): |
| 61 return Backquote(['git', 'config', |
| 62 'branch.%s.rietveldissue' % GetBranchName()]) |
| 63 |
| 64 |
| 65 def GetRietveldPatchsetNumber(): |
| 66 return Backquote(['git', 'config', |
| 67 'branch.%s.rietveldpatchset' % GetBranchName()]) |
| 68 |
| 69 |
| 70 def GetMungedDiff(branch): |
| 71 """Get the diff we'll send to the try server. We munge paths to match svn.""" |
| 72 # Make the following changes: |
| 73 # - Prepend "src/" to paths as svn is expecting |
| 74 # - In the case of added files, replace /dev/null with the path to the file |
| 75 # being added. |
| 76 output = [] |
| 77 if not branch: |
| 78 # Try to guess the upstream branch. |
| 79 branch = Backquote(['git', 'cl', 'upstream']) |
| 80 diff = subprocess.Popen(['git', 'diff-tree', '-p', '--no-prefix', |
| 81 branch, 'HEAD'], |
| 82 stdout=subprocess.PIPE).stdout.readlines() |
| 83 for i in range(len(diff)): |
| 84 line = diff[i] |
| 85 if line.startswith('--- /dev/null'): |
| 86 line = '--- %s' % diff[i+1][4:] |
| 87 elif line.startswith('--- ') or line.startswith('+++ '): |
| 88 line = line[0:4] + 'src/' + line[4:] |
| 89 output.append(line) |
| 90 |
| 91 munged_diff = ''.join(output) |
| 92 if len(munged_diff.strip()) == 0: |
| 93 raise Exception("Patch was empty, did you give the right remote branch?") |
| 94 |
| 95 return munged_diff |
| 96 |
| 97 |
| 98 def GetEmail(): |
| 99 # TODO: check for errors here? |
| 100 return Backquote(['git', 'config', 'user.email']) |
| 101 |
| 102 |
| 103 def TryChange(args): |
| 104 """Put a patch on the try server using SVN.""" |
| 105 root_dir = Backquote(['git', 'rev-parse', '--show-cdup']) |
| 106 script_path = os.path.dirname(sys.argv[0]) |
| 107 path = os.path.join(script_path, '..') |
| 108 sys.path.append(path) |
| 109 try: |
| 110 import trychange |
| 111 except ImportError, e: |
| 112 print "Error trying to import trychange from", path |
| 113 print "git-try expects to live at depot_tools/git-try-repo/git-try" |
| 114 raise e |
| 115 trychange.checkout_root = os.path.abspath(root_dir) |
| 116 trychange.TryChange(args, None, False) |
| 117 |
| 118 |
| 119 def WriteTryDiffHTTP(config, patch_name, diff, options): |
| 120 """Put a patch on the try server.""" |
| 121 params = { |
| 122 'user': getpass.getuser(), |
| 123 'name': patch_name, |
| 124 'patch': diff |
| 125 } |
| 126 |
| 127 if GetRietveldPatchsetNumber(): |
| 128 params['issue'] = GetRietveldIssueNumber() |
| 129 params['patchset'] = GetRietveldPatchsetNumber() |
| 130 |
| 131 if options.bot: |
| 132 params['bot'] = options.bot |
| 133 |
| 134 if options.clobber: |
| 135 params['clobber'] = 'true' |
| 136 |
| 137 url = 'http://%s:%s/send_try_patch' % (config['try_server_http_host'], |
| 138 config['try_server_http_port']) |
| 139 connection = urllib.urlopen(url, urllib.urlencode(params)) |
| 140 response = connection.read() |
| 141 if (response != 'OK'): |
| 142 print "Error posting to", url |
| 143 print response |
| 144 assert False |
| 145 |
| 146 |
| 147 if __name__ == '__main__': |
| 148 parser = optparse.OptionParser( |
| 149 usage='git try [options] [branch]', |
| 150 description='Upload the current diff of branch...HEAD to the try server.') |
| 151 parser.add_option("-b", "--bot", |
| 152 help="Force the use of a specific build slave (eg mac, " |
| 153 "win, or linux)") |
| 154 parser.add_option("-c", "--clobber", action="store_true", |
| 155 help="Make the try run use be a clobber build") |
| 156 parser.add_option("-r", "--revision", |
| 157 help="Specify the SVN base revision to use") |
| 158 (options, args) = parser.parse_args(sys.argv) |
| 159 |
| 160 branch = None |
| 161 if len(args) > 1: |
| 162 branch = args[1] |
| 163 |
| 164 patch_name = GetPatchName() |
| 165 diff = GetMungedDiff(branch) |
| 166 |
| 167 # Send directly to try server if we can parse the config, otherwise |
| 168 # upload via SVN. |
| 169 config = GetTryServerConfig() |
| 170 if config is not None: |
| 171 print "Sending %s using HTTP..." % patch_name |
| 172 WriteTryDiffHTTP(config=config, patch_name=patch_name, diff=diff, |
| 173 options=options) |
| 174 else: |
| 175 print "Could not get server config -- if you're within Google, " |
| 176 print "do you have have src-internal checked out?" |
| 177 print "Sending %s using SVN..." % patch_name |
| 178 |
| 179 # Write the diff out to a temporary file |
| 180 diff_file = tempfile.NamedTemporaryFile() |
| 181 diff_file.write(diff) |
| 182 diff_file.flush() |
| 183 |
| 184 email = GetEmail() |
| 185 user = email.partition('@')[0] |
| 186 args = [ |
| 187 '--use_svn', |
| 188 '--svn_repo', 'svn://svn.chromium.org/chrome-try/try', |
| 189 '-u', user, |
| 190 '-e', email, |
| 191 '-n', patch_name, |
| 192 '--diff', diff_file.name, |
| 193 ] |
| 194 if options.bot: |
| 195 args.extend(['--bot', options.bot]) |
| 196 if options.clobber: |
| 197 args.append('--clobber') |
| 198 if options.revision: |
| 199 args.extend(['-r', options.revision]) |
| 200 else: |
| 201 args.extend(['-r', GetRevision()]) |
| 202 if GetRietveldPatchsetNumber(): |
| 203 args.extend([ |
| 204 '--issue', GetRietveldIssueNumber(), |
| 205 '--patchset', GetRietveldPatchsetNumber(), |
| 206 ]) |
| 207 TryChange(args=args) |
OLD | NEW |