summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChandan Singh <csingh43@bloomberg.net>2018-05-11 16:59:21 +0100
committerChandan Singh <csingh43@bloomberg.net>2018-05-11 17:00:07 +0100
commit177c26c3ea4e437b99dd15bba9263db12392366f (patch)
tree3570814a919fa267b978f57aaa392d90f88ed05d
parent5834aa85f7721c90b3b17d7d9baae6da81916ef3 (diff)
downloadbuildstream-chandan/368-bst-from-project-subdir.tar.gz
_frontend/cli.py: Allow specifying elements by absolute/relative pathchandan/368-bst-from-project-subdir
-rw-r--r--buildstream/_frontend/cli.py72
1 files changed, 53 insertions, 19 deletions
diff --git a/buildstream/_frontend/cli.py b/buildstream/_frontend/cli.py
index 3c91cf80d..e22d7f674 100644
--- a/buildstream/_frontend/cli.py
+++ b/buildstream/_frontend/cli.py
@@ -68,7 +68,7 @@ def override_completions(cmd_param, args, incomplete):
# We can't easily extend click's data structures without
# modifying click itself, so just do some weak special casing
# right here and select which parameters we want to handle specially.
- if isinstance(cmd_param.type, click.Path) and \
+ if isinstance(cmd_param.type, ElementParamType) and \
(cmd_param.name == 'elements' or
cmd_param.name == 'element' or
cmd_param.name == 'except_' or
@@ -109,6 +109,40 @@ click.BaseCommand.main = override_main
##################################################################
+# Custom Paramaeter Types #
+##################################################################
+
+class ElementParamType(click.ParamType):
+ name = 'Element'
+
+ def convert(self, value, param, ctx):
+ target = value
+
+ # If we are dealing with relative/absolute path to element and
+ # not target name, normalize the path into target name.
+ if value.startswith('.') or os.path.isabs(value):
+ fullpath = os.path.realpath(value)
+ base_directory = os.path.abspath(ctx.parent.params['directory'])
+ project_file = os.path.join(base_directory, 'project.conf')
+ project = _yaml.load(project_file)
+ element_directory = project.get('element-path')
+ if element_directory:
+ base_directory = os.path.join(base_directory, element_directory)
+
+ # Ensure that element is not outside elements directory.
+ # This is kind of ugly but python 3.4 does not has
+ # os.path.commonpath()
+ if not fullpath.startswith(base_directory + os.path.sep):
+ raise click.BadParameter('{} is outside project context'.format(fullpath),
+ ctx=ctx,
+ param=param)
+
+ target = os.path.relpath(fullpath, base_directory)
+
+ return target
+
+
+##################################################################
# Main Options #
##################################################################
def print_version(ctx, param, value):
@@ -206,20 +240,20 @@ def init(app, project_name, format_version, element_path, force):
@click.option('--all', 'all_', default=False, is_flag=True,
help="Build elements that would not be needed for the current build plan")
@click.option('--track', 'track_', multiple=True,
- type=click.Path(dir_okay=False, readable=True),
+ type=ElementParamType(),
help="Specify elements to track during the build. Can be used "
"repeatedly to specify multiple elements")
@click.option('--track-all', default=False, is_flag=True,
help="Track all elements in the pipeline")
@click.option('--track-except', multiple=True,
- type=click.Path(dir_okay=False, readable=True),
+ type=ElementParamType(),
help="Except certain dependencies from tracking")
@click.option('--track-cross-junctions', '-J', default=False, is_flag=True,
help="Allow tracking to cross junction boundaries")
@click.option('--track-save', default=False, is_flag=True,
help="Deprecated: This is ignored")
@click.argument('elements', nargs=-1,
- type=click.Path(dir_okay=False, readable=True))
+ type=ElementParamType())
@click.pass_obj
def build(app, elements, all_, track_, track_save, track_all, track_except, track_cross_junctions):
"""Build elements in a pipeline"""
@@ -248,7 +282,7 @@ def build(app, elements, all_, track_, track_save, track_all, track_except, trac
##################################################################
@cli.command(short_help="Fetch sources in a pipeline")
@click.option('--except', 'except_', multiple=True,
- type=click.Path(dir_okay=False, readable=True),
+ type=ElementParamType(),
help="Except certain dependencies from fetching")
@click.option('--deps', '-d', default='plan',
type=click.Choice(['none', 'plan', 'all']),
@@ -258,7 +292,7 @@ def build(app, elements, all_, track_, track_save, track_all, track_except, trac
@click.option('--track-cross-junctions', '-J', default=False, is_flag=True,
help="Allow tracking to cross junction boundaries")
@click.argument('elements', nargs=-1,
- type=click.Path(dir_okay=False, readable=True))
+ type=ElementParamType())
@click.pass_obj
def fetch(app, elements, deps, track_, except_, track_cross_junctions):
"""Fetch sources required to build the pipeline
@@ -299,7 +333,7 @@ def fetch(app, elements, deps, track_, except_, track_cross_junctions):
##################################################################
@cli.command(short_help="Track new source references")
@click.option('--except', 'except_', multiple=True,
- type=click.Path(dir_okay=False, readable=True),
+ type=ElementParamType(),
help="Except certain dependencies from tracking")
@click.option('--deps', '-d', default='none',
type=click.Choice(['none', 'all']),
@@ -307,7 +341,7 @@ def fetch(app, elements, deps, track_, except_, track_cross_junctions):
@click.option('--cross-junctions', '-J', default=False, is_flag=True,
help="Allow crossing junction boundaries")
@click.argument('elements', nargs=-1,
- type=click.Path(dir_okay=False, readable=True))
+ type=ElementParamType())
@click.pass_obj
def track(app, elements, deps, except_, cross_junctions):
"""Consults the specified tracking branches for new versions available
@@ -339,7 +373,7 @@ def track(app, elements, deps, except_, cross_junctions):
@click.option('--remote', '-r',
help="The URL of the remote cache (defaults to the first configured cache)")
@click.argument('elements', nargs=-1,
- type=click.Path(dir_okay=False, readable=True))
+ type=ElementParamType())
@click.pass_obj
def pull(app, elements, deps, remote):
"""Pull a built artifact from the configured remote artifact cache.
@@ -368,7 +402,7 @@ def pull(app, elements, deps, remote):
@click.option('--remote', '-r', default=None,
help="The URL of the remote cache (defaults to the first configured cache)")
@click.argument('elements', nargs=-1,
- type=click.Path(dir_okay=False, readable=True))
+ type=ElementParamType())
@click.pass_obj
def push(app, elements, deps, remote):
"""Push a built artifact to a remote artifact cache.
@@ -391,7 +425,7 @@ def push(app, elements, deps, remote):
##################################################################
@cli.command(short_help="Show elements in the pipeline")
@click.option('--except', 'except_', multiple=True,
- type=click.Path(dir_okay=False, readable=True),
+ type=ElementParamType(),
help="Except certain dependencies")
@click.option('--deps', '-d', default='all',
type=click.Choice(['none', 'plan', 'run', 'build', 'all']),
@@ -403,7 +437,7 @@ def push(app, elements, deps, remote):
type=click.STRING,
help='Format string for each element')
@click.argument('elements', nargs=-1,
- type=click.Path(dir_okay=False, readable=True))
+ type=ElementParamType())
@click.pass_obj
def show(app, elements, deps, except_, order, format_):
"""Show elements in the pipeline
@@ -482,7 +516,7 @@ def show(app, elements, deps, except_, order, format_):
@click.option('--isolate', is_flag=True, default=False,
help='Create an isolated build sandbox')
@click.argument('element',
- type=click.Path(dir_okay=False, readable=True))
+ type=ElementParamType())
@click.argument('command', type=click.STRING, nargs=-1)
@click.pass_obj
def shell(app, element, sysroot, mount, isolate, build_, command):
@@ -543,7 +577,7 @@ def shell(app, element, sysroot, mount, isolate, build_, command):
@click.option('--hardlinks', default=False, is_flag=True,
help="Checkout hardlinks instead of copies (handle with care)")
@click.argument('element',
- type=click.Path(dir_okay=False, readable=True))
+ type=ElementParamType())
@click.argument('directory', type=click.Path(file_okay=False))
@click.pass_obj
def checkout(app, element, directory, force, integrate, hardlinks):
@@ -577,7 +611,7 @@ def workspace():
@click.option('--track', 'track_', default=False, is_flag=True,
help="Track and fetch new source references before checking out the workspace")
@click.argument('element',
- type=click.Path(dir_okay=False, readable=True))
+ type=ElementParamType())
@click.argument('directory', type=click.Path(file_okay=False))
@click.pass_obj
def workspace_open(app, no_checkout, force, track_, element, directory):
@@ -609,7 +643,7 @@ def workspace_open(app, no_checkout, force, track_, element, directory):
@click.option('--all', '-a', 'all_', default=False, is_flag=True,
help="Close all open workspaces")
@click.argument('elements', nargs=-1,
- type=click.Path(dir_okay=False, readable=True))
+ type=ElementParamType())
@click.pass_obj
def workspace_close(app, remove_dir, all_, elements):
"""Close a workspace"""
@@ -655,7 +689,7 @@ def workspace_close(app, remove_dir, all_, elements):
@click.option('--all', '-a', 'all_', default=False, is_flag=True,
help="Reset all open workspaces")
@click.argument('elements', nargs=-1,
- type=click.Path(dir_okay=False, readable=True))
+ type=ElementParamType())
@click.pass_obj
def workspace_reset(app, soft, track_, all_, elements):
"""Reset a workspace to its original state"""
@@ -704,7 +738,7 @@ def workspace_list(app):
##################################################################
@cli.command(name="source-bundle", short_help="Produce a build bundle to be manually executed")
@click.option('--except', 'except_', multiple=True,
- type=click.Path(dir_okay=False, readable=True),
+ type=ElementParamType(),
help="Elements to except from the tarball")
@click.option('--compression', default='gz',
type=click.Choice(['none', 'gz', 'bz2', 'xz']),
@@ -716,7 +750,7 @@ def workspace_list(app):
@click.option('--directory', default=os.getcwd(),
help="The directory to write the tarball to")
@click.argument('element',
- type=click.Path(dir_okay=False, readable=True))
+ type=ElementParamType())
@click.pass_obj
def source_bundle(app, element, force, directory,
track_, compression, except_):