summary refs log tree commit diff stats
path: root/ganarchy
diff options
context:
space:
mode:
Diffstat (limited to 'ganarchy')
-rw-r--r--ganarchy/__init__.py21
-rw-r--r--ganarchy/__main__.py1
-rw-r--r--ganarchy/cli/run_targets.py61
-rw-r--r--ganarchy/core.py61
-rw-r--r--ganarchy/db.py2
-rw-r--r--ganarchy/git.py12
-rw-r--r--ganarchy/templating/templates.py11
7 files changed, 90 insertions, 79 deletions
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 <https://www.gnu.org/licenses/>.
 
-#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 <https://www.gnu.org/licenses/>.
 
+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():
         <h1>{{ ganarchy.title|e }}</h1>
         <p>This is {{ ganarchy.title|e }}. Currently tracking the following projects:</p>
         <ul>
-        {% for project in ganarchy.projects -%}
+        {% for project in ganarchy.projects -%}{% if project.exists -%}
             <li><a href="/project/{{ project.commit|e }}">{{ project.title|e }}</a>: {{ project.description|e }}</li>
-        {% endfor -%}
+        {% endif -%}{% endfor -%}
         </ul>
         <p>Powered by <a href="https://ganarchy.autistic.space/">GAnarchy</a>. AGPLv3-licensed. <a href="https://cybre.tech/SoniEx2/ganarchy">Source Code</a>.</p>
         <p>
@@ -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 -%}
 """,