Add WASI SSH CLI and in-process Git SSH transport
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
//! Single-ref receive-pack client over standard wasi:http.
|
||||
//! Single-ref receive-pack over standard WASI HTTP or in-process SSH exec channels.
|
||||
|
||||
use crate::Result;
|
||||
use crate::{
|
||||
@@ -587,6 +587,9 @@ pub fn push(p: PushParams) -> Result<PushResult> {
|
||||
.to_bstring()
|
||||
.to_str_lossy()
|
||||
.into_owned();
|
||||
if crate::ssh::is_ssh(&url) {
|
||||
return ssh_push(&repo, &url, remote, &plan, p.set_upstream.unwrap_or(false));
|
||||
}
|
||||
let base = clean_url(&url)
|
||||
.map_err(|e| error("push URL", e))?
|
||||
.to_string()
|
||||
@@ -670,3 +673,57 @@ pub fn push(p: PushParams) -> Result<PushResult> {
|
||||
})();
|
||||
result
|
||||
}
|
||||
fn ssh_push(
|
||||
repo: &gix::Repository,
|
||||
url: &str,
|
||||
remote: &str,
|
||||
plan: &Plan,
|
||||
upstream: bool,
|
||||
) -> Result<PushResult> {
|
||||
let (mut read, mut write) =
|
||||
crate::ssh::connection(url, gix_transport::Service::ReceivePack)?.into_inner();
|
||||
let advertised = advertise_refs(&mut read)?;
|
||||
let old = advertised.refs.get(&plan.destination).copied();
|
||||
if let (Some(old), Some(new)) = (old, plan.new) {
|
||||
if old != new && !plan.force && !is_ancestor(repo, old, new)? {
|
||||
return Err(error("push", "non-fast-forward; fetch first or use force"));
|
||||
}
|
||||
}
|
||||
let up_to_date = old == plan.new;
|
||||
let mut objects = 0;
|
||||
if !up_to_date {
|
||||
if plan.new.is_none() && !advertised.caps.contains("delete-refs") {
|
||||
return Err(error("push", "remote does not allow deleting refs"));
|
||||
}
|
||||
let ids = match plan.new {
|
||||
Some(new) => objects_to_send(repo, new, advertised.refs.values().copied())?,
|
||||
None => BTreeSet::new(),
|
||||
};
|
||||
objects = ids.len();
|
||||
let sideband = advertised.caps.contains("side-band-64k");
|
||||
let mut caps = vec!["report-status"];
|
||||
if sideband {
|
||||
caps.push("side-band-64k");
|
||||
}
|
||||
commands(old, plan, &caps, &mut write)?;
|
||||
if plan.new.is_some() {
|
||||
pack(repo, &ids, &mut write)?;
|
||||
}
|
||||
write.flush().map_err(|e| error("push SSH flush", e))?;
|
||||
report(&mut read, &plan.destination, sideband)?;
|
||||
} else {
|
||||
write
|
||||
.write_all(b"0000")
|
||||
.and_then(|_| write.flush())
|
||||
.map_err(|e| error("push SSH finish", e))?;
|
||||
}
|
||||
update_local(repo, remote, plan, upstream)?;
|
||||
Ok(PushResult {
|
||||
remote: remote.into(),
|
||||
reference: plan.destination.clone(),
|
||||
old: old.map(|id| id.to_string()),
|
||||
new: plan.new.map(|id| id.to_string()),
|
||||
up_to_date,
|
||||
objects,
|
||||
})
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user