pijul 1.0.0-alpha.9

The sound distributed version control system.
use std::io::Write;
use std::path::PathBuf;

use clap::Clap;
use libpijul::changestore::*;
use libpijul::{Base32, TxnT, TxnTExt};
use pager::Pager;

use crate::repository::Repository;
use crate::Error;

#[derive(Clap, Debug)]
pub struct Log {
    /// Set the repository where this command should run Defaults to the first ancestor of the current directory that contains a `.pijul` directory.
    #[clap(long = "repository")]
    repo_path: Option<PathBuf>,
    /// Show logs for this channel instead of the current channel
    #[clap(long = "channel")]
    channel: Option<String>,
    /// Only show the change hashes
    #[clap(long = "hash-only")]
    hash_only: bool,
    /// Include state identifiers in the log output
    #[clap(long = "state")]
    states: bool,
    /// Include full change discription in the log output
    #[clap(long = "description")]
    descriptions: bool,
}

impl Log {
    pub fn run(self) -> Result<(), anyhow::Error> {
        let repo = Repository::find_root(self.repo_path)?;
        let txn = repo.pristine.txn_begin()?;
        let channel_name = repo.config.get_current_channel(self.channel.as_ref());
        let channel = if let Some(channel) = txn.load_channel(channel_name) {
            channel
        } else {
            return Err((Error::NoSuchChannel {
                channel: channel_name.to_string(),
            })
            .into());
        };
        Pager::with_pager("less -F").setup();
        let changes = repo.changes;
        let mut stdout = std::io::stdout();
        if self.hash_only {
            for h in libpijul::change::full_dependencies(&txn, &channel).0 {
                writeln!(stdout, "{}", h.to_base32())?
            }
        } else {
            let states = self.states;
            for (_, (h, mrk)) in txn.reverse_log(&channel.borrow(), None) {
                let change = changes.get_change(&h)?;
                writeln!(stdout, "Change {}", h.to_base32())?;
                writeln!(stdout, "Author: {:?}", change.header.authors)?;
                writeln!(stdout, "Date: {}", change.header.timestamp)?;
                if states {
                    writeln!(stdout, "State: {}", mrk.to_base32())?;
                }
                writeln!(stdout, "\n    {}\n", change.header.message)?;
                if self.descriptions {
                    if let Some(ref descr) = change.header.description {
                        writeln!(stdout, "\n    {}\n", descr)?;
                    }
                }
            }
        }
        Ok(())
    }
}