Skip to content

Commit

Permalink
Make dumping an empty cache succeed. (#916)
Browse files Browse the repository at this point in the history
This PR fixes a number of errors that can happen during dump when the cache is
missing certain directories.
  • Loading branch information
partim authored Jan 10, 2024
1 parent 6176551 commit 2127e50
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 10 deletions.
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@ on:
push:
branches:
- main
- series-*
pull_request:
branches:
- main
- series-*
jobs:
test:
name: test
Expand Down
3 changes: 2 additions & 1 deletion doc/manual/source/requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,5 @@ sphinx-version-warning==1.1.2
sphinx-tabs==3.2.0
sphinx-copybutton==0.4.0
sphinx-notfound-page
toml
sphinx_rtd_theme
toml
1 change: 1 addition & 0 deletions src/collector/rrdp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ impl Collector {
repos: DumpRegistry,
states: HashMap<uri::Https, RepositoryState>,
) -> Result<(), Failed> {
fatal::create_dir_all(repos.base_dir())?;
let path = repos.base_dir().join("repositories.json");
if let Err(err) = fs::write(
&path,
Expand Down
2 changes: 1 addition & 1 deletion src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1119,7 +1119,7 @@ impl Config {
///
/// Uses default values for everything except for the cache directory
/// which needs to be provided.
fn default_with_paths(cache_dir: PathBuf) -> Self {
pub fn default_with_paths(cache_dir: PathBuf) -> Self {
Config {
cache_dir,
no_rir_tals: false,
Expand Down
21 changes: 21 additions & 0 deletions src/engine.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2020,3 +2020,24 @@ pub trait ProcessPubPoint: Sized + Send + Sync {
}
}


//============ Tests =========================================================

#[cfg(test)]
mod test {
use super::*;

#[test]
fn dump_empty_cache() {
let _ = crate::process::Process::init(); // May be inited already.
let src = tempfile::tempdir().unwrap();
let target = tempfile::tempdir().unwrap();
let target = target.path().join("dump");
let mut config = Config::default_with_paths(src.path().into());
config.rsync_command = "echo".into();
config.rsync_args = Some(vec!["some".into()]);
let engine = Engine::new(&config, true).unwrap();
engine.dump(&target).unwrap();
}
}

9 changes: 7 additions & 2 deletions src/store.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,7 +174,7 @@ impl Store {
let target = target_base.join("ta");
debug!("Dumping trust anchor certificates to {}", target.display());
fatal::remove_dir_all(&target)?;
fatal::copy_dir_all(&source, &target)?;
fatal::try_copy_dir_all(&source, &target)?;
debug!("Trust anchor certificate dump complete.");
Ok(())
}
Expand All @@ -188,7 +188,11 @@ impl Store {
path: &Path,
repos: &mut DumpRegistry,
) -> Result<(), Failed> {
for entry in fatal::read_dir(path)? {
let dir = match fatal::try_read_dir(path)? {
Some(dir) => dir,
None => return Ok(())
};
for entry in dir {
let entry = entry?;
if entry.is_dir() {
self.dump_tree(entry.path(), repos)?;
Expand Down Expand Up @@ -295,6 +299,7 @@ impl Store {
&self,
repos: DumpRegistry,
) -> Result<(), Failed> {
fatal::create_dir_all(repos.base_dir())?;
let path = repos.base_dir().join("repositories.json");
fatal::write_file(
&path,
Expand Down
38 changes: 32 additions & 6 deletions src/utils/fatal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,28 @@ pub fn read_dir(path: &Path) -> Result<ReadDir, Failed> {
}


//------------ try_read_dir --------------------------------------------------

/// Returns an iterator over a directory if it exists.
pub fn try_read_dir(path: &Path) -> Result<Option<ReadDir>, Failed> {
match fs::read_dir(path) {
Ok(iter) => Ok(Some(ReadDir { path, iter })),
Err(err) => {
if err.kind() == io::ErrorKind::NotFound {
Ok(None)
}
else {
error!(
"Fatal: failed to open directory {}: {}",
path.display(), IoErrorDisplay(err)
);
Err(Failed)
}
}
}
}


//------------ read_existing_dir ---------------------------------------------

/// Returns an iterator over an existing directory.
Expand Down Expand Up @@ -316,15 +338,19 @@ pub fn write_file(path: &Path, contents: &[u8]) -> Result<(), Failed> {
}


//------------ copy_dir_all --------------------------------------------------
//------------ try_copy_dir_all ----------------------------------------------

/// Copies the content of a directory.
///
/// Creates the target directory with `create_dir_all`. Errors out if
/// anything goes wrong.
pub fn copy_dir_all(source: &Path, target: &Path) -> Result<(), Failed> {
/// Creates the target directory with `create_dir_all`. Errors out if
/// anything goes wrong. The source path not existing is not an error.
pub fn try_copy_dir_all(source: &Path, target: &Path) -> Result<(), Failed> {
let source_dir = match try_read_dir(source)? {
Some(entry) => entry,
None => return Ok(()),
};
create_dir_all(target)?;
for entry in read_dir(source)? {
for entry in source_dir {
let entry = entry?;
if entry.is_file() {
if let Err(err) = fs::copy(
Expand All @@ -338,7 +364,7 @@ pub fn copy_dir_all(source: &Path, target: &Path) -> Result<(), Failed> {
}
}
else if entry.is_dir() {
copy_dir_all(
try_copy_dir_all(
entry.path(),
&target.join(entry.file_name())
)?;
Expand Down

0 comments on commit 2127e50

Please sign in to comment.