~sircmpwn/lists.sr.ht

16df168c144d5ca52daea8c06b53d8591723a6f0 — Siva Mahadevan 10 months ago 0a6420d
Remove unidiff in favor of pygit2

Closes https://todo.sr.ht/~sircmpwn/lists.sr.ht/101
M listssrht/blueprints/patches.py => listssrht/blueprints/patches.py +4 -8
@@ 84,14 84,10 @@ def gen_cover_letter(patches):
        insertions = deletions = 0
        for email in patches:
            cover += f" {email.patch_subject}\n"
            patch = email.patch()
            nfiles += (len(patch.added_files)
                    + len(patch.modified_files)
                    + len(patch.removed_files))
            insertions += sum(f.added for
                    f in patch.added_files + patch.modified_files)
            deletions += sum(f.removed
                    for f in patch.removed_files + patch.modified_files)
            stats = email.patch().stats
            nfiles += stats.files_changed
            insertions += stats.insertions
            deletions += stats.deletions
    cover += f"\n {nfiles} files changed, {insertions} insertions(+), {deletions} deletions(-)\n"
    return cover


M listssrht/filters.py => listssrht/filters.py +10 -14
@@ 21,18 21,15 @@ def _format_patch(msg, limit=None):
    text = Markup("")
    is_diff = False

    def get_path(f):
        # [2:] to remove a/ or b/
        return f.target_file[2:].strip()

    # Predict the starting lines of each file name
    patch = msg.patch()
    old_files = {delta.old_file.path for delta in patch.deltas}
    new_files = {delta.new_file.path for delta in patch.deltas}
    file_lines = {
        f" {get_path(f)} ": f
        for f in patch.added_files + patch.modified_files + patch.removed_files
        f" {p} ": p for p in old_files | new_files
    }

    line_no = 0

    for line in msg.body.replace("\r", "").split("\n"):
        line_no += 1
        if line_no == limit:


@@ 48,8 45,7 @@ def _format_patch(msg, limit=None):
            if f != None:
                f = file_lines[f]
                text += Markup(" <a href='#{}'>{}</a>".format(
                    escape(msg.message_id) + "+" + escape(get_path(f)),
                    escape(get_path(f))))
                    escape(msg.message_id) + "+" + escape(f), escape(f)))
                try:
                    stat = line[line.rindex(" ") + 1:]
                    line = line[:line.rindex(" ") + 1]


@@ 71,7 67,7 @@ def _format_patch(msg, limit=None):
                        stat = escape(stat)
                except ValueError:
                    stat = Markup("")
                text += escape(line[len(get_path(f)) + 1:])
                text += escape(line[len(f) + 1:])
                text += escape(stat)
                text += Markup("\n")
            else:


@@ 143,9 139,9 @@ def format_body(msg, limit=None):
            text += Markup(urlize(escape(line), rel="noopener nofollow")) + "\n"
    return text.rstrip()

def diffstat(patch):
    p = patch.patch()
def diffstat(patch_email):
    stats = patch_email.patch().stats
    return type("diffstat", tuple(), {
        "added": sum(f.added for f in p.added_files + p.modified_files),
        "removed": sum(f.removed for f in p.removed_files + p.modified_files),
        "added": stats.insertions,
        "removed": stats.deletions,
    })

M listssrht/process.py => listssrht/process.py +4 -5
@@ 168,11 168,10 @@ def _archive(dest, envelope):
            # TODO: should we consider multiple text parts?
            mail.body = part.get_payload(decode=True).decode(charset)
            break
    try:
        patch = pygit2.Diff.parse_diff(mail.body.replace("\r\n", "\n"))
        mail.is_patch = len(patch) > 0
    except:
        mail.is_patch = False

    # force lazy parse of patch (if it exists) after msg body is set
    mail.patch()

    mail.is_request_pull = False # TODO: Detect git request-pull
    reply_to = envelope["In-Reply-To"]


M listssrht/types/email.py => listssrht/types/email.py +12 -8
@@ 1,9 1,8 @@
import email
import io
import pygit2
import sqlalchemy as sa
from email import policy
from srht.database import Base
from unidiff import PatchSet

class Email(Base):
    __tablename__ = 'email'


@@ 100,11 99,16 @@ class Email(Base):
        self._parsed._email = self
        return self._parsed

    # libgit2 Diff object parsed from message body (if it exists)
    def patch(self):
        if not self.is_patch:
            return None
        if hasattr(self, "_patch"):
        if not hasattr(self, "_patch"):
            try:
                self._patch = pygit2.Diff.parse_diff(self.body.replace("\r\n", "\n"))
                self.is_patch = len(self._patch) > 0
            except:
                self.is_patch = False

        if self.is_patch:
            return self._patch
        with io.StringIO(self.body) as f:
            self._patch = PatchSet(f)
        return self._patch

        return None

M setup.py => setup.py +0 -1
@@ 57,7 57,6 @@ setup(
      'flask-login',
      'aiosmtpd',
      'asyncpg',
      'unidiff',
  ],
  license = 'AGPL-3.0',
  package_data={