# Cicero Distribution

Need to pack multiple files into a distribution?

Cicero provides an API for specifying the file structure and then deferring to your functions to provide the contents:

```rust,no_run
#[cfg(feature = "build")] {

    use std::{fs, path::Path};
    use cicero_distribution::{Distribution, build::Target, bundle::dir::DirBundler};
    use cicero_path::repo_path;

    fn main() -> cicero_core::Result<()> {
        let distribution = Distribution::new("myproject")?;
        let target = Target::x86_64_unknown_linux_gnu;

        distribution
            .add_file_from_path("README.md", repo_path!("README.md"))?
            .add_file("myproject", |file| build_backend_executable(file, &target))?;

        distribution
            .dir("public")?
            .add_all(|dir| build_frontend(dir))?;

        let distribution_dir = distribution.bundle(DirBundler)?;
        Ok(())
    }

    fn build_frontend(out_dir: &Path) -> cicero_core::Result<()> {
        let build_out_dir: &Path = unimplemented!();
        fs::rename(build_out_dir, out_dir)?;
        Ok(())
    }

    fn build_backend_executable(out_file: &Path, target: &Target) -> cicero_core::Result<()> {
        let build_out_file: &Path = unimplemented!();
        fs::rename(build_out_file, out_file)?;
        Ok(())
    }
}
```

Advantages to this approach:
1) File structure is documented and trivially correct.
2) Conflicts due to two code locations modifying the same files are practically eliminated.
3) Obvious where to jump into the code to change a portion of the distribution.
4) Less path wrangling. Your function has the complete path passed to it. No need to modify it further.
5) Your functions become naturally testable. You can pass a temporary path (e.g. from `assert_fs`) instead and assert on that.


Mind that this API may still see larger changes, as more features are implemented.
