~edwargix/git.sr.ht

7e69181e294ec703dc80ca3cdb233f76e70776da — наб 3 years ago e181b27
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
M gitsrht/app.py => gitsrht/app.py +2 -0
@@ 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():

M gitsrht/blueprints/email.py => gitsrht/blueprints/email.py +3 -3
@@ 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()

M gitsrht/blueprints/repo.py => gitsrht/blueprints/repo.py +22 -19
@@ 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):

M gitsrht/git.py => gitsrht/git.py +3 -3
@@ 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):

M gitsrht/rss.py => gitsrht/rss.py +1 -1
@@ 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",

M gitsrht/templates/refs.html => gitsrht/templates/refs.html +6 -6
@@ 26,7 26,7 @@
    <div class="col-md-8">
      <div class="event-list">
        {% 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 %}
            <a href="{{url_for("repo.ref",
                owner=repo.owner.canonical_name,
                repo=repo.name,
                ref=tag.name)}}">
              {{tag.name}}
                ref=refname)}}">
              {{refname.decode("utf-8", "replace")}}
            </a>
            {% endif %}
            <small class="pull-right text-muted">


@@ 86,7 86,7 @@
        {% set commit = branch[2] %}
        {% set branch = branch[1] %}
        <div class="event">
          {{name}}
          {{name.decode("utf-8", "replace")}}
          {{ utils.commit_event(repo, commit, skip_body=True) }}
          <div class="row" style="margin-top: 0.5rem">
            <div class="col">


@@ 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")}}</a>
            </div>

M gitsrht/templates/repo.html => gitsrht/templates/repo.html +3 -2
@@ 7,12 7,13 @@
<meta name="go-import"
  content="{{domain}}/{{owner.canonical_name}}/{{repo.name}} git {{(repo | clone_urls)[0]}}">
{% if default_branch %}
  {% set default_branch_name = default_branch.raw_name.decode("utf-8", "replace")[len("refs/heads/"):] %}
  <meta name="go-source"
    content="{{domain}}/{{owner.canonical_name}}/{{repo.name}} {{(repo | clone_urls)[0]}}
             {{(repo | clone_urls)[0]}}/tree/
               {{- default_branch.name[("refs/heads/"|length):]}}{/dir}
               {{- default_branch_name}}{/dir}
             {{(repo | clone_urls)[0]}}/tree/
               {{- default_branch.name[("refs/heads/"|length):]}}{/dir}/{file}#L{line}">
               {{- default_branch_name}}{/dir}/{file}#L{line}">
{% endif %}
{% endblock %}
{% block body %}

M gitsrht/templates/send-email.html => gitsrht/templates/send-email.html +8 -5
@@ 41,16 41,17 @@
  <input
    type="radio"
    name="branch"
    value="{{branch[0]}}"
    value="{{branch[0]|url_quote}}"
    id="branch-{{branch_hash}}"
    {% if loop.first %}checked{% endif %}
    />
  <label for="branch-{{branch_hash}}">
    {{branch[0]}}
    {{branch[0].decode("utf-8", "replace")}}
    <span class="text-muted">
      (active {{ commit_time(branch[2]) | date }})
    </span>
  </label>
  {{valid.summary("branch")}}
  {% endfor %}

  {% if any(branches[2:]) %}


@@ 59,10 60,10 @@
    <ul>
      {% for branch in branches[2:] %}
      <li>
        {{branch[0]}}
        {{branch[0].decode("utf-8", "replace")}}
        <span class="text-muted">(active {{commit_time(branch[2]) | date}})</span>
        <br />
        <a href="?branch={{branch[0]}}">
        <a href="?branch={{branch[0]|url_quote}}">
          Select this branch {{icon('caret-right')}}
        </a>
      </li>


@@ 78,6 79,7 @@
  </small>
  {% for branch in branches[:2] %}
  {%- set branch_hash = branch[0] | hash -%}
  {%- set branch_quoted = branch[0] | url_quote -%}
  <div class="event-list commit-list reverse commits-{{branch_hash}}">
    {% if commits[branch[0]][-1].parents %}
    {% set show_commits = commits[branch[0]][:-1] %}


@@ 87,13 89,14 @@
    {% for c in show_commits[::-1] %}
    <input
      type="radio"
      name="commit-{{branch[0]}}"
      name="commit-{{branch_quoted}}"
      id="commit-{{branch_hash}}-{{c.id.hex}}"
      value="{{c.id.hex}}"
      {% if loop.last %}checked{% endif %} />
    <label class="event" for="commit-{{branch_hash}}-{{c.id.hex}}">
      {{ utils.commit_event(repo, c, False, target_blank=True) }}
    </label>
    {{valid.summary("branch-" + branch_quoted)}}
    {% endfor %}
  </div>
  <div class="pull-right form-controls form-controls-{{branch_hash}}">

M gitsrht/templates/settings_info.html => gitsrht/templates/settings_info.html +2 -1
@@ 14,7 14,8 @@
    {% if repo.git_repo.is_empty %}disabled{% endif %}
  >
    {% set default_branch_name = repo.git_repo.default_branch_name() or "" %}
    {% for branch in repo.git_repo.branches %}
    {% for branch in repo.git_repo.raw_listall_branches() %}
      {% set branch = branch.decode("utf-8", "replace") %}
      <option
        value="{{branch}}"
        {% if branch == default_branch_name %}

M gitsrht/templates/summary.html => gitsrht/templates/summary.html +3 -3
@@ 31,7 31,7 @@
          <h3>refs</h3>
          <dl>
            {% if default_branch %}
            <dt>{{default_branch.name[len("refs/heads/"):]}}</dt>
            <dt>{{default_branch.raw_name.decode("utf-8", "replace")[len("refs/heads/"):]}}</dt>
            <dd>
              <a href="{{url_for("repo.tree",
                  owner=repo.owner.canonical_name, repo=repo.name)}}"


@@ 42,12 42,12 @@
            </dd>
            {% endif %}
            {% if latest_tag %}
            <dt>{{ latest_tag[0][len("refs/tags/"):] }}</dt>
            <dt>{{ latest_tag[0].decode("utf-8", "replace")[len("refs/tags/"):] }}</dt>
            <dd>
              {% if is_annotated(latest_tag[1]) %}
                <a href="{{url_for("repo.ref",
                    owner=repo.owner.canonical_name,
                    repo=repo.name, ref=latest_tag[1].name)}}"
                    repo=repo.name, ref=latest_tag[0][len("refs/tags/"):])}}"
                >release notes&nbsp;{{icon("caret-right")}}</a>
              {% else %}
                <a href="{{url_for("repo.tree", owner=repo.owner.canonical_name,

M gitsrht/templates/utils.html => gitsrht/templates/utils.html +4 -3
@@ 1,7 1,8 @@
{% macro breadcrumb(ref, repo, path, entry, view, path_join, stat, pygit2, humanize) %}
{% if ref != repo.git_repo.default_branch_name() %}
{% set ref_s = ref.decode("utf-8", "replace") %}
{% if ref_s != repo.git_repo.default_branch_name() %}
<span style="margin-right: 1rem">
  <span class="text-muted">ref:</span> {{ ref }}
  <span class="text-muted">ref:</span> {{ ref_s }}
</span>
{% endif %}
{% if path != [''] %}


@@ 136,7 137,7 @@ endif %}{% endfor %}
          repo=repo.name,
          ref=ref.name)}}"
      {% endif %}
    >{{ref.name}}</a>
    >{{ref.name.decode("utf-8", "replace")}}</a>
  </span>
  {% endfor %}
  {% endif %}