Skip to content

Commit 6ab4a17

Browse files
Merge branch 'main' into spofford/identity-storage
2 parents 68f2e2d + 1358a56 commit 6ab4a17

File tree

18 files changed

+198
-105
lines changed

18 files changed

+198
-105
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/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,13 @@ name = "icp"
99
path = "src/main.rs"
1010

1111
[dependencies]
12-
ic-agent.workspace = true
1312
bip32.workspace = true
1413
camino.workspace = true
1514
clap.workspace = true
1615
dialoguer.workspace = true
1716
elliptic-curve.workspace = true
1817
hex.workspace = true
18+
ic-agent.workspace = true
1919
icp-dirs.workspace = true
2020
icp-fs.workspace = true
2121
icp-identity.workspace = true

bin/icp-cli/src/commands/network/run.rs

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1-
use crate::commands::network::run::RunNetworkCommandError::ProjectStructureNotFound;
2-
use crate::project::structure::ProjectDirectoryStructure;
1+
use crate::project::directory::ProjectDirectory;
2+
use crate::{
3+
commands::network::run::RunNetworkCommandError::ProjectNotFound,
4+
project::directory::FindProjectError,
5+
};
36
use clap::Parser;
47
use icp_network::{ManagedNetworkModel, RunNetworkError, run_network};
58
use snafu::Snafu;
@@ -10,21 +13,24 @@ pub struct Cmd {}
1013

1114
pub async fn exec(_cmd: Cmd) -> Result<(), RunNetworkCommandError> {
1215
let config = ManagedNetworkModel::default();
13-
let pds = ProjectDirectoryStructure::find().ok_or(ProjectStructureNotFound)?;
14-
let nds = pds.network("local");
16+
let pd = ProjectDirectory::find()?.ok_or(ProjectNotFound)?;
17+
let nd = pd.network("local");
1518

16-
eprintln!("Project root: {}", pds.root().display());
17-
eprintln!("Network root: {}", nds.network_root().display());
19+
eprintln!("Project root: {}", pd.structure().root());
20+
eprintln!("Network root: {}", nd.structure().network_root());
1821

19-
run_network(config, nds).await?;
22+
run_network(config, nd).await?;
2023

2124
Ok(())
2225
}
2326

