debian_packaging/repository/
proxy_writer.rs1use {
8 crate::{
9 error::{DebianError, Result},
10 io::ContentDigest,
11 repository::{
12 RepositoryPathVerification, RepositoryPathVerificationState, RepositoryWrite,
13 RepositoryWriter,
14 },
15 },
16 async_trait::async_trait,
17 futures::AsyncRead,
18 std::{borrow::Cow, pin::Pin, sync::Mutex},
19};
20
21#[derive(Clone, Copy, Debug, Eq, PartialEq)]
23pub enum ProxyVerifyBehavior {
24 Proxy,
26 AlwaysExistsNoIntegrityCheck,
27 AlwaysExistsIntegrityVerified,
28 AlwaysExistsIntegrityMismatch,
29 AlwaysMissing,
30}
31
32pub struct ProxyWriter<W> {
38 inner: W,
39 verify_behavior: ProxyVerifyBehavior,
40 path_writes: Mutex<Vec<String>>,
42}
43
44impl<W: RepositoryWriter + Send> ProxyWriter<W> {
45 pub fn new(writer: W) -> Self {
49 Self {
50 inner: writer,
51 verify_behavior: ProxyVerifyBehavior::Proxy,
52 path_writes: Mutex::new(vec![]),
53 }
54 }
55
56 pub fn into_inner(self) -> W {
58 self.inner
59 }
60
61 pub fn set_verify_behavior(&mut self, behavior: ProxyVerifyBehavior) {
63 self.verify_behavior = behavior;
64 }
65}
66
67#[async_trait]
68impl<W: RepositoryWriter + Send> RepositoryWriter for ProxyWriter<W> {
69 async fn verify_path<'path>(
70 &self,
71 path: &'path str,
72 expected_content: Option<(u64, ContentDigest)>,
73 ) -> Result<RepositoryPathVerification<'path>> {
74 match self.verify_behavior {
75 ProxyVerifyBehavior::Proxy => self.inner.verify_path(path, expected_content).await,
76 ProxyVerifyBehavior::AlwaysExistsIntegrityVerified => Ok(RepositoryPathVerification {
77 path,
78 state: RepositoryPathVerificationState::ExistsIntegrityVerified,
79 }),
80 ProxyVerifyBehavior::AlwaysExistsNoIntegrityCheck => Ok(RepositoryPathVerification {
81 path,
82 state: RepositoryPathVerificationState::ExistsNoIntegrityCheck,
83 }),
84 ProxyVerifyBehavior::AlwaysExistsIntegrityMismatch => Ok(RepositoryPathVerification {
85 path,
86 state: RepositoryPathVerificationState::ExistsIntegrityMismatch,
87 }),
88 ProxyVerifyBehavior::AlwaysMissing => Ok(RepositoryPathVerification {
89 path,
90 state: RepositoryPathVerificationState::Missing,
91 }),
92 }
93 }
94
95 async fn write_path<'path, 'reader>(
96 &self,
97 path: Cow<'path, str>,
98 reader: Pin<Box<dyn AsyncRead + Send + 'reader>>,
99 ) -> Result<RepositoryWrite<'path>> {
100 let res = self.inner.write_path(path.clone(), reader).await?;
101
102 self.path_writes
103 .lock()
104 .map_err(|_| {
105 DebianError::RepositoryIoPath(
106 path.to_string(),
107 std::io::Error::new(
108 std::io::ErrorKind::Other,
109 "error acquiring write paths mutex",
110 ),
111 )
112 })?
113 .push(path.to_string());
114
115 Ok(res)
116 }
117}