Skip to content

Commit 385c613

Browse files
onbjergryzhak
andauthored
fix: canonicalize paths in forge doc (#11406)
* chore: make fields non-pub * fix: canonicalize paths in `forge doc` Co-authored-by: ryzhak <[email protected]> * fix: create output directory before canonicalizing --------- Co-authored-by: ryzhak <[email protected]>
1 parent 3247715 commit 385c613

File tree

1 file changed

+27
-22
lines changed

1 file changed

+27
-22
lines changed

crates/doc/src/builder.rs

Lines changed: 27 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::{
33
document::DocumentContent, helpers::merge_toml_table,
44
};
55
use alloy_primitives::map::HashMap;
6+
use eyre::{Context, Result};
67
use forge_fmt::{FormatterConfig, Visitable};
78
use foundry_compilers::{compilers::solc::SOLC_EXTENSIONS, utils::source_files_iter};
89
use foundry_config::{DocConfig, filter::expand_globs};
@@ -22,24 +23,23 @@ use toml::value;
2223
#[derive(Debug)]
2324
pub struct DocBuilder {
2425
/// The project root
25-
pub root: PathBuf,
26+
root: PathBuf,
2627
/// Path to Solidity source files.
27-
pub sources: PathBuf,
28+
sources: PathBuf,
2829
/// Paths to external libraries.
29-
pub libraries: Vec<PathBuf>,
30+
libraries: Vec<PathBuf>,
3031
/// Flag whether to build mdbook.
31-
pub should_build: bool,
32+
should_build: bool,
3233
/// Documentation configuration.
33-
pub config: DocConfig,
34+
config: DocConfig,
3435
/// The array of preprocessors to apply.
35-
pub preprocessors: Vec<Box<dyn Preprocessor>>,
36+
preprocessors: Vec<Box<dyn Preprocessor>>,
3637
/// The formatter config.
37-
pub fmt: FormatterConfig,
38+
fmt: FormatterConfig,
3839
/// Whether to include libraries to the output.
39-
pub include_libraries: bool,
40+
include_libraries: bool,
4041
}
4142

42-
// TODO: consider using `tfio`
4343
impl DocBuilder {
4444
pub(crate) const SRC: &'static str = "src";
4545
const SOL_EXT: &'static str = "sol";
@@ -90,12 +90,15 @@ impl DocBuilder {
9090
}
9191

9292
/// Get the output directory
93-
pub fn out_dir(&self) -> PathBuf {
94-
self.root.join(&self.config.out)
93+
pub fn out_dir(&self) -> Result<PathBuf> {
94+
Ok(self.root.join(&self.config.out).canonicalize()?)
9595
}
9696

9797
/// Parse the sources and build the documentation.
9898
pub fn build(self) -> eyre::Result<()> {
99+
fs::create_dir_all(self.root.join(&self.config.out))
100+
.wrap_err("failed to create output directory")?;
101+
99102
// Expand ignore globs
100103
let ignored = expand_globs(&self.root, self.config.ignore.iter())?;
101104

@@ -121,6 +124,7 @@ impl DocBuilder {
121124
.chain(library_sources.iter().map(|path| (path, true)))
122125
.collect::<Vec<_>>();
123126

127+
let out_dir = self.out_dir()?;
124128
let documents = combined_sources
125129
.par_iter()
126130
.enumerate()
@@ -181,7 +185,8 @@ impl DocBuilder {
181185
.into_iter()
182186
.map(|item| {
183187
let relative_path = path.strip_prefix(&self.root)?.join(item.filename());
184-
let target_path = self.config.out.join(Self::SRC).join(relative_path);
188+
189+
let target_path = out_dir.join(Self::SRC).join(relative_path);
185190
let ident = item.source.ident();
186191
Ok(Document::new(
187192
path.clone(),
@@ -206,7 +211,7 @@ impl DocBuilder {
206211
name
207212
};
208213
let relative_path = path.strip_prefix(&self.root)?.join(filename);
209-
let target_path = self.config.out.join(Self::SRC).join(relative_path);
214+
let target_path = out_dir.join(Self::SRC).join(relative_path);
210215

211216
let identity = match filestem {
212217
Some(stem) if stem.to_lowercase().contains("constants") => stem.to_owned(),
@@ -230,7 +235,8 @@ impl DocBuilder {
230235
for (ident, funcs) in overloaded {
231236
let filename = funcs.first().expect("no overloaded functions").filename();
232237
let relative_path = path.strip_prefix(&self.root)?.join(filename);
233-
let target_path = self.config.out.join(Self::SRC).join(relative_path);
238+
239+
let target_path = out_dir.join(Self::SRC).join(relative_path);
234240
files.push(
235241
Document::new(
236242
path.clone(),
@@ -267,7 +273,7 @@ impl DocBuilder {
267273

268274
// Build the book if requested
269275
if self.should_build {
270-
MDBook::load(self.out_dir())
276+
MDBook::load(self.out_dir().wrap_err("failed to construct output directory")?)
271277
.and_then(|book| book.build())
272278
.map_err(|err| eyre::eyre!("failed to build book: {err:?}"))?;
273279
}
@@ -276,7 +282,7 @@ impl DocBuilder {
276282
}
277283

278284
fn write_mdbook(&self, documents: Vec<Document>) -> eyre::Result<()> {
279-
let out_dir = self.out_dir();
285+
let out_dir = self.out_dir().wrap_err("failed to construct output directory")?;
280286
let out_dir_src = out_dir.join(Self::SRC);
281287
fs::create_dir_all(&out_dir_src)?;
282288

@@ -321,11 +327,11 @@ impl DocBuilder {
321327
fs::write(out_dir.join("book.css"), include_str!("../static/book.css"))?;
322328

323329
// Write book config
324-
fs::write(self.out_dir().join("book.toml"), self.book_config()?)?;
330+
fs::write(out_dir.join("book.toml"), self.book_config()?)?;
325331

326332
// Write .gitignore
327333
let gitignore = "book/";
328-
fs::write(self.out_dir().join(".gitignore"), gitignore)?;
334+
fs::write(out_dir.join(".gitignore"), gitignore)?;
329335

330336
// Write doc files
331337
for document in documents {
@@ -427,15 +433,14 @@ impl DocBuilder {
427433
}
428434
});
429435

436+
let out_dir = self.out_dir().wrap_err("failed to construct output directory")?;
430437
let mut readme = BufWriter::new("\n\n# Contents\n");
431438
for (path, files) in grouped {
432439
if path.extension().map(|ext| ext == Self::SOL_EXT).unwrap_or_default() {
433440
for file in files {
434441
let ident = &file.identity;
435442

436-
let summary_path = file
437-
.target_path
438-
.strip_prefix(self.out_dir().strip_prefix(&self.root)?.join(Self::SRC))?;
443+
let summary_path = &file.target_path.strip_prefix(out_dir.join(Self::SRC))?;
439444
summary.write_link_list_item(
440445
ident,
441446
&summary_path.display().to_string(),
@@ -458,7 +463,7 @@ impl DocBuilder {
458463
if !readme.is_empty()
459464
&& let Some(path) = base_path
460465
{
461-
let path = self.out_dir().join(Self::SRC).join(path);
466+
let path = out_dir.join(Self::SRC).join(path);
462467
fs::create_dir_all(&path)?;
463468
fs::write(path.join(Self::README), readme.finish())?;
464469
}

0 commit comments

Comments
 (0)