From cf1c6eb0e86d74f38b181f64807ff696e527bc40 Mon Sep 17 00:00:00 2001 From: Ivan Petkov Date: Wed, 29 Dec 2021 19:26:55 -0800 Subject: [PATCH] Add checks for cleanCargoToml --- .gitignore | 1 + checks/cleanCargoToml/complex/Cargo.toml | 212 ++++++++++++++++++++ checks/cleanCargoToml/complex/default.nix | 18 ++ checks/cleanCargoToml/complex/expected.toml | 117 +++++++++++ checks/cleanCargoToml/simple/Cargo.toml | 6 + checks/cleanCargoToml/simple/default.nix | 15 ++ checks/cleanCargoToml/simple/expected.toml | 6 + checks/default.nix | 10 +- flake.nix | 4 +- lib/cleanCargoToml.nix | 49 +++-- lib/default.nix | 7 +- lib/writeTOML.nix | 5 + 12 files changed, 428 insertions(+), 22 deletions(-) create mode 100644 checks/cleanCargoToml/complex/Cargo.toml create mode 100644 checks/cleanCargoToml/complex/default.nix create mode 100644 checks/cleanCargoToml/complex/expected.toml create mode 100644 checks/cleanCargoToml/simple/Cargo.toml create mode 100644 checks/cleanCargoToml/simple/default.nix create mode 100644 checks/cleanCargoToml/simple/expected.toml create mode 100644 lib/writeTOML.nix diff --git a/.gitignore b/.gitignore index d6944e3..95c0648 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /result* +target/ diff --git a/checks/cleanCargoToml/complex/Cargo.toml b/checks/cleanCargoToml/complex/Cargo.toml new file mode 100644 index 0000000..50afcfd --- /dev/null +++ b/checks/cleanCargoToml/complex/Cargo.toml @@ -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" diff --git a/checks/cleanCargoToml/complex/default.nix b/checks/cleanCargoToml/complex/default.nix new file mode 100644 index 0000000..f76a532 --- /dev/null +++ b/checks/cleanCargoToml/complex/default.nix @@ -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 +'' diff --git a/checks/cleanCargoToml/complex/expected.toml b/checks/cleanCargoToml/complex/expected.toml new file mode 100644 index 0000000..548b726 --- /dev/null +++ b/checks/cleanCargoToml/complex/expected.toml @@ -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"] diff --git a/checks/cleanCargoToml/simple/Cargo.toml b/checks/cleanCargoToml/simple/Cargo.toml new file mode 100644 index 0000000..7cfc318 --- /dev/null +++ b/checks/cleanCargoToml/simple/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "barebones" +version = "0.1.0" + +[dependencies] +regex = "1" diff --git a/checks/cleanCargoToml/simple/default.nix b/checks/cleanCargoToml/simple/default.nix new file mode 100644 index 0000000..700efba --- /dev/null +++ b/checks/cleanCargoToml/simple/default.nix @@ -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 +'' diff --git a/checks/cleanCargoToml/simple/expected.toml b/checks/cleanCargoToml/simple/expected.toml new file mode 100644 index 0000000..326e46e --- /dev/null +++ b/checks/cleanCargoToml/simple/expected.toml @@ -0,0 +1,6 @@ +[dependencies] +regex = "1" + +[package] +name = "barebones" +version = "0.1.0" diff --git a/checks/default.nix b/checks/default.nix index 043112b..d655fe7 100644 --- a/checks/default.nix +++ b/checks/default.nix @@ -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 { }; } diff --git a/flake.nix b/flake.nix index cf8a06d..3e73355 100644 --- a/flake.nix +++ b/flake.nix @@ -29,7 +29,9 @@ inherit myPkgs; }; - checks = pkgs.callPackages ./checks { }; + checks = pkgs.callPackages ./checks { + myLib = lib; + }; in { inherit checks lib; diff --git a/lib/cleanCargoToml.nix b/lib/cleanCargoToml.nix index 502ae52..eaca37b 100644 --- a/lib/cleanCargoToml.nix +++ b/lib/cleanCargoToml.nix @@ -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 diff --git a/lib/default.nix b/lib/default.nix index 37df33f..baa3ee7 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -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 { }; }) diff --git a/lib/writeTOML.nix b/lib/writeTOML.nix new file mode 100644 index 0000000..bac8ffb --- /dev/null +++ b/lib/writeTOML.nix @@ -0,0 +1,5 @@ +{ toTOML +, writeText +}: + +name: contents: writeText name ((toTOML contents) + "\n")