From d1a3017172a415919f3335c4e43edd7488ea69b2 Mon Sep 17 00:00:00 2001 From: "Chinmay D. Pai" Date: Sun, 15 Dec 2019 12:06:12 +0530 Subject: [PATCH] fix(get-app): handle existing directory and other formatting changes * if a directory for the application already exists, provide user with 2 options: * ask to remove the directory and reclone (overwrite) * ask if the user wants to reinstall the application * separate get_app_name from get_app * move building assets and postprocessing to install_app method * make formatting changes to the code for flake8 * use reload_module from six instead of builtins Signed-off-by: Chinmay D. Pai --- bench/app.py | 102 ++++++++++++++++++++++++----------------- bench/commands/make.py | 3 +- 2 files changed, 61 insertions(+), 44 deletions(-) diff --git a/bench/app.py b/bench/app.py index 5becd1eb..ed6cee3d 100755 --- a/bench/app.py +++ b/bench/app.py @@ -4,6 +4,7 @@ from .utils import (exec_cmd, get_frappe, check_git_for_shallow_clone, build_ass restart_supervisor_processes, get_cmd_output, run_frappe_cmd, CommandFailedError, restart_systemd_processes) from .config.common_site_config import get_config +from six import reload_module import logging import requests @@ -14,6 +15,7 @@ import subprocess import bench import sys import shutil +import click logging.basicConfig(level="DEBUG") logger = logging.getLogger(__name__) @@ -50,7 +52,7 @@ def write_appstxt(apps, bench_path='.'): with open(os.path.join(bench_path, 'sites', 'apps.txt'), 'w') as f: return f.write('\n'.join(apps)) -def check_url(url, raise_err = True): +def check_url(url, raise_err=True): try: from urlparse import urlparse except ImportError: @@ -59,7 +61,7 @@ def check_url(url, raise_err = True): parsed = urlparse(url) if not parsed.scheme: if raise_err: - raise TypeError('{url} Not a valid URL'.format(url = url)) + raise TypeError('{url} Not a valid URL'.format(url=url)) else: return False @@ -93,58 +95,64 @@ def remove_from_excluded_apps_txt(app, bench_path='.'): return write_excluded_apps_txt(apps, bench_path=bench_path) def get_app(git_url, branch=None, bench_path='.', build_asset_files=True, verbose=False, - postprocess = True): + postprocess=True, overwrite=False): # from bench.utils import check_url try: from urlparse import urljoin except ImportError: from urllib.parse import urljoin - if not check_url(git_url, raise_err = False): + if not check_url(git_url, raise_err=False): orgs = ['frappe', 'erpnext'] for org in orgs: - url = 'https://api.github.com/repos/{org}/{app}'.format(org = org, app = git_url) + url = 'https://api.github.com/repos/{org}/{app}'.format(org=org, app=git_url) res = requests.get(url) if res.ok: - data = res.json() + data = res.json() if 'name' in data: if git_url == data['name']: - git_url = 'https://github.com/{org}/{app}'.format(org = org, app = git_url) + git_url = 'https://github.com/{org}/{app}'.format(org=org, app=git_url) break - #Gets repo name from URL + # Gets repo name from URL repo_name = git_url.rsplit('/', 1)[1].rsplit('.', 1)[0] - logger.info('getting app {}'.format(repo_name)) shallow_clone = '--depth 1' if check_git_for_shallow_clone() else '' branch = '--branch {branch}'.format(branch=branch) if branch else '' - exec_cmd("git clone {git_url} {branch} {shallow_clone} --origin upstream".format( - git_url=git_url, - shallow_clone=shallow_clone, - branch=branch), - cwd=os.path.join(bench_path, 'apps')) + if os.path.isdir(os.path.join(bench_path, 'apps', repo_name)): + # application directory already exists + # prompt user to overwrite it + if overwrite or click.confirm('''A directory for the application "{0}" already exists. +Do you want to continue and overwrite it?'''): + shutil.rmtree(os.path.join(bench_path, 'apps', repo_name)) + elif click.confirm('''Do you want to reinstall the existing application?''', abort=True): + app_name = get_app_name(bench_path, repo_name) + print("Reinstalling {0}".format(app_name)) + install_app(app=app_name, bench_path=bench_path, verbose=verbose, build_asset_files=build_asset_files) + sys.exit(1) - #Retrieves app name from setup.py + logger.info('Getting app {0}'.format(repo_name)) + exec_cmd("git clone {git_url} {branch} {shallow_clone} --origin upstream".format( + git_url=git_url, + shallow_clone=shallow_clone, + branch=branch), + cwd=os.path.join(bench_path, 'apps')) + + app_name = get_app_name(bench_path, repo_name) + print("Installing {0}".format(app_name)) + install_app(app=app_name, bench_path=bench_path, verbose=verbose, build_asset_files=build_asset_files) + + +def get_app_name(bench_path, repo_name): + # retrieves app name from setup.py app_path = os.path.join(bench_path, 'apps', repo_name, 'setup.py') with open(app_path, 'rb') as f: app_name = re.search(r'name\s*=\s*[\'"](.*)[\'"]', f.read().decode('utf-8')).group(1) if repo_name != app_name: apps_path = os.path.join(os.path.abspath(bench_path), 'apps') os.rename(os.path.join(apps_path, repo_name), os.path.join(apps_path, app_name)) + return app_name - print('installing', app_name) - install_app(app=app_name, bench_path=bench_path, verbose=verbose) - - if postprocess: - - if build_asset_files: - build_assets(bench_path=bench_path, app=app_name) - conf = get_config(bench_path=bench_path) - - if conf.get('restart_supervisor_on_update'): - restart_supervisor_processes(bench_path=bench_path) - if conf.get('restart_systemd_on_update'): - restart_systemd_processes(bench_path=bench_path) def new_app(app, bench_path='.'): # For backwards compatibility @@ -160,7 +168,8 @@ def new_app(app, bench_path='.'): run_frappe_cmd('make-app', apps, app, bench_path=bench_path) install_app(app, bench_path=bench_path) -def install_app(app, bench_path=".", verbose=False, no_cache=False): + +def install_app(app, bench_path=".", verbose=False, no_cache=False, postprocess=True, build_asset_files=True): logger.info("installing {}".format(app)) pip_path = os.path.join(bench_path, "env", "bin", "pip") @@ -168,11 +177,23 @@ def install_app(app, bench_path=".", verbose=False, no_cache=False): app_path = os.path.join(bench_path, "apps", app) cache_flag = "--no-cache-dir" if no_cache else "" - exec_cmd("{pip} install {quiet} -U -e {app} {no_cache}".format(pip=pip_path, quiet=quiet_flag, app=app_path, no_cache=cache_flag)) + exec_cmd("{pip} install {quiet} -U -e {app} {no_cache}".format(pip=pip_path, + quiet=quiet_flag, app=app_path, no_cache=cache_flag)) add_to_appstxt(app, bench_path=bench_path) + if postprocess: + if build_asset_files: + build_assets(bench_path=bench_path, app=app) + conf = get_config(bench_path=bench_path) + + if conf.get('restart_supervisor_on_update'): + restart_supervisor_processes(bench_path=bench_path) + if conf.get('restart_systemd_on_update'): + restart_systemd_processes(bench_path=bench_path) + + def remove_app(app, bench_path='.'): - if not app in get_apps(bench_path): + if app not in get_apps(bench_path): print("No app named {0}".format(app)) sys.exit(1) @@ -281,8 +302,7 @@ def get_current_branch(app, bench_path='.'): def get_remote(app, bench_path='.'): repo_dir = get_repo_dir(app, bench_path=bench_path) - contents = subprocess.check_output(['git', 'remote', '-v'], cwd=repo_dir, - stderr=subprocess.STDOUT) + contents = subprocess.check_output(['git', 'remote', '-v'], cwd=repo_dir, stderr=subprocess.STDOUT) contents = contents.decode('utf-8') if re.findall('upstream[\s]+', contents): return 'upstream' @@ -371,7 +391,7 @@ def switch_branch(branch, apps=None, bench_path='.', upgrade=False, check_upgrad except CommandFailedError: print("Error switching to branch {0} for {1}".format(branch, app)) except InvalidRemoteException: - print("Remote does not exist for app "+app) + print("Remote does not exist for app {0}".format(app)) except InvalidBranchException: print("Branch {0} does not exist in Upstream for {1}".format(branch, app)) @@ -382,11 +402,7 @@ def switch_branch(branch, apps=None, bench_path='.', upgrade=False, check_upgrad update_requirements() update_node_packages() pre_upgrade(version_upgrade[1], version_upgrade[2]) - if sys.version_info >= (3, 4): - import importlib - importlib.reload(utils) - else: - reload(utils) + reload_module(utils) backup_all_sites() patch_sites() build_assets() @@ -402,8 +418,7 @@ def switch_to_develop(apps=None, bench_path='.', upgrade=True): switch_branch('develop', apps=apps, bench_path=bench_path, upgrade=upgrade) def get_version_from_string(contents, field='__version__'): - match = re.search(r"^(\s*%s\s*=\s*['\\\"])(.+?)(['\"])(?sm)" % field, - contents) + match = re.search(r"^(\s*%s\s*=\s*['\\\"])(.+?)(['\"])(?sm)" % field, contents) return match.group(2) def get_major_version(version): @@ -427,7 +442,8 @@ def validate_branch(): branch = get_current_branch(app) if branch == "master": - print(''' master branch is renamed to version-11 and develop to version-12. Please switch to new branches to get future updates. + print('''master branch is renamed to version-11 and develop to version-12. +Please switch to new branches to get future updates. To switch to version 11, run the following commands: bench switch-to-branch version-11''') - sys.exit(1) \ No newline at end of file + sys.exit(1) diff --git a/bench/commands/make.py b/bench/commands/make.py index b3ca8341..dc10515a 100755 --- a/bench/commands/make.py +++ b/bench/commands/make.py @@ -35,10 +35,11 @@ def init(path, apps_path, frappe_path, frappe_branch, no_procfile, no_backups, @click.argument('name', nargs=-1) # Dummy argument for backward compatibility @click.argument('git-url') @click.option('--branch', default=None, help="branch to checkout") +@click.option('--overwrite' is_flag=True) def get_app(git_url, branch, name=None): "clone an app from the internet and set it up in your bench" from bench.app import get_app - get_app(git_url, branch=branch) + get_app(git_url, branch=branch, overwrite=overwrite) @click.command('new-app')