use eyre::{Result, bail};
use crate::system::history::sync::SyncMode;
use crate::system::history::sync::origin;
#[derive(Debug, usage_rs::Args)]
#[usage(verbatim_doc_comment, after_long_help = AFTER_LONG_HELP)]
pub(crate) struct DotfilesOrigin {
#[usage(subcommand)]
command: Option<DotfilesOriginCommands>,
#[usage(long, effect = "destructive")]
remove: bool,
}
#[derive(Debug, usage_rs::Subcommands)]
enum DotfilesOriginCommands {
Set(DotfilesOriginSet),
}
#[derive(Debug, usage_rs::Args)]
pub(crate) struct DotfilesOriginSet {
url: String,
#[usage(long, value_name = "BRANCH", default = "main")]
branch: String,
#[usage(long, value_name = "MODE")]
sync: Option<String>,
#[usage(long, short)]
yes: bool,
}
impl DotfilesOrigin {
pub(crate) async fn run(self) -> Result<()> {
match self.command {
Some(DotfilesOriginCommands::Set(cmd)) => cmd.run().await,
None if self.remove => origin::remove(),
None => {
match crate::system::history::config::origin()? {
Some((path, origin)) => {
miseprintln!(
"{} (branch {}) declared in {}; mode {}",
origin.url,
origin.branch,
crate::file::display_path(&path),
SyncMode::current()?.as_str()
);
}
None => miseprintln!(
"no setup repository is connected; `mise bootstrap dotfiles origin set <url>` connects one"
),
}
Ok(())
}
}
}
}
impl DotfilesOriginSet {
async fn run(self) -> Result<()> {
if !crate::config::Settings::get().history.enabled {
bail!("history is disabled (history.enabled = false)");
}
let mode = match self.sync.as_deref() {
Some(mode) => SyncMode::parse(mode)?,
None if self.yes || crate::config::Settings::get().yes => SyncMode::current()?,
None => match crate::ui::prompt::confirm_with_default(
"Automatically publish saved edits AND apply incoming changes to live files? Choose no for manual sharing; local autosave continues in either mode.",
false,
)? {
crate::ui::prompt::Confirmation::Yes => SyncMode::Sync,
crate::ui::prompt::Confirmation::No => SyncMode::Manual,
crate::ui::prompt::Confirmation::Unavailable => {
bail!(
"not connected: choose --sync manual, --sync sync, or --sync fetch-only to connect without a mode prompt"
);
}
},
};
let (store, tracked, _) = super::history::open().await?;
if let Some(reason) = store.unavailable() {
bail!("cannot connect a setup repository: {reason}");
}
origin::set(
&store,
&tracked,
&origin::SetOptions {
url: self.url.clone(),
branch: self.branch.clone(),
mode,
yes: self.yes,
},
)
.await
}
}
static AFTER_LONG_HELP: &str = color_print::cstr!(
r#"<bold><underline>Examples:</underline></bold>
$ <bold>mise bootstrap dotfiles origin set https://github.com/you/setup.git</bold>
$ <bold>mise bootstrap dotfiles origin set git@github.com:you/setup.git --sync manual</bold>
$ <bold>mise bootstrap dotfiles origin</bold> # what is connected
$ <bold>mise bootstrap dotfiles origin --remove</bold>
"#
);