Skip to content

Commit

Permalink
Ignore file support when finding buildpacks
Browse files Browse the repository at this point in the history
Previously we could rely on knowing that packaged buildpacks would be written to a location within the `target` directory configured in Crate. This was easy to determine through program code and could be supplied to `find_buildpack_dirs` so that packaged buildpacks weren't accidentally included when searching for buildpacks.

With the changes introduced in [#583](#583) it is no longer possible to easily determine the output location for packaged buildpacks. This PR adds the [ignore](https://crates.io/crates/ignore) crate to provide directory iteration that respects standard ignore files. This will give the user the ability to configure where we search within a project for buildpacks.
  • Loading branch information
colincasey committed Sep 13, 2023
1 parent b149bfb commit d149b15
Show file tree
Hide file tree
Showing 5 changed files with 17 additions and 34 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `libcnb-cargo`:
- No longer outputs paths for non-libcnb.rs and non-meta buildpacks. ([#657](https://github.com/heroku/libcnb.rs/pull/657))
- Build output for humans changed slightly, output intended for machines/scripting didn't change. ([#657](https://github.com/heroku/libcnb.rs/pull/657))
- `libcnb-package`
- dropped `ignore` argument from `find_buildpack_dirs` that allowed for paths to be filtered out of the directory traversal. This function will now respect standard ignore files (like `.gitignore`) while traversing.

## [0.14.0] - 2023-08-18

Expand Down
5 changes: 2 additions & 3 deletions libcnb-cargo/src/package/command.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,8 @@ pub(crate) fn execute(args: &PackageArgs) -> Result<(), Error> {
};

eprintln!("🏗️ Building buildpack dependency graph...");
let buildpack_dependency_graph =
build_libcnb_buildpacks_dependency_graph(&workspace_root_path, &[&package_dir])
.map_err(Error::CannotBuildBuildpackDependencyGraph)?;
let buildpack_dependency_graph = build_libcnb_buildpacks_dependency_graph(&workspace_root_path)
.map_err(Error::CannotBuildBuildpackDependencyGraph)?;

eprintln!("🔀 Determining build order...");
let root_nodes = buildpack_dependency_graph
Expand Down
1 change: 1 addition & 0 deletions libcnb-package/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ include = ["src/**/*", "LICENSE", "README.md"]

[dependencies]
cargo_metadata = "0.17.0"
ignore = "0.4"
libcnb-common.workspace = true
libcnb-data.workspace = true
petgraph = { version = "0.6.3", default-features = false }
Expand Down
5 changes: 2 additions & 3 deletions libcnb-package/src/buildpack_dependency_graph.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,8 @@ use std::path::{Path, PathBuf};
/// package.toml or an IO error occurred while traversing the given directory.
pub fn build_libcnb_buildpacks_dependency_graph(
cargo_workspace_root: &Path,
ignore: &[&Path],
) -> Result<Graph<BuildpackDependencyGraphNode, ()>, BuildBuildpackDependencyGraphError> {
find_buildpack_dirs(cargo_workspace_root, ignore)
find_buildpack_dirs(cargo_workspace_root)
.map_err(BuildBuildpackDependencyGraphError::FindBuildpackDirectories)
.and_then(|buildpack_directories| {
buildpack_directories
Expand Down Expand Up @@ -86,7 +85,7 @@ fn build_libcnb_buildpack_dependency_graph_node(
#[derive(thiserror::Error, Debug)]
pub enum BuildBuildpackDependencyGraphError {
#[error("IO error while finding buildpack directories: {0}")]
FindBuildpackDirectories(std::io::Error),
FindBuildpackDirectories(ignore::Error),
#[error("Cannot read buildpack descriptor: {0}")]
ReadBuildpackDescriptorError(TomlFileError),
#[error("Cannot read package descriptor: {0}")]
Expand Down
38 changes: 10 additions & 28 deletions libcnb-package/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,38 +106,20 @@ fn create_file_symlink<P: AsRef<Path>, Q: AsRef<Path>>(
///
/// # Errors
///
/// Will return an `Err` if any I/O errors happen while walking the file system.
pub fn find_buildpack_dirs(start_dir: &Path, ignore: &[&Path]) -> std::io::Result<Vec<PathBuf>> {
fn find_buildpack_dirs_recursive(
path: &Path,
ignore: &[&Path],
accumulator: &mut Vec<PathBuf>,
) -> std::io::Result<()> {
if ignore.contains(&path) {
return Ok(());
}

let metadata = path.metadata()?;
if metadata.is_dir() {
let entries = fs::read_dir(path)?;
for entry in entries {
let entry = entry?;
let metadata = entry.metadata()?;
if metadata.is_dir() {
find_buildpack_dirs_recursive(&entry.path(), ignore, accumulator)?;
} else if let Some(file_name) = entry.path().file_name() {
if file_name.to_string_lossy() == "buildpack.toml" {
accumulator.push(path.to_path_buf());
}
/// Will return an `Err` if any I/O errors happen while walking the file system or any parsing errors
/// from reading a gitignore file.
pub fn find_buildpack_dirs(start_dir: &Path) -> Result<Vec<PathBuf>, ignore::Error> {
let mut buildpack_dirs = vec![];
for result in ignore::Walk::new(start_dir) {
match result {
Ok(entry) => {
if entry.path().is_dir() && entry.path().join("buildpack.toml").exists() {
buildpack_dirs.push(entry.path().to_path_buf());
}
}
Err(error) => return Err(error),
}

Ok(())
}

let mut buildpack_dirs: Vec<PathBuf> = vec![];
find_buildpack_dirs_recursive(start_dir, ignore, &mut buildpack_dirs)?;
Ok(buildpack_dirs)
}

Expand Down

0 comments on commit d149b15

Please sign in to comment.