Skip to content

Commit dea655c

Browse files
Make sure metadata is updated along with env.
Signed-off-by: victor.linroth.sensmetry <victor.linroth@sensmetry.com>
1 parent b5b23a2 commit dea655c

10 files changed

Lines changed: 100 additions & 59 deletions

File tree

core/src/commands/sources.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -79,14 +79,14 @@ pub fn do_sources_local_src_project_no_deps(
7979
project: &LocalSrcProject,
8080
include_index: bool,
8181
) -> Result<Vec<Utf8PathBuf>, LocalSourcesError> {
82-
let unix_srcs = do_sources_project_no_deps(project, include_index)?;
82+
let unix_sources = do_sources_project_no_deps(project, include_index)?;
8383

84-
let srcs: Result<Vec<_>, _> = unix_srcs
84+
let sources: Result<Vec<_>, _> = unix_sources
8585
.iter()
8686
.map(|path| project.get_source_path(path))
8787
.collect();
8888

89-
Ok(srcs?)
89+
Ok(sources?)
9090
}
9191

9292
/// Transitively resolve a list of usages (typically the usages of some project)

core/src/env/local_directory/metadata.rs

Lines changed: 26 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,9 @@ impl Lock {
5959
metadata.projects.push(EnvProject {
6060
publisher: project.publisher,
6161
name: project.name,
62-
identifiers: project.identifiers,
6362
version: project.version,
6463
path,
64+
identifiers: project.identifiers,
6565
usages,
6666
editable: false,
6767
files: None,
@@ -81,9 +81,9 @@ impl Lock {
8181
metadata.projects.push(EnvProject {
8282
publisher: project.publisher,
8383
name: project.name,
84-
identifiers: project.identifiers,
8584
version: project.version,
8685
path: editable.as_str().into(),
86+
identifiers: project.identifiers,
8787
usages,
8888
editable: true,
8989
files: Some(files),
@@ -98,6 +98,7 @@ impl Lock {
9898
#[derive(Debug, Deserialize)]
9999
pub struct EnvMetadata {
100100
pub version: String,
101+
#[serde(rename = "project", skip_serializing_if = "Vec::is_empty", default)]
101102
pub projects: Vec<EnvProject>,
102103
}
103104

@@ -189,6 +190,17 @@ impl EnvMetadata {
189190
}
190191
}
191192

193+
pub fn remove_project<S: AsRef<str>, V: AsRef<str>>(&mut self, iri: S, version: Option<V>) {
194+
if let Some(v) = version {
195+
self.projects.retain(|p| {
196+
p.version != v.as_ref() || !p.identifiers.iter().any(|i| i == iri.as_ref())
197+
});
198+
} else {
199+
self.projects
200+
.retain(|p| !p.identifiers.iter().any(|i| i == iri.as_ref()));
201+
}
202+
}
203+
192204
/// Add `LocalSrcProject` to env. Must have `nominal_path` set.
193205
pub fn add_local_project(
194206
&mut self,
@@ -202,11 +214,11 @@ impl EnvMetadata {
202214
let project = EnvProject {
203215
publisher: info.publisher,
204216
name: Some(info.name),
205-
identifiers,
206217
version: info.version,
207218
path: project
208219
.nominal_path
209220
.expect("expected nominal path for project"),
221+
identifiers,
210222
usages: info.usage.into_iter().map(|u| u.resource).collect(),
211223
editable,
212224
files: None,
@@ -230,24 +242,27 @@ pub struct EnvProject {
230242
pub publisher: Option<String>,
231243
/// Name of the project. Intended for display purposes.
232244
pub name: Option<String>,
233-
/// List of identifiers (IRIs) used for the project.
234-
/// The first identifier is to. be considered the canonical
235-
/// identifier, and if the project is not `editable` this
236-
/// is the IRI it is installed as. The rest are considered
237-
/// as aliases. Can only be empty for `editable` projects.
238-
pub identifiers: Vec<String>,
239245
/// Version of the project.
240246
pub version: String,
241247
/// Path to the root directory of the project.
242248
/// If the project is not `editable` this should be relative
243249
/// to the env directory and otherwise it should be relative
244250
/// to the workspace root.
245251
pub path: Utf8PathBuf,
252+
/// List of identifiers (IRIs) used for the project.
253+
/// The first identifier is to. be considered the canonical
254+
/// identifier, and if the project is not `editable` this
255+
/// is the IRI it is installed as. The rest are considered
256+
/// as aliases. Can only be empty for `editable` projects.
257+
#[serde(skip_serializing_if = "Vec::is_empty", default)]
258+
pub identifiers: Vec<String>,
246259
/// Usages of the project. Intended for tools needing to
247260
/// track the interdependence of project in the environment.
261+
#[serde(skip_serializing_if = "Vec::is_empty", default)]
248262
pub usages: Vec<String>,
249263
/// Indicator of wether the project is fully installed in
250264
/// the environment or located elsewhere.
265+
#[serde(skip_serializing_if = "bool::is_false", default)]
251266
pub editable: bool,
252267
/// In case of an `editable` project these are the files
253268
/// belonging to the project. Intended for tools that
@@ -266,14 +281,14 @@ impl EnvProject {
266281
if let Some(name) = &self.name {
267282
table.insert("name", value(name));
268283
}
284+
table.insert("version", value(&self.version));
285+
table.insert("path", value(self.path.as_str()));
269286
if !self.identifiers.is_empty() {
270287
table.insert(
271288
"identifiers",
272289
value(multiline_array(self.identifiers.iter())),
273290
);
274291
}
275-
table.insert("version", value(&self.version));
276-
table.insert("path", value(self.path.as_str()));
277292
if !self.usages.is_empty() {
278293
table.insert("usages", value(multiline_array(self.usages.iter())));
279294
}

core/src/env/local_directory/utils.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@ pub fn try_remove_files<P: AsRef<Utf8Path>, I: Iterator<Item = P>>(
8080
moved.push(path.to_path_buf());
8181
}
8282
Err(cause) => {
83-
// NOTE: This dance is to bypass the fact that std::io::error is not Clone-eable...
83+
// NOTE: This dance is to bypass the fact that std::io::error is not cloneable...
8484
let mut catastrophic_error = None;
8585
for (j, recover) in moved.iter().enumerate() {
8686
if let Err(err) = move_fs_item(tempdir.path().join(j.to_string()), recover) {

sysand/src/commands/add.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,6 @@ fn resolve_deps<P: AsRef<Utf8Path>, Policy: HTTPAuthentication>(
275275
command_sync(
276276
&lock,
277277
project_root,
278-
true,
279278
&mut env,
280279
client,
281280
&provided_iris,

sysand/src/commands/clone.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -142,7 +142,6 @@ pub fn command_clone<Policy: HTTPAuthentication>(
142142
command_sync(
143143
&lock,
144144
&project.inner().project_path,
145-
true,
146145
&mut env,
147146
client,
148147
&provided_iris,

sysand/src/commands/env.rs

Lines changed: 41 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use sysand_core::{
1313
commands::{env::do_env_local_dir, lock::LockOutcome},
1414
config::Config,
1515
context::ProjectContext,
16-
env::local_directory::LocalDirectoryEnvironment,
16+
env::local_directory::{LocalDirectoryEnvironment, metadata::load_env_metadata},
1717
lock::Lock,
1818
model::InterchangeProjectUsage,
1919
project::{
@@ -120,7 +120,7 @@ pub fn command_env_install<Policy: HTTPAuthentication>(
120120
// TODO: don't use different root project resolution
121121
// mechanisms depending on no_deps
122122
if no_deps {
123-
let (_version, storage) =
123+
let (version, storage) =
124124
crate::commands::clone::get_project_version(&iri, version, &resolver)?;
125125
sysand_core::commands::env::do_env_install_project(
126126
&iri,
@@ -129,6 +129,7 @@ pub fn command_env_install<Policy: HTTPAuthentication>(
129129
allow_overwrite,
130130
allow_multiple,
131131
)?;
132+
add_single_env_project(iri, version.to_string(), env)?;
132133
} else {
133134
let usages = vec![InterchangeProjectUsage {
134135
resource: fluent_uri::Iri::from_str(iri.as_ref())?,
@@ -159,7 +160,6 @@ pub fn command_env_install<Policy: HTTPAuthentication>(
159160
command_sync(
160161
&lock,
161162
project_root,
162-
false,
163163
&mut env,
164164
client,
165165
&provided_iris,
@@ -231,14 +231,14 @@ pub fn command_env_install_path<Policy: HTTPAuthentication>(
231231
Some(config.index_urls(index, vec![DEFAULT_INDEX_URL.to_string()], default_index)?)
232232
};
233233

234-
if let Some(version) = version {
235-
let project_version = project
236-
.get_info()?
237-
.ok_or_else(|| anyhow!("missing project info"))?
238-
.version;
239-
if version != project_version {
240-
bail!("given version {version} does not match project version {project_version}")
241-
}
234+
let project_version = project
235+
.get_info()?
236+
.ok_or_else(|| anyhow!("missing project info"))?
237+
.version;
238+
if let Some(version) = version
239+
&& version != project_version
240+
{
241+
bail!("given version {version} does not match project version {project_version}")
242242
}
243243

244244
// TODO: Fix this hack. Currently installing manually then turning project into Editable to
@@ -296,24 +296,50 @@ pub fn command_env_install_path<Policy: HTTPAuthentication>(
296296
command_sync(
297297
&lock,
298298
project_root,
299-
false,
300299
&mut env,
301300
client,
302301
&provided_iris,
303302
runtime,
304303
auth_policy,
305304
)?;
305+
} else {
306+
add_single_env_project(iri, project_version, env)?;
306307
}
307308

308309
Ok(())
309310
}
310311

311-
pub fn command_env_uninstall<S: AsRef<str>, Q: AsRef<str>>(
312+
fn add_single_env_project<S: AsRef<str>, V: AsRef<str>>(
312313
iri: S,
313-
version: Option<Q>,
314+
version: V,
314315
env: LocalDirectoryEnvironment,
315316
) -> Result<()> {
316-
sysand_core::commands::env::do_env_uninstall(iri, version, env)?;
317+
let metadata_path = env.metadata_path();
318+
let mut env_metadata = load_env_metadata(&metadata_path)?;
319+
let project_path = env.project_path(&iri, version);
320+
let project = LocalSrcProject {
321+
nominal_path: Some(project_path.strip_prefix(env.root_path())?.to_owned()),
322+
project_path,
323+
};
324+
env_metadata.add_local_project(vec![iri.as_ref().to_owned()], project, false)?;
325+
wrapfs::write(metadata_path, env_metadata.to_string())?;
326+
327+
Ok(())
328+
}
329+
330+
pub fn command_env_uninstall<S: AsRef<str>, V: AsRef<str>>(
331+
iri: S,
332+
version: Option<V>,
333+
env: LocalDirectoryEnvironment,
334+
) -> Result<()> {
335+
let metadata_path = env.metadata_path();
336+
337+
sysand_core::commands::env::do_env_uninstall(&iri, version.as_ref(), env)?;
338+
339+
let mut env_metadata = load_env_metadata(&metadata_path)?;
340+
env_metadata.remove_project(iri, version);
341+
wrapfs::write(metadata_path, env_metadata.to_string())?;
342+
317343
Ok(())
318344
}
319345

sysand/src/commands/sync.rs

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use url::ParseError;
99

1010
use sysand_core::{
1111
auth::HTTPAuthentication,
12-
env::local_directory::{DEFAULT_ENV_NAME, LocalDirectoryEnvironment, METADATA_PATH},
12+
env::local_directory::{LocalDirectoryEnvironment, metadata::load_env_metadata},
1313
lock::Lock,
1414
project::{
1515
AsSyncProjectTokio, ProjectReadAsync,
@@ -27,7 +27,6 @@ use sysand_core::{
2727
pub fn command_sync<P: AsRef<Utf8Path>, Policy: HTTPAuthentication>(
2828
lock: &Lock,
2929
project_root: P,
30-
update_metadata: bool,
3130
env: &mut LocalDirectoryEnvironment,
3231
client: reqwest_middleware::ClientWithMiddleware,
3332
provided_iris: &HashMap<String, Vec<InMemoryProject>>,
@@ -69,16 +68,16 @@ pub fn command_sync<P: AsRef<Utf8Path>, Policy: HTTPAuthentication>(
6968
provided_iris,
7069
)?;
7170

72-
if update_metadata {
73-
let env_metadata = lock.to_env_metadata(env, &project_root)?;
74-
wrapfs::write(
75-
project_root
76-
.as_ref()
77-
.join(DEFAULT_ENV_NAME)
78-
.join(METADATA_PATH),
79-
env_metadata.to_string(),
80-
)?;
81-
}
71+
let lock_metadata = lock.to_env_metadata(env, project_root)?;
72+
let env_metadata = if wrapfs::is_file(env.metadata_path())? {
73+
let mut env_metadata = load_env_metadata(env.metadata_path())?;
74+
env_metadata.merge(lock_metadata);
75+
env_metadata
76+
} else {
77+
lock_metadata
78+
};
79+
80+
wrapfs::write(env.metadata_path(), env_metadata.to_string())?;
8281

8382
Ok(())
8483
}

sysand/src/lib.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,7 +110,7 @@ where
110110

111111
fn set_panic_hook() {
112112
// TODO: use `panic::update_hook()` once it's stable
113-
// also set bactrace style once it's stable, but take
113+
// also set backtrace style once it's stable, but take
114114
// into account the current level
115115
let default_hook = panic::take_hook();
116116
// panic::set_backtrace_style(panic::BacktraceStyle::Short);
@@ -181,7 +181,7 @@ pub fn run_cli(args: cli::Args) -> Result<()> {
181181
.unwrap(),
182182
);
183183

184-
let _runtime_keepalive = runtime.clone();
184+
let _runtime_keep_alive = runtime.clone();
185185

186186
// FIXME: This is a temporary implementation to provide credentials until
187187
// https://github.com/sensmetry/sysand/pull/157
@@ -418,7 +418,6 @@ pub fn run_cli(args: cli::Args) -> Result<()> {
418418
command_sync(
419419
&lock,
420420
project_root,
421-
true,
422421
&mut local_environment,
423422
client,
424423
&provided_iris,

sysand/tests/cli_env.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@ use assert_cmd::prelude::*;
77
use camino::Utf8Path;
88
use mockito::Server;
99
use predicates::prelude::*;
10-
use sysand_core::env::local_directory::{DEFAULT_ENV_NAME, ENTRIES_PATH, VERSIONS_PATH};
10+
use sysand_core::env::local_directory::{
11+
DEFAULT_ENV_NAME, ENTRIES_PATH, METADATA_PATH, VERSIONS_PATH,
12+
};
1113

1214
// pub due to https://github.com/rust-lang/rust/issues/46379
1315
mod common;
@@ -124,10 +126,12 @@ fn env_install_from_local_dir() -> Result<(), Box<dyn std::error::Error>> {
124126

125127
let entries = std::fs::read_dir(cwd.join(env_path))?.collect::<Result<Vec<_>, _>>()?;
126128

127-
assert_eq!(entries.len(), 1);
129+
assert_eq!(entries.len(), 2);
128130

129131
assert_eq!(entries[0].file_name(), ENTRIES_PATH);
130132

133+
assert_eq!(entries[1].file_name(), METADATA_PATH);
134+
131135
assert_eq!(std::fs::read_to_string(entries[0].path())?, "");
132136

133137
Ok(())

0 commit comments

Comments
 (0)