2427
#[derive(Debug, Snafu)]
2528
pub enum RunNetworkCommandError {
2629
#[snafu(display("no project (icp.yaml) found in current directory or its parents"))]
27-
ProjectStructureNotFound,
30+
ProjectNotFound,
31+
32+
#[snafu(transparent)]
33+
FindProjectError { source: FindProjectError },
2834

2935
#[snafu(transparent)]
3036
NetworkExecutionFailed { source: RunNetworkError },

bin/icp-cli/src/project.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
1+
pub mod directory;
12
pub mod structure;
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
use crate::project::structure::ProjectDirectoryStructure;
2+
use camino::Utf8PathBuf;
3+
use icp_network::NetworkDirectory;
4+
use snafu::{ResultExt, Snafu};
5+
use std::io;
6+
7+
pub struct ProjectDirectory {
8+
structure: ProjectDirectoryStructure,
9+
}
10+
11+
impl ProjectDirectory {
12+
pub fn find() -> Result<Option<Self>, FindProjectError> {
13+
let current_dir = Utf8PathBuf::try_from(std::env::current_dir().context(AccessSnafu)?)
14+
.context(NonUtf8Snafu)?;
15+
let mut path = current_dir.clone();
16+
loop {
17+
let structure = ProjectDirectoryStructure::new(&path);
18+
19+
if structure.project_yaml_path().exists() {
20+
break Ok(Some(Self { structure }));
21+
}
22+
if !path.pop() {
23+
break Ok(None);
24+
}
25+
}
26+
}
27+
28+
pub fn structure(&self) -> &ProjectDirectoryStructure {
29+
&self.structure
30+
}
31+
32+
pub fn network(&self, network_name: &str) -> NetworkDirectory {
33+
let network_root = self.structure.network_root(network_name);
34+
NetworkDirectory::new(&network_root)
35+
}
36+
}
37+
38+
#[derive(Debug, Snafu)]
39+
pub enum FindProjectError {
40+
#[snafu(display("project path is non-UTF-8"))]
41+
NonUtf8 { source: camino::FromPathBufError },
42+
#[snafu(display("failed to access current directory"))]
43+
AccessError { source: io::Error },
44+
}
Lines changed: 14 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,33 @@
1-
use icp_network::structure::NetworkDirectoryStructure;
2-
use std::path::PathBuf;
1+
use camino::{Utf8Path, Utf8PathBuf};
32

43
pub struct ProjectDirectoryStructure {
5-
root: PathBuf,
4+
root: Utf8PathBuf,
65
}
76

87
impl ProjectDirectoryStructure {
9-
pub fn find() -> Option<Self> {
10-
let current_dir = std::env::current_dir().ok()?;
11-
let mut path = current_dir.clone();
12-
loop {
13-
if path.join("icp.yaml").exists() {
14-
break Some(Self { root: path });
15-
}
16-
if !path.pop() {
17-
break None;
18-
}
19-
}
8+
pub fn new(root: &Utf8Path) -> Self {
9+
let root = root.to_path_buf();
10+
Self { root }
2011
}
2112

22-
pub fn root(&self) -> &PathBuf {
13+
pub fn root(&self) -> &Utf8PathBuf {
2314
&self.root
2415
}
2516

17+
pub fn project_yaml_path(&self) -> Utf8PathBuf {
18+
self.root.join("icp.yaml")
19+
}
20+
2621
#[allow(dead_code)]
27-
pub fn network_config_path(&self, name: &str) -> PathBuf {
22+
pub fn network_config_path(&self, name: &str) -> Utf8PathBuf {
2823
self.root.join("networks").join(format!("{name}.yaml"))
2924
}
3025

31-
fn work_dir(&self) -> PathBuf {
26+
fn work_dir(&self) -> Utf8PathBuf {
3227
self.root.join(".icp")
3328
}
3429

35-
pub fn network(&self, network_name: &str) -> NetworkDirectoryStructure {
36-
let network_root = self.work_dir().join("networks").join(network_name);
37-
38-
NetworkDirectoryStructure::new(&network_root)
30+
pub fn network_root(&self, network_name: &str) -> Utf8PathBuf {
31+
self.work_dir().join("networks").join(network_name)
3932
}
4033
}

clippy.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
disallowed-types = [
2+
{ path = "std::path::PathBuf", replacement = "camino::Utf8PathBuf" },
3+
{ path = "std::path::Path", replacement = "camino::Utf8Path" },
4+
]

lib/icp-fs/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+
camino = { workspace = true }
78
serde = { workspace = true }
89
serde_json = { workspace = true }
910
snafu = { workspace = true }

lib/icp-fs/src/fs.rs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,66 +1,70 @@
1+
use camino::{Utf8Path, Utf8PathBuf};
12
use snafu::prelude::*;
2-
use std::path::{Path, PathBuf};
33

44
#[derive(Snafu, Debug)]
5-
#[snafu(display("failed to create directory {} and parents", path.display()))]
5+
#[snafu(display("failed to create directory {path} and parents"))]
66
pub struct CreateDirAllError {
7-
pub path: PathBuf,
7+
pub path: Utf8PathBuf,
88
pub source: std::io::Error,
99
}
1010

11-
pub fn create_dir_all(path: impl AsRef<Path>) -> Result<(), CreateDirAllError> {
11+
pub fn create_dir_all(path: impl AsRef<Utf8Path>) -> Result<(), CreateDirAllError> {
1212
let path = path.as_ref();
1313
std::fs::create_dir_all(path).context(CreateDirAllSnafu { path })
1414
}
1515

1616
#[derive(Snafu, Debug)]
17-
#[snafu(display("failed to read {}", path.display()))]
17+
#[snafu(display("failed to read {path}"))]
1818
pub struct ReadFileError {
19-
pub path: PathBuf,
19+
pub path: Utf8PathBuf,
2020
pub source: std::io::Error,
2121
}
2222

23-
pub fn read<P: AsRef<Path>>(path: P) -> Result<Vec<u8>, ReadFileError> {
23+
pub fn read<P: AsRef<Utf8Path>>(path: P) -> Result<Vec<u8>, ReadFileError> {
2424
let path = path.as_ref();
2525
std::fs::read(path).context(ReadFileSnafu { path })
2626
}
2727

28-
pub fn read_to_string<P: AsRef<Path>>(path: P) -> Result<String, ReadFileError> {
28+
pub fn read_to_string<P: AsRef<Utf8Path>>(path: P) -> Result<String, ReadFileError> {
2929
let path = path.as_ref();
3030
std::fs::read_to_string(path).context(ReadFileSnafu { path })
3131
}
3232

3333
#[derive(Snafu, Debug)]
34-
#[snafu(display("failed to remove directory {} and contents", path.display()))]
34+
#[snafu(display("failed to remove directory {path} and contents"))]
3535
pub struct RemoveDirAllError {
36-
pub path: PathBuf,
36+
pub path: Utf8PathBuf,
3737
pub source: std::io::Error,
3838
}
3939

40-
pub fn remove_dir_all(path: &Path) -> Result<(), RemoveDirAllError> {
40+
pub fn remove_dir_all(path: impl AsRef<Utf8Path>) -> Result<(), RemoveDirAllError> {
41+
let path = path.as_ref();
4142
std::fs::remove_dir_all(path).context(RemoveDirAllSnafu { path })
4243
}
4344

4445
#[derive(Snafu, Debug)]
45-
#[snafu(display("failed to remove file {}", path.display()))]
46+
#[snafu(display("failed to remove file {path}"))]
4647
pub struct RemoveFileError {
47-
pub path: PathBuf,
48+
pub path: Utf8PathBuf,
4849
pub source: std::io::Error,
4950
}
5051

51-
pub fn remove_file<P: AsRef<Path>>(path: P) -> Result<(), RemoveFileError> {
52+
pub fn remove_file<P: AsRef<Utf8Path>>(path: P) -> Result<(), RemoveFileError> {
5253
let path = path.as_ref();
5354
std::fs::remove_file(path).context(RemoveFileSnafu { path })
5455
}
5556

5657
#[derive(Snafu, Debug)]
57-
#[snafu(display("failed to write {}", path.display()))]
58+
#[snafu(display("failed to write {path}"))]
5859
pub struct WriteFileError {
59-
pub path: PathBuf,
60+
pub path: Utf8PathBuf,
6061
pub source: std::io::Error,
6162
}
6263

63-
pub fn write<P: AsRef<Path>, C: AsRef<[u8]>>(path: P, contents: C) -> Result<(), WriteFileError> {
64+
pub fn write<P: AsRef<Utf8Path>, C: AsRef<[u8]>>(
65+
path: P,
66+
contents: C,
67+
) -> Result<(), WriteFileError> {
6468
let path = path.as_ref();
6569
std::fs::write(path, contents).context(WriteFileSnafu { path })
6670
}

lib/icp-fs/src/json.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
use crate::fs::{ReadFileError, WriteFileError, read};
2+
use camino::{Utf8Path, Utf8PathBuf};
23
use serde::Serialize;
34
use snafu::prelude::*;
4-
use std::path::{Path, PathBuf};
55

66
#[derive(Snafu, Debug)]
77
pub enum LoadJsonFileError {
8-
#[snafu(display("failed to parse {} as json", path.display()))]
8+
#[snafu(display("failed to parse {path} as json"))]
99
Parse {
10-
path: PathBuf,
10+
path: Utf8PathBuf,
1111
source: serde_json::Error,
1212
},
1313

@@ -16,7 +16,7 @@ pub enum LoadJsonFileError {
1616
}
1717

1818
pub fn load_json_file<T: for<'a> serde::de::Deserialize<'a>>(
19-
path: impl AsRef<Path>,
19+
path: impl AsRef<Utf8Path>,
2020
) -> Result<T, LoadJsonFileError> {
2121
let path = path.as_ref();
2222
let content = read(path)?;
@@ -26,9 +26,9 @@ pub fn load_json_file<T: for<'a> serde::de::Deserialize<'a>>(
2626

2727
#[derive(Snafu, Debug)]
2828
pub enum SaveJsonFileError {
29-
#[snafu(display("failed to serialize json for {}", path.display()))]
29+
#[snafu(display("failed to serialize json for {path}"))]
3030
Serialize {
31-
path: PathBuf,
31+
path: Utf8PathBuf,
3232
source: serde_json::Error,
3333
},
3434

@@ -37,7 +37,7 @@ pub enum SaveJsonFileError {
3737
}
3838

3939
pub fn save_json_file<T: Serialize>(
40-
path: impl AsRef<Path>,
40+
path: impl AsRef<Utf8Path>,
4141
value: &T,
4242
) -> Result<(), SaveJsonFileError> {
4343
let path = path.as_ref();

0 commit comments

Comments
 (0)