From b0892294824420012612b904b98d50afa7a6c7cb Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 2 Mar 2019 01:19:40 +0100 Subject: [PATCH 1/7] Begin to factorize script loading in an app class --- package_linter.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/package_linter.py b/package_linter.py index 690e75d..539c4bd 100755 --- a/package_linter.py +++ b/package_linter.py @@ -82,6 +82,16 @@ def file_exists(file_path): # Actual high-level checks # ############################################################################ +class App(): + + def __init__(self, path): + + print_header("LOADING APP") + self.path = path + + scripts = ["install", "remove", "upgrade", "backup", "restore"] + self.scripts = { f: Script(self.path, f) for f in scripts } + def check_files_exist(app_path): """ @@ -90,11 +100,10 @@ def check_files_exist(app_path): """ print_header("MISSING FILES") - filenames = ("manifest.json", + filenames = ("manifest.json", "LICENSE", "README.md", "scripts/install", "scripts/remove", "scripts/upgrade", - "scripts/backup", "scripts/restore", - "LICENSE", "README.md") + "scripts/backup", "scripts/restore") non_mandatory = ("script/backup", "script/restore") for filename in filenames: @@ -404,6 +413,7 @@ class Script(): self.exists = file_exists(self.path) if not self.exists: return + self.lines = list(self.read_file()) def read_file(self): with open(self.path) as f: @@ -421,7 +431,8 @@ class Script(): line = shlex.split(line, True) yield line except Exception as e: - print_warning("Could not parse this line (%s) : %s" % (e, line)) + print_warning("%s : Could not parse this line (%s) : %s" % (self.path, e, line)) + def contains(self, command): """ @@ -436,7 +447,6 @@ class Script(): def analyze(self): print_header(self.name.upper() + " SCRIPT") - self.lines = list(self.read_file()) check_verifications_done_before_modifying_system(self) check_set_usage(self) @@ -454,15 +464,13 @@ def main(): header(app_path) # Global checks + app = App(app_path) check_files_exist(app_path) check_source_management(app_path) check_manifest(app_path) # Scripts checks - scripts = ["install", "remove", "upgrade", "backup", "restore"] - for script_name in scripts: - - script = Script(app_path, script_name) + for script in app.scripts.values(): if script.exists: script.analyze() From 26c383d0b35163dde7e01723da3021f92605ba76 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 2 Mar 2019 01:30:58 +0100 Subject: [PATCH 2/7] check_files_exist -> misc_file_checks and other tweaks --- package_linter.py | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) diff --git a/package_linter.py b/package_linter.py index 539c4bd..5051833 100755 --- a/package_linter.py +++ b/package_linter.py @@ -93,13 +93,14 @@ class App(): self.scripts = { f: Script(self.path, f) for f in scripts } -def check_files_exist(app_path): - """ - Check files exist - 'backup' and 'restore' scripts are not mandatory - """ +def misc_file_checks(app_path): + + print_header("MISC FILE CHECKS") + + # + # Check for recommended and mandatory files + # - print_header("MISSING FILES") filenames = ("manifest.json", "LICENSE", "README.md", "scripts/install", "scripts/remove", "scripts/upgrade", @@ -110,14 +111,21 @@ def check_files_exist(app_path): if file_exists(app_path + "/" + filename): continue elif filename in non_mandatory: - print_warning(filename) + print_warning("Consider adding a file %s" % filename) else: - print_error(filename) + print_error("File %s is mandatory" % filename) + # # Deprecated php-fpm.ini thing + # + if file_exists(app_path + "/conf/php-fpm.ini"): print_warning("Using a separate php-fpm.ini file is deprecated. Please merge your php-fpm directives directly in the pool file. (c.f. https://github.com/YunoHost-Apps/nextcloud_ynh/issues/138 )") + # + # Deprecated usage of 'add_header' in nginx conf + # + for filename in os.listdir(app_path + "/conf"): if not os.path.isfile(filename): continue @@ -465,7 +473,7 @@ def main(): # Global checks app = App(app_path) - check_files_exist(app_path) + misc_file_checks(app_path) check_source_management(app_path) check_manifest(app_path) From a0e435c271d507bad4306aa179f9edbbd1b9a121 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 2 Mar 2019 01:34:39 +0100 Subject: [PATCH 3/7] Move license_mentionned_in_readme inside check_manifest --- package_linter.py | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/package_linter.py b/package_linter.py index 5051833..7ef7089 100755 --- a/package_linter.py +++ b/package_linter.py @@ -148,13 +148,6 @@ def check_source_management(app_path): "https://github.com/YunoHost/issues/issues/201#issuecomment-391549262") -def license_mentionned_in_readme(path): - readme_path = os.path.join(path, 'README.md') - if os.path.isfile(readme_path): - return "LICENSE" in open(readme_path).read() - return False - - def check_manifest(path): manifest = os.path.join(path, 'manifest.json') if not os.path.exists(manifest): @@ -212,6 +205,12 @@ def check_manifest(path): print_warning("[YEP-1.2] This app is not registered in official or community applications") # YEP 1.3 License + def license_mentionned_in_readme(path): + readme_path = os.path.join(path, 'README.md') + if os.path.isfile(readme_path): + return "LICENSE" in open(readme_path).read() + return False + if "license" in manifest: for license in manifest['license'].replace('&', ',').split(','): code_license = '' + license + '' From 0c4e86d0988df276f7359c0cec714037ae20b483 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 2 Mar 2019 01:43:29 +0100 Subject: [PATCH 4/7] Move general checks as methods of App class --- package_linter.py | 370 +++++++++++++++++++++++----------------------- 1 file changed, 185 insertions(+), 185 deletions(-) diff --git a/package_linter.py b/package_linter.py index 7ef7089..7881558 100755 --- a/package_linter.py +++ b/package_linter.py @@ -93,212 +93,223 @@ class App(): self.scripts = { f: Script(self.path, f) for f in scripts } -def misc_file_checks(app_path): + def analyze(self): - print_header("MISC FILE CHECKS") + self.misc_file_checks() + self.check_source_management() + self.check_manifest() - # - # Check for recommended and mandatory files - # - - filenames = ("manifest.json", "LICENSE", "README.md", - "scripts/install", "scripts/remove", - "scripts/upgrade", - "scripts/backup", "scripts/restore") - non_mandatory = ("script/backup", "script/restore") - - for filename in filenames: - if file_exists(app_path + "/" + filename): - continue - elif filename in non_mandatory: - print_warning("Consider adding a file %s" % filename) - else: - print_error("File %s is mandatory" % filename) - - # - # Deprecated php-fpm.ini thing - # - - if file_exists(app_path + "/conf/php-fpm.ini"): - print_warning("Using a separate php-fpm.ini file is deprecated. Please merge your php-fpm directives directly in the pool file. (c.f. https://github.com/YunoHost-Apps/nextcloud_ynh/issues/138 )") - - # - # Deprecated usage of 'add_header' in nginx conf - # - - for filename in os.listdir(app_path + "/conf"): - if not os.path.isfile(filename): - continue - content = open(app_path + "/conf/" + filename).read() - if "location" in content and "add_header" in content: - print_warning("Do not use 'add_header' in the nginx conf. Use 'more_set_headers' instead. (See https://www.peterbe.com/plog/be-very-careful-with-your-add_header-in-nginx and https://github.com/openresty/headers-more-nginx-module#more_set_headers )") + for script in self.scripts.values(): + if script.exists: + script.analyze() -def check_source_management(app_path): - print_header("SOURCES MANAGEMENT") - DIR = os.path.join(app_path, "sources") - # Check if there is more than six files on 'sources' folder - if os.path.exists(os.path.join(app_path, "sources")) \ - and len([name for name in os.listdir(DIR) if os.path.isfile(os.path.join(DIR, name))]) > 5: - print_warning("[YEP-3.3] Upstream app sources shouldn't be stored on this " - "'sources' folder of this git repository as a copy/paste." - "\nAt installation, the package should download sources " - "from upstream via 'ynh_setup_source'.\nSee the helper" - "documentation. Original discussion happened here : " - "https://github.com/YunoHost/issues/issues/201#issuecomment-391549262") + def misc_file_checks(self): + + print_header("MISC FILE CHECKS") + + # + # Check for recommended and mandatory files + # + + filenames = ("manifest.json", "LICENSE", "README.md", + "scripts/install", "scripts/remove", + "scripts/upgrade", + "scripts/backup", "scripts/restore") + non_mandatory = ("script/backup", "script/restore") + + for filename in filenames: + if file_exists(self.path + "/" + filename): + continue + elif filename in non_mandatory: + print_warning("Consider adding a file %s" % filename) + else: + print_error("File %s is mandatory" % filename) + + # + # Deprecated php-fpm.ini thing + # + + if file_exists(self.path + "/conf/php-fpm.ini"): + print_warning("Using a separate php-fpm.ini file is deprecated. Please merge your php-fpm directives directly in the pool file. (c.f. https://github.com/YunoHost-Apps/nextcloud_ynh/issues/138 )") + + # + # Deprecated usage of 'add_header' in nginx conf + # + + for filename in os.listdir(self.path + "/conf"): + if not os.path.isfile(filename): + continue + content = open(self.path + "/conf/" + filename).read() + if "location" in content and "add_header" in content: + print_warning("Do not use 'add_header' in the nginx conf. Use 'more_set_headers' instead. (See https://www.peterbe.com/plog/be-very-careful-with-your-add_header-in-nginx and https://github.com/openresty/headers-more-nginx-module#more_set_headers )") -def check_manifest(path): - manifest = os.path.join(path, 'manifest.json') - if not os.path.exists(manifest): - return - print_header("MANIFEST") - """ - Check if there is no comma syntax issue - """ + def check_source_management(self): + print_header("SOURCES MANAGEMENT") + DIR = os.path.join(self.path, "sources") + # Check if there is more than six files on 'sources' folder + if os.path.exists(os.path.join(self.path, "sources")) \ + and len([name for name in os.listdir(DIR) if os.path.isfile(os.path.join(DIR, name))]) > 5: + print_warning("[YEP-3.3] Upstream app sources shouldn't be stored on this " + "'sources' folder of this git repository as a copy/paste." + "\nAt installation, the package should download sources " + "from upstream via 'ynh_setup_source'.\nSee the helper" + "documentation. Original discussion happened here : " + "https://github.com/YunoHost/issues/issues/201#issuecomment-391549262") - try: - with open(manifest, encoding='utf-8') as data_file: - manifest = json.loads(data_file.read()) - except: - print_error("[YEP-2.1] Syntax (comma) or encoding issue with manifest.json. " - "Can't check file.") - fields = ("name", "id", "packaging_format", "description", "url", "version", - "license", "maintainer", "requirements", "multi_instance", - "services", "arguments") + def check_manifest(self): + manifest = os.path.join(self.path, 'manifest.json') + if not os.path.exists(manifest): + return + print_header("MANIFEST") + """ + Check if there is no comma syntax issue + """ - for field in fields: - if field not in manifest: - print_warning("[YEP-2.1] \"" + field + "\" field is missing") + try: + with open(manifest, encoding='utf-8') as data_file: + manifest = json.loads(data_file.read()) + except: + print_error("[YEP-2.1] Syntax (comma) or encoding issue with manifest.json. " + "Can't check file.") - """ - Check values in keys - """ + fields = ("name", "id", "packaging_format", "description", "url", "version", + "license", "maintainer", "requirements", "multi_instance", + "services", "arguments") - if "packaging_format" not in manifest: - print_error("[YEP-2.1] \"packaging_format\" key is missing") - elif not isinstance(manifest["packaging_format"], int): - print_error("[YEP-2.1] \"packaging_format\": value isn't an integer type") - elif manifest["packaging_format"] != 1: - print_error("[YEP-2.1] \"packaging_format\" field: current format value is '1'") + for field in fields: + if field not in manifest: + print_warning("[YEP-2.1] \"" + field + "\" field is missing") - # YEP 1.1 Name is app - if "id" in manifest: - if not re.match('^[a-z1-9]((_|-)?[a-z1-9])+$', manifest["id"]): - print_error("[YEP-1.1] 'id' field '%s' should respect this regex " - "'^[a-z1-9]((_|-)?[a-z1-9])+$'") + """ + Check values in keys + """ - if "name" in manifest: - if len(manifest["name"]) > 22: - print_warning("[YEP-1.1] The 'name' field shouldn't be too long to be" - " able to be with one line in the app list. The most " - "current bigger name is actually compound of 22 characters.") + if "packaging_format" not in manifest: + print_error("[YEP-2.1] \"packaging_format\" key is missing") + elif not isinstance(manifest["packaging_format"], int): + print_error("[YEP-2.1] \"packaging_format\": value isn't an integer type") + elif manifest["packaging_format"] != 1: + print_error("[YEP-2.1] \"packaging_format\" field: current format value is '1'") - # YEP 1.2 Put the app in a weel known repo - if "id" in manifest: - official_list_url = "https://raw.githubusercontent.com/YunoHost/apps/master/official.json" - official_list = json.loads(urlopen(official_list_url)['content']) - community_list_url = "https://raw.githubusercontent.com/YunoHost/apps/master/community.json" - community_list = json.loads(urlopen(community_list_url)['content']) - if manifest["id"] not in official_list and manifest["id"] not in community_list: - print_warning("[YEP-1.2] This app is not registered in official or community applications") + # YEP 1.1 Name is app + if "id" in manifest: + if not re.match('^[a-z1-9]((_|-)?[a-z1-9])+$', manifest["id"]): + print_error("[YEP-1.1] 'id' field '%s' should respect this regex " + "'^[a-z1-9]((_|-)?[a-z1-9])+$'") - # YEP 1.3 License - def license_mentionned_in_readme(path): - readme_path = os.path.join(path, 'README.md') - if os.path.isfile(readme_path): - return "LICENSE" in open(readme_path).read() - return False + if "name" in manifest: + if len(manifest["name"]) > 22: + print_warning("[YEP-1.1] The 'name' field shouldn't be too long to be" + " able to be with one line in the app list. The most " + "current bigger name is actually compound of 22 characters.") - if "license" in manifest: - for license in manifest['license'].replace('&', ',').split(','): - code_license = '' + license + '' - link = "https://spdx.org/licenses/" - if license == "nonfree": - print_warning("[YEP-1.3] The correct value for non free license in license" - " field is 'non-free' and not 'nonfree'") - license = "non-free" - if license in ["free", "non-free", "dep-non-free"]: - if not license_mentionned_in_readme(path): - print_warning("[YEP-1.3] The use of '%s' in license field implies to " - "write something about the license in your " - "README.md" % (license)) - if license in ["non-free", "dep-non-free"]: - print_warning("[YEP-1.3] 'non-free' apps can't be officialized." - "Their integration is still being discussed," - "especially for apps with non-free dependencies") - elif code_license not in urlopen(link)['content']: - print_warning("[YEP-1.3] The license '%s' is not registered in " - "https://spdx.org/licenses/ . It can be a typo error. " - "If not, you should replace it by 'free' or 'non-free'" - "and give some explanations in the README.md." % (license)) + # YEP 1.2 Put the app in a weel known repo + if "id" in manifest: + official_list_url = "https://raw.githubusercontent.com/YunoHost/apps/master/official.json" + official_list = json.loads(urlopen(official_list_url)['content']) + community_list_url = "https://raw.githubusercontent.com/YunoHost/apps/master/community.json" + community_list = json.loads(urlopen(community_list_url)['content']) + if manifest["id"] not in official_list and manifest["id"] not in community_list: + print_warning("[YEP-1.2] This app is not registered in official or community applications") - # YEP 1.4 Inform if we continue to maintain the app - # YEP 1.5 Update regularly the app status - # YEP 1.6 Check regularly the evolution of the upstream + # YEP 1.3 License + def license_mentionned_in_readme(): + readme_path = os.path.join(path, 'README.md') + if os.path.isfile(readme_path): + return "LICENSE" in open(readme_path).read() + return False - # YEP 1.7 - Add an app to the YunoHost-Apps organization - if "id" in manifest: - repo = "https://github.com/YunoHost-Apps/%s_ynh" % (manifest["id"]) - is_not_added_to_org = urlopen(repo)['code'] == 404 + if "license" in manifest: + for license in manifest['license'].replace('&', ',').split(','): + code_license = '' + license + '' + link = "https://spdx.org/licenses/" + if license == "nonfree": + print_warning("[YEP-1.3] The correct value for non free license in license" + " field is 'non-free' and not 'nonfree'") + license = "non-free" + if license in ["free", "non-free", "dep-non-free"]: + if not license_mentionned_in_readme(self.path): + print_warning("[YEP-1.3] The use of '%s' in license field implies to " + "write something about the license in your " + "README.md" % (license)) + if license in ["non-free", "dep-non-free"]: + print_warning("[YEP-1.3] 'non-free' apps can't be officialized." + "Their integration is still being discussed," + "especially for apps with non-free dependencies") + elif code_license not in urlopen(link)['content']: + print_warning("[YEP-1.3] The license '%s' is not registered in " + "https://spdx.org/licenses/ . It can be a typo error. " + "If not, you should replace it by 'free' or 'non-free'" + "and give some explanations in the README.md." % (license)) - if is_not_added_to_org: - print_warning("[YEP-1.7] You should add your app in the " - "YunoHost-Apps organisation.") + # YEP 1.4 Inform if we continue to maintain the app + # YEP 1.5 Update regularly the app status + # YEP 1.6 Check regularly the evolution of the upstream - # YEP 1.8 Publish test request - # YEP 1.9 Document app - if "description" in manifest: - descr = manifest["description"] - if isinstance(descr, dict): - descr = descr.get("en", None) + # YEP 1.7 - Add an app to the YunoHost-Apps organization + if "id" in manifest: + repo = "https://github.com/YunoHost-Apps/%s_ynh" % (manifest["id"]) + is_not_added_to_org = urlopen(repo)['code'] == 404 - if descr is None or descr == manifest.get("name", None): - print_warning("[YEP-1.9] You should write a good description of the app, at least in english (1 line is enough).") + if is_not_added_to_org: + print_warning("[YEP-1.7] You should add your app in the " + "YunoHost-Apps organisation.") - elif "for yunohost" in descr.lower(): - print_warning("[YEP-1.9] The 'description' should explain what the app actually does. No need to say that it is 'for YunoHost' - this is a YunoHost app so of course we know it is for YunoHost ;-).") + # YEP 1.8 Publish test request + # YEP 1.9 Document app + if "description" in manifest: + descr = manifest["description"] + if isinstance(descr, dict): + descr = descr.get("en", None) - # TODO test a specific template in README.md + if descr is None or descr == manifest.get("name", None): + print_warning("[YEP-1.9] You should write a good description of the app, at least in english (1 line is enough).") - # YEP 1.10 Garder un historique de version propre + elif "for yunohost" in descr.lower(): + print_warning("[YEP-1.9] The 'description' should explain what the app actually does. No need to say that it is 'for YunoHost' - this is a YunoHost app so of course we know it is for YunoHost ;-).") - # YEP 1.11 Cancelled + # TODO test a specific template in README.md - # YEP 2.1 - if "multi_instance" in manifest and manifest["multi_instance"] != 1 and manifest["multi_instance"] != 0: - print_error( - "[YEP-2.1] \"multi_instance\" field must be boolean type values 'true' or 'false' and not string type") + # YEP 1.10 Garder un historique de version propre - if "services" in manifest: - services = ("nginx", "mysql", "uwsgi", "metronome", - "php5-fpm", "php7.0-fpm", "php-fpm", - "postfix", "dovecot", "rspamd") + # YEP 1.11 Cancelled - for service in manifest["services"]: - if service not in services: - # FIXME : wtf is it supposed to mean ... - print_warning("[YEP-2.1] " + service + " service may not exist") + # YEP 2.1 + if "multi_instance" in manifest and manifest["multi_instance"] != 1 and manifest["multi_instance"] != 0: + print_error( + "[YEP-2.1] \"multi_instance\" field must be boolean type values 'true' or 'false' and not string type") - if "install" in manifest["arguments"]: + if "services" in manifest: + services = ("nginx", "mysql", "uwsgi", "metronome", + "php5-fpm", "php7.0-fpm", "php-fpm", + "postfix", "dovecot", "rspamd") - recognized_types = ("domain", "path", "boolean", "app", "password", "user", "string") + for service in manifest["services"]: + if service not in services: + # FIXME : wtf is it supposed to mean ... + print_warning("[YEP-2.1] " + service + " service may not exist") - for argument in manifest["arguments"]["install"]: - if "type" not in argument.keys(): - print_warning("[YEP-2.1] You should specify the type of the argument '%s'. You can use : %s." % (argument["name"], ', '.join(recognized_types))) - elif argument["type"] not in recognized_types: - print_warning("[YEP-2.1] The type '%s' for argument '%s' is not recognized... it probably doesn't behave as you expect ? Choose among those instead : %s" % (argument["type"], argument["name"], ', '.join(recognized_types))) + if "install" in manifest["arguments"]: - if "choices" in argument.keys(): - choices = [c.lower() for c in argument["choices"]] - if len(choices) == 2: - if ("true" in choices and "false" in choices) or ("yes" in choices and "no" in choices): - print_warning("Argument %s : you might want to simply use a boolean-type argument. No need to specify the choices list yourself." % argument["name"]) + recognized_types = ("domain", "path", "boolean", "app", "password", "user", "string") - if "url" in manifest and manifest["url"].endswith("_ynh"): - print_warning("'url' is not meant to be the url of the yunohost package, but rather the website or repo of the upstream app itself...") + for argument in manifest["arguments"]["install"]: + if "type" not in argument.keys(): + print_warning("[YEP-2.1] You should specify the type of the argument '%s'. You can use : %s." % (argument["name"], ', '.join(recognized_types))) + elif argument["type"] not in recognized_types: + print_warning("[YEP-2.1] The type '%s' for argument '%s' is not recognized... it probably doesn't behave as you expect ? Choose among those instead : %s" % (argument["type"], argument["name"], ', '.join(recognized_types))) + + if "choices" in argument.keys(): + choices = [c.lower() for c in argument["choices"]] + if len(choices) == 2: + if ("true" in choices and "false" in choices) or ("yes" in choices and "no" in choices): + print_warning("Argument %s : you might want to simply use a boolean-type argument. No need to specify the choices list yourself." % argument["name"]) + + if "url" in manifest and manifest["url"].endswith("_ynh"): + print_warning("'url' is not meant to be the url of the yunohost package, but rather the website or repo of the upstream app itself...") def check_verifications_done_before_modifying_system(script): @@ -469,18 +480,7 @@ def main(): app_path = sys.argv[1] header(app_path) - - # Global checks - app = App(app_path) - misc_file_checks(app_path) - check_source_management(app_path) - check_manifest(app_path) - - # Scripts checks - for script in app.scripts.values(): - if script.exists: - script.analyze() - + App(app_path).analyze() sys.exit(return_code) From 6c63667638dbe1a9370e4e0e788aeefc9d3e1886 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 2 Mar 2019 02:06:43 +0100 Subject: [PATCH 5/7] Rework formatting of multi-line strings --- package_linter.py | 158 +++++++++++++++++++++++++++++++--------------- 1 file changed, 107 insertions(+), 51 deletions(-) diff --git a/package_linter.py b/package_linter.py index 7881558..fb098fc 100755 --- a/package_linter.py +++ b/package_linter.py @@ -131,7 +131,11 @@ class App(): # if file_exists(self.path + "/conf/php-fpm.ini"): - print_warning("Using a separate php-fpm.ini file is deprecated. Please merge your php-fpm directives directly in the pool file. (c.f. https://github.com/YunoHost-Apps/nextcloud_ynh/issues/138 )") + print_warning( + "Using a separate php-fpm.ini file is deprecated. " + "Please merge your php-fpm directives directly in the pool file. " + "(c.f. https://github.com/YunoHost-Apps/nextcloud_ynh/issues/138 )" + ) # # Deprecated usage of 'add_header' in nginx conf @@ -142,7 +146,11 @@ class App(): continue content = open(self.path + "/conf/" + filename).read() if "location" in content and "add_header" in content: - print_warning("Do not use 'add_header' in the nginx conf. Use 'more_set_headers' instead. (See https://www.peterbe.com/plog/be-very-careful-with-your-add_header-in-nginx and https://github.com/openresty/headers-more-nginx-module#more_set_headers )") + print_warning( + "Do not use 'add_header' in the nginx conf. Use 'more_set_headers' instead. " + "(See https://www.peterbe.com/plog/be-very-careful-with-your-add_header-in-nginx " + "and https://github.com/openresty/headers-more-nginx-module#more_set_headers )" + ) def check_source_management(self): @@ -151,12 +159,13 @@ class App(): # Check if there is more than six files on 'sources' folder if os.path.exists(os.path.join(self.path, "sources")) \ and len([name for name in os.listdir(DIR) if os.path.isfile(os.path.join(DIR, name))]) > 5: - print_warning("[YEP-3.3] Upstream app sources shouldn't be stored on this " - "'sources' folder of this git repository as a copy/paste." - "\nAt installation, the package should download sources " - "from upstream via 'ynh_setup_source'.\nSee the helper" - "documentation. Original discussion happened here : " - "https://github.com/YunoHost/issues/issues/201#issuecomment-391549262") + print_warning( + "[YEP-3.3] Upstream app sources shouldn't be stored in this 'sources' folder of this git repository as a copy/paste\n" + "During installation, the package should download sources from upstream via 'ynh_setup_source'.\n" + "See the helper documentation. " + "Original discussion happened here : " + "https://github.com/YunoHost/issues/issues/201#issuecomment-391549262" + ) def check_manifest(self): @@ -172,8 +181,7 @@ class App(): with open(manifest, encoding='utf-8') as data_file: manifest = json.loads(data_file.read()) except: - print_error("[YEP-2.1] Syntax (comma) or encoding issue with manifest.json. " - "Can't check file.") + print_error("[YEP-2.1] Syntax (comma) or encoding issue with manifest.json. Can't check file.") fields = ("name", "id", "packaging_format", "description", "url", "version", "license", "maintainer", "requirements", "multi_instance", @@ -197,14 +205,14 @@ class App(): # YEP 1.1 Name is app if "id" in manifest: if not re.match('^[a-z1-9]((_|-)?[a-z1-9])+$', manifest["id"]): - print_error("[YEP-1.1] 'id' field '%s' should respect this regex " - "'^[a-z1-9]((_|-)?[a-z1-9])+$'") + print_error("[YEP-1.1] 'id' field '%s' should respect this regex '^[a-z1-9]((_|-)?[a-z1-9])+$'") if "name" in manifest: if len(manifest["name"]) > 22: - print_warning("[YEP-1.1] The 'name' field shouldn't be too long to be" - " able to be with one line in the app list. The most " - "current bigger name is actually compound of 22 characters.") + print_warning( + "[YEP-1.1] The 'name' field shouldn't be too long to be able to be with one line in the app list. " + "The most current bigger name is actually compound of 22 characters." + ) # YEP 1.2 Put the app in a weel known repo if "id" in manifest: @@ -227,23 +235,25 @@ class App(): code_license = '' + license + '' link = "https://spdx.org/licenses/" if license == "nonfree": - print_warning("[YEP-1.3] The correct value for non free license in license" - " field is 'non-free' and not 'nonfree'") + print_warning("[YEP-1.3] The correct value for non free license in license field is 'non-free' and not 'nonfree'") license = "non-free" if license in ["free", "non-free", "dep-non-free"]: if not license_mentionned_in_readme(self.path): - print_warning("[YEP-1.3] The use of '%s' in license field implies to " - "write something about the license in your " - "README.md" % (license)) + print_warning( + "[YEP-1.3] The use of '%s' in license field implies " + " to write something about the license in your README.md" % (license) + ) if license in ["non-free", "dep-non-free"]: - print_warning("[YEP-1.3] 'non-free' apps can't be officialized." - "Their integration is still being discussed," - "especially for apps with non-free dependencies") + print_warning( + "[YEP-1.3] 'non-free' apps can't be officialized. " + " Their integration is still being discussed, especially for apps with non-free dependencies" + ) elif code_license not in urlopen(link)['content']: - print_warning("[YEP-1.3] The license '%s' is not registered in " - "https://spdx.org/licenses/ . It can be a typo error. " - "If not, you should replace it by 'free' or 'non-free'" - "and give some explanations in the README.md." % (license)) + print_warning( + "[YEP-1.3] The license '%s' is not registered in https://spdx.org/licenses/ . " + "It can be a typo error. If not, you should replace it by 'free' " + "or 'non-free' and give some explanations in the README.md." % (license) + ) # YEP 1.4 Inform if we continue to maintain the app # YEP 1.5 Update regularly the app status @@ -255,8 +265,7 @@ class App(): is_not_added_to_org = urlopen(repo)['code'] == 404 if is_not_added_to_org: - print_warning("[YEP-1.7] You should add your app in the " - "YunoHost-Apps organisation.") + print_warning("[YEP-1.7] You should add your app in the YunoHost-Apps organisation.") # YEP 1.8 Publish test request # YEP 1.9 Document app @@ -266,10 +275,17 @@ class App(): descr = descr.get("en", None) if descr is None or descr == manifest.get("name", None): - print_warning("[YEP-1.9] You should write a good description of the app, at least in english (1 line is enough).") + print_warning( + "[YEP-1.9] You should write a good description of the app, " + "at least in english (1 line is enough)." + ) elif "for yunohost" in descr.lower(): - print_warning("[YEP-1.9] The 'description' should explain what the app actually does. No need to say that it is 'for YunoHost' - this is a YunoHost app so of course we know it is for YunoHost ;-).") + print_warning( + "[YEP-1.9] The 'description' should explain what the app actually does. " + "No need to say that it is 'for YunoHost' - this is a YunoHost app " + "so of course we know it is for YunoHost ;-)." + ) # TODO test a specific template in README.md @@ -298,18 +314,30 @@ class App(): for argument in manifest["arguments"]["install"]: if "type" not in argument.keys(): - print_warning("[YEP-2.1] You should specify the type of the argument '%s'. You can use : %s." % (argument["name"], ', '.join(recognized_types))) + print_warning( + "[YEP-2.1] You should specify the type of the argument '%s'. " + "You can use : %s." % (argument["name"], ', '.join(recognized_types)) + ) elif argument["type"] not in recognized_types: - print_warning("[YEP-2.1] The type '%s' for argument '%s' is not recognized... it probably doesn't behave as you expect ? Choose among those instead : %s" % (argument["type"], argument["name"], ', '.join(recognized_types))) + print_warning( + "[YEP-2.1] The type '%s' for argument '%s' is not recognized... " + "it probably doesn't behave as you expect ? Choose among those instead : %s" % (argument["type"], argument["name"], ', '.join(recognized_types)) + ) if "choices" in argument.keys(): choices = [c.lower() for c in argument["choices"]] if len(choices) == 2: if ("true" in choices and "false" in choices) or ("yes" in choices and "no" in choices): - print_warning("Argument %s : you might want to simply use a boolean-type argument. No need to specify the choices list yourself." % argument["name"]) + print_warning( + "Argument %s : you might want to simply use a boolean-type argument. " + "No need to specify the choices list yourself." % argument["name"] + ) if "url" in manifest and manifest["url"].endswith("_ynh"): - print_warning("'url' is not meant to be the url of the yunohost package, but rather the website or repo of the upstream app itself...") + print_warning( + "'url' is not meant to be the url of the yunohost package, " + "but rather the website or repo of the upstream app itself..." + ) def check_verifications_done_before_modifying_system(script): @@ -336,9 +364,11 @@ def check_verifications_done_before_modifying_system(script): for modifying_cmd in modifying_cmds: if any(modifying_cmd in cmd for cmd in cmds_before_exit): - print_error("[YEP-2.4] 'ynh_die' or 'exit' command is executed with system modification before (cmd '%s').\n" - "This system modification is an issue if a verification exit the script.\n" - "You should move this verification before any system modification." % modifying_cmd, False) + print_error( + "[YEP-2.4] 'ynh_die' or 'exit' command is executed with system modification before (cmd '%s').\n" + "This system modification is an issue if a verification exit the script.\n" + "You should move this verification before any system modification." % modifying_cmd, False + ) return @@ -353,13 +383,17 @@ def check_set_usage(script): if script.name == "remove": # Remove script shouldn't use set -eu or ynh_abort_if_errors if present: - print_error("[YEP-2.4] set -eu or ynh_abort_if_errors is present. " - "If there is a crash, it could put yunohost system in " - "a broken state. For details, look at " - "https://github.com/YunoHost/issues/issues/419") + print_error( + "[YEP-2.4] set -eu or ynh_abort_if_errors is present. " + "If there is a crash, it could put yunohost system in " + "a broken state. For details, look at " + "https://github.com/YunoHost/issues/issues/419" + ) elif not present: - print_error("[YEP-2.4] ynh_abort_if_errors is missing. For details, " - "look at https://github.com/YunoHost/issues/issues/419") + print_error( + "[YEP-2.4] ynh_abort_if_errors is missing. For details, " + "look at https://github.com/YunoHost/issues/issues/419" + ) def check_helper_usage_dependencies(script): @@ -369,10 +403,16 @@ def check_helper_usage_dependencies(script): """ if script.contains("ynh_package_install") or script.contains("apt-get install"): - print_warning("You should not use `ynh_package_install` or `apt-get install`, use `ynh_install_app_dependencies` instead") + print_warning( + "You should not use `ynh_package_install` or `apt-get install`, " + "use `ynh_install_app_dependencies` instead" + ) if script.contains("ynh_package_remove") or script.contains("apt-get remove"): - print_warning("You should not use `ynh_package_remove` or `apt-get remove`, use `ynh_remove_app_dependencies` instead") + print_warning( + "You should not use `ynh_package_remove` or `apt-get remove`, " + "use `ynh_remove_app_dependencies` instead" + ) def check_helper_consistency(script): @@ -391,7 +431,10 @@ def check_helper_consistency(script): if script.name == "install" and script.contains("yunohost service add"): script2 = Script("remove", os.path.dirname(script.path)) if script2.exists and not script2.contains("yunohost service remove"): - print_error("You used 'yunohost service add' in the install script, but not 'yunohost service remove' in the remove script.") + print_error( + "You used 'yunohost service add' in the install script, " + "but not 'yunohost service remove' in the remove script." + ) def check_deprecated_practices(script): @@ -412,16 +455,29 @@ def check_deprecated_practices(script): if script.contains("sed -i"): print_warning("[YEP-2.12] You should avoid using 'sed -i', please use 'ynh_replace_string' instead") if script.contains("sudo"): - print_warning("[YEP-2.12] You should not need to use 'sudo', the script is being run as root. (If you need to run a command using a specific user, use 'ynh_exec_as')") + print_warning( + "[YEP-2.12] You should not need to use 'sudo', the script is being run as root. " + "(If you need to run a command using a specific user, use 'ynh_exec_as')" + ) if script.contains("dd if=/dev/urandom") or script.contains("openssl rand"): - print_warning("Instead of 'dd if=/dev/urandom' or 'openssl rand', you might want to use ynh_string_random") + print_warning( + "Instead of 'dd if=/dev/urandom' or 'openssl rand', " + "you might want to use ynh_string_random" + ) if script.contains("systemctl restart nginx") or script.contains("service nginx restart"): - print_error("Restarting nginx is quite dangerous (especially for web installs) and should be avoided at all cost. Use 'reload' instead.") + print_error( + "Restarting nginx is quite dangerous (especially for web installs) " + "and should be avoided at all cost. Use 'reload' instead." + ) if script.name == "install" and not script.contains("ynh_print_info") and not script.contains("ynh_script_progression"): - print_warning("Please add a few messages for the user, to explain what is going on (in friendly, not-too-technical terms) during the installation. You can use 'ynh_print_info' or 'ynh_script_progression' for this.") + print_warning( + "Please add a few messages for the user, to explain what is going on " + "(in friendly, not-too-technical terms) during the installation. " + "You can use 'ynh_print_info' or 'ynh_script_progression' for this." + ) class Script(): From 1c8bc4abc4ab526003171435c7cf4c3f7b9d57e8 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 2 Mar 2019 02:10:54 +0100 Subject: [PATCH 6/7] Move script checks as method of class Script --- package_linter.py | 278 +++++++++++++++++++++++----------------------- 1 file changed, 139 insertions(+), 139 deletions(-) diff --git a/package_linter.py b/package_linter.py index fb098fc..07bf89d 100755 --- a/package_linter.py +++ b/package_linter.py @@ -340,145 +340,6 @@ class App(): ) -def check_verifications_done_before_modifying_system(script): - """ - Check if verifications are done before modifying the system - """ - - if not script.contains("ynh_die") and not script.contains("exit"): - return - - # FIXME : this really looks like a very small subset of command that - # can be used ... also packagers are not supposed to use apt or service - # anymore ... - modifying_cmds = ("cp", "mkdir", "rm", "chown", "chmod", "apt-get", "apt", - "service", "find", "sed", "mysql", "swapon", "mount", - "dd", "mkswap", "useradd") - cmds_before_exit = [] - for cmd in script.lines: - cmd = " ".join(cmd) - - if "ynh_die" in cmd or "exit" in cmd: - break - cmds_before_exit.append(cmd) - - for modifying_cmd in modifying_cmds: - if any(modifying_cmd in cmd for cmd in cmds_before_exit): - print_error( - "[YEP-2.4] 'ynh_die' or 'exit' command is executed with system modification before (cmd '%s').\n" - "This system modification is an issue if a verification exit the script.\n" - "You should move this verification before any system modification." % modifying_cmd, False - ) - return - - -def check_set_usage(script): - present = False - - if script.name in ["backup", "remove"]: - present = script.contains("ynh_abort_if_errors") or script.contains("set -eu") - else: - present = script.contains("ynh_abort_if_errors") - - if script.name == "remove": - # Remove script shouldn't use set -eu or ynh_abort_if_errors - if present: - print_error( - "[YEP-2.4] set -eu or ynh_abort_if_errors is present. " - "If there is a crash, it could put yunohost system in " - "a broken state. For details, look at " - "https://github.com/YunoHost/issues/issues/419" - ) - elif not present: - print_error( - "[YEP-2.4] ynh_abort_if_errors is missing. For details, " - "look at https://github.com/YunoHost/issues/issues/419" - ) - - -def check_helper_usage_dependencies(script): - """ - Detect usage of ynh_package_* & apt-get * - and suggest herlpers ynh_install_app_dependencies and ynh_remove_app_dependencies - """ - - if script.contains("ynh_package_install") or script.contains("apt-get install"): - print_warning( - "You should not use `ynh_package_install` or `apt-get install`, " - "use `ynh_install_app_dependencies` instead" - ) - - if script.contains("ynh_package_remove") or script.contains("apt-get remove"): - print_warning( - "You should not use `ynh_package_remove` or `apt-get remove`, " - "use `ynh_remove_app_dependencies` instead" - ) - - -def check_helper_consistency(script): - """ - check if ynh_install_app_dependencies is present in install/upgrade/restore - so dependencies are up to date after restoration or upgrade - """ - - if script.name == "install" and script.contains("ynh_install_app_dependencies"): - - for name in ["upgrade", "restore"]: - script2 = Script(name, os.path.dirname(script.path)) - if script2.exists and not script2.contains("ynh_install_app_dependencies"): - print_warning("ynh_install_app_dependencies should also be in %s script" % name) - - if script.name == "install" and script.contains("yunohost service add"): - script2 = Script("remove", os.path.dirname(script.path)) - if script2.exists and not script2.contains("yunohost service remove"): - print_error( - "You used 'yunohost service add' in the install script, " - "but not 'yunohost service remove' in the remove script." - ) - - -def check_deprecated_practices(script): - - if script.contains("yunohost app setting"): - print_warning("'yunohost app setting' shouldn't be used directly. Please use 'ynh_app_setting_(set,get,delete)' instead.") - if script.contains("yunohost app checkurl"): - print_warning("'yunohost app checkurl' is deprecated. Please use 'ynh_webpath_register' instead.") - if script.contains("yunohost app checkport"): - print_warning("'yunohost app checkport' is deprecated. Please use 'ynh_find_port' instead.") - if script.contains("yunohost app initdb"): - print_warning("'yunohost app initdb' is deprecated. Please use 'ynh_mysql_setup_db' instead.") - if script.contains("exit"): - print_warning("'exit' command shouldn't be used. Please use 'ynh_die' instead.") - - if script.contains("rm -rf"): - print_error("[YEP-2.12] You should avoid using 'rm -rf', please use 'ynh_secure_remove' instead") - if script.contains("sed -i"): - print_warning("[YEP-2.12] You should avoid using 'sed -i', please use 'ynh_replace_string' instead") - if script.contains("sudo"): - print_warning( - "[YEP-2.12] You should not need to use 'sudo', the script is being run as root. " - "(If you need to run a command using a specific user, use 'ynh_exec_as')" - ) - - if script.contains("dd if=/dev/urandom") or script.contains("openssl rand"): - print_warning( - "Instead of 'dd if=/dev/urandom' or 'openssl rand', " - "you might want to use ynh_string_random" - ) - - if script.contains("systemctl restart nginx") or script.contains("service nginx restart"): - print_error( - "Restarting nginx is quite dangerous (especially for web installs) " - "and should be avoided at all cost. Use 'reload' instead." - ) - - if script.name == "install" and not script.contains("ynh_print_info") and not script.contains("ynh_script_progression"): - print_warning( - "Please add a few messages for the user, to explain what is going on " - "(in friendly, not-too-technical terms) during the installation. " - "You can use 'ynh_print_info' or 'ynh_script_progression' for this." - ) - class Script(): def __init__(self, app_path, name): @@ -529,6 +390,145 @@ class Script(): check_deprecated_practices(self) + def check_verifications_done_before_modifying_system(self): + """ + Check if verifications are done before modifying the system + """ + + if not self.contains("ynh_die") and not self.contains("exit"): + return + + # FIXME : this really looks like a very small subset of command that + # can be used ... also packagers are not supposed to use apt or service + # anymore ... + modifying_cmds = ("cp", "mkdir", "rm", "chown", "chmod", "apt-get", "apt", + "service", "find", "sed", "mysql", "swapon", "mount", + "dd", "mkswap", "useradd") + cmds_before_exit = [] + for cmd in self.lines: + cmd = " ".join(cmd) + + if "ynh_die" in cmd or "exit" in cmd: + break + cmds_before_exit.append(cmd) + + for modifying_cmd in modifying_cmds: + if any(modifying_cmd in cmd for cmd in cmds_before_exit): + print_error( + "[YEP-2.4] 'ynh_die' or 'exit' command is executed with system modification before (cmd '%s').\n" + "This system modification is an issue if a verification exit the script.\n" + "You should move this verification before any system modification." % modifying_cmd, False + ) + return + + + def check_set_usage(self): + present = False + + if self.name in ["backup", "remove"]: + present = self.contains("ynh_abort_if_errors") or self.contains("set -eu") + else: + present = self.contains("ynh_abort_if_errors") + + if self.name == "remove": + # Remove script shouldn't use set -eu or ynh_abort_if_errors + if present: + print_error( + "[YEP-2.4] set -eu or ynh_abort_if_errors is present. " + "If there is a crash, it could put yunohost system in " + "a broken state. For details, look at " + "https://github.com/YunoHost/issues/issues/419" + ) + elif not present: + print_error( + "[YEP-2.4] ynh_abort_if_errors is missing. For details, " + "look at https://github.com/YunoHost/issues/issues/419" + ) + + + def check_helper_usage_dependencies(self): + """ + Detect usage of ynh_package_* & apt-get * + and suggest herlpers ynh_install_app_dependencies and ynh_remove_app_dependencies + """ + + if self.contains("ynh_package_install") or self.contains("apt-get install"): + print_warning( + "You should not use `ynh_package_install` or `apt-get install`, " + "use `ynh_install_app_dependencies` instead" + ) + + if self.contains("ynh_package_remove") or self.contains("apt-get remove"): + print_warning( + "You should not use `ynh_package_remove` or `apt-get remove`, " + "use `ynh_remove_app_dependencies` instead" + ) + + + def check_helper_consistency(self): + """ + check if ynh_install_app_dependencies is present in install/upgrade/restore + so dependencies are up to date after restoration or upgrade + """ + + if self.name == "install" and self.contains("ynh_install_app_dependencies"): + + for name in ["upgrade", "restore"]: + script2 = Script(name, os.path.dirname(self.path)) + if script2.exists and not script2.contains("ynh_install_app_dependencies"): + print_warning("ynh_install_app_dependencies should also be in %s script" % name) + + if self.name == "install" and script.contains("yunohost service add"): + srcipt2 = Script("remove", os.path.dirname(self.path)) + if script2.exists and not script2.contains("yunohost service remove"): + print_error( + "You used 'yunohost service add' in the install script, " + "but not 'yunohost service remove' in the remove script." + ) + + + def check_deprecated_practices(self): + + if self.contains("yunohost app setting"): + print_warning("'yunohost app setting' shouldn't be used directly. Please use 'ynh_app_setting_(set,get,delete)' instead.") + if self.contains("yunohost app checkurl"): + print_warning("'yunohost app checkurl' is deprecated. Please use 'ynh_webpath_register' instead.") + if self.contains("yunohost app checkport"): + print_warning("'yunohost app checkport' is deprecated. Please use 'ynh_find_port' instead.") + if self.contains("yunohost app initdb"): + print_warning("'yunohost app initdb' is deprecated. Please use 'ynh_mysql_setup_db' instead.") + if self.contains("exit"): + print_warning("'exit' command shouldn't be used. Please use 'ynh_die' instead.") + + if self.contains("rm -rf"): + print_error("[YEP-2.12] You should avoid using 'rm -rf', please use 'ynh_secure_remove' instead") + if self.contains("sed -i"): + print_warning("[YEP-2.12] You should avoid using 'sed -i', please use 'ynh_replace_string' instead") + if self.contains("sudo"): + print_warning( + "[YEP-2.12] You should not need to use 'sudo', the script is being run as root. " + "(If you need to run a command using a specific user, use 'ynh_exec_as')" + ) + + if self.contains("dd if=/dev/urandom") or self.contains("openssl rand"): + print_warning( + "Instead of 'dd if=/dev/urandom' or 'openssl rand', " + "you might want to use ynh_string_random" + ) + + if self.contains("systemctl restart nginx") or self.contains("service nginx restart"): + print_error( + "Restarting nginx is quite dangerous (especially for web installs) " + "and should be avoided at all cost. Use 'reload' instead." + ) + + if self.name == "install" and not self.contains("ynh_print_info") and not self.contains("ynh_script_progression"): + print_warning( + "Please add a few messages for the user, to explain what is going on " + "(in friendly, not-too-technical terms) during the installation. " + "You can use 'ynh_print_info' or 'ynh_script_progression' for this." + ) + def main(): if len(sys.argv) != 2: print("Give one app package path.") From 1ccebdbab345813819f8d818204667acba6a9ad1 Mon Sep 17 00:00:00 2001 From: Alexandre Aubin Date: Sat, 2 Mar 2019 02:24:13 +0100 Subject: [PATCH 7/7] check_helper_consistency is now an app method instead of script --- package_linter.py | 65 ++++++++++++++++++++--------------------------- 1 file changed, 27 insertions(+), 38 deletions(-) diff --git a/package_linter.py b/package_linter.py index 07bf89d..2883784 100755 --- a/package_linter.py +++ b/package_linter.py @@ -90,12 +90,12 @@ class App(): self.path = path scripts = ["install", "remove", "upgrade", "backup", "restore"] - self.scripts = { f: Script(self.path, f) for f in scripts } - + self.scripts = {f: Script(self.path, f) for f in scripts} def analyze(self): self.misc_file_checks() + self.check_helper_consistency() self.check_source_management() self.check_manifest() @@ -103,7 +103,6 @@ class App(): if script.exists: script.analyze() - def misc_file_checks(self): print_header("MISC FILE CHECKS") @@ -152,6 +151,25 @@ class App(): "and https://github.com/openresty/headers-more-nginx-module#more_set_headers )" ) + def check_helper_consistency(self): + """ + check if ynh_install_app_dependencies is present in install/upgrade/restore + so dependencies are up to date after restoration or upgrade + """ + + install_script = self.scripts["install"] + if install_script.exists: + if install_script.contains("ynh_install_app_dependencies"): + for name in ["upgrade", "restore"]: + if self.scripts[name].exists and not self.scripts[name].contains("ynh_install_app_dependencies"): + print_warning("ynh_install_app_dependencies should also be in %s script" % name) + + if install_script.contains("yunohost service add"): + if self.scripts["remove"].exists and not self.scripts["remove"].contains("yunohost service remove"): + print_error( + "You used 'yunohost service add' in the install script, " + "but not 'yunohost service remove' in the remove script." + ) def check_source_management(self): print_header("SOURCES MANAGEMENT") @@ -167,7 +185,6 @@ class App(): "https://github.com/YunoHost/issues/issues/201#issuecomment-391549262" ) - def check_manifest(self): manifest = os.path.join(self.path, 'manifest.json') if not os.path.exists(manifest): @@ -224,7 +241,7 @@ class App(): print_warning("[YEP-1.2] This app is not registered in official or community applications") # YEP 1.3 License - def license_mentionned_in_readme(): + def license_mentionned_in_readme(path): readme_path = os.path.join(path, 'README.md') if os.path.isfile(readme_path): return "LICENSE" in open(readme_path).read() @@ -368,7 +385,6 @@ class Script(): except Exception as e: print_warning("%s : Could not parse this line (%s) : %s" % (self.path, e, line)) - def contains(self, command): """ Iterate on lines to check if command is contained in line @@ -378,17 +394,14 @@ class Script(): return any(command in line for line in [ ' '.join(line) for line in self.lines]) - def analyze(self): print_header(self.name.upper() + " SCRIPT") - check_verifications_done_before_modifying_system(self) - check_set_usage(self) - check_helper_usage_dependencies(self) - check_helper_consistency(self) - check_deprecated_practices(self) - + self.check_verifications_done_before_modifying_system() + self.check_set_usage() + self.check_helper_usage_dependencies() + self.check_deprecated_practices() def check_verifications_done_before_modifying_system(self): """ @@ -421,7 +434,6 @@ class Script(): ) return - def check_set_usage(self): present = False @@ -445,7 +457,6 @@ class Script(): "look at https://github.com/YunoHost/issues/issues/419" ) - def check_helper_usage_dependencies(self): """ Detect usage of ynh_package_* & apt-get * @@ -464,29 +475,6 @@ class Script(): "use `ynh_remove_app_dependencies` instead" ) - - def check_helper_consistency(self): - """ - check if ynh_install_app_dependencies is present in install/upgrade/restore - so dependencies are up to date after restoration or upgrade - """ - - if self.name == "install" and self.contains("ynh_install_app_dependencies"): - - for name in ["upgrade", "restore"]: - script2 = Script(name, os.path.dirname(self.path)) - if script2.exists and not script2.contains("ynh_install_app_dependencies"): - print_warning("ynh_install_app_dependencies should also be in %s script" % name) - - if self.name == "install" and script.contains("yunohost service add"): - srcipt2 = Script("remove", os.path.dirname(self.path)) - if script2.exists and not script2.contains("yunohost service remove"): - print_error( - "You used 'yunohost service add' in the install script, " - "but not 'yunohost service remove' in the remove script." - ) - - def check_deprecated_practices(self): if self.contains("yunohost app setting"): @@ -529,6 +517,7 @@ class Script(): "You can use 'ynh_print_info' or 'ynh_script_progression' for this." ) + def main(): if len(sys.argv) != 2: print("Give one app package path.")