From a63e9efb958f37e557154df55f0fcde1e8589793 Mon Sep 17 00:00:00 2001 From: Anish Athalye Date: Sat, 7 Dec 2024 17:29:45 -0500 Subject: [PATCH] Fix issue with duplicate execution of plugins --- dotbot/cli.py | 5 +++++ tests/dotbot_plugin_issue_357.py | 15 +++++++++++++++ tests/test_cli.py | 13 +++++++++++++ 3 files changed, 33 insertions(+) create mode 100644 tests/dotbot_plugin_issue_357.py diff --git a/dotbot/cli.py b/dotbot/cli.py index f4210038..3a14d2d2 100644 --- a/dotbot/cli.py +++ b/dotbot/cli.py @@ -131,6 +131,11 @@ def main(): for plugin_path in plugin_paths: abspath = os.path.abspath(plugin_path) plugins.extend(module.load(abspath)) + # ensure plugins are unique to avoid duplicate execution, which + # can happen if, for example, a third-party plugin loads a + # built-in plugin, which will cause it to appear in the list + # returned by module.load above + plugins = set(plugins) if not options.config_file: log.error("No configuration file specified") exit(1) diff --git a/tests/dotbot_plugin_issue_357.py b/tests/dotbot_plugin_issue_357.py new file mode 100644 index 00000000..8aae8af4 --- /dev/null +++ b/tests/dotbot_plugin_issue_357.py @@ -0,0 +1,15 @@ +import os +from dotbot.plugin import Plugin +from dotbot.plugins import Clean, Create, Link, Shell + +# https://github.com/anishathalye/dotbot/issues/357 +# if we import from dotbot.plugins, the built-in plugins get executed multiple times + +class NoopPlugin(Plugin): + _directive = 'noop' + + def can_handle(self, directive): + return directive == self._directive + + def handle(self, directive, data): + return True diff --git a/tests/test_cli.py b/tests/test_cli.py index cc270b4b..d2edb56e 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -159,6 +159,19 @@ def test_plugin_loading_directory(home, dotfiles, run_dotbot): assert file.read() == "directory plugin loading works" +def test_issue_357(capfd, home, dotfiles, run_dotbot): + """Verify that built-in plugins are only executed once, when + using a plugin that imports from dotbot.plugins.""" + plugin_file = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "dotbot_plugin_issue_357.py" + ) + dotfiles.write_config([{"shell": [{"command": "echo apple", "stdout": True}]}]) + + run_dotbot("--plugin", plugin_file) + + assert len([line for line in capfd.readouterr().out.splitlines() if line.strip() == "apple"]) == 1 + + def test_disable_builtin_plugins(home, dotfiles, run_dotbot): """Verify that builtin plugins can be disabled."""