git: add workspace coordination forms and conversation trailers
This commit is contained in:
@@ -14,6 +14,7 @@ use std::{
|
||||
/// Attach a linked worktree, or adopt existing bytes onto an unborn branch.
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub(crate) struct AddParams {
|
||||
pub detached: Option<bool>,
|
||||
/// Repository name or absolute worktree/bare path under /repos/ or /plugins/.
|
||||
pub repo: String,
|
||||
/// Absolute worktree path under /plugins/ or /repos/, without dot segments.
|
||||
@@ -150,10 +151,28 @@ pub(crate) struct AttachParams {
|
||||
/// Existing short local branch name.
|
||||
pub branch: String,
|
||||
}
|
||||
pub(crate) fn prune(repo: &gix::Repository) -> Result<()> {
|
||||
let base = repo.common_dir().join("worktrees");
|
||||
if !base.exists() {
|
||||
return Ok(());
|
||||
}
|
||||
for entry in fs::read_dir(base).map_err(|e| error("worktree prune", e))? {
|
||||
let dir = entry.map_err(|e| error("worktree prune", e))?.path();
|
||||
if dir.join("locked").exists() {
|
||||
continue;
|
||||
}
|
||||
let gitdir = read(&dir.join("gitdir"))?;
|
||||
if !Path::new(gitdir.trim()).exists() {
|
||||
fs::remove_dir_all(dir).map_err(|e| error("worktree prune", e))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
pub(crate) fn attach(repo: &gix::Repository, p: AttachParams) -> Result<WorktreeInfo> {
|
||||
add_with(
|
||||
repo,
|
||||
AddParams {
|
||||
detached: None,
|
||||
repo: p.repo,
|
||||
path: p.path,
|
||||
branch: p.branch,
|
||||
@@ -170,20 +189,24 @@ fn add_with(repo: &gix::Repository, p: AddParams, keep_files: bool) -> Result<Wo
|
||||
let path = absolute(&p.path)?;
|
||||
let common = canonical(repo.common_dir())?;
|
||||
separate(&path, &common)?;
|
||||
let detached = p.detached.unwrap_or(false);
|
||||
let branch = branches::branch_name(&p.branch)?;
|
||||
ensure_available(repo, &branch)?;
|
||||
if !detached {
|
||||
ensure_available(repo, &branch)?;
|
||||
}
|
||||
if let Some(current_path) = repo.workdir() {
|
||||
if crate::head_info(repo)?.branch.as_deref() == Some(&branch) {
|
||||
if !detached && crate::head_info(repo)?.branch.as_deref() == Some(&branch) {
|
||||
return Err(error(
|
||||
"branch checked out",
|
||||
format!("{branch} is checked out at {}", current_path.display()),
|
||||
));
|
||||
}
|
||||
}
|
||||
let exists = repo
|
||||
.try_find_reference(branch.as_str())
|
||||
.map_err(|e| error("worktree branch", e))?
|
||||
.is_some();
|
||||
let exists = !detached
|
||||
&& repo
|
||||
.try_find_reference(branch.as_str())
|
||||
.map_err(|e| error("worktree branch", e))?
|
||||
.is_some();
|
||||
let adopt = p.adopt.unwrap_or(false);
|
||||
if adopt && (exists || p.from.is_some()) {
|
||||
return Err(error(
|
||||
@@ -296,8 +319,12 @@ fn add_with(repo: &gix::Repository, p: AddParams, keep_files: bool) -> Result<Wo
|
||||
&linked,
|
||||
branches::CheckoutParams {
|
||||
repo: p.path.clone(),
|
||||
target: p.branch.clone(),
|
||||
create: Some(!exists),
|
||||
target: if detached {
|
||||
id.to_string()
|
||||
} else {
|
||||
p.branch.clone()
|
||||
},
|
||||
create: Some(!exists && !detached),
|
||||
force: None,
|
||||
},
|
||||
)?
|
||||
|
||||
Reference in New Issue
Block a user