summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--ganarchy/cli/run_targets.py18
-rw-r--r--ganarchy/core.py7
-rw-r--r--ganarchy/data.py18
-rw-r--r--ganarchy/db.py27
-rw-r--r--ganarchy/templating/templates.py11
5 files changed, 58 insertions, 23 deletions
diff --git a/ganarchy/cli/run_targets.py b/ganarchy/cli/run_targets.py
index eb3fb0c..6b20066 100644
--- a/ganarchy/cli/run_targets.py
+++ b/ganarchy/cli/run_targets.py
@@ -104,19 +104,25 @@ def run_once(out, n_threads, keep_stale_projects):
             for (repo, count) in results:
                 if count is not None:
                     generate_html.append(
-                        (repo.url, repo.message, count, repo.branch)
+                        (repo.url, repo.message, count, repo.branch, repo.pinned)
                     )
                 else:
                     click.echo(repo.url, err=True)
                     click.echo(repo.branch, err=True)
                     click.echo(repo.errormsg, err=True)
+            pinned_entries = []
+            unpinned_entries = []
             html_entries = []
-            for (url, msg, count, branch) in generate_html:
+            for (url, msg, count, branch, pinned) in generate_html:
                 with dblock:
                     history = database.list_repobranch_activity(p.commit, url, branch)
                 # TODO process history into SVG
                 # TODO move this into a separate system
                 # (e.g. ``if project.startswith("svg-"):``)
+                if pinned:
+                    pinned_entries.append((url, msg, "", branch))
+                else:
+                    unpinned_entries.append((url, msg, "", branch))
                 html_entries.append((url, msg, "", branch))
 
             os.makedirs(out + "/project/" + p.commit, exist_ok=True)
@@ -128,6 +134,8 @@ def run_once(out, n_threads, keep_stale_projects):
                     project_body   = p.commit_body,
                     project_commit = p.commit,
                     repos          = html_entries,
+                    pinned_repos   = pinned_entries,
+                    unpinned_repos = unpinned_entries,
                     base_url       = instance.base_url,
                     # I don't think this thing supports deprecating the above?
                     project        = p,
@@ -229,16 +237,16 @@ def cron_target(dry_run, project):
     #    ...
     for (repo, count) in results:
         if count is not None:
-            generate_html.append((repo.url, repo.message, count, repo.branch))
+            generate_html.append((repo.url, repo.message, count, repo.branch, repo.pinned))
         else:
             click.echo(repo.errormsg, err=True)
     html_entries = []
-    for (url, msg, count, branch) in generate_html:
+    for (url, msg, count, branch, pinned) in generate_html:
         history = database.list_repobranch_activity(project, url, branch)
         # TODO process history into SVG
         # TODO move this into a separate system
         # (e.g. ``if project.startswith("svg-"):``)
