Skip to main content

zenith_cli/commands/workspace/
bundle.rs

1//! Logic for `zenith workspace bundle` and `zenith workspace unbundle`.
2
3use std::path::Path;
4
5use zenith_session::adapter::OsFs;
6use zenith_session::{StorePaths, bundle, resolve_data_dir, unbundle};
7
8use crate::commands::workspace::scratch::open_store;
9use crate::history::read_doc_id;
10
11// ── bundle ────────────────────────────────────────────────────────────────────
12
13/// Pack the session store for the document at `doc_path` into `out_path`.
14///
15/// Resolves the real data directory automatically. Use [`bundle_doc_in`] in
16/// tests where you want a tempdir-rooted store.
17pub fn bundle_doc(doc_path: &Path, out_path: &Path) -> Result<String, String> {
18    let paths = open_store()?;
19    bundle_doc_in(&paths, doc_path, out_path)
20}
21
22/// Testable variant with an explicit store root.
23pub fn bundle_doc_in(
24    paths: &StorePaths,
25    doc_path: &Path,
26    out_path: &Path,
27) -> Result<String, String> {
28    let doc_id = read_doc_id(doc_path)?;
29    let fs = OsFs;
30    let bytes = bundle(&fs, paths, &doc_id).map_err(|e| e.message)?;
31    std::fs::write(out_path, &bytes)
32        .map_err(|e| format!("cannot write '{}': {e}", out_path.display()))?;
33    Ok(format!("bundled {} → {}", doc_id, out_path.display()))
34}
35
36// ── unbundle ──────────────────────────────────────────────────────────────────
37
38/// Restore a document's session store from the `.zenithbundle` at `bundle_path`.
39///
40/// Resolves the real data directory automatically. Use [`unbundle_doc_in`] in
41/// tests where you want a tempdir-rooted store.
42pub fn unbundle_doc(bundle_path: &Path) -> Result<String, String> {
43    let data_dir = resolve_data_dir().map_err(|e| e.message)?;
44    let paths = StorePaths::new(data_dir);
45    unbundle_doc_in(&paths, bundle_path)
46}
47
48/// Testable variant with an explicit store root.
49pub fn unbundle_doc_in(paths: &StorePaths, bundle_path: &Path) -> Result<String, String> {
50    let bytes = std::fs::read(bundle_path)
51        .map_err(|e| format!("cannot read '{}': {e}", bundle_path.display()))?;
52    let fs = OsFs;
53    let doc_id = unbundle(&fs, paths, &bytes).map_err(|e| e.message)?;
54    Ok(doc_id)
55}