From 6e3ac343e67adea503afef98651ea134526e0453 Mon Sep 17 00:00:00 2001 From: SoniEx2 Date: Sun, 19 Jul 2020 22:06:00 -0300 Subject: Partially restore cron-target functionality Restored functionality: - Can use `config`, `project-list` and `index` targets Still broken: - `cron-target` with a project doesn't work yet --- ganarchy/__init__.py | 21 -------------- ganarchy/__main__.py | 1 + ganarchy/cli/run_targets.py | 61 +++++++++++++++++++++++++--------------- ganarchy/core.py | 61 ++++++++++++++++++++++------------------ ganarchy/db.py | 2 +- ganarchy/git.py | 12 ++++++-- ganarchy/templating/templates.py | 11 ++++---- 7 files changed, 90 insertions(+), 79 deletions(-) (limited to 'ganarchy') diff --git a/ganarchy/__init__.py b/ganarchy/__init__.py index 206bac9..fdb6788 100644 --- a/ganarchy/__init__.py +++ b/ganarchy/__init__.py @@ -14,24 +14,3 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . -#import abc -#import builtins -#import hashlib -#import hmac -#import os -#import re -#import sqlite3 -#import subprocess -# -#import click -#import jinja2 -#import qtoml -#import requests -# -#from collections import defaultdict -#from urllib.parse import urlparse -# -#import ganarchy as m_ganarchy -#import ganarchy.dirs -#import ganarchy.git - diff --git a/ganarchy/__main__.py b/ganarchy/__main__.py index 1bab5d1..63e55ed 100644 --- a/ganarchy/__main__.py +++ b/ganarchy/__main__.py @@ -24,5 +24,6 @@ import ganarchy import ganarchy.cli.db import ganarchy.cli.debug import ganarchy.cli.merge_configs +import ganarchy.cli.run_targets ganarchy.cli.main(prog_name='ganarchy') diff --git a/ganarchy/cli/run_targets.py b/ganarchy/cli/run_targets.py index 5bf48d9..5e2f8c0 100644 --- a/ganarchy/cli/run_targets.py +++ b/ganarchy/cli/run_targets.py @@ -17,9 +17,15 @@ """This module contains the CLI Run Targets. """ +import os + import click from ganarchy import cli +from ganarchy import core +from ganarchy import data +from ganarchy import db +from ganarchy import dirs from ganarchy.templating import environment #@cli.main.command() @@ -35,7 +41,7 @@ from ganarchy.templating import environment # - post_update_cycle_hook - executed after all objects in an update cycle are updated.""" # pass -@ganarchy.command() +@cli.main.command() @click.option('--update/--no-update', default=True) @click.argument('project', required=False) def cron_target(update, project): @@ -44,41 +50,52 @@ def cron_target(update, project): "Deprecated". Useful if you want full control over how GAnarchy generates the pages. """ - #conf = None - ## reverse order is intentional - #for d in reversed(config_dirs): - # try: - # conf = Config(open(d + "/config.toml", 'r', encoding='utf-8', newline=''), conf) - # except (OSError, UnicodeDecodeError, qtoml.decoder.TOMLDecodeError): - # pass - #with open(config_home + "/config.toml", 'r', encoding='utf-8', newline='') as f: - # conf = Config(f, conf) - env = get_env() + # create config objects + conf = data.ConfigManager.new_default() + effective_conf = data.EffectiveSource(conf) + repos = data.RepoListManager(effective_conf) + effective_repos = data.EffectiveSource(repos) + + # load config and repo data + effective_repos.update() + database = db.connect_database(effective_conf) + database.load_repos(effective_repos) + + # load template environment + env = environment.get_env() + + # handle config and project list if project == "config": # render the config - # doesn't have access to a GAnarchy object. this is deliberate. template = env.get_template('index.toml') - click.echo(template.render(config = conf)) + click.echo(template.render(database=database)) return if project == "project-list": # could be done with a template but eh w/e, this is probably better - for project in conf.projects.keys(): + for project in database.list_projects(): click.echo(project) return + # make sure the cache dir exists - os.makedirs(cache_home, exist_ok=True) + os.makedirs(dirs.CACHE_HOME, exist_ok=True) + # make sure it is a git repo - subprocess.call(["git", "-C", cache_home, "init", "-q"]) - conn = sqlite3.connect(data_home + "/ganarchy.db") - instance = GAnarchy(conn, conf, list_projects=project in ["index", "config"]) + core.GIT.create() + + instance = core.GAnarchy(database, effective_conf) + + if not instance.base_url or not project: + click.echo("No base URL or project commit specified", err=True) + return + if project == "index": + instance.load_projects() # render the index template = env.get_template('index.html') - click.echo(template.render(ganarchy = instance)) - return - if not instance.base_url or not project: - click.echo("No base URL or project commit specified", err=True) + click.echo(template.render(ganarchy=instance)) return + + # FIXME this should be in core, as it belongs to core logic! entries = [] generate_html = [] c = conn.cursor() diff --git a/ganarchy/core.py b/ganarchy/core.py index cf5edd4..3bdd820 100644 --- a/ganarchy/core.py +++ b/ganarchy/core.py @@ -14,8 +14,12 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see . +import re +from urllib import parse + import ganarchy.git import ganarchy.dirs +import ganarchy.data # Currently we only use one git repo, at CACHE_HOME # TODO optimize @@ -90,6 +94,8 @@ class Repo: return None class Project: + # FIXME add docs + def __init__(self, dbconn, project_commit, list_repos=False): self.commit = project_commit self.refresh_metadata() @@ -117,10 +123,12 @@ class Project: project_title, project_desc = ("Error parsing project commit",)*2 # if project_desc: # FIXME # project_desc = project_desc.strip() + self.exists = True self.commit_body = project self.title = project_title self.description = project_desc except ganarchy.git.GitError: + self.exists = False self.commit_body = None self.title = None self.description = None @@ -132,34 +140,33 @@ class Project: return results class GAnarchy: - def __init__(self, dbconn, config, list_projects=False, list_repos=False): - base_url = config.base_url - title = config.title - if not base_url: + # FIXME add docs + + def __init__(self, dbconn, config): + try: + base_url = config.get_property_value( + ganarchy.data.DataProperty.INSTANCE_BASE_URL + ) + except LookupError: # FIXME use a more appropriate error type raise ValueError - if not title: - title = "GAnarchy on " + urlparse(base_url).hostname + + try: + title = config.get_property_value( + ganarchy.data.DataProperty.INSTANCE_TITLE + ) + except LookupError: + title = "GAnarchy on " + parse.urlparse(base_url).hostname + self.title = title self.base_url = base_url - # load config onto DB - c = dbconn.cursor() - c.execute('''CREATE TEMPORARY TABLE "repos" ("url" TEXT PRIMARY KEY, "active" INT, "branch" TEXT, "project" TEXT)''') - c.execute('''CREATE UNIQUE INDEX "temp"."repos_url_branch_project" ON "repos" ("url", "branch", "project")''') - c.execute('''CREATE INDEX "temp"."repos_project" ON "repos" ("project")''') - c.execute('''CREATE INDEX "temp"."repos_active" ON "repos" ("active")''') - for (project_commit, repos) in config.projects.items(): - for (repo_url, branches) in repos.items(): - for (branchname, options) in branches.items(): - if options['active']: # no need to insert inactive repos since they get ignored anyway - c.execute('''INSERT INTO "repos" VALUES (?, ?, ?, ?)''', (repo_url, 1, branchname, project_commit)) - dbconn.commit() - if list_projects: - projects = [] - with dbconn: - for (project,) in dbconn.execute('''SELECT DISTINCT "project" FROM "repos" '''): - projects.append(Project(dbconn, project, list_repos=list_repos)) - projects.sort(key=lambda project: project.title) # sort projects by title - self.projects = projects - else: - self.projects = None + self.projects = None + self.dbconn = dbconn + + def load_projects(self, list_repos=False): + # FIXME add docs, get rid of list_repos + projects = [] + for project in self.dbconn.list_projects(): + projects.append(Project(self.dbconn, project, list_repos=list_repos)) + projects.sort(key=lambda p: p.title or "") # sort projects by title + self.projects = projects diff --git a/ganarchy/db.py b/ganarchy/db.py index f16081a..37509a5 100644 --- a/ganarchy/db.py +++ b/ganarchy/db.py @@ -332,5 +332,5 @@ def connect_database(effective_config): for the config. """ del effective_config # currently unused, intended for the future - conn = sqlite3.connect(ganarchy.dirs.data_home + "/ganarchy.db") + conn = sqlite3.connect(ganarchy.dirs.DATA_HOME + "/ganarchy.db") return Database(conn) diff --git a/ganarchy/git.py b/ganarchy/git.py index 25be04a..a658022 100644 --- a/ganarchy/git.py +++ b/ganarchy/git.py @@ -34,6 +34,14 @@ class Git: self.path = path self.base = ("git", "-C", path) + def create(self): + """Creates the local repo. + + Can safely be called on an existing repo. + """ + subprocess.call(self.base + ("init", "-q")) + + def check_history(self, local_head, commit): """Checks if the local head contains commit in its history. Raises if it doesn't. @@ -69,7 +77,7 @@ class Git: """ try: subprocess.check_output( - base + ("fetch", "-q", url, "+" + remote_head + ":" + local_head), + self.base + ("fetch", "-q", url, "+" + remote_head + ":" + local_head), stderr=subprocess.STDOUT ) except subprocess.CalledProcessError as e: @@ -89,7 +97,7 @@ class Git: """ try: res = subprocess.check_output( - base + ("rev-list", "--count", first_hash + ".." + last_hash, "--"), + self.base + ("rev-list", "--count", first_hash + ".." + last_hash, "--"), stderr=subprocess.DEVNULL ).decode("utf-8").strip() return int(res) diff --git a/ganarchy/templating/templates.py b/ganarchy/templating/templates.py index 0f691e0..213a7fa 100644 --- a/ganarchy/templating/templates.py +++ b/ganarchy/templating/templates.py @@ -53,9 +53,9 @@ def get_template_loader():

{{ ganarchy.title|e }}

This is {{ ganarchy.title|e }}. Currently tracking the following projects:

    - {% for project in ganarchy.projects -%} + {% for project in ganarchy.projects -%}{% if project.exists -%}
  • {{ project.title|e }}: {{ project.description|e }}
  • - {% endfor -%} + {% endif -%}{% endfor -%}

Powered by GAnarchy. AGPLv3-licensed. Source Code.

@@ -67,11 +67,10 @@ def get_template_loader(): ## index.toml 'index.toml': """# Generated by GAnarchy -{%- for project, repos in config.projects.items() %} +{%- for project in database.list_projects() %} [projects.{{project}}] -{%- for repo_url, branches in repos.items() %}{% for branch, options in branches.items() %}{% if options.active %} -"{{repo_url|tomle}}".{% if branch %}"{{branch|tomle}}"{% else %}HEAD{% endif %} = { active=true } -{%- endif %}{% endfor %} +{%- for repo_url, branch, _head_commit in database.list_repobranches(project) %} +"{{repo_url|tomle}}".{% if branch == "HEAD" %}HEAD{% else %}"{{branch|tomle}}"{% endif %} = { active=true } {%- endfor %} {% endfor -%} """, -- cgit 1.4.1