Add checks for cleanCargoToml

This commit is contained in:
Ivan Petkov 2021-12-29 19:26:55 -08:00
parent a286fe1ff5
commit cf1c6eb0e8
No known key found for this signature in database
GPG Key ID: BB6F9EFC065832B6
12 changed files with 428 additions and 22 deletions

1
.gitignore vendored
View File

@ -1 +1,2 @@
/result*
target/

View File

@ -0,0 +1,212 @@
cargo-features = ["some unstable features"]
[package]
name = "some name"
version = "1.2.3"
authors = ["some author", "another author"]
edition = "2021"
rust-version = "1.56"
description = "some description"
documentation = "documentation url"
readme = "readme/path"
homepage = "some homepage"
repository = "some repository"
license = "some license"
license-file = "some license-file"
keywords = ["first keyword", "second keyword"]
categories = ["first category", "second category"]
workspace = "some/path/to/workspace"
build = "buildScript.rs"
links = "libfoo"
exclude = ["first exclude", "second exclude"]
include = ["first include", "second include"]
publish = true
default-run = "some default-run"
autobins = true
autoexamples = true
autotests = true
autobenches = true
resolver = "2"
[package.metadata.android]
package-name = "my-awesome-android-app"
assets = "path/to/static"
[lib]
name = "foo"
path = "src/lib.rs"
test = true
doctest = true
bench = true
doc = true
plugin = false
proc-macro = false
harness = true
edition = "2015"
crate-type = ["lib"]
required-features = ["libfeature1", "libfeature2"]
[[bin]]
name = "bin1"
path = "src/bin1.rs"
test = true
doctest = true
bench = true
doc = true
plugin = false
proc-macro = false
harness = true
edition = "2015"
required-features = ["bin1feature1", "bin1feature2"]
[[bin]]
name = "bin2"
path = "src/bin2.rs"
test = true
doctest = true
bench = true
doc = true
plugin = false
proc-macro = false
harness = true
edition = "2015"
required-features = ["bin2feature1", "bin2feature2"]
[[example]]
name = "example1"
path = "src/example1.rs"
test = true
doctest = true
bench = true
doc = true
plugin = false
proc-macro = false
harness = true
edition = "2015"
required-features = ["example1feature1", "example1feature2"]
[[example]]
name = "example2"
path = "src/example2.rs"
test = true
doctest = true
bench = true
doc = true
plugin = false
proc-macro = false
harness = true
edition = "2015"
required-features = ["example2feature1", "example2feature2"]
[[test]]
name = "test1"
path = "src/test1.rs"
test = true
doctest = true
bench = true
doc = true
plugin = false
proc-macro = false
harness = true
edition = "2015"
required-features = ["test1feature1", "test1feature2"]
[[test]]
name = "test2"
path = "src/test2.rs"
test = true
doctest = true
bench = true
doc = true
plugin = false
proc-macro = false
harness = true
edition = "2015"
required-features = ["test2feature1", "test2feature2"]
[[bench]]
name = "bench1"
path = "src/bench1.rs"
test = true
doctest = true
bench = true
doc = true
plugin = false
proc-macro = false
harness = true
edition = "2015"
required-features = ["bench1feature1", "bench1feature2"]
[[bench]]
name = "bench2"
path = "src/bench2.rs"
test = true
doctest = true
bench = true
doc = true
plugin = false
proc-macro = false
harness = true
edition = "2015"
required-features = ["bench2feature1", "bench2feature2"]
[dependencies]
foo = "1"
bar = { version = "2", features = ["bar-feature", "bar-another-feature"] }
[dependencies.baz]
version = "3"
features = [
"baz-feature",
"baz-feature2",
]
[dev-dependencies]
qux = "4"
[dev-dependencies.zuul]
version = "5"
[build-dependencies.corge]
version = "6"
[target.'cfg(unix)'.dependencies]
grault = "7"
[target.'cfg(target_arch = "x86")'.dependencies]
garply = "8"
[badges]
some-badge = "some-badge-value"
[features]
foofeature = []
barfeature = ["foofeature"]
[patch.crates-io]
foo = { git = 'https://github.com/example/foo' }
bar = { path = 'my/local/bar' }
[replace]
"foo2:0.1.0" = { git = 'https://github.com/example/foo2' }
"bar3:1.0.2" = { path = 'my/local/bar3' }
[profile.dev]
opt-level = 1
overflow-checks = false
[profile.release]
opt-level = 2
overflow-checks = true
[workspace]
members = ["member1", "path/to/member2", "crates/*"]
default-members = ["path/to/member2", "path/to/member3/foo"]
exclude = ["crates/foo", "path/to/other"]
[workspace.metadata.webcontents]
root = "path/to/webproject"
tool = ["npm", "run", "build"]
[some-unrecognized-object]
some-unrecognized-field = "some value"

