diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-05-30 18:31:44 +0000 |
commit | c23a457e72abe608715ac76f076f47dc42af07a5 (patch) | |
tree | 2772049aaf84b5c9d0ed12ec8d86812f7a7904b6 /vendor/gix-protocol/src | |
parent | Releasing progress-linux version 1.73.0+dfsg1-1~progress7.99u1. (diff) | |
download | rustc-c23a457e72abe608715ac76f076f47dc42af07a5.tar.xz rustc-c23a457e72abe608715ac76f076f47dc42af07a5.zip |
Merging upstream version 1.74.1+dfsg1.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'vendor/gix-protocol/src')
-rw-r--r-- | vendor/gix-protocol/src/command/mod.rs | 4 | ||||
-rw-r--r-- | vendor/gix-protocol/src/fetch/arguments/blocking_io.rs | 4 | ||||
-rw-r--r-- | vendor/gix-protocol/src/fetch/arguments/mod.rs | 38 | ||||
-rw-r--r-- | vendor/gix-protocol/src/fetch/delegate.rs | 16 | ||||
-rw-r--r-- | vendor/gix-protocol/src/fetch/tests.rs | 5 | ||||
-rw-r--r-- | vendor/gix-protocol/src/fetch_fn.rs | 8 | ||||
-rw-r--r-- | vendor/gix-protocol/src/handshake/function.rs | 8 | ||||
-rw-r--r-- | vendor/gix-protocol/src/handshake/mod.rs | 8 | ||||
-rw-r--r-- | vendor/gix-protocol/src/handshake/refs/mod.rs | 15 | ||||
-rw-r--r-- | vendor/gix-protocol/src/handshake/refs/shared.rs | 99 | ||||
-rw-r--r-- | vendor/gix-protocol/src/handshake/refs/tests.rs | 11 | ||||
-rw-r--r-- | vendor/gix-protocol/src/ls_refs.rs | 2 | ||||
-rw-r--r-- | vendor/gix-protocol/src/remote_progress.rs | 57 |
13 files changed, 173 insertions, 102 deletions
diff --git a/vendor/gix-protocol/src/command/mod.rs b/vendor/gix-protocol/src/command/mod.rs index 1216ba625..9fcc48e87 100644 --- a/vendor/gix-protocol/src/command/mod.rs +++ b/vendor/gix-protocol/src/command/mod.rs @@ -140,7 +140,7 @@ mod with_io { .iter() .find_map(|c| { if c.name() == Command::Fetch.as_str() { - c.values().map(|v| v.map(|f| f.to_owned()).collect()) + c.values().map(|v| v.map(ToOwned::to_owned).collect()) } else { None } @@ -189,7 +189,7 @@ mod with_io { .iter() .find_map(|c| { if c.name() == self.as_str().as_bytes().as_bstr() { - c.values().map(|v| v.map(|f| f.to_string()).collect::<Vec<_>>()) + c.values().map(|v| v.map(ToString::to_string).collect::<Vec<_>>()) } else { None } diff --git a/vendor/gix-protocol/src/fetch/arguments/blocking_io.rs b/vendor/gix-protocol/src/fetch/arguments/blocking_io.rs index 571792148..c946d46e1 100644 --- a/vendor/gix-protocol/src/fetch/arguments/blocking_io.rs +++ b/vendor/gix-protocol/src/fetch/arguments/blocking_io.rs @@ -45,9 +45,7 @@ impl Arguments { } transport.invoke( Command::Fetch.as_str(), - self.features - .iter() - .filter_map(|(k, v)| v.as_ref().map(|v| (*k, Some(v.as_ref())))), + self.features.iter().filter(|(_, v)| v.is_some()).cloned(), Some(std::mem::replace(&mut self.args, retained_state).into_iter()), ) } diff --git a/vendor/gix-protocol/src/fetch/arguments/mod.rs b/vendor/gix-protocol/src/fetch/arguments/mod.rs index 1adf993bb..50145bb15 100644 --- a/vendor/gix-protocol/src/fetch/arguments/mod.rs +++ b/vendor/gix-protocol/src/fetch/arguments/mod.rs @@ -129,11 +129,11 @@ impl Arguments { self.prefixed("deepen ", depth); } } - /// Deepen the commit history to include all commits from now to `seconds_since_unix_epoch`. - pub fn deepen_since(&mut self, seconds_since_unix_epoch: usize) { + /// Deepen the commit history to include all commits from now to (and including) `seconds` as passed since UNIX epoch. + pub fn deepen_since(&mut self, seconds: gix_date::SecondsSinceUnixEpoch) { debug_assert!(self.deepen_since, "'deepen-since' feature required"); if self.deepen_since { - self.prefixed("deepen-since ", seconds_since_unix_epoch); + self.prefixed("deepen-since ", seconds); } } /// Deepen the commit history in a relative instead of absolute fashion. @@ -165,20 +165,30 @@ impl Arguments { pub fn use_include_tag(&mut self) { debug_assert!(self.supports_include_tag, "'include-tag' feature required"); if self.supports_include_tag { - match self.version { - gix_transport::Protocol::V0 | gix_transport::Protocol::V1 => { - let features = self - .features_for_first_want - .as_mut() - .expect("call use_include_tag before want()"); - features.push("include-tag".into()) - } - gix_transport::Protocol::V2 => { - self.args.push("include-tag".into()); - } + self.add_feature("include-tag"); + } + } + + /// Add the given `feature`, unconditionally. + /// + /// Note that sending an unknown or unsupported feature may cause the remote to terminate + /// the connection. Use this method if you know what you are doing *and* there is no specialized + /// method for this, e.g. [`Self::use_include_tag()`]. + pub fn add_feature(&mut self, feature: &str) { + match self.version { + gix_transport::Protocol::V0 | gix_transport::Protocol::V1 => { + let features = self + .features_for_first_want + .as_mut() + .expect("call add_feature before first want()"); + features.push(feature.into()) + } + gix_transport::Protocol::V2 => { + self.args.push(feature.into()); } } } + fn prefixed(&mut self, prefix: &str, value: impl fmt::Display) { self.args.push(format!("{prefix}{value}").into()); } diff --git a/vendor/gix-protocol/src/fetch/delegate.rs b/vendor/gix-protocol/src/fetch/delegate.rs index e90022d41..e6f187402 100644 --- a/vendor/gix-protocol/src/fetch/delegate.rs +++ b/vendor/gix-protocol/src/fetch/delegate.rs @@ -183,7 +183,7 @@ mod blocking_io { ops::DerefMut, }; - use gix_features::progress::Progress; + use gix_features::progress::NestedProgress; use crate::{ fetch::{DelegateBlocking, Response}, @@ -207,7 +207,7 @@ mod blocking_io { fn receive_pack( &mut self, input: impl io::BufRead, - progress: impl Progress, + progress: impl NestedProgress + 'static, refs: &[Ref], previous_response: &Response, ) -> io::Result<()>; @@ -217,7 +217,7 @@ mod blocking_io { fn receive_pack( &mut self, input: impl BufRead, - progress: impl Progress, + progress: impl NestedProgress + 'static, refs: &[Ref], previous_response: &Response, ) -> io::Result<()> { @@ -229,7 +229,7 @@ mod blocking_io { fn receive_pack( &mut self, input: impl BufRead, - progress: impl Progress, + progress: impl NestedProgress + 'static, refs: &[Ref], previous_response: &Response, ) -> io::Result<()> { @@ -246,7 +246,7 @@ mod async_io { use async_trait::async_trait; use futures_io::AsyncBufRead; - use gix_features::progress::Progress; + use gix_features::progress::NestedProgress; use crate::{ fetch::{DelegateBlocking, Response}, @@ -272,7 +272,7 @@ mod async_io { async fn receive_pack( &mut self, input: impl AsyncBufRead + Unpin + 'async_trait, - progress: impl Progress, + progress: impl NestedProgress + 'static, refs: &[Ref], previous_response: &Response, ) -> io::Result<()>; @@ -282,7 +282,7 @@ mod async_io { async fn receive_pack( &mut self, input: impl AsyncBufRead + Unpin + 'async_trait, - progress: impl Progress, + progress: impl NestedProgress + 'static, refs: &[Ref], previous_response: &Response, ) -> io::Result<()> { @@ -297,7 +297,7 @@ mod async_io { async fn receive_pack( &mut self, input: impl AsyncBufRead + Unpin + 'async_trait, - progress: impl Progress, + progress: impl NestedProgress + 'static, refs: &[Ref], previous_response: &Response, ) -> io::Result<()> { diff --git a/vendor/gix-protocol/src/fetch/tests.rs b/vendor/gix-protocol/src/fetch/tests.rs index 80dc752dd..93cf6e8db 100644 --- a/vendor/gix-protocol/src/fetch/tests.rs +++ b/vendor/gix-protocol/src/fetch/tests.rs @@ -319,6 +319,7 @@ mod arguments { assert!(arguments.is_stateless(true), "V2 is stateless…"); assert!(arguments.is_stateless(false), "…in all cases"); + arguments.add_feature("no-progress"); arguments.deepen(1); arguments.deepen_relative(); arguments.want(id("7b333369de1221f9bfbbe03a3a13e9a09bc1c907")); @@ -329,6 +330,7 @@ mod arguments { b"0012command=fetch 0001000ethin-pack 000eofs-delta +0010no-progress 000ddeepen 1 0014deepen-relative 0032want 7b333369de1221f9bfbbe03a3a13e9a09bc1c907 @@ -347,6 +349,7 @@ mod arguments { let mut t = transport(&mut out, *is_stateful); let mut arguments = arguments_v2(Some("shallow")); + arguments.add_feature("no-progress"); arguments.deepen(1); arguments.deepen_since(12345); arguments.shallow(id("7b333369de1221f9bfbbe03a3a13e9a09bc1c9ff")); @@ -362,6 +365,7 @@ mod arguments { b"0012command=fetch 0001000ethin-pack 000eofs-delta +0010no-progress 000ddeepen 1 0017deepen-since 12345 0035shallow 7b333369de1221f9bfbbe03a3a13e9a09bc1c9ff @@ -371,6 +375,7 @@ mod arguments { 00000012command=fetch 0001000ethin-pack 000eofs-delta +0010no-progress 000ddeepen 1 0017deepen-since 12345 0035shallow 7b333369de1221f9bfbbe03a3a13e9a09bc1c9ff diff --git a/vendor/gix-protocol/src/fetch_fn.rs b/vendor/gix-protocol/src/fetch_fn.rs index 64d457711..b350976ef 100644 --- a/vendor/gix-protocol/src/fetch_fn.rs +++ b/vendor/gix-protocol/src/fetch_fn.rs @@ -1,6 +1,6 @@ use std::borrow::Cow; -use gix_features::progress::Progress; +use gix_features::progress::NestedProgress; use gix_transport::client; use maybe_async::maybe_async; @@ -59,7 +59,7 @@ where F: FnMut(credentials::helper::Action) -> credentials::protocol::Result, D: Delegate, T: client::Transport, - P: Progress, + P: NestedProgress + 'static, P::SubProgress: 'static, { let crate::handshake::Outcome { @@ -136,7 +136,7 @@ where .await?; previous_response = if response.has_pack() { progress.step(); - progress.set_name("receiving pack"); + progress.set_name("receiving pack".into()); if !sideband_all { setup_remote_progress(&mut progress, &mut reader); } @@ -159,7 +159,7 @@ where fn setup_remote_progress<P>(progress: &mut P, reader: &mut Box<dyn gix_transport::client::ExtendedBufRead + Unpin + '_>) where - P: Progress, + P: NestedProgress, P::SubProgress: 'static, { reader.set_progress_handler(Some(Box::new({ diff --git a/vendor/gix-protocol/src/handshake/function.rs b/vendor/gix-protocol/src/handshake/function.rs index 6324fb3e1..9e75c18d0 100644 --- a/vendor/gix-protocol/src/handshake/function.rs +++ b/vendor/gix-protocol/src/handshake/function.rs @@ -24,12 +24,12 @@ where { let (server_protocol_version, refs, capabilities) = { progress.init(None, progress::steps()); - progress.set_name("handshake"); + progress.set_name("handshake".into()); progress.step(); let extra_parameters: Vec<_> = extra_parameters .iter() - .map(|(k, v)| (k.as_str(), v.as_ref().map(|s| s.as_str()))) + .map(|(k, v)| (k.as_str(), v.as_deref())) .collect(); let supported_versions: Vec<_> = transport.supported_protocol_versions().into(); @@ -43,13 +43,13 @@ where Err(client::Error::Io(ref err)) if err.kind() == std::io::ErrorKind::PermissionDenied => { drop(result); // needed to workaround this: https://github.com/rust-lang/rust/issues/76149 let url = transport.to_url().into_owned(); - progress.set_name("authentication"); + progress.set_name("authentication".into()); let credentials::protocol::Outcome { identity, next } = authenticate(credentials::helper::Action::get_for_url(url.clone()))? .ok_or(Error::EmptyCredentials)?; transport.set_identity(identity)?; progress.step(); - progress.set_name("handshake (authenticated)"); + progress.set_name("handshake (authenticated)".into()); match transport.handshake(service, &extra_parameters).await { Ok(v) => { authenticate(next.store())?; diff --git a/vendor/gix-protocol/src/handshake/mod.rs b/vendor/gix-protocol/src/handshake/mod.rs index 6d70ed145..28243e96d 100644 --- a/vendor/gix-protocol/src/handshake/mod.rs +++ b/vendor/gix-protocol/src/handshake/mod.rs @@ -21,7 +21,7 @@ pub enum Ref { /// The hash of the object the ref points to. object: gix_hash::ObjectId, }, - /// A symbolic ref pointing to `target` ref, which in turn points to an `object` + /// A symbolic ref pointing to `target` ref, which in turn, ultimately after possibly following `tag`, points to an `object` Symbolic { /// The name at which the symbolic ref is located, like `HEAD`. full_ref_name: BString, @@ -31,7 +31,11 @@ pub enum Ref { /// /// [#205]: https://github.com/Byron/gitoxide/issues/205 target: BString, - /// The hash of the object the `target` ref points to. + /// The hash of the annotated tag the ref points to, if present. + /// + /// Note that this field is also `None` if `full_ref_name` is a lightweight tag. + tag: Option<gix_hash::ObjectId>, + /// The hash of the object the `target` ref ultimately points to. object: gix_hash::ObjectId, }, /// A ref is unborn on the remote and just points to the initial, unborn branch, as is the case in a newly initialized repository diff --git a/vendor/gix-protocol/src/handshake/refs/mod.rs b/vendor/gix-protocol/src/handshake/refs/mod.rs index 889842e4c..39c6c85a9 100644 --- a/vendor/gix-protocol/src/handshake/refs/mod.rs +++ b/vendor/gix-protocol/src/handshake/refs/mod.rs @@ -38,10 +38,17 @@ impl Ref { /// If `unborn`, the first object id will be the null oid. pub fn unpack(&self) -> (&BStr, Option<&gix_hash::oid>, Option<&gix_hash::oid>) { match self { - Ref::Direct { full_ref_name, object } - | Ref::Symbolic { - full_ref_name, object, .. - } => (full_ref_name.as_ref(), Some(object), None), + Ref::Direct { full_ref_name, object } => (full_ref_name.as_ref(), Some(object), None), + Ref::Symbolic { + full_ref_name, + tag, + object, + .. + } => ( + full_ref_name.as_ref(), + Some(tag.as_deref().unwrap_or(object)), + tag.as_deref().map(|_| object.as_ref()), + ), Ref::Peeled { full_ref_name, tag: object, diff --git a/vendor/gix-protocol/src/handshake/refs/shared.rs b/vendor/gix-protocol/src/handshake/refs/shared.rs index 046a2a1b1..45aefe68b 100644 --- a/vendor/gix-protocol/src/handshake/refs/shared.rs +++ b/vendor/gix-protocol/src/handshake/refs/shared.rs @@ -8,20 +8,33 @@ impl From<InternalRef> for Ref { InternalRef::Symbolic { path, target: Some(target), + tag, object, } => Ref::Symbolic { full_ref_name: path, target, + tag, object, }, InternalRef::Symbolic { path, target: None, + tag: None, object, } => Ref::Direct { full_ref_name: path, object, }, + InternalRef::Symbolic { + path, + target: None, + tag: Some(tag), + object, + } => Ref::Peeled { + full_ref_name: path, + tag, + object, + }, InternalRef::Peeled { path, tag, object } => Ref::Peeled { full_ref_name: path, tag, @@ -56,6 +69,7 @@ pub(crate) enum InternalRef { /// /// The latter is more of an edge case, please [this issue][#205] for details. target: Option<BString>, + tag: Option<gix_hash::ObjectId>, object: gix_hash::ObjectId, }, /// extracted from V1 capabilities, which contain some important symbolic refs along with their targets @@ -155,6 +169,7 @@ pub(in crate::handshake::refs) fn parse_v1( Some(position) => match out_refs.swap_remove(position) { InternalRef::SymbolicForLookup { path: _, target } => out_refs.push(InternalRef::Symbolic { path: path.into(), + tag: None, // TODO: figure out how annotated tags work here. object, target, }), @@ -172,7 +187,7 @@ pub(in crate::handshake::refs) fn parse_v1( pub(in crate::handshake::refs) fn parse_v2(line: &BStr) -> Result<Ref, Error> { let trimmed = line.trim_end(); - let mut tokens = trimmed.splitn(3, |b| *b == b' '); + let mut tokens = trimmed.splitn(4, |b| *b == b' '); match (tokens.next(), tokens.next()) { (Some(hex_hash), Some(path)) => { let id = if hex_hash == b"unborn" { @@ -183,7 +198,9 @@ pub(in crate::handshake::refs) fn parse_v2(line: &BStr) -> Result<Ref, Error> { if path.is_empty() { return Err(Error::MalformedV2RefLine(trimmed.to_owned().into())); } - Ok(if let Some(attribute) = tokens.next() { + let mut symref_target = None; + let mut peeled = None; + for attribute in tokens.by_ref().take(2) { let mut tokens = attribute.splitn(2, |b| *b == b':'); match (tokens.next(), tokens.next()) { (Some(attribute), Some(value)) => { @@ -191,32 +208,12 @@ pub(in crate::handshake::refs) fn parse_v2(line: &BStr) -> Result<Ref, Error> { return Err(Error::MalformedV2RefLine(trimmed.to_owned().into())); } match attribute { - b"peeled" => Ref::Peeled { - full_ref_name: path.into(), - object: gix_hash::ObjectId::from_hex(value.as_bytes())?, - tag: id.ok_or(Error::InvariantViolation { - message: "got 'unborn' as tag target", - })?, - }, - b"symref-target" => match value { - b"(null)" => Ref::Direct { - full_ref_name: path.into(), - object: id.ok_or(Error::InvariantViolation { - message: "got 'unborn' while (null) was a symref target", - })?, - }, - name => match id { - Some(id) => Ref::Symbolic { - full_ref_name: path.into(), - object: id, - target: name.into(), - }, - None => Ref::Unborn { - full_ref_name: path.into(), - target: name.into(), - }, - }, - }, + b"peeled" => { + peeled = Some(gix_hash::ObjectId::from_hex(value.as_bytes())?); + } + b"symref-target" => { + symref_target = Some(value); + } _ => { return Err(Error::UnknownAttribute { attribute: attribute.to_owned().into(), @@ -227,13 +224,53 @@ pub(in crate::handshake::refs) fn parse_v2(line: &BStr) -> Result<Ref, Error> { } _ => return Err(Error::MalformedV2RefLine(trimmed.to_owned().into())), } - } else { - Ref::Direct { + } + if tokens.next().is_some() { + return Err(Error::MalformedV2RefLine(trimmed.to_owned().into())); + } + Ok(match (symref_target, peeled) { + (Some(target_name), peeled) => match target_name { + b"(null)" => match peeled { + None => Ref::Direct { + full_ref_name: path.into(), + object: id.ok_or(Error::InvariantViolation { + message: "got 'unborn' while (null) was a symref target", + })?, + }, + Some(peeled) => Ref::Peeled { + full_ref_name: path.into(), + object: peeled, + tag: id.ok_or(Error::InvariantViolation { + message: "got 'unborn' while (null) was a symref target", + })?, + }, + }, + name => match id { + Some(id) => Ref::Symbolic { + full_ref_name: path.into(), + tag: peeled.map(|_| id), + object: peeled.unwrap_or(id), + target: name.into(), + }, + None => Ref::Unborn { + full_ref_name: path.into(), + target: name.into(), + }, + }, + }, + (None, Some(peeled)) => Ref::Peeled { + full_ref_name: path.into(), + object: peeled, + tag: id.ok_or(Error::InvariantViolation { + message: "got 'unborn' as tag target", + })?, + }, + (None, None) => Ref::Direct { object: id.ok_or(Error::InvariantViolation { message: "got 'unborn' as object name of direct reference", })?, full_ref_name: path.into(), - } + }, }) } _ => Err(Error::MalformedV2RefLine(trimmed.to_owned().into())), diff --git a/vendor/gix-protocol/src/handshake/refs/tests.rs b/vendor/gix-protocol/src/handshake/refs/tests.rs index 7d995da5c..3a6af8d2f 100644 --- a/vendor/gix-protocol/src/handshake/refs/tests.rs +++ b/vendor/gix-protocol/src/handshake/refs/tests.rs @@ -17,6 +17,7 @@ unborn refs/heads/symbolic symref-target:refs/heads/target 808e50d724f604f69ab93c6da2919c014667bedb refs/heads/main 7fe1b98b39423b71e14217aa299a03b7c937d656 refs/tags/foo peeled:808e50d724f604f69ab93c6da2919c014667bedb 7fe1b98b39423b71e14217aa299a03b7c937d6ff refs/tags/blaz +978f927e6397113757dfec6332e7d9c7e356ac25 refs/heads/symbolic symref-target:refs/tags/v1.0 peeled:4d979abcde5cea47b079c38850828956c9382a56 " .as_bytes(), ); @@ -29,6 +30,7 @@ unborn refs/heads/symbolic symref-target:refs/heads/target Ref::Symbolic { full_ref_name: "HEAD".into(), target: "refs/heads/main".into(), + tag: None, object: oid("808e50d724f604f69ab93c6da2919c014667bedb") }, Ref::Direct { @@ -56,8 +58,14 @@ unborn refs/heads/symbolic symref-target:refs/heads/target full_ref_name: "refs/tags/blaz".into(), object: oid("7fe1b98b39423b71e14217aa299a03b7c937d6ff") }, + Ref::Symbolic { + full_ref_name: "refs/heads/symbolic".into(), + target: "refs/tags/v1.0".into(), + tag: Some(oid("978f927e6397113757dfec6332e7d9c7e356ac25")), + object: oid("4d979abcde5cea47b079c38850828956c9382a56") + }, ] - ) + ); } #[maybe_async::test(feature = "blocking-client", async(feature = "async-client", async_std::test))] @@ -86,6 +94,7 @@ dce0ea858eef7ff61ad345cc5cdac62203fb3c10 refs/tags/gix-commitgraph-v0.0.0 Ref::Symbolic { full_ref_name: "HEAD".into(), target: "refs/heads/main".into(), + tag: None, object: oid("73a6868963993a3328e7d8fe94e5a6ac5078a944") }, Ref::Direct { diff --git a/vendor/gix-protocol/src/ls_refs.rs b/vendor/gix-protocol/src/ls_refs.rs index d0b2e9ba0..c5b71da93 100644 --- a/vendor/gix-protocol/src/ls_refs.rs +++ b/vendor/gix-protocol/src/ls_refs.rs @@ -86,7 +86,7 @@ pub(crate) mod function { ); progress.step(); - progress.set_name("list refs"); + progress.set_name("list refs".into()); let mut remote_refs = transport .invoke( ls_refs.as_str(), diff --git a/vendor/gix-protocol/src/remote_progress.rs b/vendor/gix-protocol/src/remote_progress.rs index 538a767fc..b516a06bf 100644 --- a/vendor/gix-protocol/src/remote_progress.rs +++ b/vendor/gix-protocol/src/remote_progress.rs @@ -1,10 +1,11 @@ use std::convert::TryFrom; use bstr::ByteSlice; -use nom::{ - bytes::complete::{tag, take_till, take_till1}, - combinator::{map_res, opt}, - sequence::{preceded, terminated}, +use winnow::{ + combinator::opt, + combinator::{preceded, terminated}, + prelude::*, + token::{tag, take_till0, take_till1}, }; /// The information usually found in remote progress messages as sent by a git server during @@ -25,8 +26,8 @@ pub struct RemoteProgress<'a> { impl<'a> RemoteProgress<'a> { /// Parse the progress from a typical git progress `line` as sent by the remote. - pub fn from_bytes(line: &[u8]) -> Option<RemoteProgress<'_>> { - parse_progress(line).ok().and_then(|(_, r)| { + pub fn from_bytes(mut line: &[u8]) -> Option<RemoteProgress<'_>> { + parse_progress(&mut line).ok().and_then(|r| { if r.percent.is_none() && r.step.is_none() && r.max.is_none() { None } else { @@ -73,36 +74,36 @@ impl<'a> RemoteProgress<'a> { } } -fn parse_number(i: &[u8]) -> nom::IResult<&[u8], usize> { - map_res(take_till(|c: u8| !c.is_ascii_digit()), btoi::btoi)(i) +fn parse_number(i: &mut &[u8]) -> PResult<usize, ()> { + take_till0(|c: u8| !c.is_ascii_digit()) + .try_map(btoi::btoi) + .parse_next(i) } -fn next_optional_percentage(i: &[u8]) -> nom::IResult<&[u8], Option<u32>> { +fn next_optional_percentage(i: &mut &[u8]) -> PResult<Option<u32>, ()> { opt(terminated( preceded( - take_till(|c: u8| c.is_ascii_digit()), - map_res(parse_number, u32::try_from), + take_till0(|c: u8| c.is_ascii_digit()), + parse_number.try_map(u32::try_from), ), tag(b"%"), - ))(i) + )) + .parse_next(i) } -fn next_optional_number(i: &[u8]) -> nom::IResult<&[u8], Option<usize>> { - opt(preceded(take_till(|c: u8| c.is_ascii_digit()), parse_number))(i) +fn next_optional_number(i: &mut &[u8]) -> PResult<Option<usize>, ()> { + opt(preceded(take_till0(|c: u8| c.is_ascii_digit()), parse_number)).parse_next(i) } -fn parse_progress(line: &[u8]) -> nom::IResult<&[u8], RemoteProgress<'_>> { - let (i, action) = take_till1(|c| c == b':')(line)?; - let (i, percent) = next_optional_percentage(i)?; - let (i, step) = next_optional_number(i)?; - let (i, max) = next_optional_number(i)?; - Ok(( - i, - RemoteProgress { - action: action.into(), - percent, - step, - max, - }, - )) +fn parse_progress<'i>(line: &mut &'i [u8]) -> PResult<RemoteProgress<'i>, ()> { + let action = take_till1(|c| c == b':').parse_next(line)?; + let percent = next_optional_percentage.parse_next(line)?; + let step = next_optional_number.parse_next(line)?; + let max = next_optional_number.parse_next(line)?; + Ok(RemoteProgress { + action: action.into(), + percent, + step, + max, + }) } |