Skip to content

Commit d7ec657

Browse files
committed
switch from parsing yaml bytes to taking the path so we can report better errors
1 parent 14aeab5 commit d7ec657

File tree

6 files changed

+79
-35
lines changed

6 files changed

+79
-35
lines changed

Cargo.lock

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

bin/icp-cli/src/commands/build.rs

Lines changed: 23 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
use clap::Parser;
2-
use icp_canister::{CanisterManifest, CanisterManifestError};
3-
use snafu::Snafu;
2+
use snafu::{ResultExt, Snafu};
43

5-
use icp_fs::fs::{ReadFileError, read};
4+
use icp_canister::{CanisterManifest, CanisterManifestError};
65
use icp_project::{ProjectManifest, ProjectManifestError};
76

87
use crate::project::structure::ProjectDirectoryStructure;
@@ -11,30 +10,24 @@ use crate::project::structure::ProjectDirectoryStructure;
1110
pub struct Cmd;
1211

1312
pub async fn dispatch(_cmd: Cmd) -> Result<(), BuildCommandError> {
14-
// Open project
15-
let pds = ProjectDirectoryStructure::find().ok_or(BuildCommandError::ProjectNotFound)?;
16-
17-
let mpath = pds.root().join("icp.yaml");
18-
if !mpath.exists() {
19-
return Err(BuildCommandError::ProjectNotFound);
20-
}
13+
let mpath = ProjectDirectoryStructure::find()
14+
.ok_or(BuildCommandError::ProjectNotFound)?
15+
.root()
16+
.join("icp.yaml");
2117

22-
let bs = read(mpath)?;
23-
let pm = ProjectManifest::from_bytes(&bs)?;
18+
let pm = ProjectManifest::from_file(&mpath).context(ProjectLoadSnafu {
19+
path: format!("{mpath:?}"),
20+
})?;
2421

2522
// List canisters in project
2623
let mut cs = Vec::new();
2724

2825
for c in pm.canisters {
2926
let mpath = c.join("canister.yaml");
30-
if !mpath.exists() {
31-
return Err(BuildCommandError::CanisterNotFound {
32-
path: format!("{mpath:?}"),
33-
});
34-
}
3527

36-
let bs = read(mpath)?;
37-
let cm = CanisterManifest::from_bytes(&bs)?;
28+
let cm = CanisterManifest::from_file(&mpath).context(CanisterLoadSnafu {
29+
path: format!("{mpath:?}"),
30+
})?;
3831

3932
cs.push(cm);
4033
}
@@ -50,15 +43,15 @@ pub enum BuildCommandError {
5043
#[snafu(display("no project (icp.yaml) found in current directory or its parents"))]
5144
ProjectNotFound,
5245

53-
#[snafu(transparent)]
54-
ProjectParse { source: ProjectManifestError },
55-
56-
#[snafu(display("canister manifest not found: {path}"))]
57-
CanisterNotFound { path: String },
58-
59-
#[snafu(transparent)]
60-
CanisterParse { source: CanisterManifestError },
61-
62-
#[snafu(transparent)]
63-
ReadFile { source: ReadFileError },
46+
#[snafu(display("failed to load project manifest: {path}"))]
47+
ProjectLoad {
48+
source: ProjectManifestError,
49+
path: String,
50+
},
51+
52+
#[snafu(display("failed to load canister manifest: {path}"))]
53+
CanisterLoad {
54+
source: CanisterManifestError,
55+
path: String,
56+
},
6457
}

lib/icp-canister/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ version = "0.1.0"
44
edition = "2024"
55

66
[dependencies]
7+
icp-fs = { "path" = "../icp-fs" }
78
serde = { workspace = true }
89
serde_json = { workspace = true }
910
serde_yaml = { workspace = true }

lib/icp-canister/src/lib.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,9 @@
1+
use std::path::Path;
2+
13
use serde::Deserialize;
2-
use snafu::{ResultExt, Snafu};
4+
use snafu::{ResultExt, Snafu, ensure};
5+
6+
use icp_fs::fs::{ReadFileError, read};
37

48
/// Configuration for a Rust-based canister build adapter.
59
#[derive(Debug, Deserialize)]
@@ -76,7 +80,21 @@ pub struct CanisterManifest {
7680
}
7781

7882
impl CanisterManifest {
79-
pub fn from_bytes<B: AsRef<[u8]>>(bytes: B) -> Result<Self, CanisterManifestError> {
83+
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, CanisterManifestError> {
84+
let path = path.as_ref();
85+
86+
// Check existence
87+
ensure!(
88+
path.exists(),
89+
NotFoundSnafu {
90+
path: format!("{path:?}")
91+
}
92+
);
93+
94+
// Read
95+
let bytes = read(path)?;
96+
97+
// Parse
8098
let cm: CanisterManifest = serde_yaml::from_slice(bytes.as_ref()).context(ParseSnafu)?;
8199

82100
Ok(cm)
@@ -85,6 +103,12 @@ impl CanisterManifest {
85103

86104
#[derive(Debug, Snafu)]
87105
pub enum CanisterManifestError {
106+
#[snafu(display("canister manifest not found: {path}"))]
107+
NotFound { path: String },
108+
88109
#[snafu(display("failed to parse canister manifest: {}", source))]
89110
Parse { source: serde_yaml::Error },
111+
112+
#[snafu(transparent)]
113+
ReadFile { source: ReadFileError },
90114
}

lib/icp-project/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ edition = "2024"
66
[dependencies]
77
glob = { workspace = true }
88
icp-canister = { path = "../icp-canister" }
9+
icp-fs = { "path" = "../icp-fs" }
910
icp-network = { path = "../icp-network" }
1011
serde = { workspace = true }
1112
serde_json = { workspace = true }

lib/icp-project/src/lib.rs

Lines changed: 26 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
1+
use std::path::{Path, PathBuf};
2+
13
use serde::Deserialize;
2-
use snafu::{OptionExt, ResultExt, Snafu};
3-
use std::path::PathBuf;
4+
use snafu::{OptionExt, ResultExt, Snafu, ensure};
5+
6+
use icp_fs::fs::{ReadFileError, read};
47

58
/// Represents the manifest for an ICP project, typically loaded from `icp.yaml`.
69
/// A project is a repository or directory grouping related canisters and network definitions.
@@ -18,7 +21,21 @@ pub struct ProjectManifest {
1821
}
1922

2023
impl ProjectManifest {
21-
pub fn from_bytes<B: AsRef<[u8]>>(bytes: B) -> Result<Self, ProjectManifestError> {
24+
pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Self, ProjectManifestError> {
25+
let path = path.as_ref();
26+
27+
// Check existence
28+
ensure!(
29+
path.exists(),
30+
NotFoundSnafu {
31+
path: format!("{path:?}")
32+
}
33+
);
34+
35+
// Load
36+
let bytes = read(path)?;
37+
38+
// Parse
2239
let mut pm: ProjectManifest = serde_yaml::from_slice(bytes.as_ref()).context(ParseSnafu)?;
2340

2441
// Project canisters
@@ -48,6 +65,9 @@ impl ProjectManifest {
4865

4966
#[derive(Debug, Snafu)]
5067
pub enum ProjectManifestError {
68+
#[snafu(display("project manifest not found: {path}"))]
69+
NotFound { path: String },
70+
5171
#[snafu(display("failed to parse project manifest: {}", source))]
5272
Parse { source: serde_yaml::Error },
5373

@@ -59,4 +79,7 @@ pub enum ProjectManifestError {
5979

6080
#[snafu(transparent)]
6181
GlobWalk { source: glob::GlobError },
82+
83+
#[snafu(transparent)]
84+
ReadFile { source: ReadFileError },
6285
}

0 commit comments

Comments
 (0)