Skip to main content

devset_core/
lib.rs

1//! Versioned file bundles, applied to a directory and updated without losing local edits.
2//!
3//! A *profile* is a directory of files in a *source*, a git repository or a local directory; a
4//! *target* is a directory that names its sources and applies profiles from them as *layers*.
5//! Profiles compose as crates do: a profile requires others by name, and offers features that add
6//! files, parts, requirements and features of what it requires; an entry applies only when its
7//! gates hold. devset records what it wrote in the target's `.devset/`, so a later update tells a
8//! local edit from a change the profile made: the edit is kept, and merged with the change where
9//! the file's [`Policy`](profile::Policy) says so. A profile owns a whole file, or a part of one
10//! its [`Scope`](profile::Scope) names: the keys its payload defines, or a marked block.
11//!
12//! # Applying a profile
13//!
14//! Every operation is a prefix of one chain, and only [`commit`](commit()) writes:
15//!
16//! ```
17//! use std::fs;
18//!
19//! use devset_core::source::Source;
20//! use devset_core::target::LayerSpec;
21//! use devset_core::{Cache, Mode, Refresh, Target, commit, plan, resolve, survey};
22//!
23//! let dir = camino_tempfile::tempdir()?;
24//! let root = dir.path();
25//! # fs::create_dir_all(root.join("house/base/files"))?;
26//! # fs::write(root.join("house/base/profile.toml"), "[profile]\nname = \"base\"\n\n[files.\".editorconfig\"]\n")?;
27//! # fs::write(root.join("house/base/files/.editorconfig"), "root = true\n")?;
28//! # fs::create_dir(root.join("repo"))?;
29//! let mut target = Target::open_or_new(&root.join("repo"))?;
30//! target.add_source("house".parse()?, Source::Dir("../house".into()))?;
31//! target.add_layer(LayerSpec::new("house/base".parse()?))?;
32//!
33//! let resolved = resolve(&target, &Cache::at(root.join("cache")), Refresh::None)?; // read, compose
34//! let survey = survey(resolved, &target)?; // compare with the disk
35//! let plan = plan(survey, Mode::Apply, &target)?; // decide, merge
36//! commit(plan, &target)?; // write, state last
37//!
38//! let applied = fs::read_to_string(root.join("repo/.editorconfig"))?;
39//! assert_eq!(applied, "root = true\n", "the profile's file, in the target");
40//! # Ok::<(), Box<dyn std::error::Error>>(())
41//! ```
42//!
43//! # Updating
44//!
45//! [`Refresh::All`] moves every source to what its ref names now; the rest of the chain is the
46//! same. A `merge` file then merges its local edits with the profile's new version. A conflict
47//! leaves the run unfinished, waiting in `.devset/conflicts/`: a chain under
48//! [`Mode::Continue`] installs the fix, or a [`Rollback`] takes the whole run back.
49//!
50//! # Types
51//!
52//! - [`Target`]: the directory devset manages, and what its `.devset/` records.
53//! - [`Resolved`]: the target's layers composed, one provider per path.
54//! - [`Survey`]: every managed path as the profile wants it, as recorded, and as on disk.
55//! - [`Plan`]: what committing does to each path.
56//! - [`Rollback`]: an unfinished run, and what taking it back restores.
57//! - [`Error`]: why any of it did not go through, one type per domain.
58//!
59//! The files people write have modules of their own: [`profile`] for `profile.toml`,
60//! [`collection`] for a source's profiles, [`target`] for `.devset/config.toml`, and [`source`]
61//! for where profiles come from; [`name`] holds the names they use.
62
63extern crate alloc;
64
65pub mod collection;
66pub mod name;
67pub mod plan;
68pub mod profile;
69pub mod resolve;
70pub mod source;
71pub mod survey;
72pub mod target;
73
74mod commit;
75mod digest;
76mod errors;
77mod format;
78mod gate;
79mod git;
80mod graph;
81mod merge;
82mod part;
83mod path;
84mod rollback;
85mod settings;
86mod tree;
87mod vars;
88
89pub use crate::commit::commit;
90pub use crate::errors::{
91    Error, MergeError, NameError, ParseError, PathError, ProfileError, Result, SourceError,
92    TargetError, VarError,
93};
94pub use crate::path::RelPath;
95#[doc(inline)]
96pub use crate::plan::{Mode, Plan, plan};
97#[doc(inline)]
98pub use crate::resolve::{Refresh, Resolved, resolve};
99pub use crate::rollback::{Revert, Rollback};
100#[doc(inline)]
101pub use crate::source::Cache;
102#[doc(inline)]
103pub use crate::survey::{Survey, survey};
104#[doc(inline)]
105pub use crate::target::Target;
106
107/// This build's version, which a profile's `devset` requirement is checked against.
108pub const VERSION: &str = env!("CARGO_PKG_VERSION");