Verified Commit 55df28d6 authored by Jakob Moser's avatar Jakob Moser
Browse files

Add commit command

parent d899b977
Loading
Loading
Loading
Loading
+67 −3
Changes for poolpay/fints/__main__.py: 67 added lines, 3 removed lines.
Original line number Diff line number Diff line
@@ -7,6 +7,7 @@ from typing import Annotated

import minisign
import typer
from dulwich import porcelain
from pyrage import encrypt as age_encrypt
from pyrage import x25519
from sqlalchemy import select
@@ -97,13 +98,25 @@ def export(
            help="If the export should be signed with the jakob minisign key."
        ),
    ] = False,
    file: Annotated[
        Path | None,
        typer.Option(
            help="The file to write the output to (STDOUT if not provided).",
        ),
    ] = None,
    signature_file: Annotated[
        Path | None,
        typer.Option(
            help="The file to write the detached signature to, if --sign is given (STDERR if not provided)",
        ),
    ] = None,
) -> None:
    """
    Export all relevant transactions as messages to be applied in a running PoolPay instance via the Wire server.

    Produces output in JSONL format or as an ASCII-armored age blob to STDOUT.
    Produces output in JSONL format or as an ASCII-armored age blob to STDOUT or --file, if provided.

    If signing is requested, produces detached signature to STDERR.
    If signing is requested, produces detached signature to STDERR or --signature-file, if provided.
    """
    base_selection = select(Transaction)
    selection = (
@@ -127,6 +140,9 @@ def export(
    ]

    payload = _encrypt_if_requested("\n".join(str(m) for m in messages), encrypt)
    if file:
        file.write_text(payload)
    else:
        print(payload, end="")

    if sign:
@@ -135,16 +151,64 @@ def export(
        # something, so we encrypt the key with an empty string as password.
        key.decrypt("")
        signature = key.sign(payload.encode("utf-8"))
        armored_signature = bytes(signature).decode("utf-8")

        print(bytes(signature).decode("utf-8"), file=sys.stderr)
        if signature_file:
            signature_file.write_text(armored_signature)
        else:
            print(armored_signature, file=sys.stderr)


@app.command()
def list() -> None:
    """
    List all transactions
    """
    for transaction in Transaction.get_all():
        print(transaction)


@app.command()
def commit(
    repo: Annotated[
        Path, typer.Option(help="Path to the Git repository which holds the data")
    ] = Path(__file__).parents[3] / "c2",
    force: Annotated[
        bool,
        typer.Option(help="Continue even if the sync retrieves no new transactions"),
    ] = False,
    push: Annotated[
        bool,
        typer.Option(help="If git push should be run")
    ] = False,
) -> None:
    """
    Sync, export if the sync yielded new transactions, git commit
    """
    new_transactions = sync()
    if not new_transactions and not force:
        raise typer.Exit(1)

    file = repo / "messages.jsonl.age"
    signature_file = repo / "messages.jsonl.age.minisig"

    export(encrypt=True, sign=True, file=file, signature_file=signature_file)

    porcelain.add(repo, paths=(file, signature_file))

    t = len(new_transactions)
    if t == 0:
        message = "Export all currently stored transactions"
    elif t == 1:
        message = "Add one new transaction"
    else:
        message = f"Add {t} new transactions"

    porcelain.commit(repo, message=message, author="Jakob Moser <jakob@fsco.li>")
    if push:
        porcelain.push(repo)


if __name__ == "__main__":
    try:
        db.open(_guess_db_path())