H4AU6QRPRDRFW3V7NN5CJ6DHLEUBYGNLRZ5GYV6ULBGRMOPCJQXQC
DO2Y5TY5JQISUHCVNPI2FXO7WWZVJQ3LGPWF4DNADMGZRIO6PT2QC
FVQYZQFL7WHSC3UUPJ4IWTP7SKTDQ4K6K5HY4EDK3JKXG3CQNZEAC
TI7PCK7JLPU4KYE65XIMBUPPY7DRPVDAETPDFMG3VAQGGDRGQHPQC
SXEYMYF7P4RZMZ46WPL4IZUTSQ2ATBWYZX7QNVMS3SGOYXYOHAGQC
ZSFJT4SFIAS7WBODRZOFKKG4SVYBC5PC6XY75WYN7CCQ3SMV7IUQC
GYXIF25T2BCTCWCQI5DQOF3F4HBWDJUDJUMZ2WLHVBIOYATJTFAQC
FBXYP7QM7SG6P2JDJVQPPCRKJE3GVYXNQ5GVV4GRDUNG6Q4ZRDJQC
MU5GSJAW65PEG3BRYUKZ7O37BPHW3MOX3S5E2RFOXKGUOJEEDQ5AC
I52XSRUH5RVHQBFWVMAQPTUSPAJ4KNVID2RMI3UGCVKFLYUO6WZAC
Q45QHPO4HDTEZF2W4UDZSYYQ46BPEIWSW4GJILZR5HTJNLKXJABQC
OIOMXESDNMLOTMNYCZZBYSBAQTYPAXXMUHTLA2AYCMNHZMPSLX2AC
IQ4FCHPZYGTZHCQHUIRCMUI5LCHIDSJCM2AZXGRJARWLCPPLXZOQC
AI73GKAO5QBPR6YGW7H5UNZYAEGYGIHAFO6DM2DWCPMVYLHE547QC
BVVMTOYWG4WSVWEYNW2XIG3D34Y7V54ACSSJPQ2AREOO7NGPMLDQC
VBMXB443FGZL6DLT6KAP2ICFCCQNXCUMDEUL67HB4CNKFMBBNSSAC
367UBQ6KNAKUEWG32R4QRJ6H7IE7NAZFOPTC3ZOE4Z6E44RV3ISQC
JZADJIA3P3EOKPBGEKEXJVGWHNF2SIHYNNMB3XFNPBU4BTVGM3YQC
TPEH2XNBS5RO4IEVKENVF6P65AH7IX64KK2JAYMSJT3J5GXO67EAC
GFED4ORASDTMUQUCOXXZMOXSR6JJGCP3IEM3SMDG52GX2NMXC4GQC
KI2AFWOSN3PTGBGYQ7UKHFOZERZWEUWQ4AQNADG5S4QDJ53ESXFAC
A3RM526Y7LUXNYW4TL56YKQ5GVOK2R5D7JJVTSQ6TT5MEXIR6YAAC
R245EVN36J34PTG3I2RMX5LIOT76LCPL5RZ2H22BCIXFBGJYJ25QC
SEWGHUHQEEBJR7UPG3PSU7DSM376R43QEYENAZK325W46DCFMXKAC
VL7ZYKHBPKLNY5SA5QBW56SJ7LBBCKCGV5UAYLVF75KY6PPBOD4AC
impl RemoteConfig {
async fn to_remote(
&self,
channel: &str,
no_cert_check: bool,
with_path: bool,
) -> Result<RemoteRepo, anyhow::Error> {
match self {
RemoteConfig::Ssh { ssh, .. } => {
if let Some(mut sshr) = ssh_remote(ssh, with_path) {
debug!("unknown_remote, ssh = {:?}", ssh);
if let Some(c) = sshr.connect(ssh, channel).await? {
return Ok(RemoteRepo::Ssh(c));
}
}
bail!("Remote not found: {:?}", ssh)
}
RemoteConfig::Http {
http,
headers,
name,
} => {
let mut h = Vec::new();
for (k, v) in headers.iter() {
match v {
RemoteHttpHeader::String(s) => {
h.push((k.clone(), s.clone()));
}
RemoteHttpHeader::Shell(shell) => {
h.push((k.clone(), shell_cmd(&shell.shell)?));
}
}
}
return Ok(RemoteRepo::Http(Http {
url: http.parse().unwrap(),
channel: channel.to_string(),
client: reqwest::ClientBuilder::new()
.danger_accept_invalid_certs(no_cert_check)
.build()?,
headers: h,
name: name.to_string(),
}));
}
}
}
}
.header(reqwest::header::USER_AGENT, USER_AGENT)
.send()
.await
{
.header(reqwest::header::USER_AGENT, USER_AGENT);
for (k, v) in headers.iter() {
req = req.header(k.as_str(), v.as_str());
}
let mut res = if let Ok(res) = req.send().await {
.header(reqwest::header::USER_AGENT, USER_AGENT)
.body(body)
.send()
.await?;
.header(reqwest::header::USER_AGENT, USER_AGENT);
for (k, v) in self.headers.iter() {
req = req.header(k.as_str(), v.as_str());
}
let resp = req.body(body).send().await?;
#[derive(Debug, Serialize)]
pub enum RemoteName {
Name(String),
Split(SplitRemote),
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum RemoteConfig {
Ssh {
name: String,
ssh: String,
},
Http {
name: String,
http: String,
#[serde(default)]
headers: HashMap<String, RemoteHttpHeader>,
},
#[derive(Clone, Copy, Debug)]
pub enum Direction {
Push,
Pull,
}
impl RemoteName {
pub fn with_dir(&self, d: Direction) -> &str {
match (self, d) {
(RemoteName::Name(ref s), _) => s,
(RemoteName::Split(ref s), Direction::Pull) => &s.pull,
(RemoteName::Split(ref s), Direction::Push) => &s.push,
impl RemoteConfig {
pub fn name(&self) -> &str {
match self {
RemoteConfig::Ssh { name, .. } => name,
RemoteConfig::Http { name, .. } => name,
use serde::de::{self, MapAccess, Visitor};
use serde::de::{Deserialize, Deserializer};
use std::fmt;
use std::marker::PhantomData;
impl<'de> Deserialize<'de> for RemoteName {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
struct StringOrStruct(PhantomData<fn() -> RemoteName>);
impl<'de> Visitor<'de> for StringOrStruct {
type Value = RemoteName;
fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
formatter.write_str("string or map")
}
fn visit_str<E>(self, value: &str) -> Result<Self::Value, E>
where
E: de::Error,
{
Ok(RemoteName::Name(value.to_string()))
}
fn visit_map<M>(self, map: M) -> Result<Self::Value, M::Error>
where
M: MapAccess<'de>,
{
// `MapAccessDeserializer` is a wrapper that turns a `MapAccess`
// into a `Deserializer`, allowing it to be used as the input to T's
// `Deserialize` implementation. T then deserializes itself using
// the entries from the map visitor.
Ok(RemoteName::Split(Deserialize::deserialize(
de::value::MapAccessDeserializer::new(map),
)?))
}
}
deserializer.deserialize_any(StringOrStruct(PhantomData))
}
#[derive(Debug, Serialize, Deserialize)]
#[serde(untagged)]
pub enum RemoteHttpHeader {
String(String),
Shell(Shell),
pub fn shell_cmd(s: &str) -> Result<String, anyhow::Error> {
let out = if cfg!(target_os = "windows") {
std::process::Command::new("cmd")
.args(&["/C", s])
.output()
.expect("failed to execute process")
} else {
std::process::Command::new(std::env::var("SHELL").unwrap_or("sh".to_string()))
.arg("-c")
.arg(s)
.output()
.expect("failed to execute process")
};
Ok(String::from_utf8(out.stdout)?)
}