mirror of
https://codeberg.org/icewind/haze.git
synced 2026-10-01 08:44:09 +02:00
feat(start): Add --detach flag
This will create a dedicated worktree for the instance. App listed to be enabled will also benefit from their own worktrees. The worktree is cleanup when the instance is destroyed.
This commit is contained in:
parent
c54302fdaa
commit
0e702f7b87
9 changed files with 339 additions and 27 deletions
80
src/git.rs
80
src/git.rs
|
|
@ -1,9 +1,10 @@
|
|||
use crate::config::HazeConfig;
|
||||
use crate::Result;
|
||||
use camino::{Utf8Path, Utf8PathBuf};
|
||||
use git2::build::CheckoutBuilder;
|
||||
use git2::{Branch, BranchType, Repository, RepositoryState};
|
||||
use indicatif::{MultiProgress, ProgressBar, ProgressStyle};
|
||||
use miette::{Context, IntoDiagnostic};
|
||||
use miette::{Context, IntoDiagnostic, Report};
|
||||
use rayon::iter::{IntoParallelRefIterator, ParallelIterator};
|
||||
use rayon::ThreadPoolBuilder;
|
||||
use std::fs::read_dir;
|
||||
|
|
@ -69,6 +70,83 @@ pub fn checkout_all(config: &HazeConfig, mut name: &str, verbose: bool) -> Resul
|
|||
Ok(())
|
||||
}
|
||||
|
||||
pub fn find_app_repo(config: &HazeConfig, app: &str) -> Option<Utf8PathBuf> {
|
||||
find_app_repos(config)
|
||||
.ok()?
|
||||
.filter_map(|dir| Utf8PathBuf::try_from(dir).ok())
|
||||
.find(|dir| dir.file_name().is_some_and(|name| name == app))
|
||||
}
|
||||
|
||||
fn git(repo: &Utf8Path, args: &[&str]) -> Result<String> {
|
||||
let output = Command::new(GIT_BINARY)
|
||||
.args(args)
|
||||
.current_dir(repo)
|
||||
.output()
|
||||
.into_diagnostic()
|
||||
.wrap_err_with(|| format!("Failed to run git {}", args.join(" ")))?;
|
||||
if !output.status.success() {
|
||||
let err = String::from_utf8_lossy(&output.stderr);
|
||||
return Err(Report::msg(format!(
|
||||
"git {} failed in {}: {}",
|
||||
args.join(" "),
|
||||
repo,
|
||||
err.trim()
|
||||
)));
|
||||
}
|
||||
Ok(String::from_utf8_lossy(&output.stdout).trim().into())
|
||||
}
|
||||
|
||||
fn has_ref(repo: &Utf8Path, git_ref: &str) -> bool {
|
||||
git(
|
||||
repo,
|
||||
&[
|
||||
"rev-parse",
|
||||
"--verify",
|
||||
"--quiet",
|
||||
&format!("{git_ref}^{{commit}}"),
|
||||
],
|
||||
)
|
||||
.is_ok()
|
||||
}
|
||||
|
||||
pub fn create_worktree(repo: &Utf8Path, dest: &Utf8Path, git_ref: &str) -> Result<()> {
|
||||
if !has_ref(repo, git_ref) {
|
||||
// The reference might be a tag that hasn't been fetched yet.
|
||||
let _ = git(repo, &["fetch", "origin", "tag", git_ref]);
|
||||
if !has_ref(repo, git_ref) {
|
||||
return Err(Report::msg(format!("{git_ref} not found in {repo}")));
|
||||
}
|
||||
}
|
||||
|
||||
git(
|
||||
repo,
|
||||
&["worktree", "add", "--detach", dest.as_str(), git_ref], // Use a detached head so the worktree doesn't conflict with another one.
|
||||
)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn remove_worktree(repo: &Utf8Path) -> Result<()> {
|
||||
git(repo, &["worktree", "remove", "--force", repo.as_str()])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn init_submodules(worktree: &Utf8Path) -> Result<()> {
|
||||
git(worktree, &["submodule", "update", "--init", "--recursive"])?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn prune_worktrees(config: &HazeConfig) -> Result<()> {
|
||||
let app_repos = find_app_repos(config)?
|
||||
.filter_map(|repo| Utf8PathBuf::try_from(repo).ok())
|
||||
.collect::<Vec<_>>();
|
||||
for repo in once(config.sources_root.clone()).chain(app_repos) {
|
||||
if let Err(e) = git(&repo, &["worktree", "prune"]) {
|
||||
eprintln!("Failed to prune worktrees of {repo}: {e:#}");
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn current_branch_name(repo: &Repository) -> Option<String> {
|
||||
let (branch, _) = repo
|
||||
.branches(None)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue