Commit 0230d91a authored by ferringb@google.com's avatar ferringb@google.com

Cleanup chromite_wrapper.

The original design of this had some issues:

1) forced targets to be importable via 'buildbot.cbuildbot', rather
  than the proper/full 'chromite.buildbot.cbuildbot'.  Scripts worked
  around this, but it's an unwanted limitation.

2) That importation requirement means that within the chroot, we've
  had to export cros_sdk *and* cros_sdk.py in the PATH.  This is
  undesirable clutter, and introduces potential errors as scripts
  localize themselves to cros_sdk.py rather than invoking cros_sdk
  (the consumers should be agnostic to the language the tool is
  written in).

3) chromite_wrapper enforced assumptions about python namespace w/in
  the targets- specifically that 'main' must always be invokable
  without any arguments.  This limits refactoring/cleanup in chromite
  via having to support ancient API assumptions (api's that weren't
  public); modern chromite has repurposed main changing the prototype,
  and using it's own wrapper doing signal handler setup, and general
  framework behaviour.  Longer term, that 'main' functor is unlikely
  to even exist.  The strong coupling chromite_wrapper forced limits
  are refactoring possibilities.

4) In modern chromite, all user consumable tools are now required to
  exist w/in chromite/bin/, and be executable and invokable.  This is
  what we want going forward.

5) Implied we want chromite_wrapper used w/in the chroot; we don't,
  thus drop all CROS_WORKON_SRCROOT awareness.

