escargot-0.5.12/.cargo_vcs_info.json0000644000000001360000000000100127300ustar { "git": { "sha1": "ef37795dbd733f54ecbf755c6de4472c32844cc3" }, "path_in_vcs": "" }escargot-0.5.12/Cargo.lock0000644000000160240000000000100107060ustar # This file is automatically @generated by Cargo. # It is not intended for manual editing. version = 3 [[package]] name = "automod" version = "1.0.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edf3ee19dbc0a46d740f6f0926bde8c50f02bdbc7b536842da28f6ac56513a8b" dependencies = [ "proc-macro2", "quote", "syn 2.0.60", ] [[package]] name = "bitflags" version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] name = "cfg-if" version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "errno" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "534c5cf6194dfab3db3242765c03bbe257cf92f22b38f6bc0c58d59108a820ba" dependencies = [ "libc", "windows-sys", ] [[package]] name = "escargot" version = "0.5.12" dependencies = [ "automod", "log", "once_cell", "serde", "serde_json", "tempfile", ] [[package]] name = "fastrand" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9fc0510504f03c51ada170672ac806f1f105a88aa97a5281117e1ddc3368e51a" [[package]] name = "itoa" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4217ad341ebadf8d8e724e264f13e593e0648f5b3e94b3896a5df283be015ecc" [[package]] name = "libc" version = "0.2.155" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" [[package]] name = "linux-raw-sys" version = "0.4.14" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78b3ae25bc7c8c38cec158d1f2757ee79e9b3740fbc7ccf0e59e4b08d793fa89" [[package]] name = "log" version = "0.4.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" dependencies = [ "cfg-if", ] [[package]] name = "once_cell" version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "86f0b0d4bf799edbc74508c1e8bf170ff5f41238e5f8225603ca7caaae2b7860" [[package]] name = "proc-macro2" version = "1.0.81" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3d1597b0c024618f09a9c3b8655b7e430397a36d23fdafec26d6965e9eec3eba" dependencies = [ "unicode-ident", ] [[package]] name = "quote" version = "1.0.36" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" dependencies = [ "proc-macro2", ] [[package]] name = "rustix" version = "0.38.34" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" dependencies = [ "bitflags", "errno", "libc", "linux-raw-sys", "windows-sys", ] [[package]] name = "ryu" version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4501abdff3ae82a1c1b477a17252eb69cee9e66eb915c1abaa4f44d873df9f09" [[package]] name = "serde" version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e53f64bb4ba0191d6d0676e1b141ca55047d83b74f5607e6d8eb88126c52c2dc" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" version = "1.0.148" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a55492425aa53521babf6137309e7d34c20bbfbbfcfe2c7f3a047fd1f6b92c0c" dependencies = [ "proc-macro2", "quote", "syn 1.0.105", ] [[package]] name = "serde_json" version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ "itoa", "ryu", "serde", ] [[package]] name = "syn" version = "1.0.105" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "60b9b43d45702de4c839cb9b51d9f529c5dd26a4aff255b42b1ebc03e88ee908" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "syn" version = "2.0.60" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "909518bc7b1c9b779f1bbf07f2929d35af9f0f37e47c6e9ef7f9dddc1e1821f3" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] [[package]] name = "tempfile" version = "3.10.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85b77fafb263dd9d05cbeac119526425676db3784113aa9295c88498cbf8bff1" dependencies = [ "cfg-if", "fastrand", "rustix", "windows-sys", ] [[package]] name = "unicode-ident" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ceab39d59e4c9499d4e5a8ee0e2735b891bb7308ac83dfb4e80cad195c9f6f3" [[package]] name = "windows-sys" version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" dependencies = [ "windows-targets", ] [[package]] name = "windows-targets" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f0713a46559409d202e70e28227288446bf7841d3211583a4b53e3f6d96e7eb" dependencies = [ "windows_aarch64_gnullvm", "windows_aarch64_msvc", "windows_i686_gnu", "windows_i686_gnullvm", "windows_i686_msvc", "windows_x86_64_gnu", "windows_x86_64_gnullvm", "windows_x86_64_msvc", ] [[package]] name = "windows_aarch64_gnullvm" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7088eed71e8b8dda258ecc8bac5fb1153c5cffaf2578fc8ff5d61e23578d3263" [[package]] name = "windows_aarch64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9985fd1504e250c615ca5f281c3f7a6da76213ebd5ccc9561496568a2752afb6" [[package]] name = "windows_i686_gnu" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88ba073cf16d5372720ec942a8ccbf61626074c6d4dd2e745299726ce8b89670" [[package]] name = "windows_i686_gnullvm" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "87f4261229030a858f36b459e748ae97545d6f1ec60e5e0d6a3d32e0dc232ee9" [[package]] name = "windows_i686_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "db3c2bf3d13d5b658be73463284eaf12830ac9a26a90c717b7f771dfe97487bf" [[package]] name = "windows_x86_64_gnu" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4e4246f76bdeff09eb48875a0fd3e2af6aada79d409d33011886d3e1581517d9" [[package]] name = "windows_x86_64_gnullvm" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "852298e482cd67c356ddd9570386e2862b5673c85bd5f88df9ab6802b334c596" [[package]] name = "windows_x86_64_msvc" version = "0.52.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" escargot-0.5.12/Cargo.toml0000644000000105700000000000100107310ustar # THIS FILE IS AUTOMATICALLY GENERATED BY CARGO # # When uploading crates to the registry Cargo will automatically # "normalize" Cargo.toml files for maximal compatibility # with all versions of Cargo and also rewrite `path` dependencies # to registry (e.g., crates.io) dependencies. # # If you are reading this file be aware that the original Cargo.toml # will likely look very different (and much more reasonable). # See Cargo.toml.orig for the original contents. [package] edition = "2021" rust-version = "1.65" name = "escargot" version = "0.5.12" build = "build.rs" include = [ "build.rs", "src/**/*", "Cargo.toml", "Cargo.lock", "LICENSE*", "README.md", "benches/**/*", "examples/**/*", ] autobins = false autoexamples = false autotests = false autobenches = false description = "Cargo API written in Paris" homepage = "https://github.com/crate-ci/escargot" readme = "README.md" keywords = [ "cargo", "packaging", ] categories = ["development-tools::build-utils"] license = "MIT OR Apache-2.0" repository = "https://github.com/crate-ci/escargot.git" [package.metadata.docs.rs] all-features = true rustdoc-args = [ "--cfg", "docsrs", ] [[package.metadata.release.pre-release-replacements]] file = "CHANGELOG.md" min = 1 replace = "{{version}}" search = "Unreleased" [[package.metadata.release.pre-release-replacements]] exactly = 1 file = "CHANGELOG.md" replace = "...{{tag_name}}" search = '\.\.\.HEAD' [[package.metadata.release.pre-release-replacements]] file = "CHANGELOG.md" min = 1 replace = "{{date}}" search = "ReleaseDate" [[package.metadata.release.pre-release-replacements]] exactly = 1 file = "CHANGELOG.md" replace = """ ## [Unreleased] - ReleaseDate """ search = "" [[package.metadata.release.pre-release-replacements]] exactly = 1 file = "CHANGELOG.md" replace = """ [Unreleased]: https://github.com/crate-ci/escargot/compare/{{tag_name}}...HEAD""" search = "" [lib] name = "escargot" path = "src/lib.rs" [[bin]] name = "bin_fixture" path = "src/bin/bin_fixture.rs" [[example]] name = "example_fixture" path = "examples/example_fixture.rs" [dependencies.log] version = "0.4.4" [dependencies.once_cell] version = "1.2.0" [dependencies.serde] version = "1.0.113" features = ["derive"] [dependencies.serde_json] version = "1.0" [dev-dependencies.automod] version = "1.0.14" [dev-dependencies.tempfile] version = "3.3.0" [features] cargo_unstable = [] print = [] strict_unstable = [] test_unstable = [] [lints.clippy] bool_assert_comparison = "allow" branches_sharing_code = "allow" checked_conversions = "warn" collapsible_else_if = "allow" create_dir = "warn" dbg_macro = "warn" debug_assert_with_mut_call = "warn" doc_markdown = "warn" empty_enum = "warn" enum_glob_use = "warn" expl_impl_clone_on_copy = "warn" explicit_deref_methods = "warn" explicit_into_iter_loop = "warn" fallible_impl_from = "warn" filter_map_next = "warn" flat_map_option = "warn" float_cmp_const = "warn" fn_params_excessive_bools = "warn" from_iter_instead_of_collect = "warn" if_same_then_else = "allow" implicit_clone = "warn" imprecise_flops = "warn" inconsistent_struct_constructor = "warn" inefficient_to_string = "warn" infinite_loop = "warn" invalid_upcast_comparisons = "warn" items_after_statements = "warn" large_digit_groups = "warn" large_stack_arrays = "warn" large_types_passed_by_value = "warn" let_and_return = "allow" linkedlist = "warn" lossy_float_literal = "warn" macro_use_imports = "warn" match_wildcard_for_single_variants = "warn" mem_forget = "warn" mutex_integer = "warn" needless_continue = "warn" needless_for_each = "warn" negative_feature_names = "warn" path_buf_push_overwrite = "warn" ptr_as_ptr = "warn" rc_mutex = "warn" redundant_feature_names = "warn" ref_option_ref = "warn" rest_pat_in_fully_bound_structs = "warn" same_functions_in_if_condition = "warn" self_named_module_files = "warn" semicolon_if_nothing_returned = "warn" single_match_else = "warn" str_to_string = "warn" string_add = "warn" string_add_assign = "warn" string_lit_as_bytes = "warn" string_to_string = "warn" todo = "warn" trait_duplication_in_bounds = "warn" verbose_file_reads = "warn" wildcard_imports = "warn" zero_sized_map_values = "warn" [lints.rust] rust_2018_idioms = "warn" unreachable_pub = "warn" unsafe_op_in_unsafe_fn = "warn" unused_lifetimes = "warn" unused_macro_rules = "warn" unused_qualifications = "warn" escargot-0.5.12/Cargo.toml.orig000064400000000000000000000075601046102023000144170ustar 00000000000000[workspace] resolver = "2" [workspace.package] license = "MIT OR Apache-2.0" edition = "2021" rust-version = "1.65" # MSRV include = [ "build.rs", "src/**/*", "Cargo.toml", "Cargo.lock", "LICENSE*", "README.md", "benches/**/*", "examples/**/*" ] [workspace.lints.rust] rust_2018_idioms = "warn" unreachable_pub = "warn" unsafe_op_in_unsafe_fn = "warn" unused_lifetimes = "warn" unused_macro_rules = "warn" unused_qualifications = "warn" [workspace.lints.clippy] bool_assert_comparison = "allow" branches_sharing_code = "allow" checked_conversions = "warn" collapsible_else_if = "allow" create_dir = "warn" dbg_macro = "warn" debug_assert_with_mut_call = "warn" doc_markdown = "warn" empty_enum = "warn" enum_glob_use = "warn" expl_impl_clone_on_copy = "warn" explicit_deref_methods = "warn" explicit_into_iter_loop = "warn" fallible_impl_from = "warn" filter_map_next = "warn" flat_map_option = "warn" float_cmp_const = "warn" fn_params_excessive_bools = "warn" from_iter_instead_of_collect = "warn" if_same_then_else = "allow" implicit_clone = "warn" imprecise_flops = "warn" inconsistent_struct_constructor = "warn" inefficient_to_string = "warn" infinite_loop = "warn" invalid_upcast_comparisons = "warn" items_after_statements = "warn" large_digit_groups = "warn" large_stack_arrays = "warn" large_types_passed_by_value = "warn" let_and_return = "allow" # sometimes good to name what you are returning linkedlist = "warn" lossy_float_literal = "warn" macro_use_imports = "warn" match_wildcard_for_single_variants = "warn" mem_forget = "warn" mutex_integer = "warn" needless_continue = "warn" needless_for_each = "warn" negative_feature_names = "warn" path_buf_push_overwrite = "warn" ptr_as_ptr = "warn" rc_mutex = "warn" redundant_feature_names = "warn" ref_option_ref = "warn" rest_pat_in_fully_bound_structs = "warn" same_functions_in_if_condition = "warn" self_named_module_files = "warn" semicolon_if_nothing_returned = "warn" single_match_else = "warn" str_to_string = "warn" string_add = "warn" string_add_assign = "warn" string_lit_as_bytes = "warn" string_to_string = "warn" todo = "warn" trait_duplication_in_bounds = "warn" verbose_file_reads = "warn" wildcard_imports = "warn" zero_sized_map_values = "warn" [package] name = "escargot" version = "0.5.12" description = "Cargo API written in Paris" repository = "https://github.com/crate-ci/escargot.git" homepage = "https://github.com/crate-ci/escargot" categories = ["development-tools::build-utils"] keywords = ["cargo", "packaging"] license.workspace = true edition.workspace = true rust-version.workspace = true include.workspace = true [package.metadata.docs.rs] all-features = true rustdoc-args = ["--cfg", "docsrs"] [package.metadata.release] pre-release-replacements = [ {file="CHANGELOG.md", search="Unreleased", replace="{{version}}", min=1}, {file="CHANGELOG.md", search="\\.\\.\\.HEAD", replace="...{{tag_name}}", exactly=1}, {file="CHANGELOG.md", search="ReleaseDate", replace="{{date}}", min=1}, {file="CHANGELOG.md", search="", replace="\n## [Unreleased] - ReleaseDate\n", exactly=1}, {file="CHANGELOG.md", search="", replace="\n[Unreleased]: https://github.com/crate-ci/escargot/compare/{{tag_name}}...HEAD", exactly=1}, ] [features] # Upcoming features in cargo. cargo_unstable = [] # Programmatic use of `cargo test` (relies on an unstable CLI API). test_unstable = [] # This mostly exists for testing, to catch new fields and enum variants being # added (for the cases we actually cover). strict_unstable = [] # This is for when using `escargot` in tests and you want logged output to # instead be printed because no logger is configured. print = [] [dependencies] serde = { version = "1.0.113", features = ["derive"] } serde_json = "1.0" once_cell = "1.2.0" log = "0.4.4" [dev-dependencies] tempfile = "3.3.0" automod = "1.0.14" [lints] workspace = true escargot-0.5.12/LICENSE-APACHE000064400000000000000000000261361046102023000134540ustar 00000000000000 Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "{}" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright {yyyy} {name of copyright owner} 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. escargot-0.5.12/LICENSE-MIT000064400000000000000000000020461046102023000131560ustar 00000000000000Copyright (c) Individual contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. escargot-0.5.12/README.md000064400000000000000000000026741046102023000130100ustar 00000000000000# escargot > **Cargo API written in Paris** [![codecov](https://codecov.io/gh/crate-ci/escargot/branch/master/graph/badge.svg)](https://codecov.io/gh/crate-ci/escargot) [![Documentation](https://img.shields.io/badge/docs-master-blue.svg)][Documentation] ![License](https://img.shields.io/crates/l/escargot.svg) [![Crates Status](https://img.shields.io/crates/v/escargot.svg)][Crates.io] ## Why escargot Compared to depending on `cargo`: - Faster compile times. - Simpler API. - Better interop with projects relying on other cargo versions. - Probably slower execution, especially on platforms without an optimized `fork` (e.g. Windows). ## Relevant crates Other related crates: * [cargo](https://crates.io/crates/cargo) for the real thing * [cargo-metadata](https://crates.io/crates/cargo_metadata) for a similar project specifically geared to the `metadata` subcommand. ## License Licensed under either of * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or ) * MIT license ([LICENSE-MIT](LICENSE-MIT) or ) at your option. ### Contribution Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions. [Crates.io]: https://crates.io/crates/escargot [Documentation]: https://docs.rs/escargot escargot-0.5.12/build.rs000064400000000000000000000011201046102023000131570ustar 00000000000000use std::env; use std::fs; use std::io::Write; use std::path; fn main() { println!("cargo:rerun-if-changed=build.rs"); // env::ARCH doesn't include full triplet, and AFAIK there isn't a nicer way of getting the full triplet // (see lib.rs for the rest of this hack) let out = path::PathBuf::from(env::var_os("OUT_DIR").expect("run within cargo")) .join("current_target.txt"); let default_target = env::var("TARGET").expect("run as cargo build script"); let mut file = fs::File::create(out).unwrap(); file.write_all(default_target.as_bytes()).unwrap(); } escargot-0.5.12/examples/example_fixture.rs000064400000000000000000000013101046102023000171000ustar 00000000000000use std::env; use std::error::Error; use std::io; use std::io::Write; use std::process; fn run() -> Result<(), Box> { if let Ok(text) = env::var("stdout") { println!("{}", text); } if let Ok(text) = env::var("stderr") { eprintln!("{}", text); } let code = env::var("exit") .ok() .map(|v| v.parse::()) .map(|r| r.map(Some)) .unwrap_or(Ok(None))? .unwrap_or(0); process::exit(code); } fn main() { let code = match run() { Ok(_) => 0, Err(ref e) => { write!(&mut io::stderr(), "{}", e).expect("writing to stderr won't fail"); 1 } }; process::exit(code); } escargot-0.5.12/src/bin/bin_fixture.rs000064400000000000000000000013101046102023000157360ustar 00000000000000use std::env; use std::error::Error; use std::io; use std::io::Write; use std::process; fn run() -> Result<(), Box> { if let Ok(text) = env::var("stdout") { println!("{}", text); } if let Ok(text) = env::var("stderr") { eprintln!("{}", text); } let code = env::var("exit") .ok() .map(|v| v.parse::()) .map(|r| r.map(Some)) .unwrap_or(Ok(None))? .unwrap_or(0); process::exit(code); } fn main() { let code = match run() { Ok(_) => 0, Err(ref e) => { write!(&mut io::stderr(), "{}", e).expect("writing to stderr won't fail"); 1 } }; process::exit(code); } escargot-0.5.12/src/build.rs000064400000000000000000000215601046102023000137600ustar 00000000000000use std::ffi::OsStr; use std::process; use crate::cargo::Cargo; use crate::cargo::CURRENT_TARGET; use crate::error::CargoResult; use crate::msg::CommandMessages; use crate::run::CargoRun; #[cfg(feature = "test_unstable")] use crate::test::CargoTest; /// The `build` subcommand. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// escargot::CargoBuild::new() /// .bin("bin") /// .current_release() /// .current_target() /// .manifest_path("tests/testsuite/fixtures/bin/Cargo.toml") /// .target_dir(target_dir.path()) /// .exec() /// .unwrap(); /// ``` pub struct CargoBuild { cmd: process::Command, bin: bool, example: bool, } impl CargoBuild { /// Shortcut to create a `build` subcommand. /// /// See also [`Cargo`]. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// escargot::CargoBuild::new() /// .bin("bin") /// .manifest_path("tests/testsuite/fixtures/bin/Cargo.toml") /// .target_dir(target_dir.path()) /// .exec() /// .unwrap(); /// ``` /// pub fn new() -> Self { Cargo::new().build() } pub(crate) fn with_command(cmd: process::Command) -> Self { Self { cmd, bin: false, example: false, } } /// Build from `name` package in workspaces. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// escargot::CargoBuild::new() /// .package("bin") /// .bin("bin") /// .manifest_path("tests/testsuite/fixtures/bin/Cargo.toml") /// .target_dir(target_dir.path()) /// .exec() /// .unwrap(); /// ``` pub fn package>(self, name: S) -> Self { self.arg("--package").arg(name) } /// Build all binaries. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// escargot::CargoBuild::new() /// .bins() /// .manifest_path("tests/testsuite/fixtures/bin/Cargo.toml") /// .target_dir(target_dir.path()) /// .exec() /// .unwrap(); /// ``` pub fn bins(mut self) -> Self { self.bin = true; self.arg("--bins") } /// Build only `name` binary. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// escargot::CargoBuild::new() /// .bin("bin") /// .manifest_path("tests/testsuite/fixtures/bin/Cargo.toml") /// .target_dir(target_dir.path()) /// .exec() /// .unwrap(); /// ``` pub fn bin>(mut self, name: S) -> Self { self.bin = true; self.arg("--bin").arg(name) } /// Build all examples /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// escargot::CargoBuild::new() /// .examples() /// .manifest_path("tests/testsuite/fixtures/example/Cargo.toml") /// .target_dir(target_dir.path()) /// .exec() /// .unwrap(); /// ``` pub fn examples(mut self) -> Self { self.example = true; self.arg("--examples") } /// Build only `name` example. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// escargot::CargoBuild::new() /// .example("example_fixture") /// .manifest_path("tests/testsuite/fixtures/example/Cargo.toml") /// .target_dir(target_dir.path()) /// .exec() /// .unwrap(); /// ``` pub fn example>(mut self, name: S) -> Self { self.example = true; self.arg("--example").arg(name) } /// Build all tests /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// escargot::CargoBuild::new() /// .tests() /// .manifest_path("tests/testsuite/fixtures/test/Cargo.toml") /// .target_dir(target_dir.path()) /// .exec() /// .unwrap(); /// ``` pub fn tests(self) -> Self { self.arg("--tests") } /// Build only `name` test. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// escargot::CargoBuild::new() /// .test("test") /// .manifest_path("tests/testsuite/fixtures/test/Cargo.toml") /// .target_dir(target_dir.path()) /// .exec() /// .unwrap(); /// ``` pub fn test>(self, name: S) -> Self { self.arg("--test").arg(name) } /// Path to Cargo.toml pub fn manifest_path>(self, path: S) -> Self { self.arg("--manifest-path").arg(path) } /// Build artifacts in release mode, with optimizations. pub fn release(self) -> Self { self.arg("--release") } /// Inserts or updates an environment variable mapping. pub fn env(mut self, key: K, val: V) -> Self where K: AsRef, V: AsRef, { self.cmd.env(key, val); self } /// Removes an environment variable pub fn env_remove(mut self, key: K) -> Self where K: AsRef, { self.cmd.env_remove(key); self } /// Build artifacts in release mode if the current process has, with optimizations. #[cfg(debug_assertions)] pub fn current_release(self) -> Self { self } /// Build artifacts in release mode if the current process has, with optimizations. #[cfg(not(debug_assertions))] pub fn current_release(self) -> Self { self.release() } /// Build for the target triplet. pub fn target>(self, triplet: S) -> Self { self.arg("--target").arg(triplet) } /// Build for the current process' triplet. pub fn current_target(self) -> Self { self.target(CURRENT_TARGET) } /// Directory for all generated artifacts pub fn target_dir>(self, dir: S) -> Self { self.arg("--target-dir").arg(dir) } /// Activate all available features pub fn all_features(self) -> Self { self.arg("--all-features") } /// Do not activate the `default` feature pub fn no_default_features(self) -> Self { self.arg("--no-default-features") } /// Space-separated list of features to activate pub fn features>(self, features: S) -> Self { self.arg("--features").arg(features) } /// Manually pass an argument that is unsupported. /// /// Caution: Passing in `--` can throw off the API. pub fn arg>(mut self, arg: S) -> Self { self.cmd.arg(arg); self } /// Manually pass arguments that are unsupported. /// /// Caution: Passing in `--` can throw off the API. pub fn args, S: AsRef>(mut self, args: I) -> Self { self.cmd.args(args); self } /// Build the configured target, returning compiler messages. pub fn exec(self) -> CargoResult { CommandMessages::with_command(self.cmd) } /// Provide a proxy for running the built target. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// let run = escargot::CargoBuild::new() /// .bin("bin") /// .current_release() /// .current_target() /// .manifest_path("tests/testsuite/fixtures/bin/Cargo.toml") /// .target_dir(target_dir.path()) /// .run() /// .unwrap(); /// println!("artifact={}", run.path().display()); /// ``` pub fn run(self) -> CargoResult { let msgs = CommandMessages::with_command(self.cmd)?; CargoRun::from_message(msgs, self.bin, self.example) } /// Provide a proxy for running the built target. /// /// Required feature: `test_unstable` since the format parsed is unstable. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// let run = escargot::CargoBuild::new() /// .test("test") /// .current_release() /// .current_target() /// .manifest_path("tests/testsuite/fixtures/test/Cargo.toml") /// .target_dir(target_dir.path()) /// .run_tests().unwrap() /// .next().unwrap().unwrap(); /// println!("artifact={}", run.path().display()); /// ``` #[cfg(feature = "test_unstable")] pub fn run_tests(self) -> CargoResult>> { let msgs = CommandMessages::with_command(self.cmd)?; Ok(CargoTest::with_messages(msgs)) } } impl Default for CargoBuild { fn default() -> Self { Self::new() } } escargot-0.5.12/src/cargo.rs000064400000000000000000000030651046102023000137540ustar 00000000000000use std::env; use std::ffi; use std::process; use std::str; use crate::build::CargoBuild; /// The current process' target triplet. pub const CURRENT_TARGET: &str = include_str!(concat!(env!("OUT_DIR"), "/current_target.txt")); static CARBO_BIN: once_cell::sync::Lazy = once_cell::sync::Lazy::new(|| env::var_os("CARGO").unwrap_or_else(|| "cargo".into())); /// Top-level command. #[derive(Debug)] pub struct Cargo { cmd: process::Command, } impl Cargo { /// Create a top-level command. pub fn new() -> Self { Self { cmd: process::Command::new(CARBO_BIN.as_os_str()), } } /// Manually pass an argument that is unsupported. /// /// Caution: Passing in a sub-command or `--` can throw off the API. pub fn arg>(mut self, arg: S) -> Self { self.cmd.arg(arg); self } /// Manually pass arguments that are unsupported. /// /// Caution: Passing in a sub-command or `--` can throw off the API. pub fn args, S: AsRef>(mut self, args: I) -> Self { self.cmd.args(args); self } /// Run the `build` subcommand. pub fn build(self) -> CargoBuild { self.build_with("build") } /// Run a custom `build` subcommand. pub fn build_with>(mut self, name: S) -> CargoBuild { self.cmd.arg(name).arg("--message-format=json"); CargoBuild::with_command(self.cmd) } } impl Default for Cargo { fn default() -> Self { Self::new() } } escargot-0.5.12/src/error.rs000064400000000000000000000044521046102023000140130ustar 00000000000000//! Error reporting API. use std::error::Error; use std::fmt; /// Result of a cargo command. pub type CargoResult = Result; /// For programmatically processing failures. #[derive(Debug, Copy, Clone, PartialEq, Eq)] pub enum ErrorKind { /// Spawning the cargo subommand failed. InvalidCommand, /// The cargo subcommand returned an error. CommandFailed, /// Parsing the cargo subcommand's output failed. InvalidOutput, } impl fmt::Display for ErrorKind { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match *self { ErrorKind::InvalidOutput => write!(f, "Spawning the cargo subommand failed."), ErrorKind::CommandFailed => write!(f, "The cargo subcommand returned an error."), ErrorKind::InvalidCommand => write!(f, "Parsing the cargo subcommand's output failed."), } } } /// Cargo command failure information. #[derive(Debug)] pub struct CargoError { kind: ErrorKind, context: Option, cause: Option>, } impl CargoError { pub(crate) fn new(kind: ErrorKind) -> Self { Self { kind, context: None, cause: None, } } pub(crate) fn set_context(mut self, context: S) -> Self where S: Into, { let context = context.into(); self.context = Some(context); self } pub(crate) fn set_cause(mut self, cause: E) -> Self where E: Error + Send + Sync + 'static, { let cause = Box::new(cause); self.cause = Some(cause); self } /// For programmatically processing failures. pub fn kind(&self) -> ErrorKind { self.kind } } impl Error for CargoError { fn cause(&self) -> Option<&dyn Error> { self.cause.as_ref().map(|c| { let c: &dyn Error = c.as_ref(); c }) } } impl fmt::Display for CargoError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { writeln!(f, "Cargo command failed: {}", self.kind)?; if let Some(ref context) = self.context { writeln!(f, "{}", context)?; } if let Some(ref cause) = self.cause { writeln!(f, "Cause: {}", cause)?; } Ok(()) } } escargot-0.5.12/src/format/diagnostic.rs000064400000000000000000000132051046102023000162720ustar 00000000000000//! This module contains `Diagnostic` and the types/functions it uses for deserialization. use std::borrow; use std::path; type CowPath<'a> = borrow::Cow<'a, path::Path>; type CowStr<'a> = borrow::Cow<'a, str>; /// The error code associated to this diagnostic. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))] #[non_exhaustive] pub struct DiagnosticCode<'a> { /// The code itself. #[serde(borrow)] pub code: CowStr<'a>, /// An explanation for the code #[serde(borrow)] pub explanation: Option>, } /// A line of code associated with the Diagnostic #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))] #[non_exhaustive] pub struct DiagnosticSpanLine<'a> { /// The line of code associated with the error #[serde(borrow)] pub text: CowStr<'a>, /// Start of the section of the line to highlight. 1-based, character offset in self.text pub highlight_start: usize, /// End of the section of the line to highlight. 1-based, character offset in self.text pub highlight_end: usize, } /// Macro expansion information associated with a diagnostic. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))] #[non_exhaustive] pub struct DiagnosticSpanMacroExpansion<'a> { /// span where macro was applied to generate this code; note that /// this may itself derive from a macro (if /// `span.expansion.is_some()`) #[serde(borrow)] pub span: DiagnosticSpan<'a>, /// name of macro that was applied (e.g., "foo!" or "#[derive(Eq)]") #[serde(borrow)] pub macro_decl_name: CowStr<'a>, /// span where macro was defined (if known) #[serde(borrow)] pub def_site_span: Option>, } /// A section of the source code associated with a Diagnostic #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))] #[non_exhaustive] pub struct DiagnosticSpan<'a> { /// The file name this diagnostic comes from. #[serde(borrow)] pub file_name: CowPath<'a>, /// The byte offset in the file where this diagnostic starts from. pub byte_start: u32, /// The byte offset in the file where this diagnostic ends. pub byte_end: u32, /// 1-based. The line in the file. pub line_start: usize, /// 1-based. The line in the file. pub line_end: usize, /// 1-based, character offset. pub column_start: usize, /// 1-based, character offset. pub column_end: usize, /// Is this a "primary" span -- meaning the point, or one of the points, /// where the error occurred? pub is_primary: bool, /// Source text from the start of `line_start` to the end of `line_end`. #[serde(borrow)] pub text: Vec>, /// Label that should be placed at this location (if any) #[serde(borrow)] pub label: Option>, /// If we are suggesting a replacement, this will contain text /// that should be sliced in atop this span. #[serde(borrow)] pub suggested_replacement: Option>, /// If the suggestion is approximate pub suggestion_applicability: Option, /// Macro invocations that created the code at this span, if any. #[serde(borrow)] pub expansion: Option>>, } /// Whether a suggestion can be safely applied. #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] pub enum Applicability { /// The suggested replacement can be applied automatically safely MachineApplicable, /// The suggested replacement has placeholders that will need to be manually /// replaced. HasPlaceholders, /// The suggested replacement may be incorrect in some circumstances. Needs /// human review. MaybeIncorrect, /// The suggested replacement will probably not work. Unspecified, #[cfg(not(feature = "strict_unstable"))] #[doc(hidden)] #[serde(other)] Unknown, } /// A diagnostic message generated by rustc #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))] #[non_exhaustive] pub struct Diagnostic<'a> { /// Can be used to distinguish the different formats. /// /// When parsing, care should be taken to be forwards-compatible with future changes to the format. #[serde(borrow, rename = "$message_type")] pub message_type: Option>, /// The error message of this diagnostic. #[serde(borrow)] pub message: CowStr<'a>, /// The associated error code for this diagnostic #[serde(borrow)] pub code: Option>, /// The severity of the diagnostic. pub level: DiagnosticLevel, /// A list of source code spans this diagnostic is associated with. #[serde(borrow)] pub spans: Vec>, /// Associated diagnostic messages. #[serde(borrow)] pub children: Vec>, /// The message as rustc would render it #[serde(borrow)] pub rendered: Option>, } /// The diagnostic level #[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)] #[serde(rename_all = "lowercase")] pub enum DiagnosticLevel { /// Internal compiler error #[serde(rename = "error: internal compiler error")] Ice, /// Error Error, /// Warning Warning, /// Note Note, /// Help Help, #[cfg(not(feature = "strict_unstable"))] #[doc(hidden)] #[serde(other)] Unknown, } escargot-0.5.12/src/format/mod.rs000064400000000000000000000224131046102023000147260ustar 00000000000000//! Serialization formats for cargo messages. use std::borrow; use std::path; pub mod diagnostic; #[cfg(feature = "test_unstable")] pub mod test; type CowPath<'a> = borrow::Cow<'a, path::Path>; type CowStr<'a> = borrow::Cow<'a, str>; /// A cargo message #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[serde(tag = "reason", rename_all = "kebab-case")] #[allow(clippy::large_enum_variant)] pub enum Message<'a> { /// Build completed, all further output should not be parsed BuildFinished(BuildFinished), /// The compiler generated an artifact #[serde(borrow)] CompilerArtifact(Artifact<'a>), /// The compiler wants to display a message #[serde(borrow)] CompilerMessage(FromCompiler<'a>), /// A build script successfully executed. #[serde(borrow)] BuildScriptExecuted(BuildScript<'a>), #[cfg(not(feature = "strict_unstable"))] #[doc(hidden)] #[serde(other)] Unknown, } /// Build completed, all further output should not be parsed #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))] #[non_exhaustive] pub struct BuildFinished { success: bool, } /// A compiler-generated file. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))] #[non_exhaustive] pub struct Artifact<'a> { /// The workspace member this artifact belongs to #[serde(borrow)] pub package_id: WorkspaceMember<'a>, /// The full path to the artifact's manifest #[serde(borrow)] pub manifest_path: Option>, /// The target this artifact was compiled for #[serde(borrow)] pub target: Target<'a>, /// The profile this artifact was compiled with #[serde(borrow)] pub profile: ArtifactProfile<'a>, /// The enabled features for this artifact #[serde(borrow)] pub features: Vec>, /// The full paths to the generated artifacts #[serde(borrow)] pub filenames: Vec>, /// The full paths to the generated artifacts #[serde(borrow)] #[serde(default)] pub executable: Option>, /// If true, then the files were already generated pub fresh: bool, } /// A single target (lib, bin, example, ...) provided by a crate #[derive(Clone, PartialEq, Eq, Serialize, Deserialize, Debug)] #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))] #[non_exhaustive] pub struct Target<'a> { /// Name as given in the `Cargo.toml` or generated from the file name #[serde(borrow)] pub name: CowStr<'a>, /// Kind of target ("bin", "example", "test", "bench", "lib") #[serde(borrow)] pub kind: Vec>, /// Almost the same as `kind`, except when an example is a library instead of an executable. /// In that case `crate_types` contains things like `rlib` and `dylib` while `kind` is `example` #[serde(default)] #[serde(borrow)] pub crate_types: Vec>, /// Whether this is a doctest or not #[serde(default)] pub doctest: Option, /// Whether this is documentation or not #[serde(default)] pub doc: Option, /// Whether this is a test file #[serde(default)] pub test: bool, #[serde(default)] #[serde(rename = "required-features")] /// This target is built only if these features are enabled. /// It doesn't apply to `lib` targets. #[serde(borrow)] pub required_features: Vec>, /// Path to the main source file of the target #[serde(borrow)] pub src_path: CowPath<'a>, /// Rust edition for this target #[serde(default = "edition_default")] #[serde(borrow)] pub edition: CowStr<'a>, } fn edition_default() -> CowStr<'static> { "2015".into() } /// A workspace member. This is basically identical to `cargo::core::package_id::PackageId`, except /// that this does not use `Arc` internally. #[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)] #[serde(transparent)] #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))] pub struct WorkspaceMember<'a> { /// The raw package id as given by cargo #[serde(borrow)] raw: CowStr<'a>, } /// Profile settings used to determine which compiler flags to use for a /// target. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))] #[non_exhaustive] pub struct ArtifactProfile<'a> { /// Optimization level. Possible values are 0-3, s or z. #[serde(borrow)] pub opt_level: CowStr<'a>, /// The amount of debug info. 0 for none, 1 for limited, 2 for full pub debuginfo: Option, /// State of the `cfg(debug_assertions)` directive, enabling macros like /// `debug_assert!` pub debug_assertions: bool, /// State of the overflow checks. pub overflow_checks: bool, /// Whether this profile is a test pub test: bool, } /// Message left by the compiler #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))] #[non_exhaustive] pub struct FromCompiler<'a> { /// The workspace member this message belongs to #[serde(borrow)] pub package_id: WorkspaceMember<'a>, /// The full path to the artifact's manifest #[serde(borrow)] pub manifest_path: Option>, /// The target this message is aimed at #[serde(borrow)] pub target: Target<'a>, /// The message the compiler sent. #[serde(borrow)] pub message: diagnostic::Diagnostic<'a>, } /// Output of a Build Script execution. #[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] #[cfg_attr(feature = "strict_unstable", serde(deny_unknown_fields))] #[non_exhaustive] pub struct BuildScript<'a> { /// The workspace member this build script execution belongs to #[serde(borrow)] pub package_id: WorkspaceMember<'a>, /// The outdir used. #[serde(borrow)] #[serde(default)] pub out_dir: Option>, /// The libs to link #[serde(borrow)] pub linked_libs: Vec>, /// The paths to search when resolving libs #[serde(borrow)] pub linked_paths: Vec>, /// The paths to search when resolving libs #[serde(borrow)] pub cfgs: Vec>, /// The environment variables to add to the compilation #[serde(borrow)] pub env: Vec<(CowStr<'a>, CowStr<'a>)>, } #[cfg(not(feature = "print"))] pub(crate) fn log_message(msg: &Message<'_>) { match msg { Message::BuildFinished(ref finished) => { log::trace!("Build Finished: {:?}", finished.success); } Message::CompilerArtifact(ref art) => { log::trace!("Building {:#?}", art.package_id,); } Message::CompilerMessage(ref comp) => { let content = comp .message .rendered .as_ref() .map(|s| s.as_ref()) .unwrap_or_else(|| comp.message.message.as_ref()); match comp.message.level { diagnostic::DiagnosticLevel::Ice => log::error!("{}", content), diagnostic::DiagnosticLevel::Error => log::error!("{}", content), diagnostic::DiagnosticLevel::Warning => log::warn!("{}", content), diagnostic::DiagnosticLevel::Note => log::info!("{}", content), diagnostic::DiagnosticLevel::Help => log::info!("{}", content), #[cfg(not(feature = "strict_unstable"))] _ => log::warn!("Unknown message: {:#?}", msg), } } Message::BuildScriptExecuted(ref script) => { log::trace!("Ran script from {:#?}", script.package_id); } #[cfg(not(feature = "strict_unstable"))] _ => { log::warn!("Unknown message: {:#?}", msg); } } } #[cfg(feature = "print")] #[allow(clippy::print_stderr)] pub(crate) fn log_message(msg: &Message<'_>) { match msg { Message::BuildFinished(ref finished) => { eprintln!("Build Finished: {:?}", finished.success); } Message::CompilerArtifact(ref art) => { eprintln!("Building {:#?}", art.package_id,); } Message::CompilerMessage(ref comp) => { let content = comp .message .rendered .as_ref() .map(|s| s.as_ref()) .unwrap_or_else(|| comp.message.message.as_ref()); match comp.message.level { diagnostic::DiagnosticLevel::Ice => eprintln!("{}", content), diagnostic::DiagnosticLevel::Error => eprintln!("{}", content), diagnostic::DiagnosticLevel::Warning => eprintln!("{}", content), diagnostic::DiagnosticLevel::Note => eprintln!("{}", content), diagnostic::DiagnosticLevel::Help => eprintln!("{}", content), #[cfg(not(feature = "strict_unstable"))] _ => eprintln!("Unknown message: {:#?}", msg), } } Message::BuildScriptExecuted(ref script) => { eprintln!("Ran script from {:#?}", script.package_id); } #[cfg(not(feature = "strict_unstable"))] _ => { eprintln!("Unknown message: {:#?}", msg); } } } escargot-0.5.12/src/format/test.rs000064400000000000000000000145001046102023000151240ustar 00000000000000//! Test runner emitted events. //! //! Required feature: `test_unstable` since the format parsed is unstable. use serde::Deserialize; // See https://github.com/rust-lang/rust/tree/master/src/libtest/formatters/json.rs /// Test-runner event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[serde(rename_all = "snake_case")] #[serde(tag = "type")] pub enum Event { /// Suite event. Suite(Suite), /// Test case event. Test(Test), /// Benchmark event. Bench(Bench), #[cfg(not(feature = "strict_unstable"))] #[doc(hidden)] #[serde(other)] Unknown, } /// Suite event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[serde(rename_all = "snake_case")] #[serde(tag = "event")] pub enum Suite { /// Suite-started event. Started(SuiteStarted), /// Suite-finished successfully event. Ok(SuiteOk), /// Suite-finished with failure event. Failed(SuiteFailed), #[cfg(not(feature = "strict_unstable"))] #[doc(hidden)] #[serde(other)] Unknown, } /// Suite-started event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct SuiteStarted { /// Number of test cases in the suite. pub test_count: usize, } /// Suite-finished successfully event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct SuiteOk { /// Cases that passed. pub passed: usize, /// Cases that failed. pub failed: usize, /// Cases that were allowed to fail. pub allowed_fail: usize, /// Ignored cases. pub ignored: usize, /// Benchmarks pub measured: usize, /// Cases filtered out by caller. pub filtered_out: usize, } /// Suite-finished with failure event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct SuiteFailed { /// Cases that passed. pub passed: usize, /// Cases that failed. pub failed: usize, /// Cases that were allowed to fail. pub allowed_fail: usize, /// Ignored cases. pub ignored: usize, /// Benchmarks pub measured: usize, /// Cases filtered out by caller. pub filtered_out: usize, } /// Test case event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[serde(rename_all = "snake_case")] #[serde(tag = "event")] pub enum Test { /// Case-started event. Started(TestStarted), /// Case-finished successfully event. Ok(TestOk), /// Case-finished with failure event. Failed(TestFailed), /// Case-ignored event. Ignored(TestIgnored), /// Case-allowed-failure event. AllowedFailure(TestAllowedFailure), /// Case-timeout event. Timeout(TestTimeout), #[cfg(not(feature = "strict_unstable"))] #[doc(hidden)] #[serde(other)] Unknown, } /// Case-started event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct TestStarted { /// Test case name. pub name: String, } /// Case-finished successfully event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct TestOk { /// Test case name. pub name: String, } /// Case-finished with failure event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct TestFailed { /// Test case name. pub name: String, /// Test's stdout pub stdout: Option, /// Test failure mssage pub message: Option, } /// Case-ignored event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct TestIgnored { /// Test case name. pub name: String, } /// Case-allowed-failure event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct TestAllowedFailure { /// Test case name. pub name: String, } /// Case-timeout event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct TestTimeout { /// Test case name. pub name: String, } /// Benchmark event. #[derive(Serialize, Deserialize, Clone, Debug, Eq, PartialEq)] #[non_exhaustive] pub struct Bench { /// Benchmark name. pub name: String, /// Median performance. pub median: usize, /// Deviation from median. pub deviation: usize, /// Mb/s pub mib_per_second: Option, } #[cfg(test)] mod tests { use super::*; #[test] fn suite_started() { let input = r#"{ "type": "suite", "event": "started", "test_count": 10 }"#; let _data: Event = serde_json::from_str(input).unwrap(); } #[test] fn suite_ok() { let input = "{ \"type\": \"suite\", \ \"event\": \"ok\", \ \"passed\": 6, \ \"failed\": 5, \ \"allowed_fail\": 4, \ \"ignored\": 3, \ \"measured\": 2, \ \"filtered_out\": 1 }"; let _data: Event = serde_json::from_str(input).unwrap(); } #[test] fn suite_failed() { let input = "{ \"type\": \"suite\", \ \"event\": \"failed\", \ \"passed\": 6, \ \"failed\": 5, \ \"allowed_fail\": 4, \ \"ignored\": 3, \ \"measured\": 2, \ \"filtered_out\": 1 }"; let _data: Event = serde_json::from_str(input).unwrap(); } #[test] fn test_started() { let input = r#"{ "type": "test", "event": "started", "name": "foo" }"#; let _data: Event = serde_json::from_str(input).unwrap(); } #[test] fn test_timeout() { let input = r#"{ "type": "test", "event": "timeout", "name": "foo" }"#; let _data: Event = serde_json::from_str(input).unwrap(); } #[test] fn bench() { let input = "{ \"type\": \"bench\", \ \"name\": \"foo\", \ \"median\": 10, \ \"deviation\": 2 }"; let _data: Event = serde_json::from_str(input).unwrap(); } #[test] fn bench_full() { let input = "{ \"type\": \"bench\", \ \"name\": \"foo\", \ \"median\": 10, \ \"deviation\": 2, \ \"mib_per_second\": 1 }"; let _data: Event = serde_json::from_str(input).unwrap(); } } escargot-0.5.12/src/lib.rs000064400000000000000000000027511046102023000134300ustar 00000000000000//! # Escargot: A Cargo API //! //! ## Features //! //! Features: //! - `print` for logged output to be printed instead, generally for test writing. //! //! ## Why escargot //! //! Compared to depending on `cargo`: //! - Faster compile times. //! - Simpler API. //! - Better interop with projects relying on other cargo versions. //! - Probably slower execution, especially on platforms without an optimized `fork` (e.g. Windows). //! //! ## Relevant crates //! //! Other related crates: //! * [cargo](https://crates.io/crates/cargo) for the real thing //! * [cargo-metadata](https://crates.io/crates/cargo_metadata) for a similar project specifically geared to the `metadata` subcommand. //! //! # Example //! //! ```rust //! # let target_dir = tempfile::TempDir::new().unwrap(); //! escargot::CargoBuild::new() //! .bin("bin") //! .current_release() //! .current_target() //! .manifest_path("tests/fixtures/bin/Cargo.toml") //! .target_dir(target_dir.path()) //! .exec() //! .unwrap(); //! ``` #![allow(clippy::self_named_module_files)] // false positive #![warn(missing_docs)] #![warn(clippy::print_stderr)] #![warn(clippy::print_stdout)] #![cfg_attr(docsrs, feature(doc_auto_cfg))] #[macro_use] extern crate serde; mod build; pub use crate::build::*; mod cargo; pub use crate::cargo::*; mod msg; pub use crate::msg::*; mod run; pub use crate::run::*; #[cfg(feature = "test_unstable")] mod test; #[cfg(feature = "test_unstable")] pub use test::*; pub mod error; pub mod format; escargot-0.5.12/src/msg.rs000064400000000000000000000065411046102023000134510ustar 00000000000000use std::io; use std::io::BufRead; use std::io::Read; use std::process; use crate::error::{CargoError, CargoResult, ErrorKind}; use crate::format; /// Messages returned from a cargo sub-command. pub struct CommandMessages(InnerCommandMessages); struct InnerCommandMessages { done: bool, child: process::Child, stdout: io::BufReader, stderr: io::BufReader, } impl CommandMessages { /// Run the command, allowing iteration over ndjson messages. pub fn with_command(mut cmd: process::Command) -> CargoResult { let mut child = cmd .stdout(process::Stdio::piped()) .stderr(process::Stdio::piped()) .spawn() .map_err(|e| CargoError::new(ErrorKind::InvalidCommand).set_cause(e))?; let stdout = child.stdout.take().expect("piped above"); let stdout = io::BufReader::new(stdout); let stderr = child.stderr.take().expect("piped above"); let stderr = io::BufReader::new(stderr); let msgs = InnerCommandMessages { done: false, child, stdout, stderr, }; Ok(CommandMessages(msgs)) } #[inline] fn next_msg(&mut self) -> CargoResult> { #![allow(clippy::branches_sharing_code)] let mut content = String::new(); let len = self .0 .stdout .read_line(&mut content) .map_err(|e| CargoError::new(ErrorKind::InvalidOutput).set_cause(e))?; if 0 < len { Ok(Some(Message(content))) } else { let status = self .0 .child .wait() .map_err(|e| CargoError::new(ErrorKind::InvalidOutput).set_cause(e))?; if !status.success() && !self.0.done { self.0.done = true; let mut data = vec![]; self.0 .stderr .read_to_end(&mut data) .map_err(|e| CargoError::new(ErrorKind::InvalidOutput).set_cause(e))?; let err = CargoError::new(ErrorKind::CommandFailed) .set_context(String::from_utf8_lossy(&data)); Err(err) } else { self.0.done = true; Ok(None) } } } } impl Drop for CommandMessages { fn drop(&mut self) { if !self.0.done { let _ = self.0.child.wait(); } } } impl Iterator for CommandMessages { type Item = CargoResult; #[inline] fn next(&mut self) -> Option> { match self.next_msg() { Ok(Some(x)) => Some(Ok(x)), Ok(None) => None, Err(e) => Some(Err(e)), } } } /// An individual message from a cargo sub-command. #[derive(Debug, Clone, PartialEq, Eq)] pub struct Message(String); impl Message { /// Deserialize the message. pub fn decode(&self) -> CargoResult> { self.decode_custom() } /// Deserialize the message. pub fn decode_custom<'a, T>(&'a self) -> CargoResult where T: serde::Deserialize<'a>, { let data = serde_json::from_str(self.0.as_str()) .map_err(|e| CargoError::new(ErrorKind::InvalidOutput).set_cause(e))?; Ok(data) } } escargot-0.5.12/src/run.rs000064400000000000000000000131601046102023000134620ustar 00000000000000use std::path; use std::process; use crate::error::{CargoError, CargoResult, ErrorKind}; use crate::format; use crate::msg::CommandMessages; /// The `run` subcommand (emulated). /// /// Created via [`CargoBuild::run`][crate::CargoBuild::run]. /// /// Benefits over spawning `cargo run`: /// - Able to cache binary path, avoiding cargo overhead. /// - Independent of CWD. /// - stdout/stderr are clean of `cargo run` output. /// /// Relevant features /// - `print` for logged output to be printed instead, generally for test writing. /// /// # Example /// /// To create a [`CargoRun`]: /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// let run = escargot::CargoBuild::new() /// .bin("bin") /// .current_release() /// .current_target() /// .manifest_path("tests/testsuite/fixtures/bin/Cargo.toml") /// .target_dir(target_dir.path()) /// .run() /// .unwrap(); /// println!("artifact={}", run.path().display()); /// ``` /// See [`CargoRun::path`] for how to then run the newly compiled /// program. pub struct CargoRun { bin_path: path::PathBuf, } impl CargoRun { pub(crate) fn from_message( msgs: CommandMessages, is_bin: bool, is_example: bool, ) -> CargoResult { let kind = match (is_bin, is_example) { (true, true) => { return Err(CargoError::new(ErrorKind::CommandFailed) .set_context("Ambiguous which binary is intended, multiple selected")); } (false, true) => "example", _ => "bin", }; let bin_path = extract_binary_path(msgs, kind)?; Ok(Self { bin_path }) } /// Path to the specified binary. /// /// This is to support alternative ways of launching the binary besides [`Command`]. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// let run = escargot::CargoBuild::new() /// .bin("bin") /// .current_release() /// .current_target() /// .manifest_path("tests/testsuite/fixtures/bin/Cargo.toml") /// .target_dir(target_dir.path()) /// .run() /// .unwrap(); /// println!("artifact={}", run.path().display()); /// ``` /// or /// ```rust,no_run /// # let target_dir = tempfile::TempDir::new().unwrap(); /// let run = escargot::CargoBuild::new() /// .example("example_fixture") /// .current_release() /// .current_target() /// .manifest_path("tests/testsuite/fixtures/example/Cargo.toml") /// .target_dir(target_dir.path()) /// .run() /// .unwrap(); /// println!("artifact={}", run.path().display()); /// ``` /// /// [`Command`]: std::process::Command pub fn path(&self) -> &path::Path { &self.bin_path } /// Run the build artifact. /// /// # Example /// /// ```rust,no_run /// # let target_dir = tempfile::TempDir::new().unwrap(); /// let run = escargot::CargoBuild::new() /// .bin("bin") /// .current_release() /// .current_target() /// .manifest_path("tests/testsuite/fixtures/bin/Cargo.toml") /// .target_dir(target_dir.path()) /// .run() /// .unwrap() /// .command() /// .arg("--help") /// .status() /// .unwrap(); /// ``` /// or /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// let run = escargot::CargoBuild::new() /// .example("example_fixture") /// .current_release() /// .current_target() /// .manifest_path("tests/testsuite/fixtures/example/Cargo.toml") /// .target_dir(target_dir.path()) /// .run() /// .unwrap() /// .command() /// .arg("--help") /// .status() /// .unwrap(); /// ``` pub fn command(&self) -> process::Command { process::Command::new(self.path()) } } fn extract_bin<'a>(msg: &'a format::Message<'_>, desired_kind: &str) -> Option<&'a path::Path> { match msg { format::Message::CompilerArtifact(art) => { if !art.profile.test && art.target.crate_types == ["bin"] && art.target.kind == [desired_kind] { Some(art.filenames.first().expect("files must exist")) } else { None } } _ => None, } } fn transpose(r: Result, E>) -> Option> { match r { Ok(Some(x)) => Some(Ok(x)), Ok(None) => None, Err(e) => Some(Err(e)), } } fn extract_binary_paths( msgs: CommandMessages, kind: &'static str, ) -> impl Iterator> { msgs.filter_map(move |m| { let m = m.and_then(|m| { let m = m.decode()?; format::log_message(&m); let p = extract_bin(&m, kind).map(|p| p.to_path_buf()); Ok(p) }); transpose(m) }) } fn extract_binary_path( msgs: CommandMessages, kind: &'static str, ) -> Result { let bins: Result, CargoError> = extract_binary_paths(msgs, kind).collect(); let bins = bins?; if bins.is_empty() { return Err(CargoError::new(ErrorKind::CommandFailed).set_context("No binaries in crate")); } else if bins.len() != 1 { return Err( CargoError::new(ErrorKind::CommandFailed).set_context(std::format!( "Ambiguous which binary is intended: {:?}", bins )), ); } Ok(bins.into_iter().next().expect("already validated")) } escargot-0.5.12/src/test.rs000064400000000000000000000125541046102023000136430ustar 00000000000000use std::path; use std::process; use crate::error::{CargoError, CargoResult}; use crate::format; use crate::msg::CommandMessages; /// The `test` subcommand (emulated). /// /// Created via [`CargoBuild::run_tests`]. /// /// Benefits over spawning `cargo test`: /// - Able to cache binary path, avoiding cargo overhead. /// - Independent of CWD. /// - stdout/stderr are clean of `cargo test` output. /// /// Required feature: `test_unstable` since the format parsed is unstable. /// /// Relevant features /// - `print` for logged output to be printed instead, generally for test writing. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// let run = escargot::CargoBuild::new() /// .test("test") /// .manifest_path("tests/testsuite/fixtures/test/Cargo.toml") /// .target_dir(target_dir.path()) /// .run_tests().unwrap() /// .next().unwrap().unwrap(); /// println!("artifact={}", run.path().display()); /// ``` /// /// [`CargoBuild::run_tests`]: crate::CargoBuild::run_tests() pub struct CargoTest { bin_path: path::PathBuf, kind: String, name: String, } impl CargoTest { pub(crate) fn with_messages( msgs: CommandMessages, ) -> impl Iterator> { extract_binary_paths(msgs) } /// The `name` of test /// /// Used to offer filtering or displays. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// let run: Result, _> = escargot::CargoBuild::new() /// .tests() /// .current_release() /// .current_target() /// .manifest_path("tests/testsuite/fixtures/test/Cargo.toml") /// .target_dir(target_dir.path()) /// .run_tests() /// .unwrap() /// .collect(); /// let run = run.unwrap(); /// let mut names: Vec<_> = run.iter().map(|r| r.name()).collect(); /// names.sort_unstable(); /// assert_eq!(names, ["test", "test_fixture", "test_fixture"]); /// ``` pub fn name(&self) -> &str { self.name.as_str() } /// The `kind` of test /// /// Used to distinguish between integration tests (`test`) and unit tests (`bin`, `lib`). /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// let run: Result, _> = escargot::CargoBuild::new() /// .tests() /// .current_release() /// .current_target() /// .manifest_path("tests/testsuite/fixtures/test/Cargo.toml") /// .target_dir(target_dir.path()) /// .run_tests() /// .unwrap() /// .collect(); /// let run = run.unwrap(); /// let mut kinds: Vec<_> = run.iter().map(|r| r.kind()).collect(); /// kinds.sort_unstable(); /// assert_eq!(kinds, ["bin", "lib", "test"]); /// ``` pub fn kind(&self) -> &str { self.kind.as_str() } /// Path to the specified binary. /// /// This is to support alternative ways of launching the binary besides [`Command`]. /// /// # Example /// /// ```rust /// # let target_dir = tempfile::TempDir::new().unwrap(); /// let run: Vec<_> = escargot::CargoBuild::new() /// .tests() /// .current_release() /// .current_target() /// .manifest_path("tests/testsuite/fixtures/test/Cargo.toml") /// .target_dir(target_dir.path()) /// .run_tests() /// .unwrap() /// .collect(); /// assert_eq!(run.len(), 3); /// ``` /// /// [`Command`]: std::process::Command pub fn path(&self) -> &path::Path { &self.bin_path } /// Run the build artifact. pub fn command(&self) -> process::Command { let mut cmd = process::Command::new(self.path()); cmd.arg("-Z").arg("unstable-options").arg("--format=json"); cmd } /// Run the configured test, returning test events. pub fn exec(&self) -> CargoResult { CommandMessages::with_command(self.command()) } } fn extract_bin(msg: &format::Message<'_>) -> Option { match msg { format::Message::CompilerArtifact(art) => { if art.profile.test { let bin_path = art .filenames .first() .expect("files must exist") .to_path_buf(); let kind = art .target .kind .first() .expect("kind must exist") .as_ref() .to_owned(); let name = art.target.name.as_ref().to_owned(); Some(CargoTest { bin_path, kind, name, }) } else { None } } _ => None, } } fn transpose(r: Result, E>) -> Option> { match r { Ok(Some(x)) => Some(Ok(x)), Ok(None) => None, Err(e) => Some(Err(e)), } } fn extract_binary_paths( msgs: CommandMessages, ) -> impl Iterator> { msgs.filter_map(move |m| { let m = m.and_then(|m| { let m = m.decode()?; format::log_message(&m); let p = extract_bin(&m); Ok(p) }); transpose(m) }) } escargot-0.5.12/tests/testsuite/build.rs000064400000000000000000000027251046102023000163660ustar 00000000000000fn test_fixture(name: &str) { let temp = tempfile::TempDir::new().unwrap(); let msgs = escargot::CargoBuild::new() .manifest_path(format!("tests/testsuite/fixtures/{}/Cargo.toml", name)) .current_release() .current_target() .target_dir(temp.path()) .exec() .unwrap(); for msg in msgs { let raw_msg = msg.unwrap(); let msg = raw_msg.decode(); match msg { Ok(msg) => println!("{:#?}", msg), Err(err) => panic!("{}\nmsg=`{:#?}`", err, raw_msg), } } } #[test] fn test_bin() { test_fixture("bin"); } #[test] fn test_lib() { test_fixture("lib"); } #[test] fn test_bin_lib() { test_fixture("bin_lib"); } #[test] fn test_warn() { test_fixture("warn"); } #[test] fn test_build_script() { test_fixture("script"); } #[test] fn test_dependency() { test_fixture("dep"); } #[test] fn test_error() { let msgs: Vec<_> = escargot::CargoBuild::new() .manifest_path("tests/testsuite/fixtures/error/Cargo.toml") .current_release() .current_target() .exec() .unwrap() .collect(); assert!(1 < msgs.len()); let error_idx = msgs.len() - 1; for msg in &msgs[0..error_idx] { let msg = msg.as_ref().unwrap(); let msg = msg.decode().unwrap(); println!("{:#?}", msg); } assert!(msgs[error_idx].is_err()); println!("```{}```", msgs[error_idx].as_ref().err().unwrap()); }