* [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings
@ 2021-01-25 13:42 Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 01/15] report: type-alias function call tuple Fabian Grünbichler
` (17 more replies)
0 siblings, 18 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
various parameter/types refactorings to simplify function
signatures/return types/...
I am grateful for suggestions on better names ;)
I tried to order/group the patches so that they also apply
individually/as sub-groups.
with all of these, we are now down to some very recently touched files
with trivial fixes that I didn't want to change since I suspected them
to be still under development, and one missing docs lint:
warning: unsafe function's docs miss `# Safety` section
--> src/tools/fs.rs:78:5
|
78 | / pub unsafe fn file_name_utf8_unchecked(&self) -> &str {
79 | | std::str::from_utf8_unchecked(self.file_name().to_bytes())
80 | | }
| |_____^
proxmox-backup:
report: type-alias function call tuple
broadcast_future: refactor broadcast/future binding
client: refactor catalog upload spawning
allow complex Futures in tower_service impl
async index reader: typedef ReadFuture
systemd/time: extract Time/DateSpec structs
client: factor out UploadOptions
pxar: typedef on_error as ErrorHandler
pxar: factor out PxarCreateOptions
pxar: extract PxarExtractOptions
authid: make Tokenname(Ref) derive Eq
derive/impl and use Default for some structs
verify: factor out common parameters
clippy: allow api functions with many arguments
clippy: more misc fixes
examples/download-speed.rs | 2 +-
examples/upload-speed.rs | 2 +-
src/api2/access/acl.rs | 1 +
src/api2/access/tfa.rs | 1 +
src/api2/access/user.rs | 1 +
src/api2/admin/datastore.rs | 19 +--
src/api2/backup/environment.rs | 10 +-
src/api2/config/datastore.rs | 1 +
src/api2/config/remote.rs | 5 +-
src/api2/config/sync.rs | 1 +
src/api2/config/verify.rs | 1 +
src/api2/node/network.rs | 2 +
src/api2/node/tasks.rs | 1 +
src/api2/types/userid.rs | 52 +-------
src/backup/async_index_reader.rs | 4 +-
src/backup/prune.rs | 1 +
src/backup/verify.rs | 174 +++++++++++--------------
src/bin/proxmox-backup-client.rs | 162 +++++++++++++----------
src/bin/proxmox-daily-update.rs | 9 +-
src/bin/proxmox_backup_client/key.rs | 24 +---
src/bin/proxmox_backup_client/mount.rs | 2 +-
src/bin/proxmox_backup_manager/user.rs | 4 +-
src/bin/pxar.rs | 54 ++++----
src/client.rs | 11 +-
src/client/backup_writer.rs | 46 ++++---
src/client/http_client.rs | 38 ++++--
src/client/pull.rs | 4 +-
src/client/pxar_backup_stream.rs | 28 +---
src/config/acl.rs | 8 +-
src/config/network.rs | 2 +-
src/pxar/create.rs | 28 +++-
src/pxar/extract.rs | 24 ++--
src/pxar/mod.rs | 4 +-
src/rrd/mod.rs | 1 +
src/server/h2service.rs | 5 +-
src/server/report.rs | 6 +-
src/server/rest.rs | 3 +-
src/server/verify_job.rs | 3 +-
src/tools/broadcast_future.rs | 38 ++----
src/tools/http.rs | 5 +-
src/tools/systemd/parse_time.rs | 41 ++++--
tests/catar.rs | 10 +-
42 files changed, 414 insertions(+), 424 deletions(-)
proxmox-backup-qemu:
use UploadOptions for uploading Blobs
use new HttpClientOptions constructors
src/backup.rs | 7 ++++---
src/commands.rs | 15 +++++++++++++--
src/lib.rs | 8 +++++---
src/restore.rs | 7 ++++---
4 files changed, 26 insertions(+), 11 deletions(-)
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 01/15] report: type-alias function call tuple
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 02/15] broadcast_future: refactor broadcast/future binding Fabian Grünbichler
` (16 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
to make clippy happy.
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
could also be just #[allow(..)]ed
src/server/report.rs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/src/server/report.rs b/src/server/report.rs
index 1b77f442..e89abbc5 100644
--- a/src/server/report.rs
+++ b/src/server/report.rs
@@ -29,8 +29,10 @@ fn commands() -> Vec<(&'static str, Vec<&'static str>)> {
]
}
- // (<description>, <function to call>)
-fn function_calls() -> Vec<(&'static str, fn() -> String)> {
+// (description, function())
+type FunctionMapping = (&'static str, fn() -> String);
+
+fn function_calls() -> Vec<FunctionMapping> {
vec![
("Datastores", || {
let config = match datastore::config() {
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 02/15] broadcast_future: refactor broadcast/future binding
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 01/15] report: type-alias function call tuple Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 03/15] client: refactor catalog upload spawning Fabian Grünbichler
` (15 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
into its own, private struct.
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
src/tools/broadcast_future.rs | 42 +++++++++++++++--------------------
1 file changed, 18 insertions(+), 24 deletions(-)
diff --git a/src/tools/broadcast_future.rs b/src/tools/broadcast_future.rs
index 94aedf18..88b7aaab 100644
--- a/src/tools/broadcast_future.rs
+++ b/src/tools/broadcast_future.rs
@@ -62,14 +62,16 @@ impl <T: Clone> BroadcastData<T> {
}
}
+type SourceFuture<T> = Pin<Box<dyn Future<Output = Result<T, Error>> + Send>>;
+
+struct BroadCastFutureBinding<T> {
+ broadcast: BroadcastData<T>,
+ future: Option<SourceFuture<T>>,
+}
+
/// Broadcast future results to registered listeners
pub struct BroadcastFuture<T> {
- inner: Arc<
- Mutex<(
- BroadcastData<T>,
- Option<Pin<Box<dyn Future<Output = Result<T, Error>> + Send>>>,
- )>,
- >,
+ inner: Arc<Mutex<BroadCastFutureBinding<T>>>,
}
impl<T: Clone + Send + 'static> BroadcastFuture<T> {
@@ -77,7 +79,11 @@ impl<T: Clone + Send + 'static> BroadcastFuture<T> {
///
/// The result of the future is sent to all registered listeners.
pub fn new(source: Box<dyn Future<Output = Result<T, Error>> + Send>) -> Self {
- Self { inner: Arc::new(Mutex::new((BroadcastData::new(), Some(Pin::from(source))))) }
+ let inner = BroadCastFutureBinding {
+ broadcast: BroadcastData::new(),
+ future: Some(Pin::from(source)),
+ };
+ Self { inner: Arc::new(Mutex::new(inner)) }
}
/// Creates a new instance with a oneshot channel as trigger
@@ -92,29 +98,17 @@ impl<T: Clone + Send + 'static> BroadcastFuture<T> {
}
fn notify_listeners(
- inner: Arc<
- Mutex<(
- BroadcastData<T>,
- Option<Pin<Box<dyn Future<Output = Result<T, Error>> + Send>>>,
- )>,
- >,
+ inner: Arc<Mutex<BroadCastFutureBinding<T>>>,
result: Result<T, String>,
) {
let mut data = inner.lock().unwrap();
- data.0.notify_listeners(result);
+ data.broadcast.notify_listeners(result);
}
- fn spawn(
- inner: Arc<
- Mutex<(
- BroadcastData<T>,
- Option<Pin<Box<dyn Future<Output = Result<T, Error>> + Send>>>,
- )>,
- >,
- ) -> impl Future<Output = Result<T, Error>> {
+ fn spawn(inner: Arc<Mutex<BroadCastFutureBinding<T>>>) -> impl Future<Output = Result<T, Error>> {
let mut data = inner.lock().unwrap();
- if let Some(source) = data.1.take() {
+ if let Some(source) = data.future.take() {
let inner1 = inner.clone();
@@ -127,7 +121,7 @@ impl<T: Clone + Send + 'static> BroadcastFuture<T> {
tokio::spawn(task);
}
- data.0.listen()
+ data.broadcast.listen()
}
/// Register a listener
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 03/15] client: refactor catalog upload spawning
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 01/15] report: type-alias function call tuple Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 02/15] broadcast_future: refactor broadcast/future binding Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 04/15] allow complex Futures in tower_service impl Fabian Grünbichler
` (14 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
by pulling out Result type into separate struct
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
especially unhappy with the name here..
src/bin/proxmox-backup-client.rs | 26 +++++++++++++-------------
1 file changed, 13 insertions(+), 13 deletions(-)
diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs
index 041a670c..dce8f0b8 100644
--- a/src/bin/proxmox-backup-client.rs
+++ b/src/bin/proxmox-backup-client.rs
@@ -586,21 +586,21 @@ async fn start_garbage_collection(param: Value) -> Result<Value, Error> {
Ok(Value::Null)
}
+struct CatalogUploadResult {
+ catalog_writer: Arc<Mutex<CatalogWriter<crate::tools::StdChannelWriter>>>,
+ result: tokio::sync::oneshot::Receiver<Result<BackupStats, Error>>,
+}
+
fn spawn_catalog_upload(
client: Arc<BackupWriter>,
encrypt: bool,
-) -> Result<
- (
- Arc<Mutex<CatalogWriter<crate::tools::StdChannelWriter>>>,
- tokio::sync::oneshot::Receiver<Result<BackupStats, Error>>
- ), Error>
-{
+) -> Result<CatalogUploadResult, Error> {
let (catalog_tx, catalog_rx) = std::sync::mpsc::sync_channel(10); // allow to buffer 10 writes
let catalog_stream = crate::tools::StdChannelStream(catalog_rx);
let catalog_chunk_size = 512*1024;
let catalog_chunk_stream = ChunkStream::new(catalog_stream, Some(catalog_chunk_size));
- let catalog = Arc::new(Mutex::new(CatalogWriter::new(crate::tools::StdChannelWriter::new(catalog_tx))?));
+ let catalog_writer = Arc::new(Mutex::new(CatalogWriter::new(crate::tools::StdChannelWriter::new(catalog_tx))?));
let (catalog_result_tx, catalog_result_rx) = tokio::sync::oneshot::channel();
@@ -617,7 +617,7 @@ fn spawn_catalog_upload(
let _ = catalog_result_tx.send(catalog_upload_result);
});
- Ok((catalog, catalog_result_rx))
+ Ok(CatalogUploadResult { catalog_writer, result: catalog_result_rx })
}
fn keyfile_parameters(param: &Value) -> Result<(Option<Vec<u8>>, CryptMode), Error> {
@@ -990,7 +990,7 @@ async fn create_backup(
let mut manifest = BackupManifest::new(snapshot);
let mut catalog = None;
- let mut catalog_result_tx = None;
+ let mut catalog_result_rx = None;
for (backup_type, filename, target, size) in upload_list {
match backup_type {
@@ -1011,9 +1011,9 @@ async fn create_backup(
BackupSpecificationType::PXAR => {
// start catalog upload on first use
if catalog.is_none() {
- let (cat, res) = spawn_catalog_upload(client.clone(), crypt_mode == CryptMode::Encrypt)?;
- catalog = Some(cat);
- catalog_result_tx = Some(res);
+ let catalog_upload_res = spawn_catalog_upload(client.clone(), crypt_mode == CryptMode::Encrypt)?;
+ catalog = Some(catalog_upload_res.catalog_writer);
+ catalog_result_rx = Some(catalog_upload_res.result);
}
let catalog = catalog.as_ref().unwrap();
@@ -1065,7 +1065,7 @@ async fn create_backup(
drop(catalog); // close upload stream
- if let Some(catalog_result_rx) = catalog_result_tx {
+ if let Some(catalog_result_rx) = catalog_result_rx {
let stats = catalog_result_rx.await??;
manifest.add_file(CATALOG_NAME.to_owned(), stats.size, stats.csum, crypt_mode)?;
}
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 04/15] allow complex Futures in tower_service impl
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (2 preceding siblings ...)
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 03/15] client: refactor catalog upload spawning Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 05/15] async index reader: typedef ReadFuture Fabian Grünbichler
` (13 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
src/server/h2service.rs | 5 +++--
src/server/rest.rs | 3 ++-
src/tools/http.rs | 5 ++---
3 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/src/server/h2service.rs b/src/server/h2service.rs
index 989618ec..332b3b1a 100644
--- a/src/server/h2service.rs
+++ b/src/server/h2service.rs
@@ -1,6 +1,7 @@
use anyhow::{Error};
use std::collections::HashMap;
+use std::pin::Pin;
use std::sync::Arc;
use std::task::{Context, Poll};
@@ -85,8 +86,8 @@ impl <E: RpcEnvironment + Clone> H2Service<E> {
impl <E: RpcEnvironment + Clone> tower_service::Service<Request<Body>> for H2Service<E> {
type Response = Response<Body>;
type Error = Error;
- type Future =
- std::pin::Pin<Box<dyn Future<Output = Result<Response<Body>, Self::Error>> + Send>>;
+ #[allow(clippy::type_complexity)]
+ type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, _cx: &mut Context) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
diff --git a/src/server/rest.rs b/src/server/rest.rs
index 0586979a..fc59be9a 100644
--- a/src/server/rest.rs
+++ b/src/server/rest.rs
@@ -198,7 +198,8 @@ fn get_user_agent(headers: &HeaderMap) -> Option<String> {
impl tower_service::Service<Request<Body>> for ApiService {
type Response = Response<Body>;
type Error = Error;
- type Future = Pin<Box<dyn Future<Output = Result<Response<Body>, Self::Error>> + Send>>;
+ #[allow(clippy::type_complexity)]
+ type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send>>;
fn poll_ready(&mut self, _cx: &mut Context) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
diff --git a/src/tools/http.rs b/src/tools/http.rs
index 47d6e1f6..0fbc85fb 100644
--- a/src/tools/http.rs
+++ b/src/tools/http.rs
@@ -108,9 +108,8 @@ type MaybeTlsStream = EitherStream<
impl hyper::service::Service<Uri> for HttpsConnector {
type Response = MaybeTlsStream;
type Error = Error;
- type Future = std::pin::Pin<Box<
- dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static
- >>;
+ #[allow(clippy::type_complexity)]
+ type Future = Pin<Box<dyn Future<Output = Result<Self::Response, Self::Error>> + Send + 'static>>;
fn poll_ready(&mut self, _: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
// This connector is always ready, but others might not be.
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 05/15] async index reader: typedef ReadFuture
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (3 preceding siblings ...)
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 04/15] allow complex Futures in tower_service impl Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 06/15] systemd/time: extract Time/DateSpec structs Fabian Grünbichler
` (12 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
there is also still a FIXME here..
src/backup/async_index_reader.rs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/src/backup/async_index_reader.rs b/src/backup/async_index_reader.rs
index 60c68d4f..20a37e7e 100644
--- a/src/backup/async_index_reader.rs
+++ b/src/backup/async_index_reader.rs
@@ -15,6 +15,8 @@ use super::IndexFile;
use super::read_chunk::AsyncReadChunk;
use super::index::ChunkReadInfo;
+type ReadFuture<S> = dyn Future<Output = Result<(S, Vec<u8>), Error>> + Send + 'static;
+
// FIXME: This enum may not be required?
// - Put the `WaitForData` case directly into a `read_future: Option<>`
// - make the read loop as follows:
@@ -28,7 +30,7 @@ use super::index::ChunkReadInfo;
#[allow(clippy::enum_variant_names)]
enum AsyncIndexReaderState<S> {
NoData,
- WaitForData(Pin<Box<dyn Future<Output = Result<(S, Vec<u8>), Error>> + Send + 'static>>),
+ WaitForData(Pin<Box<ReadFuture<S>>>),
HaveData,
}
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 06/15] systemd/time: extract Time/DateSpec structs
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (4 preceding siblings ...)
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 05/15] async index reader: typedef ReadFuture Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 07/15] client: factor out UploadOptions Fabian Grünbichler
` (11 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
could be pulled up into CalendarEvent if desired..
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
src/tools/systemd/parse_time.rs | 41 ++++++++++++++++++++++-----------
1 file changed, 27 insertions(+), 14 deletions(-)
diff --git a/src/tools/systemd/parse_time.rs b/src/tools/systemd/parse_time.rs
index 88f5c92d..c0f58b04 100644
--- a/src/tools/systemd/parse_time.rs
+++ b/src/tools/systemd/parse_time.rs
@@ -86,6 +86,19 @@ lazy_static! {
map
};
}
+
+struct TimeSpec {
+ hour: Vec<DateTimeValue>,
+ minute: Vec<DateTimeValue>,
+ second: Vec<DateTimeValue>,
+}
+
+struct DateSpec {
+ year: Vec<DateTimeValue>,
+ month: Vec<DateTimeValue>,
+ day: Vec<DateTimeValue>,
+}
+
fn parse_time_comp(max: usize) -> impl Fn(&str) -> IResult<&str, u32> {
move |i: &str| {
let (i, v) = map_res(recognize(digit1), str::parse)(i)?;
@@ -176,7 +189,7 @@ fn parse_date_time_comp_list(start: u32, max: usize) -> impl Fn(&str) -> IResult
}
}
-fn parse_time_spec(i: &str) -> IResult<&str, (Vec<DateTimeValue>, Vec<DateTimeValue>, Vec<DateTimeValue>)> {
+fn parse_time_spec(i: &str) -> IResult<&str, TimeSpec> {
let (i, (hour, minute, opt_second)) = tuple((
parse_date_time_comp_list(0, 24),
@@ -185,13 +198,13 @@ fn parse_time_spec(i: &str) -> IResult<&str, (Vec<DateTimeValue>, Vec<DateTimeVa
))(i)?;
if let Some(second) = opt_second {
- Ok((i, (hour, minute, second)))
+ Ok((i, TimeSpec { hour, minute, second }))
} else {
- Ok((i, (hour, minute, vec![DateTimeValue::Single(0)])))
+ Ok((i, TimeSpec { hour, minute, second: vec![DateTimeValue::Single(0)] }))
}
}
-fn parse_date_spec(i: &str) -> IResult<&str, (Vec<DateTimeValue>, Vec<DateTimeValue>, Vec<DateTimeValue>)> {
+fn parse_date_spec(i: &str) -> IResult<&str, DateSpec> {
// TODO: implement ~ for days (man systemd.time)
if let Ok((i, (year, month, day))) = tuple((
@@ -199,12 +212,12 @@ fn parse_date_spec(i: &str) -> IResult<&str, (Vec<DateTimeValue>, Vec<DateTimeVa
preceded(tag("-"), parse_date_time_comp_list(1, 13)),
preceded(tag("-"), parse_date_time_comp_list(1, 32)),
))(i) {
- Ok((i, (year, month, day)))
+ Ok((i, DateSpec { year, month, day }))
} else if let Ok((i, (month, day))) = tuple((
parse_date_time_comp_list(1, 13),
preceded(tag("-"), parse_date_time_comp_list(1, 32)),
))(i) {
- Ok((i, (Vec::new(), month, day)))
+ Ok((i, DateSpec { year: Vec::new(), month, day }))
} else {
Err(parse_error(i, "invalid date spec"))
}
@@ -317,18 +330,18 @@ fn parse_calendar_event_incomplete(mut i: &str) -> IResult<&str, CalendarEvent>
for range in range_list { event.days.insert(range); }
}
- if let (n, Some((year, month, day))) = opt(parse_date_spec)(i)? {
- event.year = year;
- event.month = month;
- event.day = day;
+ if let (n, Some(date)) = opt(parse_date_spec)(i)? {
+ event.year = date.year;
+ event.month = date.month;
+ event.day = date.day;
has_datespec = true;
i = space0(n)?.0;
}
- if let (n, Some((hour, minute, second))) = opt(parse_time_spec)(i)? {
- event.hour = hour;
- event.minute = minute;
- event.second = second;
+ if let (n, Some(time)) = opt(parse_time_spec)(i)? {
+ event.hour = time.hour;
+ event.minute = time.minute;
+ event.second = time.second;
has_timespec = true;
i = n;
} else {
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 07/15] client: factor out UploadOptions
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (5 preceding siblings ...)
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 06/15] systemd/time: extract Time/DateSpec structs Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 08/15] pxar: typedef on_error as ErrorHandler Fabian Grünbichler
` (10 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
to reduce function signature complexity.
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
breaks/requires corresponding patch in proxmox-backup-qemu
src/bin/proxmox-backup-client.rs | 79 ++++++++++++++++++++++----------
src/client/backup_writer.rs | 44 ++++++++++--------
2 files changed, 80 insertions(+), 43 deletions(-)
diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs
index dce8f0b8..af3b8464 100644
--- a/src/bin/proxmox-backup-client.rs
+++ b/src/bin/proxmox-backup-client.rs
@@ -280,7 +280,6 @@ pub async fn api_datastore_latest_snapshot(
async fn backup_directory<P: AsRef<Path>>(
client: &BackupWriter,
- previous_manifest: Option<Arc<BackupManifest>>,
dir_path: P,
archive_name: &str,
chunk_size: Option<usize>,
@@ -290,8 +289,7 @@ async fn backup_directory<P: AsRef<Path>>(
catalog: Arc<Mutex<CatalogWriter<crate::tools::StdChannelWriter>>>,
exclude_pattern: Vec<MatchEntry>,
entries_max: usize,
- compress: bool,
- encrypt: bool,
+ upload_options: UploadOptions,
) -> Result<BackupStats, Error> {
let pxar_stream = PxarBackupStream::open(
@@ -317,8 +315,12 @@ async fn backup_directory<P: AsRef<Path>>(
}
});
+ if upload_options.fixed_size.is_some() {
+ bail!("cannot backup directory with fixed chunk size!");
+ }
+
let stats = client
- .upload_stream(previous_manifest, archive_name, stream, "dynamic", None, compress, encrypt)
+ .upload_stream(archive_name, stream, upload_options)
.await?;
Ok(stats)
@@ -326,14 +328,10 @@ async fn backup_directory<P: AsRef<Path>>(
async fn backup_image<P: AsRef<Path>>(
client: &BackupWriter,
- previous_manifest: Option<Arc<BackupManifest>>,
image_path: P,
archive_name: &str,
- image_size: u64,
chunk_size: Option<usize>,
- compress: bool,
- encrypt: bool,
- _verbose: bool,
+ upload_options: UploadOptions,
) -> Result<BackupStats, Error> {
let path = image_path.as_ref().to_owned();
@@ -345,8 +343,12 @@ async fn backup_image<P: AsRef<Path>>(
let stream = FixedChunkStream::new(stream, chunk_size.unwrap_or(4*1024*1024));
+ if upload_options.fixed_size.is_none() {
+ bail!("cannot backup image with dynamic chunk size!");
+ }
+
let stats = client
- .upload_stream(previous_manifest, archive_name, stream, "fixed", Some(image_size), compress, encrypt)
+ .upload_stream(archive_name, stream, upload_options)
.await?;
Ok(stats)
@@ -604,9 +606,15 @@ fn spawn_catalog_upload(
let (catalog_result_tx, catalog_result_rx) = tokio::sync::oneshot::channel();
+ let upload_options = UploadOptions {
+ encrypt,
+ compress: true,
+ ..UploadOptions::default()
+ };
+
tokio::spawn(async move {
let catalog_upload_result = client
- .upload_stream(None, CATALOG_NAME, catalog_chunk_stream, "dynamic", None, true, encrypt)
+ .upload_stream(CATALOG_NAME, catalog_chunk_stream, upload_options)
.await;
if let Err(ref err) = catalog_upload_result {
@@ -995,16 +1003,28 @@ async fn create_backup(
for (backup_type, filename, target, size) in upload_list {
match backup_type {
BackupSpecificationType::CONFIG => {
+ let upload_options = UploadOptions {
+ compress: true,
+ encrypt: crypt_mode == CryptMode::Encrypt,
+ ..UploadOptions::default()
+ };
+
println!("Upload config file '{}' to '{}' as {}", filename, repo, target);
let stats = client
- .upload_blob_from_file(&filename, &target, true, crypt_mode == CryptMode::Encrypt)
+ .upload_blob_from_file(&filename, &target, upload_options)
.await?;
manifest.add_file(target, stats.size, stats.csum, crypt_mode)?;
}
BackupSpecificationType::LOGFILE => { // fixme: remove - not needed anymore ?
+ let upload_options = UploadOptions {
+ compress: true,
+ encrypt: crypt_mode == CryptMode::Encrypt,
+ ..UploadOptions::default()
+ };
+
println!("Upload log file '{}' to '{}' as {}", filename, repo, target);
let stats = client
- .upload_blob_from_file(&filename, &target, true, crypt_mode == CryptMode::Encrypt)
+ .upload_blob_from_file(&filename, &target, upload_options)
.await?;
manifest.add_file(target, stats.size, stats.csum, crypt_mode)?;
}
@@ -1019,9 +1039,15 @@ async fn create_backup(
println!("Upload directory '{}' to '{}' as {}", filename, repo, target);
catalog.lock().unwrap().start_directory(std::ffi::CString::new(target.as_str())?.as_c_str())?;
+ let upload_options = UploadOptions {
+ previous_manifest: previous_manifest.clone(),
+ compress: true,
+ encrypt: crypt_mode == CryptMode::Encrypt,
+ ..UploadOptions::default()
+ };
+
let stats = backup_directory(
&client,
- previous_manifest.clone(),
&filename,
&target,
chunk_size_opt,
@@ -1031,24 +1057,27 @@ async fn create_backup(
catalog.clone(),
pattern_list.clone(),
entries_max as usize,
- true,
- crypt_mode == CryptMode::Encrypt,
+ upload_options,
).await?;
manifest.add_file(target, stats.size, stats.csum, crypt_mode)?;
catalog.lock().unwrap().end_directory()?;
}
BackupSpecificationType::IMAGE => {
println!("Upload image '{}' to '{:?}' as {}", filename, repo, target);
+
+ let upload_options = UploadOptions {
+ previous_manifest: previous_manifest.clone(),
+ fixed_size: Some(size),
+ compress: true,
+ encrypt: crypt_mode == CryptMode::Encrypt,
+ };
+
let stats = backup_image(
&client,
- previous_manifest.clone(),
- &filename,
+ &filename,
&target,
- size,
chunk_size_opt,
- true,
- crypt_mode == CryptMode::Encrypt,
- verbose,
+ upload_options,
).await?;
manifest.add_file(target, stats.size, stats.csum, crypt_mode)?;
}
@@ -1074,8 +1103,9 @@ async fn create_backup(
if let Some(rsa_encrypted_key) = rsa_encrypted_key {
let target = ENCRYPTED_KEY_BLOB_NAME;
println!("Upload RSA encoded key to '{:?}' as {}", repo, target);
+ let options = UploadOptions { compress: false, encrypt: false, ..UploadOptions::default() };
let stats = client
- .upload_blob_from_data(rsa_encrypted_key, target, false, false)
+ .upload_blob_from_data(rsa_encrypted_key, target, options)
.await?;
manifest.add_file(target.to_string(), stats.size, stats.csum, crypt_mode)?;
@@ -1087,8 +1117,9 @@ async fn create_backup(
if verbose { println!("Upload index.json to '{}'", repo) };
+ let options = UploadOptions { compress: true, encrypt: false, ..UploadOptions::default() };
client
- .upload_blob_from_data(manifest.into_bytes(), MANIFEST_BLOB_NAME, true, false)
+ .upload_blob_from_data(manifest.into_bytes(), MANIFEST_BLOB_NAME, options)
.await?;
client.finish().await?;
diff --git a/src/client/backup_writer.rs b/src/client/backup_writer.rs
index e7a6d6bd..38953a45 100644
--- a/src/client/backup_writer.rs
+++ b/src/client/backup_writer.rs
@@ -39,6 +39,15 @@ pub struct BackupStats {
pub csum: [u8; 32],
}
+/// Options for uploading blobs/streams to the server
+#[derive(Default, Clone)]
+pub struct UploadOptions {
+ pub previous_manifest: Option<Arc<BackupManifest>>,
+ pub compress: bool,
+ pub encrypt: bool,
+ pub fixed_size: Option<u64>,
+}
+
type UploadQueueSender = mpsc::Sender<(MergedChunkInfo, Option<h2::client::ResponseFuture>)>;
type UploadResultReceiver = oneshot::Receiver<Result<(), Error>>;
@@ -168,13 +177,12 @@ impl BackupWriter {
&self,
data: Vec<u8>,
file_name: &str,
- compress: bool,
- encrypt: bool,
+ options: UploadOptions,
) -> Result<BackupStats, Error> {
- let blob = match (encrypt, &self.crypt_config) {
- (false, _) => DataBlob::encode(&data, None, compress)?,
+ let blob = match (options.encrypt, &self.crypt_config) {
+ (false, _) => DataBlob::encode(&data, None, options.compress)?,
(true, None) => bail!("requested encryption without a crypt config"),
- (true, Some(crypt_config)) => DataBlob::encode(&data, Some(crypt_config), compress)?,
+ (true, Some(crypt_config)) => DataBlob::encode(&data, Some(crypt_config), options.compress)?,
};
let raw_data = blob.into_inner();
@@ -190,8 +198,7 @@ impl BackupWriter {
&self,
src_path: P,
file_name: &str,
- compress: bool,
- encrypt: bool,
+ options: UploadOptions,
) -> Result<BackupStats, Error> {
let src_path = src_path.as_ref();
@@ -206,34 +213,33 @@ impl BackupWriter {
.await
.map_err(|err| format_err!("unable to read file {:?} - {}", src_path, err))?;
- self.upload_blob_from_data(contents, file_name, compress, encrypt).await
+ self.upload_blob_from_data(contents, file_name, options).await
}
pub async fn upload_stream(
&self,
- previous_manifest: Option<Arc<BackupManifest>>,
archive_name: &str,
stream: impl Stream<Item = Result<bytes::BytesMut, Error>>,
- prefix: &str,
- fixed_size: Option<u64>,
- compress: bool,
- encrypt: bool,
+ options: UploadOptions,
) -> Result<BackupStats, Error> {
let known_chunks = Arc::new(Mutex::new(HashSet::new()));
let mut param = json!({ "archive-name": archive_name });
- if let Some(size) = fixed_size {
+ let prefix = if let Some(size) = options.fixed_size {
param["size"] = size.into();
- }
+ "fixed"
+ } else {
+ "dynamic"
+ };
- if encrypt && self.crypt_config.is_none() {
+ if options.encrypt && self.crypt_config.is_none() {
bail!("requested encryption without a crypt config");
}
let index_path = format!("{}_index", prefix);
let close_path = format!("{}_close", prefix);
- if let Some(manifest) = previous_manifest {
+ if let Some(manifest) = options.previous_manifest {
// try, but ignore errors
match archive_type(archive_name) {
Ok(ArchiveType::FixedIndex) => {
@@ -255,8 +261,8 @@ impl BackupWriter {
stream,
&prefix,
known_chunks.clone(),
- if encrypt { self.crypt_config.clone() } else { None },
- compress,
+ if options.encrypt { self.crypt_config.clone() } else { None },
+ options.compress,
self.verbose,
)
.await?;
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 08/15] pxar: typedef on_error as ErrorHandler
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (6 preceding siblings ...)
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 07/15] client: factor out UploadOptions Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 09/15] pxar: factor out PxarCreateOptions Fabian Grünbichler
` (9 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
src/bin/pxar.rs | 4 ++--
| 6 ++++--
src/pxar/mod.rs | 2 +-
3 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/src/bin/pxar.rs b/src/bin/pxar.rs
index 4d2308bf..3d92dbe0 100644
--- a/src/bin/pxar.rs
+++ b/src/bin/pxar.rs
@@ -17,7 +17,7 @@ use proxmox::api::cli::*;
use proxmox::api::api;
use proxmox_backup::tools;
-use proxmox_backup::pxar::{fuse, format_single_line_entry, ENCODER_MAX_ENTRIES, Flags};
+use proxmox_backup::pxar::{fuse, format_single_line_entry, ENCODER_MAX_ENTRIES, ErrorHandler, Flags};
fn extract_archive_from_reader<R: std::io::Read>(
reader: &mut R,
@@ -27,7 +27,7 @@ fn extract_archive_from_reader<R: std::io::Read>(
verbose: bool,
match_list: &[MatchEntry],
extract_match_default: bool,
- on_error: Option<Box<dyn FnMut(Error) -> Result<(), Error> + Send>>,
+ on_error: Option<ErrorHandler>,
) -> Result<(), Error> {
proxmox_backup::pxar::extract_archive(
pxar::decoder::Decoder::from_std(reader)?,
--git a/src/pxar/extract.rs b/src/pxar/extract.rs
index 12f9054d..e22fc847 100644
--- a/src/pxar/extract.rs
+++ b/src/pxar/extract.rs
@@ -24,6 +24,8 @@ use crate::pxar::dir_stack::PxarDirStack;
use crate::pxar::metadata;
use crate::pxar::Flags;
+pub type ErrorHandler = Box<dyn FnMut(Error) -> Result<(), Error> + Send>;
+
pub fn extract_archive<T, F>(
mut decoder: pxar::decoder::Decoder<T>,
destination: &Path,
@@ -32,7 +34,7 @@ pub fn extract_archive<T, F>(
feature_flags: Flags,
allow_existing_dirs: bool,
mut callback: F,
- on_error: Option<Box<dyn FnMut(Error) -> Result<(), Error> + Send>>,
+ on_error: Option<ErrorHandler>,
) -> Result<(), Error>
where
T: pxar::decoder::SeqRead,
@@ -212,7 +214,7 @@ pub(crate) struct Extractor {
/// Error callback. Includes `current_path` in the reformatted error, should return `Ok` to
/// continue extracting or the passed error as `Err` to bail out.
- on_error: Box<dyn FnMut(Error) -> Result<(), Error> + Send>,
+ on_error: ErrorHandler,
}
impl Extractor {
diff --git a/src/pxar/mod.rs b/src/pxar/mod.rs
index 6e910667..82998cf8 100644
--- a/src/pxar/mod.rs
+++ b/src/pxar/mod.rs
@@ -59,7 +59,7 @@ mod flags;
pub use flags::Flags;
pub use create::create_archive;
-pub use extract::extract_archive;
+pub use extract::{extract_archive, ErrorHandler};
/// The format requires to build sorted directory lookup tables in
/// memory, so we restrict the number of allowed entries to limit
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 09/15] pxar: factor out PxarCreateOptions
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (7 preceding siblings ...)
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 08/15] pxar: typedef on_error as ErrorHandler Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 10/15] pxar: extract PxarExtractOptions Fabian Grünbichler
` (8 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
containing the CLI parameters that are mostly passed-through from the
client to our pxar archive creation wrapper in pxar::create
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
src/bin/proxmox-backup-client.rs | 27 ++++++++++++---------------
src/bin/pxar.rs | 22 ++++++++++++++--------
src/client/pxar_backup_stream.rs | 28 ++++++----------------------
src/pxar/create.rs | 28 ++++++++++++++++++++++------
src/pxar/mod.rs | 2 +-
tests/catar.rs | 10 ++++++----
6 files changed, 61 insertions(+), 56 deletions(-)
diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs
index af3b8464..c3d6a0ed 100644
--- a/src/bin/proxmox-backup-client.rs
+++ b/src/bin/proxmox-backup-client.rs
@@ -283,23 +283,15 @@ async fn backup_directory<P: AsRef<Path>>(
dir_path: P,
archive_name: &str,
chunk_size: Option<usize>,
- device_set: Option<HashSet<u64>>,
- verbose: bool,
- skip_lost_and_found: bool,
catalog: Arc<Mutex<CatalogWriter<crate::tools::StdChannelWriter>>>,
- exclude_pattern: Vec<MatchEntry>,
- entries_max: usize,
+ pxar_create_options: proxmox_backup::pxar::PxarCreateOptions,
upload_options: UploadOptions,
) -> Result<BackupStats, Error> {
let pxar_stream = PxarBackupStream::open(
dir_path.as_ref(),
- device_set,
- verbose,
- skip_lost_and_found,
catalog,
- exclude_pattern,
- entries_max,
+ pxar_create_options,
)?;
let mut chunk_stream = ChunkStream::new(pxar_stream, chunk_size);
@@ -1039,6 +1031,15 @@ async fn create_backup(
println!("Upload directory '{}' to '{}' as {}", filename, repo, target);
catalog.lock().unwrap().start_directory(std::ffi::CString::new(target.as_str())?.as_c_str())?;
+
+ let pxar_options = proxmox_backup::pxar::PxarCreateOptions {
+ device_set: devices.clone(),
+ patterns: pattern_list.clone(),
+ entries_max: entries_max as usize,
+ skip_lost_and_found,
+ verbose,
+ };
+
let upload_options = UploadOptions {
previous_manifest: previous_manifest.clone(),
compress: true,
@@ -1051,12 +1052,8 @@ async fn create_backup(
&filename,
&target,
chunk_size_opt,
- devices.clone(),
- verbose,
- skip_lost_and_found,
catalog.clone(),
- pattern_list.clone(),
- entries_max as usize,
+ pxar_options,
upload_options,
).await?;
manifest.add_file(target, stats.size, stats.csum, crypt_mode)?;
diff --git a/src/bin/pxar.rs b/src/bin/pxar.rs
index 3d92dbe0..85606c1d 100644
--- a/src/bin/pxar.rs
+++ b/src/bin/pxar.rs
@@ -311,16 +311,16 @@ fn create_archive(
exclude: Option<Vec<String>>,
entries_max: isize,
) -> Result<(), Error> {
- let pattern_list = {
+ let patterns = {
let input = exclude.unwrap_or_else(Vec::new);
- let mut pattern_list = Vec::with_capacity(input.len());
+ let mut patterns = Vec::with_capacity(input.len());
for entry in input {
- pattern_list.push(
+ patterns.push(
MatchEntry::parse_pattern(entry, PatternFlag::PATH_NAME, MatchType::Exclude)
.map_err(|err| format_err!("error in exclude pattern: {}", err))?,
);
}
- pattern_list
+ patterns
};
let device_set = if all_file_systems {
@@ -329,6 +329,15 @@ fn create_archive(
Some(HashSet::new())
};
+ let options = proxmox_backup::pxar::PxarCreateOptions {
+ entries_max: entries_max as usize,
+ device_set,
+ patterns,
+ verbose,
+ skip_lost_and_found: false,
+ };
+
+
let source = PathBuf::from(source);
let dir = nix::dir::Dir::open(
@@ -368,18 +377,15 @@ fn create_archive(
proxmox_backup::pxar::create_archive(
dir,
writer,
- pattern_list,
feature_flags,
- device_set,
- false,
|path| {
if verbose {
println!("{:?}", path);
}
Ok(())
},
- entries_max as usize,
None,
+ options,
)?;
Ok(())
diff --git a/src/client/pxar_backup_stream.rs b/src/client/pxar_backup_stream.rs
index aa3355fe..5fb28fd5 100644
--- a/src/client/pxar_backup_stream.rs
+++ b/src/client/pxar_backup_stream.rs
@@ -1,4 +1,3 @@
-use std::collections::HashSet;
use std::io::Write;
//use std::os::unix::io::FromRawFd;
use std::path::Path;
@@ -13,8 +12,6 @@ use nix::dir::Dir;
use nix::fcntl::OFlag;
use nix::sys::stat::Mode;
-use pathpatterns::MatchEntry;
-
use crate::backup::CatalogWriter;
/// Stream implementation to encode and upload .pxar archives.
@@ -38,12 +35,8 @@ impl Drop for PxarBackupStream {
impl PxarBackupStream {
pub fn new<W: Write + Send + 'static>(
dir: Dir,
- device_set: Option<HashSet<u64>>,
- verbose: bool,
- skip_lost_and_found: bool,
catalog: Arc<Mutex<CatalogWriter<W>>>,
- patterns: Vec<MatchEntry>,
- entries_max: usize,
+ options: crate::pxar::PxarCreateOptions,
) -> Result<Self, Error> {
let (tx, rx) = std::sync::mpsc::sync_channel(10);
@@ -61,22 +54,21 @@ impl PxarBackupStream {
crate::tools::StdChannelWriter::new(tx),
);
+ let verbose = options.verbose;
+
let writer = pxar::encoder::sync::StandardWriter::new(writer);
if let Err(err) = crate::pxar::create_archive(
dir,
writer,
- patterns,
crate::pxar::Flags::DEFAULT,
- device_set,
- skip_lost_and_found,
|path| {
if verbose {
println!("{:?}", path);
}
Ok(())
},
- entries_max,
Some(&mut *catalog_guard),
+ options,
) {
let mut error = error.lock().unwrap();
*error = Some(err.to_string());
@@ -93,23 +85,15 @@ impl PxarBackupStream {
pub fn open<W: Write + Send + 'static>(
dirname: &Path,
- device_set: Option<HashSet<u64>>,
- verbose: bool,
- skip_lost_and_found: bool,
catalog: Arc<Mutex<CatalogWriter<W>>>,
- patterns: Vec<MatchEntry>,
- entries_max: usize,
+ options: crate::pxar::PxarCreateOptions,
) -> Result<Self, Error> {
let dir = nix::dir::Dir::open(dirname, OFlag::O_DIRECTORY, Mode::empty())?;
Self::new(
dir,
- device_set,
- verbose,
- skip_lost_and_found,
catalog,
- patterns,
- entries_max,
+ options,
)
}
}
diff --git a/src/pxar/create.rs b/src/pxar/create.rs
index a21511c3..229e3f59 100644
--- a/src/pxar/create.rs
+++ b/src/pxar/create.rs
@@ -27,6 +27,22 @@ use crate::pxar::Flags;
use crate::pxar::tools::assert_single_path_component;
use crate::tools::{acl, fs, xattr, Fd};
+/// Pxar options for creating a pxar archive/stream
+#[derive(Default, Clone)]
+pub struct PxarCreateOptions {
+ /// Device/mountpoint st_dev numbers that should be included. None for no limitation.
+ pub device_set: Option<HashSet<u64>>,
+ /// Exclusion patterns
+ pub patterns: Vec<MatchEntry>,
+ /// Maximum number of entries to hold in memory
+ pub entries_max: usize,
+ /// Skip lost+found directory
+ pub skip_lost_and_found: bool,
+ /// Verbose output
+ pub verbose: bool,
+}
+
+
fn detect_fs_type(fd: RawFd) -> Result<i64, Error> {
let mut fs_stat = std::mem::MaybeUninit::uninit();
let res = unsafe { libc::fstatfs(fd, fs_stat.as_mut_ptr()) };
@@ -136,13 +152,10 @@ type Encoder<'a, 'b> = pxar::encoder::Encoder<'a, &'b mut dyn pxar::encoder::Seq
pub fn create_archive<T, F>(
source_dir: Dir,
mut writer: T,
- mut patterns: Vec<MatchEntry>,
feature_flags: Flags,
- mut device_set: Option<HashSet<u64>>,
- skip_lost_and_found: bool,
mut callback: F,
- entry_limit: usize,
catalog: Option<&mut dyn BackupCatalogWriter>,
+ options: PxarCreateOptions,
) -> Result<(), Error>
where
T: pxar::encoder::SeqWrite,
@@ -164,6 +177,7 @@ where
)
.map_err(|err| format_err!("failed to get metadata for source directory: {}", err))?;
+ let mut device_set = options.device_set.clone();
if let Some(ref mut set) = device_set {
set.insert(stat.st_dev);
}
@@ -171,7 +185,9 @@ where
let writer = &mut writer as &mut dyn pxar::encoder::SeqWrite;
let mut encoder = Encoder::new(writer, &metadata)?;
- if skip_lost_and_found {
+ let mut patterns = options.patterns.clone();
+
+ if options.skip_lost_and_found {
patterns.push(MatchEntry::parse_pattern(
"lost+found",
PatternFlag::PATH_NAME,
@@ -188,7 +204,7 @@ where
catalog,
path: PathBuf::new(),
entry_counter: 0,
- entry_limit,
+ entry_limit: options.entries_max,
current_st_dev: stat.st_dev,
device_set,
hardlinks: HashMap::new(),
diff --git a/src/pxar/mod.rs b/src/pxar/mod.rs
index 82998cf8..c10bb6fb 100644
--- a/src/pxar/mod.rs
+++ b/src/pxar/mod.rs
@@ -58,7 +58,7 @@ pub(crate) mod tools;
mod flags;
pub use flags::Flags;
-pub use create::create_archive;
+pub use create::{create_archive, PxarCreateOptions};
pub use extract::{extract_archive, ErrorHandler};
/// The format requires to build sorted directory lookup tables in
diff --git a/tests/catar.rs b/tests/catar.rs
index a6acf9af..2d9dea71 100644
--- a/tests/catar.rs
+++ b/tests/catar.rs
@@ -25,16 +25,18 @@ fn run_test(dir_name: &str) -> Result<(), Error> {
dir_name, nix::fcntl::OFlag::O_NOFOLLOW,
nix::sys::stat::Mode::empty())?;
+ let options = PxarCreateOptions {
+ entries_max: ENCODER_MAX_ENTRIES,
+ ..PxarCreateOptions::default()
+ };
+
create_archive(
dir,
writer,
- Vec::new(),
Flags::DEFAULT,
- None,
- false,
|_| Ok(()),
- ENCODER_MAX_ENTRIES,
None,
+ options,
)?;
Command::new("cmp")
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 10/15] pxar: extract PxarExtractOptions
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (8 preceding siblings ...)
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 09/15] pxar: factor out PxarCreateOptions Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 11/15] authid: make Tokenname(Ref) derive Eq Fabian Grünbichler
` (7 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
same as PxarCreateOptions, but for extraction/restore rather than
create.
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
src/bin/proxmox-backup-client.rs | 12 ++++++++----
src/bin/pxar.rs | 31 ++++++++++++++-----------------
| 20 ++++++++++++--------
src/pxar/mod.rs | 2 +-
4 files changed, 35 insertions(+), 30 deletions(-)
diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs
index c3d6a0ed..d31e47ae 100644
--- a/src/bin/proxmox-backup-client.rs
+++ b/src/bin/proxmox-backup-client.rs
@@ -1354,20 +1354,24 @@ async fn restore(param: Value) -> Result<Value, Error> {
let mut reader = BufferedDynamicReader::new(index, chunk_reader);
+ let options = proxmox_backup::pxar::PxarExtractOptions {
+ match_list: &[],
+ extract_match_default: true,
+ allow_existing_dirs,
+ on_error: None,
+ };
+
if let Some(target) = target {
proxmox_backup::pxar::extract_archive(
pxar::decoder::Decoder::from_std(reader)?,
Path::new(target),
- &[],
- true,
proxmox_backup::pxar::Flags::DEFAULT,
- allow_existing_dirs,
|path| {
if verbose {
println!("{:?}", path);
}
},
- None,
+ options,
)
.map_err(|err| format_err!("error extracting archive - {}", err))?;
} else {
diff --git a/src/bin/pxar.rs b/src/bin/pxar.rs
index 85606c1d..b2fe6d52 100644
--- a/src/bin/pxar.rs
+++ b/src/bin/pxar.rs
@@ -17,31 +17,26 @@ use proxmox::api::cli::*;
use proxmox::api::api;
use proxmox_backup::tools;
-use proxmox_backup::pxar::{fuse, format_single_line_entry, ENCODER_MAX_ENTRIES, ErrorHandler, Flags};
+use proxmox_backup::pxar::{fuse, format_single_line_entry, ENCODER_MAX_ENTRIES, Flags, PxarExtractOptions};
fn extract_archive_from_reader<R: std::io::Read>(
reader: &mut R,
target: &str,
feature_flags: Flags,
- allow_existing_dirs: bool,
verbose: bool,
- match_list: &[MatchEntry],
- extract_match_default: bool,
- on_error: Option<ErrorHandler>,
+ options: PxarExtractOptions,
) -> Result<(), Error> {
+
proxmox_backup::pxar::extract_archive(
pxar::decoder::Decoder::from_std(reader)?,
Path::new(target),
- &match_list,
- extract_match_default,
feature_flags,
- allow_existing_dirs,
|path| {
if verbose {
println!("{:?}", path);
}
},
- on_error,
+ options,
)
}
@@ -190,6 +185,13 @@ fn extract_archive(
}) as Box<dyn FnMut(Error) -> Result<(), Error> + Send>)
};
+ let options = PxarExtractOptions {
+ match_list: &match_list,
+ allow_existing_dirs,
+ extract_match_default,
+ on_error,
+ };
+
if archive == "-" {
let stdin = std::io::stdin();
let mut reader = stdin.lock();
@@ -197,11 +199,8 @@ fn extract_archive(
&mut reader,
&target,
feature_flags,
- allow_existing_dirs,
verbose,
- &match_list,
- extract_match_default,
- on_error,
+ options,
)?;
} else {
if verbose {
@@ -213,11 +212,8 @@ fn extract_archive(
&mut reader,
&target,
feature_flags,
- allow_existing_dirs,
verbose,
- &match_list,
- extract_match_default,
- on_error,
+ options,
)?;
}
@@ -297,6 +293,7 @@ fn extract_archive(
},
)]
/// Create a new .pxar archive.
+#[allow(clippy::too_many_arguments)]
fn create_archive(
archive: String,
source: String,
--git a/src/pxar/extract.rs b/src/pxar/extract.rs
index e22fc847..9cf3f928 100644
--- a/src/pxar/extract.rs
+++ b/src/pxar/extract.rs
@@ -24,17 +24,21 @@ use crate::pxar::dir_stack::PxarDirStack;
use crate::pxar::metadata;
use crate::pxar::Flags;
+pub struct PxarExtractOptions<'a> {
+ pub match_list: &'a[MatchEntry],
+ pub extract_match_default: bool,
+ pub allow_existing_dirs: bool,
+ pub on_error: Option<ErrorHandler>,
+}
+
pub type ErrorHandler = Box<dyn FnMut(Error) -> Result<(), Error> + Send>;
pub fn extract_archive<T, F>(
mut decoder: pxar::decoder::Decoder<T>,
destination: &Path,
- match_list: &[MatchEntry],
- extract_match_default: bool,
feature_flags: Flags,
- allow_existing_dirs: bool,
mut callback: F,
- on_error: Option<ErrorHandler>,
+ options: PxarExtractOptions,
) -> Result<(), Error>
where
T: pxar::decoder::SeqRead,
@@ -69,17 +73,17 @@ where
let mut extractor = Extractor::new(
dir,
root.metadata().clone(),
- allow_existing_dirs,
+ options.allow_existing_dirs,
feature_flags,
);
- if let Some(on_error) = on_error {
+ if let Some(on_error) = options.on_error {
extractor.on_error(on_error);
}
let mut match_stack = Vec::new();
let mut err_path_stack = vec![OsString::from("/")];
- let mut current_match = extract_match_default;
+ let mut current_match = options.extract_match_default;
while let Some(entry) = decoder.next() {
use pxar::EntryKind;
@@ -99,7 +103,7 @@ where
extractor.set_path(entry.path().as_os_str().to_owned());
- let match_result = match_list.matches(
+ let match_result = options.match_list.matches(
entry.path().as_os_str().as_bytes(),
Some(metadata.file_type() as u32),
);
diff --git a/src/pxar/mod.rs b/src/pxar/mod.rs
index c10bb6fb..5d03591b 100644
--- a/src/pxar/mod.rs
+++ b/src/pxar/mod.rs
@@ -59,7 +59,7 @@ mod flags;
pub use flags::Flags;
pub use create::{create_archive, PxarCreateOptions};
-pub use extract::{extract_archive, ErrorHandler};
+pub use extract::{extract_archive, ErrorHandler, PxarExtractOptions};
/// The format requires to build sorted directory lookup tables in
/// memory, so we restrict the number of allowed entries to limit
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 11/15] authid: make Tokenname(Ref) derive Eq
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (9 preceding siblings ...)
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 10/15] pxar: extract PxarExtractOptions Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 12/15] derive/impl and use Default for some structs Fabian Grünbichler
` (6 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
it's needed to derive Hash, and we always compare Authids or their
Userid components, never just the Tokenname part anyway..
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
src/api2/types/userid.rs | 50 +++++-----------------------------------
1 file changed, 6 insertions(+), 44 deletions(-)
diff --git a/src/api2/types/userid.rs b/src/api2/types/userid.rs
index 20ce9370..7c73e69f 100644
--- a/src/api2/types/userid.rs
+++ b/src/api2/types/userid.rs
@@ -16,10 +16,10 @@
//! * [`Authid`]: an owned Authentication ID (a `Userid` with an optional `Tokenname`).
//! Note that `Userid` and `Authid` do not have a separate borrowed type.
//!
-//! Note that `Username`s and `Tokenname`s are not unique, therefore they do not implement `Eq` and cannot be
+//! Note that `Username`s are not unique, therefore they do not implement `Eq` and cannot be
//! compared directly. If a direct comparison is really required, they can be compared as strings
-//! via the `as_str()` method. [`Realm`]s, [`Userid`]s and [`Authid`]s on the other
-//! hand can be compared with each other, as in those cases the comparison has meaning.
+//! via the `as_str()` method. [`Realm`]s, [`Userid`]s and [`Authid`]s on the other hand can be
+//! compared with each other, as in those cases the comparison has meaning.
use std::borrow::Borrow;
use std::convert::TryFrom;
@@ -299,16 +299,8 @@ impl PartialEq<Realm> for &RealmRef {
)]
/// The token ID part of an API token authentication id.
///
-/// This alone does NOT uniquely identify the API token and therefore does not implement `Eq`. In
-/// order to compare token IDs directly, they need to be explicitly compared as strings by calling
-/// `.as_str()`.
-///
-/// ```compile_fail
-/// fn test(a: Tokenname, b: Tokenname) -> bool {
-/// a == b // illegal and does not compile
-/// }
-/// ```
-#[derive(Clone, Debug, Hash, Deserialize, Serialize)]
+/// This alone does NOT uniquely identify the API token - use a full `Authid` for such use cases.
+#[derive(Clone, Debug, Eq, Hash, PartialEq, Deserialize, Serialize)]
pub struct Tokenname(String);
/// A reference to a token name part of an authentication id. This alone does NOT uniquely identify
@@ -336,24 +328,6 @@ pub struct TokennameRef(str);
/// let b: &UsernameRef = unsafe { std::mem::zeroed() };
/// let _ = <&UsernameRef as PartialEq>::eq(&a, &b);
/// ```
-///
-/// ```compile_fail
-/// let a: Tokenname = unsafe { std::mem::zeroed() };
-/// let b: Tokenname = unsafe { std::mem::zeroed() };
-/// let _ = <Tokenname as PartialEq>::eq(&a, &b);
-/// ```
-///
-/// ```compile_fail
-/// let a: &TokennameRef = unsafe { std::mem::zeroed() };
-/// let b: &TokennameRef = unsafe { std::mem::zeroed() };
-/// let _ = <&TokennameRef as PartialEq>::eq(a, b);
-/// ```
-///
-/// ```compile_fail
-/// let a: &TokennameRef = unsafe { std::mem::zeroed() };
-/// let b: &TokennameRef = unsafe { std::mem::zeroed() };
-/// let _ = <&TokennameRef as PartialEq>::eq(&a, &b);
-/// ```
struct _AssertNoEqImpl;
impl TokennameRef {
@@ -548,7 +522,7 @@ impl PartialEq<String> for Userid {
}
/// A complete authentication id consisting of a user id and an optional token name.
-#[derive(Clone, Debug, Hash)]
+#[derive(Clone, Debug, Eq, PartialEq, Hash)]
pub struct Authid {
user: Userid,
tokenname: Option<Tokenname>
@@ -590,18 +564,6 @@ lazy_static! {
pub static ref ROOT_AUTHID: Authid = Authid::from(Userid::new("root@pam".to_string(), 4));
}
-impl Eq for Authid {}
-
-impl PartialEq for Authid {
- fn eq(&self, rhs: &Self) -> bool {
- self.user == rhs.user && match (&self.tokenname, &rhs.tokenname) {
- (Some(ours), Some(theirs)) => ours.as_str() == theirs.as_str(),
- (None, None) => true,
- _ => false,
- }
- }
-}
-
impl From<Userid> for Authid {
fn from(parts: Userid) -> Self {
Self::new(parts, None)
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 12/15] derive/impl and use Default for some structs
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (10 preceding siblings ...)
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 11/15] authid: make Tokenname(Ref) derive Eq Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 13/15] verify: factor out common parameters Fabian Grünbichler
` (5 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
and revamp HttpClientOptions with two constructors for the common use
cases
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
breaks proxmox-backup-qemu, corresponding patch comes later in this
series
examples/download-speed.rs | 2 +-
examples/upload-speed.rs | 2 +-
src/api2/config/remote.rs | 4 +---
src/backup/prune.rs | 1 +
src/bin/proxmox-backup-client.rs | 18 ++++-----------
src/client.rs | 11 +++++----
src/client/http_client.rs | 38 +++++++++++++++++++++++++-------
src/client/pull.rs | 4 +---
src/config/acl.rs | 8 ++++---
src/config/network.rs | 2 +-
10 files changed, 50 insertions(+), 40 deletions(-)
diff --git a/examples/download-speed.rs b/examples/download-speed.rs
index 3ccf4ce7..a4afb7ba 100644
--- a/examples/download-speed.rs
+++ b/examples/download-speed.rs
@@ -28,7 +28,7 @@ async fn run() -> Result<(), Error> {
let auth_id = Authid::root_auth_id();
- let options = HttpClientOptions::new()
+ let options = HttpClientOptions::default()
.interactive(true)
.ticket_cache(true);
diff --git a/examples/upload-speed.rs b/examples/upload-speed.rs
index 641ed952..05e44aaf 100644
--- a/examples/upload-speed.rs
+++ b/examples/upload-speed.rs
@@ -10,7 +10,7 @@ async fn upload_speed() -> Result<f64, Error> {
let auth_id = Authid::root_auth_id();
- let options = HttpClientOptions::new()
+ let options = HttpClientOptions::default()
.interactive(true)
.ticket_cache(true);
diff --git a/src/api2/config/remote.rs b/src/api2/config/remote.rs
index fe7dc451..28221358 100644
--- a/src/api2/config/remote.rs
+++ b/src/api2/config/remote.rs
@@ -310,9 +310,7 @@ pub fn delete_remote(name: String, digest: Option<String>) -> Result<(), Error>
/// Helper to get client for remote.cfg entry
pub async fn remote_client(remote: remote::Remote) -> Result<HttpClient, Error> {
- let options = HttpClientOptions::new()
- .password(Some(remote.password.clone()))
- .fingerprint(remote.fingerprint.clone());
+ let options = HttpClientOptions::new_non_interactive(remote.password.clone(), remote.fingerprint.clone());
let client = HttpClient::new(
&remote.host,
diff --git a/src/backup/prune.rs b/src/backup/prune.rs
index baec57d6..dd038055 100644
--- a/src/backup/prune.rs
+++ b/src/backup/prune.rs
@@ -67,6 +67,7 @@ fn remove_incomplete_snapshots(
}
}
+#[derive(Default)]
pub struct PruneOptions {
pub keep_last: Option<u64>,
pub keep_hourly: Option<u64>,
diff --git a/src/bin/proxmox-backup-client.rs b/src/bin/proxmox-backup-client.rs
index d31e47ae..fe305f63 100644
--- a/src/bin/proxmox-backup-client.rs
+++ b/src/bin/proxmox-backup-client.rs
@@ -211,13 +211,7 @@ fn connect_do(server: &str, port: u16, auth_id: &Authid) -> Result<HttpClient, E
Err(NotPresent) => None,
};
- let options = HttpClientOptions::new()
- .prefix(Some("proxmox-backup".to_string()))
- .password(password)
- .interactive(true)
- .fingerprint(fingerprint)
- .fingerprint_cache(true)
- .ticket_cache(true);
+ let options = HttpClientOptions::new_interactive(password, fingerprint);
HttpClient::new(server, port, auth_id, options)
}
@@ -1565,13 +1559,9 @@ async fn try_get(repo: &BackupRepository, url: &str) -> Value {
let fingerprint = std::env::var(ENV_VAR_PBS_FINGERPRINT).ok();
let password = std::env::var(ENV_VAR_PBS_PASSWORD).ok();
- let options = HttpClientOptions::new()
- .prefix(Some("proxmox-backup".to_string()))
- .password(password)
- .interactive(false)
- .fingerprint(fingerprint)
- .fingerprint_cache(true)
- .ticket_cache(true);
+ // ticket cache, but no questions asked
+ let options = HttpClientOptions::new_interactive(password, fingerprint)
+ .interactive(false);
let client = match HttpClient::new(repo.host(), repo.port(), repo.auth_id(), options) {
Ok(v) => v,
diff --git a/src/client.rs b/src/client.rs
index 8c4542b6..d50c26c2 100644
--- a/src/client.rs
+++ b/src/client.rs
@@ -49,17 +49,16 @@ pub fn connect_to_localhost() -> Result<HttpClient, Error> {
let uid = nix::unistd::Uid::current();
- let mut options = HttpClientOptions::new()
- .prefix(Some("proxmox-backup".to_string()))
- .verify_cert(false); // not required for connection to localhost
-
let client = if uid.is_root() {
let ticket = Ticket::new("PBS", Userid::root_userid())?
.sign(private_auth_key(), None)?;
- options = options.password(Some(ticket));
+ let fingerprint = crate::tools::cert::CertInfo::new()?.fingerprint()?;
+ let options = HttpClientOptions::new_non_interactive(ticket, Some(fingerprint));
+
HttpClient::new("localhost", 8007, Authid::root_auth_id(), options)?
} else {
- options = options.ticket_cache(true).interactive(true);
+ let options = HttpClientOptions::new_interactive(None, None);
+
HttpClient::new("localhost", 8007, Authid::root_auth_id(), options)?
};
diff --git a/src/client/http_client.rs b/src/client/http_client.rs
index f279d9dd..9fd1c013 100644
--- a/src/client/http_client.rs
+++ b/src/client/http_client.rs
@@ -52,15 +52,23 @@ pub struct HttpClientOptions {
impl HttpClientOptions {
- pub fn new() -> Self {
+ pub fn new_interactive(password: Option<String>, fingerprint: Option<String>) -> Self {
Self {
- prefix: None,
- password: None,
- fingerprint: None,
- interactive: false,
- ticket_cache: false,
- fingerprint_cache: false,
- verify_cert: true,
+ password,
+ fingerprint,
+ fingerprint_cache: true,
+ ticket_cache: true,
+ interactive: true,
+ prefix: Some("proxmox-backup".to_string()),
+ ..Self::default()
+ }
+ }
+
+ pub fn new_non_interactive(password: String, fingerprint: Option<String>) -> Self {
+ Self {
+ password: Some(password),
+ fingerprint,
+ ..Self::default()
}
}
@@ -100,6 +108,20 @@ impl HttpClientOptions {
}
}
+impl Default for HttpClientOptions {
+ fn default() -> Self {
+ Self {
+ prefix: None,
+ password: None,
+ fingerprint: None,
+ interactive: false,
+ ticket_cache: false,
+ fingerprint_cache: false,
+ verify_cert: true,
+ }
+ }
+}
+
/// HTTP(S) API client
pub struct HttpClient {
client: Client<HttpsConnector>,
diff --git a/src/client/pull.rs b/src/client/pull.rs
index 15514374..95720973 100644
--- a/src/client/pull.rs
+++ b/src/client/pull.rs
@@ -502,9 +502,7 @@ pub async fn pull_group(
// get updated auth_info (new tickets)
let auth_info = client.login().await?;
- let options = HttpClientOptions::new()
- .password(Some(auth_info.ticket.clone()))
- .fingerprint(fingerprint.clone());
+ let options = HttpClientOptions::new_non_interactive(auth_info.ticket.clone(), fingerprint.clone());
let new_client = HttpClient::new(
src_repo.host(),
diff --git a/src/config/acl.rs b/src/config/acl.rs
index 6ef54e30..e02ac5c7 100644
--- a/src/config/acl.rs
+++ b/src/config/acl.rs
@@ -299,6 +299,7 @@ pub fn check_acl_path(path: &str) -> Result<(), Error> {
}
/// Tree representing a parsed acl.cfg
+#[derive(Default)]
pub struct AclTree {
/// Root node of the tree.
///
@@ -308,6 +309,7 @@ pub struct AclTree {
}
/// Node representing ACLs for a certain ACL path.
+#[derive(Default)]
pub struct AclTreeNode {
/// [User](crate::config::user::User) or
/// [Token](crate::config::user::ApiToken) ACLs for this node.
@@ -412,7 +414,7 @@ impl AclTreeNode {
}
fn insert_group_role(&mut self, group: String, role: String, propagate: bool) {
- let map = self.groups.entry(group).or_insert_with(HashMap::new);
+ let map = self.groups.entry(group).or_default();
if role == ROLE_NAME_NO_ACCESS {
map.clear();
map.insert(role, propagate);
@@ -423,7 +425,7 @@ impl AclTreeNode {
}
fn insert_user_role(&mut self, auth_id: Authid, role: String, propagate: bool) {
- let map = self.users.entry(auth_id).or_insert_with(HashMap::new);
+ let map = self.users.entry(auth_id).or_default();
if role == ROLE_NAME_NO_ACCESS {
map.clear();
map.insert(role, propagate);
@@ -465,7 +467,7 @@ impl AclTree {
node = node
.children
.entry(String::from(*comp))
- .or_insert_with(AclTreeNode::new);
+ .or_default();
}
node
}
diff --git a/src/config/network.rs b/src/config/network.rs
index 4241261a..99ea0d08 100644
--- a/src/config/network.rs
+++ b/src/config/network.rs
@@ -318,7 +318,7 @@ enum NetworkOrderEntry {
Option(String),
}
-#[derive(Debug)]
+#[derive(Debug, Default)]
pub struct NetworkConfig {
pub interfaces: BTreeMap<String, Interface>,
order: Vec<NetworkOrderEntry>,
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 13/15] verify: factor out common parameters
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (11 preceding siblings ...)
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 12/15] derive/impl and use Default for some structs Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 14/15] clippy: allow api functions with many arguments Fabian Grünbichler
` (4 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
all the verify methods pass along the following:
- task worker
- datastore
- corrupt and verified chunks
might as well pull that out into a common type, with the added bonus of
now having a single point for construction instead of copying the
default capacaties in three different modules..
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
src/api2/admin/datastore.rs | 17 +---
src/api2/backup/environment.rs | 10 +-
src/backup/verify.rs | 174 ++++++++++++++-------------------
src/server/verify_job.rs | 3 +-
4 files changed, 85 insertions(+), 119 deletions(-)
diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs
index ba8f3417..3d5b6af6 100644
--- a/src/api2/admin/datastore.rs
+++ b/src/api2/admin/datastore.rs
@@ -3,7 +3,6 @@
use std::collections::HashSet;
use std::ffi::OsStr;
use std::os::unix::ffi::OsStrExt;
-use std::sync::{Arc, Mutex};
use std::path::{Path, PathBuf};
use std::pin::Pin;
@@ -672,17 +671,12 @@ pub fn verify(
auth_id.clone(),
to_stdout,
move |worker| {
- let verified_chunks = Arc::new(Mutex::new(HashSet::with_capacity(1024*16)));
- let corrupt_chunks = Arc::new(Mutex::new(HashSet::with_capacity(64)));
-
+ let verify_worker = crate::backup::VerifyWorker::new(worker.clone(), datastore);
let failed_dirs = if let Some(backup_dir) = backup_dir {
let mut res = Vec::new();
if !verify_backup_dir(
- datastore,
+ &verify_worker,
&backup_dir,
- verified_chunks,
- corrupt_chunks,
- worker.clone(),
worker.upid().clone(),
None,
)? {
@@ -691,12 +685,9 @@ pub fn verify(
res
} else if let Some(backup_group) = backup_group {
let failed_dirs = verify_backup_group(
- datastore,
+ &verify_worker,
&backup_group,
- verified_chunks,
- corrupt_chunks,
&mut StoreProgress::new(1),
- worker.clone(),
worker.upid(),
None,
)?;
@@ -711,7 +702,7 @@ pub fn verify(
None
};
- verify_all_backups(datastore, worker.clone(), worker.upid(), owner, None)?
+ verify_all_backups(&verify_worker, worker.upid(), owner, None)?
};
if !failed_dirs.is_empty() {
worker.log("Failed to verify the following snapshots/groups:");
diff --git a/src/api2/backup/environment.rs b/src/api2/backup/environment.rs
index 38061816..c8f52b6e 100644
--- a/src/api2/backup/environment.rs
+++ b/src/api2/backup/environment.rs
@@ -1,6 +1,6 @@
use anyhow::{bail, format_err, Error};
use std::sync::{Arc, Mutex};
-use std::collections::{HashMap, HashSet};
+use std::collections::HashMap;
use nix::dir::Dir;
use ::serde::{Serialize};
@@ -525,15 +525,11 @@ impl BackupEnvironment {
move |worker| {
worker.log("Automatically verifying newly added snapshot");
- let verified_chunks = Arc::new(Mutex::new(HashSet::with_capacity(1024*16)));
- let corrupt_chunks = Arc::new(Mutex::new(HashSet::with_capacity(64)));
+ let verify_worker = crate::backup::VerifyWorker::new(worker.clone(), datastore);
if !verify_backup_dir_with_lock(
- datastore,
+ &verify_worker,
&backup_dir,
- verified_chunks,
- corrupt_chunks,
- worker.clone(),
worker.upid().clone(),
None,
snap_lock,
diff --git a/src/backup/verify.rs b/src/backup/verify.rs
index 5e4bc7fb..ac4a6c29 100644
--- a/src/backup/verify.rs
+++ b/src/backup/verify.rs
@@ -29,6 +29,29 @@ use crate::{
tools::fs::lock_dir_noblock_shared,
};
+/// A VerifyWorker encapsulates a task worker, datastore and information about which chunks have
+/// already been verified or detected as corrupt.
+pub struct VerifyWorker {
+ worker: Arc<dyn TaskState + Send + Sync>,
+ datastore: Arc<DataStore>,
+ verified_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
+ corrupt_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
+}
+
+impl VerifyWorker {
+ /// Creates a new VerifyWorker for a given task worker and datastore.
+ pub fn new(worker: Arc<dyn TaskState + Send + Sync>, datastore: Arc<DataStore>) -> Self {
+ Self {
+ worker,
+ datastore,
+ // start with 16k chunks == up to 64G data
+ verified_chunks: Arc::new(Mutex::new(HashSet::with_capacity(16*1024))),
+ // start with 64 chunks since we assume there are few corrupt ones
+ corrupt_chunks: Arc::new(Mutex::new(HashSet::with_capacity(64))),
+ }
+ }
+}
+
fn verify_blob(datastore: Arc<DataStore>, backup_dir: &BackupDir, info: &FileInfo) -> Result<(), Error> {
let blob = datastore.load_blob(backup_dir, &info.filename)?;
@@ -82,12 +105,9 @@ fn rename_corrupted_chunk(
}
fn verify_index_chunks(
- datastore: Arc<DataStore>,
+ verify_worker: &VerifyWorker,
index: Box<dyn IndexFile + Send>,
- verified_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
- corrupt_chunks: Arc<Mutex<HashSet<[u8; 32]>>>,
crypt_mode: CryptMode,
- worker: Arc<dyn TaskState + Send + Sync>,
) -> Result<(), Error> {
let errors = Arc::new(AtomicUsize::new(0));
@@ -97,10 +117,10 @@ fn verify_index_chunks(
let mut read_bytes = 0;
let mut decoded_bytes = 0;
- let worker2 = Arc::clone(&worker);
- let datastore2 = Arc::clone(&datastore);
- let corrupt_chunks2 = Arc::clone(&corrupt_chunks);
- let verified_chunks2 = Arc::clone(&verified_chunks);
+ let worker2 = Arc::clone(&verify_worker.worker);
+ let datastore2 = Arc::clone(&verify_worker.datastore);
+ let corrupt_chunks2 = Arc::clone(&verify_worker.corrupt_chunks);
+ let verified_chunks2 = Arc::clone(&verify_worker.verified_chunks);
let errors2 = Arc::clone(&errors);
let decoder_pool = ParallelHandler::new(
@@ -141,29 +161,29 @@ fn verify_index_chunks(
for pos in 0..index.index_count() {
- worker.check_abort()?;
+ verify_worker.worker.check_abort()?;
crate::tools::fail_on_shutdown()?;
let info = index.chunk_info(pos).unwrap();
let size = info.size();
- if verified_chunks.lock().unwrap().contains(&info.digest) {
+ if verify_worker.verified_chunks.lock().unwrap().contains(&info.digest) {
continue; // already verified
}
- if corrupt_chunks.lock().unwrap().contains(&info.digest) {
+ if verify_worker.corrupt_chunks.lock().unwrap().contains(&info.digest) {
let digest_str = proxmox::tools::digest_to_hex(&info.digest);
- task_log!(worker, "chunk {} was marked as corrupt", digest_str);
+ task_log!(verify_worker.worker, "chunk {} was marked as corrupt", digest_str);
errors.fetch_add(1, Ordering::SeqCst);
continue;
}
- match datastore.load_chunk(&info.digest) {
+ match verify_worker.datastore.load_chunk(&info.digest) {
Err(err) => {
- corrupt_chunks.lock().unwrap().insert(info.digest);
- task_log!(worker, "can't verify chunk, load failed - {}", err);
+ verify_worker.corrupt_chunks.lock().unwrap().insert(info.digest);
+ task_log!(verify_worker.worker, "can't verify chunk, load failed - {}", err);
errors.fetch_add(1, Ordering::SeqCst);
- rename_corrupted_chunk(datastore.clone(), &info.digest, &worker);
+ rename_corrupted_chunk(verify_worker.datastore.clone(), &info.digest, &verify_worker.worker);
continue;
}
Ok(chunk) => {
@@ -187,7 +207,7 @@ fn verify_index_chunks(
let error_count = errors.load(Ordering::SeqCst);
task_log!(
- worker,
+ verify_worker.worker,
" verified {:.2}/{:.2} MiB in {:.2} seconds, speed {:.2}/{:.2} MiB/s ({} errors)",
read_bytes_mib,
decoded_bytes_mib,
@@ -205,18 +225,15 @@ fn verify_index_chunks(
}
fn verify_fixed_index(
- datastore: Arc<DataStore>,
+ verify_worker: &VerifyWorker,
backup_dir: &BackupDir,
info: &FileInfo,
- verified_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
- corrupt_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
- worker: Arc<dyn TaskState + Send + Sync>,
) -> Result<(), Error> {
let mut path = backup_dir.relative_path();
path.push(&info.filename);
- let index = datastore.open_fixed_reader(&path)?;
+ let index = verify_worker.datastore.open_fixed_reader(&path)?;
let (csum, size) = index.compute_csum();
if size != info.size {
@@ -228,28 +245,22 @@ fn verify_fixed_index(
}
verify_index_chunks(
- datastore,
+ verify_worker,
Box::new(index),
- verified_chunks,
- corrupt_chunks,
info.chunk_crypt_mode(),
- worker,
)
}
fn verify_dynamic_index(
- datastore: Arc<DataStore>,
+ verify_worker: &VerifyWorker,
backup_dir: &BackupDir,
info: &FileInfo,
- verified_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
- corrupt_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
- worker: Arc<dyn TaskState + Send + Sync>,
) -> Result<(), Error> {
let mut path = backup_dir.relative_path();
path.push(&info.filename);
- let index = datastore.open_dynamic_reader(&path)?;
+ let index = verify_worker.datastore.open_dynamic_reader(&path)?;
let (csum, size) = index.compute_csum();
if size != info.size {
@@ -261,12 +272,9 @@ fn verify_dynamic_index(
}
verify_index_chunks(
- datastore,
+ verify_worker,
Box::new(index),
- verified_chunks,
- corrupt_chunks,
info.chunk_crypt_mode(),
- worker,
)
}
@@ -280,34 +288,28 @@ fn verify_dynamic_index(
/// - Ok(false) if there were verification errors
/// - Err(_) if task was aborted
pub fn verify_backup_dir(
- datastore: Arc<DataStore>,
+ verify_worker: &VerifyWorker,
backup_dir: &BackupDir,
- verified_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
- corrupt_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
- worker: Arc<dyn TaskState + Send + Sync>,
upid: UPID,
filter: Option<&dyn Fn(&BackupManifest) -> bool>,
) -> Result<bool, Error> {
let snap_lock = lock_dir_noblock_shared(
- &datastore.snapshot_path(&backup_dir),
+ &verify_worker.datastore.snapshot_path(&backup_dir),
"snapshot",
"locked by another operation");
match snap_lock {
Ok(snap_lock) => verify_backup_dir_with_lock(
- datastore,
+ verify_worker,
backup_dir,
- verified_chunks,
- corrupt_chunks,
- worker,
upid,
filter,
snap_lock
),
Err(err) => {
task_log!(
- worker,
+ verify_worker.worker,
"SKIPPED: verify {}:{} - could not acquire snapshot lock: {}",
- datastore.name(),
+ verify_worker.datastore.name(),
backup_dir,
err,
);
@@ -318,22 +320,19 @@ pub fn verify_backup_dir(
/// See verify_backup_dir
pub fn verify_backup_dir_with_lock(
- datastore: Arc<DataStore>,
+ verify_worker: &VerifyWorker,
backup_dir: &BackupDir,
- verified_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
- corrupt_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
- worker: Arc<dyn TaskState + Send + Sync>,
upid: UPID,
filter: Option<&dyn Fn(&BackupManifest) -> bool>,
_snap_lock: Dir,
) -> Result<bool, Error> {
- let manifest = match datastore.load_manifest(&backup_dir) {
+ let manifest = match verify_worker.datastore.load_manifest(&backup_dir) {
Ok((manifest, _)) => manifest,
Err(err) => {
task_log!(
- worker,
+ verify_worker.worker,
"verify {}:{} - manifest load error: {}",
- datastore.name(),
+ verify_worker.datastore.name(),
backup_dir,
err,
);
@@ -344,54 +343,48 @@ pub fn verify_backup_dir_with_lock(
if let Some(filter) = filter {
if !filter(&manifest) {
task_log!(
- worker,
+ verify_worker.worker,
"SKIPPED: verify {}:{} (recently verified)",
- datastore.name(),
+ verify_worker.datastore.name(),
backup_dir,
);
return Ok(true);
}
}
- task_log!(worker, "verify {}:{}", datastore.name(), backup_dir);
+ task_log!(verify_worker.worker, "verify {}:{}", verify_worker.datastore.name(), backup_dir);
let mut error_count = 0;
let mut verify_result = VerifyState::Ok;
for info in manifest.files() {
let result = proxmox::try_block!({
- task_log!(worker, " check {}", info.filename);
+ task_log!(verify_worker.worker, " check {}", info.filename);
match archive_type(&info.filename)? {
ArchiveType::FixedIndex =>
verify_fixed_index(
- datastore.clone(),
+ verify_worker,
&backup_dir,
info,
- verified_chunks.clone(),
- corrupt_chunks.clone(),
- worker.clone(),
),
ArchiveType::DynamicIndex =>
verify_dynamic_index(
- datastore.clone(),
+ verify_worker,
&backup_dir,
info,
- verified_chunks.clone(),
- corrupt_chunks.clone(),
- worker.clone(),
),
- ArchiveType::Blob => verify_blob(datastore.clone(), &backup_dir, info),
+ ArchiveType::Blob => verify_blob(verify_worker.datastore.clone(), &backup_dir, info),
}
});
- worker.check_abort()?;
+ verify_worker.worker.check_abort()?;
crate::tools::fail_on_shutdown()?;
if let Err(err) = result {
task_log!(
- worker,
+ verify_worker.worker,
"verify {}:{}/{} failed: {}",
- datastore.name(),
+ verify_worker.datastore.name(),
backup_dir,
info.filename,
err,
@@ -407,7 +400,7 @@ pub fn verify_backup_dir_with_lock(
upid,
};
let verify_state = serde_json::to_value(verify_state)?;
- datastore.update_manifest(&backup_dir, |manifest| {
+ verify_worker.datastore.update_manifest(&backup_dir, |manifest| {
manifest.unprotected["verify_state"] = verify_state;
}).map_err(|err| format_err!("unable to update manifest blob - {}", err))?;
@@ -422,24 +415,21 @@ pub fn verify_backup_dir_with_lock(
/// - Ok((count, failed_dirs)) where failed_dirs had verification errors
/// - Err(_) if task was aborted
pub fn verify_backup_group(
- datastore: Arc<DataStore>,
+ verify_worker: &VerifyWorker,
group: &BackupGroup,
- verified_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
- corrupt_chunks: Arc<Mutex<HashSet<[u8;32]>>>,
progress: &mut StoreProgress,
- worker: Arc<dyn TaskState + Send + Sync>,
upid: &UPID,
filter: Option<&dyn Fn(&BackupManifest) -> bool>,
) -> Result<Vec<String>, Error> {
let mut errors = Vec::new();
- let mut list = match group.list_backups(&datastore.base_path()) {
+ let mut list = match group.list_backups(&verify_worker.datastore.base_path()) {
Ok(list) => list,
Err(err) => {
task_log!(
- worker,
+ verify_worker.worker,
"verify group {}:{} - unable to list backups: {}",
- datastore.name(),
+ verify_worker.datastore.name(),
group,
err,
);
@@ -448,18 +438,15 @@ pub fn verify_backup_group(
};
let snapshot_count = list.len();
- task_log!(worker, "verify group {}:{} ({} snapshots)", datastore.name(), group, snapshot_count);
+ task_log!(verify_worker.worker, "verify group {}:{} ({} snapshots)", verify_worker.datastore.name(), group, snapshot_count);
progress.group_snapshots = snapshot_count as u64;
BackupInfo::sort_list(&mut list, false); // newest first
for (pos, info) in list.into_iter().enumerate() {
if !verify_backup_dir(
- datastore.clone(),
+ verify_worker,
&info.backup_dir,
- verified_chunks.clone(),
- corrupt_chunks.clone(),
- worker.clone(),
upid.clone(),
filter,
)? {
@@ -467,7 +454,7 @@ pub fn verify_backup_group(
}
progress.done_snapshots = pos as u64 + 1;
task_log!(
- worker,
+ verify_worker.worker,
"percentage done: {}",
progress
);
@@ -484,22 +471,22 @@ pub fn verify_backup_group(
/// - Ok(failed_dirs) where failed_dirs had verification errors
/// - Err(_) if task was aborted
pub fn verify_all_backups(
- datastore: Arc<DataStore>,
- worker: Arc<dyn TaskState + Send + Sync>,
+ verify_worker: &VerifyWorker,
upid: &UPID,
owner: Option<Authid>,
filter: Option<&dyn Fn(&BackupManifest) -> bool>,
) -> Result<Vec<String>, Error> {
let mut errors = Vec::new();
+ let worker = Arc::clone(&verify_worker.worker);
- task_log!(worker, "verify datastore {}", datastore.name());
+ task_log!(worker, "verify datastore {}", verify_worker.datastore.name());
if let Some(owner) = &owner {
task_log!(worker, "limiting to backups owned by {}", owner);
}
let filter_by_owner = |group: &BackupGroup| {
- match (datastore.get_owner(group), &owner) {
+ match (verify_worker.datastore.get_owner(group), &owner) {
(Ok(ref group_owner), Some(owner)) => {
group_owner == owner
|| (group_owner.is_token()
@@ -527,7 +514,7 @@ pub fn verify_all_backups(
}
};
- let mut list = match BackupInfo::list_backup_groups(&datastore.base_path()) {
+ let mut list = match BackupInfo::list_backup_groups(&verify_worker.datastore.base_path()) {
Ok(list) => list
.into_iter()
.filter(|group| !(group.backup_type() == "host" && group.backup_id() == "benchmark"))
@@ -545,12 +532,6 @@ pub fn verify_all_backups(
list.sort_unstable();
- // start with 16384 chunks (up to 65GB)
- let verified_chunks = Arc::new(Mutex::new(HashSet::with_capacity(1024*16)));
-
- // start with 64 chunks since we assume there are few corrupt ones
- let corrupt_chunks = Arc::new(Mutex::new(HashSet::with_capacity(64)));
-
let group_count = list.len();
task_log!(worker, "found {} groups", group_count);
@@ -562,12 +543,9 @@ pub fn verify_all_backups(
progress.group_snapshots = 0;
let mut group_errors = verify_backup_group(
- datastore.clone(),
+ verify_worker,
&group,
- verified_chunks.clone(),
- corrupt_chunks.clone(),
&mut progress,
- worker.clone(),
upid,
filter,
)?;
diff --git a/src/server/verify_job.rs b/src/server/verify_job.rs
index ca6eb554..1dd8baa7 100644
--- a/src/server/verify_job.rs
+++ b/src/server/verify_job.rs
@@ -67,7 +67,8 @@ pub fn do_verification_job(
task_log!(worker,"task triggered by schedule '{}'", event_str);
}
- let result = verify_all_backups(datastore, worker.clone(), worker.upid(), None, Some(&filter));
+ let verify_worker = crate::backup::VerifyWorker::new(worker.clone(), datastore);
+ let result = verify_all_backups(&verify_worker, worker.upid(), None, Some(&filter));
let job_result = match result {
Ok(ref failed_dirs) if failed_dirs.is_empty() => Ok(()),
Ok(ref failed_dirs) => {
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 14/15] clippy: allow api functions with many arguments
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (12 preceding siblings ...)
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 13/15] verify: factor out common parameters Fabian Grünbichler
@ 2021-01-25 13:42 ` Fabian Grünbichler
2021-01-25 13:43 ` [pbs-devel] [PATCH proxmox-backup 15/15] clippy: more misc fixes Fabian Grünbichler
` (3 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:42 UTC (permalink / raw)
To: pbs-devel
some of those can be reduced/cleaned up when we have updater support in
the api macro.
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
src/api2/access/acl.rs | 1 +
src/api2/access/tfa.rs | 1 +
src/api2/access/user.rs | 1 +
src/api2/admin/datastore.rs | 2 --
src/api2/config/datastore.rs | 1 +
src/api2/config/remote.rs | 1 +
src/api2/config/sync.rs | 1 +
src/api2/config/verify.rs | 1 +
src/api2/node/network.rs | 2 ++
src/api2/node/tasks.rs | 1 +
src/bin/pxar.rs | 1 +
src/client/backup_writer.rs | 2 ++
12 files changed, 13 insertions(+), 2 deletions(-)
diff --git a/src/api2/access/acl.rs b/src/api2/access/acl.rs
index 6f1ba327..be9ad380 100644
--- a/src/api2/access/acl.rs
+++ b/src/api2/access/acl.rs
@@ -165,6 +165,7 @@ pub fn read_acl(
},
)]
/// Update Access Control List (ACLs).
+#[allow(clippy::too_many_arguments)]
pub fn update_acl(
path: String,
role: String,
diff --git a/src/api2/access/tfa.rs b/src/api2/access/tfa.rs
index 5df0baec..ba583323 100644
--- a/src/api2/access/tfa.rs
+++ b/src/api2/access/tfa.rs
@@ -421,6 +421,7 @@ impl TfaUpdateInfo {
},
)]
/// Add a TFA entry to the user.
+#[allow(clippy::too_many_arguments)]
fn add_tfa_entry(
userid: Userid,
description: Option<String>,
diff --git a/src/api2/access/user.rs b/src/api2/access/user.rs
index c6032818..c49b12b1 100644
--- a/src/api2/access/user.rs
+++ b/src/api2/access/user.rs
@@ -353,6 +353,7 @@ pub enum DeletableProperty {
},
)]
/// Update user configuration.
+#[allow(clippy::too_many_arguments)]
pub fn update_user(
userid: Userid,
comment: Option<String>,
diff --git a/src/api2/admin/datastore.rs b/src/api2/admin/datastore.rs
index 3d5b6af6..6f02e460 100644
--- a/src/api2/admin/datastore.rs
+++ b/src/api2/admin/datastore.rs
@@ -1293,8 +1293,6 @@ pub fn catalog(
backup_id: String,
backup_time: i64,
filepath: String,
- _param: Value,
- _info: &ApiMethod,
rpcenv: &mut dyn RpcEnvironment,
) -> Result<Value, Error> {
let datastore = DataStore::lookup_datastore(&store)?;
diff --git a/src/api2/config/datastore.rs b/src/api2/config/datastore.rs
index 00009b74..3a3dc176 100644
--- a/src/api2/config/datastore.rs
+++ b/src/api2/config/datastore.rs
@@ -277,6 +277,7 @@ pub enum DeletableProperty {
},
)]
/// Update datastore config.
+#[allow(clippy::too_many_arguments)]
pub fn update_datastore(
name: String,
comment: Option<String>,
diff --git a/src/api2/config/remote.rs b/src/api2/config/remote.rs
index 28221358..446a2604 100644
--- a/src/api2/config/remote.rs
+++ b/src/api2/config/remote.rs
@@ -203,6 +203,7 @@ pub enum DeletableProperty {
},
)]
/// Update remote configuration.
+#[allow(clippy::too_many_arguments)]
pub fn update_remote(
name: String,
comment: Option<String>,
diff --git a/src/api2/config/sync.rs b/src/api2/config/sync.rs
index e7360051..00a8c0b3 100644
--- a/src/api2/config/sync.rs
+++ b/src/api2/config/sync.rs
@@ -279,6 +279,7 @@ pub enum DeletableProperty {
},
)]
/// Update sync job config.
+#[allow(clippy::too_many_arguments)]
pub fn update_sync_job(
id: String,
store: Option<String>,
diff --git a/src/api2/config/verify.rs b/src/api2/config/verify.rs
index 08a9e717..db5f4d83 100644
--- a/src/api2/config/verify.rs
+++ b/src/api2/config/verify.rs
@@ -215,6 +215,7 @@ pub enum DeletableProperty {
},
)]
/// Update verification job config.
+#[allow(clippy::too_many_arguments)]
pub fn update_verification_job(
id: String,
store: Option<String>,
diff --git a/src/api2/node/network.rs b/src/api2/node/network.rs
index d9c031ae..0dc321b8 100644
--- a/src/api2/node/network.rs
+++ b/src/api2/node/network.rs
@@ -213,6 +213,7 @@ pub fn read_interface(iface: String) -> Result<Value, Error> {
},
)]
/// Create network interface configuration.
+#[allow(clippy::too_many_arguments)]
pub fn create_interface(
iface: String,
autostart: Option<bool>,
@@ -477,6 +478,7 @@ pub enum DeletableProperty {
},
)]
/// Update network interface config.
+#[allow(clippy::too_many_arguments)]
pub fn update_interface(
iface: String,
autostart: Option<bool>,
diff --git a/src/api2/node/tasks.rs b/src/api2/node/tasks.rs
index 99470531..ff6ed726 100644
--- a/src/api2/node/tasks.rs
+++ b/src/api2/node/tasks.rs
@@ -425,6 +425,7 @@ fn stop_task(
},
)]
/// List tasks.
+#[allow(clippy::too_many_arguments)]
pub fn list_tasks(
start: u64,
limit: u64,
diff --git a/src/bin/pxar.rs b/src/bin/pxar.rs
index b2fe6d52..814b3346 100644
--- a/src/bin/pxar.rs
+++ b/src/bin/pxar.rs
@@ -112,6 +112,7 @@ fn extract_archive_from_reader<R: std::io::Read>(
},
)]
/// Extract an archive.
+#[allow(clippy::too_many_arguments)]
fn extract_archive(
archive: String,
pattern: Option<Vec<String>>,
diff --git a/src/client/backup_writer.rs b/src/client/backup_writer.rs
index 38953a45..01ea7704 100644
--- a/src/client/backup_writer.rs
+++ b/src/client/backup_writer.rs
@@ -57,6 +57,8 @@ impl BackupWriter {
Arc::new(Self { h2, abort, crypt_config, verbose })
}
+ // FIXME: extract into (flattened) parameter struct?
+ #[allow(clippy::too_many_arguments)]
pub async fn start(
client: HttpClient,
crypt_config: Option<Arc<CryptConfig>>,
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup 15/15] clippy: more misc fixes
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (13 preceding siblings ...)
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 14/15] clippy: allow api functions with many arguments Fabian Grünbichler
@ 2021-01-25 13:43 ` Fabian Grünbichler
2021-01-25 13:43 ` [pbs-devel] [PATCH proxmox-backup-qemu 1/2] use UploadOptions for uploading Blobs Fabian Grünbichler
` (2 subsequent siblings)
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
src/bin/proxmox-daily-update.rs | 9 +++------
src/bin/proxmox_backup_client/key.rs | 24 +++++-------------------
src/bin/proxmox_backup_client/mount.rs | 2 +-
src/bin/proxmox_backup_manager/user.rs | 4 ++--
src/rrd/mod.rs | 1 +
5 files changed, 12 insertions(+), 28 deletions(-)
diff --git a/src/bin/proxmox-daily-update.rs b/src/bin/proxmox-daily-update.rs
index 99f5152e..83c6b80c 100644
--- a/src/bin/proxmox-daily-update.rs
+++ b/src/bin/proxmox-daily-update.rs
@@ -63,11 +63,8 @@ fn main() {
let mut rpcenv = CliEnvironment::new();
rpcenv.set_auth_id(Some(String::from("root@pam")));
- match proxmox_backup::tools::runtime::main(do_update(&mut rpcenv)) {
- Err(err) => {
- eprintln!("error during update: {}", err);
- std::process::exit(1);
- },
- _ => (),
+ if let Err(err) = proxmox_backup::tools::runtime::main(do_update(&mut rpcenv)) {
+ eprintln!("error during update: {}", err);
+ std::process::exit(1);
}
}
diff --git a/src/bin/proxmox_backup_client/key.rs b/src/bin/proxmox_backup_client/key.rs
index ef3123bb..405cb818 100644
--- a/src/bin/proxmox_backup_client/key.rs
+++ b/src/bin/proxmox_backup_client/key.rs
@@ -315,22 +315,13 @@ fn change_passphrase(
},
)]
/// Print the encryption key's metadata.
-fn show_key(
- path: Option<String>,
- param: Value,
-) -> Result<(), Error> {
+fn show_key(path: Option<String>, param: Value) -> Result<(), Error> {
let path = match path {
Some(path) => PathBuf::from(path),
- None => {
- let path = find_default_encryption_key()?
- .ok_or_else(|| {
- format_err!("no encryption file provided and no default file found")
- })?;
- path
- }
+ None => find_default_encryption_key()?
+ .ok_or_else(|| format_err!("no encryption file provided and no default file found"))?,
};
-
let config: KeyConfig = serde_json::from_slice(&file_get_contents(path.clone())?)?;
let output_format = get_output_format(¶m);
@@ -442,13 +433,8 @@ fn paper_key(
) -> Result<(), Error> {
let path = match path {
Some(path) => PathBuf::from(path),
- None => {
- let path = find_default_encryption_key()?
- .ok_or_else(|| {
- format_err!("no encryption file provided and no default file found")
- })?;
- path
- }
+ None => find_default_encryption_key()?
+ .ok_or_else(|| format_err!("no encryption file provided and no default file found"))?,
};
let data = file_get_contents(&path)?;
diff --git a/src/bin/proxmox_backup_client/mount.rs b/src/bin/proxmox_backup_client/mount.rs
index 72ed9166..24100752 100644
--- a/src/bin/proxmox_backup_client/mount.rs
+++ b/src/bin/proxmox_backup_client/mount.rs
@@ -345,7 +345,7 @@ fn unmap(
let mut any = false;
for (backing, loopdev) in tools::fuse_loop::find_all_mappings()? {
let name = tools::systemd::unescape_unit(&backing)?;
- println!("{}:\t{}", loopdev.unwrap_or("(unmapped)".to_owned()), name);
+ println!("{}:\t{}", loopdev.unwrap_or_else(|| "(unmapped)".to_string()), name);
any = true;
}
if !any {
diff --git a/src/bin/proxmox_backup_manager/user.rs b/src/bin/proxmox_backup_manager/user.rs
index d68e9e81..6603db1b 100644
--- a/src/bin/proxmox_backup_manager/user.rs
+++ b/src/bin/proxmox_backup_manager/user.rs
@@ -133,7 +133,7 @@ fn list_permissions(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Val
let output_format = get_output_format(¶m);
let info = &api2::access::API_METHOD_LIST_PERMISSIONS;
- let mut data = match info.handler {
+ let data = match info.handler {
ApiHandler::Sync(handler) => (handler)(param, info, rpcenv)?,
_ => unreachable!(),
};
@@ -161,7 +161,7 @@ fn list_permissions(param: Value, rpcenv: &mut dyn RpcEnvironment) -> Result<Val
}
}
} else {
- format_and_print_result(&mut data, &output_format);
+ format_and_print_result(&data, &output_format);
}
Ok(Value::Null)
diff --git a/src/rrd/mod.rs b/src/rrd/mod.rs
index c09efebf..03e4c9de 100644
--- a/src/rrd/mod.rs
+++ b/src/rrd/mod.rs
@@ -1,3 +1,4 @@
+#[allow(clippy::module_inception)]
mod rrd;
pub use rrd::*;
mod cache;
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup-qemu 1/2] use UploadOptions for uploading Blobs
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (14 preceding siblings ...)
2021-01-25 13:43 ` [pbs-devel] [PATCH proxmox-backup 15/15] clippy: more misc fixes Fabian Grünbichler
@ 2021-01-25 13:43 ` Fabian Grünbichler
2021-01-25 13:43 ` [pbs-devel] [PATCH proxmox-backup-qemu 2/2] use new HttpClientOptions constructors Fabian Grünbichler
2021-01-26 9:44 ` [pbs-devel] applied series: [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Wolfgang Bumiller
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:43 UTC (permalink / raw)
To: pbs-devel
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
Notes:
needs corresponding proxmox-backup commit
src/commands.rs | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/src/commands.rs b/src/commands.rs
index 2f6eb0f..c63c4f7 100644
--- a/src/commands.rs
+++ b/src/commands.rs
@@ -93,7 +93,13 @@ pub(crate) async fn add_config(
let blob_name = format!("{}.blob", name);
- let stats = client.upload_blob_from_data(data, &blob_name, compress, crypt_mode == CryptMode::Encrypt).await?;
+ let options = UploadOptions {
+ compress,
+ encrypt: crypt_mode == CryptMode::Encrypt,
+ ..UploadOptions::default()
+ };
+
+ let stats = client.upload_blob_from_data(data, &blob_name, options).await?;
let mut guard = manifest.lock().unwrap();
guard.add_file(blob_name, stats.size, stats.csum, crypt_mode)?;
@@ -457,8 +463,13 @@ pub(crate) async fn finish_backup(
*key_fingerprint_guard = key_fingerprint;
}
+ let options = UploadOptions {
+ compress: true,
+ ..UploadOptions::default()
+ };
+
client
- .upload_blob_from_data(manifest.into_bytes(), MANIFEST_BLOB_NAME, true, false)
+ .upload_blob_from_data(manifest.into_bytes(), MANIFEST_BLOB_NAME, options)
.await?;
client.finish().await?;
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] [PATCH proxmox-backup-qemu 2/2] use new HttpClientOptions constructors
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (15 preceding siblings ...)
2021-01-25 13:43 ` [pbs-devel] [PATCH proxmox-backup-qemu 1/2] use UploadOptions for uploading Blobs Fabian Grünbichler
@ 2021-01-25 13:43 ` Fabian Grünbichler
2021-01-26 9:44 ` [pbs-devel] applied series: [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Wolfgang Bumiller
17 siblings, 0 replies; 19+ messages in thread
From: Fabian Grünbichler @ 2021-01-25 13:43 UTC (permalink / raw)
To: pbs-devel
and make password non-optional from the start.
Signed-off-by: Fabian Grünbichler <f.gruenbichler@proxmox.com>
---
Notes:
needs corresponding proxmox_backup commit
src/backup.rs | 7 ++++---
src/lib.rs | 8 +++++---
src/restore.rs | 7 ++++---
3 files changed, 13 insertions(+), 9 deletions(-)
diff --git a/src/backup.rs b/src/backup.rs
index b5e1263..e2062e7 100644
--- a/src/backup.rs
+++ b/src/backup.rs
@@ -107,9 +107,10 @@ impl BackupTask {
self.check_aborted()?;
let command_future = async {
- let options = HttpClientOptions::new()
- .fingerprint(self.setup.fingerprint.clone())
- .password(self.setup.password.clone());
+ let options = HttpClientOptions::new_non_interactive(
+ self.setup.password.clone(),
+ self.setup.fingerprint.clone(),
+ );
let http = HttpClient::new(&self.setup.host, self.setup.port, &self.setup.auth_id, options)?;
let writer = BackupWriter::start(
diff --git a/src/lib.rs b/src/lib.rs
index b755014..fd7c064 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -134,7 +134,7 @@ pub(crate) struct BackupSetup {
pub backup_type: String,
pub backup_id: String,
pub backup_time: i64,
- pub password: Option<String>,
+ pub password: String,
pub keyfile: Option<std::path::PathBuf>,
pub key_password: Option<String>,
pub fingerprint: Option<String>,
@@ -222,7 +222,8 @@ pub extern "C" fn proxmox_backup_new(
let backup_id = tools::utf8_c_string(backup_id)?
.ok_or_else(|| format_err!("backup_id must not be NULL"))?;
- let password = tools::utf8_c_string(password)?;
+ let password = tools::utf8_c_string(password)?
+ .ok_or_else(|| format_err!("password must not be NULL"))?;
let keyfile = tools::utf8_c_string(keyfile)?.map(std::path::PathBuf::from);
let key_password = tools::utf8_c_string(key_password)?;
let fingerprint = tools::utf8_c_string(fingerprint)?;
@@ -701,7 +702,8 @@ pub extern "C" fn proxmox_restore_new(
let backup_id = snapshot.group().backup_id().to_owned();
let backup_time = snapshot.backup_time();
- let password = tools::utf8_c_string(password)?;
+ let password = tools::utf8_c_string(password)?
+ .ok_or_else(|| format_err!("password must not be null"))?;
let keyfile = tools::utf8_c_string(keyfile)?.map(std::path::PathBuf::from);
let key_password = tools::utf8_c_string(key_password)?;
let fingerprint = tools::utf8_c_string(fingerprint)?;
diff --git a/src/restore.rs b/src/restore.rs
index 1cc99a6..0790d7f 100644
--- a/src/restore.rs
+++ b/src/restore.rs
@@ -75,9 +75,10 @@ impl RestoreTask {
pub async fn connect(&self) -> Result<libc::c_int, Error> {
- let options = HttpClientOptions::new()
- .fingerprint(self.setup.fingerprint.clone())
- .password(self.setup.password.clone());
+ let options = HttpClientOptions::new_non_interactive(
+ self.setup.password.clone(),
+ self.setup.fingerprint.clone(),
+ );
let http = HttpClient::new(&self.setup.host, self.setup.port, &self.setup.auth_id, options)?;
let client = BackupReader::start(
--
2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
* [pbs-devel] applied series: [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
` (16 preceding siblings ...)
2021-01-25 13:43 ` [pbs-devel] [PATCH proxmox-backup-qemu 2/2] use new HttpClientOptions constructors Fabian Grünbichler
@ 2021-01-26 9:44 ` Wolfgang Bumiller
17 siblings, 0 replies; 19+ messages in thread
From: Wolfgang Bumiller @ 2021-01-26 9:44 UTC (permalink / raw)
To: Fabian Grünbichler; +Cc: pbs-devel
applied series
On Mon, Jan 25, 2021 at 02:42:45PM +0100, Fabian Grünbichler wrote:
> various parameter/types refactorings to simplify function
> signatures/return types/...
>
> I am grateful for suggestions on better names ;)
>
> I tried to order/group the patches so that they also apply
> individually/as sub-groups.
>
> with all of these, we are now down to some very recently touched files
> with trivial fixes that I didn't want to change since I suspected them
> to be still under development, and one missing docs lint:
>
> warning: unsafe function's docs miss `# Safety` section
> --> src/tools/fs.rs:78:5
> |
> 78 | / pub unsafe fn file_name_utf8_unchecked(&self) -> &str {
> 79 | | std::str::from_utf8_unchecked(self.file_name().to_bytes())
> 80 | | }
> | |_____^
>
> proxmox-backup:
> report: type-alias function call tuple
> broadcast_future: refactor broadcast/future binding
> client: refactor catalog upload spawning
> allow complex Futures in tower_service impl
> async index reader: typedef ReadFuture
> systemd/time: extract Time/DateSpec structs
> client: factor out UploadOptions
> pxar: typedef on_error as ErrorHandler
> pxar: factor out PxarCreateOptions
> pxar: extract PxarExtractOptions
> authid: make Tokenname(Ref) derive Eq
> derive/impl and use Default for some structs
> verify: factor out common parameters
> clippy: allow api functions with many arguments
> clippy: more misc fixes
>
> examples/download-speed.rs | 2 +-
> examples/upload-speed.rs | 2 +-
> src/api2/access/acl.rs | 1 +
> src/api2/access/tfa.rs | 1 +
> src/api2/access/user.rs | 1 +
> src/api2/admin/datastore.rs | 19 +--
> src/api2/backup/environment.rs | 10 +-
> src/api2/config/datastore.rs | 1 +
> src/api2/config/remote.rs | 5 +-
> src/api2/config/sync.rs | 1 +
> src/api2/config/verify.rs | 1 +
> src/api2/node/network.rs | 2 +
> src/api2/node/tasks.rs | 1 +
> src/api2/types/userid.rs | 52 +-------
> src/backup/async_index_reader.rs | 4 +-
> src/backup/prune.rs | 1 +
> src/backup/verify.rs | 174 +++++++++++--------------
> src/bin/proxmox-backup-client.rs | 162 +++++++++++++----------
> src/bin/proxmox-daily-update.rs | 9 +-
> src/bin/proxmox_backup_client/key.rs | 24 +---
> src/bin/proxmox_backup_client/mount.rs | 2 +-
> src/bin/proxmox_backup_manager/user.rs | 4 +-
> src/bin/pxar.rs | 54 ++++----
> src/client.rs | 11 +-
> src/client/backup_writer.rs | 46 ++++---
> src/client/http_client.rs | 38 ++++--
> src/client/pull.rs | 4 +-
> src/client/pxar_backup_stream.rs | 28 +---
> src/config/acl.rs | 8 +-
> src/config/network.rs | 2 +-
> src/pxar/create.rs | 28 +++-
> src/pxar/extract.rs | 24 ++--
> src/pxar/mod.rs | 4 +-
> src/rrd/mod.rs | 1 +
> src/server/h2service.rs | 5 +-
> src/server/report.rs | 6 +-
> src/server/rest.rs | 3 +-
> src/server/verify_job.rs | 3 +-
> src/tools/broadcast_future.rs | 38 ++----
> src/tools/http.rs | 5 +-
> src/tools/systemd/parse_time.rs | 41 ++++--
> tests/catar.rs | 10 +-
> 42 files changed, 414 insertions(+), 424 deletions(-)
>
> proxmox-backup-qemu:
> use UploadOptions for uploading Blobs
> use new HttpClientOptions constructors
>
> src/backup.rs | 7 ++++---
> src/commands.rs | 15 +++++++++++++--
> src/lib.rs | 8 +++++---
> src/restore.rs | 7 ++++---
> 4 files changed, 26 insertions(+), 11 deletions(-)
>
> --
> 2.20.1
^ permalink raw reply [flat|nested] 19+ messages in thread
end of thread, other threads:[~2021-01-26 9:45 UTC | newest]
Thread overview: 19+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-01-25 13:42 [pbs-devel] [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 01/15] report: type-alias function call tuple Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 02/15] broadcast_future: refactor broadcast/future binding Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 03/15] client: refactor catalog upload spawning Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 04/15] allow complex Futures in tower_service impl Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 05/15] async index reader: typedef ReadFuture Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 06/15] systemd/time: extract Time/DateSpec structs Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 07/15] client: factor out UploadOptions Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 08/15] pxar: typedef on_error as ErrorHandler Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 09/15] pxar: factor out PxarCreateOptions Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 10/15] pxar: extract PxarExtractOptions Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 11/15] authid: make Tokenname(Ref) derive Eq Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 12/15] derive/impl and use Default for some structs Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 13/15] verify: factor out common parameters Fabian Grünbichler
2021-01-25 13:42 ` [pbs-devel] [PATCH proxmox-backup 14/15] clippy: allow api functions with many arguments Fabian Grünbichler
2021-01-25 13:43 ` [pbs-devel] [PATCH proxmox-backup 15/15] clippy: more misc fixes Fabian Grünbichler
2021-01-25 13:43 ` [pbs-devel] [PATCH proxmox-backup-qemu 1/2] use UploadOptions for uploading Blobs Fabian Grünbichler
2021-01-25 13:43 ` [pbs-devel] [PATCH proxmox-backup-qemu 2/2] use new HttpClientOptions constructors Fabian Grünbichler
2021-01-26 9:44 ` [pbs-devel] applied series: [PATCH proxmox-backup(-qemu) 00/17] clippy refactorings Wolfgang Bumiller
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.