From 009d8bd5c7483d0fd27876a9e60dd93dec1d76a0 Mon Sep 17 00:00:00 2001
From: Klaus Koder <klauskoder@pagure.local>
Date: Dec 04 2025 16:21:00 +0000
Subject: [PATCH 1/10] Update pygit-object handling


* <git>.oid with <git>.id
* replace <git>.oid.hex with str() method

---

diff --git a/pagure/api/fork.py b/pagure/api/fork.py
index 55553a4..d158413 100644
--- a/pagure/api/fork.py
+++ b/pagure/api/fork.py
@@ -1601,14 +1601,14 @@ def api_pull_request_create(repo, username=None, namespace=None):
                 )
 
     if orig_commit:
-        orig_commit = orig_commit.oid.hex
+        orig_commit = str(orig_commit.oid)
 
     initial_comment = form.initial_comment.data.strip() or None
 
     commit_start = commit_stop = None
     if diff_commits:
-        commit_stop = diff_commits[0].oid.hex
-        commit_start = diff_commits[-1].oid.hex
+        commit_stop = str(diff_commits[0].oid)
+        commit_start = str(diff_commits[-1].oid)
 
     request = pagure.lib.query.new_pull_request(
         flask.g.session,
@@ -1720,7 +1720,7 @@ def api_pull_request_diffstats(repo, requestid, username=None, namespace=None):
         try:
             for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_NONE):
                 diff_commits.append(commit)
-                if commit.oid.hex == request.commit_start:
+                if str(commit.oid) == request.commit_start:
                     break
         except KeyError:
             # This happens when repo.walk() cannot find commitid
@@ -1729,19 +1729,19 @@ def api_pull_request_diffstats(repo, requestid, username=None, namespace=None):
         if diff_commits:
             # Ensure the first commit in the PR as a parent, otherwise
             # point to it
-            start = diff_commits[-1].oid.hex
+            start = str(diff_commits[-1].oid)
             if diff_commits[-1].parents:
-                start = diff_commits[-1].parents[0].oid.hex
+                start = str(diff_commits[-1].parents[0].oid)
 
             # If the start and the end commits are the same, it means we are,
             # dealing with one commit that has no parent, so just diff that
             # one commit
-            if start == diff_commits[0].oid.hex:
+            if start == str(diff_commits[0].oid):
                 diff = diff_commits[0].tree.diff_to_tree(swap=True)
             else:
                 diff = repo_obj.diff(
                     repo_obj.revparse_single(start),
-                    repo_obj.revparse_single(diff_commits[0].oid.hex),
+                    repo_obj.revparse_single(str(diff_commits[0].oid)),
                 )
     else:
         try:
diff --git a/pagure/internal/__init__.py b/pagure/internal/__init__.py
index 306605a..897681e 100644
--- a/pagure/internal/__init__.py
+++ b/pagure/internal/__init__.py
@@ -612,20 +612,20 @@ def get_branches_of_commit():
 
             if compare_branch:
                 merge_commit_obj = repo_obj.merge_base(
-                    compare_branch.peel().hex, branch.peel().hex
+                    str(compare_branch.peel().id), str(branch.peel().id)
                 )
 
                 if merge_commit_obj:
-                    merge_commit = merge_commit_obj.hex
+                    merge_commit = str(merge_commit_obj.id)
 
-            repo_commit = repo_obj[branch.peel().hex]
+            repo_commit = repo_obj[str(branch.peel().id)]
 
             for commit in repo_obj.walk(
-                repo_commit.oid.hex, pygit2.GIT_SORT_NONE
+                str(repo_commit.id), pygit2.GIT_SORT_NONE
             ):
-                if commit.oid.hex == merge_commit:
+                if str(commit.id) == merge_commit:
                     break
-                if commit.oid.hex == commit_id:
+                if str(commit.id) == commit_id:
                     branches.append(branchname)
                     break
 
@@ -696,7 +696,7 @@ def get_branches_head():
     if not repo_obj.is_empty and len(repo_obj.listall_branches()) > 1:
         for branchname in repo_obj.listall_branches():
             branch = repo_obj.lookup_branch(branchname)
-            branches[branchname] = branch.peel().hex
+            branches[branchname] = str(branch.peel().id)
 
     # invert the dict
     heads = collections.defaultdict(list)
