103 lines
3.1 KiB
Python
103 lines
3.1 KiB
Python
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
|
# MIT License. See license.txt
|
|
|
|
from __future__ import unicode_literals
|
|
import frappe
|
|
import frappe.utils
|
|
import frappe.installer
|
|
import frappe.sessions
|
|
import subprocess
|
|
import os
|
|
import json
|
|
from frappe import _
|
|
from distutils.spawn import find_executable
|
|
|
|
@frappe.whitelist()
|
|
def get_app_list():
|
|
"""Get list of all apps with properties, installed, category from hooks and
|
|
`frappe/data/app_listing/` if an entry exists"""
|
|
out = {}
|
|
installed = frappe.get_installed_apps()
|
|
for app in frappe.get_all_apps(True):
|
|
app_hooks = frappe.get_hooks(app_name=app)
|
|
|
|
if app not in installed and app_hooks.get('hide_in_installer'):
|
|
continue
|
|
|
|
out[app] = {}
|
|
for key in ("app_name", "app_title", "app_description", "app_icon",
|
|
"app_publisher", "app_version", "app_url", "app_color"):
|
|
val = app_hooks.get(key) or []
|
|
out[app][key] = val[0] if len(val) else ""
|
|
|
|
if app in installed:
|
|
out[app]["installed"] = 1
|
|
|
|
for app_from_list in get_app_listing().values():
|
|
if app_from_list.app_name in out:
|
|
out[app_from_list.app_name].update(app_from_list)
|
|
else:
|
|
if not frappe.conf.disallow_app_listing:
|
|
out[app_from_list.app_name] = app_from_list
|
|
|
|
return out
|
|
|
|
def get_app_listing():
|
|
"""Get apps listed in `frappe/data/app_listing/`"""
|
|
apps_listing_dir = os.path.join(os.path.dirname(frappe.__file__), 'data', 'app_listing')
|
|
out = {}
|
|
for app in os.listdir(apps_listing_dir):
|
|
if app.endswith(".json"):
|
|
with open(os.path.join(apps_listing_dir, app)) as f:
|
|
out[app[:-5]] = frappe._dict(json.load(f))
|
|
return out
|
|
|
|
@frappe.whitelist()
|
|
def install_app(name):
|
|
"""Install app, if app is not installed in local environment, install it via git url in
|
|
`frappe/data/app_listing/`"""
|
|
frappe.only_for("System Manager")
|
|
|
|
if name not in frappe.get_all_apps(True):
|
|
if not frappe.conf.disallow_app_listing:
|
|
get_app(name)
|
|
frappe.cache().delete_value(["app_hooks"])
|
|
# reload sys.path
|
|
import site
|
|
reload(site)
|
|
else:
|
|
# will only come via direct API
|
|
frappe.throw("Listing app not allowed")
|
|
|
|
app_hooks = frappe.get_hooks(app_name=name)
|
|
if app_hooks.get('hide_in_installer'):
|
|
frappe.throw(_("You cannot install this app"))
|
|
|
|
frappe.publish_realtime("install_app_progress", {"status": _("Installing App {0}").format(name)},
|
|
user=frappe.session.user)
|
|
|
|
frappe.installer.install_app(name)
|
|
|
|
frappe.publish_realtime("install_app_progress", {"status": _("{0} Installed").format(name)},
|
|
user=frappe.session.user)
|
|
|
|
def get_app(name):
|
|
"""Get app using git clone and install it in bench environment"""
|
|
app_listing = get_app_listing()
|
|
if name not in app_listing:
|
|
frappe.throw(_("Unknown app {0}").format(name))
|
|
raise frappe.ValidationError
|
|
|
|
frappe.publish_realtime("install_app_progress", {"status": _("Downloading App {0}").format(name)},
|
|
user=frappe.session.user)
|
|
|
|
args = [find_executable('bench'), 'get-app', name, app_listing[name]['repo_url']]
|
|
|
|
try:
|
|
subprocess.check_call(args, cwd=frappe.utils.get_bench_path(),
|
|
stderr=subprocess.STDOUT)
|
|
return "okay"
|
|
except subprocess.CalledProcessError as e:
|
|
frappe.msgprint("<b>" + " ".join(args) + "</b>")
|
|
frappe.msgprint(e.output)
|
|
return e.output
|