From 89627a8b6a58cad55267296c666d7c4b246e6c53 Mon Sep 17 00:00:00 2001 From: Fintan Halpenny Date: Tue, 23 Apr 2024 17:20:48 +0100 Subject: [PATCH] radicle: add upload-pack events Add a variant for upload-pack events to allow reporting from the upload-pack process. Signed-off-by: Fintan Halpenny X-Clacks-Overhead: GNU Terry Pratchett --- radicle/src/node/events.rs | 11 +++ radicle/src/node/events/upload_pack.rs | 96 ++++++++++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 radicle/src/node/events/upload_pack.rs diff --git a/radicle/src/node/events.rs b/radicle/src/node/events.rs index 34d9f43e..945195e5 100644 --- a/radicle/src/node/events.rs +++ b/radicle/src/node/events.rs @@ -1,3 +1,7 @@ +//! Events for `upload-pack` processes. +pub mod upload_pack; +pub use upload_pack::UploadPack; + use std::ops::Deref; use std::sync::Arc; use std::sync::Mutex; @@ -62,6 +66,13 @@ pub enum Event { features: node::Features, addresses: Vec, }, + UploadPack(upload_pack::UploadPack), +} + +impl From for Event { + fn from(value: upload_pack::UploadPack) -> Self { + Self::UploadPack(value) + } } /// Events feed. diff --git a/radicle/src/node/events/upload_pack.rs b/radicle/src/node/events/upload_pack.rs new file mode 100644 index 00000000..284947fe --- /dev/null +++ b/radicle/src/node/events/upload_pack.rs @@ -0,0 +1,96 @@ +use std::fmt; +use std::io; +use std::process::ExitStatus; + +use crate::node::NodeId; +use crate::prelude::RepoId; + +/// Events that can occur when an upload-pack process is running. +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub enum UploadPack { + /// The upload-pack process finished with `status`. + Done { + /// The repository being fetched. + rid: RepoId, + /// The node being fetched from. + remote: NodeId, + /// The status code of the upload-pack process. + /// + /// N.b. `ExitStatus` can not be de/serialized, so the `Display` of the + /// status is used instead. + status: String, + }, + /// The upload-pack process emitted some [`Progress`] data. + Write { + /// The repository being fetched. + rid: RepoId, + /// The node being fetched from. + remote: NodeId, + /// The progress metadata of the upload-pack. + progress: Progress, + }, + Error { + /// The repository being fetched. + rid: RepoId, + /// The node being fetched from. + remote: NodeId, + /// The error that occurred during the upload-pack. + err: String, + }, +} + +impl UploadPack { + /// Construct a `UploadPack::Write` event. + pub fn write(rid: RepoId, remote: NodeId, progress: Progress) -> Self { + Self::Write { + rid, + remote, + progress, + } + } + + /// Construct a `UploadPack::Done` event. + /// + /// If `error` is `None` the process finished successfully, otherwise it + /// finished with an error. + pub fn done(rid: RepoId, remote: NodeId, status: ExitStatus) -> Self { + Self::Done { + rid, + remote, + status: status.to_string(), + } + } + + pub fn error(rid: RepoId, remote: NodeId, err: io::Error) -> Self { + Self::Error { + rid, + remote, + err: err.to_string(), + } + } +} + +/// Progress updates emitted from the `git-upload-pack` process. +#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] +#[serde(rename_all = "camelCase")] +pub enum Progress { + Enumerating { total: usize }, + Counting { processed: usize, total: usize }, + Compressing { processed: usize, total: usize }, +} + +impl fmt::Display for Progress { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self { + Progress::Enumerating { total } => write!(f, "Enumerating objects: {total}"), + Progress::Counting { processed, total } => { + let percent = (processed / total) * 100; + write!(f, "Counting objects: {percent}% ({processed}/{total})") + } + Progress::Compressing { processed, total } => { + let percent = (processed / total) * 100; + write!(f, "Compressing objects: {percent}% ({processed}/{total})") + } + } + } +}