| OLD | NEW |
| 1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
| 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 3 # Use of this source code is governed by a BSD-style license that can be | 3 # Use of this source code is governed by a BSD-style license that can be |
| 4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
| 5 | 5 |
| 6 """Script that reads omahaproxy and gsutil to determine version of SDK to put | 6 """Script that reads omahaproxy and gsutil to determine version of SDK to put |
| 7 in manifest. | 7 in manifest. |
| 8 """ | 8 """ |
| 9 | 9 |
| 10 # pylint is convinced the email module is missing attributes | 10 # pylint is convinced the email module is missing attributes |
| (...skipping 149 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 stdin: If src is '-', this is used as the stdin to give to gsutil. The | 160 stdin: If src is '-', this is used as the stdin to give to gsutil. The |
| 161 effect is that text in stdin is copied to |dest|.""" | 161 effect is that text in stdin is copied to |dest|.""" |
| 162 raise NotImplementedError() | 162 raise NotImplementedError() |
| 163 | 163 |
| 164 def Print(self, *args): | 164 def Print(self, *args): |
| 165 """Print a message.""" | 165 """Print a message.""" |
| 166 raise NotImplementedError() | 166 raise NotImplementedError() |
| 167 | 167 |
| 168 | 168 |
| 169 class RealDelegate(Delegate): | 169 class RealDelegate(Delegate): |
| 170 def __init__(self, dryrun=False, gsutil=None): | 170 def __init__(self, dryrun=False, gsutil=None, verbose=False): |
| 171 super(RealDelegate, self).__init__() | 171 super(RealDelegate, self).__init__() |
| 172 self.dryrun = dryrun | 172 self.dryrun = dryrun |
| 173 self.verbose = verbose |
| 173 if gsutil: | 174 if gsutil: |
| 174 self.gsutil = gsutil | 175 self.gsutil = gsutil |
| 175 else: | 176 else: |
| 176 self.gsutil = buildbot_common.GetGsutil() | 177 self.gsutil = buildbot_common.GetGsutil() |
| 177 | 178 |
| 178 def GetRepoManifest(self): | 179 def GetRepoManifest(self): |
| 179 """See Delegate.GetRepoManifest""" | 180 """See Delegate.GetRepoManifest""" |
| 180 with open(REPO_MANIFEST, 'r') as sdk_stream: | 181 with open(REPO_MANIFEST, 'r') as sdk_stream: |
| 181 sdk_json_string = sdk_stream.read() | 182 sdk_json_string = sdk_stream.read() |
| 182 | 183 |
| 183 manifest = manifest_util.SDKManifest() | 184 manifest = manifest_util.SDKManifest() |
| 184 manifest.LoadDataFromString(sdk_json_string) | 185 manifest.LoadDataFromString(sdk_json_string, add_missing_info=True) |
| 185 return manifest | 186 return manifest |
| 186 | 187 |
| 187 def GetHistory(self): | 188 def GetHistory(self): |
| 188 """See Delegate.GetHistory""" | 189 """See Delegate.GetHistory""" |
| 189 url_stream = urllib2.urlopen('https://omahaproxy.appspot.com/history') | 190 url_stream = urllib2.urlopen('https://omahaproxy.appspot.com/history') |
| 190 return [(platform, channel, version, date) | 191 return [(platform, channel, version, date) |
| 191 for platform, channel, version, date in csv.reader(url_stream)] | 192 for platform, channel, version, date in csv.reader(url_stream)] |
| 192 | 193 |
| 193 def GetTrunkRevision(self, version): | 194 def GetTrunkRevision(self, version): |
| 194 """See Delegate.GetTrunkRevision""" | 195 """See Delegate.GetTrunkRevision""" |
| (...skipping 10 matching lines...) Expand all Loading... |
| 205 # filter out empty lines | 206 # filter out empty lines |
| 206 return filter(None, stdout.split('\n')) | 207 return filter(None, stdout.split('\n')) |
| 207 | 208 |
| 208 def GsUtil_cat(self, url): | 209 def GsUtil_cat(self, url): |
| 209 """See Delegate.GsUtil_cat""" | 210 """See Delegate.GsUtil_cat""" |
| 210 return self._RunGsUtil(None, 'cat', url) | 211 return self._RunGsUtil(None, 'cat', url) |
| 211 | 212 |
| 212 def GsUtil_cp(self, src, dest, stdin=None): | 213 def GsUtil_cp(self, src, dest, stdin=None): |
| 213 """See Delegate.GsUtil_cp""" | 214 """See Delegate.GsUtil_cp""" |
| 214 if self.dryrun: | 215 if self.dryrun: |
| 216 self.Trace("Skipping upload: %s -> %s" % (src, dest)) |
| 215 return | 217 return |
| 216 | 218 |
| 217 # -p ensures we keep permissions when copying "in-the-cloud". | 219 # -p ensures we keep permissions when copying "in-the-cloud". |
| 218 return self._RunGsUtil(stdin, 'cp', '-p', '-a', 'public-read', src, dest) | 220 return self._RunGsUtil(stdin, 'cp', '-p', '-a', 'public-read', src, dest) |
| 219 | 221 |
| 220 def Print(self, *args): | 222 def Print(self, *args): |
| 221 sys.stdout.write(' '.join(map(str, args)) + '\n') | 223 sys.stdout.write(' '.join(map(str, args)) + '\n') |
| 222 | 224 |
| 225 def Trace(self, *args): |
| 226 if self.verbose: |
| 227 self.Print(*args) |
| 228 |
| 223 def _RunGsUtil(self, stdin, *args): | 229 def _RunGsUtil(self, stdin, *args): |
| 224 """Run gsutil as a subprocess. | 230 """Run gsutil as a subprocess. |
| 225 | 231 |
| 226 Args: | 232 Args: |
| 227 stdin: If non-None, used as input to the process. | 233 stdin: If non-None, used as input to the process. |
| 228 *args: Arguments to pass to gsutil. The first argument should be an | 234 *args: Arguments to pass to gsutil. The first argument should be an |
| 229 operation such as ls, cp or cat. | 235 operation such as ls, cp or cat. |
| 230 Returns: | 236 Returns: |
| 231 The stdout from the process.""" | 237 The stdout from the process.""" |
| 232 cmd = [self.gsutil] + list(args) | 238 cmd = [self.gsutil] + list(args) |
| 239 self.Trace("Running: %s" % str(cmd)) |
| 233 if stdin: | 240 if stdin: |
| 234 stdin_pipe = subprocess.PIPE | 241 stdin_pipe = subprocess.PIPE |
| 235 else: | 242 else: |
| 236 stdin_pipe = None | 243 stdin_pipe = None |
| 237 | 244 |
| 238 process = subprocess.Popen(cmd, stdin=stdin_pipe, stdout=subprocess.PIPE, | 245 try: |
| 239 stderr=subprocess.PIPE) | 246 process = subprocess.Popen(cmd, stdin=stdin_pipe, stdout=subprocess.PIPE, |
| 240 stdout, stderr = process.communicate(stdin) | 247 stderr=subprocess.PIPE) |
| 248 stdout, stderr = process.communicate(stdin) |
| 249 except OSError as e: |
| 250 raise manifest_util.Error("Unable to run '%s': %s" % (cmd[0], str(e))) |
| 241 | 251 |
| 242 if process.returncode != 0: | 252 if process.returncode: |
| 243 sys.stderr.write(stderr) | 253 sys.stderr.write(stderr) |
| 244 raise subprocess.CalledProcessError(process.returncode, ' '.join(cmd)) | 254 raise subprocess.CalledProcessError(process.returncode, ' '.join(cmd)) |
| 245 return stdout | 255 return stdout |
| 246 | 256 |
| 247 | 257 |
| 248 class VersionFinder(object): | 258 class VersionFinder(object): |
| 249 """Finds a version of a pepper bundle that all desired platforms share.""" | 259 """Finds a version of a pepper bundle that all desired platforms share.""" |
| 250 def __init__(self, delegate): | 260 def __init__(self, delegate): |
| 251 self.delegate = delegate | 261 self.delegate = delegate |
| 252 self.history = delegate.GetHistory() | 262 self.history = delegate.GetHistory() |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 | 521 |
| 512 def _UploadManifest(self, manifest): | 522 def _UploadManifest(self, manifest): |
| 513 """Upload a serialized manifest_util.SDKManifest object. | 523 """Upload a serialized manifest_util.SDKManifest object. |
| 514 | 524 |
| 515 Upload one copy to gs://<BUCKET_PATH>/naclsdk_manifest2.json, and a copy to | 525 Upload one copy to gs://<BUCKET_PATH>/naclsdk_manifest2.json, and a copy to |
| 516 gs://<BUCKET_PATH>/manifest_backups/naclsdk_manifest2.<TIMESTAMP>.json. | 526 gs://<BUCKET_PATH>/manifest_backups/naclsdk_manifest2.<TIMESTAMP>.json. |
| 517 | 527 |
| 518 Args: | 528 Args: |
| 519 manifest: The new manifest to upload. | 529 manifest: The new manifest to upload. |
| 520 """ | 530 """ |
| 531 if self.delegate.dryrun: |
| 532 name = MANIFEST_BASENAME + ".new" |
| 533 self.delegate.Print("Writing new manifest: %s" % name) |
| 534 with open(name, 'w') as f: |
| 535 f.write(manifest.GetDataAsString()) |
| 536 stdout = self.delegate.GsUtil_cat(GS_SDK_MANIFEST) |
| 537 |
| 538 online = MANIFEST_BASENAME + ".online" |
| 539 self.delegate.Print("Writing online manifest: %s" % online) |
| 540 with open(online, 'w') as f: |
| 541 f.write(stdout) |
| 542 os.system('diff -u %s %s' % (online, name)) |
| 543 |
| 521 timestamp_manifest_path = GS_MANIFEST_BACKUP_DIR + \ | 544 timestamp_manifest_path = GS_MANIFEST_BACKUP_DIR + \ |
| 522 GetTimestampManifestName() | 545 GetTimestampManifestName() |
| 523 self.delegate.GsUtil_cp('-', timestamp_manifest_path, | 546 self.delegate.GsUtil_cp('-', timestamp_manifest_path, |
| 524 stdin=manifest.GetDataAsString()) | 547 stdin=manifest.GetDataAsString()) |
| 525 | 548 |
| 526 # copy from timestampped copy over the official manifest. | 549 # copy from timestampped copy over the official manifest. |
| 527 self.delegate.GsUtil_cp(timestamp_manifest_path, GS_SDK_MANIFEST) | 550 self.delegate.GsUtil_cp(timestamp_manifest_path, GS_SDK_MANIFEST) |
| 528 | 551 |
| 529 | 552 |
| 530 def Run(delegate, platforms): | 553 def Run(delegate, platforms): |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 590 self.written.write(s) | 613 self.written.write(s) |
| 591 if self.passthrough: | 614 if self.passthrough: |
| 592 self.passthrough.write(s) | 615 self.passthrough.write(s) |
| 593 | 616 |
| 594 def getvalue(self): | 617 def getvalue(self): |
| 595 return self.written.getvalue() | 618 return self.written.getvalue() |
| 596 | 619 |
| 597 | 620 |
| 598 def main(args): | 621 def main(args): |
| 599 parser = optparse.OptionParser() | 622 parser = optparse.OptionParser() |
| 600 parser.add_option('--gsutil', help='path to gsutil', dest='gsutil', | 623 parser.add_option('--gsutil', help='path to gsutil.') |
| 601 default=None) | 624 parser.add_option('-d', '--debug', help='run in debug mode.', |
| 602 parser.add_option('--mailfrom', help='email address of sender', | 625 action='store_true') |
| 603 dest='mailfrom', default=None) | 626 parser.add_option('--mailfrom', help='email address of sender.') |
| 604 parser.add_option('--mailto', help='send error mails to...', dest='mailto', | 627 parser.add_option('--mailto', help='send error mails to...', action='append') |
| 605 default=[], action='append') | 628 parser.add_option('-n', '--dryrun', help="don't upload the manifest.", |
| 606 parser.add_option('--dryrun', help='don\'t upload the manifest.', | 629 action='store_true') |
| 607 dest='dryrun', action='store_true', default=False) | 630 parser.add_option('-v', '--verbose', help='print more diagnotic messages.', |
| 631 action='store_true') |
| 608 options, args = parser.parse_args(args[1:]) | 632 options, args = parser.parse_args(args[1:]) |
| 609 | 633 |
| 610 if (options.mailfrom is None) != (not options.mailto): | 634 if (options.mailfrom is None) != (not options.mailto): |
| 611 options.mailfrom = None | 635 options.mailfrom = None |
| 612 options.mailto = None | 636 options.mailto = None |
| 613 sys.stderr.write('warning: Disabling email, one of --mailto or --mailfrom ' | 637 sys.stderr.write('warning: Disabling email, one of --mailto or --mailfrom ' |
| 614 'was missing.\n') | 638 'was missing.\n') |
| 615 | 639 |
| 616 if options.mailfrom and options.mailto: | 640 if options.mailfrom and options.mailto: |
| 617 # Capture stderr so it can be emailed, if necessary. | 641 # Capture stderr so it can be emailed, if necessary. |
| 618 sys.stderr = CapturedFile(sys.stderr) | 642 sys.stderr = CapturedFile(sys.stderr) |
| 619 | 643 |
| 620 try: | 644 try: |
| 621 delegate = RealDelegate(dryrun=options.dryrun, gsutil=options.gsutil) | 645 try: |
| 622 Run(delegate, ('mac', 'win', 'linux')) | 646 delegate = RealDelegate(options.dryrun, options.gsutil, options.verbose) |
| 623 except Exception: | 647 Run(delegate, ('mac', 'win', 'linux')) |
| 624 if options.mailfrom and options.mailto: | 648 except Exception: |
| 625 traceback.print_exc() | 649 if options.mailfrom and options.mailto: |
| 626 scriptname = os.path.basename(sys.argv[0]) | 650 traceback.print_exc() |
| 627 subject = '[%s] Failed to update manifest' % (scriptname,) | 651 scriptname = os.path.basename(sys.argv[0]) |
| 628 text = '%s failed.\n\nSTDERR:\n%s\n' % (scriptname, sys.stderr.getvalue()) | 652 subject = '[%s] Failed to update manifest' % (scriptname,) |
| 629 SendMail(options.mailfrom, options.mailto, subject, text) | 653 text = '%s failed.\n\nSTDERR:\n%s\n' % (scriptname, |
| 630 sys.exit(1) | 654 sys.stderr.getvalue()) |
| 631 else: | 655 SendMail(options.mailfrom, options.mailto, subject, text) |
| 656 sys.exit(1) |
| 657 else: |
| 658 raise |
| 659 except manifest_util.Error as e: |
| 660 if options.debug: |
| 632 raise | 661 raise |
| 662 print e |
| 663 sys.exit(1) |
| 633 | 664 |
| 634 | 665 |
| 635 if __name__ == '__main__': | 666 if __name__ == '__main__': |
| 636 sys.exit(main(sys.argv)) | 667 sys.exit(main(sys.argv)) |
| OLD | NEW |