Skip to main content

radicle/node/events/
upload_pack.rs

1use std::fmt;
2use std::io;
3use std::process::ExitStatus;
4
5use crate::node::NodeId;
6use crate::prelude::RepoId;
7
8/// Events that can occur when an upload-pack process is running.
9#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
10pub enum UploadPack {
11    /// The upload-pack process finished with `status`.
12    Done {
13        /// The repository being fetched.
14        rid: RepoId,
15        /// The node being fetched from.
16        remote: NodeId,
17        /// The status code of the upload-pack process.
18        ///
19        /// N.b. `ExitStatus` cannot be de/serialized, so the `Display` of the
20        /// status is used instead.
21        status: String,
22    },
23    /// The upload-pack process emitted some [`Progress`] data.
24    Write {
25        /// The repository being fetched.
26        rid: RepoId,
27        /// The node being fetched from.
28        remote: NodeId,
29        /// The progress metadata of the upload-pack.
30        progress: Progress,
31    },
32    /// An error occurred during the upload-pack process.
33    Error {
34        /// The repository being fetched.
35        rid: RepoId,
36        /// The node being fetched from.
37        remote: NodeId,
38        /// The error that occurred during the upload-pack.
39        err: String,
40    },
41    /// The upload-pack packfile transmission progress.
42    PackProgress {
43        /// The repository being fetched.
44        rid: RepoId,
45        /// The node being fetched from.
46        remote: NodeId,
47        /// The total number of bytes transmitted.
48        transmitted: usize,
49    },
50}
51
52impl UploadPack {
53    /// Construct a `UploadPack::PackProgress` event.
54    pub fn pack_progress(rid: RepoId, remote: NodeId, transmitted: usize) -> Self {
55        Self::PackProgress {
56            rid,
57            remote,
58            transmitted,
59        }
60    }
61
62    /// Construct a `UploadPack::Write` event.
63    pub fn write(rid: RepoId, remote: NodeId, progress: Progress) -> Self {
64        Self::Write {
65            rid,
66            remote,
67            progress,
68        }
69    }
70
71    /// Construct a `UploadPack::Done` event.
72    ///
73    /// If `error` is `None` the process finished successfully; otherwise, it
74    /// finished with an error.
75    pub fn done(rid: RepoId, remote: NodeId, status: ExitStatus) -> Self {
76        Self::Done {
77            rid,
78            remote,
79            status: status.to_string(),
80        }
81    }
82
83    pub fn error(rid: RepoId, remote: NodeId, err: io::Error) -> Self {
84        Self::Error {
85            rid,
86            remote,
87            err: err.to_string(),
88        }
89    }
90}
91
92/// Progress updates emitted from the `git-upload-pack` process.
93#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)]
94#[serde(rename_all = "camelCase")]
95pub enum Progress {
96    Enumerating { total: usize },
97    Counting { processed: usize, total: usize },
98    Compressing { processed: usize, total: usize },
99}
100
101impl fmt::Display for Progress {
102    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
103        match self {
104            Progress::Enumerating { total } => write!(f, "Enumerating objects: {total}"),
105            Progress::Counting { processed, total } => {
106                let percent = (processed / total) * 100;
107                write!(f, "Counting objects: {percent}% ({processed}/{total})")
108            }
109            Progress::Compressing { processed, total } => {
110                let percent = (processed / total) * 100;
111                write!(f, "Compressing objects: {percent}% ({processed}/{total})")
112            }
113        }
114    }
115}