asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 1 | #!/usr/bin/python2.6 |
| 2 | # |
| 3 | # Copyright 2010 Google Inc. All Rights Reserved. |
| 4 | |
| 5 | """Script to build the ChromeOS toolchain. |
| 6 | |
| 7 | This script sets up the toolchain if you give it the gcctools directory. |
asharif | d8d0d9b | 2013-02-15 04:56:21 +0000 | [diff] [blame] | 8 | A typical usage scenerio of this script is as follows: |
| 9 | |
| 10 | update_git_repo.py -t gcc |
| 11 | update_git_repo.py -t binutils |
| 12 | |
| 13 | To set it up for the first time, run the following: |
| 14 | update_git_repo.py -t gcc -c <CL#> |
| 15 | update_git_repo.py -t gcc -b <Branch name> -c <CL#> |
| 16 | update_git_repo.py -t gcc |
| 17 | update_git_repo.py -t gcc -b <Branch name> |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 18 | """ |
| 19 | |
| 20 | __author__ = "asharif@google.com (Ahmad Sharif)" |
| 21 | |
| 22 | import getpass |
| 23 | import optparse |
asharif | d8d0d9b | 2013-02-15 04:56:21 +0000 | [diff] [blame] | 24 | import os |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 25 | import re |
| 26 | import socket |
| 27 | import sys |
| 28 | import tempfile |
raymes | 01959ae | 2013-02-15 04:50:07 +0000 | [diff] [blame] | 29 | from utils import command_executer |
| 30 | from utils import logger |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 31 | from utils import utils |
| 32 | |
| 33 | # Common initializations |
raymes | 01959ae | 2013-02-15 04:50:07 +0000 | [diff] [blame] | 34 | cmd_executer = command_executer.GetCommandExecuter() |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 35 | (rootdir, basename) = utils.GetRoot(sys.argv[0]) |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 36 | |
| 37 | |
| 38 | def CreateP4Client(client_name, p4_port, p4_paths, checkoutdir): |
| 39 | """Creates a perforce client from the given parameters.""" |
| 40 | command = "cd " + checkoutdir |
| 41 | command += "; cp ${HOME}/.p4config ." |
| 42 | command += "; echo \"P4PORT=" + p4_port + "\" >> .p4config" |
| 43 | command += "; echo \"P4CLIENT=" + client_name + "\" >> .p4config" |
| 44 | command += "; g4 client -a " + " -a ".join(p4_paths) |
| 45 | print command |
raymes | 01959ae | 2013-02-15 04:50:07 +0000 | [diff] [blame] | 46 | retval = cmd_executer.RunCommand(command) |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 47 | return retval |
| 48 | |
| 49 | |
asharif | d8d0d9b | 2013-02-15 04:56:21 +0000 | [diff] [blame] | 50 | def DeleteP4Client(client_name, client_dir): |
| 51 | command = "cd " + client_dir |
| 52 | command += "&& g4 client -d " + client_name |
raymes | 01959ae | 2013-02-15 04:50:07 +0000 | [diff] [blame] | 53 | retval = cmd_executer.RunCommand(command) |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 54 | return retval |
| 55 | |
| 56 | |
| 57 | def SyncP4Client(client_name, checkoutdir, revision=None): |
| 58 | command = "cd " + checkoutdir |
asharif | 8d5ecd2 | 2013-02-15 04:46:22 +0000 | [diff] [blame] | 59 | if revision: |
| 60 | command += " && g4 sync ...@" + revision |
| 61 | else: |
| 62 | command += " && g4 sync ..." |
raymes | 01959ae | 2013-02-15 04:50:07 +0000 | [diff] [blame] | 63 | retval = cmd_executer.RunCommand(command) |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 64 | return retval |
| 65 | |
| 66 | |
| 67 | def GetP4PathsForTool(client_name, tool, branch_path): |
asharif | 8d5ecd2 | 2013-02-15 04:46:22 +0000 | [diff] [blame] | 68 | """Returns the perforce paths for a tool {gcc|binutils}.""" |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 69 | p4_paths = [] |
| 70 | if branch_path[-1] == "/": |
| 71 | branch_path = branch_path[0:-1] |
| 72 | if tool == "gcc": |
| 73 | p4_paths.append("\"" + branch_path + "/google_vendor_src_branch/" + |
| 74 | "gcc/gcc-4.4.3/..." + |
| 75 | " //" + client_name + "/gcc/gcc-4.4.3/..." + |
| 76 | "\"") |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 77 | version_number = utils.GetRoot(rootdir)[1] |
| 78 | p4_paths.append("\"//depot2/gcctools/chromeos/" + version_number + |
| 79 | "/build-gcc/..." + |
| 80 | " //" + client_name + "/build-gcc/..." + |
| 81 | "\"") |
asharif | d8d0d9b | 2013-02-15 04:56:21 +0000 | [diff] [blame] | 82 | elif tool == "binutils": |
| 83 | p4_paths.append("\"" + branch_path + "/google_vendor_src_branch/" + |
| 84 | "binutils/binutils-2.20.1-mobile/..." + |
| 85 | " //" + client_name + "/binutils/binutils-2.20.1-mobile/..." + |
| 86 | "\"") |
| 87 | p4_paths.append("\"" + branch_path + "/google_vendor_src_branch/" + |
| 88 | "binutils/binutils-20100303/..." + |
| 89 | " //" + client_name + "/binutils/binutils-20100303/..." + |
| 90 | "\"") |
| 91 | version_number = utils.GetRoot(rootdir)[1] |
| 92 | p4_paths.append("\"//depot2/gcctools/chromeos/" + version_number + |
| 93 | "/build-binutils/..." + |
| 94 | " //" + client_name + "/build-binutils/..." + |
| 95 | "\"") |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 96 | |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 97 | return p4_paths |
| 98 | |
| 99 | |
| 100 | def GetGitRepoForTool(tool): |
| 101 | # This should return the correct server repository when the script |
| 102 | # is fully done. |
| 103 | if tool == "gcc": |
asharif | 8d5ecd2 | 2013-02-15 04:46:22 +0000 | [diff] [blame] | 104 | return "ssh://git@gitrw.chromium.org:9222/gcc.git" |
| 105 | elif tool == "binutils": |
| 106 | return "ssh://git@gitrw.chromium.org:9222/binutils.git" |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 107 | |
| 108 | |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 109 | def SetupBranch(checkoutdir, branch_name): |
asharif | 8d5ecd2 | 2013-02-15 04:46:22 +0000 | [diff] [blame] | 110 | """Sets up either the master or another branch in the local repo.""" |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 111 | if branch_name == "master": |
| 112 | return 0 |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 113 | command = "cd " + checkoutdir |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 114 | command += " && git branch -a | grep -wq " + branch_name |
raymes | 01959ae | 2013-02-15 04:50:07 +0000 | [diff] [blame] | 115 | retval = cmd_executer.RunCommand(command) |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 116 | command = "cd " + checkoutdir |
| 117 | if retval == 0: |
| 118 | command += (" && git branch --track " + branch_name + |
| 119 | " remotes/origin/" + branch_name) |
| 120 | command += " && git checkout " + branch_name |
| 121 | else: |
| 122 | command += (" && git checkout -b " + branch_name) |
raymes | 01959ae | 2013-02-15 04:50:07 +0000 | [diff] [blame] | 123 | retval = cmd_executer.RunCommand(command) |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 124 | return retval |
| 125 | |
| 126 | |
| 127 | def CreateGitClient(git_repo, checkoutdir, branch_name): |
asharif | 8d5ecd2 | 2013-02-15 04:46:22 +0000 | [diff] [blame] | 128 | """Creates a git client with in a dir with a branch.""" |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 129 | command = "cd " + checkoutdir |
| 130 | command += " && git clone -v " + git_repo + " ." |
raymes | 01959ae | 2013-02-15 04:50:07 +0000 | [diff] [blame] | 131 | retval = cmd_executer.RunCommand(command) |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 132 | if retval != 0: |
| 133 | return retval |
| 134 | retval = SetupBranch(checkoutdir, branch_name) |
| 135 | if retval != 0: |
| 136 | return retval |
| 137 | command = "cd " + checkoutdir |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 138 | command += " && rm -rf *" |
raymes | 01959ae | 2013-02-15 04:50:07 +0000 | [diff] [blame] | 139 | retval = cmd_executer.RunCommand(command) |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 140 | return retval |
| 141 | |
| 142 | |
| 143 | def GetLatestCL(client_name, checkoutdir): |
| 144 | command = "cd " + checkoutdir |
asharif | e9433c3 | 2013-02-15 05:53:27 +0000 | [diff] [blame] | 145 | command += " && g4 changes -m1 ...#have" |
raymes | 01959ae | 2013-02-15 04:50:07 +0000 | [diff] [blame] | 146 | (status, stdout, stderr) = cmd_executer.RunCommand(command, True) |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 147 | if status != 0: |
| 148 | return -1 |
| 149 | mo = re.match("^Change (\d+)", stdout) |
| 150 | if mo is None: |
| 151 | return -1 |
| 152 | return mo.groups(0)[0] |
| 153 | |
| 154 | |
| 155 | def WriteStringToFile(filename, string): |
| 156 | f = open(filename, "w") |
| 157 | f.write(string) |
| 158 | f.close() |
| 159 | |
| 160 | |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 161 | def AddGitIgnores(checkoutdir): |
| 162 | f = open(checkoutdir + "/.gitignore", "w") |
| 163 | f.write(".gitignore\n") |
| 164 | f.write("README.google\n") |
| 165 | f.write(".p4config\n") |
| 166 | f.close() |
| 167 | |
| 168 | |
| 169 | def PushToRemoteGitRepo(checkoutdir, branch_name, message_file, push_args): |
asharif | 8d5ecd2 | 2013-02-15 04:46:22 +0000 | [diff] [blame] | 170 | """Do the actualy git push to remote repository.""" |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 171 | # Add the stuff we want git to ignore for the add. |
| 172 | AddGitIgnores(checkoutdir) |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 173 | command = "cd " + checkoutdir |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 174 | # For testing purposes, I am only adding a single file to the |
| 175 | # remote repository. |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 176 | command += " && git add -Av . " |
| 177 | ### command += " && git add -Av gcc/gcc-4.4.3/README" |
| 178 | command += " && git commit -v -F " + message_file |
| 179 | command += (" && git push -v " + push_args + " origin " + |
| 180 | branch_name + ":" + branch_name) |
raymes | 01959ae | 2013-02-15 04:50:07 +0000 | [diff] [blame] | 181 | retval = cmd_executer.RunCommand(command) |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 182 | return retval |
| 183 | |
| 184 | |
| 185 | def Main(): |
| 186 | """The main function.""" |
| 187 | parser = optparse.OptionParser() |
| 188 | parser.add_option("-t", "--tool", dest="tool", |
| 189 | help="Tool can be gcc or binutils.") |
| 190 | parser.add_option("-b", "--branch", dest="branch", |
| 191 | help="Full branch path to use, if not the trunk.") |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 192 | parser.add_option("-n", "--dry-run", dest="dry_run", default=False, |
| 193 | action="store_true", |
| 194 | help="Do a dry run of the git push.") |
| 195 | parser.add_option("-F", "--file", dest="message_file", |
| 196 | help="Path to file containing the commit message.") |
| 197 | parser.add_option("-r", "--remote", dest="remote", |
| 198 | help="Optional location of the remote git repository.") |
asharif | 8d5ecd2 | 2013-02-15 04:46:22 +0000 | [diff] [blame] | 199 | parser.add_option("-c", "--changelist", dest="changelist", |
| 200 | help="Optional changelist to sync to.") |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 201 | |
| 202 | options = parser.parse_args()[0] |
| 203 | |
| 204 | if options.tool is None: |
| 205 | parser.print_help() |
| 206 | sys.exit() |
| 207 | |
| 208 | if not options.branch: |
| 209 | branch_path = ("//depot2/gcctools/") |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 210 | branch_name = "master" |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 211 | else: |
| 212 | branch_path = ("//depot2/branches/" + options.branch + |
| 213 | "/gcctools") |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 214 | branch_name = options.branch |
asharif | d8d0d9b | 2013-02-15 04:56:21 +0000 | [diff] [blame] | 215 | utils.AssertTrue(os.path.exists("/google/src/files/p2/head/depot2/" + |
| 216 | "branches/" + branch_name), |
| 217 | "Branch name: " + branch_name + " not found!") |
| 218 | |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 219 | if options.remote: |
| 220 | git_repo = options.remote |
| 221 | else: |
| 222 | git_repo = GetGitRepoForTool(options.tool) |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 223 | |
| 224 | # Setup a perforce checkout of Crosstool trunk or branch. |
| 225 | temp_dir = tempfile.mkdtemp() |
| 226 | client_name = getpass.getuser() + "-" + socket.gethostname() + "-" + temp_dir |
| 227 | client_name = str.replace(client_name, "/", "-") |
| 228 | p4_paths = GetP4PathsForTool(client_name, options.tool, branch_path) |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 229 | status = CreateGitClient(git_repo, temp_dir, branch_name) |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 230 | utils.AssertTrue(status == 0, "Git repo cloning failed") |
| 231 | status = CreateP4Client(client_name, "perforce2:2666", p4_paths, temp_dir) |
| 232 | utils.AssertTrue(status == 0, "Could not create p4 client") |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 233 | # If the user presses Ctrl-C, make sure to clean up p4 client. |
| 234 | try: |
asharif | 8d5ecd2 | 2013-02-15 04:46:22 +0000 | [diff] [blame] | 235 | status = SyncP4Client(client_name, temp_dir, options.changelist) |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 236 | utils.AssertTrue(status == 0, "Could not sync p4 client") |
| 237 | if not options.message_file: |
| 238 | changelist = GetLatestCL(client_name, temp_dir) |
| 239 | message_file = tempfile.mktemp() |
| 240 | WriteStringToFile(message_file, "Sync'd to revision " + changelist) |
| 241 | else: |
| 242 | message_file = rootdir + "/" + options.message_file |
| 243 | if options.dry_run: |
| 244 | push_args = " -n " |
| 245 | else: |
| 246 | push_args = "" |
| 247 | status = PushToRemoteGitRepo(temp_dir, branch_name, message_file, push_args) |
| 248 | utils.AssertTrue(status == 0, "Could not push to remote repo") |
| 249 | except (KeyboardInterrupt, SystemExit): |
raymes | 01959ae | 2013-02-15 04:50:07 +0000 | [diff] [blame] | 250 | logger.GetLogger().LogOutput("Caught exception... Cleaning up.") |
asharif | d8d0d9b | 2013-02-15 04:56:21 +0000 | [diff] [blame] | 251 | status = DeleteP4Client(client_name, temp_dir) |
asharif | 6fca6ca | 2013-02-15 04:36:09 +0000 | [diff] [blame] | 252 | raise |
asharif | d8d0d9b | 2013-02-15 04:56:21 +0000 | [diff] [blame] | 253 | status = DeleteP4Client(client_name, temp_dir) |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 254 | utils.AssertTrue(status == 0, "Could not delete p4 client") |
asharif | 2198c51 | 2013-02-15 09:21:35 +0000 | [diff] [blame] | 255 | return status |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 256 | |
| 257 | |
| 258 | if __name__ == "__main__": |
asharif | 2198c51 | 2013-02-15 09:21:35 +0000 | [diff] [blame] | 259 | retval = Main() |
| 260 | sys.exit(retval) |
asharif | 00e8b29 | 2013-02-15 04:36:08 +0000 | [diff] [blame] | 261 | |
| 262 | |