You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@buildstream.apache.org by ro...@apache.org on 2020/12/29 13:38:19 UTC

[buildstream] branch valentindavid/workspacedir_config created (now 2584b0b)

This is an automated email from the ASF dual-hosted git repository.

root pushed a change to branch valentindavid/workspacedir_config
in repository https://gitbox.apache.org/repos/asf/buildstream.git.


      at 2584b0b  doc/source/commands.rst: Fix reference to workspace_open

This branch includes the following new commits:

     new 9dd928d  Add 'workspacedir' configuration.
     new bd59867  buildstream/_frontend/app.py: Keep relative workspace relative in workspaces.yml.
     new d64a8ee  buildstream/data/userconfig.yaml: Make default workspace dir current directory instead of project directory.
     new 28d2203  buildstream/_frontend/cli.py: Add support for multiple element parameters to 'workspace open'
     new c10c065  tests/frontend/workspace.py: Fix PEP8
     new 50ee3ca  tests/frontend/workspace.py: Update to new behavior
     new 6536f56  buildstream/_frontend/cli.py: Fix PEP8
     new 53667de  tests/frontend/workspace.py: Remove a now useless cleanup.
     new 3b99205  tests/frontend/workspace.py: Fix compatibility with older Python
     new 639ba18  tests/frontend/workspace.py: Add test for 'workspace open --multiple'
     new 2584b0b  doc/source/commands.rst: Fix reference to workspace_open

The 11 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.



[buildstream] 04/11: buildstream/_frontend/cli.py: Add support for multiple element parameters to 'workspace open'

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

root pushed a commit to branch valentindavid/workspacedir_config
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 28d22030796fc7952ddef5c9701cab9147432d2d
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Tue May 1 15:46:37 2018 +0200

    buildstream/_frontend/cli.py: Add support for multiple element parameters to 'workspace open'
---
 buildstream/_frontend/cli.py     | 105 +++++++++++++++++++++++++++++----------
 tests/completions/completions.py |   2 +
 2 files changed, 82 insertions(+), 25 deletions(-)

diff --git a/buildstream/_frontend/cli.py b/buildstream/_frontend/cli.py
index 2b5483e..38bb4dc 100644
--- a/buildstream/_frontend/cli.py
+++ b/buildstream/_frontend/cli.py
@@ -585,39 +585,94 @@ def workspace():
 ##################################################################
 #                     Workspace Open Command                     #
 ##################################################################
-@workspace.command(name='open', short_help="Open a new workspace")
-@click.option('--no-checkout', default=False, is_flag=True,
-              help="Do not checkout the source, only link to the given directory")
-@click.option('--force', '-f', default=False, is_flag=True,
-              help="Overwrite files existing in checkout directory")
-@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))
-@click.argument('directory', type=click.Path(file_okay=False))
-@click.pass_obj
-def workspace_open(app, no_checkout, force, track_, element, directory):
+def workspace_open(app, no_checkout, force, track_, elements, directory):
     """Open a workspace for manual source modification"""
 
     with app.initialized():
 
