hnz/src/main.rs
use std::{ops::Deref, path::PathBuf, sync::Arc};
use clap::{ArgMatches, Command, arg};
use jj_lib::{
backend::{Backend, BackendLoadError},
config::StackedConfig,
default_index::DefaultIndexStore,
default_submodule_store::DefaultSubmoduleStore,
git_backend::GitBackend,
repo::{ReadonlyRepo, RepoLoader, RepoLoaderError, StoreFactories, StoreLoadError},
settings::UserSettings,
simple_op_heads_store::SimpleOpHeadsStore,
simple_op_store::SimpleOpStore,
};
mod back;
mod front;
mod sync;
pub struct Help<'a>(&'a ArgMatches);
impl<'a> Deref for Help<'a> {
type Target = ArgMatches;
fn deref(&self) -> &Self::Target {
self.0
}
}
fn main() {
let matches = Command::new("hnz")
.version("1.0")
.about("Manage hennzau's jj hub")
.subcommand_required(true)
.subcommand(
Command::new("gen-front")
.about("Generate the correct .md file for a repo")
.arg(
arg!(<REPO_PATH>)
.required(true)
.value_parser(clap::value_parser!(PathBuf))
.help("Root path of a jj repository"),
)
.arg(
arg!(<OUTPUT>)
.required(true)
.value_parser(clap::value_parser!(PathBuf))
.help("Path where the <REPO_NAME>.md will be created"),
),
)
.subcommand(
Command::new("gen-back")
.about("Generate the correct .json file for a repo")
.arg(
arg!(<REPO_PATH>)
.required(true)
.value_parser(clap::value_parser!(PathBuf))
.help("Root path of a jj repository"),
)
.arg(
arg!(<OUTPUT>)
.required(true)
.value_parser(clap::value_parser!(PathBuf))
.help("Path where the <REPO_NAME>.json will be created"),
),
)
.subcommand(
Command::new("sync")
.about("Make sure to remove front and back files for non existing repositories")
.arg(
arg!(<BASE_PATH>)
.required(true)
.value_parser(clap::value_parser!(PathBuf))
.help("Root path of a jj hub"),
)
.arg(
arg!(<MD_PATH>)
.required(true)
.value_parser(clap::value_parser!(PathBuf))
.help("Path where the .md files must be sync"),
)
.arg(
arg!(<JSON_PATH>)
.required(true)
.value_parser(clap::value_parser!(PathBuf))
.help("Path where the .json files must be sync"),
),
)
.get_matches();
match matches.subcommand() {
Some(("gen-front", args)) => {
if let Err(e) = front::gen_front(Help(args)) {
println!("{e:?}")
}
}
Some(("gen-back", args)) => {
if let Err(e) = back::gen_back(Help(args)) {
println!("{e:?}")
}
}
Some(("sync", args)) => {
if let Err(e) = sync::sync(Help(args)) {
println!("{e:?}")
}
}
_ => unreachable!(),
}
}
impl Help<'_> {
pub fn load(
&self,
path: PathBuf,
) -> Result<Result<Arc<ReadonlyRepo>, RepoLoaderError>, StoreLoadError> {
let mut store_factories = StoreFactories::empty();
store_factories.add_backend(
"git",
Box::new(|a, b| {
GitBackend::load(a, b)
.map(|git| Box::new(git) as Box<dyn Backend>)
.map_err(|e| BackendLoadError(Box::new(*e)))
}),
);
store_factories.add_op_store(
"simple_op_store",
Box::new(|_, b, c| Ok(Box::new(SimpleOpStore::load(b, c)))),
);
store_factories.add_op_heads_store(
"simple_op_heads_store",
Box::new(|_, b| Ok(Box::new(SimpleOpHeadsStore::load(b)))),
);
store_factories.add_index_store(
"default",
Box::new(|_, b| Ok(Box::new(DefaultIndexStore::load(b)))),
);
store_factories.add_submodule_store(
"default",
Box::new(|_, b| Ok(Box::new(DefaultSubmoduleStore::load(b)))),
);
let config = StackedConfig::with_defaults();
let settings = UserSettings::from_config(config)
.expect("UserSettings from default config should never fail");
RepoLoader::init_from_file_system(&settings, &path, &store_factories)
.map(|loader| loader.load_at_head())
}
}