diff --git a/bench/app.py b/bench/app.py index 0ba81931..1b62a92b 100755 --- a/bench/app.py +++ b/bench/app.py @@ -10,6 +10,8 @@ import json import re import subprocess import bench +import sys +import shutil logging.basicConfig(level="DEBUG") logger = logging.getLogger(__name__) @@ -101,6 +103,32 @@ def install_app(app, bench_path='.', verbose=False): find_links=find_links)) add_to_appstxt(app, bench_path=bench_path) + +def remove_app(app, bench_path='.'): + if not app in get_apps(): + print "No app named {0}".format(app) + sys.exit(1) + + app_path = os.path.join(bench_path, 'apps', app) + site_path = os.path.join(bench_path, 'sites') + pip = os.path.join(bench_path, 'env', 'bin', 'pip') + + for site in os.listdir(site_path): + req_file = os.path.join(site_path, site, 'site_config.json') + if os.path.exists(req_file): + out = subprocess.check_output(["bench", "--site", site, "list-apps"], cwd=bench_path) + if re.search(r'\b' + app + r'\b', out): + print "Cannot remove, app is installed on site: {0}".format(site) + sys.exit(1) + + exec_cmd(["{0} uninstall -y {1}".format(pip, app_path)], cwd=bench_path) + remove_from_appstxt(app, bench_path) + shutil.rmtree(app_path) + run_frappe_cmd("build", cwd=bench_path) + if get_config(bench_path).get('restart_supervisor_on_update'): + restart_supervisor_processes(bench_path=bench_path) + + def pull_all_apps(bench_path='.'): rebase = '--rebase' if get_config(bench_path).get('rebase_on_pull') else '' diff --git a/bench/commands/__init__.py b/bench/commands/__init__.py old mode 100644 new mode 100755 index a1f7f450..09f6af5c --- a/bench/commands/__init__.py +++ b/bench/commands/__init__.py @@ -21,10 +21,11 @@ def bench_command(bench_path='.'): setup_logging(bench_path=bench_path) -from bench.commands.make import init, get_app, new_app, new_site +from bench.commands.make import init, get_app, new_app, remove_app, new_site bench_command.add_command(init) bench_command.add_command(get_app) bench_command.add_command(new_app) +bench_command.add_command(remove_app) bench_command.add_command(new_site) diff --git a/bench/commands/make.py b/bench/commands/make.py old mode 100644 new mode 100755 index 3efc8da3..ecfcec0a --- a/bench/commands/make.py +++ b/bench/commands/make.py @@ -36,6 +36,14 @@ def new_app(app_name): new_app(app_name) +@click.command('remove-app') +@click.argument('app-name') +def remove_app(app_name): + "completely remove app from bench" + from bench.app import remove_app + remove_app(app_name) + + @click.command('new-site') @click.option('--mariadb-root-password', help="MariaDB root password") @click.option('--admin-password', help="admin password to set for site") diff --git a/bench/tests/test_init.py b/bench/tests/test_init.py index 09ed25de..bf9374e1 100755 --- a/bench/tests/test_init.py +++ b/bench/tests/test_init.py @@ -116,6 +116,25 @@ class TestBenchInit(unittest.TestCase): out = subprocess.check_output(["bench", "--site", site_name, "list-apps"], cwd=bench_path) self.assertTrue("erpnext" in out) + + def test_remove_app(self): + site_name = "test-site-4.dev" + self.init_bench('test-bench') + + self.new_site(site_name) + bench_path = os.path.join(self.benches_path, "test-bench") + + # get app + bench.app.get_app("https://github.com/frappe/erpnext", "develop", bench_path=bench_path) + + self.assertTrue(os.path.exists(os.path.join(bench_path, "apps", "erpnext"))) + + # remove it + bench.app.remove_app("erpnext", bench_path=bench_path) + + self.assertFalse(os.path.exists(os.path.join(bench_path, "apps", "erpnext"))) + + def test_switch_to_branch(self): self.init_bench('test-bench') diff --git a/bench/utils.py b/bench/utils.py old mode 100644 new mode 100755