{% extends "base.html" %} {% import "repo_tabs.html" as m %} {% block title %}Proposal #{{ p.number }} {{ p.title }} · {{ repo.owner }}/{{ repo.name }}{% endblock %} {% block bodyattrs %} data-repo="{{ repo.url }}"{% endblock %} {% block tabs %}{% call m::tabs(repo, "proposals") %}{% endblock %} {% block mainclass %} class="wide"{% endblock %} {% block content %}

{{ p.title }} proposal #{{ p.number }} {{ p.state }} {{ p.author }} wants {{ source_label }} into {{ p.target }} · {{ changes.len()|plural("change", "changes") }} · opened

{% if !closes.is_empty() %}

{% for c in closes %}issue #{{ c.number }} {{ c.title }} {{ c.state }}{% if !loop.last %} + {% endif %}{% endfor %} → proposal #{{ p.number }} {{ p.state }} → {{ p.target }}{% if p.state == "landed" %} landed{% endif %}

{% endif %} {% if let Some(n) = notice %}

{{ n }}

{% endif %} {% if let Some(e) = error %}

{{ e }}

{% endif %} {% if conflicted %}
Landing would carry {{ conflicts.len()|plural("conflict", "conflicts") }}. Any collaborator can push a resolution change to the source; the proposal follows it. See them
{% endif %} {% if landed_already && p.state != "landed" %}
Every change is already in {{ p.target }}.
{% endif %}
conversation ({{ comments.len() + reviews.len() }}) changes ({{ changes.len() }}) files ({{ files.len() }}) projected state {{ state_hash|short }} · {{ heads.len()|plural("head", "heads") }} · browse · json
{% if tab == "changes" %} {% if changes.is_empty() %}

Nothing to add: the target already has everything.

{% endif %} {% for c in changes %}{% call m::change_row(repo, c) %}{% endfor %} {% else if tab == "files" %} {% if !conflicts.is_empty() %}

Conflicts the landing would carry

{% for c in conflicts %}

{{ c.path }} {{ c.kind }}

{% if let Some(t) = c.marked %}
{{ t }}
{% endif %}{% endfor %}
{% endif %} {% if !files.is_empty() %}{% call m::diff_bar(ignore_ws, "tab=files&") %}{% endif %} {% for f in files %}
{{ f.kind }} {{ f.path }} +{{ f.added }} −{{ f.removed }} {% if f.lines.is_empty() %}

No line changes.

{% else %} {% for l in f.lines %} {% if let Some(n) = l.new_no %}{% if let Some(idxs) = placed.get(&crate::web::proposals::key(&f.path, n)) %} {% endif %}{% endif %} {% endfor %}
{% if let Some(n) = l.old_no %}{{ n }}{% endif %} {% if let Some(n) = l.new_no %}{{ n }}{% endif %} {{ l.kind.sign() }} {% call m::line_text(l) %}{% if let Some(n) = l.new_no %}{% if shell.user.is_some() && p.is_open() %}
+
{% endif %}{% endif %}
{% for i in idxs %}{% let c = comments[*i] %}
{{ c.row.author }} {% if c.row.resolved %} resolved{% endif %} {% if shell.user.is_some() %}
{% endif %}
{{ c.body_html|safe }}
{% endfor %}
{% endif %}
{% endfor %} {% if !outdated.is_empty() %}

Comments on lines that are gone

{% for i in outdated %}{% let c = comments[*i] %}
{{ c.row.author }} on {{ c.row.path }}
{{ c.body_html|safe }}
{% endfor %}
{% endif %} {% else %}
{% if !p.body.is_empty() %}
{{ body_html|safe }}
{% endif %} {% for c in comments %}{% if c.row.anchor_change.is_empty() %}
{{ c.row.author }}
{{ c.body_html|safe }}
{% endif %}{% endfor %} {% for r in reviews %}
{{ r.row.author }} {% if r.row.verdict == "approve" %}{% if r.sealed %}◈ approved and sealed{% else %}○ approved, seal pending{% endif %}{% else if r.row.verdict == "changes" %}✘ requested changes{% else %}commented{% endif %} {% if !r.row.body.is_empty() %}
{{ r.body_html|safe }}
{% endif %}
{% endfor %} {% for e in events %}

{{ e.actor }} {{ e.event }}{% if e.event.ends_with("by change") && !e.detail.is_empty() %}{% let hash = e.detail.split(' ').next().unwrap_or("") %} {{ hash }}{{ e.detail[hash.len()..] }}{% else if !e.detail.is_empty() %}: {{ e.detail }}{% endif %} · {{ e.at_ms|ago_i }}

{% endfor %} {% if shell.user.is_some() %}
{% if p.is_open() %}

Review

An approval counts once you seal the changes from a client: oxy seal --proposal {{ shell.base_url }}{{ repo.url }}/proposal/{{ p.number }}

{% endif %} {% endif %}
{% endif %} {% endblock %}