-        if not os.path.isabs(directory):
-            directory = os.path.join(app.context.workspacedir, directory)
+        targets = app.stream.load_selection(elements)
+        for target in targets:
+            targetdir = directory
+            if not targetdir:
+                targetdir, element_ext = os.path.splitext(target.name)
+                if element_ext != '.bst':
+                    targetdir.append(element_ext)
+
+            if not os.path.isabs(targetdir):
+                targetdir = os.path.join(app.context.workspacedir, targetdir)
+
+            if os.path.exists(targetdir):
+
+                if not os.path.isdir(targetdir):
+                    click.echo("Checkout directory is not a directory: {}".format(targetdir), err=True)
+                    sys.exit(-1)
+
+                if not (no_checkout or force) and os.listdir(targetdir):
+                    click.echo("Checkout directory is not empty: {}".format(targetdir), err=True)
+                    sys.exit(-1)
+
+            app.stream.workspace_open(target.name, targetdir,
+                                      no_checkout=no_checkout,
+                                      track_first=track_,
+                                      force=force)
+
+
+def workspace_open_options(fun):
+    options = []
+    options.append(click.option('--no-checkout', default=False, is_flag=True,
+                                help="Do not checkout the source, only link to the given directory"))
+    options.append(click.option('--force', '-f', default=False, is_flag=True,
+                                help="Overwrite files existing in checkout directory"))
+    options.append(click.option('--track', 'track_', default=False, is_flag=True,
+                                help="Track and fetch new source references before checking out the workspace"))
+    for option in options:
+        fun = option(fun)
+    return fun
+
+
+@workspace.command(name='open', short_help="Open new workspaces")
+@workspace_open_options
+@click.option('--multiple', 'multiple', default=False, is_flag=True,
+              help="Behave has open-multiple command. Otherwise this command is the same as open-single")
+@click.argument('arguments', nargs=-1, type=click.UNPROCESSED)
+@click.pass_obj
+@click.pass_context
+def workspace_open_base(ctx, app, multiple,  arguments, **kwargs):
+    if multiple:
+        new_ctx = click.Context(workspace_open_multiple, parent=ctx)
+        workspace_open_multiple.parse_args(new_ctx, list(arguments))
+        new_ctx.forward(workspace_open_multiple, **kwargs)
+    else:
+        new_ctx = click.Context(workspace_open_single, parent=ctx)
+        workspace_open_single.parse_args(new_ctx, list(arguments))
+        new_ctx.forward(workspace_open_single, **kwargs)
 
-        if os.path.exists(directory):
 
-            if not os.path.isdir(directory):
-                click.echo("Checkout directory is not a directory: {}".format(directory), err=True)
-                sys.exit(-1)
+@workspace.command(name='open-single',
+                   short_help="Open a new workspace")
+@workspace_open_options
+@click.argument('element',
+                nargs=1,
+                required=True,
+                type=click.Path(dir_okay=False, readable=True))
+@click.argument('directory',
+                nargs=1,
+                required=False,
+                type=click.Path(file_okay=False))
+@click.pass_obj
+def workspace_open_single(app, no_checkout, force, track_, element, directory):
+    workspace_open(app, no_checkout, force, track_, (element,), directory)
 
-            if not (no_checkout or force) and os.listdir(directory):
-                click.echo("Checkout directory is not empty: {}".format(directory), err=True)
-                sys.exit(-1)
 
-        app.stream.workspace_open(element, directory,
-                                  no_checkout=no_checkout,
-                                  track_first=track_,
-                                  force=force)
+@workspace.command(name='open-multiple', short_help="Open new workspaces")
+@workspace_open_options
+@click.argument('elements',
+                nargs=-1,
+                required=True,
+                type=click.Path(dir_okay=False, readable=True))
+@click.pass_obj
+def workspace_open_multiple(app, no_checkout, force, track_, elements):
+    workspace_open(app, no_checkout, force, track_, elements, None)
 
 
 ##################################################################
diff --git a/tests/completions/completions.py b/tests/completions/completions.py
index d6d0fde..27e28c1 100644
--- a/tests/completions/completions.py
+++ b/tests/completions/completions.py
@@ -50,6 +50,8 @@ WORKSPACE_COMMANDS = [
     'close ',
     'list ',
     'open ',
+    'open-multiple ',
+    'open-single ',
     'reset '
 ]
 


[buildstream] 10/11: tests/frontend/workspace.py: Add test for 'workspace open --multiple'

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

root pushed a commit to branch valentindavid/workspacedir_config
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 639ba184b8c8dc48dec346f1fe74bda0852f3133
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Thu May 3 10:13:26 2018 +0200

    tests/frontend/workspace.py: Add test for 'workspace open --multiple'
---
 tests/frontend/workspace.py | 74 ++++++++++++++++++++++++++++++++++++---------
 1 file changed, 60 insertions(+), 14 deletions(-)

diff --git a/tests/frontend/workspace.py b/tests/frontend/workspace.py
index eedcf47..e90dd0c 100644
--- a/tests/frontend/workspace.py
+++ b/tests/frontend/workspace.py
@@ -18,20 +18,12 @@ DATA_DIR = os.path.join(
 )
 
 
