aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWill Drewry <drewry@google.com>2015-10-21 14:47:09 -0700
committerWill Drewry <drewry@google.com>2015-10-21 21:39:43 -0700
commit6cf9c6c632cf200bbc6da02d7453381269067d3b (patch)
treef53c2659df766e0f23b755f86f0ec847ee5046a6
parent2026eb3d850c7902586fb8c0143d5aaf3b14443f (diff)
downloadbdk-6cf9c6c632cf200bbc6da02d7453381269067d3b.tar.gz
brunch: first cut at portable product directories
While product reconfig provides a good means to update envsetup.sh or restore a bad database, it is not practical in cases where the same product dir is being used from different paths. For example, if the product dir is mounted in different places on different hosts. This change removes product paths from the product configuration and attempts to use the relative path. If it cannot be found, the user is requested to export PRODUCT_PATH before using envsetup.sh. The same is true for the BDK location where it can be set with BDK_PATH. BUG=25148498 TEST=moved a product. Sourced in tree and out of tree using both bash and dash. Aliases still worked. Change-Id: If6d06eabf1af650f41f71c5c5d94a3324103a473
-rw-r--r--brunch/lib/commands/product/envsetup.py8
-rw-r--r--brunch/lib/commands/product/reconfig.py1
-rw-r--r--brunch/lib/core/config.py2
-rw-r--r--brunch/lib/core/product.py17
-rw-r--r--brunch/lib/core/product_templates.py46
5 files changed, 59 insertions, 15 deletions
diff --git a/brunch/lib/commands/product/envsetup.py b/brunch/lib/commands/product/envsetup.py
index 27bcbcf..18dfd82 100644
--- a/brunch/lib/commands/product/envsetup.py
+++ b/brunch/lib/commands/product/envsetup.py
@@ -37,13 +37,15 @@ class Envsetup(clicommand.Command):
# TODO(wad): Add 'shell' argument to select a non-sh format.
def Run(self, args):
- # TODO(wad) Check version difference.
- store = config.ProductStore(args.product_path)
+ # As product_path will end up in the shell environment, we can't
+ # rely on a relative path being safe for reinvocation.
+ product_path = os.path.abspath(args.product_path)
+ store = config.ProductStore(product_path)
if not store.complete():
# TODO(wad) what's the best way to recover for a user here?
print "Product data store is incomplete. Product must be recreated."
return 1
- env = product.Environment(store)
+ env = product.Environment(store, product_path)
if args.generate is False:
print env.environment()
else:
diff --git a/brunch/lib/commands/product/reconfig.py b/brunch/lib/commands/product/reconfig.py
index c0bc135..eb340c3 100644
--- a/brunch/lib/commands/product/reconfig.py
+++ b/brunch/lib/commands/product/reconfig.py
@@ -58,7 +58,6 @@ class Reconfig(clicommand.Command):
if not store.buildtype: store.buildtype = 'eng'
if not store.type: store.type = 'empty'
- store.path = args.product_path
store.bdk_version = util.GetBDKVersion()
# Repopulate the envsetup.sh file.
diff --git a/brunch/lib/core/config.py b/brunch/lib/core/config.py
index 050924f..e565ede 100644
--- a/brunch/lib/core/config.py
+++ b/brunch/lib/core/config.py
@@ -121,7 +121,7 @@ class UserStore(Store):
class ProductStore(Store):
REQUIRED_PROPS = [ 'name', 'device', 'manufacturer', \
- 'buildtype', 'path', 'bdk_version', 'type' ]
+ 'buildtype', 'bdk_version', 'type' ]
OPTIONAL_PROPS = [ 'java' ]
PREFIX = 'product_'
diff --git a/brunch/lib/core/product.py b/brunch/lib/core/product.py
index 0c9b94c..7a9812c 100644
--- a/brunch/lib/core/product.py
+++ b/brunch/lib/core/product.py
@@ -120,10 +120,14 @@ class ProductCreator(object):
class Environment(object):
"""This class is used to generate a shell environment meant to streamline
the use of the BDK while keeping it familiar to Android device developers.
+
+ Note: None of the templates other than ENVSETUP should contain 's. If they
+ do, it will break during sourcing of envsetup.sh.
"""
- def __init__(self, config):
+ def __init__(self, config, product_dir=util.GetProductDir()):
self._config = config
+ self._product_dir = product_dir
def banner(self):
"""Return the banner to be printed after envsetup.sh is sourced"""
@@ -145,15 +149,17 @@ class Environment(object):
return product_templates.ENV_EXPORTS.substitute(
self._config.dict(),
bdk_path=bdk_path,
+ product_path=self._product_dir,
brunch_path=os.path.join(bdk_path, 'tools', 'bdk', 'brunch'),
- target_out=os.path.join(self._config.path, 'out',
+ target_out=os.path.join(self._product_dir, 'out',
'out-%s' % (self._config.device),
'target', 'product', self._config.device)
)
def aliases(self):
"""Wrap brunch commands with shell functions"""
- return product_templates.ENV_ALIASES.substitute(self._config.dict())
+ return product_templates.ENV_ALIASES.substitute(
+ self._config.dict(), product_path=self._product_dir)
def environment(self):
"""Returns a complete shell environment for product development"""
@@ -163,6 +169,7 @@ class Environment(object):
"""Generates a file which will run brunch product envsetup"""
bdk_path = util.GetBDKPath()
bdk_version = util.GetBDKVersion()
- with open(os.path.join(self._config.path, 'envsetup.sh'), 'w') as f:
+ with open(os.path.join(self._product_dir, 'envsetup.sh'), 'w') as f:
f.write(product_templates.ENVSETUP.substitute(
- self._config.dict(), bdk_path=bdk_path))
+ self._config.dict(), bdk_path=bdk_path,
+ product_path=self._product_dir))
diff --git a/brunch/lib/core/product_templates.py b/brunch/lib/core/product_templates.py
index ea64286..d81045a 100644
--- a/brunch/lib/core/product_templates.py
+++ b/brunch/lib/core/product_templates.py
@@ -124,13 +124,49 @@ provision() {
""")
+# Inside this template, brunch is re-called to export an updated
+# environment. To do so, the output is packed into an fd and then
+# source'd by the shell. The approach is messier than using <()
+# in order to avoid a specific bashism and keep this part dash clean.
+# That is yet to be a requirement across all the scripts, though.
ENVSETUP = string.Template("""\
_envsetup_load() {
- local t=`mktemp ${product_path}/.envsetup.sh.XXXXX`
- ${bdk_path}/tools/bdk/brunch/brunch product envsetup \\
- --product_path="${product_path}" > "$$t"
- source $$t
- rm $$t
+ # Allow the environment to override the BDK path.
+ local bdk="$${BDK_PATH:-${bdk_path}}"
+ if ! test -x "$${bdk}/tools/bdk/brunch/brunch"; then
+ echo "The BDK cannot be found." 1>&2
+ echo "Please supply its path in the BDK_PATH environment variable or " 1>&2
+ echo "run 'brunch product reconfig'" 1>&2
+ return 1
+ fi
+
+ # Make sure we're in the root of a product.
+ # If the user explicitly exported a PRODUCT_PATH, then fail if it is wrong.
+ if test -n "$${PRODUCT_PATH}" && \
+ ! test -e "$${PRODUCT_PATH}/.brunch_product.db"; then
+ echo "Cannot find a product at PRODUCT_PATH: $${PRODUCT_PATH}" 1>&2
+ return 1
+ fi
+ # Otherwise, use the default or check the cwd.
+ local product_path="$${PRODUCT_PATH:-${product_path}}"
+ if ! test -e "$${product_path}/.brunch_product.db"; then
+ echo "Checking current directory for a valid product . . ." 1>&2
+ product_path=$$PWD
+ if ! test -e "$${product_path}/.brunch_product.db"; then
+ echo "Please source envsetup.sh from the product directory " 1>&2
+ echo "or set a valid PRODUCT_PATH in the environment." 1>&2
+ return 1
+ fi
+ fi
+
+ # Find a free file descriptor and use it rather than a tempfile.
+ fd=$$((`ls /dev/fd/ | sort -n | tail -1` + 1))
+ eval 'exec '$$fd'<<EOFEOF
+ $$($${bdk}/tools/bdk/brunch/brunch product envsetup \\
+ --product_path="$${product_path}")
+EOFEOF'
+ . /dev/fd/$$fd
+ eval "exec $$fd<&-"
}
_envsetup_load
""")