use std::collections::BTreeSet;
use std::{borrow::Cow, ops::Deref, path::PathBuf};
use derivative::Derivative;
use libflowers::prelude::*;
use pijul::change::{Author, ChangeHeader, Hunk, Local};
use pijul::change::{BaseHunk, LocalChange};
use pijul::Hash;
#[derive(Derivative)]
#[derivative(Debug)]
pub struct State {
#[derivative(Debug(format_with = "fmt_pijul_repository"))]
pub state: pijul::Repository,
pub changed_files: BTreeSet<String>,
}
impl Deref for State {
type Target = pijul::Repository;
fn deref(&self) -> &Self::Target {
&self.state
}
}
pub type Diff = LocalChange<Hunk<Option<Hash>, Local>, Author>;
pub fn load(path: PathBuf) -> State {
let state = pijul::Repository::find_root(Some(path)).unwrap();
let diff = diff(&state);
let changed_files = changed_files(&diff);
State {
state,
changed_files,
}
}
pub fn dir_name(repo: &pijul::Repository) -> Cow<'_, str> {
repo.path.iter().last().unwrap().to_string_lossy()
}
pub fn current_channel(repo: &pijul::Repository) -> String {
use pijul::TxnT;
let txn = repo.pristine.arc_txn_begin().unwrap();
let read_guard = txn.read();
read_guard
.current_channel()
.unwrap_or(pijul::DEFAULT_CHANNEL)
.to_string()
}
pub fn diff(repo: &pijul::Repository) -> Diff {
use pijul::MutTxnT;
use pijul::TxnT;
let txn = repo.pristine.arc_txn_begin().unwrap();
let cur_channel = txn
.read()
.current_channel()
.unwrap_or(pijul::DEFAULT_CHANNEL)
.to_string();
let channel = txn.write().open_or_create_channel(&cur_channel).unwrap();
let mut state = pijul::RecordBuilder::new();
state
.record(
txn.clone(),
pijul::Algorithm::default(),
false,
&pijul::DEFAULT_SEPARATOR,
channel.clone(),
&repo.working_copy,
&repo.changes,
"",
std::thread::available_parallelism().unwrap().get(),
)
.unwrap();
let rec = state.finish();
let actions: Vec<_> = {
let txn_ = txn.read();
rec.actions
.into_iter()
.map(|rec| rec.globalize(&*txn_).unwrap())
.collect()
};
let contents = std::sync::Arc::try_unwrap(rec.contents)
.unwrap()
.into_inner();
let mut change = LocalChange::make_change(
&*txn.read(),
&channel,
actions,
contents,
ChangeHeader::default(),
Vec::new(),
)
.unwrap();
let (dependencies, extra_known) = {
let txn_ = txn.read();
pijul::change::dependencies(
&*txn_,
&*channel.read(),
change.changes.iter(),
)
.unwrap()
};
change.dependencies = dependencies;
change.extra_known = extra_known;
change
}
fn changed_files(diff: &Diff) -> BTreeSet<String> {
diff.changes
.iter()
.map(|change| match change {
BaseHunk::FileMove { del, add, path } => todo!(),
BaseHunk::FileDel {
del,
contents,
path,
encoding,
} => todo!(),
BaseHunk::FileUndel {
undel,
contents,
path,
encoding,
} => todo!(),
BaseHunk::FileAdd {
add_name,
add_inode,
contents,
path,
encoding,
} => todo!(),
BaseHunk::SolveNameConflict { name, path } => todo!(),
BaseHunk::UnsolveNameConflict { name, path } => todo!(),
BaseHunk::Edit {
change,
local,
encoding,
} => local.path.clone(),
BaseHunk::Replacement {
change,
replacement,
local,
encoding,
} => todo!(),
BaseHunk::SolveOrderConflict { change, local } => todo!(),
BaseHunk::UnsolveOrderConflict { change, local } => todo!(),
BaseHunk::ResurrectZombies {
change,
local,
encoding,
} => todo!(),
BaseHunk::AddRoot { name, inode } => todo!(),
BaseHunk::DelRoot { name, inode } => todo!(),
})
.collect()
}
fn fmt_pijul_repository(
value: &pijul::Repository,
f: &mut std::fmt::Formatter,
) -> Result<(), std::fmt::Error> {
f.debug_struct("Repository")
.field("config", &value.config)
.field("path", &value.path)
.field("changes_dir", &value.changes_dir)
.finish()
}