Skip to content

Commit 22e3b97

Browse files
authored
Merge pull request #56 from regexident/path-patch
Add support for path-based patches
2 parents bca69a8 + 1bcae84 commit 22e3b97

File tree

10 files changed

+155
-23
lines changed

10 files changed

+155
-23
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 `BuildBuilder::patch_with_path()` for path-based patching (as compared to git-based).
11+
812
## [0.14.0] - 2021-08-19
913

1014
### Added

src/build.rs

Lines changed: 50 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,24 @@ use std::path::PathBuf;
66
use std::vec::Vec;
77

88
#[derive(Clone)]
9-
pub(crate) struct CratePatch {
9+
pub(crate) enum CratePatch {
10+
Git(GitCratePatch),
11+
Path(PathCratePatch),
12+
}
13+
14+
#[derive(Clone)]
15+
pub(crate) struct GitCratePatch {
1016
pub(crate) name: String,
1117
pub(crate) uri: String,
1218
pub(crate) branch: String,
1319
}
1420

21+
#[derive(Clone)]
22+
pub(crate) struct PathCratePatch {
23+
pub(crate) name: String,
24+
pub(crate) path: String,
25+
}
26+
1527
/// Directory in the [`Workspace`](struct.Workspace.html) where builds can be executed.
1628
///
1729
/// The build directory contains the source code of the crate being built and the target directory
@@ -32,7 +44,7 @@ pub struct BuildBuilder<'a> {
3244
}
3345

