Skip to content

Commit d2a9e73

Browse files
committed
workspace: add Workspace::purge_all_caches method
1 parent 6f74e0a commit d2a9e73

File tree

6 files changed

+144
-2
lines changed

6 files changed

+144
-2
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
55

66
## Unreleased
77

8+
### Added
9+
10+
- New method `Workspace::purge_all_caches`
11+
812
### Changed
913

1014
- Subcommands executed in sandbox respect configs of parent command

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@ getrandom = { version = "0.1.12", features = ["std"] }
4545
[dev-dependencies]
4646
env_logger = "0.6.1"
4747
tiny_http = "0.7.0"
48+
sha1 = "0.6.0"

src/workspace.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,31 @@ impl Workspace {
220220
Ok(())
221221
}
222222

223+
/// Remove all the contents of the caches in the workspace, freeing disk space.
224+
pub fn purge_all_caches(&self) -> Result<(), Error> {
225+
let mut paths = vec![
226+
self.cache_dir(),
227+
self.cargo_home().join("git"),
228+
self.cargo_home().join("registry").join("src"),
229+
self.cargo_home().join("registry").join("cache"),
230+
];
231+
232+
for index in std::fs::read_dir(self.cargo_home().join("registry").join("index"))? {
233+
let index = index?;
234+
if index.file_type()?.is_dir() {
235+
paths.push(index.path().join(".cache"));
236+
}
237+
}
238+
239+
for path in &paths {
240+
if path.exists() {
241+
remove_dir_all(&path)?;
242+
}
243+
}
244+
245+
Ok(())
246+
}
247+
223248
/// Return a list of all the toolchains present in the workspace.
224249
///
225250
/// # Example

tests/integration/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
mod crates_git;
2+
mod purge_caches;

tests/integration/purge_caches.rs

Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
use failure::Error;
2+
use rustwide::cmd::SandboxBuilder;
3+
use rustwide::{Crate, Toolchain};
4+
use sha1::{Digest, Sha1};
5+
use std::collections::HashMap;
6+
use std::path::{Path, PathBuf};
7+
8+
const WORKSPACE_NAME: &str = "purge-caches";
9+
10+
#[test]
11+
fn test_purge_caches() -> Result<(), Error> {
12+
let workspace_path = crate::utils::workspace_path(WORKSPACE_NAME);
13+
let workspace = crate::utils::init_named_workspace(WORKSPACE_NAME)?;
14+
15+
// Do an initial purge to prevent stale files from being present.
16+
workspace.purge_all_build_dirs()?;
17+
workspace.purge_all_caches()?;
18+
19+
let toolchain = Toolchain::dist("stable");
20+
toolchain.install(&workspace)?;
21+
22+
let start_contents = WorkspaceContents::collect(&workspace_path)?;
23+
24+
let crates = vec![
25+
Crate::crates_io("lazy_static", "1.0.0"),
26+
Crate::git("https://github.com/pietroalbini/git-credential-null"),
27+
];
28+
29+
// Simulate a build, which is going to fill up the caches.
30+
for krate in &crates {
31+
krate.fetch(&workspace)?;
32+
33+
let sandbox = SandboxBuilder::new().enable_networking(false);
34+
let mut build_dir = workspace.build_dir("shared");
35+
build_dir.build(&toolchain, krate, sandbox).run(|build| {
36+
build.cargo().args(&["check"]).run()?;
37+
Ok(())
38+
})?;
39+
}
40+
41+
// After all the builds are done purge everything again, and ensure the contents are the same
42+
// as when we started.
43+
workspace.purge_all_build_dirs()?;
44+
workspace.purge_all_caches()?;
45+
let end_contents = WorkspaceContents::collect(&workspace_path)?;
46+
start_contents.assert_same(end_contents);
47+
48+
Ok(())
49+
}
50+
51+
#[derive(Debug, PartialEq, Eq)]
52+
struct WorkspaceContents {
53+
files: HashMap<PathBuf, Digest>,
54+
}
55+
56+
impl WorkspaceContents {
57+
fn collect(path: &Path) -> Result<Self, Error> {
58+
let mut files = HashMap::new();
59+
60+
for entry in walkdir::WalkDir::new(path) {
61+
let entry = entry?;
62+
if !entry.metadata()?.is_file() {
63+
continue;
64+
}
65+
66+
let mut sha = Sha1::new();
67+
sha.update(&std::fs::read(entry.path())?);
68+
69+
files.insert(entry.path().into(), sha.digest());
70+
}
71+
72+
Ok(Self { files })
73+
}
74+
75+
fn assert_same(self, mut other: Self) {
76+
let mut same = true;
77+
78+
println!("=== start directory differences ===");
79+
80+
for (path, start_digest) in self.files.into_iter() {
81+
if let Some(end_digest) = other.files.remove(&path) {
82+
if start_digest != end_digest {
83+
println!("file {} changed", path.display());
84+
same = false;
85+
}
86+
} else {
87+
println!("file {} was removed", path.display());
88+
same = false;
89+
}
90+
}
91+
92+
for (path, _) in other.files.into_iter() {
93+
println!("file {} was added", path.display());
94+
same = false;
95+
}
96+
97+
println!("=== end directory differences ===");
98+
99+
if !same {
100+
panic!("the contents of the directory changed");
101+
}
102+
}
103+
}

tests/utils/mod.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,21 @@
11
use failure::Error;
22
use log::LevelFilter;
33
use rustwide::{Workspace, WorkspaceBuilder};
4-
use std::path::Path;
4+
use std::path::{Path, PathBuf};
55

66
static USER_AGENT: &str = "rustwide-tests (https://github.com/rust-lang/rustwide)";
77

8+
pub(crate) fn workspace_path(name: &str) -> PathBuf {
9+
Path::new(".workspaces").join(name)
10+
}
11+
812
pub(crate) fn init_workspace() -> Result<Workspace, Error> {
13+
init_named_workspace("integration")
14+
}
15+
16+
pub(crate) fn init_named_workspace(name: &str) -> Result<Workspace, Error> {
917
init_logs();
10-
let workspace_path = Path::new(".workspaces").join("integration");
18+
let workspace_path = workspace_path(name);
1119
let mut builder = WorkspaceBuilder::new(&workspace_path, USER_AGENT).fast_init(true);
1220

1321
if std::env::var("RUSTWIDE_TEST_INSIDE_DOCKER").is_ok() {

0 commit comments

Comments
 (0)