fuchsia_repo/repository/
pm.rs1use crate::range::Range;
6use crate::repo_keys;
7use crate::repository::{
8 CopyMode, Error, FileSystemRepository, FileSystemRepositoryBuilder, RepoProvider, RepoStorage,
9};
10use crate::resource::Resource;
11use anyhow::Result;
12use camino::{Utf8Path, Utf8PathBuf};
13use delivery_blob::DeliveryBlobType;
14use fuchsia_merkle::Hash;
15use futures::AsyncRead;
16use futures::future::BoxFuture;
17use futures::stream::BoxStream;
18use std::collections::BTreeSet;
19use std::fmt::Debug;
20use std::time::SystemTime;
21use tuf::metadata::{MetadataPath, MetadataVersion, TargetPath};
22use tuf::pouf::Pouf1;
23use tuf::repository::{
24 RepositoryProvider as TufRepositoryProvider, RepositoryStorage as TufRepositoryStorage,
25};
26
27#[cfg(not(target_os = "fuchsia"))]
28use crate::repository::RepositorySpec;
29
30pub struct PmRepositoryBuilder {
31 pm_repo_path: Utf8PathBuf,
32 builder: FileSystemRepositoryBuilder,
33}
34
35impl PmRepositoryBuilder {
36 pub fn new(pm_repo_path: Utf8PathBuf) -> Self {
37 let metadata_repo_path = pm_repo_path.join("repository");
38 let blob_repo_path = metadata_repo_path.join("blobs");
39
40 PmRepositoryBuilder {
41 pm_repo_path,
42 builder: FileSystemRepositoryBuilder::new(metadata_repo_path, blob_repo_path),
43 }
44 }
45
46 pub fn copy_mode(mut self, copy_mode: CopyMode) -> Self {
48 self.builder = self.builder.copy_mode(copy_mode);
49 self
50 }
51
52 pub fn alias(mut self, alias: String) -> Self {
54 self.builder = self.builder.alias(alias);
55 self
56 }
57
58 pub fn aliases(mut self, aliases: impl IntoIterator<Item = String>) -> Self {
60 self.builder = self.builder.aliases(aliases);
61 self
62 }
63
64 pub fn delivery_blob_type(mut self, delivery_blob_type: DeliveryBlobType) -> Self {
66 self.builder = self.builder.delivery_blob_type(delivery_blob_type);
67 self
68 }
69
70 pub fn blob_repo_path(mut self, blob_repo_path: Utf8PathBuf) -> Self {
72 self.builder = self.builder.blob_repo_path(blob_repo_path);
73 self
74 }
75
76 pub fn build(self) -> PmRepository {
77 PmRepository { pm_repo_path: self.pm_repo_path, repo: self.builder.build() }
78 }
79}
80
81#[derive(Debug)]
83pub struct PmRepository {
84 pm_repo_path: Utf8PathBuf,
85 repo: FileSystemRepository,
86}
87
88impl PmRepository {
89 pub fn builder(pm_repo_path: Utf8PathBuf) -> PmRepositoryBuilder {
90 PmRepositoryBuilder::new(pm_repo_path)
91 }
92
93 pub fn new(pm_repo_path: Utf8PathBuf) -> Self {
95 Self::builder(pm_repo_path).build()
96 }
97
98 pub fn repo_keys(&self) -> Result<repo_keys::RepoKeys, repo_keys::ParseError> {
101 let keys_path = self.pm_repo_path.join("keys");
102 if keys_path.exists() {
103 repo_keys::RepoKeys::from_dir(keys_path.as_std_path())
104 } else {
105 Ok(repo_keys::RepoKeys::builder().build())
106 }
107 }
108}
109
110impl RepoProvider for PmRepository {
111 #[cfg(not(target_os = "fuchsia"))]
112 fn spec(&self) -> RepositorySpec {
113 RepositorySpec::Pm { path: self.pm_repo_path.clone(), aliases: self.repo.aliases().clone() }
114 }
115
116 fn aliases(&self) -> &BTreeSet<String> {
117 self.repo.aliases()
118 }
119
120 fn fetch_metadata_range<'a>(
121 &'a self,
122 resource_path: &str,
123 range: Range,
124 ) -> BoxFuture<'a, Result<Resource, Error>> {
125 self.repo.fetch_metadata_range(resource_path, range)
126 }
127
128 fn fetch_blob_range<'a>(
129 &'a self,
130 resource_path: &str,
131 range: Range,
132 ) -> BoxFuture<'a, Result<Resource, Error>> {
133 self.repo.fetch_blob_range(resource_path, range)
134 }
135
136 fn supports_watch(&self) -> bool {
137 self.repo.supports_watch()
138 }
139
140 fn watch(&self) -> Result<BoxStream<'static, ()>> {
141 self.repo.watch()
142 }
143
144 fn blob_modification_time<'a>(
145 &'a self,
146 path: &str,
147 ) -> BoxFuture<'a, Result<Option<SystemTime>>> {
148 self.repo.blob_modification_time(path)
149 }
150
151 fn blob_type(&self) -> DeliveryBlobType {
152 self.repo.blob_type()
153 }
154}
155
156impl TufRepositoryProvider<Pouf1> for PmRepository {
157 fn fetch_metadata<'a>(
158 &'a self,
159 meta_path: &MetadataPath,
160 version: MetadataVersion,
161 ) -> BoxFuture<'a, tuf::Result<Box<dyn AsyncRead + Send + Unpin + 'a>>> {
162 self.repo.fetch_metadata(meta_path, version)
163 }
164
165 fn fetch_target<'a>(
166 &'a self,
167 target_path: &TargetPath,
168 ) -> BoxFuture<'a, tuf::Result<Box<dyn AsyncRead + Send + Unpin + 'a>>> {
169 self.repo.fetch_target(target_path)
170 }
171}
172
173impl TufRepositoryStorage<Pouf1> for PmRepository {
174 fn store_metadata<'a>(
175 &'a self,
176 meta_path: &MetadataPath,
177 version: MetadataVersion,
178 metadata: &'a mut (dyn AsyncRead + Send + Unpin + 'a),
179 ) -> BoxFuture<'a, tuf::Result<()>> {
180 self.repo.store_metadata(meta_path, version, metadata)
181 }
182
183 fn store_target<'a>(
184 &'a self,
185 target_path: &TargetPath,
186 target: &'a mut (dyn AsyncRead + Send + Unpin + 'a),
187 ) -> BoxFuture<'a, tuf::Result<()>> {
188 self.repo.store_target(target_path, target)
189 }
190}
191
192impl RepoStorage for PmRepository {
193 fn store_blob<'a>(
194 &'a self,
195 hash: &Hash,
196 len: u64,
197 path: &Utf8Path,
198 ) -> BoxFuture<'a, Result<()>> {
199 self.repo.store_blob(hash, len, path)
200 }
201 fn store_delivery_blob<'a>(
202 &'a self,
203 hash: &Hash,
204 path: &Utf8Path,
205 delivery_blob_type: DeliveryBlobType,
206 ) -> BoxFuture<'a, Result<()>> {
207 self.repo.store_delivery_blob(hash, path, delivery_blob_type)
208 }
209}