Skip to content

Commit

Permalink
[clone] Capabilities now can have multiple values (per command) for V2
Browse files Browse the repository at this point in the history
We  handle all of this in a single, simple type, which is nice and makes
things easier.
  • Loading branch information
Byron committed Aug 24, 2020
1 parent f58a785 commit 44dcea6
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 10 deletions.
33 changes: 24 additions & 9 deletions git-transport/src/client/capabilities.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,10 @@ quick_error! {
}
}

pub struct Capabilities(BString);
pub struct Capabilities {
data: BString,
value_sep: u8,
}
pub struct Capability<'a>(&'a BStr);

impl<'a> Capability<'a> {
Expand All @@ -43,6 +46,9 @@ impl<'a> Capability<'a> {
pub fn value(&self) -> Option<&BStr> {
self.0.splitn(2, |b| *b == b'=').nth(1).map(|s| s.as_bstr())
}
pub fn values(&self) -> Option<impl Iterator<Item = &BStr>> {
self.value().map(|v| v.split(|b| *b == b' ').map(|s| s.as_bstr()))
}
}

impl Capabilities {
Expand All @@ -52,7 +58,13 @@ impl Capabilities {
return Err(Error::NoCapabilities);
}
let capabilities = &bytes[delimiter_pos + 1..];
Ok((Capabilities(capabilities.as_bstr().to_owned()), delimiter_pos))
Ok((
Capabilities {
data: capabilities.as_bstr().to_owned(),
value_sep: b' ',
},
delimiter_pos,
))
}
pub fn from_lines(read: impl io::BufRead) -> Result<Capabilities, Error> {
let mut lines = read.lines();
Expand All @@ -69,23 +81,26 @@ impl Capabilities {
}
_ => return Err(Error::MalformattedVersionLine(version_line)),
};
Ok(Capabilities(
lines
Ok(Capabilities {
value_sep: b'\n',
data: lines
.inspect(|l| {
if let Ok(l) = l {
assert!(
!l.contains(" "),
"spaces are not expected in keys or values, got '{}'",
!l.contains('\n'),
"newlines are not expected in keys or values, got '{}'",
l
)
}
})
.collect::<Result<Vec<_>, _>>()?
.join(" ")
.join("\n")
.into(),
))
})
}
pub fn iter(&self) -> impl Iterator<Item = Capability> {
self.0.split(|b| *b == b' ').map(|c| Capability(c.as_bstr()))
self.data
.split(move |b| *b == self.value_sep)
.map(|c| Capability(c.as_bstr()))
}
}
24 changes: 24 additions & 0 deletions git-transport/tests/client/http.rs
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,29 @@ User-Agent: git/oxide-{}
refs.is_none(),
"refs are only returned in V1, as V2 favors a separate command (with more options)"
);
assert_eq!(
capabilities
.iter()
.map(|v| {
(
v.name().to_owned(),
v.values().map(|v| v.map(ToOwned::to_owned).collect::<Vec<_>>()),
)
})
.collect::<Vec<_>>(),
[
("agent", Some(&["git/github-gdf51a71f0236"][..])),
("ls-refs", None),
("fetch", Some(&["shallow", "filter"])),
("server-option", None)
]
.iter()
.map(|(k, v)| (
k.as_bytes().into(),
v.map(|v| v.iter().map(|v| v.as_bytes().into()).collect::<Vec<_>>())
))
.collect::<Vec<_>>()
);

assert_eq!(
server.received_as_string().lines().collect::<Vec<_>>(),
Expand All @@ -241,6 +264,7 @@ User-Agent: git/oxide-{}
Host: 127.0.0.1:{}
Accept: */*
User-Agent: git/oxide-{}
Git-Protocol: version=2
",
server.addr.port(),
Expand Down
8 changes: 7 additions & 1 deletion tasks.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,16 @@
* [ ] ssh?
* [ ] git://git-upload-pack
* [x] V1 handshake
* [ ] send values
* [ ] receive data with sidebands
* [x] V2 handshake
* [ ] send command request
* [ ] http://git-upload-pack
* [x] V1 handshake
* [ ] V2 handshake
* [ ] send values
* [ ] receive data with sidebands
* [x] V2 handshake
* [ ] send command request
* **git-refs**
* [ ] a way to know if a ref needs to be parsed (like `ref/name^{}`)
* [ ] create ref pointing to ID
Expand Down

0 comments on commit 44dcea6

Please sign in to comment.