1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
//! Marina is a dataset manager for robotics built to organize, share, and discover datasets and bags across teams and storage backends.
//!
//! ## Add the dependency
//!
//! ```toml
//! [dependencies]
//! marina = "0.2"
//! tokio = { version = "1", features = ["rt", "macros"] }
//! ```
//!
//! Marina's async methods require a **tokio** runtime. A single-threaded runtime
//! (`#[tokio::main(flavor = "current_thread")]`) is sufficient.
//!
//! ## Resolve a dataset
//!
//! [`Marina::resolve_target`] checks whether a dataset is already cached, available locally,
//! or only reachable via a remote registry.
//!
//! ```no_run
//! use marina::{Marina, ResolveResult};
//!
//! #[tokio::main]
//! async fn main() -> anyhow::Result<()> {
//! let marina = Marina::load()?;
//!
//! match marina.resolve_target("outdoor-run:v2", None).await? {
//! ResolveResult::LocalPath(p) | ResolveResult::Cached(p) => {
//! println!("ready at {}", p.display());
//! }
//! ResolveResult::RemoteAvailable { bag, registry, .. } => {
//! println!("remote: {bag} in {registry}");
//! }
//! ResolveResult::Ambiguous { candidates } => {
//! println!("found in {} registries", candidates.len());
//! }
//! }
//! Ok(())
//! }
//! ```
//!
//! Pass a registry name as the second argument to restrict the search:
//!
//! ```no_run
//! # use marina::Marina;
//! # #[tokio::main] async fn main() -> anyhow::Result<()> {
//! # let marina = Marina::load()?;
//! marina.resolve_target("outdoor-run:v2", Some("team-ssh")).await?;
//! # Ok(()) }
//! ```
//!
//! ## Pull a dataset
//!
//! [`Marina::pull_exact`] downloads a dataset if it is not already cached and returns the local path:
//!
//! ```no_run
//! use marina::{Marina, BagRef};
//!
//! #[tokio::main]
//! async fn main() -> anyhow::Result<()> {
//! let mut marina = Marina::load()?;
//! let bag: BagRef = "outdoor-run:v2".parse()?;
//! let path = marina.pull_exact(&bag, None).await?;
//! println!("cached at {}", path.display());
//! Ok(())
//! }
//! ```
//!
//! ## Pull with progress reporting
//!
//! Implement [`ProgressSink`] to receive phase events during download and decompression:
//!
//! ```no_run
//! use marina::{Marina, BagRef, ProgressEvent, ProgressReporter, ProgressSink};
//!
//! struct MyProgress;
//!
//! impl ProgressSink for MyProgress {
//! fn emit(&mut self, event: ProgressEvent) {
//! println!("[{}] {}", event.phase, event.message);
//! }
//! }
//!
//! #[tokio::main]
//! async fn main() -> anyhow::Result<()> {
//! let mut marina = Marina::load()?;
//! let bag: BagRef = "outdoor-run:v2".parse()?;
//!
//! let mut sink = MyProgress;
//! let mut reporter = ProgressReporter::new(&mut sink);
//! let path = marina.pull_exact_with_progress(&bag, None, &mut reporter).await?;
//! println!("done: {}", path.display());
//! Ok(())
//! }
//! ```
//!
//! [`WriterProgress`] is a built-in sink that writes human-readable output to any [`std::io::Write`]:
//!
//! ```no_run
//! use marina::{Marina, BagRef, ProgressReporter, WriterProgress};
//!
//! #[tokio::main]
//! async fn main() -> anyhow::Result<()> {
//! let mut marina = Marina::load()?;
//! let bag: BagRef = "outdoor-run:v2".parse()?;
//!
//! let mut stdout = std::io::stdout();
//! let mut sink = WriterProgress::new(&mut stdout);
//! let mut reporter = ProgressReporter::new(&mut sink);
//! marina.pull_exact_with_progress(&bag, None, &mut reporter).await?;
//! Ok(())
//! }
//! ```
pub use ;
/// Parsed bag reference like `namespace/name:tag1:tag2[attachment.txt]`.
pub use BagRef;
/// Progress primitives to receive phase-based feedback from push/pull operations.
pub use ;