// git restore-autosave
// - --user and --all-users cannot both be present
// - --branch and --all-branches cannot both be present
// - if --user or -u is not present, the selected user is the repository signature
// - if --branch or -b is not present, the selected branch is the checked out branch
// - if --device or -d is present (UUID or hostname), filter to autosaves from that device
// - filter to autosaves from the current user (name or email) if --all-users is not present
// - filter to autosaves on the current branch
// - filter to autosaves after the head commit
// - if there is more than one option, enter pick mode
// - if there are no options, tell the user to use --all-users or --all-branches or --anytime
use auth_git2::GitAuthenticator;
use git_autosave::{Config, authenticate::Inquirer, inquire::AutosaveFilters};
use git2::{RemoteCallbacks, Repository, build::CheckoutBuilder};
fn main() -> Result<(), anyhow::Error> {
let all_users = std::env::args().any(|arg| arg == "--all-users");
let all_branches = std::env::args().any(|arg| arg == "--all-branches");
let all_devices = std::env::args().any(|arg| arg == "--all-devices");
let anytime = std::env::args().any(|arg| arg == "--anytime");
let force = std::env::args().any(|arg| arg == "--force");
let repository = Repository::discover(".")?;
let repo_id = git_autosave::repository_id(&repository)?;
let signature = repository.signature()?;
let branch = git_autosave::utils::current_branch(&repository)?;
let earliest_time = repository.head()?.peel_to_commit()?.time();
let gitconfig = repository.config()?;
let config: &'static _ = Box::leak(Box::new(Config::load()?));
let auth = GitAuthenticator::new().set_prompter(Inquirer(config));
let mut callbacks = RemoteCallbacks::new();
callbacks.credentials(auth.credentials(&gitconfig));
git_autosave::fetch_autosaves(&repository, callbacks)?;
let autosaves = git_autosave::autosaves(&repository)?;
let autosaves = git_autosave::inquire::filter_autosaves(
autosaves,
AutosaveFilters {
signature: &signature,
branch: &branch,
earliest_time,
repo_id: &repo_id,
all_users,
all_branches,
anytime,
all_devices,
},
)
.collect::<Vec<_>>();
if autosaves.is_empty() {
eprintln!("ERROR: There are no available autosaves for the given filters.");
if !all_users || !all_branches || !anytime {
eprintln!(
"hint: Use --all-users, --all-branches, --all-devices, or --anytime to include more options."
);
}
std::process::exit(1);
}
let autosave = git_autosave::inquire::select_autosave(autosaves, all_branches, all_users)?;
let autosaved_commit = repository.find_commit(autosave.commit_id)?;
let workdir = repository.find_tree(git_autosave::utils::workdir_to_tree(&repository)?)?;
let new_tree =
git_autosave::utils::merge_commit_with_tree(&repository, &autosaved_commit, &workdir)?;
git_autosave::save_undo_tree(&repository, &workdir)?;
git_autosave::saved_restored_autosave(&repository, &autosave)?;
let mut options = CheckoutBuilder::new();
if force {
options.force();
}
repository.checkout_tree(
&repository.find_object(new_tree, Some(git2::ObjectType::Tree))?,
Some(&mut options),
)?;
Ok(())
}
|