lds_pack/lib.rs
1//! Pack a whole project into one portable archive, and put it back.
2//!
3//! An `lds` pack is not a source tarball and not a `git bundle`. It carries the
4//! project as it actually exists on the machine:
5//!
6//! - the **`.git` directory itself**, copied wholesale — so stashes, the
7//! reflog, local-only branches, and objects no ref points at all come along.
8//! A bundle is assembled from an enumerated set of refs, and everything
9//! outside that set is quietly left behind; copying the directory means there
10//! is no set to enumerate and nothing to forget.
11//! - the **untracked local state** that ordinarily never leaves the machine:
12//! a `workspace/` tree, journal databases, sandbox snapshots, agent and
13//! editor dotfiles.
14//!
15//! Three things are treated specially:
16//!
17//! | | treatment |
18//! |---|---|
19//! | secrets (`.env`, `*.pem`, …) | **not packed**, reported instead — moving credentials is the operator's own business |
20//! | caches (`target/`, `node_modules/`, …) | **not packed**, recorded — regenerable by definition |
21//! | symlinks | packed as links, never followed; reported so a restore elsewhere can name what dangles |
22//!
23//! A symlink is reported because it is a problem: it breaks when the project
24//! lands somewhere else. The exception is a directory that is *meant* to be
25//! links — a shared dotfile tree, say — where the operator already knows and
26//! the entries are noise hiding the links that do need attention. Name such a
27//! path in `[pack] no_link_report` and its links are packed without being
28//! reported. There is no default and no directory name this crate treats as
29//! special.
30//!
31//! Every rule that fired is named in the manifest, including that one. The
32//! reports exist to be acted on and scripted against, so a rule that quietly
33//! changed what a report contains would send the reader after the wrong thing;
34//! `no_link_report_applied` keeps "no links here" and "links hidden here"
35//! distinguishable, and `kept_over_secret` names any file a `keep` glob carried
36//! past the secret list.
37//!
38//! # Example
39//!
40//! ```no_run
41//! use lds_pack::{CreateOptions, RestoreOptions, create, restore};
42//!
43//! let report = create(&CreateOptions::new("/path/to/proj", "proj.pack", "0.13.3"))?;
44//! println!("packed {} files", report.manifest.stats.file_count);
45//!
46//! let restored = restore(&RestoreOptions::new("proj.pack", "/tmp/proj"))?;
47//! if restored.needs_attention() {
48//! println!("{} symlinks dangle here", restored.dangling_symlinks.len());
49//! }
50//! # Ok::<(), lds_pack::PackError>(())
51//! ```
52
53mod contained;
54pub mod create;
55pub mod error;
56pub mod inspect;
57pub mod manifest;
58pub mod restore;
59pub mod rules;
60pub mod scan;
61
62pub use create::{CreateOptions, CreateReport, DEFAULT_COMPRESSION_LEVEL, create};
63pub use error::PackError;
64pub use inspect::{inspect, list_payload_paths, verify};
65pub use manifest::{
66 CacheRecord, KeptOverSecret, MANIFEST_NAME, Manifest, PACK_FORMAT_VERSION, SkipRecord, Stats,
67 SymlinkRecord, WorktreeOrigin, WorktreeRecord,
68};
69pub use restore::{HardLinkRecord, RestoreOptions, RestoreReport, WorktreeConflict, restore};
70pub use rules::{DEFAULT_CACHE_DIRS, DEFAULT_KEEP, DEFAULT_SECRET_GLOBS, PackRules, RuleOverrides};
71pub use scan::{Scan, scan, scan_with};