diff --git a/.lintignore b/.lintignore new file mode 100644 index 00000000000..dd3af6cbdc5 --- /dev/null +++ b/.lintignore @@ -0,0 +1,5 @@ +third_party/ +**/generated/ +**/jni/ +stage0_bin/supply-chain +linter/tests/testdata diff --git a/Cargo.bazel.lock b/Cargo.bazel.lock index 07d37731ed8..0933eba6cf9 100644 --- a/Cargo.bazel.lock +++ b/Cargo.bazel.lock @@ -338,6 +338,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "bstr" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -494,6 +504,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +[[package]] +name = "colored" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +dependencies = [ + "lazy_static", + "windows-sys 0.48.0", +] + [[package]] name = "command-fds" version = "0.3.0" @@ -545,6 +565,31 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "crunchy" version = "0.2.2" @@ -742,6 +787,7 @@ dependencies = [ "bytes", "ciborium", "clap", + "colored", "command-fds", "coset", "curve25519-dalek", @@ -754,6 +800,8 @@ dependencies = [ "hex", "hkdf", "hpke", + "ignore", + "lazy_static", "libm", "linked_list_allocator", "lock_api", @@ -1106,6 +1154,19 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "globset" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + [[package]] name = "goblin" version = "0.8.0" @@ -1357,6 +1418,22 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "ignore" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + [[package]] name = "indexmap" version = "1.9.3" diff --git a/bazel/crates/oak_crates_index.bzl b/bazel/crates/oak_crates_index.bzl index 3344a5a542f..1bcc553f3e5 100644 --- a/bazel/crates/oak_crates_index.bzl +++ b/bazel/crates/oak_crates_index.bzl @@ -109,6 +109,7 @@ def oak_crates_index(cargo_lockfile, lockfile): ], version = "*", ), + "colored": crate.spec(version = "*"), "command-fds": crate.spec( features = ["tokio"], version = "*", @@ -165,6 +166,8 @@ def oak_crates_index(cargo_lockfile, lockfile): ], version = "*", ), + "ignore": crate.spec(version = "*"), + "lazy_static": crate.spec(version = "*"), "libm": crate.spec(version = "*"), "linked_list_allocator": crate.spec( features = [ diff --git a/bazel/test_workspace/Cargo-test.bazel.lock b/bazel/test_workspace/Cargo-test.bazel.lock index a1ddeedf4c2..e9720ba5f83 100644 --- a/bazel/test_workspace/Cargo-test.bazel.lock +++ b/bazel/test_workspace/Cargo-test.bazel.lock @@ -338,6 +338,16 @@ dependencies = [ "tokio", ] +[[package]] +name = "bstr" +version = "1.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "bumpalo" version = "3.16.0" @@ -500,6 +510,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b6a852b24ab71dffc585bcb46eaf7959d175cb865a7152e35b348d1b2960422" +[[package]] +name = "colored" +version = "2.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" +dependencies = [ + "lazy_static", + "windows-sys 0.48.0", +] + [[package]] name = "command-fds" version = "0.3.0" @@ -551,6 +571,31 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-deque" +version = "0.8.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + [[package]] name = "crunchy" version = "0.2.2" @@ -748,6 +793,7 @@ dependencies = [ "bytes", "ciborium", "clap", + "colored", "command-fds", "coset", "curve25519-dalek", @@ -760,6 +806,8 @@ dependencies = [ "hex", "hkdf", "hpke", + "ignore", + "lazy_static", "libm", "linked_list_allocator", "lock_api", @@ -1112,6 +1160,19 @@ version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" +[[package]] +name = "globset" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata", + "regex-syntax", +] + [[package]] name = "goblin" version = "0.8.2" @@ -1363,6 +1424,22 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "ignore" +version = "0.4.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata", + "same-file", + "walkdir", + "winapi-util", +] + [[package]] name = "indexmap" version = "1.9.3" diff --git a/bazel/test_workspace/cargo-bazel-test-lock.json b/bazel/test_workspace/cargo-bazel-test-lock.json index 7c5c13bba61..ec08e667bfc 100644 --- a/bazel/test_workspace/cargo-bazel-test-lock.json +++ b/bazel/test_workspace/cargo-bazel-test-lock.json @@ -1,5 +1,5 @@ { - "checksum": "2a035addb746c8ca234cb3909b9c267ae8c1865e72c084934f37c1903d734e78", + "checksum": "c76f99a89bf7249906fb292449157f50596f6df3d7e08c0b3bcce7c93db0510c", "crates": { "acpi 5.0.0": { "name": "acpi", @@ -378,6 +378,7 @@ ], "crate_features": { "common": [ + "default", "perf-literal", "std" ], @@ -2046,6 +2047,61 @@ ], "license_file": "LICENSE" }, + "bstr 1.9.1": { + "name": "bstr", + "version": "1.9.1", + "package_url": "https://github.com/BurntSushi/bstr", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/bstr/1.9.1/download", + "sha256": "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" + } + }, + "targets": [ + { + "Library": { + "crate_name": "bstr", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "bstr", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "std" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "memchr 2.7.2", + "target": "memchr" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "1.9.1" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, "bumpalo 3.16.0": { "name": "bumpalo", "version": "3.16.0", @@ -3040,6 +3096,60 @@ ], "license_file": "LICENSE-APACHE" }, + "colored 2.1.0": { + "name": "colored", + "version": "2.1.0", + "package_url": "https://github.com/mackwic/colored", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/colored/2.1.0/download", + "sha256": "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" + } + }, + "targets": [ + { + "Library": { + "crate_name": "colored", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "colored", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "lazy_static 1.4.0", + "target": "lazy_static" + } + ], + "selects": { + "cfg(windows)": [ + { + "id": "windows-sys 0.48.0", + "target": "windows_sys" + } + ] + } + }, + "edition": "2021", + "version": "2.1.0" + }, + "license": "MPL-2.0", + "license_ids": [ + "MPL-2.0" + ], + "license_file": "LICENSE" + }, "command-fds 0.3.0": { "name": "command-fds", "version": "0.3.0", @@ -3362,6 +3472,191 @@ ], "license_file": "LICENSE-APACHE" }, + "crossbeam-deque 0.8.5": { + "name": "crossbeam-deque", + "version": "0.8.5", + "package_url": "https://github.com/crossbeam-rs/crossbeam", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/crossbeam-deque/0.8.5/download", + "sha256": "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" + } + }, + "targets": [ + { + "Library": { + "crate_name": "crossbeam_deque", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "crossbeam_deque", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "default", + "std" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "crossbeam-epoch 0.9.18", + "target": "crossbeam_epoch" + }, + { + "id": "crossbeam-utils 0.8.20", + "target": "crossbeam_utils" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.8.5" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "crossbeam-epoch 0.9.18": { + "name": "crossbeam-epoch", + "version": "0.9.18", + "package_url": "https://github.com/crossbeam-rs/crossbeam", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/crossbeam-epoch/0.9.18/download", + "sha256": "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" + } + }, + "targets": [ + { + "Library": { + "crate_name": "crossbeam_epoch", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "crossbeam_epoch", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "std" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "crossbeam-utils 0.8.20", + "target": "crossbeam_utils" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.9.18" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "crossbeam-utils 0.8.20": { + "name": "crossbeam-utils", + "version": "0.8.20", + "package_url": "https://github.com/crossbeam-rs/crossbeam", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/crossbeam-utils/0.8.20/download", + "sha256": "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + } + }, + "targets": [ + { + "Library": { + "crate_name": "crossbeam_utils", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "crossbeam_utils", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "std" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "crossbeam-utils 0.8.20", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.8.20" + }, + "build_script_attrs": { + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, "crunchy 0.2.2": { "name": "crunchy", "version": "0.2.2", @@ -4501,6 +4796,10 @@ "id": "clap 4.5.4", "target": "clap" }, + { + "id": "colored 2.1.0", + "target": "colored" + }, { "id": "command-fds 0.3.0", "target": "command_fds" @@ -4549,6 +4848,14 @@ "id": "hpke 0.11.0", "target": "hpke" }, + { + "id": "ignore 0.4.22", + "target": "ignore" + }, + { + "id": "lazy_static 1.4.0", + "target": "lazy_static" + }, { "id": "libm 0.2.8", "target": "libm" @@ -6654,6 +6961,77 @@ ], "license_file": "LICENSE-APACHE" }, + "globset 0.4.14": { + "name": "globset", + "version": "0.4.14", + "package_url": "https://github.com/BurntSushi/ripgrep/tree/master/crates/globset", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/globset/0.4.14/download", + "sha256": "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" + } + }, + "targets": [ + { + "Library": { + "crate_name": "globset", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "globset", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "default", + "log" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "aho-corasick 1.1.3", + "target": "aho_corasick" + }, + { + "id": "bstr 1.9.1", + "target": "bstr" + }, + { + "id": "log 0.4.21", + "target": "log" + }, + { + "id": "regex-automata 0.4.6", + "target": "regex_automata" + }, + { + "id": "regex-syntax 0.8.3", + "target": "regex_syntax" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.4.14" + }, + "license": "Unlicense OR MIT", + "license_ids": [ + "MIT", + "Unlicense" + ], + "license_file": "LICENSE-MIT" + }, "goblin 0.8.2": { "name": "goblin", "version": "0.8.2", @@ -8145,6 +8523,85 @@ ], "license_file": "LICENSE" }, + "ignore 0.4.22": { + "name": "ignore", + "version": "0.4.22", + "package_url": "https://github.com/BurntSushi/ripgrep/tree/master/crates/ignore", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/ignore/0.4.22/download", + "sha256": "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" + } + }, + "targets": [ + { + "Library": { + "crate_name": "ignore", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "ignore", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "crossbeam-deque 0.8.5", + "target": "crossbeam_deque" + }, + { + "id": "globset 0.4.14", + "target": "globset" + }, + { + "id": "log 0.4.21", + "target": "log" + }, + { + "id": "memchr 2.7.2", + "target": "memchr" + }, + { + "id": "regex-automata 0.4.6", + "target": "regex_automata" + }, + { + "id": "same-file 1.0.6", + "target": "same_file" + }, + { + "id": "walkdir 2.5.0", + "target": "walkdir" + } + ], + "selects": { + "cfg(windows)": [ + { + "id": "winapi-util 0.1.8", + "target": "winapi_util" + } + ] + } + }, + "edition": "2021", + "version": "0.4.22" + }, + "license": "Unlicense OR MIT", + "license_ids": [ + "MIT", + "Unlicense" + ], + "license_file": "LICENSE-MIT" + }, "indexmap 1.9.3": { "name": "indexmap", "version": "1.9.3", @@ -12962,9 +13419,11 @@ "dfa-onepass", "hybrid", "meta", + "nfa", "nfa-backtrack", "nfa-pikevm", "nfa-thompson", + "perf", "perf-inline", "perf-literal", "perf-literal-multisubstring", @@ -20247,6 +20706,7 @@ "bytes 1.6.0", "ciborium 0.2.2", "clap 4.5.4", + "colored 2.1.0", "command-fds 0.3.0", "coset 0.3.7", "curve25519-dalek 4.1.1", @@ -20259,6 +20719,8 @@ "hex 0.4.3", "hkdf 0.12.4", "hpke 0.11.0", + "ignore 0.4.22", + "lazy_static 1.4.0", "libm 0.2.8", "linked_list_allocator 0.10.5", "lock_api 0.4.12", diff --git a/cargo-bazel-lock.json b/cargo-bazel-lock.json index 4eaaa9299fe..f2db87142dd 100644 --- a/cargo-bazel-lock.json +++ b/cargo-bazel-lock.json @@ -1,5 +1,5 @@ { - "checksum": "682754f838a52af6677cda26d9abff71b5539ae2534786da75c150bbb00d9826", + "checksum": "c270d2af8cbfa713600adffa8f19b1d1438cbaeb9659df72985628729fa5d86a", "crates": { "acpi 5.0.0": { "name": "acpi", @@ -378,6 +378,7 @@ ], "crate_features": { "common": [ + "default", "perf-literal", "std" ], @@ -2067,6 +2068,61 @@ ], "license_file": "LICENSE" }, + "bstr 1.9.1": { + "name": "bstr", + "version": "1.9.1", + "package_url": "https://github.com/BurntSushi/bstr", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/bstr/1.9.1/download", + "sha256": "05efc5cfd9110c8416e471df0e96702d58690178e206e61b7173706673c93706" + } + }, + "targets": [ + { + "Library": { + "crate_name": "bstr", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "bstr", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "std" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "memchr 2.7.2", + "target": "memchr" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "1.9.1" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, "bumpalo 3.16.0": { "name": "bumpalo", "version": "3.16.0", @@ -3023,6 +3079,60 @@ ], "license_file": "LICENSE-APACHE" }, + "colored 2.1.0": { + "name": "colored", + "version": "2.1.0", + "package_url": "https://github.com/mackwic/colored", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/colored/2.1.0/download", + "sha256": "cbf2150cce219b664a8a70df7a1f933836724b503f8a413af9365b4dcc4d90b8" + } + }, + "targets": [ + { + "Library": { + "crate_name": "colored", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "colored", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "lazy_static 1.4.0", + "target": "lazy_static" + } + ], + "selects": { + "cfg(windows)": [ + { + "id": "windows-sys 0.48.0", + "target": "windows_sys" + } + ] + } + }, + "edition": "2021", + "version": "2.1.0" + }, + "license": "MPL-2.0", + "license_ids": [ + "MPL-2.0" + ], + "license_file": "LICENSE" + }, "command-fds 0.3.0": { "name": "command-fds", "version": "0.3.0", @@ -3366,6 +3476,191 @@ ], "license_file": "LICENSE-APACHE" }, + "crossbeam-deque 0.8.5": { + "name": "crossbeam-deque", + "version": "0.8.5", + "package_url": "https://github.com/crossbeam-rs/crossbeam", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/crossbeam-deque/0.8.5/download", + "sha256": "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d" + } + }, + "targets": [ + { + "Library": { + "crate_name": "crossbeam_deque", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "crossbeam_deque", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "default", + "std" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "crossbeam-epoch 0.9.18", + "target": "crossbeam_epoch" + }, + { + "id": "crossbeam-utils 0.8.20", + "target": "crossbeam_utils" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.8.5" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "crossbeam-epoch 0.9.18": { + "name": "crossbeam-epoch", + "version": "0.9.18", + "package_url": "https://github.com/crossbeam-rs/crossbeam", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/crossbeam-epoch/0.9.18/download", + "sha256": "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" + } + }, + "targets": [ + { + "Library": { + "crate_name": "crossbeam_epoch", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "crossbeam_epoch", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "alloc", + "std" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "crossbeam-utils 0.8.20", + "target": "crossbeam_utils" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.9.18" + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, + "crossbeam-utils 0.8.20": { + "name": "crossbeam-utils", + "version": "0.8.20", + "package_url": "https://github.com/crossbeam-rs/crossbeam", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/crossbeam-utils/0.8.20/download", + "sha256": "22ec99545bb0ed0ea7bb9b8e1e9122ea386ff8a48c0922e43f36d45ab09e0e80" + } + }, + "targets": [ + { + "Library": { + "crate_name": "crossbeam_utils", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + }, + { + "BuildScript": { + "crate_name": "build_script_build", + "crate_root": "build.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "crossbeam_utils", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "std" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "crossbeam-utils 0.8.20", + "target": "build_script_build" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.8.20" + }, + "build_script_attrs": { + "data_glob": [ + "**" + ] + }, + "license": "MIT OR Apache-2.0", + "license_ids": [ + "Apache-2.0", + "MIT" + ], + "license_file": "LICENSE-APACHE" + }, "crunchy 0.2.2": { "name": "crunchy", "version": "0.2.2", @@ -4505,6 +4800,10 @@ "id": "clap 4.5.4", "target": "clap" }, + { + "id": "colored 2.1.0", + "target": "colored" + }, { "id": "command-fds 0.3.0", "target": "command_fds" @@ -4553,6 +4852,14 @@ "id": "hpke 0.11.0", "target": "hpke" }, + { + "id": "ignore 0.4.22", + "target": "ignore" + }, + { + "id": "lazy_static 1.4.0", + "target": "lazy_static" + }, { "id": "libm 0.2.8", "target": "libm" @@ -6658,6 +6965,77 @@ ], "license_file": "LICENSE-APACHE" }, + "globset 0.4.14": { + "name": "globset", + "version": "0.4.14", + "package_url": "https://github.com/BurntSushi/ripgrep/tree/master/crates/globset", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/globset/0.4.14/download", + "sha256": "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1" + } + }, + "targets": [ + { + "Library": { + "crate_name": "globset", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "globset", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "crate_features": { + "common": [ + "default", + "log" + ], + "selects": {} + }, + "deps": { + "common": [ + { + "id": "aho-corasick 1.1.3", + "target": "aho_corasick" + }, + { + "id": "bstr 1.9.1", + "target": "bstr" + }, + { + "id": "log 0.4.21", + "target": "log" + }, + { + "id": "regex-automata 0.4.6", + "target": "regex_automata" + }, + { + "id": "regex-syntax 0.8.3", + "target": "regex_syntax" + } + ], + "selects": {} + }, + "edition": "2021", + "version": "0.4.14" + }, + "license": "Unlicense OR MIT", + "license_ids": [ + "MIT", + "Unlicense" + ], + "license_file": "LICENSE-MIT" + }, "goblin 0.8.0": { "name": "goblin", "version": "0.8.0", @@ -8149,6 +8527,85 @@ ], "license_file": "LICENSE" }, + "ignore 0.4.22": { + "name": "ignore", + "version": "0.4.22", + "package_url": "https://github.com/BurntSushi/ripgrep/tree/master/crates/ignore", + "repository": { + "Http": { + "url": "https://static.crates.io/crates/ignore/0.4.22/download", + "sha256": "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1" + } + }, + "targets": [ + { + "Library": { + "crate_name": "ignore", + "crate_root": "src/lib.rs", + "srcs": { + "allow_empty": false, + "include": [ + "**/*.rs" + ] + } + } + } + ], + "library_target_name": "ignore", + "common_attrs": { + "compile_data_glob": [ + "**" + ], + "deps": { + "common": [ + { + "id": "crossbeam-deque 0.8.5", + "target": "crossbeam_deque" + }, + { + "id": "globset 0.4.14", + "target": "globset" + }, + { + "id": "log 0.4.21", + "target": "log" + }, + { + "id": "memchr 2.7.2", + "target": "memchr" + }, + { + "id": "regex-automata 0.4.6", + "target": "regex_automata" + }, + { + "id": "same-file 1.0.6", + "target": "same_file" + }, + { + "id": "walkdir 2.5.0", + "target": "walkdir" + } + ], + "selects": { + "cfg(windows)": [ + { + "id": "winapi-util 0.1.8", + "target": "winapi_util" + } + ] + } + }, + "edition": "2021", + "version": "0.4.22" + }, + "license": "Unlicense OR MIT", + "license_ids": [ + "MIT", + "Unlicense" + ], + "license_file": "LICENSE-MIT" + }, "indexmap 1.9.3": { "name": "indexmap", "version": "1.9.3", @@ -12881,9 +13338,11 @@ "dfa-onepass", "hybrid", "meta", + "nfa", "nfa-backtrack", "nfa-pikevm", "nfa-thompson", + "perf", "perf-inline", "perf-literal", "perf-literal-multisubstring", @@ -20048,6 +20507,7 @@ "bytes 1.6.0", "ciborium 0.2.2", "clap 4.5.4", + "colored 2.1.0", "command-fds 0.3.0", "coset 0.3.7", "curve25519-dalek 4.1.1", @@ -20060,6 +20520,8 @@ "hex 0.4.3", "hkdf 0.12.4", "hpke 0.11.0", + "ignore 0.4.22", + "lazy_static 1.4.0", "libm 0.2.8", "linked_list_allocator 0.10.5", "lock_api 0.4.11", diff --git a/fuzz/fuzz_targets/apply_policy.rs b/fuzz/fuzz_targets/apply_policy.rs index 61b4f629f1c..102cb086cd1 100644 --- a/fuzz/fuzz_targets/apply_policy.rs +++ b/fuzz/fuzz_targets/apply_policy.rs @@ -42,24 +42,18 @@ impl Arbitrary<'_> for ResponseAndValidPolicy { // We limit the fuzzing to constant response size larger than the body. let constant_response_size_bytes = body_len + raw.int_in_range(0..=1000000)?; - Ok(ResponseAndValidPolicy { - response, - constant_response_size_bytes, - }) + Ok(ResponseAndValidPolicy { response, constant_response_size_bytes }) } } -// This fuzz target checks that the constant size policy applies to an arbitrary request. +// This fuzz target checks that the constant size policy applies to an arbitrary +// request. fuzz_target!(|data: ResponseAndValidPolicy| { let constant_response_size_bytes = data.constant_response_size_bytes; - let response = data - .response - .pad(constant_response_size_bytes) - .unwrap() - .encode_to_vec(); + let response = data.response.pad(constant_response_size_bytes).unwrap().encode_to_vec(); - // Check the response size, which is the constant response size plus a fixed offset, where the - // status code and actual length are stored. + // Check the response size, which is the constant response size plus a fixed + // offset, where the status code and actual length are stored. assert_eq!( response.len(), oak_functions_abi::RESPONSE_BODY_OFFSET + constant_response_size_bytes diff --git a/justfile b/justfile index e79aa99bd1b..bf143ed7884 100644 --- a/justfile +++ b/justfile @@ -241,7 +241,8 @@ xtask job: ./scripts/xtask {{job}} clippy-ci: (xtask "run-cargo-clippy") bazel-clippy -check-format-ci: (xtask "check-format") bazel-fmt +check-format-ci: + bazel build --config=unsafe-fast-presubmit linter && bazel-bin/linter/linter --verbose # Temporary target to help debugging Bazel remote cache with more detailed logs. # It should be deleted when debugging is completed. @@ -249,3 +250,7 @@ check-format-ci: (xtask "check-format") bazel-fmt bazel-cache-test: mkdir --parents target bazel test --config=unsafe-fast-presubmit --build_event_text_file=./target/bazel_bep_1.txt --execution_log_binary_file=./target/bazel_exec_1.log -- //cc/bazel_cache_test:test + + +format: + bazel build linter && bazel-bin/linter/linter --fix diff --git a/linter/BUILD b/linter/BUILD new file mode 100644 index 00000000000..2e6774b3d05 --- /dev/null +++ b/linter/BUILD @@ -0,0 +1,68 @@ +# +# Copyright 2024 The Project Oak Authors +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +load("@rules_rust//rust:defs.bzl", "rust_binary", "rust_library") + +package( + default_visibility = ["//visibility:public"], + licenses = ["notice"], +) + +rust_binary( + name = "linter", + srcs = ["main.rs"], + deps = [ + ":lib", + ":tools", + "@oak_crates_index//:clap", + "@oak_crates_index//:colored", + "@oak_crates_index//:ignore", + ], +) + +rust_library( + name = "lib", + srcs = [ + "lib.rs", + ], + crate_name = "linter", + deps = [ + "@oak_crates_index//:anyhow", + "@oak_crates_index//:ignore", + ], +) + +rust_library( + name = "tools", + srcs = [ + "tools/bad_todos.rs", + "tools/build_license.rs", + "tools/buildifier.rs", + "tools/clang_format.rs", + "tools/hadolint.rs", + "tools/lib.rs", + "tools/markdownlint.rs", + "tools/prettier.rs", + "tools/rustfmt.rs", + "tools/shell_check.rs", + "tools/source_license.rs", + ], + deps = [ + ":lib", + "@oak_crates_index//:anyhow", + "@oak_crates_index//:lazy_static", + "@oak_crates_index//:regex", + ], +) diff --git a/linter/README.md b/linter/README.md new file mode 100644 index 00000000000..c6ca321460e --- /dev/null +++ b/linter/README.md @@ -0,0 +1,17 @@ +# Oak Project Linter Tool Runner + +This is a small tool designed to quickly and easily run a variety of lint tools +on the repository. + +Key Features: + +- Ignore file handling: .gitignore file is respected by default, along with an + additional .lintignore file. + +- Fast! It runs the entire suite of linters in under 5 seconds. Lint early, lint + often. + +- Concise output: By default, the output focuses only on issues, and doesn't + fill the screen with unnecessary information. + +- Easily extensible: To add new linters, you can just define a new struct. diff --git a/linter/lib.rs b/linter/lib.rs new file mode 100644 index 00000000000..dd650f4b681 --- /dev/null +++ b/linter/lib.rs @@ -0,0 +1,167 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use std::{path::Path, process, sync::mpsc}; + +use ignore::{DirEntry, WalkBuilder}; + +// A mode flag to specify whether a linter run should just report errors, or +// also try to fix them in place. +#[derive(Copy, Clone, Debug)] +pub enum Mode { + // When running the linter tool, only report errors, don't change the file. + Check, + + // Fix any linter issues that the related tool is able to fix. + Fix, +} + +// The result of running a linter tool on a file. +// This may look like it should be a result, but "Failures" are not really +// errors in this context, so it remains its own type. +#[derive(Clone, Debug)] +pub enum Outcome { + /// The linter action succeeded without issues + Success, + + /// The linter tool failed to launch or failed to terminate normally. + Failure(String), +} + +// A tuple struct holding a filename, and the outcome for that filename. +#[derive(Debug)] +pub struct FileOutcome { + pub filename: String, + pub outcome: anyhow::Result, +} + +/// An implementation of a linter tool. +pub trait LinterTool: Send + Sync { + /// A display name for this tool. + const NAME: &'static str; + + /// Return true if this tool can support any sort of automatic fixing + /// behavior. + const SUPPORTS_FIX: bool = false; + + /// Returns true if the provided [Path] appears to be a filetype handled by + /// this tool. If there's an error making the determination, an Error result + /// will be returned instead. + fn accept(&self, entry: &Path) -> anyhow::Result; + + /// Run the linter tool in "check" mode - no changes will be made to the + /// fail, but information about issues will be provided, if there are any. + fn check(&self, entry: &Path) -> anyhow::Result; + + /// Run the linter tool in "fix" mode - when possible, the file issues will + /// be automatically fixed in place. Note that not all tools can fix all + /// issues, so some failure output may still occur. + /// + /// If fixing is not supported, this simply runs the check behavior. + fn fix(&self, entry: &Path) -> anyhow::Result { + self.check(entry) + } +} + +/// It's common to use a command line tool for linting. +/// This is a convenience to convert the output of the linter program into the +/// [Outcome] type returned from the linter. +/// +/// In failure cases, stderr will be included as the output. +impl TryFrom<&mut process::Command> for Outcome { + type Error = anyhow::Error; + + fn try_from(command: &mut process::Command) -> Result { + let output = command.output()?; + Ok(match output.status.success() { + true => Outcome::Success, + false => Outcome::Failure(format!( + "{}\n{}", + String::from_utf8_lossy(&output.stdout), + String::from_utf8_lossy(&output.stderr) + )), + }) + } +} + +// A structure that actually performs the linting on a group of files, via the +// `lint_files` method. +pub struct Linter { + tool: LT, +} + +impl Linter { + // Create a new linter instance that uses the provided `tool` when + // `lint_files` is called. + pub fn new(tool: LT) -> Self { + Linter { tool } + } + + // Returns the [LinterTool] that this instance was constructed with. + pub fn tool(&self) -> < { + &self.tool + } + + /// Lint one individual file with the [LinterTool], + fn lint_file(&self, path: &Path, mode: Mode) -> Option { + let accept = self.tool.accept(path).unwrap_or_else(|err| { + eprintln!("Failed to check {} for acceptance: {err:?}", path.display(),); + false + }); + if accept { + Some(FileOutcome { + filename: path.display().to_string(), + outcome: match mode { + Mode::Check => self.tool.check(path), + Mode::Fix => self.tool.fix(path), + }, + }) + } else { + None + } + } + + // Run the [LinterTool] on all of the files exposed by the provided + // `WalkBuilder`, in the [Mode] specified. + // + // The files will be processed in parallel, with a thread count based on the + // configuration of the provided WalkBuilder. + pub fn lint_files(&self, walk_builder: &WalkBuilder, mode: Mode) -> Vec { + let (tx, rx) = mpsc::channel(); + + let is_directory = + |entry: &DirEntry| entry.file_type().map(|ft| ft.is_dir()).unwrap_or(false); + + walk_builder.build_parallel().run(|| { + Box::new(|entry| { + match entry { + Ok(entry) if is_directory(&entry) => {} + Ok(entry) => { + if let Some(outcome) = self.lint_file(entry.path(), mode) { + tx.send(outcome).unwrap() + } + } + Err(err) => eprintln!("Failed to process something: {err:?}"), + }; + ignore::WalkState::Continue + }) + }); + + // Drop the tx channel so that rx collection terminates. + drop(tx); + rx.iter().collect() + } +} diff --git a/linter/main.rs b/linter/main.rs new file mode 100644 index 00000000000..db64e6047ae --- /dev/null +++ b/linter/main.rs @@ -0,0 +1,142 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use std::time::Instant; + +use clap::Parser; +use colored::*; +use linter::Linter; + +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +struct Args { + // Set to true to attempt to automatically fix issues. + #[arg(short, long)] + fix: bool, + + // If true, includes more output, like listing succeeded files. + #[arg(short, long)] + verbose: bool, + + // The root directory to search for files in. Defaults to `.`. + #[arg(short, long, default_value = ".")] + root: String, +} + +struct LinterContext { + walk_builder: ignore::WalkBuilder, + mode: linter::Mode, + verbose: bool, +} + +#[derive(Copy, Clone, Debug, Default)] +struct ResultCounts { + processed: usize, + failures: usize, +} + +impl std::ops::AddAssign for ResultCounts { + fn add_assign(&mut self, rhs: ResultCounts) { + self.processed += rhs.processed; + self.failures += rhs.failures; + } +} + +fn main() { + let args = Args::parse(); + let mode = if args.fix { linter::Mode::Fix } else { linter::Mode::Check }; + + let mut walk_builder = ignore::WalkBuilder::new(args.root); + walk_builder.threads(100); + walk_builder.add_ignore(".lintignore"); + + let context = LinterContext { walk_builder, mode, verbose: args.verbose }; + + let start = Instant::now(); + let mut counts = ResultCounts::default(); + + counts += context.lint(tools::bad_todos::BadTodoTool {}); + counts += context.lint(tools::build_license::BuildFileLicenseTool {}); + counts += context.lint(tools::buildifier::BuildifierTool {}); + counts += context.lint(tools::clang_format::ClangFormatTool {}); + counts += context.lint(tools::hadolint::HadolintTool {}); + counts += context.lint(tools::prettier::PrettierTool {}); + counts += context.lint(tools::shell_check::ShellCheckTool {}); + counts += context.lint(tools::rustfmt::RustfmtTool {}); + counts += context.lint(tools::markdownlint::MarkdownlintTool {}); + counts += context.lint(tools::source_license::SourceLicenseTool {}); + + let end = Instant::now(); + let elapsed = end.duration_since(start); + println!("\n\nProcessed {} files in {:?}", counts.processed, elapsed); + + if counts.failures > 0 { + println!("{}", format!("Files with issues: {}", counts.failures).red()); + std::process::exit(1); + } else { + println!("{}", "No files with issues found".cyan()); + std::process::exit(0); + } +} + +impl LinterContext { + fn banner(&self) { + let verb = match self.mode { + linter::Mode::Fix if LT::SUPPORTS_FIX => "Fixing".cyan(), + _ => "Checking".green(), + }; + let title = format!("{} {}", verb, LT::NAME.bright_white()); + + let padding_size = (80 - title.len()) / 2; + let padding = (0..padding_size).map(|_| "*").collect::(); + println!("\n\n\n{} {} {}\n", padding, title, padding); + } + + fn lint(&self, tool: LT) -> ResultCounts { + let start = Instant::now(); + self.banner::(); + let linter = Linter::new(tool); + let outcomes = linter.lint_files(&self.walk_builder, self.mode); + let processed = outcomes.len(); + let mut failures = 0; + for outcome in outcomes { + match outcome.outcome { + Err(err) => { + let message = format!("TOOL FAILURE {err:?}").red(); + println!("{}", message); + } + Ok(linter::Outcome::Success) => { + if self.verbose { + println!("No issues: {}", outcome.filename.cyan()) + } + } + Ok(linter::Outcome::Failure(message)) => { + failures += 1; + println!("{}\n{message}", outcome.filename.red()) + } + }; + } + let end = Instant::now(); + let elapsed = end.duration_since(start); + println!( + "=======> {} processed {} files in {:?}", + LT::NAME.bright_white(), + processed, + elapsed + ); + ResultCounts { processed, failures } + } +} diff --git a/linter/tools/bad_todos.rs b/linter/tools/bad_todos.rs new file mode 100644 index 00000000000..e95b376221d --- /dev/null +++ b/linter/tools/bad_todos.rs @@ -0,0 +1,58 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use std::{ + fs::File, + io::{BufRead, BufReader}, + path::Path, +}; + +use lazy_static::lazy_static; +use linter::Outcome; +use regex::Regex; + +pub struct BadTodoTool {} + +lazy_static! { + // Using \x54 = T to prevent triggering the lint here. + static ref PATTERN: Regex = Regex::new("(\x54ODO\\(#[0-9]+\\)|\x54ODO: .+ - [0-9A-Za-z]+)") + .expect("couldn't parse regex"); +} + +impl linter::LinterTool for BadTodoTool { + // Using \x54 = T to prevent triggering the lint here. + const NAME: &'static str = "Bad \x54ODOs"; + + fn accept(&self, path: &Path) -> anyhow::Result { + Ok(super::has_extension(path, &["c", "h", "cc", "java", "go", "js", "proto", "kt", "rs"])) + } + + fn check(&self, path: &Path) -> anyhow::Result { + let f = File::open(path)?; + let reader = BufReader::new(f); + + let mut results = Vec::::new(); + for (n, line) in reader.lines().enumerate() { + let line = line?; + // Using \x54 = T to prevent triggering the lint here. + if line.contains("\x54ODO") && !PATTERN.is_match(&line) { + results.push(format!(" . Line {}: {}", n, line)); + } + } + + Ok(if results.is_empty() { Outcome::Success } else { Outcome::Failure(results.join("\n")) }) + } +} diff --git a/linter/tools/build_license.rs b/linter/tools/build_license.rs new file mode 100644 index 00000000000..c99a27c0203 --- /dev/null +++ b/linter/tools/build_license.rs @@ -0,0 +1,42 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use std::{ + fs::File, + io::{BufRead, BufReader}, + path::Path, +}; + +pub struct BuildFileLicenseTool {} + +impl linter::LinterTool for BuildFileLicenseTool { + const NAME: &'static str = "Build File License"; + + fn accept(&self, path: &Path) -> anyhow::Result { + Ok(super::has_filename(path, &["BUILD"])) + } + + fn check(&self, path: &Path) -> anyhow::Result { + let f = File::open(path)?; + + for line in BufReader::new(f).lines().take(50) { + if line?.contains(r#"licenses = ["notice"]"#) { + return Ok(linter::Outcome::Success); + } + } + Ok(linter::Outcome::Failure("No license file header found.".to_string())) + } +} diff --git a/linter/tools/buildifier.rs b/linter/tools/buildifier.rs new file mode 100644 index 00000000000..87b84c2a685 --- /dev/null +++ b/linter/tools/buildifier.rs @@ -0,0 +1,37 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use std::path::Path; + +pub struct BuildifierTool {} + +impl linter::LinterTool for BuildifierTool { + const NAME: &'static str = "Buildifier"; + const SUPPORTS_FIX: bool = true; + + fn accept(&self, path: &Path) -> anyhow::Result { + Ok(super::has_extension(path, &["bzl"]) + || super::has_filename(path, &["BUILD", "WORKSPACE"])) + } + + fn check(&self, path: &Path) -> anyhow::Result { + super::linter_command("buildifier", &["-mode=check", "-lint=warn"], path) + } + + fn fix(&self, path: &Path) -> anyhow::Result { + super::linter_command("buildifier", &["-mode=fix", "-lint=fix"], path) + } +} diff --git a/linter/tools/clang_format.rs b/linter/tools/clang_format.rs new file mode 100644 index 00000000000..c29af5f454c --- /dev/null +++ b/linter/tools/clang_format.rs @@ -0,0 +1,38 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use std::path::Path; + +use super::has_extension; + +pub struct ClangFormatTool {} + +impl linter::LinterTool for ClangFormatTool { + const NAME: &'static str = "Clang Format"; + const SUPPORTS_FIX: bool = true; + + fn accept(&self, path: &Path) -> anyhow::Result { + Ok(has_extension(path, &["c", "cc", "h", "proto", "java"])) + } + + fn check(&self, path: &Path) -> anyhow::Result { + super::linter_command("clang-format", &["--dry-run", "-Werror"], path) + } + + fn fix(&self, path: &Path) -> anyhow::Result { + super::linter_command("clang-format", &["-i"], path) + } +} diff --git a/linter/tools/hadolint.rs b/linter/tools/hadolint.rs new file mode 100644 index 00000000000..284c324a33f --- /dev/null +++ b/linter/tools/hadolint.rs @@ -0,0 +1,32 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use std::path::Path; + +pub struct HadolintTool {} + +impl linter::LinterTool for HadolintTool { + const NAME: &'static str = "Hadolint"; + + fn accept(&self, path: &Path) -> anyhow::Result { + Ok(super::has_extension(path, &["Dockerfile"]) + || super::has_filename(path, &["Dockerfile"])) + } + + fn check(&self, path: &Path) -> anyhow::Result { + super::linter_command("hadolint", &[], path) + } +} diff --git a/linter/tools/lib.rs b/linter/tools/lib.rs new file mode 100644 index 00000000000..73b9e122d42 --- /dev/null +++ b/linter/tools/lib.rs @@ -0,0 +1,52 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +pub mod bad_todos; +pub mod build_license; +pub mod buildifier; +pub mod clang_format; +pub mod hadolint; +pub mod markdownlint; +pub mod prettier; +pub mod rustfmt; +pub mod shell_check; +pub mod source_license; + +use std::{fs::File, io::Read, path::Path, process::Command}; + +fn has_extension(path: &Path, extensions: &[&str]) -> bool { + match path.extension() { + Some(ex) => extensions.contains(&ex.to_string_lossy().as_ref()), + _ => false, + } +} + +fn has_filename(path: &Path, names: &[&str]) -> bool { + match path.file_name() { + Some(name) => names.contains(&name.to_string_lossy().as_ref()), + _ => false, + } +} + +fn contents_starts_with(path: &Path, bytes: &[u8]) -> anyhow::Result { + let f = File::open(path)?; + let start: std::io::Result> = f.bytes().take(bytes.len()).collect(); + Ok(start? == bytes) +} + +fn linter_command(command: &str, args: &[&str], path: &Path) -> anyhow::Result { + Command::new(command).args(args).arg(path.to_str().unwrap()).try_into() +} diff --git a/linter/tools/markdownlint.rs b/linter/tools/markdownlint.rs new file mode 100644 index 00000000000..d360f542418 --- /dev/null +++ b/linter/tools/markdownlint.rs @@ -0,0 +1,38 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use std::path::Path; + +use super::has_extension; + +pub struct MarkdownlintTool {} + +impl linter::LinterTool for MarkdownlintTool { + const NAME: &'static str = "Markdownlint"; + const SUPPORTS_FIX: bool = true; + + fn accept(&self, path: &Path) -> anyhow::Result { + Ok(has_extension(path, &["md"])) + } + + fn check(&self, path: &Path) -> anyhow::Result { + super::linter_command("markdownlint", &[], path) + } + + fn fix(&self, path: &Path) -> anyhow::Result { + super::linter_command("markdownlint", &["--fix"], path) + } +} diff --git a/linter/tools/prettier.rs b/linter/tools/prettier.rs new file mode 100644 index 00000000000..deb3bad1a3d --- /dev/null +++ b/linter/tools/prettier.rs @@ -0,0 +1,41 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use std::path::Path; + +use super::has_extension; + +pub struct PrettierTool {} + +impl linter::LinterTool for PrettierTool { + const NAME: &'static str = "Prettier"; + const SUPPORTS_FIX: bool = true; + + fn accept(&self, path: &Path) -> anyhow::Result { + Ok(has_extension( + path, + &["yaml", "yml", "toml", "tml", "html", "htm", "js", "ts", "tsx", "msj", "md"], + )) + } + + fn check(&self, path: &Path) -> anyhow::Result { + super::linter_command("prettier", &["--check", "--log-level=warn"], path) + } + + fn fix(&self, path: &Path) -> anyhow::Result { + super::linter_command("prettier", &["--write", "--log-level=warn"], path) + } +} diff --git a/linter/tools/rustfmt.rs b/linter/tools/rustfmt.rs new file mode 100644 index 00000000000..0eadf294315 --- /dev/null +++ b/linter/tools/rustfmt.rs @@ -0,0 +1,38 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use std::path::Path; + +use super::has_extension; + +pub struct RustfmtTool {} + +impl linter::LinterTool for RustfmtTool { + const NAME: &'static str = "Rust Format"; + const SUPPORTS_FIX: bool = true; + + fn accept(&self, path: &Path) -> anyhow::Result { + Ok(has_extension(path, &["rs"])) + } + + fn check(&self, path: &Path) -> anyhow::Result { + super::linter_command("rustfmt", &["--check"], path) + } + + fn fix(&self, path: &Path) -> anyhow::Result { + super::linter_command("rustfmt", &[], path) + } +} diff --git a/linter/tools/shell_check.rs b/linter/tools/shell_check.rs new file mode 100644 index 00000000000..5bb249a2708 --- /dev/null +++ b/linter/tools/shell_check.rs @@ -0,0 +1,38 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use std::path::Path; + +pub struct ShellCheckTool {} + +impl linter::LinterTool for ShellCheckTool { + const NAME: &'static str = "ShellCheck"; + const SUPPORTS_FIX: bool = true; + + fn accept(&self, path: &Path) -> anyhow::Result { + super::contents_starts_with(path, b"#!") + } + + fn check(&self, path: &Path) -> anyhow::Result { + super::linter_command( + "shellcheck", + // SC2155 (warning): Declare and assign separately to avoid masking return values. + // We allow this, since it's such a common pattern. + &["--exclude=SC2155", "--external-sources"], + path, + ) + } +} diff --git a/linter/tools/source_license.rs b/linter/tools/source_license.rs new file mode 100644 index 00000000000..f9c87e2e8d7 --- /dev/null +++ b/linter/tools/source_license.rs @@ -0,0 +1,45 @@ +// +// Copyright 2024 The Project Oak Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +use std::{ + fs::File, + io::{BufRead, BufReader}, + path::Path, +}; + +use linter::Outcome; + +pub struct SourceLicenseTool {} + +impl linter::LinterTool for SourceLicenseTool { + const NAME: &'static str = "Source License Headers"; + + fn accept(&self, path: &Path) -> anyhow::Result { + Ok(super::has_extension(path, &["c", "h", "cc", "java", "go", "js", "proto", "kt", "rs"])) + } + + fn check(&self, path: &Path) -> anyhow::Result { + let f = File::open(path)?; + let reader = BufReader::new(f); + + for line in reader.lines().take(50) { + if line?.contains("Apache License") { + return Ok(Outcome::Success); + } + } + Ok(Outcome::Failure("No license file header found.".to_string())) + } +} diff --git a/oak_proto_build_utils/src/lib.rs b/oak_proto_build_utils/src/lib.rs index 293eddff6f6..5404a4ed20a 100644 --- a/oak_proto_build_utils/src/lib.rs +++ b/oak_proto_build_utils/src/lib.rs @@ -12,8 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -use std::fs; -use std::path::PathBuf; +use std::{fs, path::PathBuf}; /// Replaces refs to prost with prost_derive. See b/340185847. /// Only to be called from build scripts of crates that generate prost code. @@ -46,7 +45,8 @@ pub fn fix_prost_derives() -> Result<(), Box> { Ok(()) } -// Returns the include paths of common protos: Oak proto and com_google_protobuf. +// Returns the include paths of common protos: Oak proto and +// com_google_protobuf. pub fn get_common_proto_path() -> Vec { // The root of all Oak protos let oak_proto_root = PathBuf::from(".."); diff --git a/snp_measurement/src/elf.rs b/snp_measurement/src/elf.rs index 1a80c279453..ac5003ebaa1 100644 --- a/snp_measurement/src/elf.rs +++ b/snp_measurement/src/elf.rs @@ -34,8 +34,9 @@ pub struct MemorySegment { pub fn load_elf_segments(elf_path: PathBuf) -> anyhow::Result> { let elf_bytes = load_elf_file(elf_path)?; let elf = Elf::parse(&elf_bytes).context("invalid ELF file")?; - // For now we assume each segment's start address will be 4KiB aligned, so we do not pad the - // start. This assumption is validated when the segments are measured. + // For now we assume each segment's start address will be 4KiB aligned, so we do + // not pad the start. This assumption is validated when the segments are + // measured. Ok(elf .program_headers .iter()