diff --git a/pagure/lib/git.py b/pagure/lib/git.py
index df97de2..f4c03ab 100644
--- a/pagure/lib/git.py
+++ b/pagure/lib/git.py
@@ -127,7 +127,7 @@ Subject: {subject}
 
 {patch}
 """.format(
-                    commit=commit.oid.hex,
+                    commit=str(commit.id),
                     author_name=commit.author.name,
                     author_email=commit.author.email,
                     date=datetime.datetime.utcfromtimestamp(
@@ -272,7 +272,7 @@ def _update_git(obj, repo):
         # See if there is a parent to this commit
         parent = None
         try:
-            parent = new_repo.head.peel().oid
+            parent = new_repo.head.peel().id
         except pygit2.GitError:
             pass
 
@@ -343,7 +343,7 @@ def _clean_git(repo, obj_repotype, obj_uid):
         # See if there is a parent to this commit
         parent = None
         if not new_repo.is_empty:
-            parent = new_repo.head.peel().oid
+            parent = new_repo.head.peel().id
 
         parents = []
         if parent:
@@ -942,7 +942,7 @@ def _add_file_to_git(repo, issue, attachmentfolder, user, filename):
         # See if there is a parent to this commit
         parent = None
         try:
-            parent = new_repo.head.peel().oid
+            parent = new_repo.head.peel().id
         except pygit2.GitError:
             pass
 
@@ -1085,7 +1085,7 @@ class TemporaryClone(object):
                 self.repo.branches.local.create(localname, branch.peel())
             elif ref.startswith("refs/pull/"):
                 reference = self._origrepo.references.get(ref)
-                self.repo.references.create(ref, reference.peel().oid.hex)
+                self.repo.references.create(ref, str(reference.peel().id))
 
         return self
 
@@ -1307,7 +1307,7 @@ def _update_file_in_git(
 
         parents = []
         if parent:
-            parents.append(parent.hex)
+            parents.append(str(parent.id))
 
         # Author/commiter will always be this one
         name = user.fullname or user.username
@@ -1735,7 +1735,7 @@ def merge_pull_request(session, request, username, domerge=True):
             remote.fetch()
 
             # repo_commit = fork_obj[branch.peel().hex]
-            repo_commit = new_repo[branch.peel().hex]
+            repo_commit = new_repo[str(branch.peel().id)]
 
             # Checkout the correct branch
             if new_repo.is_empty or new_repo.head_is_unborn:
@@ -1748,7 +1748,7 @@ def merge_pull_request(session, request, username, domerge=True):
                     _log.info("  PR merged using fast-forward")
                     if not request.project.settings.get("always_merge", False):
                         new_repo.create_branch(request.branch, repo_commit)
-                        commit = repo_commit.oid.hex
+                        commit = str(repo_commit.id)
                     else:
                         tree = new_repo.index.write_tree()
                         user_obj = pagure.lib.query.get_user(session, username)
@@ -1762,7 +1762,7 @@ def merge_pull_request(session, request, username, domerge=True):
                             author,
                             "Merge #%s `%s`" % (request.id, request.title),
                             tree,
-                            [repo_commit.oid.hex],
+                            [str(repo_commit.id)],
                         )
 
                     _log.info("  New head: %s", commit)
@@ -1793,14 +1793,14 @@ def merge_pull_request(session, request, username, domerge=True):
                 ref = new_repo.lookup_reference(
                     "refs/pull/%s/head" % request.id
                 )
-                repo_commit = new_repo[ref.target.hex]
+                repo_commit = new_repo[str(ref.target.id)]
             except KeyError:
                 pass
 
-        merge = new_repo.merge(repo_commit.oid)
+        merge = new_repo.merge(repo_commit.id)
         _log.debug("  Merge: %s", merge)
         if merge is None:
-            mergecode = new_repo.merge_analysis(repo_commit.oid)[0]
+            mergecode = new_repo.merge_analysis(repo_commit.id)[0]
             _log.debug("  Mergecode: %s", mergecode)
 
         # Wait until the last minute then check if the PR was already closed
@@ -1851,8 +1851,8 @@ def merge_pull_request(session, request, username, domerge=True):
                         # This is depending on the pygit2 version
                         branch_ref.target = merge.fastforward_oid
                     elif merge is None and mergecode is not None:
-                        branch_ref.set_target(repo_commit.oid.hex)
-                    commit = repo_commit.oid.hex
+                        branch_ref.set_target(str(repo_commit.id))
+                    commit = str(repo_commit.id)
                 else:
                     tree = new_repo.index.write_tree()
                     user_obj = pagure.lib.query.get_user(session, username)
@@ -1879,7 +1879,7 @@ def merge_pull_request(session, request, username, domerge=True):
                         author,
                         commit_message,
                         tree,
-                        [head.hex, repo_commit.oid.hex],
+                        [str(head.id), str(repo_commit.id)],
                     )
 
                 _log.info("  New head: %s", commit)
@@ -1924,7 +1924,7 @@ def merge_pull_request(session, request, username, domerge=True):
                 _log.info("  Writing down merge commit")
                 head = new_repo.lookup_reference("HEAD").peel()
                 _log.info(
-                    "  Basing on: %s - %s", head.hex, repo_commit.oid.hex
+                    "  Basing on: %s - %s", str(head.id), str(repo_commit.id)
                 )
                 user_obj = pagure.lib.query.get_user(session, username)
                 commitname = user_obj.fullname or user_obj.user
@@ -1945,7 +1945,7 @@ def merge_pull_request(session, request, username, domerge=True):
                     author,
                     commit_message,
                     tree,
-                    [head.hex, repo_commit.oid.hex],
+                    [str(head.id), str(repo_commit.id)],
                 )
 
                 _log.info("  New head: %s", commit)
@@ -2151,13 +2151,13 @@ def get_diff_info(repo_obj, orig_repo, branch_from, branch_to, prid=None):
 
     commitid = None
     if frombranch:
-        commitid = frombranch.peel().hex
+        commitid = str(frombranch.peel().id)
     elif prid is not None:
         # If there is not branch found but there is a PR open, use the ref
         # of that PR in the main repo
         try:
             ref = orig_repo.lookup_reference("refs/pull/%s/head" % prid)
-            commitid = ref.target.hex
+            commitid = str(ref.target.id)
         except KeyError:
             pass
 
@@ -2179,14 +2179,14 @@ def get_diff_info(repo_obj, orig_repo, branch_from, branch_to, prid=None):
             "pagure.lib.git.get_diff_info: Pulling into a non-empty repo"
         )
         if branch:
-            orig_commit = orig_repo[branch.peel().hex]
+            orig_commit = orig_repo[str(branch.peel().id)]
             main_walker = orig_repo.walk(
-                orig_commit.oid.hex, pygit2.GIT_SORT_NONE
+                str(orig_commit.id), pygit2.GIT_SORT_NONE
             )
 
         repo_commit = repo_obj[commitid]
         branch_walker = repo_obj.walk(
-            repo_commit.oid.hex, pygit2.GIT_SORT_NONE
+            str(repo_commit.id), pygit2.GIT_SORT_NONE
         )
 
         main_commits = set()
@@ -2197,7 +2197,7 @@ def get_diff_info(repo_obj, orig_repo, branch_from, branch_to, prid=None):
             if branch:
                 try:
                     com = next(main_walker)
-                    main_commits.add(com.oid.hex)
+                    main_commits.add(str(com.id))
                 except StopIteration:
                     com = None
 
@@ -2211,7 +2211,7 @@ def get_diff_info(repo_obj, orig_repo, branch_from, branch_to, prid=None):
                 break
 
             if branch_commit:
-                branch_commits.add(branch_commit.oid.hex)
+                branch_commits.add(str(branch_commit.id))
                 diff_commits.append(branch_commit)
             if main_commits.intersection(branch_commits):
                 break
@@ -2221,19 +2221,19 @@ def get_diff_info(repo_obj, orig_repo, branch_from, branch_to, prid=None):
         i = 0
         if diff_commits and main_commits:
             for i in range(len(diff_commits)):
-                if diff_commits[i].oid.hex in main_commits:
+                if str(diff_commits[i].id) in main_commits:
                     break
             diff_commits = diff_commits[:i]
 
         _log.debug("Diff commits: %s", diff_commits)
         if diff_commits:
-            first_commit = repo_obj[diff_commits[-1].oid.hex]
+            first_commit = repo_obj[str(diff_commits[-1].id)]
             if len(first_commit.parents) > 0:
                 diff = repo_obj.diff(
-                    repo_obj.revparse_single(first_commit.parents[0].oid.hex),
-                    repo_obj.revparse_single(diff_commits[0].oid.hex),
+                    repo_obj.revparse_single(str(first_commit.parents[0].id)),
+                    repo_obj.revparse_single(str(diff_commits[0].id)),
                 )
-            elif first_commit.oid.hex == diff_commits[0].oid.hex:
+            elif str(first_commit.id) == str(diff_commits[0].id):
                 _log.info(
                     "pagure.lib.git.get_diff_info: First commit is also the "
                     "last commit"
@@ -2248,7 +2248,7 @@ def get_diff_info(repo_obj, orig_repo, branch_from, branch_to, prid=None):
             branch = repo_obj.lookup_branch(branch_from)
             repo_commit = branch.peel()
 
-        for commit in repo_obj.walk(repo_commit.oid.hex, pygit2.GIT_SORT_NONE):
+        for commit in repo_obj.walk(str(repo_commit.id), pygit2.GIT_SORT_NONE):
             diff_commits.append(commit)
 
         _log.debug("Diff commits: %s", diff_commits)
@@ -2309,8 +2309,8 @@ def diff_pull_request(
         # Check if we can still rely on the merge_status
         commenttext = None
         if (
-            request.commit_start != first_commit.oid.hex
-            or request.commit_stop != diff_commits[0].oid.hex
+            request.commit_start != str(first_commit.id)
+            or request.commit_stop != str(diff_commits[0].id)
         ):
             request.merge_status = None
             if request.commit_start:
@@ -2318,7 +2318,7 @@ def diff_pull_request(
                 new_commits_count = 0
                 commenttext = ""
                 for i in diff_commits:
-                    if i.oid.hex == request.commit_stop:
+                    if str(i.id) == request.commit_stop:
                         break
                     new_commits_count = new_commits_count + 1
                     commenttext = "%s * ``%s``\n" % (
@@ -2337,15 +2337,15 @@ def diff_pull_request(
                     )
             if (
                 request.commit_start
-                and request.commit_start != first_commit.oid.hex
+                and request.commit_start != str(first_commit.id)
             ):
                 pr_action = "rebased"
                 if orig_commit:
-                    commenttext = "rebased onto %s" % orig_commit.oid.hex
+                    commenttext = "rebased onto %s" % str(orig_commit.id)
                 else:
                     commenttext = "rebased onto unknown target"
-        request.commit_start = first_commit.oid.hex
-        request.commit_stop = diff_commits[0].oid.hex
+        request.commit_start = str(first_commit.id)
+        request.commit_stop = str(diff_commits[0].id)
         session.add(request)
         session.commit()
         _log.debug(
@@ -2454,7 +2454,7 @@ def get_git_tags(project, with_commits=False):
                 if ref:
                     com = ref.peel()
                     if com:
-                        tags[tag.split("refs/tags/")[1]] = com.oid.hex
+                        tags[tag.split("refs/tags/")[1]] = str(com.id)
     else:
         tags = [
             tag.split("refs/tags/")[1]
@@ -2576,7 +2576,7 @@ def log_commits_to_db(session, project, commits, gitdir):
             user_email=commit.author.email if not author_obj else None,
             project_id=project.id,
             log_type="committed",
-            ref_id=commit.oid.hex,
+            ref_id=str(commit.id),
             date=date_created.date(),
             date_created=date_created.datetime,
         )
@@ -2619,7 +2619,7 @@ def get_git_branches(project, with_commits=False):
             resolved_branch = repo_obj.lookup_branch(branch).resolve()
             com = resolved_branch.peel()
             if com:
-                branches[branch] = com.oid.hex
+                branches[branch] = str(com.id)
     else:
         branches = repo_obj.listall_branches()
 
@@ -2636,7 +2636,7 @@ def get_default_git_branches(project):
     branch = repo_obj.lookup_branch(branchname)
     commit = branch.peel(pygit2.Commit)
 
-    return branchname, commit.oid.hex
+    return branchname, str(commit.id)
 
 
 def new_git_branch(
diff --git a/pagure/lib/tasks.py b/pagure/lib/tasks.py
index e964084..a370bb6 100644
--- a/pagure/lib/tasks.py
+++ b/pagure/lib/tasks.py
@@ -973,7 +973,7 @@ def commits_author_stats(self, session, repopath):
     number_of_commits = 0
     authors_email = set()
     for commit in repo_obj.walk(
-        repo_obj.head.peel().oid.hex, pygit2.GIT_SORT_NONE
+        str(repo_obj.head.peel().id), pygit2.GIT_SORT_NONE
     ):
         # For each commit record how many times each combination of name and
         # e-mail appears in the git history.
@@ -1034,7 +1034,7 @@ def commits_history_stats(self, session, repopath):
 
     dates = collections.defaultdict(int)
     for commit in repo_obj.walk(
-        repo_obj.head.peel().oid.hex, pygit2.GIT_SORT_NONE
+        str(repo_obj.head.peel().id), pygit2.GIT_SORT_NONE
     ):
         delta = (
             datetime.datetime.utcnow() - arrow.get(commit.commit_time).naive
@@ -1099,7 +1099,7 @@ def link_pr_to_ticket(self, session, pr_uid):
     user = request.project.user.user if request.project.is_fork else None
 
     for line in pagure.lib.git.read_git_lines(
-        ["log", "--no-walk"] + [c.oid.hex for c in diff_commits] + ["--"],
+        ["log", "--no-walk"] + [str(c.id) for c in diff_commits] + ["--"],
         repopath,
     ):
 
diff --git a/pagure/templates/commits.html b/pagure/templates/commits.html
index 8aee5c9..a8e8206 100644
--- a/pagure/templates/commits.html
+++ b/pagure/templates/commits.html
@@ -107,7 +107,7 @@
                           repo=repo.name,
                           username=username,
                           namespace=repo.namespace,
-                          commitid=diff_commit_full.hex) }}"
+                          commitid=str(diff_commit_full.id)) }}"
                       class="notblue">
                       <strong>{{ diff_commit_full.message.split('\n')[0] }}</strong>
                     </a>
@@ -126,13 +126,13 @@
                         repo=repo.name,
                         username=username,
                         namespace=repo.namespace,
-                        commitid=diff_commit_full.hex) }}"
+                        commitid=str(diff_commit_full.id)) }}"
                         class="btn btn-outline-primary font-weight-bold">
-                        <code>{{ diff_commit_full.hex|short }}</code>
+                        <code>{{ str(diff_commit_full.id)|short }}</code>
                       </a>
                       <a class="btn btn-outline-primary font-weight-bold" href="{{ url_for(
                         'ui_ns.view_tree', username=username, namespace=repo.namespace,
-                        repo=repo.name, identifier=diff_commit_full.hex) }}"><span class="fa fa-file-code-o fa-fw"></span></a>
+                        repo=repo.name, identifier=str(diff_commit_full.id)) }}"><span class="fa fa-file-code-o fa-fw"></span></a>
                     </div>
                   </div>
                 </div>
@@ -146,10 +146,10 @@
 
 
               {% for commit in last_commits %}
-              <div class="list-group-item {{'ml-4' if diff_commits and commit.oid.hex in diff_commits}}"
-                   id="c_{{ commit.hex }}">
+              <div class="list-group-item {{'ml-4' if diff_commits and str(commit.id) in diff_commits}}"
+                   id="c_{{ str(commit.id) }}">
                 <div class="row align-items-center">
-                    {% if diff_commits and commit.oid.hex in diff_commits %}
+                    {% if diff_commits and str(commit.id) in diff_commits %}
                     <div class="new_commit" title="This commit is not in the main branch of this Repo">
                       <span class="fa fa-arrow-circle-right text-muted pl-1"></span>
                     </div>
@@ -159,7 +159,7 @@
                       repo=repo.name,
                       username=username,
                       namespace=repo.namespace,
-                      commitid=commit.hex, branch=branchname) }}"
+                      commitid=str(commit.id), branch=branchname) }}"
                       class="notblue">
                       <strong>{{ commit.message.split('\n')[0] }}</strong>
                     </a>
@@ -185,13 +185,13 @@
                         repo=repo.name,
                         username=username,
                         namespace=repo.namespace,
-                        commitid=commit.hex, branch=branchname) }}"
-                        class="btn btn-outline-primary font-weight-bold commithash" id="c_{{ commit.hex }}">
-                        <code>{{ commit.hex|short }}</code>
+                        commitid=str(commit.id), branch=branchname) }}"
+                        class="btn btn-outline-primary font-weight-bold commithash" id="c_{{ str(commit.id) }}">
+                        <code>{{ str(commit.id)|short }}</code>
                       </a>
                       <a class="btn btn-outline-primary font-weight-bold" href="{{ url_for(
                         'ui_ns.view_tree', username=username, namespace=repo.namespace,
-                        repo=repo.name, identifier=commit.hex) }}"><span class="fa fa-file-code-o fa-fw"></span></a>
+                        repo=repo.name, identifier=str(commit.id)) }}"><span class="fa fa-file-code-o fa-fw"></span></a>
                     </div>
                   </div>
                 </div>
diff --git a/pagure/templates/file_history.html b/pagure/templates/file_history.html
index d016528..c6439ef 100644
--- a/pagure/templates/file_history.html
+++ b/pagure/templates/file_history.html
@@ -101,14 +101,14 @@
           <div class="list-group my-2">
               {% for line in log %}
               {% set commit = g.repo_obj[line[0]] %}
-              <div class="list-group-item " id="c_{{ commit.hex }}">
+              <div class="list-group-item " id="c_{{ str(commit.id) }}">
                 <div class="row align-items-center">
                   <div class="col">
                     <a href="{{ url_for('ui_ns.view_commit',
                       repo=repo.name,
                       username=username,
                       namespace=repo.namespace,
-                      commitid=commit.hex, branch=branchname) }}"
+                      commitid=str(commit.id), branch=branchname) }}"
                       class="notblue">
                       <strong>{{ commit.message.split('\n')[0] }}</strong>
                     </a>
@@ -134,13 +134,13 @@
                         repo=repo.name,
                         username=username,
                         namespace=repo.namespace,
-                        commitid=commit.hex, branch=branchname) }}"
-                        class="btn btn-outline-primary font-weight-bold commithash" id="c_{{ commit.hex }}">
-                        <code>{{ commit.hex|short }}</code>
+                        commitid=str(commit.id), branch=branchname) }}"
+                        class="btn btn-outline-primary font-weight-bold commithash" id="c_{{ str(commit.id) }}">
+                        <code>{{ str(commit.id)|short }}</code>
                       </a>
                       <a class="btn btn-outline-primary font-weight-bold" href="{{ url_for(
                         'ui_ns.view_tree', username=username, namespace=repo.namespace,
-                        repo=repo.name, identifier=commit.hex) }}"><span class="fa fa-file-code-o fa-fw"></span></a>
+                        repo=repo.name, identifier=str(commit.id)) }}"><span class="fa fa-file-code-o fa-fw"></span></a>
                     </div>
                   </div>
                 </div>
diff --git a/pagure/templates/releases.html b/pagure/templates/releases.html
index 1ca3182..9a4bc4e 100644
--- a/pagure/templates/releases.html
+++ b/pagure/templates/releases.html
@@ -61,7 +61,7 @@
                     repo=repo.name,
                     username=username,
                     namespace=repo.namespace,
-                    identifier=tag['object'].oid) }}"
+                    identifier=tag['object'].id) }}"
                     class="font-weight-bold">
                     <i class="fa fa-fw fa-tags text-muted"></i> {{tag['tagname']}}
                     </a>
@@ -77,9 +77,9 @@
                     repo=repo.name,
                     username=username,
                     namespace=repo.namespace,
-                    commitid=tag['object'].oid) }}"
+                    commitid=tag['object'].id) }}"
                class="btn btn-outline-secondary disabled">
-              <code class="font-weight-bold">{{ tag['object'].oid | short }}</code>
+              <code class="font-weight-bold">{{ tag['object'].id | short }}</code>
             </a>
             <div class="btn-group">
               <a class="btn btn-outline-primary"
@@ -87,7 +87,7 @@
                        repo=repo.name,
                        username=username,
                        namespace=repo.namespace,
-                       identifier=tag['object'].oid) }}"
+                       identifier=tag['object'].id) }}"
                 title="view code tree for this release">
                 <i class="fa fa-fw fa-file-code-o"></i>
               </a>
diff --git a/pagure/templates/repo_comparecommits.html b/pagure/templates/repo_comparecommits.html
index 5c76efe..c0ede22 100644
--- a/pagure/templates/repo_comparecommits.html
+++ b/pagure/templates/repo_comparecommits.html
@@ -50,10 +50,10 @@
           repo=pull_request.project_from.name,
           username=pull_request.project_from.user.user,
           namespace=repo.namespace,
-          commitid=commit.oid.hex)%}
+          commitid=str(commit.id))%}
         {% set tree_link = url_for(
           'ui_ns.view_tree', username=pull_request.project_from.user.user, namespace=repo.namespace,
-          repo=repo.name, identifier=commit.hex) %}
+          repo=repo.name, identifier=str(commit.id)) %}
       {% elif pull_request and pull_request.remote %}
         {% set commit_link = None %}
       {% else %}
@@ -61,10 +61,10 @@
                   repo=repo.name,
                   username=username,
                   namespace=repo.namespace,
-                  commitid=commit.oid.hex) %}
+                  commitid=str(commit.id)) %}
         {% set tree_link = url_for(
           'ui_ns.view_tree', username=username, namespace=repo.namespace,
-          repo=repo.name, identifier=commit.hex) %}
+          repo=repo.name, identifier=str(commit.id)) %}
       {% endif %}
       {% if not loop.last and loop.index == 2 %}
         <div class="list-group-item text-center bg-light" id="show_hidden_commits">
@@ -104,7 +104,7 @@
               <div class="btn-group">
                 <a href="{{ commit_link }}"
                   class="btn btn-outline-primary font-weight-bold {{'disabled' if not commit_link}}">
-                  <code>{{ commit.hex|short }}</code>
+                  <code>{{ str(commit.id)|short }}</code>
                 </a>
                 <a class="btn btn-outline-primary font-weight-bold {{'disabled' if not commit_link}}" href="{{tree_link}}"><span class="fa fa-file-code-o fa-fw"></span></a>
               </div>
diff --git a/pagure/templates/repo_info.html b/pagure/templates/repo_info.html
index e8ec2e0..bac479f 100644
--- a/pagure/templates/repo_info.html
+++ b/pagure/templates/repo_info.html
@@ -277,10 +277,10 @@
                           repo=repo.name,
                           username=username,
                           namespace=repo.namespace,
-                          commitid=commit.hex, branch=branchname) }}"
+                          commitid=str(commit.id), branch=branchname) }}"
                           class="notblue">
                           <code class="py-1 px-2 font-weight-bold commit_branch">{{ branchname }}</code><code
-                           class="py-1 px-2 font-weight-bold commit_hash">{{ commit.hex|short }}</code>
+                           class="py-1 px-2 font-weight-bold commit_hash">{{ str(commit.id)|short }}</code>
                           <span class="font-weight-bold">{{ commit.message.split('\n')[0] }}</span>
                         </a>
                       </div>
diff --git a/pagure/templates/repo_new_pull_request.html b/pagure/templates/repo_new_pull_request.html
index bec836b..908662d 100644
--- a/pagure/templates/repo_new_pull_request.html
+++ b/pagure/templates/repo_new_pull_request.html
@@ -265,10 +265,10 @@
                         repo=repo.name,
                         username=username,
                         namespace=repo.namespace,
-                        commitid=commit.oid.hex) %}
+                        commitid=str(commit.id)) %}
               {% set tree_link = url_for(
                 'ui_ns.view_tree', username=username, namespace=repo.namespace,
-                repo=repo.name, identifier=commit.hex) %}
+                repo=repo.name, identifier=str(commit.id) %}
 
             <div class="list-group-item">
             <div class="row align-items-center">
@@ -299,7 +299,7 @@
                   <div class="btn-group">
                     <a href="{{ commit_link }}"
                       class="btn btn-outline-primary font-weight-bold {{'disabled' if not commit_link}}">
-                      <code>{{ commit.hex|short }}</code>
+                      <code>{{ str(commit.id)|short }}</code>
                     </a>
                     <a class="btn btn-outline-primary font-weight-bold {{'disabled' if not commit_link}}" href="{{tree_link}}"><span class="fa fa-file-code-o fa-fw"></span></a>
                   </div>
diff --git a/pagure/templates/repo_pull_request.html b/pagure/templates/repo_pull_request.html
index fd7d9d2..e98104c 100644
--- a/pagure/templates/repo_pull_request.html
+++ b/pagure/templates/repo_pull_request.html
@@ -304,10 +304,10 @@
                 repo=pull_request.project_from.name,
                 username=pull_request.project_from.user.user,
                 namespace=repo.namespace,
-                commitid=commit.oid.hex)%}
+                commitid=str(commit.id))%}
               {% set tree_link = url_for(
                 'ui_ns.view_tree', username=pull_request.project_from.user.user, namespace=repo.namespace,
-                repo=repo.name, identifier=commit.hex) %}
+                repo=repo.name, identifier=str(commit.id)) %}
             {% elif pull_request.remote %}
               {% set commit_link = None %}
             {% else %}
@@ -315,12 +315,12 @@
                         repo=repo.name,
                         username=repo.user.user if repo.is_fork else None,
                         namespace=repo.namespace,
-                        commitid=commit.oid.hex) %}
+                        commitid=str(commit.id)) %}
               {% set tree_link = url_for(
                 'ui_ns.view_tree',
                 username=repo.user.user if repo.is_fork else None,
                 namespace=repo.namespace,
-                repo=repo.name, identifier=commit.hex) %}
+                repo=repo.name, identifier=str(commit.id)) %}
             {% endif %}
             <div class="list-group-item">
             <div class="row align-items-center">
@@ -350,9 +350,9 @@
               <div class="col-xs-auto pr-3 text-right">
                   <div class="btn-group">
                     <a href="{{ commit_link }}"
-                      data-commithash="{{ commit.hex }}"
+                      data-commithash="{{ str(commit.id) }}"
                       class="btn btn-outline-primary font-weight-bold {{'disabled' if not commit_link}} commithash">
-                      <code>{{ commit.hex|short }}</code>
+                      <code>{{ str(commit.id)|short }}</code>
                     </a>
                     <a class="btn btn-outline-primary font-weight-bold {{'disabled' if not commit_link}}" href="{{tree_link}}"><span class="fa fa-file-code-o fa-fw"></span></a>
                   </div>
diff --git a/pagure/ui/fork.py b/pagure/ui/fork.py
index 0ba221f..1c7d7c4 100644
--- a/pagure/ui/fork.py
+++ b/pagure/ui/fork.py
@@ -226,6 +226,7 @@ def request_pulls(repo, username=None, namespace=None):
         total_page=total_page,
         total_open=total_open,
         total_merged=total_merged,
+        str=str,
     )
 
 
@@ -280,7 +281,7 @@ def request_pull(repo, requestid, username=None, namespace=None):
         try:
             for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_NONE):
                 diff_commits.append(commit)
-                if commit.oid.hex == request.commit_start:
+                if str(commit.id) == request.commit_start:
                     break
         except KeyError:
             # This happens when repo.walk() cannot find commitid
@@ -289,19 +290,19 @@ def request_pull(repo, requestid, username=None, namespace=None):
         if diff_commits:
             # Ensure the first commit in the PR as a parent, otherwise
             # point to it
-            start = diff_commits[-1].oid.hex
+            start = str(diff_commits[-1].id)
             if diff_commits[-1].parents:
-                start = diff_commits[-1].parents[0].oid.hex
+                start = str(diff_commits[-1].parents[0].id)
 
             # If the start and the end commits are the same, it means we are,
             # dealing with one commit that has no parent, so just diff that
             # one commit
-            if start == diff_commits[0].oid.hex:
+            if start == str(diff_commits[0].id):
                 diff = diff_commits[0].tree.diff_to_tree(swap=True)
             else:
                 diff = repo_obj.diff(
                     repo_obj.revparse_single(start),
-                    repo_obj.revparse_single(diff_commits[0].oid.hex),
+                    repo_obj.revparse_single(str(diff_commits[0].id)),
                 )
     else:
         try:
@@ -374,6 +375,7 @@ def request_pull(repo, requestid, username=None, namespace=None):
         trigger_ci_pr_form=trigger_ci_pr_form,
         flag_statuses_labels=json.dumps(pagure_config["FLAG_STATUSES_LABELS"]),
         warning_characters=warning_characters,
+        str=str,
     )
 
 
@@ -455,7 +457,7 @@ def request_pull_to_diff_or_patch(
     branch = repo_obj.lookup_branch(request.branch_from)
     commitid = None
     if branch:
-        commitid = branch.peel().hex
+        commitid = str(branch.peel().id)
 
     diff_commits = []
     if request.status != "Open":
@@ -463,7 +465,7 @@ def request_pull_to_diff_or_patch(
         try:
             for commit in repo_obj.walk(commitid, pygit2.GIT_SORT_NONE):
                 diff_commits.append(commit)
-                if commit.oid.hex == request.commit_start:
+                if str(commit.id) == request.commit_start:
                     break
         except KeyError:
             # This happens when repo.walk() cannot find commitid
@@ -609,6 +611,7 @@ def request_pull_edit(repo, requestid, username=None, namespace=None):
         repo=repo,
         username=username,
         form=form,
+        str=str,
     )
 
 
@@ -734,6 +737,7 @@ def pull_request_add_comment(
         filename=filename,
         row=row,
         form=form,
+        str=str,
     )
 
 
@@ -924,6 +928,7 @@ def pull_request_edit_comment(
         form=form,
         comment=comment,
         is_js=is_js,
+        str=str,
     )
 
 
@@ -1720,13 +1725,13 @@ def new_request_pull(
                         )
 
             if orig_commit:
-                orig_commit = orig_commit.oid.hex
+                orig_commit = str(orig_commit.id)
 
             initial_comment = form.initial_comment.data.strip() or None
             commit_start = commit_stop = None
             if diff_commits:
-                commit_stop = diff_commits[0].oid.hex
-                commit_start = diff_commits[-1].oid.hex
+                commit_stop = str(diff_commits[0].id)
+                commit_start = str(diff_commits[-1].id)
             request = pagure.lib.query.new_pull_request(
                 flask.g.session,
                 repo_to=parent,
@@ -1939,6 +1944,7 @@ def new_remote_request_pull(repo, username=None, namespace=None):
                 branch_from=branch_from,
                 remote_git=remote_git,
                 parent=repo,
+                str=str,
             )
 
         try:
@@ -1953,7 +1959,7 @@ def new_remote_request_pull(repo, username=None, namespace=None):
                         )
 
             if orig_commit:
-                orig_commit = orig_commit.oid.hex
+                orig_commit = str(orig_commit.id)
 
             parent = repo
             if repo.parent:
@@ -2037,6 +2043,7 @@ def new_remote_request_pull(repo, username=None, namespace=None):
         username=username,
         form=form,
         branch_to=branch_to,
+        str=str,
     )
 
 
diff --git a/pagure/ui/repo.py b/pagure/ui/repo.py
index d4ce2e3..4e31e02 100644
--- a/pagure/ui/repo.py
+++ b/pagure/ui/repo.py
@@ -186,6 +186,7 @@ def view_repo(repo, username=None, namespace=None):
         last_commits=last_commits,
         tree=tree,
         num_watchers=len(watch_users),
+        str=str,
     )
 
 
@@ -210,7 +211,7 @@ def view_repo_branch(repo, branchname, username=None, namespace=None):
         head = None
     cnt = 0
     last_commits = []
-    for commit in repo_obj.walk(branch.peel().hex, pygit2.GIT_SORT_NONE):
+    for commit in repo_obj.walk(str(branch.peel().id), pygit2.GIT_SORT_NONE):
         last_commits.append(commit)
         cnt += 1
         if cnt == 3:
@@ -239,19 +240,19 @@ def view_repo_branch(repo, branchname, username=None, namespace=None):
 
         if compare_branch:
             commit_list = [
-                commit.oid.hex
+                str(commit.id)
                 for commit in orig_repo.walk(
-                    compare_branch.peel().hex,
+                    str(compare_branch.peel().id),
                     pygit2.GIT_SORT_NONE)
             ]
 
-        repo_commit = repo_obj[branch.peel().hex]
+        repo_commit = repo_obj[str(branch.peel().id)]
 
         for commit in repo_obj.walk(
-                repo_commit.oid.hex, pygit2.GIT_SORT_NONE):
-            if commit.oid.hex in commit_list:
+                str(repo_commit.id), pygit2.GIT_SORT_NONE):
+            if str(commit.id) in commit_list:
                 break
-            diff_commits.append(commit.oid.hex)
+            diff_commits.append(str(commit.id))
 
         tree = sorted(last_commits[0].tree, key=lambda x: x.filemode)
         for i in tree:
@@ -280,6 +281,7 @@ def view_repo_branch(repo, branchname, username=None, namespace=None):
         safe=safe,
         readme=readme,
         diff_commits=diff_commits,
+        str=str,
     )
 """
 
@@ -320,11 +322,11 @@ def view_commits(repo, branchname=None, username=None, namespace=None):
         # where we expected a commit, in this case, get the actual commit
         if isinstance(commit, pygit2.Tag):
             commit = commit.peel(pygit2.Commit)
-            branchname = commit.oid.hex
+            branchname = str(commit.id)
         elif isinstance(commit, pygit2.Blob):
             try:
                 commit = commit.peel(pygit2.Commit)
-                branchname = commit.oid.hex
+                branchname = str(commit.id)
             except Exception:
                 flask.abort(
                     404, description="Invalid branch/identifier provided"
@@ -361,7 +363,7 @@ def view_commits(repo, branchname=None, username=None, namespace=None):
     n_commits = 0
     last_commits = []
     if commit:
-        for commit in repo_obj.walk(commit.hex, pygit2.GIT_SORT_NONE):
+        for commit in repo_obj.walk(str(commit.id), pygit2.GIT_SORT_NONE):
 
             # Filters the commits for a user
             if author_obj:
@@ -412,7 +414,7 @@ def view_commits(repo, branchname=None, username=None, namespace=None):
             )
 
             for commit in diff_commits_full:
-                diff_commits.append(commit.oid.hex)
+                diff_commits.append(str(commit.id))
 
     return flask.render_template(
         "commits.html",
@@ -429,6 +431,7 @@ def view_commits(repo, branchname=None, username=None, namespace=None):
         page=page,
         total_page=total_page,
         flag_statuses_labels=json.dumps(pagure_config["FLAG_STATUSES_LABELS"]),
+        str=str,
     )
 
 
@@ -468,7 +471,7 @@ def compare_commits(repo, commit1, commit2, username=None, namespace=None):
     last_commit = commit2
 
     commits = [
-        commit.oid.hex[: len(first_commit)]
+        str(commit.id)[: len(first_commit)]
         for commit in repo_obj.walk(last_commit, pygit2.GIT_SORT_NONE)
     ]
 