-def open_workspace(cli, tmpdir, datafiles, kind, track, suffix='', workspacedir=None):
-    project = os.path.join(datafiles.dirname, datafiles.basename)
+def open_workspace_create_element(cli, project, tmpdir, kind, track, suffix):
     bin_files_path = os.path.join(project, 'files', 'bin-files')
     element_path = os.path.join(project, 'elements')
-    element_name = 'workspace-test-{}{}.bst'.format(kind, suffix)
-    if workspacedir is None:
-        workspace = os.path.join(str(tmpdir), 'workspace{}'.format(suffix))
-    else:
-        workspace = os.path.join(project, 'workspace{}'.format(suffix))
 
-    # Create our repo object of the given source type with
-    # the bin files, and then collect the initial ref.
-    #
-    repo = create_repo(kind, str(tmpdir))
+    element_name = 'workspace-test-{}{}.bst'.format(kind, suffix)
+    repo = create_repo(kind, os.path.join(str(tmpdir), 'repo-{}'.format(suffix)))
     ref = repo.create(bin_files_path)
     if track:
         ref = None
@@ -54,16 +46,60 @@ def open_workspace(cli, tmpdir, datafiles, kind, track, suffix='', workspacedir=
     else:
         assert state == 'fetch needed'
 
-    # Now open the workspace, this should have the effect of automatically
-    # tracking & fetching the source from the repo.
+    return element_name
+
+
+def open_workspace_run_client(cli, project, track, *params):
     args = ['workspace', 'open']
     if track:
         args.append('--track')
-    args.extend([element_name, workspace])
+
+    args.extend(params)
 
     result = cli.run(project=project, args=args)
     result.assert_success()
 
+
+def open_workspace_multiple(cli, tmpdir, datafiles, kind, track, workspacedir, suffixes=['-alpha', '-beta']):
+    project = os.path.join(datafiles.dirname, datafiles.basename)
+
+    element_names = []
+    for suffix in suffixes:
+        element_names.append(open_workspace_create_element(cli, project, tmpdir, kind, track, suffix))
+
+    # Now open the workspace, this should have the effect of automatically
+    # tracking & fetching the source from the repo.
+    open_workspace_run_client(cli, project, track, "--multiple", *element_names)
+
+    # Assert that we are now buildable because the source is
+    # now cached.
+    for element_name in element_names:
+        assert cli.get_element_state(project, element_name) == 'buildable'
+
+        element_basename, _ = os.path.splitext(element_name)
+        workspace = os.path.join(workspacedir, element_basename)
+        filename = os.path.join(workspace, 'usr', 'bin', 'hello')
+
+        # Check that the executable hello file is found in the workspace
+        assert os.path.exists(filename)
+
+    return (element_names, project)
+
+
+def open_workspace(cli, tmpdir, datafiles, kind, track, suffix='', workspacedir=None):
+    project = os.path.join(datafiles.dirname, datafiles.basename)
+
+    element_name = open_workspace_create_element(cli, project, tmpdir, kind, track, suffix)
+
+    if workspacedir is None:
+        workspace = os.path.join(str(tmpdir), 'workspace{}'.format(suffix))
+    else:
+        workspace = os.path.join(project, 'workspace{}'.format(suffix))
+
+    # Now open the workspace, this should have the effect of automatically
+    # tracking & fetching the source from the repo.
+    open_workspace_run_client(cli, project, track, element_name, workspace)
+
     # Assert that we are now buildable because the source is
     # now cached.
     assert cli.get_element_state(project, element_name) == 'buildable'
@@ -131,6 +167,16 @@ def test_open_force(cli, tmpdir, datafiles, kind):
 
 @pytest.mark.datafiles(DATA_DIR)
 @pytest.mark.parametrize("kind", repo_kinds)
+def test_open_multiple(cli, tmpdir, datafiles, kind):
+    workspacedir = os.path.join(str(tmpdir), 'workspaces')
+    user_config = {'workspacedir': workspacedir}
+    cli.configure(user_config)
+    open_workspace_multiple(cli, tmpdir, datafiles, kind, False,
+                            workspacedir)
+
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("kind", repo_kinds)
 def test_open_workspacedir_absolute(cli, tmpdir, datafiles, kind):
     workspacedir = os.path.join(str(tmpdir), 'workspaces')
     user_config = {'workspacedir': workspacedir}


[buildstream] 03/11: buildstream/data/userconfig.yaml: Make default workspace dir current directory instead of project directory.

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

root pushed a commit to branch valentindavid/workspacedir_config
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit d64a8ee234fcef742af39e73b85cc6323f5284ab
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Tue May 1 18:03:00 2018 +0200

    buildstream/data/userconfig.yaml: Make default workspace dir current directory instead of project directory.
---
 buildstream/data/userconfig.yaml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/buildstream/data/userconfig.yaml b/buildstream/data/userconfig.yaml
index 25b2541..3faf0b9 100644
--- a/buildstream/data/userconfig.yaml
+++ b/buildstream/data/userconfig.yaml
@@ -23,7 +23,7 @@ artifactdir: ${XDG_CACHE_HOME}/buildstream/artifacts
 logdir: ${XDG_CACHE_HOME}/buildstream/logs
 
 # Default root location for workspaces
-workspacedir: .
+workspacedir: ${PWD}
 
 #
 #    Scheduler


[buildstream] 09/11: tests/frontend/workspace.py: Fix compatibility with older Python

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

root pushed a commit to branch valentindavid/workspacedir_config
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 3b992050354e4e97c6d8860e24fe2870f801a813
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Tue May 1 20:06:47 2018 +0200

    tests/frontend/workspace.py: Fix compatibility with older Python
---
 tests/frontend/workspace.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/frontend/workspace.py b/tests/frontend/workspace.py
index 0f30c9d..eedcf47 100644
--- a/tests/frontend/workspace.py
+++ b/tests/frontend/workspace.py
@@ -132,7 +132,7 @@ def test_open_force(cli, tmpdir, datafiles, kind):
 @pytest.mark.datafiles(DATA_DIR)
 @pytest.mark.parametrize("kind", repo_kinds)
 def test_open_workspacedir_absolute(cli, tmpdir, datafiles, kind):
-    workspacedir = os.path.join(tmpdir, 'workspaces')
+    workspacedir = os.path.join(str(tmpdir), 'workspaces')
     user_config = {'workspacedir': workspacedir}
     cli.configure(user_config)
     open_workspace(cli, tmpdir, datafiles, kind, False,


[buildstream] 11/11: doc/source/commands.rst: Fix reference to workspace_open

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

root pushed a commit to branch valentindavid/workspacedir_config
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 2584b0bf8318d1ca9b39c73a218defe68cddcd66
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Fri Jun 8 13:42:58 2018 +0200

    doc/source/commands.rst: Fix reference to workspace_open
---
 doc/source/commands.rst | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/doc/source/commands.rst b/doc/source/commands.rst
index 18affc6..6366cd7 100644
--- a/doc/source/commands.rst
+++ b/doc/source/commands.rst
@@ -102,7 +102,7 @@ project's main directory.
 
 .. _invoking_workspace_open:
 
-.. click:: buildstream._frontend.cli:workspace_open
+.. click:: buildstream._frontend.cli:workspace_open_base
    :prog: bst workspace open
 
 ----


[buildstream] 05/11: tests/frontend/workspace.py: Fix PEP8

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

root pushed a commit to branch valentindavid/workspacedir_config
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit c10c065a77623202902351586f89d3655680b2d9
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Tue May 1 17:59:22 2018 +0200

    tests/frontend/workspace.py: Fix PEP8
---
 tests/frontend/workspace.py | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/tests/frontend/workspace.py b/tests/frontend/workspace.py
index 9f1a6c0..c2086ff 100644
--- a/tests/frontend/workspace.py
+++ b/tests/frontend/workspace.py
@@ -128,6 +128,7 @@ def test_open_force(cli, tmpdir, datafiles, kind):
     ])
     result.assert_success()
 
