From 7e69181e294ec703dc80ca3cdb233f76e70776da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=BD=D0=B0=D0=B1?= Date: Thu, 25 Feb 2021 20:44:15 +0100 Subject: [PATCH] Handle non-default-encoding ref names Some of the paths can't be used, simply because we get the path elements as strs, but they fail more-less gracefully with a 404, instead of most routes 500ing at the very whiff of a nonrepresentable ref name Ref: ~sircmpwn/git.sr.ht#310 --- gitsrht/app.py | 2 ++ gitsrht/blueprints/email.py | 6 ++-- gitsrht/blueprints/repo.py | 41 +++++++++++++++------------- gitsrht/git.py | 6 ++-- gitsrht/rss.py | 2 +- gitsrht/templates/refs.html | 12 ++++---- gitsrht/templates/repo.html | 5 ++-- gitsrht/templates/send-email.html | 13 +++++---- gitsrht/templates/settings_info.html | 3 +- gitsrht/templates/summary.html | 6 ++-- gitsrht/templates/utils.html | 7 +++-- 11 files changed, 57 insertions(+), 46 deletions(-) diff --git a/gitsrht/app.py b/gitsrht/app.py index 34f52a3..9ad916f 100644 --- a/gitsrht/app.py +++ b/gitsrht/app.py @@ -11,6 +11,7 @@ from scmsrht.flask import ScmSrhtFlask from srht.config import cfg from srht.database import DbSession from srht.flask import session +from werkzeug.urls import url_quote db = DbSession(cfg("git.sr.ht", "connection-string")) db.init() @@ -44,6 +45,7 @@ class GitApp(ScmSrhtFlask): self.add_template_filter(urls.clone_urls) self.add_template_filter(urls.log_rss_url) self.add_template_filter(urls.refs_rss_url) + self.add_template_filter(url_quote) @self.context_processor def inject(): diff --git a/gitsrht/blueprints/email.py b/gitsrht/blueprints/email.py index 1d20848..6a2b886 100644 --- a/gitsrht/blueprints/email.py +++ b/gitsrht/blueprints/email.py @@ -45,8 +45,8 @@ def send_email_start(owner, repo): branch, git_repo.branches[branch], git_repo.get(git_repo.branches[branch].target) - ) for branch in git_repo.branches.local] - default_branch = git_repo.default_branch().name + ) for branch + in git_repo.raw_listall_branches(pygit2.GIT_BRANCH_LOCAL)] branches = sorted(branches, key=lambda b: (b[0] == selected_branch, commit_time(b[2])), reverse=True) @@ -358,5 +358,5 @@ def send_email_send(owner, repo): @mail.app_template_filter('hash') def to_hash(value): - hashed_value = hashlib.sha256(value.encode()) + hashed_value = hashlib.sha256(value.encode() if isinstance(value, str) else value) return hashed_value.hexdigest() diff --git a/gitsrht/blueprints/repo.py b/gitsrht/blueprints/repo.py index ce427c4..ddddc15 100644 --- a/gitsrht/blueprints/repo.py +++ b/gitsrht/blueprints/repo.py @@ -91,19 +91,21 @@ def summary(owner, repo): if not default_branch: return render_empty_repo(owner, repo) - tip = git_repo.get(default_branch.target) + default_branch_name = default_branch.raw_name \ + .decode("utf-8", "replace")[len("refs/heads/"):] + tip = git_repo.get(default_branch.raw_target) commits = get_last_3_commits(git_repo, tip) link_prefix = url_for( 'repo.tree', owner=repo.owner, repo=repo.name, - ref=f"{default_branch.name}/") # Trailing slash needed + ref=f"{default_branch_name}/") # Trailing slash needed blob_prefix = url_for( 'repo.raw_blob', owner=repo.owner, repo=repo.name, - ref=f"{default_branch.name}/", path="") # Trailing slash needed + ref=f"{default_branch_name}/", path="") # Trailing slash needed readme = get_readme(repo, git_repo, tip, link_prefix=[link_prefix, blob_prefix]) - tags = [(ref, git_repo.get(git_repo.references[ref].target)) - for ref in git_repo.listall_references() - if ref.startswith("refs/tags/")] + tags = [(ref, git_repo.get(git_repo.references[ref].raw_target)) + for ref in git_repo.raw_listall_references() + if ref.startswith(b"refs/tags/")] tags = [tag for tag in tags if isinstance(tag[1], pygit2.Tag) or isinstance(tag[1], pygit2.Commit)] tags = sorted(tags, key=lambda c: commit_time(c[1]), reverse=True) @@ -155,7 +157,7 @@ def lookup_ref(git_repo, ref, path): branch = git_repo.default_branch() if not branch: abort(404) - ref = ref or branch.name[len("refs/heads/"):] + ref = ref.encode("utf-8") if ref else branch.raw_name[len(b"refs/heads/"):] if not path: path = [] else: @@ -168,7 +170,7 @@ def lookup_ref(git_repo, ref, path): except ValueError: pass while commit is None and len(path): - ref += "/" + path[0] + ref += b"/" + path[0].encode("utf-8") path = path[1:] try: commit = git_repo.revparse_single(ref) @@ -365,14 +367,14 @@ class _AnnotatedRef: def __init__(self, repo, ref): self.ref = ref self.target = ref.target - if ref.name.startswith("refs/heads/"): + if ref.raw_name.startswith(b"refs/heads/"): self.type = "branch" - self.name = ref.name[len("refs/heads/"):] + self.name = ref.raw_name[len(b"refs/heads/"):] self.branch = repo.get(ref.target) self.commit = self.branch - elif ref.name.startswith("refs/tags/"): + elif ref.raw_name.startswith(b"refs/tags/"): self.type = "tag" - self.name = ref.name[len("refs/tags/"):] + self.name = ref.raw_name[len(b"refs/tags/"):] self.tag = repo.get(self.target) if isinstance(self.tag, pygit2.Commit): self.commit = self.tag @@ -383,7 +385,7 @@ class _AnnotatedRef: def collect_refs(git_repo): refs = {} - for _ref in git_repo.references: + for _ref in git_repo.raw_listall_references(): _ref = _AnnotatedRef(git_repo, git_repo.references[_ref]) if not _ref.type or not hasattr(_ref, "commit"): continue @@ -439,7 +441,7 @@ def log_rss(owner, repo, ref): repo_name = f"{repo.owner.canonical_name}/{repo.name}" title = f"{repo_name} log" - description = f"Git log for {repo_name} {ref}" + description = f"Git log for {repo_name} {ref.decode('utf-8', 'replace')}" link = cfg("git.sr.ht", "origin") + url_for("repo.log", owner=repo.owner.canonical_name, repo=repo.name, @@ -499,7 +501,8 @@ def refs(owner, repo): tags = [( ref, git_repo.get(git_repo.references[ref].target) - ) for ref in git_repo.references if ref.startswith("refs/tags/")] + ) for ref in git_repo.raw_listall_references() + if ref.startswith(b"refs/tags/")] tags = [tag for tag in tags if isinstance(tag[1], pygit2.Commit) or isinstance(tag[1], pygit2.Tag)] def _tag_key(tag): @@ -513,10 +516,10 @@ def refs(owner, repo): branch, git_repo.branches[branch], git_repo.get(git_repo.branches[branch].target) - ) for branch in git_repo.branches.local] + ) for branch in git_repo.raw_listall_branches(pygit2.GIT_BRANCH_LOCAL)] default_branch = git_repo.default_branch() branches = sorted(branches, - key=lambda b: (b[1].name == default_branch.name, b[2].commit_time), + key=lambda b: (b[1].raw_name == default_branch.raw_name, b[2].commit_time), reverse=True) results_per_page = 10 @@ -548,8 +551,8 @@ def refs_rss(owner, repo): with GitRepository(repo.path) as git_repo: references = [ git_repo.references[name] - for name in git_repo.references - if name.startswith("refs/tags/") + for name in git_repo.raw_listall_references() + if name.startswith(b"refs/tags/") ] def _ref_sort_key(ref): diff --git a/gitsrht/git.py b/gitsrht/git.py index 09ed144..eeea9e3 100644 --- a/gitsrht/git.py +++ b/gitsrht/git.py @@ -75,18 +75,18 @@ class Repository(GitRepository): def default_branch(self): head_ref = self.lookup_reference("HEAD") - return self.branches.get(head_ref.target[len("refs/heads/"):]) + return self.branches.get(head_ref.raw_target[len(b"refs/heads/"):]) def default_branch_name(self): branch = self.default_branch() if branch: - return branch.name[len("refs/heads/"):] + return branch.raw_name.decode("utf-8", "replace")[len("refs/heads/"):] else: return None @property def is_empty(self): - return len(list(self.branches.local)) == 0 + return len(self.raw_listall_branches(pygit2.GIT_BRANCH_LOCAL)) == 0 class AnnotatedTreeEntry: def __init__(self, repo, entry): diff --git a/gitsrht/rss.py b/gitsrht/rss.py index 23b3f46..9716af8 100644 --- a/gitsrht/rss.py +++ b/gitsrht/rss.py @@ -15,7 +15,7 @@ def aware_time(author): return datetime.fromtimestamp(author.time, tzinfo) def ref_name(reference): - return reference.name.split("/")[-1] + return reference.raw_name.decode("utf-8", "replace").split("/")[-1] def ref_url(repo, reference): return ORIGIN + url_for("repo.ref", diff --git a/gitsrht/templates/refs.html b/gitsrht/templates/refs.html index dccdea3..a9f369a 100644 --- a/gitsrht/templates/refs.html +++ b/gitsrht/templates/refs.html @@ -26,7 +26,7 @@
{% for tag in tags %} - {% set ref = tag[0] %} + {% set ref = tag[0].decode("utf-8", "replace") %} {% set tag = tag[1] %} {% if isinstance(tag, pygit2.Commit) %} {% set commit = tag %} @@ -39,12 +39,12 @@ {% set refname = commit.id.hex %} {{ref[len("refs/tags/"):]}} {% else %} - {% set refname = tag.name %} + {% set refname = tag.raw_name %} - {{tag.name}} + ref=refname)}}"> + {{refname.decode("utf-8", "replace")}} {% endif %} @@ -86,7 +86,7 @@ {% set commit = branch[2] %} {% set branch = branch[1] %}
- {{name}} + {{name.decode("utf-8", "replace")}} {{ utils.commit_event(repo, commit, skip_body=True) }}
@@ -95,7 +95,7 @@ owner=repo.owner.canonical_name, repo=repo.name, ref=name)}}" class="btn btn-block {{ "btn-primary" - if branch.name == default_branch.name + if branch.raw_name == default_branch.raw_name else "btn-default" }}" >browse {{icon("caret-right")}}
diff --git a/gitsrht/templates/repo.html b/gitsrht/templates/repo.html index 16e32a4..63f460c 100644 --- a/gitsrht/templates/repo.html +++ b/gitsrht/templates/repo.html @@ -7,12 +7,13 @@ {% if default_branch %} + {% set default_branch_name = default_branch.raw_name.decode("utf-8", "replace")[len("refs/heads/"):] %} + {{- default_branch_name}}{/dir}/{file}#L{line}"> {% endif %} {% endblock %} {% block body %} diff --git a/gitsrht/templates/send-email.html b/gitsrht/templates/send-email.html index 035e089..77eafd1 100644 --- a/gitsrht/templates/send-email.html +++ b/gitsrht/templates/send-email.html @@ -41,16 +41,17 @@ + {{valid.summary("branch")}} {% endfor %} {% if any(branches[2:]) %} @@ -59,10 +60,10 @@