3446
impl<'a> BuildBuilder<'a> {
35-
/// Add a patch to this build.
47+
/// Add a git-based patch to this build.
3648
/// Patches get added to the crate's Cargo.toml in the `patch.crates-io` table.
3749
/// # Example
3850
///
@@ -54,11 +66,45 @@ impl<'a> BuildBuilder<'a> {
5466
/// # Ok(())
5567
/// # }
5668
pub fn patch_with_git(mut self, name: &str, uri: &str, branch: &str) -> Self {
57-
self.patches.push(CratePatch {
69+
self.patches.push(CratePatch::Git(GitCratePatch {
5870
name: name.into(),
5971
uri: uri.into(),
6072
branch: branch.into(),
61-
});
73+
}));
74+
self
75+
}
76+
77+
/// Add a path-based patch to this build.
78+
/// Patches get added to the crate's Cargo.toml in the `patch.crates-io` table.
79+
/// # Example
80+
///
81+
/// ```no_run
82+
/// # use rustwide::{WorkspaceBuilder, Toolchain, Crate, cmd::{MountKind, SandboxBuilder}};
83+
/// # use std::{error::Error, path::{Path, PathBuf}};
84+
/// # fn main() -> Result<(), Box<dyn Error>> {
85+
/// # let workspace = WorkspaceBuilder::new("".as_ref(), "").init()?;
86+
/// # let toolchain = Toolchain::dist("");
87+
/// # let krate = Crate::local("".as_ref());
88+
/// # let manifest_dir = "/path/to/bar";
89+
/// let sandbox = SandboxBuilder::new().mount(
90+
/// Path::new(manifest_dir),
91+
/// Path::new("/patch/bar"),
92+
/// MountKind::ReadOnly,
93+
/// );
94+
/// let mut build_dir = workspace.build_dir("foo");
95+
/// build_dir.build(&toolchain, &krate, sandbox)
96+
/// .patch_with_path("bar", "/patch/bar")
97+
/// .run(|build| {
98+
/// build.cargo().args(&["test", "--all"]).run()?;
99+
/// Ok(())
100+
/// })?;
101+
/// # Ok(())
102+
/// # }
103+
pub fn patch_with_path(mut self, name: &str, path: &str) -> Self {
104+
self.patches.push(CratePatch::Path(PathCratePatch {
105+
name: name.into(),
106+
path: path.into(),
107+
}));
62108
self
63109
}
64110

src/prepare.rs

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -312,13 +312,24 @@ impl<'a> TomlTweaker<'a> {
312312
};
313313

314314
for patch in self.patches.iter().cloned() {
315-
let mut table = Table::new();
316-
table.insert("git".into(), Value::String(patch.uri));
317-
table.insert("branch".into(), Value::String(patch.branch));
315+
let (name, table) = match patch {
316+
CratePatch::Git(patch) => {
317+
let mut table = Table::new();
318+
table.insert("git".into(), Value::String(patch.uri));
319+
table.insert("branch".into(), Value::String(patch.branch));
320+
(patch.name, table)
321+
}
322+
CratePatch::Path(patch) => {
323+
let mut table = Table::new();
324+
table.insert("path".into(), Value::String(patch.path.clone()));
325+
(patch.name, table)
326+
}
327+
};
328+
318329
cratesio_table
319330
.as_table_mut()
320331
.unwrap()
321-
.insert(patch.name, Value::Table(table));
332+
.insert(name, Value::Table(table));
322333
}
323334
}
324335
}
@@ -361,7 +372,7 @@ pub enum PrepareError {
361372
#[cfg(test)]
362373
mod tests {
363374
use super::TomlTweaker;
364-
use crate::build::CratePatch;
375+
use crate::build::{CratePatch, GitCratePatch, PathCratePatch};
365376
use crate::crates::Crate;
366377
use toml::{self, Value};
367378

@@ -459,14 +470,21 @@ mod tests {
459470

460471
[patch.crates-io]
461472
quux = { git = "https://git.example.com/quux", branch = "dev" }
473+
baz = { path = "/path/to/baz" }
462474
};
463475

464476
let krate = Crate::local("/dev/null".as_ref());
465-
let patches = vec![CratePatch {
466-
name: "quux".into(),
467-
uri: "https://git.example.com/quux".into(),
468-
branch: "dev".into(),
469-
}];
477+
let patches = vec![
478+
CratePatch::Git(GitCratePatch {
479+
name: "quux".into(),
480+
uri: "https://git.example.com/quux".into(),
481+
branch: "dev".into(),
482+
}),
483+
CratePatch::Path(PathCratePatch {
484+
name: "baz".into(),
485+
path: "/path/to/baz".into(),
486+
}),
487+
];
470488
let mut tweaker =
471489
TomlTweaker::new_with_table(&krate, toml.as_table().unwrap().clone(), &patches);
472490
tweaker.tweak();
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
[package]
2+
name = "path-based-patch"
3+
version = "0.1.0"
4+
authors = ["Pietro Albini <[email protected]>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
10+
empty-library = "1.0.0"
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
[package]
2+
name = "empty-library"
3+
version = "1.0.1"
4+
authors = ["Pietro Albini <[email protected]>"]
5+
edition = "2018"
6+
7+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
8+
9+
[dependencies]
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
pub fn dummy() {
2+
println!("This is coming from the patch!");
3+
}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
fn main() {
2+
println!("Hello, world!");
3+
empty_library::dummy();
4+
}

tests/buildtest/inside_docker.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,12 @@ fn test_hello_world() {
1515
execute("buildtest::test_hello_world").unwrap();
1616
}
1717

18+
#[test]
19+
#[cfg(unix)]
20+
fn test_path_based_patch() {
21+
execute("buildtest::path_based_patch").unwrap();
22+
}
23+
1824
fn execute(test: &str) -> Result<(), Error> {
1925
// The current working directory is mounted in the container to /outside.
2026
// The binary to execute is remapped to be prefixed by /outside instead of the current

tests/buildtest/mod.rs

Lines changed: 29 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ mod inside_docker;
99
#[test]
1010
fn test_hello_world() {
1111
runner::run("hello-world", |run| {
12-
run.build(SandboxBuilder::new().enable_networking(false), |build| {
12+
run.run(SandboxBuilder::new().enable_networking(false), |build| {
1313
let storage = rustwide::logging::LogStorage::new(LevelFilter::Info);
1414
rustwide::logging::capture(&storage, || -> Result<_, Error> {
1515
build.cargo().args(&["run"]).run()?;
@@ -26,10 +26,34 @@ fn test_hello_world() {
2626
});
2727
}
2828

29+
#[test]
30+
fn path_based_patch() {
31+
runner::run("path-based-patch", |run| {
32+
run.build(SandboxBuilder::new().enable_networking(false), |builder| {
33+
builder
34+
.patch_with_path("empty-library", "./patch")
35+
.run(move |build| {
36+
let storage = rustwide::logging::LogStorage::new(LevelFilter::Info);
37+
rustwide::logging::capture(&storage, || -> Result<_, Error> {
38+
build.cargo().args(&["run"]).run()?;
39+
Ok(())
40+
})?;
41+
42+
assert!(storage.to_string().contains("[stdout] Hello, world!\n"));
43+
assert!(storage
44+
.to_string()
45+
.contains("[stdout] This is coming from the patch!\n"));
46+
Ok(())
47+
})
48+
})?;
49+
Ok(())
50+
});
51+
}
52+
2953
#[test]
3054
fn test_process_lines() {
3155
runner::run("process-lines", |run| {
32-
run.build(SandboxBuilder::new().enable_networking(false), |build| {
56+
run.run(SandboxBuilder::new().enable_networking(false), |build| {
3357
let storage = rustwide::logging::LogStorage::new(LevelFilter::Info);
3458
let mut ex = false;
3559
rustwide::logging::capture(&storage, || -> Result<_, Error> {
@@ -64,7 +88,7 @@ fn test_sandbox_oom() {
6488
use rustwide::cmd::CommandError;
6589

6690
runner::run("out-of-memory", |run| {
67-
let res = run.build(
91+
let res = run.run(
6892
SandboxBuilder::new()
6993
.enable_networking(false)
7094
.memory_limit(Some(512 * 1024 * 1024)),
@@ -85,7 +109,7 @@ fn test_sandbox_oom() {
85109
#[test]
86110
fn test_override_files() {
87111
runner::run("cargo-config", |run| {
88-
run.build(SandboxBuilder::new().enable_networking(false), |build| {
112+
run.run(SandboxBuilder::new().enable_networking(false), |build| {
89113
let storage = rustwide::logging::LogStorage::new(LevelFilter::Info);
90114
rustwide::logging::capture(&storage, || -> Result<_, Error> {
91115
build.cargo().args(&["--version"]).run()?;
@@ -104,7 +128,7 @@ fn test_override_files() {
104128
#[test]
105129
fn test_cargo_workspace() {
106130
runner::run("cargo-workspace", |run| {
107-
run.build(SandboxBuilder::new().enable_networking(false), |build| {
131+
run.run(SandboxBuilder::new().enable_networking(false), |build| {
108132
let storage = rustwide::logging::LogStorage::new(LevelFilter::Info);
109133
rustwide::logging::capture(&storage, || -> Result<_, Error> {
110134
build.cargo().args(&["run"]).run()?;

tests/buildtest/runner.rs

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use failure::Error;
2-
use rustwide::{cmd::SandboxBuilder, Build, Crate, Toolchain, Workspace};
2+
use rustwide::{cmd::SandboxBuilder, Build, BuildBuilder, Crate, Toolchain, Workspace};
33
use std::path::Path;
44

55
pub(crate) fn run(crate_name: &str, f: impl FnOnce(&mut Runner) -> Result<(), Error>) {
@@ -38,11 +38,19 @@ impl Runner {
3838
pub(crate) fn build<T>(
3939
&self,
4040
sandbox: SandboxBuilder,
41-
f: impl FnOnce(&Build) -> Result<T, Error>,
41+
f: impl FnOnce(BuildBuilder) -> Result<T, Error>,
4242
) -> Result<T, Error> {
4343
let mut dir = self.workspace.build_dir(&self.crate_name);
4444
dir.purge()?;
45-
dir.build(&self.toolchain, &self.krate, sandbox).run(f)
45+
f(dir.build(&self.toolchain, &self.krate, sandbox))
46+
}
47+
48+
pub(crate) fn run<T>(
49+
&self,
50+
sandbox: SandboxBuilder,
51+
f: impl FnOnce(&Build) -> Result<T, Error>,
52+
) -> Result<T, Error> {
53+
self.build(sandbox, |builder| builder.run(f))
4654
}
4755
}
4856

@@ -51,7 +59,7 @@ macro_rules! test_prepare_error {
5159
#[test]
5260
fn $name() {
5361
runner::run($krate, |run| {
54-
let res = run.build(
62+
let res = run.run(
5563
rustwide::cmd::SandboxBuilder::new().enable_networking(false),
5664
|_| Ok(()),
5765
);

0 commit comments

Comments
 (0)