blob: 6a5a3a391d68f0b963599912a850cd14fcc21d87 [file] [log] [blame]
asharif00e8b292013-02-15 04:36:08 +00001#!/usr/bin/python2.6
2#
3# Copyright 2010 Google Inc. All Rights Reserved.
4
5"""Script to build the ChromeOS toolchain.
6
7This script sets up the toolchain if you give it the gcctools directory.
asharifd8d0d9b2013-02-15 04:56:21 +00008A 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
13To 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>
asharif00e8b292013-02-15 04:36:08 +000018"""
19
20__author__ = "asharif@google.com (Ahmad Sharif)"
21
22import getpass
23import optparse
asharifd8d0d9b2013-02-15 04:56:21 +000024import os
asharif00e8b292013-02-15 04:36:08 +000025import re
26import socket
27import sys
28import tempfile
raymes01959ae2013-02-15 04:50:07 +000029from utils import command_executer
30from utils import logger
asharif00e8b292013-02-15 04:36:08 +000031from utils import utils
32
33# Common initializations
raymes01959ae2013-02-15 04:50:07 +000034cmd_executer = command_executer.GetCommandExecuter()
asharif00e8b292013-02-15 04:36:08 +000035(rootdir, basename) = utils.GetRoot(sys.argv[0])
asharif00e8b292013-02-15 04:36:08 +000036
37
38def 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
raymes01959ae2013-02-15 04:50:07 +000046 retval = cmd_executer.RunCommand(command)
asharif00e8b292013-02-15 04:36:08 +000047 return retval
48
49
asharifd8d0d9b2013-02-15 04:56:21 +000050def DeleteP4Client(client_name, client_dir):
51 command = "cd " + client_dir
52 command += "&& g4 client -d " + client_name
raymes01959ae2013-02-15 04:50:07 +000053 retval = cmd_executer.RunCommand(command)
asharif00e8b292013-02-15 04:36:08 +000054 return retval
55
56
57def SyncP4Client(client_name, checkoutdir, revision=None):
58 command = "cd " + checkoutdir
asharif8d5ecd22013-02-15 04:46:22 +000059 if revision:
60 command += " && g4 sync ...@" + revision
61 else:
62 command += " && g4 sync ..."
raymes01959ae2013-02-15 04:50:07 +000063 retval = cmd_executer.RunCommand(command)
asharif00e8b292013-02-15 04:36:08 +000064 return retval
65
66
67def GetP4PathsForTool(client_name, tool, branch_path):
asharif8d5ecd22013-02-15 04:46:22 +000068 """Returns the perforce paths for a tool {gcc|binutils}."""
asharif00e8b292013-02-15 04:36:08 +000069 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 "\"")
asharif6fca6ca2013-02-15 04:36:09 +000077 version_number = utils.GetRoot(rootdir)[1]
78 p4_paths.append("\"//depot2/gcctools/chromeos/" + version_number +
79 "/build-gcc/..." +
80 " //" + client_name + "/build-gcc/..." +
81 "\"")
asharifd8d0d9b2013-02-15 04:56:21 +000082 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 "\"")
asharif6fca6ca2013-02-15 04:36:09 +000096
asharif00e8b292013-02-15 04:36:08 +000097 return p4_paths
98
99
100def GetGitRepoForTool(tool):
101 # This should return the correct server repository when the script
102 # is fully done.
103 if tool == "gcc":
asharif8d5ecd22013-02-15 04:46:22 +0000104 return "ssh://git@gitrw.chromium.org:9222/gcc.git"
105 elif tool == "binutils":
106 return "ssh://git@gitrw.chromium.org:9222/binutils.git"
asharif00e8b292013-02-15 04:36:08 +0000107
108
asharif6fca6ca2013-02-15 04:36:09 +0000109def SetupBranch(checkoutdir, branch_name):
asharif8d5ecd22013-02-15 04:46:22 +0000110 """Sets up either the master or another branch in the local repo."""
asharif6fca6ca2013-02-15 04:36:09 +0000111 if branch_name == "master":
112 return 0
asharif00e8b292013-02-15 04:36:08 +0000113 command = "cd " + checkoutdir
asharif6fca6ca2013-02-15 04:36:09 +0000114 command += " && git branch -a | grep -wq " + branch_name
raymes01959ae2013-02-15 04:50:07 +0000115 retval = cmd_executer.RunCommand(command)
asharif6fca6ca2013-02-15 04:36:09 +0000116 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)
raymes01959ae2013-02-15 04:50:07 +0000123 retval = cmd_executer.RunCommand(command)
asharif6fca6ca2013-02-15 04:36:09 +0000124 return retval
125
126
127def CreateGitClient(git_repo, checkoutdir, branch_name):
asharif8d5ecd22013-02-15 04:46:22 +0000128 """Creates a git client with in a dir with a branch."""
asharif6fca6ca2013-02-15 04:36:09 +0000129 command = "cd " + checkoutdir
130 command += " && git clone -v " + git_repo + " ."
raymes01959ae2013-02-15 04:50:07 +0000131 retval = cmd_executer.RunCommand(command)
asharif6fca6ca2013-02-15 04:36:09 +0000132 if retval != 0:
133 return retval
134 retval = SetupBranch(checkoutdir, branch_name)
135 if retval != 0:
136 return retval
137 command = "cd " + checkoutdir
asharif00e8b292013-02-15 04:36:08 +0000138 command += " && rm -rf *"
raymes01959ae2013-02-15 04:50:07 +0000139 retval = cmd_executer.RunCommand(command)
asharif00e8b292013-02-15 04:36:08 +0000140 return retval
141
142
143def GetLatestCL(client_name, checkoutdir):
144 command = "cd " + checkoutdir
asharife9433c32013-02-15 05:53:27 +0000145 command += " && g4 changes -m1 ...#have"
raymes01959ae2013-02-15 04:50:07 +0000146 (status, stdout, stderr) = cmd_executer.RunCommand(command, True)
asharif00e8b292013-02-15 04:36:08 +0000147 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
155def WriteStringToFile(filename, string):
156 f = open(filename, "w")
157 f.write(string)
158 f.close()
159
160
asharif6fca6ca2013-02-15 04:36:09 +0000161def 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
169def PushToRemoteGitRepo(checkoutdir, branch_name, message_file, push_args):
asharif8d5ecd22013-02-15 04:46:22 +0000170 """Do the actualy git push to remote repository."""
asharif6fca6ca2013-02-15 04:36:09 +0000171 # Add the stuff we want git to ignore for the add.
172 AddGitIgnores(checkoutdir)
asharif00e8b292013-02-15 04:36:08 +0000173 command = "cd " + checkoutdir
asharif00e8b292013-02-15 04:36:08 +0000174 # For testing purposes, I am only adding a single file to the
175 # remote repository.
asharif6fca6ca2013-02-15 04:36:09 +0000176 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)
raymes01959ae2013-02-15 04:50:07 +0000181 retval = cmd_executer.RunCommand(command)
asharif00e8b292013-02-15 04:36:08 +0000182 return retval
183
184
185def 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.")
asharif6fca6ca2013-02-15 04:36:09 +0000192 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.")
asharif8d5ecd22013-02-15 04:46:22 +0000199 parser.add_option("-c", "--changelist", dest="changelist",
200 help="Optional changelist to sync to.")
asharif00e8b292013-02-15 04:36:08 +0000201
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/")
asharif6fca6ca2013-02-15 04:36:09 +0000210 branch_name = "master"
asharif00e8b292013-02-15 04:36:08 +0000211 else:
212 branch_path = ("//depot2/branches/" + options.branch +
213 "/gcctools")
asharif6fca6ca2013-02-15 04:36:09 +0000214 branch_name = options.branch
asharifd8d0d9b2013-02-15 04:56:21 +0000215 utils.AssertTrue(os.path.exists("/google/src/files/p2/head/depot2/" +
216 "branches/" + branch_name),
217 "Branch name: " + branch_name + " not found!")
218
asharif6fca6ca2013-02-15 04:36:09 +0000219 if options.remote:
220 git_repo = options.remote
221 else:
222 git_repo = GetGitRepoForTool(options.tool)
asharif00e8b292013-02-15 04:36:08 +0000223
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)
asharif6fca6ca2013-02-15 04:36:09 +0000229 status = CreateGitClient(git_repo, temp_dir, branch_name)
asharif00e8b292013-02-15 04:36:08 +0000230 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")
asharif6fca6ca2013-02-15 04:36:09 +0000233 # If the user presses Ctrl-C, make sure to clean up p4 client.
234 try:
asharif8d5ecd22013-02-15 04:46:22 +0000235 status = SyncP4Client(client_name, temp_dir, options.changelist)
asharif6fca6ca2013-02-15 04:36:09 +0000236 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):
raymes01959ae2013-02-15 04:50:07 +0000250 logger.GetLogger().LogOutput("Caught exception... Cleaning up.")
asharifd8d0d9b2013-02-15 04:56:21 +0000251 status = DeleteP4Client(client_name, temp_dir)
asharif6fca6ca2013-02-15 04:36:09 +0000252 raise
asharifd8d0d9b2013-02-15 04:56:21 +0000253 status = DeleteP4Client(client_name, temp_dir)
asharif00e8b292013-02-15 04:36:08 +0000254 utils.AssertTrue(status == 0, "Could not delete p4 client")
asharif2198c512013-02-15 09:21:35 +0000255 return status
asharif00e8b292013-02-15 04:36:08 +0000256
257
258if __name__ == "__main__":
asharif2198c512013-02-15 09:21:35 +0000259 retval = Main()
260 sys.exit(retval)
asharif00e8b292013-02-15 04:36:08 +0000261
262