6) Exposed a chromite_wrapper invokable (that didn't work) into the
  PATH outside the chroot; this is resolved via moving it into a
  support directory and repointing symlinks to it.

At this point, if it's working with a modern chromite checkout the
script is a simple execv pass thru.  If it isn't, then it will fallback
to the old import trickery.

This has been tested against R16, R17, R18, ToT, 0.11.241.B, factory-*,
basically all branches w/in chromite without issue.




git-svn-id: svn://svn.chromium.org/chrome/trunk/tools/depot_tools@128555 0039d316-1c4b-4281-b951-d872f2087c98
parent a2cbbbb3
chromite_wrapper
\ No newline at end of file
support/chromite_wrapper
\ No newline at end of file
chromite_wrapper
\ No newline at end of file
support/chromite_wrapper
\ No newline at end of file
#!/usr/bin/env python
# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Wrapper for chromite tools.
The script is intend to be symlinked to any number of chromite tools, attempts
to find the path for chromite, and runs the right tool based on argv[0].
It is intended to run in several ways:
- Outside the chroot, it should be _copied_ to someplace that is in the
path (like depot_tools). It will search for the right chromite by looking
for a file 'chromite/shell/main.py' upward based on the CWD.
- Inside the chroot, it might be _either_ copied to someplace in the path (since
depot_tools is in the path in the chroot) or it might run from chromite/bin
directly, which should be in the PATH. In any case, we'll look for the
real 'chromite/shell/main.py' based on the environment variable
CROS_WORKON_SRCROOT, so it doesn't matter what the CWD is.
If you're looking at a copy and want to know where the original looks at, look
here:
http://git.chromium.org/gitweb/?p=chromite.git;a=blob;f=bin/chromite
Since this script is _copied_, it should remain small and not use internal libs.
"""
import os
import sys
def Search(path):
"""Return an iterator of lists of places to look for chromite."""
if os.path.exists('/etc/debian_chroot'):
# We're in the chroot. Chromite should be in the python path inside the
# chroot, so we don't do any searching. NOTE that we purposely don't want
# CROS_WORKON_SRCROOT in the python path.
yield []
else:
# Look in $CROS_WORKON_SRCROOT first. The idea is that a user would set
# this manually if they wanted to specify a particular version of chromite.
if 'CROS_WORKON_SRCROOT' in os.environ:
yield [os.environ['CROS_WORKON_SRCROOT']]
# Search upward until we either end up with a blank dir or the "parent" dir
# doesn't change.
prev_path = None
while path and path != prev_path:
yield [path]
path, prev_path = os.path.dirname(path), path
def main():
# Decide what the name of the called binary will be.
our_name = os.path.basename(sys.argv[0])
# Some tools map to an arbitrary path, rather than to a .py file of the same
# exact name. By default, we pick the tool from chromite/bin/
TOOLS_MAP = {
'chromite' : 'shell.main',
'cbuildbot' : 'buildbot.cbuildbot',
}
our_name = TOOLS_MAP.get(our_name, 'bin.' + our_name)
for path in Search(os.getcwd()):
sys.path = path + sys.path
try:
exec 'import chromite.' + our_name + ' as our_tool'
break
except ImportError, e:
# Just in case there is actually something wrong with Chromite, print
# a sensible error. We match only the end of the string so that we can
# handle an error within the chromite directory.
# The full error is 'No module named (chromite.)shell.main'
# Note: If you hit the directory containing chromite on the way up, then
# the error will be 'No module named shell.main' so we must check only the
# shell.main part.
if not str(e).endswith(our_name):
raise
# We've got different modules named chromite in the tree, pulling in the
# wrong one will break the right one. So unload it.
if 'chromite' in sys.modules:
del sys.modules['chromite']
sys.path = sys.path[len(path):]
else:
# TODO(dianders): Should we actually print out the 'repo init' call that
# the user should use?
sys.stderr.write(
"ERROR: Couldn't find the chromite tool.\n"
"\n"
"Please change to a directory inside your Chromium OS source tree\n"
"and retry. If you need to setup a Chromium OS source tree, see:\n"
" http://www.chromium.org/chromium-os/developer-guide\n")
return 1
return our_tool.main()
if __name__ == '__main__':
sys.exit(main())
chromite_wrapper
\ No newline at end of file
support/chromite_wrapper
\ No newline at end of file
#!/usr/bin/env python
# Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
"""Wrapper for chromite tools.
The script is intend to be symlinked to any number of chromite tools, attempts
to find the path for chromite, and hands off to the right tool via exec if
possible.
It is intended to used strictly outside of the chroot.
If you're looking at a copy and want to know where the original looks at, look
here:
http://git.chromium.org/gitweb/?p=chromite.git;a=blob;f=bin/chromite
Since this script is _copied_, it should remain small and not use internal libs.
"""
import errno
import os
import sys
# Due to historical reasons, and the fact depot_tools ToT is used by older
# factory branches (lacking chromite script cleanups), note we have to
# fallback to some odd import locations. This is the only reason for the
# fallback code- any/all new scripts symlinked to this script *must* exist
# in chromite/bin/ .
def _FindRoot(path):
"""Find the root of a repo checkout"""
path = os.path.abspath(path)
while path != '/':
# Look for the chromite repository itself- it's always been at the root
# of a repo checkout.
if all(os.path.exists(os.path.join(path, x))
for x in ['.repo', 'chromite/.git']):
return path
path = os.path.dirname(path)
return None
def _MissingErrorOut(target):
sys.stderr.write(
"""ERROR: Couldn't find the chromite tool %s.
Please change to a directory inside your Chromium OS source tree
and retry. If you need to setup a Chromium OS source tree, see
http://www.chromium.org/chromium-os/developer-guide
""" % target)
return 127
def main():
root = _FindRoot(os.getcwd())
target = os.path.basename(sys.argv[0])
if root is None:
return _MissingErrorOut(target)
path = os.path.join(root, 'chromite/bin', target)
try:
os.execv(path, [path] + sys.argv[1:])
except EnvironmentError, e:
if e.errno not in (errno.ENOENT, errno.EPERM):
raise
# Reaching here means it's either a bad target, or we're working against
# an old (pre 6be2efcf5bb575b03862113eec097c44d8d7f93e) revision of
# chromite. Fallback to trying to import it; this code works at least as
# far back as branch 0.11.241.B; likely further.
if target == 'cbuildbot':
target = 'chromite.buildbot.cbuildbot'
else:
target = 'chromite.bin.%s' % (target,)
# Adjust the path importation so we can import our our target.
sys.path.insert(0, root)
try:
module = __import__(target, fromlist=['main'])
except ImportError:
return _MissingErrorOut(target)
return module.main()
if __name__ == '__main__':
sys.exit(main())
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment