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

Unified Diff: scripts/slave/annotated_checkout.py

Issue 15270004: Add step generator protocol, remove annotated_checkout, remove script. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/tools/build
Patch Set: Address comments and change expected json output format Created 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « scripts/common/annotator.py ('k') | scripts/slave/annotated_run.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: scripts/slave/annotated_checkout.py
diff --git a/scripts/slave/annotated_checkout.py b/scripts/slave/annotated_checkout.py
deleted file mode 100755
index 9562be686d6c04524a984d0aa61b018ad459fd51..0000000000000000000000000000000000000000
--- a/scripts/slave/annotated_checkout.py
+++ /dev/null
@@ -1,269 +0,0 @@
-#!/usr/bin/env python
-# Copyright (c) 2013 The Chromium Authors. All rights reserved.
-# Use of this source code is governed by a BSD-style license that can be
-# found in the LICENSE file.
-
-"""Helper script for fully-annotated builds. Performs checkouts of various
-kinds.
-
-This script is part of the effort to move all builds to annotator-based systems.
-Any builder configured to use the AnnotatorFactory uses run.py as its entry
-point. If that builder's factory_properties include a spec for a checkout, then
-the work of actually performing that checkout is done here.
-"""
-
-import cStringIO as StringIO
-import optparse
-import os
-import pipes
-import subprocess
-import sys
-
-from common import annotator
-from common import chromium_utils
-
-
-SCRIPT_PATH = os.path.dirname(os.path.abspath(__file__))
-
-
-def get_args():
- """Process command-line arguments."""
- parser = optparse.OptionParser(
- description='Checkout helper for annotated builds.')
- parser.add_option('--type',
- action='store', type='string', default='',
- help='type of checkout (i.e. gclient, git, or svn)')
- parser.add_option('--spec',
- action='callback', callback=chromium_utils.convert_json,
- type='string', default={},
- help='repository spec (url and metadata) to checkout')
- return parser.parse_args()
-
-
-class _CheckoutMetaclass(type):
- """Automatically register Checkout subclasses for factory discoverability."""
- checkout_registry = {}
-
- def __new__(mcs, name, bases, attrs):
- checkout_type = attrs['CHECKOUT_TYPE']
-
- if checkout_type in mcs.checkout_registry:
- raise ValueError('Duplicate checkout identifier "%s" found in: %s' %
- (checkout_type, name))
-
- # Only the base class is allowed to have no CHECKOUT_TYPE. The base class
- # should be the only one to specify this metaclass.
- if not checkout_type and attrs.get('__metaclass__') != mcs:
- raise ValueError('"%s" CHECKOUT_TYPE cannot be empty or None.' % name)
-
- newcls = super(_CheckoutMetaclass, mcs).__new__(mcs, name, bases, attrs)
- # Don't register the base class.
- if checkout_type:
- mcs.checkout_registry[checkout_type] = newcls
- return newcls
-
-
-class Checkout(object):
- """Base class for implementing different types of checkouts.
-
- Attributes:
- CHECKOUT_TYPE: String identifier used when selecting the type of checkout to
- perform. All subclasses must specify a unique CHECKOUT_TYPE value.
- """
- __metaclass__ = _CheckoutMetaclass
- CHECKOUT_TYPE = None
-
- def __init__(self, spec):
- self.spec = spec
-
- def setup(self):
- pass
-
- def clean(self):
- pass
-
- def checkout(self):
- pass
-
- def root(self):
- pass
-
-
-def CheckoutFactory(type_name, spec):
- """Factory to build Checkout class instances."""
- class_ = _CheckoutMetaclass.checkout_registry.get(type_name)
- if not class_ or not issubclass(class_, Checkout):
- raise KeyError('unrecognized checkout type: %s' % type_name)
- return class_(spec)
-
-
-class GclientCheckout(Checkout):
- CHECKOUT_TYPE = 'gclient'
-
- gclient_path = os.path.abspath(
- os.path.join(SCRIPT_PATH, '..', '..', '..', 'depot_tools', 'gclient'))
- if sys.platform.startswith('win'):
- gclient_path += '.bat'
-
- def __init__(self, *args, **kwargs):
- super(GclientCheckout, self).__init__(*args, **kwargs)
- assert 'solutions' in self.spec
-
- @classmethod
- def run_gclient(cls, *cmd):
- print 'Running: gclient %s' % ' '.join(pipes.quote(x) for x in cmd)
- subprocess.check_call((cls.gclient_path,)+cmd)
-
- def setup(self):
- spec_string = ''
- for key in self.spec:
- # We should be using json.dumps here, but gclient directly execs the dict
- # that it receives as the argument to --spec, so we have to have True,
- # False, and None instead of JSON's true, false, and null.
- spec_string += '%s = %s\n' % (key, str(self.spec[key]))
- self.run_gclient('config', '--spec', spec_string)
-
- def clean(self):
- self.run_gclient('revert', '--nohooks')
-
- def checkout(self):
- self.run_gclient('sync', '--nohooks')
-
- def root(self):
- return os.path.abspath(self.spec['solutions'][0]['name'])
-
-
-class GclientGitCheckout(GclientCheckout):
- """A gclient checkout tuned for purely git-based DEPS."""
- CHECKOUT_TYPE = 'gclient_git'
- def clean(self):
- # clean() isn't used because the gclient sync flags passed in checkout() do
- # much the same thing, and they're more correct than doing a separate
- # 'gclient revert' because it makes sure the other args are correct when a
- # repo was deleted and needs to be re-cloned (notably --with_branch_heads),
- # whereas 'revert' uses default args for clone operations.
- #
- # TODO(mmoss): To be like current official builders, this step could just
- # delete the whole <slave_name>/build/ directory and start each build from
- # scratch. That might be the least bad solution, at least until we have a
- # reliable gclient method to produce a pristine working dir for git-based
- # builds (e.g. maybe some combination of 'git reset/clean -fx' and removing
- # the 'out' directory).
- pass
-
- def checkout(self):
- self.run_gclient('sync', '--verbose', '--with_branch_heads', '--nohooks',
- '--reset', '--delete_unversioned_trees', '--force')
-
-
-class GitCheckout(Checkout):
- """Git specs are a dictionary with up to four keys: |url|, |branch|,
- |recursive|, and |directory|. Only |url| is required. The others default
- to empty, which results in using the git-default values of HEAD, False,
- and the 'humanish' interpretation of the url, respectively. Note that |url|
- is the full git url of the repo, including username and port number if
- necessary."""
- CHECKOUT_TYPE = 'git'
-
- def __init__(self, *args, **kwargs):
- super(GitCheckout, self).__init__(*args, **kwargs)
- assert 'url' in self.spec
- assert os.pardir not in self.spec.get('directory', '')
-
- dir_path = self.spec.get('directory')
- if not dir_path:
- dir_path = self.spec['url'].rsplit('/', 1)[-1]
- if dir_path.endswith('.git'): # ex: https://host/foobar.git
- dir_path = dir_path[:-len('.git')]
- if not dir_path: # ex: ssh://host:repo/foobar/.git
- dir_path = dir_path.rsplit('/', 1)[-1]
- self.cwd = os.path.abspath(os.path.join(os.curdir, dir_path))
-
- def setup(self):
- if not os.path.exists(self.cwd):
- os.makedirs(self.cwd)
-
- try:
- self.run_git('branch')
- exists = True
- except subprocess.CalledProcessError:
- exists = False
- if exists:
- self.run_git('remote', 'rm', 'origin')
- else:
- self.run_git('init')
- self.run_git('remote', 'add', 'origin', self.spec['url'])
- # TODO(agable): add support for git crup.
- if self.spec.get('recursive'):
- self.run_git('fetch', 'origin', '--recurse-submodules')
- else:
- self.run_git('fetch', 'origin')
- branch = self.spec.get('branch', 'master')
- self.run_git('update-ref', 'refs/heads/%s' % branch, 'origin/%s' % branch)
-
- def run_git(self, *cmd):
- cmd = ('git',) + cmd
- print 'Running: %s' % (' '.join(pipes.quote(x) for x in cmd))
- subprocess.check_call(cmd, cwd=self.cwd)
-
- def clean(self):
- self.run_git('clean', '-f', '-d', '-x')
-
- def checkout(self):
- self.run_git('checkout', '-f', self.spec.get('branch', 'master'))
- self.run_git('submodule', 'update', '--init', '--recursive')
-
- def root(self):
- return self.cwd
-
-
-class SvnCheckout(Checkout):
- CHECKOUT_TYPE = 'svn'
-
-
-def run(checkout_type, checkout_spec, test_mode=False):
- """Perform a checkout with the given type and configuration.
-
- Args:
- checkout_type: Type of checkout to perform (matching a Checkout subclass
- CHECKOUT_TYPE attribute).
- checkout_spec: Configuration values needed for the type of checkout
- (repository url, etc.).
- test_mode: If we're in test_mode, just return error code and root without
- actually doing anything.
-
- Returns:
- Tuple of (<retcode>, <root_path>) where root_path is the absolute path
- to the 'root' of the checkout (as defined by |checkout_type|).
- """
- stream = sys.stdout
- if test_mode:
- stream = StringIO.StringIO()
- stream = annotator.StructuredAnnotationStream(
- seed_steps=['checkout_setup', 'checkout_clean', 'checkout'],
- stream=stream)
-
- with stream.step('checkout_setup') as s:
- try:
- checkout = CheckoutFactory(checkout_type, checkout_spec)
- except KeyError as e:
- s.step_text(e)
- s.step_failure()
- return (1, None)
- if test_mode:
- return (0, checkout.root())
- checkout.setup()
- with stream.step('checkout_clean') as s:
- checkout.clean()
- with stream.step('checkout') as s:
- checkout.checkout()
- return (0, checkout.root())
-
-
-def main():
- opts, _ = get_args()
- return run(opts.type, opts.spec)[0]
-
-
-if __name__ == '__main__':
- sys.exit(main())
« no previous file with comments | « scripts/common/annotator.py ('k') | scripts/slave/annotated_run.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698