diff --git a/bench/app.py b/bench/app.py index 0dc2fba71..fd9b16dc2 100755 --- a/bench/app.py +++ b/bench/app.py @@ -1,4 +1,5 @@ # imports - standard imports +from collections import OrderedDict import functools import json import logging @@ -46,6 +47,7 @@ def __init__(self, name: str, branch: str = None, to_clone: bool = True): 3. frappe/healthcare@develop 4. healthcare 5. healthcare@develop, healthcare@v13.12.1 + 6. erpnext References for Version Identifiers: * https://www.python.org/dev/peps/pep-0440/#version-specifiers @@ -91,6 +93,7 @@ def setup_details(self): self._setup_details_from_name_tag() def _setup_details_from_mounted_disk(self): + self.branch = subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]) self.org, self.repo, self.tag = os.path.split(self.name)[-2:] + (self.branch,) def _setup_details_from_name_tag(self): @@ -98,6 +101,7 @@ def _setup_details_from_name_tag(self): self.tag = self.tag or self.branch def _setup_details_from_installed_apps(self): + self.branch = subprocess.check_output(["git", "rev-parse", "--abbrev-ref", "HEAD"]) self.org, self.repo, self.tag = os.path.split( os.path.join(self.bench.name, "apps", self.name) )[-2:] + (self.branch,) @@ -197,6 +201,35 @@ def install(self, skip_assets=False, verbose=False): def uninstall(self): self.bench.run(f"{self.bench.python} -m pip uninstall -y {self.repo}") + def _get_dependencies(self): + from bench.utils.app import get_required_deps_url + import toml + + info_file = None + required_url = get_required_deps_url(self.url, self.tag) + print(required_url) + try: + info_file = toml.loads(requests.get(required_url).text) + except Exception: + click.echo("\nNo toml file found \n", err=True) + + return info_file["required_apps"] if info_file else {} + +def make_resolution_plan(app: App, bench): + """ + decide what apps and versions to install and in what order + """ + resolution = OrderedDict() + resolution[app.repo] = app + for app_name, branch in app._get_dependencies().items(): + dep_app = App(app_name, branch=branch, bench=bench) + resolution[dep_app.repo] = dep_app + resolution.update(make_resolution_plan(dep_app, bench)) + if app_name in resolution: + print("Resolve this conflict!") + return resolution + + def add_to_appstxt(app, bench_path="."): from bench.bench import Bench @@ -310,6 +343,7 @@ def get_app( repo_name = app.repo branch = app.tag bench_setup = False + apps_to_install = make_resolution_plan(app, bench) if not is_bench_directory(bench_path): if not init_bench: @@ -320,8 +354,9 @@ def get_app( from bench.utils.system import init + frappe_app = apps_to_install["frappe"] bench_path = get_available_folder_name(f"{app.repo}-bench", bench_path) - init(path=bench_path, frappe_branch=branch) + init(path=bench_path, frappe_branch=frappe_app.tag) os.chdir(bench_path) bench_setup = True diff --git a/bench/utils/app.py b/bench/utils/app.py index ae9807439..f7a6d5cc2 100644 --- a/bench/utils/app.py +++ b/bench/utils/app.py @@ -164,6 +164,12 @@ def get_current_branch(app, bench_path="."): repo_dir = get_repo_dir(app, bench_path=bench_path) return get_cmd_output("basename $(git symbolic-ref -q HEAD)", cwd=repo_dir) +def get_required_deps_url(git_url, branch="master", deps="info.toml"): + git_url = ( + git_url.replace(".git", "").replace("github.com", "raw.github.com") + ) + git_url += f"/{branch}/{deps}" if branch else f"/{deps}" + return git_url def get_remote(app, bench_path="."): repo_dir = get_repo_dir(app, bench_path=bench_path)