From b90b1f8577ab0e5afd9dc1704537c3da82218629 Mon Sep 17 00:00:00 2001 From: Leonardo Rochael Almeida Date: Fri, 10 Feb 2017 19:14:03 -0200 Subject: [PATCH 1/6] Actually parse booleans with bool_opt_get --- anybox/recipe/odoo/base.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/anybox/recipe/odoo/base.py b/anybox/recipe/odoo/base.py index cb75a2e5..7c4e155b 100644 --- a/anybox/recipe/odoo/base.py +++ b/anybox/recipe/odoo/base.py @@ -185,12 +185,10 @@ def __init__(self, buildout, name, options): # GR: would prefer lower() but doing as in 'zc.recipe.egg' # (later) the standard way for all booleans is to use # options.query_bool() or get_bool(), but it doesn't lower() at all - self.offline = self.b_options['offline'] == 'true' - self.clean = options.get('clean') == 'true' - clear_locks = options.get('vcs-clear-locks', '').lower() - self.vcs_clear_locks = clear_locks == 'true' - clear_retry = options.get('vcs-clear-retry', '').lower() - self.clear_retry = clear_retry == 'true' + self.offline = self.bool_opt_get('offline', is_global=True) + self.clean = self.bool_opt_get('clean') + self.vcs_clear_locks = self.bool_opt_get('vcs-clear-locks') + self.clear_retry = self.bool_opt_get('vcs-clear-retry') if self.bool_opt_get(WITH_ODOO_REQUIREMENTS_FILE_OPTION): logger.debug("%s option: adding 'pip' to the recipe requirements", From 9d277f63c972c3a8fe7ab60e81d725d305b35287 Mon Sep 17 00:00:00 2001 From: Leonardo Rochael Almeida Date: Fri, 10 Feb 2017 19:49:46 -0200 Subject: [PATCH 2/6] Option for allowing checkouts to be skipped --- anybox/recipe/odoo/base.py | 1 + anybox/recipe/odoo/vcs/base.py | 7 +++++++ anybox/recipe/odoo/vcs/tests/test_base.py | 21 +++++++++++++++++++++ 3 files changed, 29 insertions(+) diff --git a/anybox/recipe/odoo/base.py b/anybox/recipe/odoo/base.py index 7c4e155b..da9f6836 100644 --- a/anybox/recipe/odoo/base.py +++ b/anybox/recipe/odoo/base.py @@ -846,6 +846,7 @@ def retrieve_addons(self): loc_type, loc_spec, addons_options = source_spec local_dir = self.make_absolute(local_dir) options = dict(offline=self.offline, + skip_checkout=self.bool_opt_get('skip-checkout'), clear_locks=self.vcs_clear_locks, clean=self.clean) if loc_type == 'git': diff --git a/anybox/recipe/odoo/vcs/base.py b/anybox/recipe/odoo/vcs/base.py index 0d172539..692dcbdc 100644 --- a/anybox/recipe/odoo/vcs/base.py +++ b/anybox/recipe/odoo/vcs/base.py @@ -1,4 +1,5 @@ import os +import os.path import shutil import subprocess import logging @@ -105,6 +106,12 @@ def revert(self, revision): def __call__(self, revision): """Create if needed from remote source, and put it at wanted revision. """ + if (self.options.get('skip_checkout') and + os.path.exists(self.target_dir)): + logger.info("Directory exists and skip-checkout is active. Skipping: %s", + self.target_dir) + return self + if self.options.get('clean'): self.clean() diff --git a/anybox/recipe/odoo/vcs/tests/test_base.py b/anybox/recipe/odoo/vcs/tests/test_base.py index b8385d76..bd17ec77 100644 --- a/anybox/recipe/odoo/vcs/tests/test_base.py +++ b/anybox/recipe/odoo/vcs/tests/test_base.py @@ -4,6 +4,7 @@ """ import os +import os.path import subprocess from zc.buildout import UserError @@ -36,6 +37,26 @@ def test_str(self): self.assertEqual(str(repo), "BaseRepo at '/some/path' " "(remote='http://some/url')") + def test_skip_checkout(self): + existing_dir = self.dst_dir + non_existing_dir = os.path.join(existing_dir + 'foo') + + # Repos should try checkout when not called with skip_checkout + self.assertRaises( + NotImplementedError, BaseRepo(existing_dir, 'http://some/url') + ) + # Specially when the target doesn't exist + self.assertRaises( + NotImplementedError, BaseRepo(non_existing_dir, 'http://some/url') + ) + # But also when called with skip_checkout and the target doesn't exist + self.assertRaises( + NotImplementedError, + BaseRepo(non_existing_dir, 'http://some/url', skip_checkout=True) + ) + # But not when it exists + BaseRepo(existing_dir, 'http://some/url', skip_checkout=True) + def test_unknown(self): self.assertRaises(UserError, get_update, 'unknown', '', '', 'default') From f43b67fca52773b45937caabed2e75b0944ae7f9 Mon Sep 17 00:00:00 2001 From: Leonardo Rochael Almeida Date: Mon, 13 Feb 2017 13:12:49 -0200 Subject: [PATCH 3/6] fixup! Actually parse booleans with bool_opt_get --- anybox/recipe/odoo/base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/anybox/recipe/odoo/base.py b/anybox/recipe/odoo/base.py index da9f6836..864c5b90 100644 --- a/anybox/recipe/odoo/base.py +++ b/anybox/recipe/odoo/base.py @@ -174,7 +174,8 @@ def bool_opt_get(self, name, is_global=False): taken care of by this recipe instance. """ options = self.b_options if is_global else self.options - return options.get(name, '').lower() == 'true' + value = options.get(name, False) + return value.lower() == 'true' if isinstance(value, str) else value def __init__(self, buildout, name, options): self.requirements = list(self.requirements) From c0a1f8559ba902bf9ffa87f75664d2bc56aa3b0f Mon Sep 17 00:00:00 2001 From: Leonardo Rochael Almeida Date: Mon, 13 Feb 2017 13:14:02 -0200 Subject: [PATCH 4/6] fixup! Option for allowing checkouts to be skipped Fix tests and flake8 --- anybox/recipe/odoo/tests/test_server.py | 30 +++++++++++++---------- anybox/recipe/odoo/vcs/base.py | 6 +++-- anybox/recipe/odoo/vcs/tests/test_base.py | 14 ++++++++--- 3 files changed, 31 insertions(+), 19 deletions(-) diff --git a/anybox/recipe/odoo/tests/test_server.py b/anybox/recipe/odoo/tests/test_server.py index 83fd8012..28158daf 100644 --- a/anybox/recipe/odoo/tests/test_server.py +++ b/anybox/recipe/odoo/tests/test_server.py @@ -74,7 +74,8 @@ def test_retrieve_addons_vcs(self): self.assertEquals( get_vcs_log(), [ (addons_dir, 'http://trunk.example', 'rev', - dict(offline=False, clear_locks=False, clean=False) + dict(offline=False, clear_locks=False, clean=False, + skip_checkout=False,) )]) self.assertEquals(paths, [addons_dir]) @@ -90,12 +91,13 @@ def test_retrieve_addons_vcs_2(self): self.recipe.retrieve_addons() paths = self.recipe.addons_paths + options = dict( + offline=False, clear_locks=False, clean=False, skip_checkout=False, + ) self.assertEquals( get_vcs_log(), [ - (addons_dir, 'http://trunk.example', 'rev', - dict(offline=False, clear_locks=False, clean=False)), - (other_dir, 'http://other.example', '76', - dict(offline=False, clear_locks=False, clean=False)), + (addons_dir, 'http://trunk.example', 'rev', options), + (other_dir, 'http://other.example', '76', options), ]) self.assertEquals(paths, [addons_dir, other_dir]) @@ -129,7 +131,8 @@ def test_retrieve_addons_subdir(self): self.assertEquals(get_vcs_log(), [ (web_dir, 'lp:openerp-web', 'last:1', dict(offline=False, clear_locks=False, clean=False, - subdir="addons", bzrinit="branch")) + subdir="addons", bzrinit="branch", + skip_checkout=False)) ]) self.assertEquals(paths, [web_addons_dir]) @@ -145,13 +148,13 @@ def test_retrieve_addons_standalone_grouped(self): self.recipe.retrieve_addons() paths = self.recipe.addons_paths + options = dict( + offline=False, clear_locks=False, clean=False, + skip_checkout=False, group="grouped", + ) self.assertEquals(get_vcs_log(), [ - (addons1_dir, 'lp:my-addons1', 'last:1', - dict(offline=False, clear_locks=False, clean=False, - group="grouped")), - (addons2_dir, 'lp:my-addons2', 'last:1', - dict(offline=False, clear_locks=False, clean=False, - group="grouped")) + (addons1_dir, 'lp:my-addons1', 'last:1', options), + (addons2_dir, 'lp:my-addons2', 'last:1', options), ]) self.assertEquals(paths, [group_dir]) @@ -178,7 +181,8 @@ def test_retrieve_addons_clear_locks(self): self.recipe.retrieve_addons() self.assertEquals(get_vcs_log(), [ (addons_dir, 'lp:my-addons', '-1', - dict(offline=False, clear_locks=True, clean=False)) + dict(offline=False, clear_locks=True, clean=False, + skip_checkout=False,)) ]) def test_merge_requirements(self): diff --git a/anybox/recipe/odoo/vcs/base.py b/anybox/recipe/odoo/vcs/base.py index 692dcbdc..ba092ca0 100644 --- a/anybox/recipe/odoo/vcs/base.py +++ b/anybox/recipe/odoo/vcs/base.py @@ -108,8 +108,10 @@ def __call__(self, revision): """ if (self.options.get('skip_checkout') and os.path.exists(self.target_dir)): - logger.info("Directory exists and skip-checkout is active. Skipping: %s", - self.target_dir) + logger.info( + "Directory exists and skip-checkout is active. Skipping: %s", + self.target_dir, + ) return self if self.options.get('clean'): diff --git a/anybox/recipe/odoo/vcs/tests/test_base.py b/anybox/recipe/odoo/vcs/tests/test_base.py index bd17ec77..83791f3a 100644 --- a/anybox/recipe/odoo/vcs/tests/test_base.py +++ b/anybox/recipe/odoo/vcs/tests/test_base.py @@ -42,20 +42,26 @@ def test_skip_checkout(self): non_existing_dir = os.path.join(existing_dir + 'foo') # Repos should try checkout when not called with skip_checkout + revision = "1.0" self.assertRaises( - NotImplementedError, BaseRepo(existing_dir, 'http://some/url') + NotImplementedError, + BaseRepo(existing_dir, 'http://some/url'), + revision, ) # Specially when the target doesn't exist self.assertRaises( - NotImplementedError, BaseRepo(non_existing_dir, 'http://some/url') + NotImplementedError, + BaseRepo(non_existing_dir, 'http://some/url'), + revision, ) # But also when called with skip_checkout and the target doesn't exist self.assertRaises( NotImplementedError, - BaseRepo(non_existing_dir, 'http://some/url', skip_checkout=True) + BaseRepo(non_existing_dir, 'http://some/url', skip_checkout=True), + revision, ) # But not when it exists - BaseRepo(existing_dir, 'http://some/url', skip_checkout=True) + BaseRepo(existing_dir, 'http://some/url', skip_checkout=True)(revision) def test_unknown(self): self.assertRaises(UserError, From 78f8cfb156d486fea65787e67b36357e653ba195 Mon Sep 17 00:00:00 2001 From: Leonardo Rochael Almeida Date: Mon, 13 Feb 2017 13:17:04 -0200 Subject: [PATCH 5/6] Documentation for `skip-checkout` option --- doc/configuration.rst | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/doc/configuration.rst b/doc/configuration.rst index d6657104..bb6d4c49 100644 --- a/doc/configuration.rst +++ b/doc/configuration.rst @@ -370,6 +370,29 @@ Currently only merges on bzr and git repositories are supported .. _eggs: +skip-checkout +------------- +This option causes the checkout of each repository specified under +:ref:`addons` or :ref:`version` to be skipped if it already exists on the +filesystem. + +It's useful during development when you already have a working buildout with +many addons and would like to skip the part where each addon is checked out +again. + +For examples, if you want to: + +* just rebuild ``odoo.cfg`` with newer settings. + +* add another python package in ``eggs =`` + +* temporarily work on an addon in a branch that is different than the one + specified in the ``addons`` setting but wanting to re-run buildout for one of the above reasons. + +This is mostly to be used from the command line, like:: + + bin/buildout odoo:skip-checkout=true + eggs ---- This option behaves like the identically named one of the most common From 60c1b6e549224b5ca6694618eb209bde71561a1b Mon Sep 17 00:00:00 2001 From: Leonardo Rochael Almeida Date: Tue, 14 Feb 2017 19:16:59 -0200 Subject: [PATCH 6/6] fixup! Option for allowing checkouts to be skipped Allow the main server part to be skipped as well. --- anybox/recipe/odoo/base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/anybox/recipe/odoo/base.py b/anybox/recipe/odoo/base.py index 864c5b90..d9912e18 100644 --- a/anybox/recipe/odoo/base.py +++ b/anybox/recipe/odoo/base.py @@ -1055,7 +1055,8 @@ def retrieve_main_software(self): if type_spec == 'git': options['depth'] = options.pop('git-depth', None) - options.update(source[2]) + options.update(source[2], + skip_checkout=self.bool_opt_get('skip-checkout')) if self.clean: options['clean'] = True vcs.get_update(type_spec, self.openerp_dir, url, rev,