refactor(metadata): Switch opaque ID from PackageID to PackageIDSpec

This commit is contained in:
Ed Page 2023-11-02 11:37:14 -05:00
parent 187d4cf35e
commit 594c96ad51
13 changed files with 316 additions and 304 deletions

View File

@ -22,7 +22,7 @@ use crate::core::compiler::{CompileKind, RustcTargetData};
use crate::core::dependency::DepKind;
use crate::core::resolver::features::ForceAllTargets;
use crate::core::resolver::{HasDevUnits, Resolve};
use crate::core::{Dependency, Manifest, PackageId, SourceId, Target};
use crate::core::{Dependency, Manifest, PackageId, PackageIdSpec, SourceId, Target};
use crate::core::{Summary, Workspace};
use crate::sources::source::{MaybePackage, SourceMap};
use crate::util::cache_lock::{CacheLock, CacheLockMode};
@ -82,7 +82,7 @@ impl PartialOrd for Package {
pub struct SerializedPackage {
name: InternedString,
version: Version,
id: PackageId,
id: PackageIdSpec,
license: Option<String>,
license_file: Option<String>,
description: Option<String>,
@ -239,7 +239,7 @@ impl Package {
SerializedPackage {
name: package_id.name(),
version: package_id.version().clone(),
id: package_id,
id: package_id.to_spec(),
license: manmeta.license.clone(),
license_file: manmeta.license_file.clone(),
description: manmeta.description.clone(),

View File

@ -3,7 +3,7 @@ use crate::core::compiler::{CompileKind, RustcTargetData};
use crate::core::dependency::DepKind;
use crate::core::package::SerializedPackage;
use crate::core::resolver::{features::CliFeatures, HasDevUnits, Resolve};
use crate::core::{Package, PackageId, Workspace};
use crate::core::{Package, PackageId, PackageIdSpec, Workspace};
use crate::ops::{self, Packages};
use crate::util::interning::InternedString;
use crate::util::CargoResult;
@ -42,8 +42,11 @@ pub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> Cargo
Ok(ExportInfo {
packages,
workspace_members: ws.members().map(|pkg| pkg.package_id()).collect(),
workspace_default_members: ws.default_members().map(|pkg| pkg.package_id()).collect(),
workspace_members: ws.members().map(|pkg| pkg.package_id().to_spec()).collect(),
workspace_default_members: ws
.default_members()
.map(|pkg| pkg.package_id().to_spec())
.collect(),
resolve,
target_directory: ws.target_dir().into_path_unlocked(),
version: VERSION,
@ -58,8 +61,8 @@ pub fn output_metadata(ws: &Workspace<'_>, opt: &OutputMetadataOptions) -> Cargo
#[derive(Serialize)]
pub struct ExportInfo {
packages: Vec<SerializedPackage>,
workspace_members: Vec<PackageId>,
workspace_default_members: Vec<PackageId>,
workspace_members: Vec<PackageIdSpec>,
workspace_default_members: Vec<PackageIdSpec>,
resolve: Option<MetadataResolve>,
target_directory: PathBuf,
version: u32,
@ -70,13 +73,13 @@ pub struct ExportInfo {
#[derive(Serialize)]
struct MetadataResolve {
nodes: Vec<MetadataResolveNode>,
root: Option<PackageId>,
root: Option<PackageIdSpec>,
}
#[derive(Serialize)]
struct MetadataResolveNode {
id: PackageId,
dependencies: Vec<PackageId>,
id: PackageIdSpec,
dependencies: Vec<PackageIdSpec>,
deps: Vec<Dep>,
features: Vec<InternedString>,
}
@ -86,7 +89,9 @@ struct Dep {
// TODO(bindeps): after -Zbindeps gets stabilized,
// mark this field as deprecated in the help manual of cargo-metadata
name: InternedString,
pkg: PackageId,
pkg: PackageIdSpec,
#[serde(skip)]
pkg_id: PackageId,
dep_kinds: Vec<DepKindInfo>,
}
@ -179,7 +184,7 @@ fn build_resolve_graph(
let mr = MetadataResolve {
nodes: node_map.into_iter().map(|(_pkg_id, node)| node).collect(),
root: ws.current_opt().map(|pkg| pkg.package_id()),
root: ws.current_opt().map(|pkg| pkg.package_id().to_spec()),
};
Ok((actual_packages, mr))
}
@ -301,18 +306,20 @@ fn build_resolve_graph_r(
dep_kinds.sort();
let pkg = normalize_id(dep_id);
let pkg_id = normalize_id(dep_id);
let dep = match (lib_target, dep_kinds.len()) {
(Some(target), _) => Dep {
name: extern_name(target)?,
pkg,
pkg: pkg_id.to_spec(),
pkg_id,
dep_kinds,
},
// No lib target exists but contains artifact deps.
(None, 1..) => Dep {
name: InternedString::new(""),
pkg,
pkg: pkg_id.to_spec(),
pkg_id,
dep_kinds,
},
// No lib or artifact dep exists.
@ -325,11 +332,10 @@ fn build_resolve_graph_r(
dep_metadatas
};
let dumb_deps: Vec<PackageId> = deps.iter().map(|dep| dep.pkg).collect();
let to_visit = dumb_deps.clone();
let to_visit: Vec<PackageId> = deps.iter().map(|dep| dep.pkg_id).collect();
let node = MetadataResolveNode {
id: normalize_id(pkg_id),
dependencies: dumb_deps,
id: normalize_id(pkg_id).to_spec(),
dependencies: to_visit.iter().map(|id| id.to_spec()).collect(),
deps,
features,
};

View File

@ -56,7 +56,7 @@ The JSON output has the following format:
/* The Package ID, an opaque and unique identifier for referring to the
package. See "Compatibility" above for the stability guarantee.
*/
"id": "my-package 0.1.0 (path+file:///path/to/my-package)",
"id": "file:///path/to/my-package#0.1.0",
/* The license value from the manifest, or null. */
"license": "MIT/Apache-2.0",
/* The license-file value from the manifest, or null. */
@ -242,13 +242,13 @@ The JSON output has the following format:
Each entry is the Package ID for the package.
*/
"workspace_members": [
"my-package 0.1.0 (path+file:///path/to/my-package)",
"file:///path/to/my-package#0.1.0",
],
/* Array of default members of the workspace.
Each entry is the Package ID for the package.
*/
"workspace_default_members": [
"my-package 0.1.0 (path+file:///path/to/my-package)",
"file:///path/to/my-package#0.1.0",
],
// The resolved dependency graph for the entire workspace. The enabled
// features are based on the enabled features for the "current" package.
@ -266,10 +266,10 @@ The JSON output has the following format:
"nodes": [
{
/* The Package ID of this node. */
"id": "my-package 0.1.0 (path+file:///path/to/my-package)",
"id": "file:///path/to/my-package#0.1.0",
/* The dependencies of this package, an array of Package IDs. */
"dependencies": [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)"
"https://github.com/rust-lang/crates.io-index#bitflags@1.0.4"
],
/* The dependencies of this package. This is an alternative to
"dependencies" which contains additional information. In
@ -283,7 +283,7 @@ The JSON output has the following format:
*/
"name": "bitflags",
/* The Package ID of the dependency. */
"pkg": "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg": "https://github.com/rust-lang/crates.io-index#bitflags@1.0.4"
/* Array of dependency kinds. Added in Cargo 1.40. */
"dep_kinds": [
{
@ -309,7 +309,7 @@ The JSON output has the following format:
This is null if this is a virtual workspace. Otherwise it is
the Package ID of the root package.
*/
"root": "my-package 0.1.0 (path+file:///path/to/my-package)"
"root": "file:///path/to/my-package#0.1.0",
},
/* The absolute path to the build directory where Cargo places its output. */
"target_directory": "/path/to/my-package/target",

View File

@ -52,7 +52,7 @@ OUTPUT FORMAT
/* The Package ID, an opaque and unique identifier for referring to the
package. See "Compatibility" above for the stability guarantee.
*/
"id": "my-package 0.1.0 (path+file:///path/to/my-package)",
"id": "file:///path/to/my-package#0.1.0",
/* The license value from the manifest, or null. */
"license": "MIT/Apache-2.0",
/* The license-file value from the manifest, or null. */
@ -238,13 +238,13 @@ OUTPUT FORMAT
Each entry is the Package ID for the package.
*/
"workspace_members": [
"my-package 0.1.0 (path+file:///path/to/my-package)",
"file:///path/to/my-package#0.1.0",
],
/* Array of default members of the workspace.
Each entry is the Package ID for the package.
*/
"workspace_default_members": [
"my-package 0.1.0 (path+file:///path/to/my-package)",
"file:///path/to/my-package#0.1.0",
],
// The resolved dependency graph for the entire workspace. The enabled
// features are based on the enabled features for the "current" package.
@ -262,10 +262,10 @@ OUTPUT FORMAT
"nodes": [
{
/* The Package ID of this node. */
"id": "my-package 0.1.0 (path+file:///path/to/my-package)",
"id": "file:///path/to/my-package#0.1.0",
/* The dependencies of this package, an array of Package IDs. */
"dependencies": [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)"
"https://github.com/rust-lang/crates.io-index#bitflags@1.0.4"
],
/* The dependencies of this package. This is an alternative to
"dependencies" which contains additional information. In
@ -279,7 +279,7 @@ OUTPUT FORMAT
*/
"name": "bitflags",
/* The Package ID of the dependency. */
"pkg": "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg": "https://github.com/rust-lang/crates.io-index#bitflags@1.0.4"
/* Array of dependency kinds. Added in Cargo 1.40. */
"dep_kinds": [
{
@ -305,7 +305,7 @@ OUTPUT FORMAT
This is null if this is a virtual workspace. Otherwise it is
the Package ID of the root package.
*/
"root": "my-package 0.1.0 (path+file:///path/to/my-package)"
"root": "file:///path/to/my-package#0.1.0",
},
/* The absolute path to the build directory where Cargo places its output. */
"target_directory": "/path/to/my-package/target",

View File

@ -56,7 +56,7 @@ The JSON output has the following format:
/* The Package ID, an opaque and unique identifier for referring to the
package. See "Compatibility" above for the stability guarantee.
*/
"id": "my-package 0.1.0 (path+file:///path/to/my-package)",
"id": "file:///path/to/my-package#0.1.0",
/* The license value from the manifest, or null. */
"license": "MIT/Apache-2.0",
/* The license-file value from the manifest, or null. */
@ -242,13 +242,13 @@ The JSON output has the following format:
Each entry is the Package ID for the package.
*/
"workspace_members": [
"my-package 0.1.0 (path+file:///path/to/my-package)",
"file:///path/to/my-package#0.1.0",
],
/* Array of default members of the workspace.
Each entry is the Package ID for the package.
*/
"workspace_default_members": [
"my-package 0.1.0 (path+file:///path/to/my-package)",
"file:///path/to/my-package#0.1.0",
],
// The resolved dependency graph for the entire workspace. The enabled
// features are based on the enabled features for the "current" package.
@ -266,10 +266,10 @@ The JSON output has the following format:
"nodes": [
{
/* The Package ID of this node. */
"id": "my-package 0.1.0 (path+file:///path/to/my-package)",
"id": "file:///path/to/my-package#0.1.0",
/* The dependencies of this package, an array of Package IDs. */
"dependencies": [
"bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)"
"https://github.com/rust-lang/crates.io-index#bitflags@1.0.4"
],
/* The dependencies of this package. This is an alternative to
"dependencies" which contains additional information. In
@ -283,7 +283,7 @@ The JSON output has the following format:
*/
"name": "bitflags",
/* The Package ID of the dependency. */
"pkg": "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)",
"pkg": "https://github.com/rust-lang/crates.io-index#bitflags@1.0.4"
/* Array of dependency kinds. Added in Cargo 1.40. */
"dep_kinds": [
{
@ -309,7 +309,7 @@ The JSON output has the following format:
This is null if this is a virtual workspace. Otherwise it is
the Package ID of the root package.
*/
"root": "my-package 0.1.0 (path+file:///path/to/my-package)"
"root": "file:///path/to/my-package#0.1.0",
},
/* The absolute path to the build directory where Cargo places its output. */
"target_directory": "/path/to/my-package/target",

View File

@ -58,7 +58,7 @@ The JSON output has the following format:
/* The Package ID, an opaque and unique identifier for referring to the
package. See "Compatibility" above for the stability guarantee.
*/
"id": "my\-package 0.1.0 (path+file:///path/to/my\-package)",
"id": "file:///path/to/my\-package#0.1.0",
/* The license value from the manifest, or null. */
"license": "MIT/Apache\-2.0",
/* The license\-file value from the manifest, or null. */
@ -244,13 +244,13 @@ The JSON output has the following format:
Each entry is the Package ID for the package.
*/
"workspace_members": [
"my\-package 0.1.0 (path+file:///path/to/my\-package)",
"file:///path/to/my\-package#0.1.0",
],
/* Array of default members of the workspace.
Each entry is the Package ID for the package.
*/
"workspace_default_members": [
"my\-package 0.1.0 (path+file:///path/to/my\-package)",
"file:///path/to/my\-package#0.1.0",
],
// The resolved dependency graph for the entire workspace. The enabled
// features are based on the enabled features for the "current" package.
@ -268,10 +268,10 @@ The JSON output has the following format:
"nodes": [
{
/* The Package ID of this node. */
"id": "my\-package 0.1.0 (path+file:///path/to/my\-package)",
"id": "file:///path/to/my\-package#0.1.0",
/* The dependencies of this package, an array of Package IDs. */
"dependencies": [
"bitflags 1.0.4 (registry+https://github.com/rust\-lang/crates.io\-index)"
"https://github.com/rust\-lang/crates.io\-index#bitflags@1.0.4"
],
/* The dependencies of this package. This is an alternative to
"dependencies" which contains additional information. In
@ -285,7 +285,7 @@ The JSON output has the following format:
*/
"name": "bitflags",
/* The Package ID of the dependency. */
"pkg": "bitflags 1.0.4 (registry+https://github.com/rust\-lang/crates.io\-index)",
"pkg": "https://github.com/rust\-lang/crates.io\-index#bitflags@1.0.4"
/* Array of dependency kinds. Added in Cargo 1.40. */
"dep_kinds": [
{
@ -311,7 +311,7 @@ The JSON output has the following format:
This is null if this is a virtual workspace. Otherwise it is
the Package ID of the root package.
*/
"root": "my\-package 0.1.0 (path+file:///path/to/my\-package)"
"root": "file:///path/to/my\-package#0.1.0",
},
/* The absolute path to the build directory where Cargo places its output. */
"target_directory": "/path/to/my\-package/target",

View File

@ -857,7 +857,7 @@ fn alt_reg_metadata() {
{
"name": "foo",
"version": "0.0.1",
"id": "foo 0.0.1 (path+file:[..]/foo)",
"id": "path+file:[..]/foo#0.0.1",
"license": null,
"license_file": null,
"description": null,
@ -907,10 +907,10 @@ fn alt_reg_metadata() {
}
],
"workspace_members": [
"foo 0.0.1 (path+file:[..]/foo)"
"path+file:[..]/foo#0.0.1"
],
"workspace_default_members": [
"foo 0.0.1 (path+file:[..]/foo)"
"path+file:[..]/foo#0.0.1"
],
"resolve": null,
"target_directory": "[..]/foo/target",
@ -930,7 +930,7 @@ fn alt_reg_metadata() {
{
"name": "altdep",
"version": "0.0.1",
"id": "altdep 0.0.1 (registry+file:[..]/alternative-registry)",
"id": "registry+file:[..]/alternative-registry#altdep@0.0.1",
"license": null,
"license_file": null,
"description": null,
@ -969,7 +969,7 @@ fn alt_reg_metadata() {
{
"name": "altdep2",
"version": "0.0.1",
"id": "altdep2 0.0.1 (registry+file:[..]/alternative-registry)",
"id": "registry+file:[..]/alternative-registry#altdep2@0.0.1",
"license": null,
"license_file": null,
"description": null,
@ -995,7 +995,7 @@ fn alt_reg_metadata() {
{
"name": "bar",
"version": "0.0.1",
"id": "bar 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1",
"license": null,
"license_file": null,
"description": null,
@ -1021,7 +1021,7 @@ fn alt_reg_metadata() {
{
"name": "foo",
"version": "0.0.1",
"id": "foo 0.0.1 (path+file:[..]/foo)",
"id": "path+file:[..]/foo#0.0.1",
"license": null,
"license_file": null,
"description": null,
@ -1072,7 +1072,7 @@ fn alt_reg_metadata() {
{
"name": "iodep",
"version": "0.0.1",
"id": "iodep 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"id": "registry+https://github.com/rust-lang/crates.io-index#iodep@0.0.1",
"license": null,
"license_file": null,
"description": null,
@ -1110,10 +1110,10 @@ fn alt_reg_metadata() {
}
],
"workspace_members": [
"foo 0.0.1 (path+file:[..]/foo)"
"path+file:[..]/foo#0.0.1"
],
"workspace_default_members": [
"foo 0.0.1 (path+file:[..]/foo)"
"path+file:[..]/foo#0.0.1"
],
"resolve": "{...}",
"target_directory": "[..]/foo/target",
@ -1173,7 +1173,7 @@ fn unknown_registry() {
{
"name": "bar",
"version": "0.0.1",
"id": "bar 0.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"id": "registry+https://github.com/rust-lang/crates.io-index#bar@0.0.1",
"license": null,
"license_file": null,
"description": null,
@ -1212,7 +1212,7 @@ fn unknown_registry() {
{
"name": "baz",
"version": "0.0.1",
"id": "baz 0.0.1 (registry+file://[..]/alternative-registry)",
"id": "registry+file://[..]/alternative-registry#baz@0.0.1",
"license": null,
"license_file": null,
"description": null,
@ -1238,7 +1238,7 @@ fn unknown_registry() {
{
"name": "foo",
"version": "0.0.1",
"id": "foo 0.0.1 (path+file://[..]/foo)",
"id": "path+file://[..]/foo#0.0.1",
"license": null,
"license_file": null,
"description": null,
@ -1276,10 +1276,10 @@ fn unknown_registry() {
}
],
"workspace_members": [
"foo 0.0.1 (path+file://[..]/foo)"
"path+file://[..]/foo#0.0.1"
],
"workspace_default_members": [
"foo 0.0.1 (path+file://[..]/foo)"
"path+file://[..]/foo#0.0.1"
],
"resolve": "{...}",
"target_directory": "[..]/foo/target",

View File

@ -586,7 +586,7 @@ fn json_exposed() {
{
"name": "foo",
"version": "0.1.0",
"id": "foo 0.1.0 [..]",
"id": "[..]foo#0.1.0",
"license": null,
"license_file": null,
"description": null,

View File

@ -3275,7 +3275,7 @@ fn metadata_master_consistency() {
{
"name": "bar",
"version": "1.0.0",
"id": "bar 1.0.0 (__BAR_SOURCE__#__BAR_HASH__)",
"id": "__BAR_SOURCE__#1.0.0",
"license": null,
"license_file": null,
"description": null,
@ -3301,7 +3301,7 @@ fn metadata_master_consistency() {
{
"name": "foo",
"version": "0.1.0",
"id": "foo 0.1.0 [..]",
"id": "[..]foo#0.1.0",
"license": null,
"license_file": null,
"description": null,
@ -3339,28 +3339,28 @@ fn metadata_master_consistency() {
}
],
"workspace_members": [
"foo 0.1.0 [..]"
"[..]foo#0.1.0"
],
"workspace_default_members": [
"foo 0.1.0 [..]"
"[..]foo#0.1.0"
],
"resolve": {
"nodes": [
{
"id": "bar 1.0.0 (__BAR_SOURCE__#__BAR_HASH__)",
"id": "__BAR_SOURCE__#1.0.0",
"dependencies": [],
"deps": [],
"features": []
},
{
"id": "foo 0.1.0 [..]",
"id": "[..]foo#0.1.0",
"dependencies": [
"bar 1.0.0 (__BAR_SOURCE__#__BAR_HASH__)"
"__BAR_SOURCE__#1.0.0"
],
"deps": [
{
"name": "bar",
"pkg": "bar 1.0.0 (__BAR_SOURCE__#__BAR_HASH__)",
"pkg": "__BAR_SOURCE__#1.0.0",
"dep_kinds": [
{
"kind": null,
@ -3372,7 +3372,7 @@ fn metadata_master_consistency() {
"features": []
}
],
"root": "foo 0.1.0 [..]"
"root": "[..]foo#0.1.0"
},
"target_directory": "[..]",
"version": 1,

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@ fn manifest_output(readme_value: &str) -> String {
"repository": null,
"rust_version": null,
"version":"0.5.0",
"id":"foo[..]0.5.0[..](path+file://[..]/foo)",
"id":"path+file://[..]/foo#0.5.0",
"keywords": [],
"license": null,
"license_file": null,

View File

@ -1024,7 +1024,7 @@ fn cmd_metadata_with_embedded() {
"default_run": null,
"name": "script",
"version": "0.0.0",
"id": "script[..]",
"id": "path+file:[..]foo#script@0.0.0",
"keywords": [],
"source": null,
"dependencies": [],
@ -1062,18 +1062,18 @@ fn cmd_metadata_with_embedded() {
"publish": []
}
],
"workspace_members": ["script 0.0.0 (path+file:[..]foo)"],
"workspace_default_members": ["script 0.0.0 (path+file:[..]foo)"],
"workspace_members": ["path+file:[..]foo#script@0.0.0"],
"workspace_default_members": ["path+file:[..]foo#script@0.0.0"],
"resolve": {
"nodes": [
{
"dependencies": [],
"deps": [],
"features": [],
"id": "script 0.0.0 (path+file:[..]foo)"
"id": "path+file:[..]foo#script@0.0.0"
}
],
"root": "script 0.0.0 (path+file:[..]foo)"
"root": "path+file:[..]foo#script@0.0.0"
},
"target_directory": "[ROOT]/home/.cargo/target/[..]",
"version": 1,
@ -1112,7 +1112,7 @@ fn cmd_read_manifest_with_embedded() {
"repository": null,
"rust_version": null,
"version":"0.0.0",
"id":"script[..]0.0.0[..](path+file://[..]/foo)",
"id":"path+file://[..]/foo#script@0.0.0",
"keywords": [],
"license": null,
"license_file": null,

View File

@ -700,7 +700,7 @@ fn update_precise_first_run() {
"edition": "2015",
"features": {},
"homepage": null,
"id": "bar 0.0.1 (path+file://[..]/foo)",
"id": "path+file://[..]/foo#bar@0.0.1",
"keywords": [],
"license": null,
"license_file": null,
@ -741,7 +741,7 @@ fn update_precise_first_run() {
"edition": "2015",
"features": {},
"homepage": null,
"id": "serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
"id": "registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0",
"keywords": [],
"license": null,
"license_file": null,
@ -777,7 +777,7 @@ fn update_precise_first_run() {
"nodes": [
{
"dependencies": [
"serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)"
"registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0"
],
"deps": [
{
@ -788,28 +788,28 @@ fn update_precise_first_run() {
}
],
"name": "serde",
"pkg": "serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)"
"pkg": "registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0"
}
],
"features": [],
"id": "bar 0.0.1 (path+file://[..]/foo)"
"id": "path+file://[..]/foo#bar@0.0.1"
},
{
"dependencies": [],
"deps": [],
"features": [],
"id": "serde 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)"
"id": "registry+https://github.com/rust-lang/crates.io-index#serde@0.2.0"
}
],
"root": "bar 0.0.1 (path+file://[..]/foo)"
"root": "path+file://[..]/foo#bar@0.0.1"
},
"target_directory": "[..]/foo/target",
"version": 1,
"workspace_members": [
"bar 0.0.1 (path+file://[..]/foo)"
"path+file://[..]/foo#bar@0.0.1"
],
"workspace_default_members": [
"bar 0.0.1 (path+file://[..]/foo)"
"path+file://[..]/foo#bar@0.0.1"
],
"workspace_root": "[..]/foo",
"metadata": null