@@ -479,7 +482,7 @@ def compare_commits(repo, commit1, commit2, username=None, namespace=None):
     for commit in repo_obj.walk(last_commit, order):
         diff_commits.append(commit)
 
-        if commit.oid.hex == first_commit or commit.oid.hex.startswith(
+        if str(commit.id) == first_commit or str(commit.id).startswith(
             first_commit
         ):
             break
@@ -498,6 +501,7 @@ def compare_commits(repo, commit1, commit2, username=None, namespace=None):
         commit2=commit2,
         diff=diff,
         diff_commits=diff_commits,
+        str=str,
     )
 
 
@@ -548,7 +552,7 @@ def view_file(repo, identifier, filename, username=None, namespace=None):
         )
         if not content:
             flask.abort(404, description="File not found")
-        content = repo_obj[content.oid]
+        content = repo_obj[content.id]
     else:
         content = commit
 
@@ -713,7 +717,7 @@ def view_raw_file(
         if not content or isinstance(content, pygit2.Tree):
             flask.abort(404, description="File not found")
 
-        data = repo_obj[content.oid].data
+        data = repo_obj[content.id].data
     else:
         if commit.parents:
             # We need to take this not so nice road to ensure that the
@@ -800,7 +804,7 @@ def view_blame_file(repo, filename, username=None, namespace=None):
         _log.exception("File could not be decoded")
         flask.abort(500, description="File could not be decoded")
 
-    blame = repo_obj.blame(filename, newest_commit=commit.oid.hex)
+    blame = repo_obj.blame(filename, newest_commit=str(commit.id))
 
     return flask.render_template(
         "blame.html",
@@ -813,6 +817,7 @@ def view_blame_file(repo, filename, username=None, namespace=None):
         content=content,
         output_type="blame",
         blame=blame,
+        str=str,
     )
 
 
@@ -862,6 +867,7 @@ def view_history_file(repo, filename, username=None, namespace=None):
         branchname=branchname,
         output_type="history",
         log=log,
+        str=str,
     )
 
 
@@ -912,7 +918,7 @@ def view_commit(repo, commitid, username=None, namespace=None):
                 repo=repo.name,
                 username=username,
                 namespace=repo.namespace,
-                commitid=commit.hex,
+                commitid=str(commit.id),
             )
         )
 
@@ -938,6 +944,7 @@ def view_commit(repo, commitid, username=None, namespace=None):
         flags=pagure.lib.query.get_commit_flag(
             flask.g.session, repo, commitid
         ),
+        str=str,
     )
 
 
@@ -1058,7 +1065,7 @@ def view_tree(repo, identifier=None, username=None, namespace=None):
         # where we expected a commit, in this case, get the actual commit
         if isinstance(commit, pygit2.Tag):
             commit = commit.peel(pygit2.Commit)
-            branchname = commit.oid.hex
+            branchname = str(commit.id)
 
         if commit and not isinstance(commit, pygit2.Blob):
             content = sorted(commit.tree, key=lambda x: x.filemode)
@@ -1089,6 +1096,7 @@ def view_tree(repo, identifier=None, username=None, namespace=None):
         readme=readme,
         readme_ext=readme_ext,
         safe=safe,
+        str=str,
     )
 
 
@@ -1117,6 +1125,7 @@ def view_tags(repo, username=None, namespace=None):
         repo=repo,
         tags=tags,
         pagure_checksum=pagure_checksum,
+        str=str,
     )
 
 
@@ -1151,6 +1160,7 @@ def view_branches(repo, username=None, namespace=None):
         head=head,
         origin="view_repo",
         branchname=branchname,
+        str=str,
     )
 
 
@@ -1166,7 +1176,7 @@ def view_forks(repo, username=None, namespace=None):
     """Forks"""
 
     return flask.render_template(
-        "repo_forks.html", select="forks", username=username, repo=flask.g.repo
+        "repo_forks.html", select="forks", username=username, repo=flask.g.repo, str=str
     )
 
 
@@ -1248,6 +1258,7 @@ def new_release(repo, username=None, namespace=None):
         username=username,
         repo=repo,
         form=form,
+        str=str,
     )
 
 
@@ -1345,6 +1356,7 @@ def view_settings(repo, username=None, namespace=None):
         branchname=branchname,
         pagure_admin=pagure.utils.is_admin(),
         branch_aliases=branch_aliases,
+        str=str,
     )
 
 
@@ -2004,7 +2016,7 @@ def add_deploykey(repo, username=None, namespace=None):
             flask.flash("Deploy key could not be added", "error")
 
     return flask.render_template(
-        "add_deploykey.html", form=form, username=username, repo=repo
+        "add_deploykey.html", form=form, username=username, repo=repo, str=str
     )
 
 
@@ -2094,6 +2106,7 @@ def add_user(repo, username=None, namespace=None):
         access_levels=access_levels,
         user_to_update=user_to_update,
         user_access=user_access,
+        str=str,
     )
 
 
@@ -2267,6 +2280,7 @@ def add_group_project(repo, username=None, namespace=None):
         access_levels=access_levels,
         group_to_update=group_to_update,
         group_access=group_access,
+        str=str,
     )
 
 
@@ -2402,6 +2416,7 @@ def add_token(repo, username=None, namespace=None):
         acls=acls,
         username=username,
         repo=repo,
+        str=str,
     )
 
 
@@ -2618,7 +2633,7 @@ def edit_file(repo, branchname, filename, username=None, namespace=None):
             flask.abort(400, description="Cannot edit binary files")
 
         try:
-            data = repo_obj[content.oid].data.decode("utf-8")
+            data = repo_obj[content.id].data.decode("utf-8")
         except UnicodeDecodeError:  # pragma: no cover
             # In theory we shouldn't reach here since we check if the file
             # is binary with `is_binary_string()` above
@@ -2639,6 +2654,7 @@ def edit_file(repo, branchname, filename, username=None, namespace=None):
         filename=filename,
         form=form,
         user=user,
+        str=str,
     )
 
 
@@ -2718,6 +2734,7 @@ def view_docs(repo, username=None, filename=None, namespace=None):
         username=username,
         filename=filename,
         endpoint="view_docs",
+        str=str,
     )
 
 
@@ -2733,7 +2750,7 @@ def view_project_activity(repo, namespace=None):
 
     repo = flask.g.repo
 
-    return flask.render_template("activity.html", repo=repo)
+    return flask.render_template("activity.html", repo=repo, str=str)
 
 
 @UI_NS.route("/<repo>/stargazers/")
@@ -2751,6 +2768,7 @@ def view_stargazers(repo, username=None, namespace=None):
         username=username,
         namespace=namespace,
         users=users,
+        str=str,
     )
 
 
@@ -3288,7 +3306,7 @@ def project_dowait(repo, username=None, namespace=None):
 def view_stats(repo, username=None, namespace=None):
     """Displays some statistics about the specified repo."""
     return flask.render_template(
-        "repo_stats.html", select="stats", username=username, repo=flask.g.repo
+        "repo_stats.html", select="stats", username=username, repo=flask.g.repo, str=str
     )
 
 
@@ -3510,7 +3528,7 @@ def edit_tag(repo, tag, username=None, namespace=None):
         form.tag.data = tag
 
     return flask.render_template(
-        "edit_tag.html", username=username, repo=repo, form=form, tagname=tag
+        "edit_tag.html", username=username, repo=repo, form=form, tagname=tag, str=str
     )
 
 
