105 lines
3 KiB
Python
105 lines
3 KiB
Python
# Copyright (c) 2015, Frappe Technologies Pvt. Ltd. and Contributors
|
|
# MIT License. See license.txt
|
|
|
|
from __future__ import unicode_literals
|
|
import os
|
|
import json
|
|
from semantic_version import Version
|
|
import frappe
|
|
from frappe.utils import cstr
|
|
|
|
def get_change_log(user=None):
|
|
if not user: user = frappe.session.user
|
|
|
|
last_known_versions = frappe._dict(json.loads(frappe.db.get_value("User",
|
|
user, "last_known_versions") or "{}"))
|
|
current_versions = get_versions()
|
|
|
|
if not last_known_versions:
|
|
update_last_known_versions()
|
|
return []
|
|
|
|
change_log = []
|
|
def set_in_change_log(app, opts, change_log):
|
|
from_version = last_known_versions.get(app, {}).get("version") or "0.0.1"
|
|
to_version = opts["version"]
|
|
|
|
if from_version != to_version:
|
|
app_change_log = get_change_log_for_app(app, from_version=from_version, to_version=to_version)
|
|
|
|
if app_change_log:
|
|
change_log.append({
|
|
"title": opts["title"],
|
|
"description": opts["description"],
|
|
"version": to_version,
|
|
"change_log": app_change_log
|
|
})
|
|
|
|
for app, opts in current_versions.items():
|
|
if app != "frappe":
|
|
set_in_change_log(app, opts, change_log)
|
|
|
|
if "frappe" in current_versions:
|
|
set_in_change_log("frappe", current_versions["frappe"], change_log)
|
|
|
|
return change_log
|
|
|
|
def get_change_log_for_app(app, from_version, to_version):
|
|
change_log_folder = os.path.join(frappe.get_app_path(app), "change_log")
|
|
if not os.path.exists(change_log_folder):
|
|
return
|
|
|
|
from_version = Version(from_version)
|
|
to_version = Version(to_version)
|
|
# remove pre-release part
|
|
to_version.prerelease = None
|
|
|
|
major_version_folders = ["v{0}".format(i) for i in xrange(from_version.major, to_version.major + 1)]
|
|
app_change_log = []
|
|
|
|
for folder in os.listdir(change_log_folder):
|
|
if folder in major_version_folders:
|
|
for file in os.listdir(os.path.join(change_log_folder, folder)):
|
|
version = Version(os.path.splitext(file)[0][1:].replace("_", "."))
|
|
|
|
if from_version < version <= to_version:
|
|
file_path = os.path.join(change_log_folder, folder, file)
|
|
content = frappe.read_file(file_path)
|
|
app_change_log.append([version, content])
|
|
|
|
app_change_log = sorted(app_change_log, key=lambda d: d[0], reverse=True)
|
|
|
|
# convert version to string and send
|
|
return [[cstr(d[0]), d[1]] for d in app_change_log]
|
|
|
|
@frappe.whitelist()
|
|
def update_last_known_versions():
|
|
frappe.db.set_value("User", frappe.session.user, "last_known_versions",
|
|
json.dumps(get_versions()), update_modified=False)
|
|
|
|
@frappe.whitelist()
|
|
def get_versions():
|
|
"""Get versions of all installed apps.
|
|
|
|
Example:
|
|
|
|
{
|
|
"frappe": {
|
|
"title": "Frappe Framework",
|
|
"version": "5.0.0"
|
|
}
|
|
}"""
|
|
versions = {}
|
|
for app in frappe.get_installed_apps(sort=True):
|
|
versions[app] = {
|
|
"title": frappe.get_hooks("app_title", app_name=app)[0],
|
|
"description": frappe.get_hooks("app_description", app_name=app)[0]
|
|
}
|
|
try:
|
|
versions[app]["version"] = frappe.get_attr(app + ".__version__")
|
|
except AttributeError:
|
|
versions[app]["version"] = '0.0.1'
|
|
|
|
return versions
|
|
|
|
|