+
 @pytest.mark.datafiles(DATA_DIR)
 @pytest.mark.parametrize("kind", repo_kinds)
 def test_open_workspacedir_absolute(cli, tmpdir, datafiles, kind):
@@ -137,6 +138,7 @@ def test_open_workspacedir_absolute(cli, tmpdir, datafiles, kind):
     open_workspace(cli, tmpdir, datafiles, kind, False,
                    workspacedir=workspacedir)
 
+
 @pytest.mark.datafiles(DATA_DIR)
 @pytest.mark.parametrize("kind", repo_kinds)
 def test_open_workspacedir_relative(cli, tmpdir, datafiles, kind):
@@ -148,6 +150,7 @@ def test_open_workspacedir_relative(cli, tmpdir, datafiles, kind):
     open_workspace(cli, tmpdir, datafiles, kind, False,
                    workspacedir=workspacedir)
 
+
 @pytest.mark.datafiles(DATA_DIR)
 @pytest.mark.parametrize("kind", repo_kinds)
 def test_close(cli, tmpdir, datafiles, kind):


[buildstream] 06/11: tests/frontend/workspace.py: Update to new behavior

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

root pushed a commit to branch valentindavid/workspacedir_config
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 50ee3ca172430e5bc78ea3601aad01caa495d185
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Tue May 1 19:34:22 2018 +0200

    tests/frontend/workspace.py: Update to new behavior