@@ -3628,7 +3646,7 @@ def generate_project_archive(
         archive_folder,
         flask.g.repo.fullname,
         tag_path,
-        commit.oid.hex,
+        str(commit.id),
         "%s.%s" % (name, extension),
     )
     headers = {
@@ -3651,7 +3669,7 @@ def generate_project_archive(
         repo,
         namespace=namespace,
         username=username,
-        commit=commit.oid.hex,
+        commit=str(commit.id),
         tag=tag_filename,
         name=name,
         archive_fmt=extension,

From 8e3598e28b93a86e274bc37d44f729dd4d035940 Mon Sep 17 00:00:00 2001
From: Klaus Koder <klauskoder@pagure.local>
Date: Dec 04 2025 16:21:00 +0000
Subject: [PATCH 2/10] sqlalchemy.orm import relationship not relation


---

diff --git a/pagure/hooks/fedmsg_hook.py b/pagure/hooks/fedmsg_hook.py
index d512062..0c0079a 100644
--- a/pagure/hooks/fedmsg_hook.py
+++ b/pagure/hooks/fedmsg_hook.py
@@ -17,7 +17,7 @@ try:
     from flask_wtf import FlaskForm
 except ImportError:
     from flask_wtf import Form as FlaskForm
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import backref
 
 from pagure.hooks import BaseHook, BaseRunner
diff --git a/pagure/hooks/irc.py b/pagure/hooks/irc.py
index 9c324ac..8a53956 100644
--- a/pagure/hooks/irc.py
+++ b/pagure/hooks/irc.py
@@ -18,7 +18,7 @@ try:
     from flask_wtf import FlaskForm
 except ImportError:
     from flask_wtf import Form as FlaskForm
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import backref
 
 from pagure.hooks import BaseHook, RequiredIf
diff --git a/pagure/hooks/mail.py b/pagure/hooks/mail.py
index 7dfcaef..1556cbb 100644
--- a/pagure/hooks/mail.py
+++ b/pagure/hooks/mail.py
@@ -20,7 +20,7 @@ try:
     from flask_wtf import FlaskForm
 except ImportError:
     from flask_wtf import Form as FlaskForm
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import backref
 
 from pagure.config import config as pagure_config
diff --git a/pagure/hooks/mirror_hook.py b/pagure/hooks/mirror_hook.py
index 51f30d1..9d45e03 100644
--- a/pagure/hooks/mirror_hook.py
+++ b/pagure/hooks/mirror_hook.py
@@ -16,7 +16,7 @@ try:
     from flask_wtf import FlaskForm
 except ImportError:
     from flask_wtf import Form as FlaskForm
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import backref
 
 import pagure.config
diff --git a/pagure/hooks/pagure_ci.py b/pagure/hooks/pagure_ci.py
index aa7a383..4894f63 100644
--- a/pagure/hooks/pagure_ci.py
+++ b/pagure/hooks/pagure_ci.py
@@ -18,7 +18,7 @@ try:
     from flask_wtf import FlaskForm
 except ImportError:
     from flask_wtf import Form as FlaskForm
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import backref
 
 import pagure.lib.login
diff --git a/pagure/hooks/pagure_force_commit.py b/pagure/hooks/pagure_force_commit.py
index e49c9c6..4d1c042 100644
--- a/pagure/hooks/pagure_force_commit.py
+++ b/pagure/hooks/pagure_force_commit.py
@@ -17,7 +17,7 @@ try:
     from flask_wtf import FlaskForm
 except ImportError:
     from flask_wtf import Form as FlaskForm
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import backref
 
 import pagure.lib.git
diff --git a/pagure/hooks/pagure_hook.py b/pagure/hooks/pagure_hook.py
index 18d9ac1..608b341 100644
--- a/pagure/hooks/pagure_hook.py
+++ b/pagure/hooks/pagure_hook.py
@@ -21,7 +21,7 @@ try:
 except ImportError:
     from flask_wtf import Form as FlaskForm
 from sqlalchemy.exc import SQLAlchemyError
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import backref
 
 import pagure.config
diff --git a/pagure/hooks/pagure_no_new_branches.py b/pagure/hooks/pagure_no_new_branches.py
index 9dbbfaa..5dc585c 100644
--- a/pagure/hooks/pagure_no_new_branches.py
+++ b/pagure/hooks/pagure_no_new_branches.py
@@ -17,7 +17,7 @@ try:
     from flask_wtf import FlaskForm
 except ImportError:
     from flask_wtf import Form as FlaskForm
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import backref
 
 from pagure.hooks import BaseHook, BaseRunner
diff --git a/pagure/hooks/pagure_request_hook.py b/pagure/hooks/pagure_request_hook.py
index 9630292..2b89e37 100644
--- a/pagure/hooks/pagure_request_hook.py
+++ b/pagure/hooks/pagure_request_hook.py
@@ -17,7 +17,7 @@ try:
     from flask_wtf import FlaskForm
 except ImportError:
     from flask_wtf import Form as FlaskForm
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import backref
 
 import pagure.lib.git
diff --git a/pagure/hooks/pagure_ticket_hook.py b/pagure/hooks/pagure_ticket_hook.py
index c29ca62..a39dace 100644
--- a/pagure/hooks/pagure_ticket_hook.py
+++ b/pagure/hooks/pagure_ticket_hook.py
@@ -19,7 +19,7 @@ try:
     from flask_wtf import FlaskForm
 except ImportError:
     from flask_wtf import Form as FlaskForm
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import backref
 
 import pagure.lib.git
diff --git a/pagure/hooks/pagure_unsigned_commits.py b/pagure/hooks/pagure_unsigned_commits.py
index e407e9b..7651a2f 100644
--- a/pagure/hooks/pagure_unsigned_commits.py
+++ b/pagure/hooks/pagure_unsigned_commits.py
@@ -17,7 +17,7 @@ try:
     from flask_wtf import FlaskForm
 except ImportError:
     from flask_wtf import Form as FlaskForm
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import backref
 
 import pagure.config
diff --git a/pagure/hooks/rtd.py b/pagure/hooks/rtd.py
index bbdb2c5..6be056a 100644
--- a/pagure/hooks/rtd.py
+++ b/pagure/hooks/rtd.py
@@ -19,7 +19,7 @@ try:
     from flask_wtf import FlaskForm
 except ImportError:
     from flask_wtf import Form as FlaskForm
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import backref
 
 import pagure
diff --git a/pagure/lib/model.py b/pagure/lib/model.py
index 7eabb34..2327d29 100644
--- a/pagure/lib/model.py
+++ b/pagure/lib/model.py
@@ -29,7 +29,7 @@ from sqlalchemy.exc import SQLAlchemyError
 from sqlalchemy.orm import backref
 from sqlalchemy.orm import sessionmaker
 from sqlalchemy.orm import scoped_session
-from sqlalchemy.orm import relation
+from sqlalchemy.orm import relationship as relation
 from sqlalchemy.orm import validates
 
 import pagure.exceptions

From 715e86f27018546679aa57b733304465480f1f2f Mon Sep 17 00:00:00 2001
From: Klaus Koder <klauskoder@pagure.local>
Date: Dec 04 2025 16:21:00 +0000
Subject: [PATCH 3/10] Add support for chardet version 5


---

diff --git a/pagure/lib/encoding_utils.py b/pagure/lib/encoding_utils.py
index 2746f81..54bc4d0 100644
--- a/pagure/lib/encoding_utils.py
+++ b/pagure/lib/encoding_utils.py
@@ -68,7 +68,7 @@ def detect_encodings(data):
     if cchardet:
         return encodings
 
-    if ch_version[0] in ("3", "4"):
+    if ch_version[0] in ("3", "4", "5"):
         for prober in detector._charset_probers:
             if hasattr(prober, "probers"):
                 for prober in prober.probers:

From 2f38225791bf394cdec9f57bceabb9652ffbeed5 Mon Sep 17 00:00:00 2001
From: Klaus Koder <klauskoder@pagure.local>
Date: Dec 04 2025 16:21:00 +0000
Subject: [PATCH 4/10] cast ALLOWED_TAGS to list() before concatination


---

diff --git a/pagure/lib/query.py b/pagure/lib/query.py
index c372b67..484728a 100644
--- a/pagure/lib/query.py
+++ b/pagure/lib/query.py
@@ -4496,7 +4496,7 @@ def clean_input(text, ignore=None):
         else:
             attrs["img"] = filter_img_src
 
-    tags = bleach.ALLOWED_TAGS + [
+    tags = list(bleach.ALLOWED_TAGS) + [
         "p",
         "br",
         "div",
@@ -4536,7 +4536,7 @@ def clean_input(text, ignore=None):
 
     # newer bleach allow to customize the protocol supported
     if tuple(bleach_v) >= (1, 5, 0):  # pragma: no cover
-        protocols = bleach.ALLOWED_PROTOCOLS + ["irc", "ircs"]
+        protocols = list(bleach.ALLOWED_PROTOCOLS) + ["irc", "ircs"]
         kwargs["protocols"] = protocols
 
     return bleach.clean(text, **kwargs)

From 96cc359a869e9c2b075c424d157d43afb85628c9 Mon Sep 17 00:00:00 2001
From: Klaus Koder <klauskoder@pagure.local>
Date: Dec 04 2025 16:27:06 +0000
Subject: [PATCH 5/10] Use markupsafe instead of deprecated flask.Markup


---

diff --git a/files/pagure.spec b/files/pagure.spec
index 68b418e..5f3b028 100644
--- a/files/pagure.spec
+++ b/files/pagure.spec
@@ -1,6 +1,6 @@
 %{?python_enable_dependency_generator}
 
-%if 0%{?rhel} && 0%{?rhel} < 8
+%if (0%{?rhel} && 0%{?rhel} < 8)
 # Since the Python 3 stack in EPEL is missing too many dependencies,
 # we're sticking with Python 2 there for now.
 %global __python %{__python2}
@@ -11,19 +11,23 @@
 %global python_pkgversion %{python3_pkgversion}
 %endif
 
-# For now, to keep behavior consistent
-%global _python_bytecompile_extra 1
-
-
 Name:               pagure
 Version:            5.14.1
-Release:            1%{?dist}
+Release:            9%{?dist}
 Summary:            A git-centered forge
 
-License:            GPLv2+
+# Automatically converted from old format: GPLv2+ - review is highly recommended.
+License:            GPL-2.0-or-later
 URL:                https://pagure.io/pagure
 Source0:            https://pagure.io/releases/pagure/%{name}-%{version}.tar.gz
 
+Source10:           pagure-README.Fedora
+
+# fix(5.14.x): Use '==' instead of 'is' in template if condition because of old Jinja2 version on EL8
+# fix(oidc): Edge case, avoid 'KeyError' after pagure update if a cached session is used
+# https://pagure.io/pagure/pull-request/5486
+Patch0001:          5486.patch
+
 BuildArch:          noarch
 
 BuildRequires:      systemd-devel
@@ -40,12 +44,15 @@ Requires:           python%{python_pkgversion}-fedora-flask
 # flask-session
 %else
 Recommends:         python%{python_pkgversion}-fedora-flask
+# Needed for fedora-messaging support
+Recommends:         fedora-messaging
+Recommends:         python%{python_pkgversion}-pagure-messages
 %endif
 
 # We require OpenSSH 7.4+ for SHA256 support
 Requires:           openssh >= 7.4
 
-%if %{undefined python_enable_dependency_generator} && %{undefined python_disable_dependency_generator}
+%if 0%{?rhel} && 0%{?rhel} < 8
 Requires:           python%{python_pkgversion}-alembic
 Requires:           python%{python_pkgversion}-arrow
 Requires:           python%{python_pkgversion}-bcrypt
@@ -56,14 +63,11 @@ Requires:           python%{python_pkgversion}-celery
 Requires:           python%{python_pkgversion}-chardet
 Requires:           python%{python_pkgversion}-cryptography
 Requires:           python%{python_pkgversion}-docutils
-%if ! (0%{?rhel} && 0%{?rhel} < 8)
-Requires:           python%{python_pkgversion}-email-validator
-%endif
 Requires:           python%{python_pkgversion}-enum34
 Requires:           python%{python_pkgversion}-flask
 Requires:           python%{python_pkgversion}-flask-wtf
-Requires:           python%{python_pkgversion}-flask-oidc
 Requires:           python%{python_pkgversion}-markdown
+Requires:           python%{python_pkgversion}-markupsafe
 Requires:           python%{python_pkgversion}-munch
 Requires:           python%{python_pkgversion}-pillow
 Requires:           python%{python_pkgversion}-psutil
@@ -80,10 +84,33 @@ Requires:           python%{python_pkgversion}-whitenoise
 Requires:           python%{python_pkgversion}-wtforms
 %endif
 
-%{?systemd_requires}
+
+%if 0%{?fedora} || 0%{?rhel} >= 8
+# We want to use cchardet whenever it's available
+Recommends:         python3-cchardet
+
+# If using PostgreSQL, the correct driver should be installed
+Recommends:         ((python3-psycopg2 or python3-pg8000) if postgresql-server)
+
+# If using MariaDB/MySQL, the correct driver should be installed
+Recommends:         ((python3-mysqlclient or python3-PyMySQL) if mysql-server)
+
+# If using Apache web server, the correct configuration should be installed
+Recommends:         (%{name}-web-apache-httpd if httpd)
+
+# If using Nginx web server, the correct configuration should be installed
+Recommends:         (%{name}-web-nginx if nginx)
+%endif
+
+# We use the git tools for some actions due to deficiencies in libgit2 and pygit2
+Requires:           git-core
 
 # No dependency of the app per se, but required to make it working.
+%if 0%{?rhel} && 0%{?rhel} < 8
 Requires:           gitolite3
+%else
+Recommends:         gitolite3
+%endif
 
 %description
 Pagure is a light-weight git-centered forge based on pygit2.
@@ -92,6 +119,9 @@ Currently, Pagure offers a web-interface for git repositories, a ticket
 system and possibilities to create new projects, fork existing ones and
 create/merge pull-requests across or within projects.
 
+For steps on how to set up the system after installing this package,
+please read %{_pkgdocdir}/README.Fedora.
+
 
 %package            web-apache-httpd
 Summary:            Apache HTTPD configuration for Pagure
@@ -103,6 +133,9 @@ Requires:           mod_wsgi
 Requires:           httpd-filesystem
 Requires:           python%{python_pkgversion}-mod_wsgi
 %endif
+# Apache config moved out to its own subpackage
+Obsoletes:          pagure < 5.10.0
+Conflicts:          pagure < 5.10.0
 %description        web-apache-httpd
 This package provides the configuration files for deploying
 a Pagure server using the Apache HTTPD server.
@@ -151,7 +184,6 @@ Summary:            Milter to integrate pagure with emails
 BuildArch:          noarch
 Requires:           %{name} = %{version}-%{release}
 Requires:           python%{python_pkgversion}-pymilter
-%{?systemd_requires}
 # It would work with sendmail but we configure things (like the tempfile)
 # to work with postfix
 Requires:           postfix
@@ -165,7 +197,6 @@ Summary:            EventSource server for pagure
 BuildArch:          noarch
 Requires:           %{name} = %{version}-%{release}
 Requires:           python%{python_pkgversion}-trololio
-%{?systemd_requires}
 %description        ev
 Pagure comes with an eventsource server allowing live update of the pages
 supporting it. This package provides it.
@@ -175,7 +206,6 @@ supporting it. This package provides it.
 Summary:            Web-Hook server for pagure
 BuildArch:          noarch
 Requires:           %{name} = %{version}-%{release}
-%{?systemd_requires}
 %description        webhook
 Pagure comes with an webhook server allowing http callbacks for any action
 done on a project. This package provides it.
@@ -187,7 +217,6 @@ BuildArch:          noarch
 Requires:           %{name} = %{version}-%{release}
 Requires:           python%{python_pkgversion}-cryptography
 Requires:           python%{python_pkgversion}-jenkins
-%{?systemd_requires}
 %description        ci
 Pagure comes with a continuous integration service, currently supporting
 only jenkins but extendable to others.
@@ -199,7 +228,6 @@ build on the pull-requests opened to your project.
 Summary:            The logcom service for pagure
 BuildArch:          noarch
 Requires:           %{name} = %{version}-%{release}
-%{?systemd_requires}
 %description        logcom
 pagure-logcom contains the service that logs commits into the database so that
 the activity calendar heatmap is filled.
@@ -209,7 +237,6 @@ the activity calendar heatmap is filled.
 Summary:            The loadjson service for pagure
 BuildArch:          noarch
 Requires:           %{name} = %{version}-%{release}
-%{?systemd_requires}
 %description        loadjson
 pagure-loadjson is the service allowing to update the database with the
 information provided in the JSON blobs that are stored in the tickets (and
@@ -220,7 +247,6 @@ in the future pull-requests) git repo.
 Summary:            The mirroring service for pagure
 BuildArch:          noarch
 Requires:           %{name} = %{version}-%{release}
-%{?systemd_requires}
 %description        mirror
 pagure-mirror is the service mirroring projects that asked for it outside
 of this pagure instance.
@@ -239,6 +265,9 @@ sed -e "s/^email_validator.*//g" -i requirements.txt
 sed -e "s/^python3-openid$//g" -i requirements.txt
 %endif
 
+# Install README.Fedora file
+install -pm 0644 %{SOURCE10} README.Fedora
+
 
 %build
 %py_build
@@ -248,148 +277,152 @@ sed -e "s/^python3-openid$//g" -i requirements.txt
 %py_install
 
 # Install apache configuration file
-mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/httpd/conf.d/
-install -p -m 644 files/pagure-apache-httpd.conf $RPM_BUILD_ROOT/%{_sysconfdir}/httpd/conf.d/pagure.conf
+mkdir -p %{buildroot}/%{_sysconfdir}/httpd/conf.d/
+install -p -m 644 files/pagure-apache-httpd.conf %{buildroot}/%{_sysconfdir}/httpd/conf.d/pagure.conf
 
 # Install nginx configuration file
-mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/nginx/conf.d/
-install -p -m 644 files/pagure-nginx.conf $RPM_BUILD_ROOT/%{_sysconfdir}/nginx/conf.d/pagure.conf
+mkdir -p %{buildroot}/%{_sysconfdir}/nginx/conf.d/
+install -p -m 644 files/pagure-nginx.conf %{buildroot}/%{_sysconfdir}/nginx/conf.d/pagure.conf
 
 # Install configuration file
-mkdir -p $RPM_BUILD_ROOT/%{_sysconfdir}/pagure
-install -p -m 644 files/pagure.cfg.sample $RPM_BUILD_ROOT/%{_sysconfdir}/pagure/pagure.cfg
+mkdir -p %{buildroot}/%{_sysconfdir}/pagure
+install -p -m 644 files/pagure.cfg.sample %{buildroot}/%{_sysconfdir}/pagure/pagure.cfg
 
 # Install WSGI file
-mkdir -p $RPM_BUILD_ROOT/%{_datadir}/pagure
-install -p -m 644 files/pagure.wsgi $RPM_BUILD_ROOT/%{_datadir}/pagure/pagure.wsgi
-install -p -m 644 files/doc_pagure.wsgi $RPM_BUILD_ROOT/%{_datadir}/pagure/doc_pagure.wsgi
+mkdir -p %{buildroot}/%{_datadir}/pagure
+install -p -m 644 files/pagure.wsgi %{buildroot}/%{_datadir}/pagure/pagure.wsgi
+install -p -m 644 files/doc_pagure.wsgi %{buildroot}/%{_datadir}/pagure/doc_pagure.wsgi
 
 # Install the createdb script
-install -p -m 644 createdb.py $RPM_BUILD_ROOT/%{_datadir}/pagure/pagure_createdb.py
+install -p -m 644 createdb.py %{buildroot}/%{_datadir}/pagure/pagure_createdb.py
 
 # Install the api_key_expire_mail.py script
-install -p -m 644 files/api_key_expire_mail.py $RPM_BUILD_ROOT/%{_datadir}/pagure/api_key_expire_mail.py
+install -p -m 644 files/api_key_expire_mail.py %{buildroot}/%{_datadir}/pagure/api_key_expire_mail.py
 
 # Install the mirror_project_in.py script
-install -p -m 644 files/mirror_project_in.py $RPM_BUILD_ROOT/%{_datadir}/pagure/mirror_project_in.py
+install -p -m 644 files/mirror_project_in.py %{buildroot}/%{_datadir}/pagure/mirror_project_in.py
 
 # Install the keyhelper and aclcheck scripts
-mkdir -p $RPM_BUILD_ROOT/%{_libexecdir}/pagure/
-install -p -m 755 files/aclchecker.py $RPM_BUILD_ROOT/%{_libexecdir}/pagure/aclchecker.py
-install -p -m 755 files/keyhelper.py $RPM_BUILD_ROOT/%{_libexecdir}/pagure/keyhelper.py
+mkdir -p %{buildroot}/%{_libexecdir}/pagure/
+install -p -m 755 files/aclchecker.py %{buildroot}/%{_libexecdir}/pagure/aclchecker.py
+install -p -m 755 files/keyhelper.py %{buildroot}/%{_libexecdir}/pagure/keyhelper.py
 
 # Install the alembic configuration file
-install -p -m 644 files/alembic.ini $RPM_BUILD_ROOT/%{_sysconfdir}/pagure/alembic.ini
+install -p -m 644 files/alembic.ini %{buildroot}/%{_sysconfdir}/pagure/alembic.ini
 
 # Install the alembic revisions
-cp -r alembic $RPM_BUILD_ROOT/%{_datadir}/pagure
+cp -r alembic %{buildroot}/%{_datadir}/pagure
 
 # Install the systemd file for the web frontend
-mkdir -p $RPM_BUILD_ROOT/%{_unitdir}
+mkdir -p %{buildroot}/%{_unitdir}
 install -p -m 644 files/pagure_web.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_web.service
+    %{buildroot}/%{_unitdir}/pagure_web.service
 
 # Install the systemd file for the docs web frontend
-mkdir -p $RPM_BUILD_ROOT/%{_unitdir}
+mkdir -p %{buildroot}/%{_unitdir}
 install -p -m 644 files/pagure_docs_web.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_docs_web.service
+    %{buildroot}/%{_unitdir}/pagure_docs_web.service
 
 # Install the systemd file for the worker
-mkdir -p $RPM_BUILD_ROOT/%{_unitdir}
+mkdir -p %{buildroot}/%{_unitdir}
 install -p -m 644 files/pagure_worker.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_worker.service
+    %{buildroot}/%{_unitdir}/pagure_worker.service
+
+# Install the systemd file for the authorized_keys worker
+install -p -m 644 files/pagure_authorized_keys_worker.service \
+    %{buildroot}/%{_unitdir}/pagure_authorized_keys_worker.service
 
 # Install the systemd file for the gitolite worker
 install -p -m 644 files/pagure_gitolite_worker.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_gitolite_worker.service
+    %{buildroot}/%{_unitdir}/pagure_gitolite_worker.service
 
 # Install the systemd file for the web-hook
 install -p -m 644 files/pagure_webhook.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_webhook.service
+    %{buildroot}/%{_unitdir}/pagure_webhook.service
 
 # Install the systemd file for the ci service
 install -p -m 644 files/pagure_ci.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_ci.service
+    %{buildroot}/%{_unitdir}/pagure_ci.service
 
 # Install the systemd file for the logcom service
 install -p -m 644 files/pagure_logcom.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_logcom.service
+    %{buildroot}/%{_unitdir}/pagure_logcom.service
 
 # Install the systemd file for the loadjson service
 install -p -m 644 files/pagure_loadjson.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_loadjson.service
+    %{buildroot}/%{_unitdir}/pagure_loadjson.service
 
 # Install the systemd file for the mirror service
 install -p -m 644 files/pagure_mirror.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_mirror.service
+    %{buildroot}/%{_unitdir}/pagure_mirror.service
 
 # Install the systemd file for the script sending reminder about API key
 # expiration
 install -p -m 644 files/pagure_api_key_expire_mail.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_api_key_expire_mail.service
+    %{buildroot}/%{_unitdir}/pagure_api_key_expire_mail.service
 install -p -m 644 files/pagure_api_key_expire_mail.timer \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_api_key_expire_mail.timer
+    %{buildroot}/%{_unitdir}/pagure_api_key_expire_mail.timer
 
 # Install the systemd file for the script updating mirrored project
 install -p -m 644 files/pagure_mirror_project_in.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_mirror_project_in.service
+    %{buildroot}/%{_unitdir}/pagure_mirror_project_in.service
 install -p -m 644 files/pagure_mirror_project_in.timer \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_mirror_project_in.timer
+    %{buildroot}/%{_unitdir}/pagure_mirror_project_in.timer
 
 # Install the milter files
-mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/run/pagure
-mkdir -p $RPM_BUILD_ROOT/%{_tmpfilesdir}
+mkdir -p %{buildroot}/%{_localstatedir}/run/pagure
+mkdir -p %{buildroot}/%{_tmpfilesdir}
 install -p -m 0644 pagure-milters/milter_tempfile.conf \
-    $RPM_BUILD_ROOT/%{_tmpfilesdir}/%{name}-milter.conf
+    %{buildroot}/%{_tmpfilesdir}/%{name}-milter.conf
 install -p -m 644 pagure-milters/pagure_milter.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_milter.service
+    %{buildroot}/%{_unitdir}/pagure_milter.service
 install -p -m 644 pagure-milters/comment_email_milter.py \
-    $RPM_BUILD_ROOT/%{_datadir}/pagure/comment_email_milter.py
+    %{buildroot}/%{_datadir}/pagure/comment_email_milter.py
 
 # Install the eventsource
-mkdir -p $RPM_BUILD_ROOT/%{_libexecdir}/pagure-ev
+mkdir -p %{buildroot}/%{_libexecdir}/pagure-ev
 install -p -m 755 pagure-ev/pagure_stream_server.py \
-    $RPM_BUILD_ROOT/%{_libexecdir}/pagure-ev/pagure_stream_server.py
+    %{buildroot}/%{_libexecdir}/pagure-ev/pagure_stream_server.py
 install -p -m 644 pagure-ev/pagure_ev.service \
-    $RPM_BUILD_ROOT/%{_unitdir}/pagure_ev.service
+    %{buildroot}/%{_unitdir}/pagure_ev.service
 
 # Fix the shebang for various scripts
 sed -e "s|#!/usr/bin/env python|#!%{__python}|" -i \
-    $RPM_BUILD_ROOT/%{_libexecdir}/pagure-ev/*.py \
-    $RPM_BUILD_ROOT/%{_libexecdir}/pagure/*.py \
-    $RPM_BUILD_ROOT/%{_datadir}/pagure/*.py \
-    $RPM_BUILD_ROOT/%{python_sitelib}/pagure/hooks/files/*.py \
-    $RPM_BUILD_ROOT/%{python_sitelib}/pagure/hooks/files/hookrunner \
-    $RPM_BUILD_ROOT/%{python_sitelib}/pagure/hooks/files/post-receive \
-    $RPM_BUILD_ROOT/%{python_sitelib}/pagure/hooks/files/pre-receive \
-    $RPM_BUILD_ROOT/%{python_sitelib}/pagure/hooks/files/repospannerhook
+    %{buildroot}/%{_libexecdir}/pagure-ev/*.py \
+    %{buildroot}/%{_libexecdir}/pagure/*.py \
+    %{buildroot}/%{_datadir}/pagure/*.py \
+    %{buildroot}/%{python_sitelib}/pagure/hooks/files/*.py \
+    %{buildroot}/%{python_sitelib}/pagure/hooks/files/hookrunner \
+    %{buildroot}/%{python_sitelib}/pagure/hooks/files/post-receive \
+    %{buildroot}/%{python_sitelib}/pagure/hooks/files/pre-receive \
+    %{buildroot}/%{python_sitelib}/pagure/hooks/files/repospannerhook
 
 # Switch interpreter for systemd units
-sed -e "s|/usr/bin/python|%{__python}|g" -i $RPM_BUILD_ROOT/%{_unitdir}/*.service
+sed -e "s|/usr/bin/python|%{__python}|g" -i %{buildroot}/%{_unitdir}/*.service
 
-%if ! (0%{?rhel} && 0%{?rhel} < 8)
+%if !(0%{?rhel} && 0%{?rhel} < 8)
 # Switch all systemd units to use the correct celery
-sed -e "s|/usr/bin/celery|/usr/bin/celery-3|g" -i $RPM_BUILD_ROOT/%{_unitdir}/*.service
+sed -e "s|/usr/bin/celery|/usr/bin/celery-3|g" -i %{buildroot}/%{_unitdir}/*.service
 
 # Switch all systemd units to use the correct gunicorn
-sed -e "s|/usr/bin/gunicorn|/usr/bin/gunicorn-3|g" -i $RPM_BUILD_ROOT/%{_unitdir}/*.service
+sed -e "s|/usr/bin/gunicorn|/usr/bin/gunicorn-3|g" -i %{buildroot}/%{_unitdir}/*.service
 %endif
 
 # Make log directories
-mkdir -p $RPM_BUILD_ROOT/%{_localstatedir}/log/pagure
+mkdir -p %{buildroot}/%{_localstatedir}/log/pagure
 logfiles="web docs_web"
 
 for logfile in $logfiles; do
-   touch $RPM_BUILD_ROOT/%{_localstatedir}/log/pagure/access_${logfile}.log
-   touch $RPM_BUILD_ROOT/%{_localstatedir}/log/pagure/error_${logfile}.log
+   touch %{buildroot}/%{_localstatedir}/log/pagure/access_${logfile}.log
+   touch %{buildroot}/%{_localstatedir}/log/pagure/error_${logfile}.log
 done
 
 # Regenerate missing symlinks (really needed for upgrades from pagure < 5.0)
 runnerhooks="post-receive pre-receive"
 
 for runnerhook in $runnerhooks; do
-   rm -rf $RPM_BUILD_ROOT/%{python_sitelib}/pagure/hooks/files/$runnerhook
-   ln -sf hookrunner $RPM_BUILD_ROOT/%{python_sitelib}/pagure/hooks/files/$runnerhook
+   rm -rf %{buildroot}/%{python_sitelib}/pagure/hooks/files/$runnerhook
+   ln -sf hookrunner %{buildroot}/%{python_sitelib}/pagure/hooks/files/$runnerhook
 done
 
 %if 0%{?fedora} || 0%{?rhel} >= 8
@@ -401,6 +434,7 @@ done
 
 %post
 %systemd_post pagure_worker.service
+%systemd_post pagure_authorized_keys_worker.service
 %systemd_post pagure_gitolite_worker.service
 %systemd_post pagure_api_key_expire_mail.timer
 %systemd_post pagure_mirror_project_in.timer
@@ -424,6 +458,7 @@ done
 
 %preun
 %systemd_preun pagure_worker.service
+%systemd_preun pagure_authorized_keys_worker.service
 %systemd_preun pagure_gitolite_worker.service
 %systemd_preun pagure_api_key_expire_mail.timer
 %systemd_preun pagure_mirror_project_in.timer
@@ -447,6 +482,7 @@ done
 
 %postun
 %systemd_postun_with_restart pagure_worker.service
+%systemd_postun_with_restart pagure_authorized_keys_worker.service
 %systemd_postun_with_restart pagure_gitolite_worker.service
 %systemd_postun pagure_api_key_expire_mail.timer
 %systemd_postun pagure_mirror_project_in.timer
@@ -471,6 +507,7 @@ done
 
 %files
 %doc README.rst UPGRADING.rst doc/
+%doc README.Fedora
 %license LICENSE
 %config(noreplace) %{_sysconfdir}/pagure/pagure.cfg
 %config(noreplace) %{_sysconfdir}/pagure/alembic.ini
@@ -489,6 +526,7 @@ done
 %{python_sitelib}/pagure*.egg-info
 %{_bindir}/pagure-admin
 %{_unitdir}/pagure_worker.service
+%{_unitdir}/pagure_authorized_keys_worker.service
 %{_unitdir}/pagure_gitolite_worker.service
 %{_unitdir}/pagure_api_key_expire_mail.service
 %{_unitdir}/pagure_api_key_expire_mail.timer
@@ -568,1112 +606,332 @@ done
 
 
 %changelog
+* Fri Aug 15 2025 Python Maint <python-maint@redhat.com> - 5.14.1-9
+- Rebuilt for Python 3.14.0rc2 bytecode
+
+* Thu Jul 24 2025 Fedora Release Engineering <releng@fedoraproject.org> - 5.14.1-8
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_43_Mass_Rebuild
+
+* Mon Jun 02 2025 Python Maint <python-maint@redhat.com> - 5.14.1-7
+- Rebuilt for Python 3.14
+
+* Fri Jan 17 2025 Fedora Release Engineering <releng@fedoraproject.org> - 5.14.1-6
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_42_Mass_Rebuild
+
+* Fri Jul 26 2024 Miroslav Suchý <msuchy@redhat.com> - 5.14.1-5
+- convert license to SPDX
+
+* Thu Jul 18 2024 Fedora Release Engineering <releng@fedoraproject.org> - 5.14.1-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_41_Mass_Rebuild
+
+* Fri Jun 07 2024 Python Maint <python-maint@redhat.com> - 5.14.1-3
+- Rebuilt for Python 3.13
+
+* Mon May 27 2024 Dominik Wombacher <dominik@wombacher.cc> - 5.14.1-2
+- Backport patches to fix issues on EL8 (https://pagure.io/pagure/pull-request/5486)
+- fix(5.14.x): Use '==' instead of 'is' in template if condition because of old Jinja2 version on EL8
+- fix(oidc): Edge case, avoid 'KeyError' after pagure update if a cached session is used
+
 * Fri May 24 2024 Dominik Wombacher <dominik@wombacher.cc> - 5.14.1-1
-- Update to 5.14.1
+- Update to new release 5.14.1
+- Includes all previously backported patches
+- Fixes rhbz#2277121, rhbz#2278745, rhbz#2279411, rhbz#2280725, rhbz#2280723, rhbz#2280728, rhbz#2280726
 
-* Mon Nov 01 2021 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.13.3-1
-- Update to 5.13.3
+* Tue Apr 23 2024 Maja Massarini <mmassari@redhat.com> - 5.13.3-14
+- Backport patch: owner_of_a_pr_can_update_is_own_pr.patch from upstream commit: a3cd8f60bc7f7c8f29f1ce0f0737c2778bb839d2
+- Backport patch: allow_author_to_update_pr_but_not_to_change_assignee.patch from upstream commit: c8ea20215862e8ea8611fec66e1a386aff91c65c
+- Backport patch: fix_pagure_lib_git_get_changed_files.patch from upstream commit: 1b36cb8e32bab2fac9d5a51a374522069b537342
 
-* Wed Feb 10 2021 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.13.2-1
-- Update to 5.13.2
+* Tue Apr 02 2024 Nikola Forró <nforro@redhat.com> - 5.13.3-13
+- Backport patch: push_notification_pr_id.patch from upstream commit: 8ed510d99c9fbe3736c96b751d567891cbad343a
+- Backport patch: user_token_pr_close_acl.patch from upstream commit: 661557f3ecab5630e083ae498a54398ca3b5f007
 
-* Fri Jan 29 2021 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.13.1-1
-- Update to 5.13.1
+* Mon Mar 25 2024 Nils Philippsen <nils@tiptoe.de> - 5.13.3-12
+- Revert constraining SQLAlchemy version
 
-* Tue Jan 19 2021 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.13-1
-- Update to 5.13
+* Thu Mar 21 2024 Nils Philippsen <nils@tiptoe.de> - 5.13.3-11
+- Require SQLAlchemy < 2
 
-* Fri Jan 08 2021 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.12.1-1
-- Update to 5.12.1
+* Mon Jan 22 2024 Nikola Forró <nforro@redhat.com> - 5.13.3-10
+- Backport patch: push_notification_changed_files.patch from upstream commits:
+    - f9a2d7d3fb7084374063b70b455f93ba5a421fd1
+    - 9be5b2dc8c057778262700251584ce38b8338d16
+- Backport patch: user_token_pr_update_acl.patch from upstream commit:
+    - 133da07764314a73452487603f6f509b05f96204
 
-* Wed Jan 06 2021 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.12-1
-- Update to 5.12
+* Sun Jan 21 2024 Fedora Release Engineering <releng@fedoraproject.org> - 5.13.3-9
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_40_Mass_Rebuild
 
-* Tue Aug 11 2020 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.11.3-1
-- Update to 5.11.3
+* Thu Jul 20 2023 Fedora Release Engineering <releng@fedoraproject.org> - 5.13.3-8
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_39_Mass_Rebuild
 
-* Tue Aug 04 2020 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.11.2-1
-- Update to 5.11.2
+* Tue Jun 13 2023 Python Maint <python-maint@redhat.com> - 5.13.3-7
+- Rebuilt for Python 3.12
 
-* Mon Aug 03 2020 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.11.1-1
-- Update to 5.11.1
+* Thu Jan 19 2023 Fedora Release Engineering <releng@fedoraproject.org> - 5.13.3-6
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_38_Mass_Rebuild
 
-* Mon Aug 03 2020 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.11.0-1
-- Update to 5.11.0
+* Fri Jul 22 2022 Fedora Release Engineering <releng@fedoraproject.org> - 5.13.3-5
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_37_Mass_Rebuild
 
-* Thu May 14 2020 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.10.0-1
-- Update to 5.10.0
+* Mon Jun 13 2022 Python Maint <python-maint@redhat.com> - 5.13.3-4
+- Rebuilt for Python 3.11
 
-* Mon Mar 30 2020 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.9.1-1
-- Update to 5.9.1
+* Thu Jan 20 2022 Fedora Release Engineering <releng@fedoraproject.org> - 5.13.3-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_36_Mass_Rebuild
 
-* Tue Mar 24 2020 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.9.0-1
-- Update to 5.9.0
+* Sat Jan 01 2022 Neal Gompa <ngompa@fedoraproject.org> - 5.13.3-2
+- Bump to upgrade over infra builds
 
-* Mon Dec 02 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.8.1-1
-- Update to 5.8.1
+* Sat Jan 01 2022 Neal Gompa <ngompa@fedoraproject.org> - 5.13.3-1
+- Update to 5.13.3 (RH#2019098)
+- Drop patch for noggin_support which is now in this release
 
-* Fri Nov 15 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.8-1
-- Update to 5.8
+* Sat Jan 01 2022 Neal Gompa <ngompa@fedoraproject.org> - 5.13.2-6
+- Backport fix for oidc logins from FAS with multiple SSH keys
 
-* Sat Aug 10 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.7.4-1
-- Update to 5.7.4
+* Thu Jul 22 2021 Fedora Release Engineering <releng@fedoraproject.org> - 5.13.2-5
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild
 
-* Fri Aug 02 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.7.3-1
-- Update to pagure 5.7.3
+* Fri Jun 04 2021 Python Maint <python-maint@redhat.com> - 5.13.2-4
+- Rebuilt for Python 3.10
 
-* Tue Jul 30 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.7.2-1
-- Update to pagure 5.7.2
+* Tue Apr 06 2021 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.13.2-3
+- Backport patch: noggin_support.patch from upstream commit: 6a3f43dd1fc33367f9ab2a2dca8f941591374374
 
-* Fri Jul 12 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.7.1-1
-- Update to pagure 5.7.1
+* Tue Mar 02 2021 Zbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl> - 5.13.2-2
+- Rebuilt for updated systemd-rpm-macros
+  See https://pagure.io/fesco/issue/2583.
 
-* Fri Jul 05 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.7-1
-- Update to pagure 5.7
+* Thu Feb 11 2021 Neal Gompa <ngompa13@gmail.com> - 5.13.2-1
+- Update to 5.13.2 (RH#1927326)
 
-* Tue Jun 04 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.6-1
-- Update to pagure 5.6
+* Fri Jan 29 2021 Neal Gompa <ngompa13@gmail.com> - 5.13.1-1
+- Update to 5.13.1 (RH#1914378)
 
-* Mon Apr 08 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.5-1
-- Update to pagure 5.5
+* Tue Jan 26 2021 Fedora Release Engineering <releng@fedoraproject.org> - 5.12-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_34_Mass_Rebuild
 
-* Thu Mar 28 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.4-1
-- Update to pagure 5.4
+* Thu Jan  7 2021 Neal Gompa <ngompa13@gmail.com> - 5.12-2
+- Add optional dependencies for fedora-messaging support
 
-* Fri Feb 22 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.3-1
-- Update to pagure 5.3
+* Thu Jan 07 2021 Neal Gompa <ngompa13@gmail.com> - 5.12-1
+- Update to 5.12 (RH#1913480)
 
-* Mon Jan 07 2019 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.2-1
-- Update to pagure 5.2
+* Thu Sep 24 2020 Neal Gompa <ngompa13@gmail.com> - 5.11.3-2
+- Backport various fixes from upstream
 
-* Thu Oct 11 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.1.3-1
-- Update to pagure 5.1.3
+* Tue Aug 11 2020 Neal Gompa <ngompa13@gmail.com> - 5.11.3-1
+- Update to 5.11.3 (RH#1868029)
 
-* Thu Oct 11 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.1.2-1
-- Update to pagure 5.1.2
+* Tue Aug 04 2020 Neal Gompa <ngompa13@gmail.com> - 5.11.2-1
+- Update to 5.11.2 (RH#1862974)
 
-* Tue Oct 09 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.1.1-1
-- Update to pagure 5.1.1
+* Tue Jul 28 2020 Fedora Release Engineering <releng@fedoraproject.org> - 5.10.0-12
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_33_Mass_Rebuild
 
-* Tue Oct 09 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.1-1
-- Update to pagure 5.1
+* Sun Jun 21 2020 Neal Gompa <ngompa13@gmail.com> - 5.10.0-11
+- Backport various fixes from upstream
+- Add patch to use whitenoise for serving static assets
 
-* Thu Sep 27 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.0.1-1
-- Update to pagure 5.0.1
+* Tue Jun 02 2020 Neal Gompa <ngompa13@gmail.com> - 5.10.0-10
+- Backport various fixes from upstream
 
-* Mon Sep 24 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 5.0-1
-- Update to pagure 5.0
+* Sat May 30 2020 Neal Gompa <ngompa13@gmail.com> - 5.10.0-9
+- Fix installability of web-apache-httpd subpackage on EL7
 
-* Mon Sep 17 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 4.93.0-1
-- Update to 4.93.0, fourth beta release of pagure 5.0
+* Tue May 26 2020 Miro Hrončok <mhroncok@redhat.com> - 5.10.0-8
+- Rebuilt for Python 3.9
 
-* Wed Aug 29 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 4.92.0-1
-- Update to 4.92.0, third beta release of pagure 5.0
+* Wed May 20 2020 Neal Gompa <ngompa13@gmail.com> - 5.10.0-7
+- Backport support for STARTTLS support for SMTP servers
 
-* Thu Aug 23 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 4.91.0-1
-- Update to 4.91.0, second beta release of pagure 5.0
+* Sat May 16 2020 Neal Gompa <ngompa13@gmail.com> - 5.10.0-6
+- Backport fix for stats
+- Add missing step to start pagure web services for nginx setup in quickstart
 
-* Mon Aug 20 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 4.90.0-1
-- Update to 4.90.0, first beta release of pagure 5.0
+* Thu May 14 2020 Neal Gompa <ngompa13@gmail.com> - 5.10.0-5
+- Install missing pagure_authorized_keys_worker service
 
-* Thu Jul 19 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 4.0.4-1
-- Update to 4.0.4
+* Thu May 14 2020 Neal Gompa <ngompa13@gmail.com> - 5.10.0-4
+- Fix thinko in quick start instructions
 
-* Mon May 14 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 4.0.3-1
-- Update to 4.0.3
+* Thu May 14 2020 Neal Gompa <ngompa13@gmail.com> - 5.10.0-3
+- Add Obsoletes for package split of webserver configuration
 
-* Mon May 14 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 4.0.2-1
-- Update to 4.0.2
+* Thu May 14 2020 Neal Gompa <ngompa13@gmail.com> - 5.10.0-2
+- Bump to build in EPEL8
 
-* Thu Apr 26 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 4.0.1-1
-- Update to 4.0.1
+* Thu May 14 2020 Neal Gompa <ngompa13@gmail.com> - 5.10.0-1
+- Update to 5.10.0 (RH#1836004)
+- Clean up spec for better suitability for container deployments
+- Refresh quick start instructions for new configuration options
+- Drop unneeded patch
 
-* Thu Apr 26 2018 Pierre-Yves Chibon <pingou@pingoured.fr> - 4.0-1
-- Update to 4.0
-- Changelog is from now on included in the doc/ folder
+* Mon Mar 30 2020 Neal Gompa <ngompa13@gmail.com> - 5.9.1-1
+- Update to 5.9.1 (RH#1818753)
+- Downgrade gitolite3 dependency to Recommends per CPE team request
 
-* Thu Dec 21 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.13.2-1
-- Update to 3.13.2
-- Fix ordering issues by author using an alias so the User doesn't collide
+* Wed Mar 25 2020 Neal Gompa <ngompa13@gmail.com> - 5.9.0-1
+- Update to 5.9.0 (RH#1816636)
 
-* Tue Dec 19 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.13.1-1
-- Update to 3.13.1
-- Add an alembic migration removing a constraint on the DB that not only no
-  longer needed but even blocking regular use now
+* Wed Jan 29 2020 Fedora Release Engineering <releng@fedoraproject.org> - 5.8.1-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_32_Mass_Rebuild
 
-* Mon Dec 18 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.13-1
-- Update to 3.13
-- Fix the alembic migration adjusting the pull_requests table
-- Fix how is created the db in the docker development environment (Clement
-  Verna)
-- Ensure optional dependencies remain optional
-- Ensure groups cannot be created when it is not allowed
-- When listing issues, include the project as well in the user's issue API
-  endpoint
-- Sort forks by date of creation (descending) (Neha Kandpal)
-- Ensure the pagination arguments are returned when a page is specified
-- Make the milestone clickable on the issue page
-- Make the celery tasks update their status so we know when they are running (vs
-  pending)
-
-* Fri Dec 08 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.12-1
-- Update to 3.12
-- Adjust the API endpoint listing project to not return a 404 when not projects
-  are found (Vivek Anand)
-- Remove --autoreload from the docker dev deployment (Vivek Anand)
-- Fix ordering issues (Patrick Uiterwijk)
-- Do not log actions pertaining to private issues, PRs or projects
-- Fix flagging a PR when no uid is specified
-- Fix the doc about custom gitolite config
-- Fix displaying the filename on the side and linking to file for remote PRs
-- Add irc info in Readme (Vivek Anand)
-- Make pagure compatible with newer python chardet
-- Check that the identifier isn't the hash of a git tree in view_file
-- Fix if the identifier provided is one of a blob instead of a commit in
-  view_commit
-- Include the status when flagging a PR via jenkins
-- Enable OpenID Connect authentication (Slavek Kabrda)
-- Use the updated timestamp in the pull-request list
-- Add migration to fix the project_from_id foreign key in pull_requests
-- Let the SSE server to send the notifications so they can be displayed live
-- Improve the createdb script to support stamping the database in the initial
-  run
-- Specify a different connection and read timeout in pagure-ci
-- Small CSS fix making the (un)subscribe show up on the PR page
-
-* Wed Nov 29 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.11.2-1
-- Update to 3.11.2
-- Fix giving a project if no user is specified
-- Don't show issue stats when issues are off
+* Mon Dec 02 2019 Neal Gompa <ngompa13@gmail.com> - 5.8.1-1
+- Update to 5.8.1 (RH#1778787)
+
+* Sat Nov 16 2019 Neal Gompa <ngompa13@gmail.com> - 5.8-1
+- Update to 5.8 (RH#1744065)
+
+* Thu Oct 03 2019 Miro Hrončok <mhroncok@redhat.com> - 5.7.4-4
+- Rebuilt for Python 3.8.0rc1 (#1748018)
+
+* Mon Aug 19 2019 Miro Hrončok <mhroncok@redhat.com> - 5.7.4-3
+- Rebuilt for Python 3.8
+
+* Sun Aug 11 2019 Neal Gompa <ngompa13@gmail.com> - 5.7.4-2
+- Fix httpd conf path in README.Fedora
+
+* Sun Aug 11 2019 Neal Gompa <ngompa13@gmail.com> - 5.7.4-1
+- Update to 5.7.4
+
+* Thu Jul 25 2019 Fedora Release Engineering <releng@fedoraproject.org> - 5.5-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_31_Mass_Rebuild
+
+* Tue Apr 09 2019 Neal Gompa <ngompa13@gmail.com> - 5.5-1
+- Update to 5.5
+- Backport fix for pull mirroring feature
+
+* Fri Mar 29 2019 Neal Gompa <ngompa13@gmail.com> - 5.4-1
+- Update to 5.4
+- Backport fix for using pagure-ev on Python 3
+- Add patch to allow pagure to install with SQLAlchemy 1.3.0+
+- Add initial README.Fedora to document a quick-start setup process
+
+* Fri Feb 22 2019 Neal Gompa <ngompa13@gmail.com> - 5.3-1
+- Update to 5.3
+- Add weak dependencies for supported database client libraries
+- Use macros consistently in the spec
+
+* Fri Feb 01 2019 Fedora Release Engineering <releng@fedoraproject.org> - 5.2-3
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_30_Mass_Rebuild
+
+* Mon Jan 07 2019 Neal Gompa <ngompa13@gmail.com> - 5.2-2
+- Ensure all shebangs are set to the correct Python version
+- Fix RHEL conditionals to account for EL8
+- Fix pygit2 dependency for EL7
+
+* Mon Jan 07 2019 Neal Gompa <ngompa13@gmail.com> - 5.2-1
+- Update to 5.2
+
+* Fri Dec 14 2018 Neal Gompa <ngompa13@gmail.com> - 5.1.4-2
+- Backport fix from master to add compatibility with Markdown 3.0+
+- Backport fix from master to properly skip legacy hooks
+
+* Tue Oct 30 2018 Neal Gompa <ngompa13@gmail.com> - 5.1.4-1
+- Update to 5.1.4
+
+* Thu Oct 11 2018 Neal Gompa <ngompa13@gmail.com> - 5.1.3-1
+- Update to 5.1.3 (RH#1638470)
+
+* Tue Oct 09 2018 Neal Gompa <ngompa13@gmail.com> - 5.1.1-1
+- Update to 5.1.1 (RH#1637595)
+
+* Tue Oct 09 2018 Neal Gompa <ngompa13@gmail.com> - 5.1-1
+- Update to 5.1 (RH#1637516)
+
+* Sat Sep 29 2018 Neal Gompa <ngompa13@gmail.com> - 5.0.1-2
+- Fix symlinks broken or missing due to setuptools
+
+* Sat Sep 29 2018 Neal Gompa <ngompa13@gmail.com> - 5.0.1-1
+- Update to 5.0.1 (RH#1634318)
+
+* Mon Sep 24 2018 Neal Gompa <ngompa13@gmail.com> - 5.0-1
+- Update to 5.0 (RH#1632468)
+
+* Mon Sep 17 2018 Neal Gompa <ngompa13@gmail.com> - 4.93.0-1
+- Rebase to 4.93.0 (5.0 beta 4)
+- Pagure is now using Python 3 on Fedora
+
+* Sat Jul 28 2018 Igor Gnatenko <ignatenkobrain@fedoraproject.org> - 4.0.4-2
+- Generate dependencies automatically
+
+* Tue Jul 24 2018 Neal Gompa <ngompa13@gmail.com> - 4.0.4-1
+- Rebase to 4.0.4
+- Add patch from Mageia to backport fix for pagure-milters
+
+* Fri Jul 13 2018 Fedora Release Engineering <releng@fedoraproject.org> - 3.13.2-4
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_29_Mass_Rebuild
+
+* Thu Mar 01 2018 Iryna Shcherbina <ishcherb@redhat.com> - 3.13.2-3
+- Update Python 2 dependency declarations to new packaging standards
+  (See https://fedoraproject.org/wiki/FinalizingFedoraSwitchtoPython3)
+
+* Thu Feb 08 2018 Fedora Release Engineering <releng@fedoraproject.org> - 3.13.2-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild
+
+* Thu Dec 21 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.13.2-1
+- Update to 3.13.2
 
 * Tue Nov 28 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.11.1-1
 - Update to 3.11.1
-- Fix showing the issue list
-- Make clear in the project's settings that tags are also for PRs (Clement
-  Verna)
-- Remove unused jdenticon js library (Shengjing Zhu)
-
-* Mon Nov 27 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.11-1
-- Update to 3.11
-- Print out the URL to existing PR(s) or to create one on push
-- Reword the repository access warning (Matt Prahl)
-- Add pagure-admin admin-token update to update the expiration date
-- Fix the api_view_user_activity_stats to return the expected data (post flask
-  0.11)
-- Add small icon showing if issues are blocked or blocking in the issue list
-- Replace all print statements with print function calls (Vadim Rutkovski)
-- Add a default_priority field to projects
-- Bail on merge a PR that is already closed
-- Add a graph of the history of the open issues on the project
-- Make the pagure hook act as the person doing the push
-- Clean spec file to drop deprecated lines and macros (Igor Gnatenko)
-- Include selectize in the settings page to fix the autocomplete in the give
-  project action
-- Do not display the close_status if there isn't one
-- Do not show the `Fork and edit` button all the time
-- Allow project maintainer to set metadata when creating a new issue (expand the
-  API as well)
-- Add a timeout when trying to query jenkins
-- Show the reply button even if the PR/issue is closed.
-- Add a diff view for PR
-- Improve the `My star` page
-- Introduce repo statistics
-- When a project enforce signed-off-by, clearly say so on the new PR page and
-  properly block the PR from being created
-- Adjust button title on the 'Fork and Edit' action
-- Fix typos in the code (chocos10)
-- When editing an issue, act as the person who pushed the change
-- Commit using the user's fullname if there is one, otherwise its username
-- Expand the group info API endpoint
-- Sorting on Opened, Modified, Closed, Priority, Reporter, Assignee cols (Mohan
-  Boddu and Matt Prahl)
-- Fix the Vagrant setup (Ryan Lerch)
-- Fix typo in the example pagure.wsgi file (Vivek Anand)
-- Add API endpoints for listing pull requests for a user (Ryan Lerch)
-- Ask for the post-commit hook to be run when editing files via the UI
-- Fix the milter for email gpg signed
-- Allow filtering the user's project by access level
-- Add a modal at the bottom of the issues list to add milestones
-- Add a field to store the order of the milestones
-- Hide the ``+`` button on the index page when it is disabled in the UI
-- Improve mimetype detection (Shengjing Zhu and Clement Verna)
-- Allow assignee to drop their assignment
-- Remove duplicate [Pagure] from mail subjects (Stefan Bühler)
-- Fix undefined 'path' in blame.html template (Stefan Bühler)
-- Warn users when a project does not support direct push
-- Update gitolite's config for the project when set to PR only
-- Do not report the branch differing master if PRs have been turned off
-- Add a button and an API endpoint to subscribe to PR's notifications
-- Fix showing the file names in PR (pre)view
-- Fix number of typos in the documentation (René Genz)
-- Improve the documentation about documentation hosting in pagure (René Genz)
-- Allow priorities and milestones to be 0 or -1
-- Return the flag UID when adding or updating a flag on a PR not in fedmsg
-- Add flags on commits
-- Add documentation about flags on commits and PRs
-- Add status fields to flags
-- Make flag's UID be unique to the commit/PR being flagged
-- Add API endpoint to retrieve all issues related to an user across all repos
-- Fix the new PR and delete buttons for branch name with + in them
-- When merging a PR, call the post-update hook on the target repo
-- Add tags to pull-request
-- Fix documentation for fork API endpoint (ishcherb)
-- Send fedmsg messages when deleting a project (Shaily)
-
-* Fri Oct 13 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.10.1-1
-- Update to 3.10.1
-- Fix providing access to some of the internal API endpoints by javascript
-
-* Fri Oct 13 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.10-1
-- Update to 3.10
-- Show the branches' head in the commit list
-- Log which IP is being denied access to the internal endpoints (makes debugging
-  easier)
-- Link to pagure's own markdown documentation and warn that remote images are
-  not supported
-- Document how to run a single test file or a single test in a file
-- Fix trying to decode when the encoding is None
-- Include an url_path field in the JSON representation of a project
-- Generalize the description of the ACLs (since we know have project-less API
-  tokens)
-- Drop ``--autoreload`` from the .service files as celery dropped support for it
-  and it never really worked (Vivek Anand)
-
-* Wed Oct 11 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.9-1
-- Update to 3.9
-- Fix the editing issue when the user does not actually edit anything
-- Fix the internal API endpoint: get branches of commit to support namespace
-- Consolidate the code in our custom markdown processor (fixes linking to a
-  commit on a namespaced project)
-- Fix deleting a project by also removing it from the gitolite config
-- Warn if the user is about to just recompile the gitolite config via
-  pagure-admin (Patrick Uiterwijk)
-- Update .git/config example in doc/usage/pull_requests.rst (sclark)
-- Include the PRs opened by the user on the 'My pull-requests' page
-- Add to pagure-admin the actions: get-watch and update-watch
-- Add to pagure-admin the action: read-only
-- Add the user's fullname (if there is one) as title when they comment
-- Fix the title of the percentage when hovering over the red bar in issues
-- Make the box to edit comments bigger
-- Document in the usage section where to find the API documentation
-- Provide the sha256 and sha512 of the releases in a CHECKSUMS file
-- Remove clear buttons (Till Maas)
-
-* Fri Sep 29 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.8-1
-- Update to 3.8
-- Fix API documentation for git/branch (Matt Prahl)
-- Fix giving a project to someone who already has access (Matth Prahl)
-- Add some border to the tables created in README files
-- Ask the user to confirm merging a pull-request
-- Fix processing status and close_status updates in the SSE
-- Fix the URL to the issue used by the SSE JS on tags
-- Increase the logging in the milter to help figuring out issues in the future
-- Fix the In-Reply-To header when sending notifications
-- Fix showing the delete project button
-- Fix search issues with a unicode character
-- Catch exception raised when accessing the head of the repo
-- Fix deleting a project when some of the folder are not used
-- Allow viewing a PR when its origin (fork or branch) is gone
-- Fix linking to issue or PR in namespaced projects via #<id>
-- Make it more obvious that the namespace and the project are different links
-- Tell fedmsg to send things with pagure certificates (Patrick Uiterwijk)
-- Fix loading ticket templates on namespaced project and extracting their names
-- Add a banner on the overview page when the ACLs are being refreshed on the
-  backend (and thus ssh access may not be entirely functional) (Vivek Anand)
-- Update the documentation on how to create pull requests (Clement Verna)
-- Add button to refresh external pull requests (Patrick Uiterwijk)
-- Add the possibility to get the group members when asking the project info
-- Make the PROJECT_NAME_REGEX used in form be configurable
-- Adjust the milter to support replying with any email addresses associated
-- Allow pagure admin to give a project
-
-* Tue Sep 05 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.7.1-1
-- Update to 3.7.1
-- Fix the UPGRADING documentation
-- Add the API endpoint to edit multiple custom fields to the doc (Clement
-  Verna)
-
-* Tue Sep 05 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.7-1
-- Update to 3.7
-- Update link to markdown documentation, fix typo on the way (Till Hofmann)
-- Add feature allowing to prevent project creation in the UI only
-- Remove the front whitespace from the commit markdown regex (Clement Verna)
-- New API endpoint to modify multiple custom fields (Clement Verna)
-- Update the example output of the API endpoint giving project information
-- Add the ability to order issues by ascending or descending (Matt Prahl)
-- Consolidate around pagure.lib.git.generate_gitolite_acls
-- Regenerate the gitolite ACL when changing the main admin of a project
-- Change the documentation link end point (Clement Verna)
-- Fixes the README.rst file (Ompragash)
-- Update Docker Environment (Clement Verna)
-- Add a configuration key to allow deleting forks but not projects
-- Show the entire project name in the UI on the delete button
-- Add support for a custom user in the SSH URL
-- Do not show the SSH url when the user isn't logged in
-- Update the documentation on how to work with pull requests (Clement Verna)
-- Support both JSON and Form POST on APIs that accepted only JSON (Matt Prahl)
-- Don't expand groups in the watchers API (Ralph Bean)
-- Add a new branch API (Matt Prahl)
-- Add bash function example to PR documentation (Clement Verna)
-- Add the star project feature (Vivek Anand)
-- Update the overview diagram
-- Fix the rendering of the API version in the html page (Clement Verna)
-- Fix message-id not having FQDN (Sachin Kamath)
-- Mention on what the rebase was done
-- Remove the line numbers coming from pygments on pull-requests
-- Include the targeted branch in the list of PRs
-- Separately link user/namespace/name
-- Fix the pagination when listing projects via the view_projects endpoints
-- Retain access when transfering ownership of the project (Matt Prahl)
-
-* Mon Aug 14 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.6-1
-- Update to 3.6
-- Blacklist creating a group named 'group'
-- Allow having a dedicated worker to compile the gitolite configuration file
-- Fix removing groups of a project
-- Make the API returns only open issues by default (as documented) (Clement
-  Verna)
-- Improve the README regarding the use of eventlet to run the tests (Vivek
-  Anand)
-- Give Pagure site admins the ability to modify projects using the API (Matt
-  Prahl)
-- Add the "git/generateacls" API endpoint for projects (Matt Prahl)
 
-* Tue Aug 08 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.5-1
+* Thu Aug 10 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.5-1
 - Update to 3.5
-- Fix login when groups are managed outside
-- Fix the ordering of the issues by priority using JS and its documentation
-- Indicate the issue/PR status in the title of its link
-- Correct typo in waiting page template: 'You task' -> 'Your task' (Hazel Smith)
-- Fix redirect in search (Carl George)
-- Fix removing users of a project
-- Allow customizing the HTML title globally
-- Drop the new line character and the '# end of body' message when loading the
-  config
-- Scroll to the comment section on clicking reply. (shivani)
-- only show issues on the My Issue page if the issue tracker is on for the
-  project (Vivek Anand)
-- Update the refresh-gitolite action of pagure-admin for the new interface
-  (turns out this wasn't in fact merged in 3.4)
-- Add a configuration key to make pagure case sensitive
-- Add an USER_ACLS configuration key
-- Document the different API token ACLs configuration keys
-- Fix syncing groups from external account sources (Patrick Uiterwijk)
-
-* Mon Jul 31 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.4-1
-- Update to 3.4
-- Fix layout breakage in the doc
-- Stop using readlines() to drop the trailing new line character
-- Fix logging by properly formatting the message
-- Fix the issue count in the My Issues page (Vivek Anand)
-- Add a configuration key to disable deleting branches from the UI
-- Add a configuration key to disable managing user's ssh key in pagure
-- Fix the vagrant environment (Clement Verna)
-- Fix branch support for the git blame view
-- Update the PR ref when the PR is updated
-- Add a configuration key to disable the deploy keys in a pagure instance
-- Fix login when groups are managed outside of pagure
-- Fix setting up the git hooks when there is no DOCS_FOLDER set
-- Fix installing up the pagure hooks when there is no DOCS_FOLDER set
+- Reverting to py-bcrypt
+
+* Wed Aug 09 2017 Gwyn Ciesla <limburgher@gmail.com> - 3.3.1-3
+- Switch to python-bcrypt, BZ 1473018.
+
+* Thu Jul 27 2017 Fedora Release Engineering <releng@fedoraproject.org> - 3.3.1-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild
 
 * Mon Jul 24 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.3.1-1
 - Update to 3.3.1
-- Fix typo in the alembic migration present in 3.3
+- Fixes a typo in the alembic migration script introduced in 3.3
 
 * Mon Jul 24 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.3-1
+- Update to 3.3
 - [SECURITY FIX] block private repo (read) access via ssh due to a bug on how we
   generated the gitolite config - CVE-2017-1002151 (Stefan Bühler)
-- Add the date_modified to projects (Clement Verna)
-
-* Fri Jul 14 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.2.1-1
-- Fix a syntax error on the JS in the wait page
-
-* Fri Jul 14 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.2-1
-- Update to 3.2
-- Use a decorator to check if a project has an issue tracker (Clement Verna)
-- Optimize generating the gitolite configuration for group change
-- Fix the issue_keys table for mysql
-- Drop the load_from_disk script
-- Fix next_url URL parameter on the login page not being used (Carlos Mogas da
-  Silva)
-- Support configuration where there are no docs folder and no tickets folder
-- Show all the projects a group has access to
-- Add pagination to the projects API (Matt Prahl)
-- Simplify diff calculation (Carlos Mogas da Silva)
-- Show the inline comment in the PR's comments by default (Clement Verna)
-- Fix the URL in the API documentation for creating a new project (Matt Prahl)
-
-* Tue Jul 04 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.1-1
-- Update to 3.1
-- Allow project-less API token to create new tickets
-- Tips/tricks: add info on how to validate local user account without email
-  verification (Vivek Anand)
-- Optimize the generation of the gitolite configuration
-- Improve logging and load only the plugin of interest instead of all of them
-- Show the task's status on the wait page and avoid reloading the page
-- Don't show '+' sign when GROUP_MNGT is off (Vivek Anand)
-
-* Fri Jun 30 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 3.0-1
-- Update to 3.0
-- Since 2.90 celery has become a requirement as well as one of the queueing
-  system it supports (pagure defaults to using redis)
-- Multiple stability and performance improvements (mainly thanks to Patrick
-  Uiterwijk)
-- Fix the assignee value in fedmsg when assigning a ticket (Ricky Elrod)
-- Make pagure support bleach 2.0.0 (Shengjing Zhu)
-- Fixes in CI support (Tim Flink)
-- Update the documentation
-- Fix plain readme html escape (Shengjing Zhu)
-- Refactor user existence code in API and UI (Abhijeet Kasurde)
-- Add an API to modify a Pagure project's owner (Matt Prahl)
-- Support for uploading multiple files to an issue at once
-- Introduce the external committer feature
-- Add the required groups feature
-- Add an API endpoint to get the git urls of a project (Matt Prahl)
-- Blacklist 'wait' as project name
-- Add a border to the search box on the side bar to the documentation
-- Add the list-id, list-archive and X-Auto-Response-Suppress email headers
-- Add ways to customize the gitolite configuration file with snippets
-- Return a 404 on private ticket if the user is not authenticated
-- cleanup: move static js/css to vendor dir
-- Limit the requests version as it conflicts with our chardet requirement
-- Rename all the services to pagure-*
-- Remove 'on <project name' - watch status dropdown (Vivek Anand)
-- Create references for pull-request in the git repo for local checkout
-- Use the entire list of users for the assignee field completion
-- Fix searching for groups
-- Make the search work when searching for project with namespaces or forks
-- Return a human-friendly error message when upload fails
-- Let acting on the status potentially set the close_status and vice versa
-- Multiple fixes to the SSE server
-- When forking a project, wait until the very end to let the user go through
-- Allow customizing the writing of gitolite's configuration file
-- Fix diffing the branch of a project against the target branch
-- Fix displaying the new PR button on the default branch
-- Do not send a notification upon merge conflicts
-- Do not let pagure return 500 when hit with bogus URL
-- When loading comment from JSON rely on username/comment rather than comment id
-- When deleting a comment, refresh the ticket git repo
-- Make patch_to_diff use lists instead of string concatenation (Patrick
-  Uiterwijk)
-
-* Wed May 24 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.90.1-1
-- Update to 2.90.1
-- Fix the systemd service file for the worker, needs to have the full path
-  (Patrick Uiterwijk and I)
-- Fix the logcom server (Patrick Uiterwijk)
-- Use python-redis instead of trollius-redis to correctly clean up when client
-  leaves on the EV server (Patrick Uiterwijk)
-
-* Tue May 23 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.90.0-1
-- Bump to 2.90, pre-release of 3.0
-- Re-architecture the interactions with git (especially the writing part) to be
-  handled by an async worker (Patrick Uiterwijk)
-- Add the ability to filter projects by owner (Matt Prahl)
-
-* Thu May 18 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.15.1-1
-- Update to 2.15.1
-- Fix the requirements on straight.plugin in the requirements.txt file
-  (Shengjing Zhu)
-- Fix typo in the fedmsg hook so it finds the function where it actually is
-- Fix and increase the logging when merging a PR
-- Fix pushing a merge commit to the original repo
-- Use psutil's Process() instead of looping through all processes (Patrick
-  Uiterwijk)
-- Don't email admins for each PR conflicting
-- Fix/improve our new locking mechanism (Patrick Uiterwijk)
-- Drop making the token required at the database level since pagure-ci doesn't
-  use one (but do flag pull-requests)
-- Fix the watch feature (Matt Prahl)
-
-* Tue May 16 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.15-1
-- Update to 2.15
-- Improve logic in api/issue.py to reduce code duplication (Martin Basti)
-- Fix the download button for attachment (Mark Reynolds)
-- Fix our markdown processor for strikethrough
-- Add a spinner indicating when we are retrieving the list of branches differing
-- Make add_file_to_git use a lock as we do for our other git repositories
-- Add the opportunity to enforce a PR-based workflow
-- Store in the DB the API token used to flag a pull-request
-- Allow people with ticket access to take and drop issues
-- Display the users and groups tied to the repo in the API (Matt Prahl)
-- Document our markdown in rest so it shows up in our documentation
-- Fix comparing the minimal version of flask-wtf required
-- Allow the td and th tags to have an align attribute to allow align in html
-  tables via markdown
-- Avoid binaryornot 0.4.3 and chardet 3.0.0 for the time being
-- Add group information API that shows group members (Matt Prahl)
-- Ensure people with ticket metadata can edit the custom fields
-- Add support to create private projects (Farhaan Bukhsh) - Off by default
-- Link to the doc when the documentation is activated but has no content
-- Enforce project wide flake8 compliance in the tests
-- Enforce a linear alembic history in the tests
-- Increase logging in pagure.lib.git
-- Use custom logger on all module so we can configure finely the logging
-- Multiple improvements to the documentation (René Genz)
-- Add the ability to query projects by a namespace in the API (Matt Prahl)
-- Add the /<repo>/git/branches API endpoint (Matt Prahl)
-- Lock the git repo when removing elements from it
-- Always remove the lockfile after using it, just check if it is still present
-- Implement the `Give Repo` feature
-- Allow project-less token to change the status of an issue in the API
-- Make the watch feature more granular (Matt Prahl): you can now watch tickets,
-  commits, both, neither or go back to the default
-- Bring the pagure.lib coverage to 100% in the tests (which results to bug fixes
-  in the code)
-- Add locking at the project level using SQL rather than filelock at the git
-  repo level
-
-* Wed Mar 29 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.14.2-1
-- Update to 2.14.2
-- Fix a bug in the logic around diff branches in repos
 
 * Wed Mar 29 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.14.1-1
 - Update to 2.14.1
-- Fix typo for walking the repo when creating a diff of a PR
-- Have the web-hook use the signed content and have a content-type header
-- Fix running the tests on jenkins via a couple of fixes to pagure-admin and
-  skipping a couple of tests on jenkins due to the current pygit2/libgit2
-  situation in epel7
-
-* Mon Mar 27 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.14-1
-- Update to 2.14
-- Update the label of the button to comment on a PR (Abhijeet Kasurde)
-- Make search case insensitive (Vivek Anand)
-- Improve the debugging on pagure_loadjson
-- Only link the diff to the file if the PR is local and not remote
-- Do not log on fedmsg edition to private comment
-- When deleting a project, give the fullname in the confirmation window
-- Add link to the FPCA indicating where to sign it when complaining that the
-  user did not sign it (Charelle Collett)
-- Fix the error: 'Project' object has no attribute 'ci_hook'
-- Fix input text height to match to button (Abhijeet Kasurde)
-- Fix the data model to make deleting a project straight forward
-- Fix searching issues in the right project by including the namespace
-- When creating the pull-request, save the commit_start and commit_stop
-- Ensure there is a date before trying to humanize it
-- Fixing showing tags even when some of them are not formatted as expected
-- Allow repo user to Take/Drop assigment of issue (Vivek Anand)
-- Add merge status column in pull requests page (Abhijeet Kasurde)
-- Allow user with ticket access to edit custom fields, metadata and the privacy
-  flag (Vivek Anand)
-- Add number of issues in my issues page (Abhijeet Kasurde)
-- Allow report to filter for a key multiple times
-- Add the support to delete a report in a project
-- Fix rendering the roadmap when there are tickets closed without a close date
-- Fix to show tabs in pull request page on mobile (Abhijeet Kasurde)
-- Document some existing API endpoints that were missing from the doc
-- Make issues and pull-requests tables behave in responsive way (Abhijeet Kasurde)
-- Add option to custom field for email notification (Mark Reynolds)
-- When resetting the value of a custom field, indicate what the old value was
-- Add instance wide API token
-- Move the admin functions out of the UI and into a CLI tool pagure-admin
-- Do not update the hash in the URL for every tabs on the PR page
-- Fix heatmap to show current datetime not when when object was created (Smit
-  Thakkar and Vivek Anand)
-- Do not include watchers in the subscribers of a private issue
-- Do not highlight code block unless a language is specified
-- Make getting a project be case insensitive
-- Do not change the privacy status of an issue unless one is specified
-- Fix the logic of the `since` keyword in the API (Vivek Anand)
-- Fix the logic around ticket dependencies
-- Add reset watch button making it go back to the default (Vivek Anand)
-- Do not show dates that are None object, instead make them empty strings
-- Allow filtering tickets by milestones in the API
-- Allow filtering tickets by priorities in the API
-- Expand the API to support filtering issues having or not having a milestone
-- Use plural form for SSH key textfield (Martin Basti)
-- Support irc:// links in our markdown and adjust the regex
-- Remove backticks from email subject (Martin Basti)
-- Adjust the logic when filtering issues by priorities in the API
-- Remove mentioning if a commit is in master on the front page
-- Optimize finding out which branches are in a PR or can be
-- Add required asterisk to Description on new issues (Abhijeet Kasurde)
-- Fix misc typo in 404 messages (Abhijeet Kasurde)
-- Add performance git repo analyzer/framework (Patrick Uiterwijk)
-- Added tip_tricks in doc to document how to pre-fill issues using the url
-  (Eashan)
-- Document how to filter out for issues having a certain tag in the tips and
-  tricks section
-- Allow to manually triggering a run of pagure-ci via a list of sentences set in
-  the configuration
-- Add support for admin API token to pagure-admin
-- Make clicking on 'Unassigned' filter the unassigned PR as it does for issues
-- Add Priority column to My Issues page (Abhijeet Kasurde)
-- Optimize diffing pull-requests
-- Add a description to the API tokens
-- Include the fullname in the API output, in the project representation
-- Add the possibility to edit issue milestone in the API (Martin Basti)
-- Fix some wording (Till Maas)
-- Rename "request pull" to pull request (Stanislav Laznicka)
-- Make tags in issue list clickable (Martin Basti)
-- Include the priority name in the notification rather than its level
-- Update the ticket metadata before adding the new comment (if there is one)
-
-* Fri Feb 24 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.13.2-1
-- Update to 2.13.2
-- Fix running the test suite due to bugs in the code:
-- Fix picking which markdown extensions are available
-- Fix rendering empty text files
-
-* Fri Feb 24 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.13.1-1
+
+* Wed Mar 01 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.13.1-1
 - Update to 2.13.1
-- Add a cancel button on the edit file page (shivani)
-- Fix rendering empty file (Farhan Bukhsh)
-- Fix retrieving the merge status of a pull-request when there is no master
-- On the diff of a pull-request, add link to see that line in the entire file
-  (Pradeep CE)
-- Make the pagure_hook_tickets git hook file be executable
-- Be a little more selective about the markdown extensions always activated
-- Do not notify the SSE server on comment added to a ticket via git
-- Fix inline comment not showing on first click in PR page (Pradeep CE)
-
-* Tue Feb 21 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.13-1
-- Update to 2.13
-- Allow filtering issues for certain custom keys using <key>:<value> in the
-  search input (Patric Uiterwijk)
-- Make loading the JSON blob into the database its own async service
-- Add ACLs to pagure (Vivek Anand)
-- Fix running the tests against postgresql
-- Let the doc server return the content as is when it fails to decode it
-- Fix rendering a issue when one of the custom fields has not been properly
-  setup (ie a custom field of type list, with no options set-up but still having
-  a value for that ticket)
-- Fix auto-completion when adding a tag to a ticket
-- Add the possibility to filter the issues with no milestone assigned (Mark
-  Reynolds)
-- Fix the callback URL for jenkins for pagure-ci
-- Backport the equalto test to ensure it works on old jinja2 version (fixes
-  accessing the user's PR page)
-
-* Mon Feb 13 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.12.1-1
-- Update to 2.12.1
-- Include the build id in the flag set by pagure-ci on PR (Farhaan Bukhsh)
-- Fix using the deploy keys (Patrick Uiterwijk)
-- Add the possibility to ignore existing git repo on disk when creating a new
-  project
-- Fix checking for blacklisted projects if they have no namespace
-- Link to the documentation in the footer (Rahul Bajaj)
-- Fix retrieving the list of branches available for pull-request
-- Order the project of a group alphabetically (case-insensitive)
-- Fix listing the priorities always in their right order
-
-* Fri Feb 10 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.12-1
-- Update to 2.12
-- Fix the place of the search and tags bars in the issues page (Pradeep CE)
-- Support removing all content of a custom field (Patrick Uiterwijk)
-- Improve the `My Pull Requests` page (Pradeep CE)
-- Fix displaying binary files in the documentation
-- Add a way to easily select multiple tags in the issues list and roadmap
-- Allow selecting multiple milestones easily in the UI of the roadmap
-- Fix displaying namespaced docs (Igor Gnatenko)
-- Fix the web-hook server
-- Add a way to view patch attached to a ticket as raw
-- Allow milestone to be set when creating an issue using the API (Mark Reynolds)
-- Fix adding and editing tags to/of a project
-- Make the usage section of the doc be at the top of it (Jeremy Cline)
-- Add notifications to issues for meta-data changes (Mark Reynolds)
-- Fix not updating the private status of an issue when loading it from JSON
-  (Vivek Anand)
-- Fix triggering web-hook notifications via the fedmsg hook
-- Add a configuration key allowing to hide some projects that users have access
-  to only via these groups
-- Fix figuring out which branches are not merged in namespaced project
-- Automatically link the commits mentionned in a ticket if their hash is 7 chars
-  or more
-- Allow dropping all the priorities info of an issue
-- Do not edit multiple times the milestone info when updating a ticket
-- Only update the custom field if there is a value to give it, otherwise remote
-  it
-- Make pagure compatible with flask-wtf >= 0.14.0
-- Add a button to test web-hook notifications
-- Fix the layout on the page listing all the closed issues (Rahul Bajaj)
-- Load priorities when refreshing the DB from the ticket git repos (Mark
-  Reynolds)
-- Ignore `No Content-Type header in response` error raised by libgit2 on pull
-  from repo hosted on github (for remote PR)
-- Add deployment keys (ssh key specific for a single project can be either read
-  and write or read-only) (Patrick Uiterwijk)
-- Fix install the logcom service to log commits
-- Fix deleting tickets that have a tag attached
-- Allow pre-filling title and content of an issue via URL arguments:
-  ?title=<title>&content=<issue description>
-- Re-initialize the backend git repos if there are no tickets/PRs in the DB
-  (Vivek Anand)
-- Fix invalid pagination when listing all the tickets (regardless of their
-  status) and then applying some filtering (Vibhor Verma)
+
+* Sat Feb 11 2017 Fedora Release Engineering <releng@fedoraproject.org> - 2.11-2
+- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild
 
 * Fri Jan 20 2017 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.11-1
 - Update to 2.11
-- Fix the forked repo text on the user's PR page (Rahul Bajaj)
-- Display the number of subscribers subscribed to the ticket
-- Add an attachments section to tickets (Mark Reynolds)
-- Small fixes around the git blame feature
-- Add an `Add group` button on page listing the groups (Rahul Bajaj)
-- Move the `My Issues` and `My Pull-requests` links under the user's menu
-- Document the FORK_FOLDER configuration key as deprecated
-- Display the subscribers to PR in the same way to display them on ticket
-- Adjust the wording when showing a merge commit
-- Ensure the last_updated field is always properly updated (Mark Reynolds)
-- Fix decoding files when we present or blame them
-- Disable the markdown extensions nl2br on README files
-- Make issue reports public
-- Only display modified time as the modifying user can not be determined (Mark
-  Reynolds)
-- Add a new API endpoint returning information about a specific project
-- Add a button allowing dropping of assignments for an issue easily (Paul W.
-  Frields)
-- Make attachments of ticket downloadable (Mark Reynolds)
-- Make patch/diff render nicely when viewed attached to a ticket (Mark Reynolds)
-- Filter out the currrent ticket in the drop-down list for the blocker/depending
-  fields (Eric Barbour)
-- Move the logging of the commit as activity to its own service: pagure_logcom
-- Add a new API endpoint to set/reset custom fields on tickets
-- Introduce the USER_NAMESPACE configuration key allowing to put the project on
-  the user's namespace by default
-- Fix sending notifications about pull-requests to people watching a project
-- Fix the list of blacklisted projects
-- Inform the user when they try to create a new group using a display name
-  already used (Rahul Bajaj)
-- Fix importing the milestones into the project when loading from the git repo
-  (Clement Verna)
-- Add a button to create a default set of close status (as we have a default set
-  of priorities)
-- Have pagure bail with an error message if the OpenID server did not return an
-  username
-- Let the error email use the FROM_EMAIL address set in the configuration file
-- Fix theprogress bar shown when listing issues (Gaurav Kumar)
-- Replace our current tags by colored one (Mark Reynolds)
-- Make the roadmap page use the colored tag (Mark Reynolds)
-- Fix the tag of Open pull-request when listing all the pull-requests (Rahul
-  Bajaj)
-- Remove the 'pagure.lib.model.drop_tables' from test/__init__.py file (Amol
-  Kahat)
-- Fix the headers of the table listing all the pull-request
-- Raise an exception when a PR was made against a branch that no longer exists
-- Document what to do when pull-requests are not available in a troubleshooting
-  section of the documentation
-- Send notification upon closing tickets
-- Fix re-setting the close_status to None it when re-opening a ticket
-- Fix linking to the tabs in the pull-request page (cep)
-- Adjust the rundocserver utility script to have the same arguments as runserver
-- Ensure the filtering by author remains when changing the status filter on PR
-  list (Rahul Bajaj)
-- Improve the page/process to create a new API token (Pradeep CE)
-- Prevent re-uploading a file with the same name
-- Improve the roadmap page (Mark Reynolds)
-- Improve the `My Issues` page (Mark Reynolds)
-- Fix home page 'open issues' links for namespaced projects (Adam Williamson)
-- Fix logging who did the action
-- Return a nicer error message to the user when an error occurs with a remote
-  pull-request
-- Make interacting with the different git repos a locked process to avoid
-  lost/orphan commits
-- Update API doc for api_view_user (Clement Verna)
-- Dont return 404 when viewing empty files (Pradeep CE (cep))
-- Do not automatically update the last_updated or updated_on fields
-- Make alembic use the DB url specified in the configuration file of pagure
-- Only connect to the smtp server if we're going to send an email
-- Add a type list to the custom fields (allows restricting the options) (Mark
-  Reynolds)
-- Fix displaying non-ascii milestones
-- Add the possibility to view all the milestones vs only the active ones (Mark
-  Reynolds)
-
-* Sun Dec 04 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.10.1-1
+
+* Mon Dec 26 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.10.1-1
 - Update to 2.10.1
-- Clean up the JS code in the settings page (Lubomír Sedlář)
-- Fix the URLs in the `My Issues` and `My Pull-request` pages
-
-* Fri Dec 02 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.10-1
-- Update to 2.10
-- Updating language on not found page (Brian (bex) Exelbierd)
-- Add a view for open pull requests and issues (Jeremy Cline)
-- Issue 1540 - New meta-data custom field type of "link" (Mark Reynolds)
-- Fix overflow issue with comment preview and pre (Ryan Lerch)
-- Issue 1549 - Add "updated_on" to Issues and make it queryable (Mark Reynolds)
-- Drop UPLOAD_FOLDER in favor of UPLOAD_FOLDER_URL
-- Make the group_name be of max 255 characters
-- Bug - Update documentation to match the default EMAIL_SEND value (Michael
-  Watters)
-- Change - Fix grammar in UI messages around enabling/deactivating git hooks
-  (Michael Watters)
-- Allow resetting the priorities of a project
-- Several fixes and enhancements around the activity calendarheatmap
-- Add quick_replies field to project (Lubomír Sedlář)
-- Fix blaming files containing non-ascii characters (Jeremy Cline and I)
-- Include regular contributors when checking if user is watching a project
-- List subscribers on the issue pages (Mark Renyolds and I)
-
-* Fri Nov 18 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.9-1
-- Update to 2.9
-- Fix redirecting after updating an issue on a project with namespace (Vivek
-  Anand)
-- Remove take button from Closed Issues (Rahul Bajaj)
-- Show the open date/time on issues as we do for PR (Rahul Bajaj)
-- When rendering markdown file use the same code path as when rendering comments
-- Add documentation for using Markdown in Pagure (Justing W. Flory)
-- Fix the behavior of the Cancel button on PR page (Rahul Bajaj)
-- Be tolerant to markdown processing error
-- Let the notifications render correctly when added by the SSE server
-- Fix the URL for pull request on the list of branches of a fork (Rahul Bajaj)
-- Adjust the markdown processor to have 1 regex for all cross-project links
-- Remove unsued variables (Farhaan Bukhsh)
-- Hide the title of private tickets when linking to them in markdown
-- Show user activity in pagure on the user's page
-- Add the possibility to subscribe to issues
-- Do not cache the session in pagure-ci (as we did for pagure-webhook)
-- Fix rendering raw file when the sha1 provided is one of a blob
-- Include project's custom fields in the JSON representation of a project
-- Include the issue's custom fields values in the JSON representation of an
-  issue
-- Include the list of close_status and the milestones in the JSON of a project
-- Improve documentation related to unit-tests (Rahul Bajaj)
-- Use `project.fullname` in X-Pagure-Project header (Adam Williamson)
-- Figure a way to properly support WTF_CSRF_TIME_LIMIT on older version of
-  flask-wtf
-- When updating an issue, if the form does not validate, say so to the user
-- Fix the total number of pages when there are no PR/issues/repo (vibhcool)
-- Fix forking a repo with a namespace
-- Include the namespace in the message returned in pagure.lib.new_project
-- Move the metadata-ery area in PR to under the comments tab (Ryan Lerch)
-- Update setup instructions in the README.rst (alunux)
-- Support namespaced projects when reading json data (clime)
-- When uploading a file in a new issue, propagate the namespace info
-- Ensure our avatar works with non-ascii email addresses
-- Downgrade to emoji 1.3.1, we loose some of the newer emojis we get back
-  preview and reasonable size (Clément Verna)
-- Fix sending notifications email containing non-ascii characters
-- Fix using the proper URL in email notifications (Adam Williamson)
-- Move the Clear and Cancel buttons to the right hand side of the comment box
-- Fix spelling in the PR page (Vibhor Verma)
-- Support loading custom fields from JSON when loading issues from git (Vivek
-  Anand)
-- Fix handling namespaced project in the SSE server (Adam Williamson)
-- Add a pylintrc configuration file to help with code standards (Adam
-  Williamson)
-- Add go-import meta tag allowing go projects to be hosted on pagure (Patrick
-  Uiterwijk)
-- Fix index overflow when opening remote pull-request (Mark Reynolds)
-- Add SSE support for custom fields
-- Add a git blame view
-- Allow emptying a file when doing online editing
-- Only let admins edit the dependency tree of issues
-- Fix some spelling errors (Adam Williamson)
-- Add SHA256 signature to webhooks notifications (Patrick Uiterwijk)
-- Multiple fixes in the API documentation and output
-
-* Mon Oct 24 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.8.1-1
-- Update to 2.8.1
-- Handle empty files in detect_encodings (Jeremy Cline)
-- Fix the import of encoding_utils in the issues controller
-- Fix the list of commits page
-- Update docs to dnf (Rahul Bajaj)
-- Add close status in the repo table if not present when updating/creating issue
-  via git (Vivek Anand)
-- If chardet do not return any result, default to UTF-8
-
-* Fri Oct 21 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.8-1
-- Update to 2.8
-- Fix the migration adding the close_status field to remove the old status
-  only at the end
-- Fix the RTD and Force push hooks for the change in location of the plugins
-- Fix creating new PR from the page listing the pull-requests
-- Add the possibility for the user to edit their settings in their settings page
-- Include the close_status in the JSON representation of an issue
-- Load the close_status if there is one set in the JSON repsentation given
-- Fix running the tests when EVENTSOURCE_SOURCE is defined in the
-  configuration.
-- Make the search case-insensitive when searching issues
-- Fix the "cancel" button when editing a "regular" comment on a pull-request
-- Remove the ``Content-Encoding`` headers from responses (Jeremy Cline)
-- Fix creating the release folder for project with a namespace
-- When sending email, make the user who made the action be in the From field
-- When searching groups, search both their name and display name
-- Create a Vagrantfile and Ansible role for Pagure development (Jeremy Cline)
-- Made searching issue stop clearing status and tags filters (Ryan Lerch)
-- Improve documentation (Bill Auger)
-- Fix finding out the encoding of a file in git (Jeremy Cline)
-- Fix making cross-project references using <project>#<id>
-- Allow filter the list of commits for a certain user
-- Ensure we disable all the submit button when clicking on one (avoid sending
-  two comments)
-- Do not always compute the list of diff commits
-- Let's not assume PAGURE_CI_SERVICES is always there
-- Allow html table to define their CSS class
-- Add a link to the user on the commit list (Ryan Lerch)
-- Change `Fork` button to `View Fork` on all pages of the project (tenstormavi)
-- Enable some of the markdown extensions by default
-- Fix mixed content blocked in the doc by not sending our user to google (Rahul
-  Bajaj)
-
-* Thu Oct 13 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.7.2-1
-- Update to 2.7.2
-- Do not show the custom field if the project has none
-- Improve the documentation around SEND_EMAIL (Jeremy Cline)
-
-* Wed Oct 12 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.7.1-1
-- Update to 2.7.1
-- Bug fix to the custom fields feature
-
-* Tue Oct 11 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.7-1
-- Update to 2.7
-- Clean imports (Vivek Anand)
-- Fix NoneType error when pagure-ci form is inactively updated first time
-  (Farhaan Bukhsh)
-- Fix minor typos in configuration documentation (Jeremy Cline)
-- Use context managers to ensure files are closed (Jeremy Cline)
-- Adjust update_tickets_from_git to add milestones for issues as well (Vivek
-  Anand)
-- Update milestone description in Settings (Lubomír Sedlář)
-- Add checks for the validity of the ssh keys provided (Patrick Uiterwijk)
-- Remove hardcoded hostnames in unit tests (Jeremy Cline)
-- Skip clamd-dependent tests when pyclamd isn't installed (Patrick Uiterwijk)
-- Fix interacting with branch containing a dot in their name (new PR button,
-  delete branch button)
-- Ensure only project admins can create reports
-- Do not warn admins when a build in jenkins did not correspond to a
-  pull-request
-- Fix the progress bar on the page listing the issues (d3prof3t)
-- Do not call the API when viewing a diff or a PR if issues or PRs are disabled
-- Port pagure to flask 0.13+
-- Fix displaying the reason when a PR cannot be merged
-- Allow projects to turn on/off fedmsg notifications
-- Fix the web-hook service so when a project is updated the service is as well
-- Add the possibility to specify a status to close ticket (closed as upstream,
-  works for me, invalid...)
-- Let all the optional SelectFields in forms return None when they should
-- Make each tests in the test suite run in its own temporary directory (Jeremy
-  Cline)
-- Use long dash in footer instead of two short ones (Lubomír Sedlář)
-- Add a welcome screen to new comers (does not work with local auth)
-- Ensure user are not logged in if we couldn't properly set them up in pagure
-- Add the possibility to search through issues (AnjaliPardeshi)
-- Add a default hook to all new projects, this hook re-set the merge status of
-  all the open PR upon push to the main branch of the repo
-- Add support for setting custom fields for issues per projects
-
-* Tue Sep 20 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.6-1
-- Update to 2.6
-- Fix creating new PR from the page listing all the PRs
-- Fix grammar error in the issues and PRs page (Jason Tibbitts)
-- Fall back to the user's username if no fullname is provided (Vivek Anand)
-- Fix typo in the using_docs documentation page (Aleksandra Fedorova (bookwar))
-- Fix viewing plugins when the project has a namespace (and the redirection
-  after that)
-- Rework the milestone, so that a ticket can only be assigned to one milestone
-  and things look better
-- Add a project wide setting allowing to make all new tickets private by default
-  (with the option to make them public)
-- Allow toggling the privacy setting when editing the ticket's metadata
-- Rework some of the logic of pagure-ci for when it searches the project related
-  to a receive notification
-- Fix the label of the button to view all close issues to be consistent with the
-  PR page (Jeremy Cline)
-- Add the possibility for projects to notify specific email addresses about
-  issues/PRs update
-- Fix loading tickets from the ticket git repository (fixes importing project to
-  pagure)
-
-* Tue Sep 13 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.5-1
-- Update to 2.5
-- Don't track pagure_env (venv) dir (Paul W. Frields)
-- Setting Mail-Followup-To when sending message to users (Sergio Durigan Junior)
-  (Fixed by Ryan Lerch and I)
-- Fixed the tickets hook so that we dont ignore the files committed in the first
-  commit (Clement Verna)
-- Fix behavior of view of tree if default branch is not 'master' (Vivek Anand)
-- Fix checking the release folder for forks
-- Improve the Remote PR page
-- Improve the fatal error page to display the error message is there is one
-- Avoid issues attachment containing json to be considered as an issue to be
-  created/updated (Clement Verna)
-- Allow the <del> html tag (Clement Verna)
-- Specify rel="noopener noreferrer" to link including target='_blank'
-- Show in the overview page when a branch is already concerned by a PR
-- Fix viewing a tree when the identifier provided is one of a blob (not a tree)
-- Port all the plugins to `uselist=False` in their backref to make the code
-  cleaner
-- Fix pagure_ci for all sort of small issues but also simply so that it works as
-  expected
-- Make the private method __get_user public as get_user
-- Improve the documentation (fix typos and grammar errors) (Sergio Durigan
-  Junior)
-- Drop the `fake` namespaces in favor of real ones
-- Add the possibility to view all tickets/pull-requests of a project (regardless
-  of their status)
-- Paginate the pages listing the tickets and the pull-requests
-- Add the possibility to save a certain filtering on issues as reports
-- Add support to our local markdown processor for ~~striked~~
-
-* Wed Aug 31 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.4-1
-- Update to 2.4
-- - [Security] Avoid all html related mimetypes and force the download if any
-  (CVE-2016-1000037) -- Fixed in 2.3.4 as well
-- Redirect the URL to projects <foo>.git to <foo> (Abhishek Goswami)
-- Allow creating projects with 40 chars length name on newer pagure instances
-- Fix @<user> and #<id> when editing a comment (Eric Barbour)
-- Display properly and nicely the ACLs of the API tokens (Lubomír Sedlář)
-- Removing html5lib so bleach installation finds what version is best (Tiago M.
-  Vieira)
-- Remove the branchchooser from the repoheader (again) (Ryan Lerch)
-- Fix hard-coded urls in the master template
-- Made the interaction with the watch button clearer (Ryan Lerch)
-- Introduce pagure-ci, a service allowing to integrate pagure with a jenkins
-  instance (Farhaan Bukhsh and I)
-- Accept Close{,s,d} in the same way as Merges and Fixes (Patrick Uiterwijk)
-- Avoid showing the 'New PR' button on the overview page is a PR already exists
-  for this branch, in the main project or a fork (Vivek Anand)
-- Fix presenting the readme file and display the readme in the tree page if
-  there is one in the folder displayed (Ryan Lerch)
-- Move the new issue button to be available on every page (AnjaliPardeshi)
-- Fix pagure for when an user enters a comment containing #<id> where the id
-  isn't found in the db
-- Make the bootstrap URLs configurable (so that they don't necessarily point to
-  the Fedora infra) (Farhaan Bukhsh)
-- Fix how the web-hook server determine the project and its username
-- Replace the login icon with plain text (Ryan Lerch)
-- Fix layout in the doc (Farhaan Bukhsh)
-- Improve the load_from_disk utility script
-- Fix our mardown processor to avoid crashing on #<text> (where we expect #<id>)
-- Fix the search for projects with a / in their names
-- Fix adding a file to a ticket when running pagure with `local` auth
-- Improve the grammar around the allowed prefix in our fake-namespaces (Jason
-  Tibbitts)
-- Implement scanning of attached files for viruses (Patrick Uiterwijk)
-- Document how to set-up multiple ssh keys per user (William Moreno Reyes)
-- Add display_name and description to groups, and allow editing them
-- Add the ability to run the post-receive hook after merging a PR in the UI
-- Fix showing the group page even when user management is turned off (Vivek
-  Anand)
-- Make explicit what the separators for tags is (Farhaan Bukhsh)
-- Include the word setting with icon (tenstormavi)
-- Fix the requirements.txt file (Vivek Anand)
-- Cleaned up the topbar a bit (Ryan Lerch)
-- Fix location of bottom pagination links on user page (Ryan Lerch)
-- Add user's project watch list in index page of the user (Vivek Anand)
-- Fix showing the reporter when listing the closed issues (Vivek Anand)
-- Fix accessing forks once the main repo has been deleted (Farhaan Bukhsh)
-
-* Wed Jul 27 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.3.4-1
+
+* Thu Aug 04 2016 Bruno Wolff III <bruno@wolff.to> - 2.3.4-1
 - Update to 2.3.4
 - Security fix release blocking all html related mimetype when displaying the
   raw files in issues and forces the browser to download them instead (Thanks to
   Patrick Uiterwijk for finding this issue) - CVE: CVE-2016-1000037
 
-* Fri Jul 15 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.3.3-1
+* Tue Jul 19 2016 Fedora Release Engineering <rel-eng@lists.fedoraproject.org> - 2.3.3-2
+- https://fedoraproject.org/wiki/Changes/Automatic_Provides_for_Python_RPM_Packages
+
+* Fri Jul 15 2016 Bruno Wolff III <bruno@wolff.to> - 2.3.3-1
 - Update to 2.3.3
-- Fix redering the release page when the tag message contain only spaces (Vivek
+- Fix rendering the release page when the tag message contain only spaces (Vivek
   Anand)
 - Fix the search in @<username> (Eric Barbour)
 - Displays link and git sub-modules in the tree with a dedicated icon
 
-* Tue Jul 12 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.3.2-1
+* Tue Jul 12 2016 Bruno Wolff III <bruno@wolff.to> - 2.3.2-1
+- Make sure to read UPGRADING.rst when upgrading from previous releases
 - Update to 2.3.2
 - Do not mark as local only some of the internal API endpoints since they are
   called via ajax and thus with the user's IP
-
-* Mon Jul 11 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.3.1-1
 - Update to 2.3.1
 - Fix sending notifications to users watching a project
 - Fix displaying if you are watching the project or not
@@ -1725,7 +983,13 @@ done
 - Mark the wsgi files provided with the RPM as %%config(noreplace)
 - Install the api_key_expire_mail.py script next to the createdb one
 
-* Wed Jun 01 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.2.1-1
+* Tue Jul 05 2016 Bruno Wolff III <bruno@wolff.to> - 2.2.2-1
+- Update to 2.2.2
+- Security fix release blocking all html related mimetype when displaying the
+  raw files and forces the browser to download them instead (Thanks to Patrick
+  Uiterwijk for finding this issue)
+
+* Wed Jun 01 2016 Bruno Wolff III <bruno@wolff.to> - 2.2.1-1
 - Update to 2.2.1
 - Fix showing the inital comment on PR having only one commit (Ryan Lerch)
 - Fix diffs not showing for additions/deletions for files under 1000 lines (Ryan
@@ -1734,7 +998,7 @@ done
 - Fix hightlighting the commits tab on commit view
 - Fix the fact that the no readme box show on empty repo (Ryan Lerch)
 
-* Tue May 31 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.2-1
+* Tue May 31 2016 Bruno Wolff III <bruno@wolff.to> - 2.2-1
 - Update to 2.2
 - Fix retrieving the log level from the configuration file (Nuno Maltez)
 - Rework the labels used when sorting projects (Ankush Behl)
@@ -1771,12 +1035,8 @@ done
   the settings page (Ryan Lerch)
 - Check if a tag exists on a project before allowing to edit it (skrzepto)
 
-* Fri May 13 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.1.1-1
-- Update to 2.1.1
-- Do not render the comment as markdown when importing tickets via the ticket
-  git repo
-- Revert get_revs_between changes made in
-  https://pagure.io/pagure/pull-request/941 (Clement Verna)
+* Fri May 27 2016 Bruno Wolff III <bruno@wolff.to> - 2.1.1-1
+- Update by several versions
 
 * Fri May 13 2016 Pierre-Yves Chibon <pingou@pingoured.fr> - 2.1-1
 - Update to 2.1
@@ -1907,7 +1167,7 @@ done
 - Add a small padding at the bottom of the blockquote (Ryan Lerch)
 - In the list of closed PR, replace the column of the assignee with the date of
   closing (Ryan Lerch)
-- Drop font awesome since we no longer use it and compress the png of the
+- Drop font awesome since we no longer use it and compress the png of the 
   current logo (Ryan Lerch)
 - Drop the svg of the old logo from the source (Ryan Lerch)
 - Add descriptions to the git hooks in the settings page (farhaanbukhsh)

From 73b9d078baad76e06c5fbf697ba10a1e184d096c Mon Sep 17 00:00:00 2001
From: Klaus Koder <klauskoder@pagure.local>
Date: Dec 04 2025 16:27:06 +0000
Subject: [PATCH 6/10] validator.Required -> DataRequired


---

diff --git a/pagure/forms.py b/pagure/forms.py
index 458a74a..280ba4d 100644
--- a/pagure/forms.py
+++ b/pagure/forms.py
@@ -335,7 +335,7 @@ class RequestPullEditForm(RequestPullForm):
 
     branch_to = wtforms.SelectField(
         "Target branch",
-        [wtforms.validators.Required()],
+        [wtforms.validators.DataRequired()],
         choices=[],
         coerce=convert_value,
     )
@@ -964,7 +964,7 @@ class TriggerCIPRForm(PagureForm):
         self.comment.choices = choices
 
     comment = wtforms.SelectField(
-        "comment", [wtforms.validators.Required()], choices=[]
+        "comment", [wtforms.validators.DataRequired()], choices=[]
     )
 
 

From 639c235a9cf0e8a1ba14193431a5a7a79acf31dd Mon Sep 17 00:00:00 2001
From: Klaus Koder <klauskoder@pagure.local>
Date: Dec 04 2025 16:27:06 +0000
Subject: [PATCH 7/10] remote_addr check doesn't work for me


---

diff --git a/pagure/internal/__init__.py b/pagure/internal/__init__.py
index 897681e..da4423a 100644
--- a/pagure/internal/__init__.py
+++ b/pagure/internal/__init__.py
@@ -79,13 +79,13 @@ def internal_access_only(function):
             res = pagure.utils.check_api_acls(acls=["internal_access"])
             if res:
                 return res
-        elif flask.request.remote_addr not in ip_allowed:
-            _log.debug(
-                "IP: %s is not in the list of allowed IPs: %s "
-                "and 'Authorization' header not provided"
-                % (flask.request.remote_addr, ip_allowed)
-            )
-            flask.abort(403)
+        #elif flask.request.remote_addr not in ip_allowed:
+            #_log.debug(
+            #    "IP: %s is not in the list of allowed IPs: %s "
+            #    "and 'Authorization' header not provided"
+            #    % (flask.request.remote_addr, ip_allowed)
+            #)
+            #flask.abort(403)
         return function(*args, **kwargs)
 
     return decorated_function

From 20d6e3db981cc293a692b1b30d37d1ff2c94fa15 Mon Sep 17 00:00:00 2001
From: Klaus Koder <klauskoder@pagure.local>
Date: Dec 04 2025 16:28:56 +0000
Subject: [PATCH 8/10] pygit2.remotes not .remote


---

diff --git a/pagure/lib/git.py b/pagure/lib/git.py
index f4c03ab..3b1358d 100644
--- a/pagure/lib/git.py
+++ b/pagure/lib/git.py
@@ -34,7 +34,7 @@ import six
 from sqlalchemy.exc import SQLAlchemyError
 
 # from sqlalchemy.orm.session import Session
-from pygit2.remote import RemoteCollection
+from pygit2.remotes import RemoteCollection
 
 import pagure.utils
 import pagure.exceptions

From 3ef15faedb8142878063f4b94aeb64849641eb94 Mon Sep 17 00:00:00 2001
From: Klaus Koder <klauskoder@pagure.local>
Date: Dec 04 2025 16:32:34 +0000
Subject: [PATCH 9/10] use SSH_COMMAND instead of SSH_COMMAND_NON_REPOSPANNER


---

diff --git a/files/aclchecker.py b/files/aclchecker.py
index 9592845..920d625 100644
--- a/files/aclchecker.py
+++ b/files/aclchecker.py
@@ -90,10 +90,11 @@ if not result["access"]:
 # Now go run the configured command
 # We verified that cmd is either "git-receive-pack" or "git-send-pack"
 # and "path" is a path that points to a valid Pagure repository.
-if result["region"]:
-    runner, env = pagure_config["SSH_COMMAND_REPOSPANNER"]
-else:
-    runner, env = pagure_config["SSH_COMMAND_NON_REPOSPANNER"]
+#if result["region"]:
+#    runner, env = pagure_config["SSH_COMMAND_REPOSPANNER"]
+#else:
+#    runner, env = pagure_config["SSH_COMMAND_NON_REPOSPANNER"]
+runner, env = pagure_config["SSH_COMMAND"]
 
 result.update({"username": remoteuser, "cmd": cmd})
 

From 5c3ac409426bf3bcf25cba201d6b3ab36cceec59 Mon Sep 17 00:00:00 2001
From: Klaus Koder <klauskoder@pagure.local>
Date: Dec 04 2025 16:32:34 +0000
Subject: [PATCH 10/10] Change depreciated create_remote to remotes.create()


---

diff --git a/pagure/lib/git.py b/pagure/lib/git.py
index 3b1358d..c27c772 100644
--- a/pagure/lib/git.py
+++ b/pagure/lib/git.py
@@ -176,7 +176,7 @@ def generate_gitolite_acls(project=None, group=None):
 
 
 def update_git(obj, repo):
-    """ Schedules an update_repo task after determining arguments. """
+    """Schedules an update_repo task after determining arguments."""
     ticketuid = None
     requestuid = None
     if obj.isa == "issue":
@@ -1729,7 +1729,7 @@ def merge_pull_request(session, request, username, domerge=True):
             _log.info(
                 "  Adding remote: %s pointing to: %s", reponame, repopath
             )
-            remote = new_repo.create_remote(reponame, repopath)
+            remote = new_repo.remotes.create(reponame, repopath)
 
             # Fetch the commits
             remote.fetch()
@@ -2029,7 +2029,7 @@ def rebase_pull_request(session, request, username):
         _log.info(
             "  Adding remote: %s pointing to: %s", upstream, upstream_path
         )
-        remote = new_repo.create_remote(upstream, upstream_path)
+        remote = new_repo.remotes.create(upstream, upstream_path)
 
         # Fetch the commits
         remote.fetch()
@@ -2465,7 +2465,7 @@ def get_git_tags(project, with_commits=False):
     return tags
 
 
-def new_git_tag(project, tagname, target, user, message=None, force=False):
+def new_git_tag(project, tagname, target, user, message=str(), force=False):
     """Create a new git tag in the git repositorie of the specified project.
 
     :arg project: the project in which we want to create a git tag
diff --git a/pagure/lib/tasks.py b/pagure/lib/tasks.py
index a370bb6..62db1a6 100644
--- a/pagure/lib/tasks.py
+++ b/pagure/lib/tasks.py
@@ -661,7 +661,7 @@ def move_to_repospanner(self, session, name, namespace, user, region):
                 continue
             repourl, _ = project.repospanner_repo_info(repotype, region)
             repo_obj = pagure.lib.repo.PagureRepo(repopath)
-            repo_obj.create_remote("repospanner_push", repourl)
+            repo_obj.remotes.remote("repospanner_push", repourl)
 
             command = [
                 "git",
diff --git a/tests/__init__.py b/tests/__init__.py
index 28d33c1..762266d 100644
--- a/tests/__init__.py
+++ b/tests/__init__.py
@@ -1195,7 +1195,7 @@ def add_pull_request_git_repo(
 
     # Add the main project as remote repo
     upstream_path = os.path.join(folder, "repos", repo.path)
-    remote = clone_repo.create_remote("upstream", upstream_path)
+    remote = clone_repo.remotes.create("upstream", upstream_path)
     remote.fetch()
 
     # Edit the sources file again
diff --git a/tests/test_pagure_flask_docs.py b/tests/test_pagure_flask_docs.py
index d187bd8..896a13a 100644
--- a/tests/test_pagure_flask_docs.py
+++ b/tests/test_pagure_flask_docs.py
@@ -85,7 +85,7 @@ class PagureFlaskDocstests(tests.SimplePagureTest):
         )
 
         # Push the changes to the bare repo
-        remote = repo.create_remote(
+        remote = repo.remotes.create(
             "origin", os.path.join(self.path, "repos", "docs", "test.git")
         )
 
diff --git a/tests/test_pagure_flask_ui_fork.py b/tests/test_pagure_flask_ui_fork.py
index d71d571..9a79ad1 100644
--- a/tests/test_pagure_flask_ui_fork.py
+++ b/tests/test_pagure_flask_ui_fork.py
@@ -5440,7 +5440,7 @@ More information</textarea>
         PagureRepo.push(ori_remote, refname)
 
         # Push to the fork repo
-        remote = clone_repo.create_remote("pingou_fork", gitrepo2)
+        remote = clone_repo.remotes.create("pingou_fork", gitrepo2)
         PagureRepo.push(remote, refname)
 
         # Add 1 commits to the fork repo
diff --git a/tests/test_pagure_lib_git_diff_pr.py b/tests/test_pagure_lib_git_diff_pr.py
index 3861873..624845a 100644
--- a/tests/test_pagure_lib_git_diff_pr.py
+++ b/tests/test_pagure_lib_git_diff_pr.py
@@ -125,7 +125,7 @@ class PagureFlaskForkPrtests(tests.Modeltests):
         PagureRepo.push(ori_remote, refname)
 
         # Push to the fork repo
-        remote = clone_repo.create_remote("pingou_fork", gitrepo2)
+        remote = clone_repo.remotes.create("pingou_fork", gitrepo2)
         PagureRepo.push(remote, refname)
 
         # Do another 3 commits to the main repo