-        html_entries.append((url, msg, "", branch))
+        html_entries.append((url, msg, "", branch, pinned))
 
     template = env.get_template('project.html')
     click.echo(
diff --git a/ganarchy/core.py b/ganarchy/core.py
index 872705c..d162dff 100644
--- a/ganarchy/core.py
+++ b/ganarchy/core.py
@@ -45,7 +45,7 @@ class Repo:
     """
     # TODO fill in Attributes.
 
-    def __init__(self, dbconn, project_commit, url, branch, head_commit):
+    def __init__(self, dbconn, project_commit, url, branch, head_commit, pinned):
         self.url = url
         self.branch = branch
         self.project_commit = project_commit
@@ -55,6 +55,7 @@ class Repo:
         self.hash = None
         self.branchname = None
         self.head = None
+        self.pinned = pinned
 
         if not self._check_branch(GIT):
             return
@@ -180,9 +181,9 @@ class Project:
         """
         repos = []
         with self._dblock:
-            for url, branch, head_commit in self._dbconn.list_repobranches(self.commit):
+            for url, branch, head_commit, pinned in self._dbconn.list_repobranches(self.commit):
                 repos.append(
-                    Repo(self._dbconn, self.commit, url, branch, head_commit)
+                    Repo(self._dbconn, self.commit, url, branch, head_commit, pinned)
                 )
         self.repos = repos
 
diff --git a/ganarchy/data.py b/ganarchy/data.py
index 36c32d9..b497176 100644
--- a/ganarchy/data.py
+++ b/ganarchy/data.py
@@ -89,7 +89,8 @@ _MATCHER_REPOS = abdl.compile("""->'projects':$dict
                                      ->url[:?$str:?$uri]:?$dict
                                        ->branch:?$dict
                                          (->active'active'?:?$bool)
-                                         (->federate'federate'?:?$bool)?""",
+                                         (->federate'federate'?:?$bool)?
+                                         (->pinned'pinned'?:?$bool)?""",
                               dict(bool=bool, dict=dict, str=str, uri=URIPredicate(), commit=CommitPredicate()))
 _MATCHER_REPO_LIST_SRCS = abdl.compile("""->'repo_list_srcs':$dict
                                             ->src[:?$str:?$uri]:?$dict
@@ -157,6 +158,10 @@ class PCTP(OverridableProperty):
     def federate(self):
         return self.options.get('federate', True)
 
+    @property
+    def pinned(self):
+        return self.options.get('pinned', False)
+
 class RepoListSource(OverridableProperty):
     """A source for a repo list.
 
@@ -273,7 +278,7 @@ class ObjectDataSource(DataSource):
     _SUPPORTED_PROPERTIES = {
                                 DataProperty.INSTANCE_TITLE: lambda obj: (d['title'][1] for d in _MATCHER_TITLE.match(obj)),
                                 DataProperty.INSTANCE_BASE_URL: lambda obj: (d['base_url'][1] for d in _MATCHER_BASE_URL.match(obj)),
-                                DataProperty.VCS_REPOS: lambda obj: (PCTP(r['commit'][0], r['url'][0], r['branch'][0], {k: v[1] for k, v in r.items() if k in {'active', 'federate'}}) for r in _MATCHER_REPOS.match(obj)),
+                                DataProperty.VCS_REPOS: lambda obj: (PCTP(r['commit'][0], r['url'][0], r['branch'][0], {k: v[1] for k, v in r.items() if k in {'active', 'federate', 'pinned'}}) for r in _MATCHER_REPOS.match(obj)),
                                 DataProperty.REPO_LIST_SOURCES: lambda obj: (RepoListSource(d['src'][0], d['src'][1]) for d in _MATCHER_REPO_LIST_SRCS.match(obj)),
                             }
 
@@ -511,10 +516,11 @@ class RepoListManager(DataSource):
                 else:
                     for pctp in iterator:
                         # but repo lists aren't allowed to override anything
-                        try:
-                            del pctp.options['federate']
-                        except KeyError:
-                            pass
+                        for filtered in ['federate', 'pinned']:
+                            try:
+                                del pctp.options[filtered]
+                            except KeyError:
+                                pass
                         if pctp.active:
                             yield pctp
 
diff --git a/ganarchy/db.py b/ganarchy/db.py
index 14d0d47..a8bcc8d 100644
--- a/ganarchy/db.py
+++ b/ganarchy/db.py
@@ -164,7 +164,8 @@ class Database:
                 "active" INT,
                 "branch" TEXT,
                 "project" TEXT,
-                "federate" INT
+                "federate" INT,
+                "pinned" INT
             )
         ''')
         c.execute('''
@@ -184,8 +185,8 @@ class Database:
         ):
             if repo.active:
                 c.execute(
-                    '''INSERT INTO "repos" VALUES (?, ?, ?, ?, ?)''',
-                    (repo.uri, 1, repo.branch, repo.project_commit, int(repo.federate))
+                    '''INSERT INTO "repos" VALUES (?, ?, ?, ?, ?, ?)''',
+                    (repo.uri, 1, repo.branch, repo.project_commit, int(repo.federate), int(repo.pinned))
                 )
         self.conn.commit()
         c.close()
@@ -259,9 +260,14 @@ class Database:
         """
         c = self.conn.cursor()
         try:
-            for (e, url, branch, head_commit) in c.execute(
+            for (e, url, branch, head_commit, pinned) in c.execute(
                 '''
-                    SELECT "max"("e"), "url", "branch", "head_commit"
+                    SELECT
+                        "max"("e"),
+                        "url",
+                        "branch",
+                        "head_commit",
+                        "pinned"
                     FROM (
                         SELECT
                             "max"("T1"."entry") "e",
@@ -282,13 +288,20 @@ class Database:
                         SELECT null, "T3"."url", "T3"."branch", null
                         FROM "repos" "T3"
                         WHERE "active" AND "project" IS ?1
-                    )
+                    ) JOIN (
+                        SELECT
+                            "T4"."url" "purl",
+                            "T4"."branch" "pbranch",
+                            "T4"."pinned"
+                        FROM "repos" "T4"
+                        WHERE "project" IS ?1
+                    ) ON ("url" IS "purl" AND "branch" IS "pbranch")
                     GROUP BY "url", "branch"
                     ORDER BY "e"
                 ''',
                 (project_commit,)
             ):
-                yield url, branch, head_commit
+                yield url, branch, head_commit, pinned
         finally:
             c.close()
 
diff --git a/ganarchy/templating/templates.py b/ganarchy/templating/templates.py
index 1e9c074..1574d7c 100644
--- a/ganarchy/templating/templates.py
+++ b/ganarchy/templating/templates.py
@@ -70,7 +70,7 @@ def get_template_loader():
 
 {%- for project in database.list_projects() %}
 [projects.{{project}}]
-{%- for repo_url, branch, _head_commit in database.list_repobranches(project) %}
+{%- for repo_url, branch, _head_commit, _pinned in database.list_repobranches(project) %}
 {%- if database.should_repo_federate(project, repo_url, branch) %}
 "{{repo_url|tomle}}".{% if not branch %}HEAD{% else %}"{{branch|tomle}}"{% endif %} = { active=true }
 {%- endif %}
@@ -108,8 +108,15 @@ def get_template_loader():
         <h1>{{ project_title|e }}</h1>
         <p>Tracking <span id="project_commit"><a href="web+ganarchy:{{ project_commit }}">{{ project_commit }}</a></span></p>
         <div id="project_body"><p>{{ project_body|e|replace("\n\n", "</p><p>") }}</p></div>
+        <h2>Pinned repos</h2>
         <ul>
-        {% for url, msg, img, branch in repos -%}
+        {% for url, msg, img, branch in pinned_repos -%}
+            <li><a href="{{ url|e }}">{{ url|e }}</a>{% if branch %} <span class="branchname">[{{ branch|e }}]</span>{% endif %}: {{ msg|e }}</li>
+        {% endfor -%}
+        </ul>
+        <h2>Additional repos</h2>
+        <ul>
+        {% for url, msg, img, branch in unpinned_repos -%}
             <li><a href="{{ url|e }}">{{ url|e }}</a>{% if branch %} <span class="branchname">[{{ branch|e }}]</span>{% endif %}: {{ msg|e }}</li>
         {% endfor -%}
         </ul>