---
 tests/frontend/workspace.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/tests/frontend/workspace.py b/tests/frontend/workspace.py
index c2086ff..e168a61 100644
--- a/tests/frontend/workspace.py
+++ b/tests/frontend/workspace.py
@@ -26,7 +26,7 @@ def open_workspace(cli, tmpdir, datafiles, kind, track, suffix='', workspacedir=
     if workspacedir is None:
         workspace = os.path.join(str(tmpdir), 'workspace{}'.format(suffix))
     else:
-        workspace = os.path.join('workspace{}'.format(suffix))
+        workspace = os.path.join(project, 'workspace{}'.format(suffix))
 
     # Create our repo object of the given source type with
     # the bin files, and then collect the initial ref.


[buildstream] 02/11: buildstream/_frontend/app.py: Keep relative workspace relative in workspaces.yml.

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

root pushed a commit to branch valentindavid/workspacedir_config
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit bd59867df37e32fe8682d5445fb3e63fa23508f3
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Tue Apr 24 17:58:06 2018 +0200

    buildstream/_frontend/app.py: Keep relative workspace relative in workspaces.yml.
---
 buildstream/_stream.py | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/buildstream/_stream.py b/buildstream/_stream.py
index f2806b4..e294b09 100644
--- a/buildstream/_stream.py
+++ b/buildstream/_stream.py
@@ -424,7 +424,6 @@ class Stream():
 
         elements, track_elements = self._load((target,), track_targets)
         target = elements[0]
-        workdir = os.path.abspath(directory)
 
         if not list(target.sources()):
             build_depends = [x.name for x in target.dependencies(Scope.BUILD, recurse=False)]
@@ -460,7 +459,7 @@ class Stream():
         except OSError as e:
             raise StreamError("Failed to create workspace directory: {}".format(e)) from e
 
-        self._project.workspaces.create_workspace(target.name, workdir)
+        self._project.workspaces.create_workspace(target.name, directory)
 
         if not no_checkout:
             with target.timed_activity("Staging sources to {}".format(directory)):


[buildstream] 08/11: tests/frontend/workspace.py: Remove a now useless cleanup.

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

root pushed a commit to branch valentindavid/workspacedir_config
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 53667de50bb0d72eafd92d6999595c29b8d3cf83
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Tue May 1 20:05:17 2018 +0200

    tests/frontend/workspace.py: Remove a now useless cleanup.
---
 tests/frontend/workspace.py | 2 --
 1 file changed, 2 deletions(-)

diff --git a/tests/frontend/workspace.py b/tests/frontend/workspace.py
index e168a61..0f30c9d 100644
--- a/tests/frontend/workspace.py
+++ b/tests/frontend/workspace.py
@@ -143,8 +143,6 @@ def test_open_workspacedir_absolute(cli, tmpdir, datafiles, kind):
 @pytest.mark.parametrize("kind", repo_kinds)
 def test_open_workspacedir_relative(cli, tmpdir, datafiles, kind):
     workspacedir = os.path.join('workspaces')
-    if os.path.isdir(workspacedir):
-        shutil.rmtree(workspacedir)
     user_config = {'workspacedir': workspacedir}
     cli.configure(user_config)
     open_workspace(cli, tmpdir, datafiles, kind, False,


[buildstream] 07/11: buildstream/_frontend/cli.py: Fix PEP8

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

root pushed a commit to branch valentindavid/workspacedir_config
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 6536f561c7aef3443524d7634501851efd664ed2
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Tue May 1 20:04:50 2018 +0200

    buildstream/_frontend/cli.py: Fix PEP8
---
 buildstream/_frontend/cli.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/buildstream/_frontend/cli.py b/buildstream/_frontend/cli.py
index 38bb4dc..31f4187 100644
--- a/buildstream/_frontend/cli.py
+++ b/buildstream/_frontend/cli.py
@@ -637,7 +637,7 @@ def workspace_open_options(fun):
 @click.argument('arguments', nargs=-1, type=click.UNPROCESSED)
 @click.pass_obj
 @click.pass_context
-def workspace_open_base(ctx, app, multiple,  arguments, **kwargs):
+def workspace_open_base(ctx, app, multiple, arguments, **kwargs):
     if multiple:
         new_ctx = click.Context(workspace_open_multiple, parent=ctx)
         workspace_open_multiple.parse_args(new_ctx, list(arguments))


[buildstream] 01/11: Add 'workspacedir' configuration.

Posted by ro...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

root pushed a commit to branch valentindavid/workspacedir_config
in repository https://gitbox.apache.org/repos/asf/buildstream.git

commit 9dd928dc7ad033b475ce6a2afd66aef71d5ea8ac
Author: Valentin David <va...@codethink.co.uk>
AuthorDate: Wed Apr 18 14:27:35 2018 +0200

    Add 'workspacedir' configuration.
    
    'workspacedir' is either absolute or relative from project directory.
    
    Fixes #229.
---
 buildstream/_context.py          |  6 +++++-
 buildstream/_frontend/cli.py     | 20 ++++++++++++--------
 buildstream/data/userconfig.yaml |  3 +++
 tests/frontend/workspace.py      | 29 +++++++++++++++++++++++++++--
 4 files changed, 47 insertions(+), 11 deletions(-)

diff --git a/buildstream/_context.py b/buildstream/_context.py
index c0d49b2..b578d44 100644
--- a/buildstream/_context.py
+++ b/buildstream/_context.py
@@ -59,6 +59,9 @@ class Context():
         # The local binary artifact cache directory
         self.artifactdir = None
 
+        # Default root location for workspaces
+        self.workspacedir = None
+
         # The locations from which to push and pull prebuilt artifacts
         self.artifact_cache_specs = []
 
@@ -152,9 +155,10 @@ class Context():
         _yaml.node_validate(defaults, [
             'sourcedir', 'builddir', 'artifactdir', 'logdir',
             'scheduler', 'artifacts', 'logging', 'projects',
+            'workspacedir',
         ])
 
-        for directory in ['sourcedir', 'builddir', 'artifactdir', 'logdir']:
+        for directory in ['sourcedir', 'builddir', 'artifactdir', 'logdir', 'workspacedir']:
             # Allow the ~ tilde expansion and any environment variables in
             # path specification in the config files.
             #
diff --git a/buildstream/_frontend/cli.py b/buildstream/_frontend/cli.py
index 5ed967d..2b5483e 100644
--- a/buildstream/_frontend/cli.py
+++ b/buildstream/_frontend/cli.py
@@ -599,17 +599,21 @@ def workspace():
 def workspace_open(app, no_checkout, force, track_, element, directory):
     """Open a workspace for manual source modification"""
 
-    if os.path.exists(directory):
+    with app.initialized():
 
-        if not os.path.isdir(directory):
-            click.echo("Checkout directory is not a directory: {}".format(directory), err=True)
-            sys.exit(-1)
+        if not os.path.isabs(directory):
+            directory = os.path.join(app.context.workspacedir, directory)
 
-        if not (no_checkout or force) and os.listdir(directory):
-            click.echo("Checkout directory is not empty: {}".format(directory), err=True)
-            sys.exit(-1)
+        if os.path.exists(directory):
+
+            if not os.path.isdir(directory):
+                click.echo("Checkout directory is not a directory: {}".format(directory), err=True)
+                sys.exit(-1)
+
+            if not (no_checkout or force) and os.listdir(directory):
+                click.echo("Checkout directory is not empty: {}".format(directory), err=True)
+                sys.exit(-1)
 
-    with app.initialized():
         app.stream.workspace_open(element, directory,
                                   no_checkout=no_checkout,
                                   track_first=track_,
diff --git a/buildstream/data/userconfig.yaml b/buildstream/data/userconfig.yaml
index 6bb54ff..25b2541 100644
--- a/buildstream/data/userconfig.yaml
+++ b/buildstream/data/userconfig.yaml
@@ -22,6 +22,9 @@ artifactdir: ${XDG_CACHE_HOME}/buildstream/artifacts
 # Location to store build logs
 logdir: ${XDG_CACHE_HOME}/buildstream/logs
 
+# Default root location for workspaces
+workspacedir: .
+
 #
 #    Scheduler
 #
diff --git a/tests/frontend/workspace.py b/tests/frontend/workspace.py
index 90b5061..9f1a6c0 100644
--- a/tests/frontend/workspace.py
+++ b/tests/frontend/workspace.py
@@ -18,12 +18,15 @@ DATA_DIR = os.path.join(
 )
 
 
-def open_workspace(cli, tmpdir, datafiles, kind, track, suffix=''):
+def open_workspace(cli, tmpdir, datafiles, kind, track, suffix='', workspacedir=None):
     project = os.path.join(datafiles.dirname, datafiles.basename)
     bin_files_path = os.path.join(project, 'files', 'bin-files')
     element_path = os.path.join(project, 'elements')
     element_name = 'workspace-test-{}{}.bst'.format(kind, suffix)
-    workspace = os.path.join(str(tmpdir), 'workspace{}'.format(suffix))
+    if workspacedir is None:
+        workspace = os.path.join(str(tmpdir), 'workspace{}'.format(suffix))
+    else:
+        workspace = os.path.join('workspace{}'.format(suffix))
 
     # Create our repo object of the given source type with
     # the bin files, and then collect the initial ref.
@@ -67,6 +70,9 @@ def open_workspace(cli, tmpdir, datafiles, kind, track, suffix=''):
 
     # Check that the executable hello file is found in the workspace
     filename = os.path.join(workspace, 'usr', 'bin', 'hello')
+    if workspacedir is not None:
+        filename = os.path.join(workspacedir, filename)
+
     assert os.path.exists(filename)
 
     return (element_name, project, workspace)
@@ -122,6 +128,25 @@ def test_open_force(cli, tmpdir, datafiles, kind):
     ])
     result.assert_success()
 
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("kind", repo_kinds)
+def test_open_workspacedir_absolute(cli, tmpdir, datafiles, kind):
+    workspacedir = os.path.join(tmpdir, 'workspaces')
+    user_config = {'workspacedir': workspacedir}
+    cli.configure(user_config)
+    open_workspace(cli, tmpdir, datafiles, kind, False,
+                   workspacedir=workspacedir)
+
+@pytest.mark.datafiles(DATA_DIR)
+@pytest.mark.parametrize("kind", repo_kinds)
+def test_open_workspacedir_relative(cli, tmpdir, datafiles, kind):
+    workspacedir = os.path.join('workspaces')
+    if os.path.isdir(workspacedir):
+        shutil.rmtree(workspacedir)
+    user_config = {'workspacedir': workspacedir}
+    cli.configure(user_config)
+    open_workspace(cli, tmpdir, datafiles, kind, False,
+                   workspacedir=workspacedir)
 
 @pytest.mark.datafiles(DATA_DIR)
 @pytest.mark.parametrize("kind", repo_kinds)