Repository navigation
Expand file tree
/
Copy pathcontext.rs
More file actions
113 lines (101 loc) · 4.15 KB
/
Copy pathcontext.rs
File metadata and controls
113 lines (101 loc) · 4.15 KB
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
//! The project a command reads, loaded lazily and at most once per run:
//! the patch stores ([`LoadedLedgers`]: manifest + both ledgers), the lock
//! set (the lockfile inventory and its refused npm layouts) and the
//! lockfile wiring discovery. `scan`, `vendor`, `vex`, `list` and `get`
//! read these through one [`ProjectContext`] instead of each re-loading
//! and re-merging them its own way.
//!
//! The lock set and the discovery read `--cwd` through one
//! [`DiskSnapshot`], so each lock and config file is read once and both see
//! the same bytes.
//!
//! Everything here is a read-only snapshot. A command that writes a store
//! under the apply lock (the hosted engine, rollback, remove) re-loads it
//! under that lock instead of trusting a pre-lock snapshot, and an embedded
//! `--vex` after the writes loads its own inputs.
use std::path::PathBuf;
use socket_patch_core::ledgers::{Ledgers, LoadedLedgers};
use socket_patch_core::vendor::lock_inventory::{
DiskSnapshot, LockfileEntry, ProjectView, ReadSet, UnsupportedNpmLayout,
};
use socket_patch_core::vex::discover::Discovery;
use tokio::sync::OnceCell;
use crate::args::GlobalArgs;
/// The project's lockfile inventory and the npm layouts it refused.
pub(crate) struct LockSet {
pub(crate) entries: Vec<LockfileEntry>,
pub(crate) unsupported: Vec<UnsupportedNpmLayout>,
}
pub(crate) struct ProjectContext<'a> {
pub(crate) common: &'a GlobalArgs,
/// Where the ledgers live: the manifest's project (see
/// [`GlobalArgs::project_root`]).
pub(crate) root: PathBuf,
snapshot: DiskSnapshot<'a>,
ledgers: OnceCell<LoadedLedgers>,
locks: OnceCell<LockSet>,
/// The discovery, with the paths it read and their fingerprints
/// (`None` when they cannot cover what it read; see
/// [`DiskSnapshot::end_recording`]).
discovery: OnceCell<(Discovery, Option<ReadSet>)>,
}
impl<'a> ProjectContext<'a> {
pub(crate) fn new(common: &'a GlobalArgs) -> Self {
Self::rooted(common, common.project_root())
}
/// A context whose ledgers load from `root` (commands that read the
/// ledgers of `--cwd` rather than of the manifest's project).
pub(crate) fn rooted(common: &'a GlobalArgs, root: PathBuf) -> Self {
Self {
common,
root,
snapshot: DiskSnapshot::tracked(&common.cwd),
ledgers: OnceCell::new(),
locks: OnceCell::new(),
discovery: OnceCell::new(),
}
}
/// The three stores, each with its own load outcome.
pub(crate) async fn loaded(&self) -> &LoadedLedgers {
self.ledgers
.get_or_init(|| async {
LoadedLedgers::load(&self.root, &self.common.resolved_manifest_path()).await
})
.await
}
/// The readable stores as one view (a failed store reads as absent).
pub(crate) async fn ledgers(&self) -> Ledgers<'_> {
self.loaded().await.view()
}
/// The lockfile inventory of `--cwd`.
pub(crate) async fn locks(&self) -> &LockSet {
self.locks
.get_or_init(|| async {
let (entries, unsupported) =
socket_patch_core::vendor::lock_inventory::inventory_project_diagnosed_in(
&ProjectView::Snapshot(&self.snapshot),
)
.await;
LockSet {
entries,
unsupported,
}
})
.await
}
/// The lockfile wiring discovery of `--cwd` ([`super::discover_wiring`]).
pub(crate) async fn discovery(&self) -> &Discovery {
&self.recorded_discovery().await.0
}
/// [`Self::discovery`] with the read set that tells whether it still
/// describes the project (stats only; see [`ReadSet::unchanged`]).
pub(crate) async fn recorded_discovery(&self) -> &(Discovery, Option<ReadSet>) {
self.discovery
.get_or_init(|| async {
self.snapshot.begin_recording();
let discovery = super::discover_wiring_in(self.common, &self.snapshot).await;
(discovery, self.snapshot.end_recording())
})
.await
}
}