pijul 0.12.2

A patch-based distributed version control system, easy to use and fast. Command-line interface.
use super::BasicOptions;
use clap::{Arg, ArgMatches, SubCommand};
use commands::{default_explain, StaticSubcommand};
use error::Error;
use sequoia_openpgp::parse::{PacketParser, PacketParserResult, Parse};
use sequoia_openpgp::serialize::Serialize;
use sequoia_openpgp::Packet;
use std::fs::File;
use std::io::stdin;

pub fn invocation() -> StaticSubcommand {
    return SubCommand::with_name("sign")
        .about("Add patch signatures")
        .arg(
            Arg::with_name("repository")
                .long("repository")
                .help(
                    "Path to the repository where the patches will be applied. Defaults to the \
                     repository containing the current directory.",
                )
                .takes_value(true),
        );
}

pub fn run(args: &ArgMatches) -> Result<(), Error> {
    let opts = BasicOptions::from_args(args)?;

    let mut path = opts.patches_dir();
    let mut stdin = stdin();

    // Signatures messages are made of two packets: a `Literal`
    // packet, followed by a `Signature` packet. The following loop
    // gets an arbitrary sequence of packets, and writes them to
    // the corresponding signature files.
    let mut literal = None;
    let mut ppr = PacketParser::from_reader(&mut stdin).unwrap();
    while let PacketParserResult::Some(pp) = ppr {
        let (packet, next) = pp.recurse().unwrap();
        debug!("packet {:?}", packet);
        match packet {
            Packet::Literal(l) => literal = Some(l),
            Packet::Signature(s) => {
                if let Some(literal) = literal.take() {
                    if let Some(filename) = literal.filename() {
                        let filename = std::str::from_utf8(filename).unwrap();
                        path.push(&filename);
                        path.set_extension("sig");
                        let mut f = File::create(&path)?;
                        literal.serialize(&mut f)?;
                        s.serialize(&mut f)?;
                        path.pop();
                    }
                }
            }
            _ => {}
        }
        ppr = next
    }
    Ok(())
}

pub fn explain(res: Result<(), Error>) {
    default_explain(res)
}