View File

@ -0,0 +1,18 @@
{ cleanCargoToml
, runCommand
, writeTOML
}:
let
cleaned = cleanCargoToml {
cargoToml = ./Cargo.toml;
};
cleanedToml = runCommand "replaced.toml" { } ''
sed 's!/nix/store/[a-z0-9]\+-!/nix/store/!' \
${writeTOML "cleaned.toml" cleaned} >$out
'';
in
runCommand "compare" { } ''
diff ${./expected.toml} ${cleanedToml}
touch $out
''

View File

@ -0,0 +1,117 @@
cargo-features = ["some unstable features"]
[build-dependencies]
[build-dependencies.corge]
version = "6"
[dependencies]
foo = "1"
[dependencies.bar]
features = ["bar-feature", "bar-another-feature"]
version = "2"
[dependencies.baz]
features = ["baz-feature", "baz-feature2"]
version = "3"
[dev-dependencies]
qux = "4"
[dev-dependencies.zuul]
version = "5"
[features]
barfeature = ["foofeature"]
foofeature = []
[lib]
name = "foo"
path = "/nix/store/dummy.rs"
required-features = ["libfeature1", "libfeature2"]
[package]
name = "some name"
version = "1.2.3"
workspace = "some/path/to/workspace"
[patch]
[patch.crates-io]
[patch.crates-io.bar]
path = "my/local/bar"
[patch.crates-io.foo]
git = "https://github.com/example/foo"
[profile]
[profile.dev]
opt-level = 1
overflow-checks = false
[profile.release]
opt-level = 2
overflow-checks = true
[replace]
[replace."bar3:1.0.2"]
path = "my/local/bar3"
[replace."foo2:0.1.0"]
git = "https://github.com/example/foo2"
[some-unrecognized-object]
some-unrecognized-field = "some value"
[target]
[target."cfg(target_arch = \"x86\")"]
[target."cfg(target_arch = \"x86\")".dependencies]
garply = "8"
[target."cfg(unix)"]
[target."cfg(unix)".dependencies]
grault = "7"
[workspace]
default-members = ["path/to/member2", "path/to/member3/foo"]
exclude = ["crates/foo", "path/to/other"]
members = ["member1", "path/to/member2", "crates/*"]
[[bench]]
name = "bench1"
path = "/nix/store/dummy.rs"
required-features = ["bench1feature1", "bench1feature2"]
[[bench]]
name = "bench2"
path = "/nix/store/dummy.rs"
required-features = ["bench2feature1", "bench2feature2"]
[[bin]]
name = "bin1"
path = "/nix/store/dummy.rs"
required-features = ["bin1feature1", "bin1feature2"]
[[bin]]
name = "bin2"
path = "/nix/store/dummy.rs"
required-features = ["bin2feature1", "bin2feature2"]
[[example]]
name = "example1"
path = "/nix/store/dummy.rs"
required-features = ["example1feature1", "example1feature2"]
[[example]]
name = "example2"
path = "/nix/store/dummy.rs"
required-features = ["example2feature1", "example2feature2"]
[[test]]
name = "test1"
path = "/nix/store/dummy.rs"
required-features = ["test1feature1", "test1feature2"]
[[test]]
name = "test2"
path = "/nix/store/dummy.rs"
required-features = ["test2feature1", "test2feature2"]

View File

@ -0,0 +1,6 @@
[package]
name = "barebones"
version = "0.1.0"
[dependencies]
regex = "1"

View File

@ -0,0 +1,15 @@
{ cleanCargoToml
, runCommand
, writeTOML
}:
let
cleaned = cleanCargoToml {
cargoToml = ./Cargo.toml;
};
cleanedToml = writeTOML "cleaned.toml" cleaned;
in
runCommand "compare" { } ''
diff ${./expected.toml} ${cleanedToml}
touch $out
''

View File

@ -0,0 +1,6 @@
[dependencies]
regex = "1"
[package]
name = "barebones"
version = "0.1.0"

View File

@ -1,5 +1,11 @@
{ pkgs }:
{ myLib }:
let
callPackage = myLib.newScope { };
in
{
nixpkgs-fmt = pkgs.callPackage ./nixpkgs-fmt.nix { };
nixpkgs-fmt = callPackage ./nixpkgs-fmt.nix { };
cleanCargoTomlSimple = callPackage ./cleanCargoToml/simple { };
cleanCargoTomlComplex = callPackage ./cleanCargoToml/complex { };
}

View File

@ -29,7 +29,9 @@
inherit myPkgs;
};
checks = pkgs.callPackages ./checks { };
checks = pkgs.callPackages ./checks {
myLib = lib;
};
in
{
inherit checks lib;

View File

@ -4,8 +4,12 @@
}:
let
dummyLib = writeText "lib.rs" "#[test] fn it_works() {}";
dummyMain = writeText "main.rs" "fn main() {}";
dummyrs = writeText "dummy.rs" ''
#![allow(dead_code)]
pub fn main() {}
#[test]
fn it_works() {}
'';
# https://doc.rust-lang.org/cargo/reference/manifest.html#the-package-section
cleanPackage = package: removeAttrs package [
@ -42,7 +46,7 @@ let
];
# https://doc.rust-lang.org/cargo/reference/cargo-targets.html#configuring-a-target
cleanTargetCommon = pathReplacement: target:
cleanTargetCommon = target:
let
cleanedCommon =
removeAttrs target [
@ -62,11 +66,28 @@ let
# "required-features" # influences dependency feature combinations
];
in
cleanedCommon // { path = builtins.toString pathReplacement; };
cleanedCommon // { path = builtins.toString dummyrs; };
cleanWorkspace = workspace: removeAttrs workspace [
"metadata"
# Additional package attributes which are expressly kept in
# (but listed here for audit purposes)
# "default-members"
# "exclude"
# "members"
];
# https://doc.rust-lang.org/cargo/reference/manifest.html
cleanCargoToml = parsed:
let
safeClean = f: attr:
if builtins.hasAttr attr parsed
then { ${attr} = f (builtins.getAttr attr parsed); }
else { };
safeCleanList = f: safeClean (map f);
topLevelCleaned = removeAttrs parsed [
"badges" # Badges to display on a registry.
@ -80,20 +101,16 @@ let
# "profile" # this could influence how dependencies are built/optimized
# "replace" # (deprecated) configures sources as the project wants
# "target" # we want to build and cache these
# "workspace" # keep the workspace hierarchy as the project wants
];
recursivelyCleaned = {
package = cleanPackage (parsed.package or { });
lib = cleanTargetCommon dummyLib (parsed.lib or { });
bench = map (cleanTargetCommon dummyLib) (parsed.bench or [ ]);
bin = map (cleanTargetCommon dummyMain) (parsed.bin or [ ]);
example = map (cleanTargetCommon dummyLib) (parsed.example or [ ]);
test = map (cleanTargetCommon dummyLib) (parsed.test or [ ]);
};
in
topLevelCleaned // recursivelyCleaned;
topLevelCleaned
// (safeClean cleanPackage "package")
// (safeClean cleanTargetCommon "lib")
// (safeClean cleanWorkspace "workspace")
// (safeCleanList cleanTargetCommon "bench")
// (safeCleanList cleanTargetCommon "bin")
// (safeCleanList cleanTargetCommon "example")
// (safeCleanList cleanTargetCommon "test");
in
{ cargoToml ? throw "either cargoToml or cargoTomlContents must be specified"
, cargoTomlContents ? builtins.readFile cargoToml

View File

@ -7,14 +7,15 @@
lib.makeScope newScope (self:
let
callPackage = self.newScope { };
callPackage = self.newScope myPkgs;
in
myPkgs // {
inherit callPackage fromTOML toTOML;
{
inherit fromTOML toTOML;
buildWithCargo = callPackage ./buildWithCargo.nix { };
cleanCargoToml = callPackage ./cleanCargoToml.nix { };
downloadCargoPackage = callPackage ./downloadCargoPackage.nix { };
urlForCargoPackage = callPackage ./urlForCargoPackage.nix { };
vendorCargoDeps = callPackage ./vendorCargoDeps.nix { };
writeTOML = callPackage ./writeTOML.nix { };
})

5
lib/writeTOML.nix Normal file
View File

@ -0,0 +1,5 @@
{ toTOML
, writeText
}:
name: contents: writeText name ((toTOML contents) + "\n")