From 5363f350887b1e5b5dd21a86f88c8af9d7fea6da Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Wed, 17 Apr 2024 14:18:25 +0200 Subject: Merging upstream version 1.67.1+dfsg1. Signed-off-by: Daniel Baumann --- vendor/env_logger/.cargo-checksum.json | 1 - vendor/env_logger/CHANGELOG.md | 3 - vendor/env_logger/Cargo.toml | 65 - vendor/env_logger/LICENSE-APACHE | 201 --- vendor/env_logger/LICENSE-MIT | 25 - vendor/env_logger/README.md | 185 --- vendor/env_logger/src/filter/mod.rs | 868 ------------- vendor/env_logger/src/filter/regex.rs | 29 - vendor/env_logger/src/filter/string.rs | 24 - vendor/env_logger/src/fmt/humantime/extern_impl.rs | 118 -- vendor/env_logger/src/fmt/humantime/mod.rs | 11 - vendor/env_logger/src/fmt/humantime/shim_impl.rs | 5 - vendor/env_logger/src/fmt/mod.rs | 652 ---------- vendor/env_logger/src/fmt/writer/atty.rs | 32 - vendor/env_logger/src/fmt/writer/mod.rs | 252 ---- .../src/fmt/writer/termcolor/extern_impl.rs | 510 -------- vendor/env_logger/src/fmt/writer/termcolor/mod.rs | 12 - .../src/fmt/writer/termcolor/shim_impl.rs | 73 -- vendor/env_logger/src/lib.rs | 1315 -------------------- .../env_logger/tests/init-twice-retains-filter.rs | 40 - vendor/env_logger/tests/log-in-log.rs | 39 - vendor/env_logger/tests/log_tls_dtors.rs | 66 - vendor/env_logger/tests/regexp_filter.rs | 57 - 23 files changed, 4583 deletions(-) delete mode 100644 vendor/env_logger/.cargo-checksum.json delete mode 100644 vendor/env_logger/CHANGELOG.md delete mode 100644 vendor/env_logger/Cargo.toml delete mode 100644 vendor/env_logger/LICENSE-APACHE delete mode 100644 vendor/env_logger/LICENSE-MIT delete mode 100644 vendor/env_logger/README.md delete mode 100644 vendor/env_logger/src/filter/mod.rs delete mode 100644 vendor/env_logger/src/filter/regex.rs delete mode 100644 vendor/env_logger/src/filter/string.rs delete mode 100644 vendor/env_logger/src/fmt/humantime/extern_impl.rs delete mode 100644 vendor/env_logger/src/fmt/humantime/mod.rs delete mode 100644 vendor/env_logger/src/fmt/humantime/shim_impl.rs delete mode 100644 vendor/env_logger/src/fmt/mod.rs delete mode 100644 vendor/env_logger/src/fmt/writer/atty.rs delete mode 100644 vendor/env_logger/src/fmt/writer/mod.rs delete mode 100644 vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs delete mode 100644 vendor/env_logger/src/fmt/writer/termcolor/mod.rs delete mode 100644 vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs delete mode 100644 vendor/env_logger/src/lib.rs delete mode 100644 vendor/env_logger/tests/init-twice-retains-filter.rs delete mode 100644 vendor/env_logger/tests/log-in-log.rs delete mode 100644 vendor/env_logger/tests/log_tls_dtors.rs delete mode 100644 vendor/env_logger/tests/regexp_filter.rs (limited to 'vendor/env_logger') diff --git a/vendor/env_logger/.cargo-checksum.json b/vendor/env_logger/.cargo-checksum.json deleted file mode 100644 index ae346af10..000000000 --- a/vendor/env_logger/.cargo-checksum.json +++ /dev/null @@ -1 +0,0 @@ -{"files":{"CHANGELOG.md":"34c3abc5bfaeb865e9b901c245f7e41f02a96b6be50beef5302458bff548ef3c","Cargo.toml":"ee8ec2750c4a2c13b1140b72a17355ddd7496f5636e9694d7648fd4d4ff23151","LICENSE-APACHE":"a60eea817514531668d7e00765731449fe14d059d3249e0bc93b36de45f759f2","LICENSE-MIT":"6485b8ed310d3f0340bf1ad1f47645069ce4069dcc6bb46c7d5c6faf41de1fdb","README.md":"534d72fab83eaa93e0e61e3d092b888681e4705c77e568e4acad6d42993278ed","src/filter/mod.rs":"1df1659ebe5815119999a7f49dadb1c69d703acd6fad69a29574470aa1dd3533","src/filter/regex.rs":"bdf875bac25e089e1e462f5dd01a88678067c24118ecd6268561c6a6af39747d","src/filter/string.rs":"fac54d51189fc0b5d2bff334b7a7e465177b431e3428299e345e1f90062d832e","src/fmt/humantime/extern_impl.rs":"f3087b29eedb8b4d5573621ad206e48a2eac72a77277be3b0e631d7dc9fb7a2e","src/fmt/humantime/mod.rs":"f4111c26cf2ffb85c1d639bd7674d55af7e1736e7e98c52f7be3070046a3253f","src/fmt/humantime/shim_impl.rs":"cce9a252abd5952fa109a72b1dfb85a593d237e22606b2b608a32c69184560e9","src/fmt/mod.rs":"6256c12a661c471c2e8e4c3cb21a9a19bf9da793ae44addbbe059a056d5fa964","src/fmt/writer/atty.rs":"09d14097dee61492828daaabdbde9f43251e2cb32e79d66c1c0e63f317761704","src/fmt/writer/mod.rs":"960d9bdeb356b555d32269c6a2f68252c0553078d0c2b7915fdaf98842ef4ef3","src/fmt/writer/termcolor/extern_impl.rs":"839b8bf043939f3f22a6cd21c94e339149e5d0578a9b40fa8ca4fbe574573475","src/fmt/writer/termcolor/mod.rs":"a790f9391a50cd52be6823e3e55942de13a8d12e23d63765342ae9e8dd6d091c","src/fmt/writer/termcolor/shim_impl.rs":"9e9997823434d6741934ddeb5f4354c7da5083cee1e9dda997b4c6ccb31f9842","src/lib.rs":"2c97b9d898197b5b8f2a62c181f4d3ded0584b4548a888991e5fbe61caec5fa2","tests/init-twice-retains-filter.rs":"be5cd2132342d89ede1f5c4266173bb3c4d51cc22a1847f133d299a1c5430ccb","tests/log-in-log.rs":"29fecc65c1e0d1c22d79c97e7ca843ad44a91f27934148d7a05c48899a3f39d8","tests/log_tls_dtors.rs":"7320667d774a9b05037f7bf273fb2574dec0705707692a9cd2f46f4cd5bc68dd","tests/regexp_filter.rs":"a84263c995b534b6479a1d0abadf63f4f0264958ff86d9173d6b2139b82c4dc5"},"package":"0b2cf0344971ee6c64c31be0d530793fba457d322dfec2810c453d0ef228f9c3"} \ No newline at end of file diff --git a/vendor/env_logger/CHANGELOG.md b/vendor/env_logger/CHANGELOG.md deleted file mode 100644 index 266e24a78..000000000 --- a/vendor/env_logger/CHANGELOG.md +++ /dev/null @@ -1,3 +0,0 @@ -Changes to this crate are tracked via [GitHub Releases][releases]. - -[releases]: https://github.com/env-logger-rs/env_logger/releases diff --git a/vendor/env_logger/Cargo.toml b/vendor/env_logger/Cargo.toml deleted file mode 100644 index b91eddb65..000000000 --- a/vendor/env_logger/Cargo.toml +++ /dev/null @@ -1,65 +0,0 @@ -# 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 believe there's an error in this file please file an -# issue against the rust-lang/cargo repository. If you're -# editing this file be aware that the upstream Cargo.toml -# will likely look very different (and much more reasonable) - -[package] -edition = "2018" -name = "env_logger" -version = "0.9.0" -authors = ["The Rust Project Developers"] -include = ["src/**/*", "tests", "LICENSE-*", "README.md", "CHANGELOG.md"] -description = "A logging implementation for `log` which is configured via an environment\nvariable.\n" -documentation = "https://docs.rs/env_logger" -readme = "README.md" -keywords = ["logging", "log", "logger"] -categories = ["development-tools::debugging"] -license = "MIT/Apache-2.0" -repository = "https://github.com/env-logger-rs/env_logger/" - -[[test]] -name = "regexp_filter" -harness = false - -[[test]] -name = "log-in-log" -harness = false - -[[test]] -name = "log_tls_dtors" -harness = false - -[[test]] -name = "init-twice-retains-filter" -harness = false -[dependencies.atty] -version = "0.2.5" -optional = true - -[dependencies.humantime] -version = "2.0.0" -optional = true - -[dependencies.log] -version = "0.4.8" -features = ["std"] - -[dependencies.regex] -version = "1.0.3" -features = ["std", "perf"] -optional = true -default-features = false - -[dependencies.termcolor] -version = "1.0.2" -optional = true - -[features] -default = ["termcolor", "atty", "humantime", "regex"] diff --git a/vendor/env_logger/LICENSE-APACHE b/vendor/env_logger/LICENSE-APACHE deleted file mode 100644 index 16fe87b06..000000000 --- a/vendor/env_logger/LICENSE-APACHE +++ /dev/null @@ -1,201 +0,0 @@ - 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. diff --git a/vendor/env_logger/LICENSE-MIT b/vendor/env_logger/LICENSE-MIT deleted file mode 100644 index 39d4bdb5a..000000000 --- a/vendor/env_logger/LICENSE-MIT +++ /dev/null @@ -1,25 +0,0 @@ -Copyright (c) 2014 The Rust Project Developers - -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. diff --git a/vendor/env_logger/README.md b/vendor/env_logger/README.md deleted file mode 100644 index 4e84e8f34..000000000 --- a/vendor/env_logger/README.md +++ /dev/null @@ -1,185 +0,0 @@ -# env_logger - -[![Maintenance](https://img.shields.io/badge/maintenance-actively%20maintained-brightgreen.svg)](https://github.com/env-logger-rs/env_logger) -[![crates.io](https://img.shields.io/crates/v/env_logger.svg)](https://crates.io/crates/env_logger) -[![Documentation](https://docs.rs/env_logger/badge.svg)](https://docs.rs/env_logger) -[![Documentation](https://img.shields.io/badge/docs-master-blue.svg)](https://env-logger-rs.github.io/env_logger/env_logger/index.html) -========== - -Implements a logger that can be configured via environment variables. - -## Usage - -### In libraries - -`env_logger` makes sense when used in executables (binary projects). Libraries should use the [`log`](https://doc.rust-lang.org/log) crate instead. - -### In executables - -It must be added along with `log` to the project dependencies: - -```toml -[dependencies] -log = "0.4.0" -env_logger = "0.8.4" -``` - -`env_logger` must be initialized as early as possible in the project. After it's initialized, you can use the `log` macros to do actual logging. - -```rust -#[macro_use] -extern crate log; - -fn main() { - env_logger::init(); - - info!("starting up"); - - // ... -} -``` - -Then when running the executable, specify a value for the **`RUST_LOG`** -environment variable that corresponds with the log messages you want to show. - -```bash -$ RUST_LOG=info ./main -[2018-11-03T06:09:06Z INFO default] starting up -``` - -The letter case is not significant for the logging level names; e.g., `debug`, -`DEBUG`, and `dEbuG` all represent the same logging level. Therefore, the -previous example could also have been written this way, specifying the log -level as `INFO` rather than as `info`: - -```bash -$ RUST_LOG=INFO ./main -[2018-11-03T06:09:06Z INFO default] starting up -``` - -So which form should you use? For consistency, our convention is to use lower -case names. Where our docs do use other forms, they do so in the context of -specific examples, so you won't be surprised if you see similar usage in the -wild. - -The log levels that may be specified correspond to the [`log::Level`][level-enum] -enum from the `log` crate. They are: - - * `error` - * `warn` - * `info` - * `debug` - * `trace` - -[level-enum]: https://docs.rs/log/latest/log/enum.Level.html "log::Level (docs.rs)" - -There is also a pseudo logging level, `off`, which may be specified to disable -all logging for a given module or for the entire application. As with the -logging levels, the letter case is not significant. - -`env_logger` can be configured in other ways besides an environment variable. See [the examples](https://github.com/env-logger-rs/env_logger/tree/master/examples) for more approaches. - -### In tests - -Tests can use the `env_logger` crate to see log messages generated during that test: - -```toml -[dependencies] -log = "0.4.0" - -[dev-dependencies] -env_logger = "0.8.4" -``` - -```rust -#[macro_use] -extern crate log; - -fn add_one(num: i32) -> i32 { - info!("add_one called with {}", num); - num + 1 -} - -#[cfg(test)] -mod tests { - use super::*; - - fn init() { - let _ = env_logger::builder().is_test(true).try_init(); - } - - #[test] - fn it_adds_one() { - init(); - - info!("can log from the test too"); - assert_eq!(3, add_one(2)); - } - - #[test] - fn it_handles_negative_numbers() { - init(); - - info!("logging from another test"); - assert_eq!(-7, add_one(-8)); - } -} -``` - -Assuming the module under test is called `my_lib`, running the tests with the -`RUST_LOG` filtering to info messages from this module looks like: - -```bash -$ RUST_LOG=my_lib=info cargo test - Running target/debug/my_lib-... - -running 2 tests -[INFO my_lib::tests] logging from another test -[INFO my_lib] add_one called with -8 -test tests::it_handles_negative_numbers ... ok -[INFO my_lib::tests] can log from the test too -[INFO my_lib] add_one called with 2 -test tests::it_adds_one ... ok - -test result: ok. 2 passed; 0 failed; 0 ignored; 0 measured -``` - -Note that `env_logger::try_init()` needs to be called in each test in which you -want to enable logging. Additionally, the default behavior of tests to -run in parallel means that logging output may be interleaved with test output. -Either run tests in a single thread by specifying `RUST_TEST_THREADS=1` or by -running one test by specifying its name as an argument to the test binaries as -directed by the `cargo test` help docs: - -```bash -$ RUST_LOG=my_lib=info cargo test it_adds_one - Running target/debug/my_lib-... - -running 1 test -[INFO my_lib::tests] can log from the test too -[INFO my_lib] add_one called with 2 -test tests::it_adds_one ... ok - -test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured -``` - -## Configuring log target - -By default, `env_logger` logs to stderr. If you want to log to stdout instead, -you can use the `Builder` to change the log target: - -```rust -use std::env; -use env_logger::{Builder, Target}; - -let mut builder = Builder::from_default_env(); -builder.target(Target::Stdout); - -builder.init(); -``` - -## Stability of the default format - -The default format won't optimise for long-term stability, and explicitly makes no guarantees about the stability of its output across major, minor or patch version bumps during `0.x`. - -If you want to capture or interpret the output of `env_logger` programmatically then you should use a custom format. diff --git a/vendor/env_logger/src/filter/mod.rs b/vendor/env_logger/src/filter/mod.rs deleted file mode 100644 index 9ebeab0b5..000000000 --- a/vendor/env_logger/src/filter/mod.rs +++ /dev/null @@ -1,868 +0,0 @@ -//! Filtering for log records. -//! -//! This module contains the log filtering used by `env_logger` to match records. -//! You can use the `Filter` type in your own logger implementation to use the same -//! filter parsing and matching as `env_logger`. For more details about the format -//! for directive strings see [Enabling Logging]. -//! -//! ## Using `env_logger` in your own logger -//! -//! You can use `env_logger`'s filtering functionality with your own logger. -//! Call [`Builder::parse`] to parse directives from a string when constructing -//! your logger. Call [`Filter::matches`] to check whether a record should be -//! logged based on the parsed filters when log records are received. -//! -//! ``` -//! extern crate log; -//! extern crate env_logger; -//! use env_logger::filter::Filter; -//! use log::{Log, Metadata, Record}; -//! -//! struct MyLogger { -//! filter: Filter -//! } -//! -//! impl MyLogger { -//! fn new() -> MyLogger { -//! use env_logger::filter::Builder; -//! let mut builder = Builder::new(); -//! -//! // Parse a directives string from an environment variable -//! if let Ok(ref filter) = std::env::var("MY_LOG_LEVEL") { -//! builder.parse(filter); -//! } -//! -//! MyLogger { -//! filter: builder.build() -//! } -//! } -//! } -//! -//! impl Log for MyLogger { -//! fn enabled(&self, metadata: &Metadata) -> bool { -//! self.filter.enabled(metadata) -//! } -//! -//! fn log(&self, record: &Record) { -//! // Check if the record is matched by the filter -//! if self.filter.matches(record) { -//! println!("{:?}", record); -//! } -//! } -//! -//! fn flush(&self) {} -//! } -//! ``` -//! -//! [Enabling Logging]: ../index.html#enabling-logging -//! [`Builder::parse`]: struct.Builder.html#method.parse -//! [`Filter::matches`]: struct.Filter.html#method.matches - -use log::{Level, LevelFilter, Metadata, Record}; -use std::collections::HashMap; -use std::env; -use std::fmt; -use std::mem; - -#[cfg(feature = "regex")] -#[path = "regex.rs"] -mod inner; - -#[cfg(not(feature = "regex"))] -#[path = "string.rs"] -mod inner; - -/// A log filter. -/// -/// This struct can be used to determine whether or not a log record -/// should be written to the output. -/// Use the [`Builder`] type to parse and construct a `Filter`. -/// -/// [`Builder`]: struct.Builder.html -pub struct Filter { - directives: Vec, - filter: Option, -} - -/// A builder for a log filter. -/// -/// It can be used to parse a set of directives from a string before building -/// a [`Filter`] instance. -/// -/// ## Example -/// -/// ``` -/// # #[macro_use] extern crate log; -/// # use std::env; -/// use env_logger::filter::Builder; -/// -/// let mut builder = Builder::new(); -/// -/// // Parse a logging filter from an environment variable. -/// if let Ok(rust_log) = env::var("RUST_LOG") { -/// builder.parse(&rust_log); -/// } -/// -/// let filter = builder.build(); -/// ``` -/// -/// [`Filter`]: struct.Filter.html -pub struct Builder { - directives: HashMap, LevelFilter>, - filter: Option, - built: bool, -} - -#[derive(Debug)] -struct Directive { - name: Option, - level: LevelFilter, -} - -impl Filter { - /// Returns the maximum `LevelFilter` that this filter instance is - /// configured to output. - /// - /// # Example - /// - /// ```rust - /// use log::LevelFilter; - /// use env_logger::filter::Builder; - /// - /// let mut builder = Builder::new(); - /// builder.filter(Some("module1"), LevelFilter::Info); - /// builder.filter(Some("module2"), LevelFilter::Error); - /// - /// let filter = builder.build(); - /// assert_eq!(filter.filter(), LevelFilter::Info); - /// ``` - pub fn filter(&self) -> LevelFilter { - self.directives - .iter() - .map(|d| d.level) - .max() - .unwrap_or(LevelFilter::Off) - } - - /// Checks if this record matches the configured filter. - pub fn matches(&self, record: &Record) -> bool { - if !self.enabled(record.metadata()) { - return false; - } - - if let Some(filter) = self.filter.as_ref() { - if !filter.is_match(&*record.args().to_string()) { - return false; - } - } - - true - } - - /// Determines if a log message with the specified metadata would be logged. - pub fn enabled(&self, metadata: &Metadata) -> bool { - let level = metadata.level(); - let target = metadata.target(); - - enabled(&self.directives, level, target) - } -} - -impl Builder { - /// Initializes the filter builder with defaults. - pub fn new() -> Builder { - Builder { - directives: HashMap::new(), - filter: None, - built: false, - } - } - - /// Initializes the filter builder from an environment. - pub fn from_env(env: &str) -> Builder { - let mut builder = Builder::new(); - - if let Ok(s) = env::var(env) { - builder.parse(&s); - } - - builder - } - - /// Adds a directive to the filter for a specific module. - pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self { - self.filter(Some(module), level) - } - - /// Adds a directive to the filter for all modules. - pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self { - self.filter(None, level) - } - - /// Adds a directive to the filter. - /// - /// The given module (if any) will log at most the specified level provided. - /// If no module is provided then the filter will apply to all log messages. - pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self { - self.directives.insert(module.map(|s| s.to_string()), level); - self - } - - /// Parses the directives string. - /// - /// See the [Enabling Logging] section for more details. - /// - /// [Enabling Logging]: ../index.html#enabling-logging - pub fn parse(&mut self, filters: &str) -> &mut Self { - let (directives, filter) = parse_spec(filters); - - self.filter = filter; - - for directive in directives { - self.directives.insert(directive.name, directive.level); - } - self - } - - /// Build a log filter. - pub fn build(&mut self) -> Filter { - assert!(!self.built, "attempt to re-use consumed builder"); - self.built = true; - - let mut directives = Vec::new(); - if self.directives.is_empty() { - // Adds the default filter if none exist - directives.push(Directive { - name: None, - level: LevelFilter::Error, - }); - } else { - // Consume map of directives. - let directives_map = mem::take(&mut self.directives); - directives = directives_map - .into_iter() - .map(|(name, level)| Directive { name, level }) - .collect(); - // Sort the directives by length of their name, this allows a - // little more efficient lookup at runtime. - directives.sort_by(|a, b| { - let alen = a.name.as_ref().map(|a| a.len()).unwrap_or(0); - let blen = b.name.as_ref().map(|b| b.len()).unwrap_or(0); - alen.cmp(&blen) - }); - } - - Filter { - directives: mem::take(&mut directives), - filter: mem::replace(&mut self.filter, None), - } - } -} - -impl Default for Builder { - fn default() -> Self { - Builder::new() - } -} - -impl fmt::Debug for Filter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Filter") - .field("filter", &self.filter) - .field("directives", &self.directives) - .finish() - } -} - -impl fmt::Debug for Builder { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.built { - f.debug_struct("Filter").field("built", &true).finish() - } else { - f.debug_struct("Filter") - .field("filter", &self.filter) - .field("directives", &self.directives) - .finish() - } - } -} - -/// Parse a logging specification string (e.g: "crate1,crate2::mod3,crate3::x=error/foo") -/// and return a vector with log directives. -fn parse_spec(spec: &str) -> (Vec, Option) { - let mut dirs = Vec::new(); - - let mut parts = spec.split('/'); - let mods = parts.next(); - let filter = parts.next(); - if parts.next().is_some() { - eprintln!( - "warning: invalid logging spec '{}', \ - ignoring it (too many '/'s)", - spec - ); - return (dirs, None); - } - if let Some(m) = mods { - for s in m.split(',').map(|ss| ss.trim()) { - if s.is_empty() { - continue; - } - let mut parts = s.split('='); - let (log_level, name) = - match (parts.next(), parts.next().map(|s| s.trim()), parts.next()) { - (Some(part0), None, None) => { - // if the single argument is a log-level string or number, - // treat that as a global fallback - match part0.parse() { - Ok(num) => (num, None), - Err(_) => (LevelFilter::max(), Some(part0)), - } - } - (Some(part0), Some(""), None) => (LevelFilter::max(), Some(part0)), - (Some(part0), Some(part1), None) => match part1.parse() { - Ok(num) => (num, Some(part0)), - _ => { - eprintln!( - "warning: invalid logging spec '{}', \ - ignoring it", - part1 - ); - continue; - } - }, - _ => { - eprintln!( - "warning: invalid logging spec '{}', \ - ignoring it", - s - ); - continue; - } - }; - dirs.push(Directive { - name: name.map(|s| s.to_string()), - level: log_level, - }); - } - } - - let filter = filter.and_then(|filter| match inner::Filter::new(filter) { - Ok(re) => Some(re), - Err(e) => { - eprintln!("warning: invalid regex filter - {}", e); - None - } - }); - - (dirs, filter) -} - -// Check whether a level and target are enabled by the set of directives. -fn enabled(directives: &[Directive], level: Level, target: &str) -> bool { - // Search for the longest match, the vector is assumed to be pre-sorted. - for directive in directives.iter().rev() { - match directive.name { - Some(ref name) if !target.starts_with(&**name) => {} - Some(..) | None => return level <= directive.level, - } - } - false -} - -#[cfg(test)] -mod tests { - use log::{Level, LevelFilter}; - - use super::{enabled, parse_spec, Builder, Directive, Filter}; - - fn make_logger_filter(dirs: Vec) -> Filter { - let mut logger = Builder::new().build(); - logger.directives = dirs; - logger - } - - #[test] - fn filter_info() { - let logger = Builder::new().filter(None, LevelFilter::Info).build(); - assert!(enabled(&logger.directives, Level::Info, "crate1")); - assert!(!enabled(&logger.directives, Level::Debug, "crate1")); - } - - #[test] - fn filter_beginning_longest_match() { - let logger = Builder::new() - .filter(Some("crate2"), LevelFilter::Info) - .filter(Some("crate2::mod"), LevelFilter::Debug) - .filter(Some("crate1::mod1"), LevelFilter::Warn) - .build(); - assert!(enabled(&logger.directives, Level::Debug, "crate2::mod1")); - assert!(!enabled(&logger.directives, Level::Debug, "crate2")); - } - - // Some of our tests are only correct or complete when they cover the full - // universe of variants for log::Level. In the unlikely event that a new - // variant is added in the future, this test will detect the scenario and - // alert us to the need to review and update the tests. In such a - // situation, this test will fail to compile, and the error message will - // look something like this: - // - // error[E0004]: non-exhaustive patterns: `NewVariant` not covered - // --> src/filter/mod.rs:413:15 - // | - // 413 | match level_universe { - // | ^^^^^^^^^^^^^^ pattern `NewVariant` not covered - #[test] - fn ensure_tests_cover_level_universe() { - let level_universe: Level = Level::Trace; // use of trace variant is arbitrary - match level_universe { - Level::Error | Level::Warn | Level::Info | Level::Debug | Level::Trace => (), - } - } - - #[test] - fn parse_default() { - let logger = Builder::new().parse("info,crate1::mod1=warn").build(); - assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1")); - assert!(enabled(&logger.directives, Level::Info, "crate2::mod2")); - } - - #[test] - fn parse_default_bare_level_off_lc() { - let logger = Builder::new().parse("off").build(); - assert!(!enabled(&logger.directives, Level::Error, "")); - assert!(!enabled(&logger.directives, Level::Warn, "")); - assert!(!enabled(&logger.directives, Level::Info, "")); - assert!(!enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - - #[test] - fn parse_default_bare_level_off_uc() { - let logger = Builder::new().parse("OFF").build(); - assert!(!enabled(&logger.directives, Level::Error, "")); - assert!(!enabled(&logger.directives, Level::Warn, "")); - assert!(!enabled(&logger.directives, Level::Info, "")); - assert!(!enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - - #[test] - fn parse_default_bare_level_error_lc() { - let logger = Builder::new().parse("error").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(!enabled(&logger.directives, Level::Warn, "")); - assert!(!enabled(&logger.directives, Level::Info, "")); - assert!(!enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - - #[test] - fn parse_default_bare_level_error_uc() { - let logger = Builder::new().parse("ERROR").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(!enabled(&logger.directives, Level::Warn, "")); - assert!(!enabled(&logger.directives, Level::Info, "")); - assert!(!enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - - #[test] - fn parse_default_bare_level_warn_lc() { - let logger = Builder::new().parse("warn").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(enabled(&logger.directives, Level::Warn, "")); - assert!(!enabled(&logger.directives, Level::Info, "")); - assert!(!enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - - #[test] - fn parse_default_bare_level_warn_uc() { - let logger = Builder::new().parse("WARN").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(enabled(&logger.directives, Level::Warn, "")); - assert!(!enabled(&logger.directives, Level::Info, "")); - assert!(!enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - - #[test] - fn parse_default_bare_level_info_lc() { - let logger = Builder::new().parse("info").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(enabled(&logger.directives, Level::Warn, "")); - assert!(enabled(&logger.directives, Level::Info, "")); - assert!(!enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - - #[test] - fn parse_default_bare_level_info_uc() { - let logger = Builder::new().parse("INFO").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(enabled(&logger.directives, Level::Warn, "")); - assert!(enabled(&logger.directives, Level::Info, "")); - assert!(!enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - - #[test] - fn parse_default_bare_level_debug_lc() { - let logger = Builder::new().parse("debug").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(enabled(&logger.directives, Level::Warn, "")); - assert!(enabled(&logger.directives, Level::Info, "")); - assert!(enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - - #[test] - fn parse_default_bare_level_debug_uc() { - let logger = Builder::new().parse("DEBUG").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(enabled(&logger.directives, Level::Warn, "")); - assert!(enabled(&logger.directives, Level::Info, "")); - assert!(enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - - #[test] - fn parse_default_bare_level_trace_lc() { - let logger = Builder::new().parse("trace").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(enabled(&logger.directives, Level::Warn, "")); - assert!(enabled(&logger.directives, Level::Info, "")); - assert!(enabled(&logger.directives, Level::Debug, "")); - assert!(enabled(&logger.directives, Level::Trace, "")); - } - - #[test] - fn parse_default_bare_level_trace_uc() { - let logger = Builder::new().parse("TRACE").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(enabled(&logger.directives, Level::Warn, "")); - assert!(enabled(&logger.directives, Level::Info, "")); - assert!(enabled(&logger.directives, Level::Debug, "")); - assert!(enabled(&logger.directives, Level::Trace, "")); - } - - // In practice, the desired log level is typically specified by a token - // that is either all lowercase (e.g., 'trace') or all uppercase (.e.g, - // 'TRACE'), but this tests serves as a reminder that - // log::Level::from_str() ignores all case variants. - #[test] - fn parse_default_bare_level_debug_mixed() { - { - let logger = Builder::new().parse("Debug").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(enabled(&logger.directives, Level::Warn, "")); - assert!(enabled(&logger.directives, Level::Info, "")); - assert!(enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - { - let logger = Builder::new().parse("debuG").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(enabled(&logger.directives, Level::Warn, "")); - assert!(enabled(&logger.directives, Level::Info, "")); - assert!(enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - { - let logger = Builder::new().parse("deBug").build(); - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(enabled(&logger.directives, Level::Warn, "")); - assert!(enabled(&logger.directives, Level::Info, "")); - assert!(enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - { - let logger = Builder::new().parse("DeBuG").build(); // LaTeX flavor! - assert!(enabled(&logger.directives, Level::Error, "")); - assert!(enabled(&logger.directives, Level::Warn, "")); - assert!(enabled(&logger.directives, Level::Info, "")); - assert!(enabled(&logger.directives, Level::Debug, "")); - assert!(!enabled(&logger.directives, Level::Trace, "")); - } - } - - #[test] - fn match_full_path() { - let logger = make_logger_filter(vec![ - Directive { - name: Some("crate2".to_string()), - level: LevelFilter::Info, - }, - Directive { - name: Some("crate1::mod1".to_string()), - level: LevelFilter::Warn, - }, - ]); - assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1")); - assert!(!enabled(&logger.directives, Level::Info, "crate1::mod1")); - assert!(enabled(&logger.directives, Level::Info, "crate2")); - assert!(!enabled(&logger.directives, Level::Debug, "crate2")); - } - - #[test] - fn no_match() { - let logger = make_logger_filter(vec![ - Directive { - name: Some("crate2".to_string()), - level: LevelFilter::Info, - }, - Directive { - name: Some("crate1::mod1".to_string()), - level: LevelFilter::Warn, - }, - ]); - assert!(!enabled(&logger.directives, Level::Warn, "crate3")); - } - - #[test] - fn match_beginning() { - let logger = make_logger_filter(vec![ - Directive { - name: Some("crate2".to_string()), - level: LevelFilter::Info, - }, - Directive { - name: Some("crate1::mod1".to_string()), - level: LevelFilter::Warn, - }, - ]); - assert!(enabled(&logger.directives, Level::Info, "crate2::mod1")); - } - - #[test] - fn match_beginning_longest_match() { - let logger = make_logger_filter(vec![ - Directive { - name: Some("crate2".to_string()), - level: LevelFilter::Info, - }, - Directive { - name: Some("crate2::mod".to_string()), - level: LevelFilter::Debug, - }, - Directive { - name: Some("crate1::mod1".to_string()), - level: LevelFilter::Warn, - }, - ]); - assert!(enabled(&logger.directives, Level::Debug, "crate2::mod1")); - assert!(!enabled(&logger.directives, Level::Debug, "crate2")); - } - - #[test] - fn match_default() { - let logger = make_logger_filter(vec![ - Directive { - name: None, - level: LevelFilter::Info, - }, - Directive { - name: Some("crate1::mod1".to_string()), - level: LevelFilter::Warn, - }, - ]); - assert!(enabled(&logger.directives, Level::Warn, "crate1::mod1")); - assert!(enabled(&logger.directives, Level::Info, "crate2::mod2")); - } - - #[test] - fn zero_level() { - let logger = make_logger_filter(vec![ - Directive { - name: None, - level: LevelFilter::Info, - }, - Directive { - name: Some("crate1::mod1".to_string()), - level: LevelFilter::Off, - }, - ]); - assert!(!enabled(&logger.directives, Level::Error, "crate1::mod1")); - assert!(enabled(&logger.directives, Level::Info, "crate2::mod2")); - } - - #[test] - fn parse_spec_valid() { - let (dirs, filter) = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug"); - assert_eq!(dirs.len(), 3); - assert_eq!(dirs[0].name, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::Error); - - assert_eq!(dirs[1].name, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::max()); - - assert_eq!(dirs[2].name, Some("crate2".to_string())); - assert_eq!(dirs[2].level, LevelFilter::Debug); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_invalid_crate() { - // test parse_spec with multiple = in specification - let (dirs, filter) = parse_spec("crate1::mod1=warn=info,crate2=debug"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::Debug); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_invalid_level() { - // test parse_spec with 'noNumber' as log level - let (dirs, filter) = parse_spec("crate1::mod1=noNumber,crate2=debug"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::Debug); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_string_level() { - // test parse_spec with 'warn' as log level - let (dirs, filter) = parse_spec("crate1::mod1=wrong,crate2=warn"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::Warn); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_empty_level() { - // test parse_spec with '' as log level - let (dirs, filter) = parse_spec("crate1::mod1=wrong,crate2="); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::max()); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_empty_level_isolated() { - // test parse_spec with "" as log level (and the entire spec str) - let (dirs, filter) = parse_spec(""); // should be ignored - assert_eq!(dirs.len(), 0); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_blank_level_isolated() { - // test parse_spec with a white-space-only string specified as the log - // level (and the entire spec str) - let (dirs, filter) = parse_spec(" "); // should be ignored - assert_eq!(dirs.len(), 0); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_blank_level_isolated_comma_only() { - // The spec should contain zero or more comma-separated string slices, - // so a comma-only string should be interpretted as two empty strings - // (which should both be treated as invalid, so ignored). - let (dirs, filter) = parse_spec(","); // should be ignored - assert_eq!(dirs.len(), 0); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_blank_level_isolated_comma_blank() { - // The spec should contain zero or more comma-separated string slices, - // so this bogus spec should be interpretted as containing one empty - // string and one blank string. Both should both be treated as - // invalid, so ignored. - let (dirs, filter) = parse_spec(", "); // should be ignored - assert_eq!(dirs.len(), 0); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_blank_level_isolated_blank_comma() { - // The spec should contain zero or more comma-separated string slices, - // so this bogus spec should be interpretted as containing one blank - // string and one empty string. Both should both be treated as - // invalid, so ignored. - let (dirs, filter) = parse_spec(" ,"); // should be ignored - assert_eq!(dirs.len(), 0); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_global() { - // test parse_spec with no crate - let (dirs, filter) = parse_spec("warn,crate2=debug"); - assert_eq!(dirs.len(), 2); - assert_eq!(dirs[0].name, None); - assert_eq!(dirs[0].level, LevelFilter::Warn); - assert_eq!(dirs[1].name, Some("crate2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::Debug); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_global_bare_warn_lc() { - // test parse_spec with no crate, in isolation, all lowercase - let (dirs, filter) = parse_spec("warn"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, None); - assert_eq!(dirs[0].level, LevelFilter::Warn); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_global_bare_warn_uc() { - // test parse_spec with no crate, in isolation, all uppercase - let (dirs, filter) = parse_spec("WARN"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, None); - assert_eq!(dirs[0].level, LevelFilter::Warn); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_global_bare_warn_mixed() { - // test parse_spec with no crate, in isolation, mixed case - let (dirs, filter) = parse_spec("wArN"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, None); - assert_eq!(dirs[0].level, LevelFilter::Warn); - assert!(filter.is_none()); - } - - #[test] - fn parse_spec_valid_filter() { - let (dirs, filter) = parse_spec("crate1::mod1=error,crate1::mod2,crate2=debug/abc"); - assert_eq!(dirs.len(), 3); - assert_eq!(dirs[0].name, Some("crate1::mod1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::Error); - - assert_eq!(dirs[1].name, Some("crate1::mod2".to_string())); - assert_eq!(dirs[1].level, LevelFilter::max()); - - assert_eq!(dirs[2].name, Some("crate2".to_string())); - assert_eq!(dirs[2].level, LevelFilter::Debug); - assert!(filter.is_some() && filter.unwrap().to_string() == "abc"); - } - - #[test] - fn parse_spec_invalid_crate_filter() { - let (dirs, filter) = parse_spec("crate1::mod1=error=warn,crate2=debug/a.c"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate2".to_string())); - assert_eq!(dirs[0].level, LevelFilter::Debug); - assert!(filter.is_some() && filter.unwrap().to_string() == "a.c"); - } - - #[test] - fn parse_spec_empty_with_filter() { - let (dirs, filter) = parse_spec("crate1/a*c"); - assert_eq!(dirs.len(), 1); - assert_eq!(dirs[0].name, Some("crate1".to_string())); - assert_eq!(dirs[0].level, LevelFilter::max()); - assert!(filter.is_some() && filter.unwrap().to_string() == "a*c"); - } -} diff --git a/vendor/env_logger/src/filter/regex.rs b/vendor/env_logger/src/filter/regex.rs deleted file mode 100644 index fb21528a1..000000000 --- a/vendor/env_logger/src/filter/regex.rs +++ /dev/null @@ -1,29 +0,0 @@ -extern crate regex; - -use std::fmt; - -use self::regex::Regex; - -#[derive(Debug)] -pub struct Filter { - inner: Regex, -} - -impl Filter { - pub fn new(spec: &str) -> Result { - match Regex::new(spec) { - Ok(r) => Ok(Filter { inner: r }), - Err(e) => Err(e.to_string()), - } - } - - pub fn is_match(&self, s: &str) -> bool { - self.inner.is_match(s) - } -} - -impl fmt::Display for Filter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.inner.fmt(f) - } -} diff --git a/vendor/env_logger/src/filter/string.rs b/vendor/env_logger/src/filter/string.rs deleted file mode 100644 index ea476e42f..000000000 --- a/vendor/env_logger/src/filter/string.rs +++ /dev/null @@ -1,24 +0,0 @@ -use std::fmt; - -#[derive(Debug)] -pub struct Filter { - inner: String, -} - -impl Filter { - pub fn new(spec: &str) -> Result { - Ok(Filter { - inner: spec.to_string(), - }) - } - - pub fn is_match(&self, s: &str) -> bool { - s.contains(&self.inner) - } -} - -impl fmt::Display for Filter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - self.inner.fmt(f) - } -} diff --git a/vendor/env_logger/src/fmt/humantime/extern_impl.rs b/vendor/env_logger/src/fmt/humantime/extern_impl.rs deleted file mode 100644 index 19dec1b65..000000000 --- a/vendor/env_logger/src/fmt/humantime/extern_impl.rs +++ /dev/null @@ -1,118 +0,0 @@ -use std::fmt; -use std::time::SystemTime; - -use humantime::{ - format_rfc3339_micros, format_rfc3339_millis, format_rfc3339_nanos, format_rfc3339_seconds, -}; - -use crate::fmt::{Formatter, TimestampPrecision}; - -pub(in crate::fmt) mod glob { - pub use super::*; -} - -impl Formatter { - /// Get a [`Timestamp`] for the current date and time in UTC. - /// - /// # Examples - /// - /// Include the current timestamp with the log record: - /// - /// ``` - /// use std::io::Write; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let ts = buf.timestamp(); - /// - /// writeln!(buf, "{}: {}: {}", ts, record.level(), record.args()) - /// }); - /// ``` - /// - /// [`Timestamp`]: struct.Timestamp.html - pub fn timestamp(&self) -> Timestamp { - Timestamp { - time: SystemTime::now(), - precision: TimestampPrecision::Seconds, - } - } - - /// Get a [`Timestamp`] for the current date and time in UTC with full - /// second precision. - pub fn timestamp_seconds(&self) -> Timestamp { - Timestamp { - time: SystemTime::now(), - precision: TimestampPrecision::Seconds, - } - } - - /// Get a [`Timestamp`] for the current date and time in UTC with - /// millisecond precision. - pub fn timestamp_millis(&self) -> Timestamp { - Timestamp { - time: SystemTime::now(), - precision: TimestampPrecision::Millis, - } - } - - /// Get a [`Timestamp`] for the current date and time in UTC with - /// microsecond precision. - pub fn timestamp_micros(&self) -> Timestamp { - Timestamp { - time: SystemTime::now(), - precision: TimestampPrecision::Micros, - } - } - - /// Get a [`Timestamp`] for the current date and time in UTC with - /// nanosecond precision. - pub fn timestamp_nanos(&self) -> Timestamp { - Timestamp { - time: SystemTime::now(), - precision: TimestampPrecision::Nanos, - } - } -} - -/// An [RFC3339] formatted timestamp. -/// -/// The timestamp implements [`Display`] and can be written to a [`Formatter`]. -/// -/// [RFC3339]: https://www.ietf.org/rfc/rfc3339.txt -/// [`Display`]: https://doc.rust-lang.org/stable/std/fmt/trait.Display.html -/// [`Formatter`]: struct.Formatter.html -pub struct Timestamp { - time: SystemTime, - precision: TimestampPrecision, -} - -impl fmt::Debug for Timestamp { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - /// A `Debug` wrapper for `Timestamp` that uses the `Display` implementation. - struct TimestampValue<'a>(&'a Timestamp); - - impl<'a> fmt::Debug for TimestampValue<'a> { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - fmt::Display::fmt(&self.0, f) - } - } - - f.debug_tuple("Timestamp") - .field(&TimestampValue(&self)) - .finish() - } -} - -impl fmt::Display for Timestamp { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - let formatter = match self.precision { - TimestampPrecision::Seconds => format_rfc3339_seconds, - TimestampPrecision::Millis => format_rfc3339_millis, - TimestampPrecision::Micros => format_rfc3339_micros, - TimestampPrecision::Nanos => format_rfc3339_nanos, - }; - - formatter(self.time).fmt(f) - } -} diff --git a/vendor/env_logger/src/fmt/humantime/mod.rs b/vendor/env_logger/src/fmt/humantime/mod.rs deleted file mode 100644 index ac23ae249..000000000 --- a/vendor/env_logger/src/fmt/humantime/mod.rs +++ /dev/null @@ -1,11 +0,0 @@ -/* -This internal module contains the timestamp implementation. - -Its public API is available when the `humantime` crate is available. -*/ - -#[cfg_attr(feature = "humantime", path = "extern_impl.rs")] -#[cfg_attr(not(feature = "humantime"), path = "shim_impl.rs")] -mod imp; - -pub(in crate::fmt) use self::imp::*; diff --git a/vendor/env_logger/src/fmt/humantime/shim_impl.rs b/vendor/env_logger/src/fmt/humantime/shim_impl.rs deleted file mode 100644 index 906bf9e4c..000000000 --- a/vendor/env_logger/src/fmt/humantime/shim_impl.rs +++ /dev/null @@ -1,5 +0,0 @@ -/* -Timestamps aren't available when we don't have a `humantime` dependency. -*/ - -pub(in crate::fmt) mod glob {} diff --git a/vendor/env_logger/src/fmt/mod.rs b/vendor/env_logger/src/fmt/mod.rs deleted file mode 100644 index 21e09577a..000000000 --- a/vendor/env_logger/src/fmt/mod.rs +++ /dev/null @@ -1,652 +0,0 @@ -//! Formatting for log records. -//! -//! This module contains a [`Formatter`] that can be used to format log records -//! into without needing temporary allocations. Usually you won't need to worry -//! about the contents of this module and can use the `Formatter` like an ordinary -//! [`Write`]. -//! -//! # Formatting log records -//! -//! The format used to print log records can be customised using the [`Builder::format`] -//! method. -//! Custom formats can apply different color and weight to printed values using -//! [`Style`] builders. -//! -//! ``` -//! use std::io::Write; -//! -//! let mut builder = env_logger::Builder::new(); -//! -//! builder.format(|buf, record| { -//! writeln!(buf, "{}: {}", -//! record.level(), -//! record.args()) -//! }); -//! ``` -//! -//! [`Formatter`]: struct.Formatter.html -//! [`Style`]: struct.Style.html -//! [`Builder::format`]: ../struct.Builder.html#method.format -//! [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html - -use std::cell::RefCell; -use std::fmt::Display; -use std::io::prelude::*; -use std::rc::Rc; -use std::{fmt, io, mem}; - -use log::Record; - -mod humantime; -pub(crate) mod writer; - -pub use self::humantime::glob::*; -pub use self::writer::glob::*; - -use self::writer::{Buffer, Writer}; - -pub(crate) mod glob { - pub use super::{Target, TimestampPrecision, WriteStyle}; -} - -/// Formatting precision of timestamps. -/// -/// Seconds give precision of full seconds, milliseconds give thousands of a -/// second (3 decimal digits), microseconds are millionth of a second (6 decimal -/// digits) and nanoseconds are billionth of a second (9 decimal digits). -#[derive(Copy, Clone, Debug)] -pub enum TimestampPrecision { - /// Full second precision (0 decimal digits) - Seconds, - /// Millisecond precision (3 decimal digits) - Millis, - /// Microsecond precision (6 decimal digits) - Micros, - /// Nanosecond precision (9 decimal digits) - Nanos, -} - -/// The default timestamp precision is seconds. -impl Default for TimestampPrecision { - fn default() -> Self { - TimestampPrecision::Seconds - } -} - -/// A formatter to write logs into. -/// -/// `Formatter` implements the standard [`Write`] trait for writing log records. -/// It also supports terminal colors, through the [`style`] method. -/// -/// # Examples -/// -/// Use the [`writeln`] macro to format a log record. -/// An instance of a `Formatter` is passed to an `env_logger` format as `buf`: -/// -/// ``` -/// use std::io::Write; -/// -/// let mut builder = env_logger::Builder::new(); -/// -/// builder.format(|buf, record| writeln!(buf, "{}: {}", record.level(), record.args())); -/// ``` -/// -/// [`Write`]: https://doc.rust-lang.org/stable/std/io/trait.Write.html -/// [`writeln`]: https://doc.rust-lang.org/stable/std/macro.writeln.html -/// [`style`]: #method.style -pub struct Formatter { - buf: Rc>, - write_style: WriteStyle, -} - -impl Formatter { - pub(crate) fn new(writer: &Writer) -> Self { - Formatter { - buf: Rc::new(RefCell::new(writer.buffer())), - write_style: writer.write_style(), - } - } - - pub(crate) fn write_style(&self) -> WriteStyle { - self.write_style - } - - pub(crate) fn print(&self, writer: &Writer) -> io::Result<()> { - writer.print(&self.buf.borrow()) - } - - pub(crate) fn clear(&mut self) { - self.buf.borrow_mut().clear() - } -} - -impl Write for Formatter { - fn write(&mut self, buf: &[u8]) -> io::Result { - self.buf.borrow_mut().write(buf) - } - - fn flush(&mut self) -> io::Result<()> { - self.buf.borrow_mut().flush() - } -} - -impl fmt::Debug for Formatter { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Formatter").finish() - } -} - -pub(crate) type FormatFn = Box io::Result<()> + Sync + Send>; - -pub(crate) struct Builder { - pub format_timestamp: Option, - pub format_module_path: bool, - pub format_target: bool, - pub format_level: bool, - pub format_indent: Option, - pub custom_format: Option, - pub format_suffix: &'static str, - built: bool, -} - -impl Default for Builder { - fn default() -> Self { - Builder { - format_timestamp: Some(Default::default()), - format_module_path: false, - format_target: true, - format_level: true, - format_indent: Some(4), - custom_format: None, - format_suffix: "\n", - built: false, - } - } -} - -impl Builder { - /// Convert the format into a callable function. - /// - /// If the `custom_format` is `Some`, then any `default_format` switches are ignored. - /// If the `custom_format` is `None`, then a default format is returned. - /// Any `default_format` switches set to `false` won't be written by the format. - pub fn build(&mut self) -> FormatFn { - assert!(!self.built, "attempt to re-use consumed builder"); - - let built = mem::replace( - self, - Builder { - built: true, - ..Default::default() - }, - ); - - if let Some(fmt) = built.custom_format { - fmt - } else { - Box::new(move |buf, record| { - let fmt = DefaultFormat { - timestamp: built.format_timestamp, - module_path: built.format_module_path, - target: built.format_target, - level: built.format_level, - written_header_value: false, - indent: built.format_indent, - suffix: built.format_suffix, - buf, - }; - - fmt.write(record) - }) - } - } -} - -#[cfg(feature = "termcolor")] -type SubtleStyle = StyledValue<'static, &'static str>; -#[cfg(not(feature = "termcolor"))] -type SubtleStyle = &'static str; - -/// The default format. -/// -/// This format needs to work with any combination of crate features. -struct DefaultFormat<'a> { - timestamp: Option, - module_path: bool, - target: bool, - level: bool, - written_header_value: bool, - indent: Option, - buf: &'a mut Formatter, - suffix: &'a str, -} - -impl<'a> DefaultFormat<'a> { - fn write(mut self, record: &Record) -> io::Result<()> { - self.write_timestamp()?; - self.write_level(record)?; - self.write_module_path(record)?; - self.write_target(record)?; - self.finish_header()?; - - self.write_args(record) - } - - fn subtle_style(&self, text: &'static str) -> SubtleStyle { - #[cfg(feature = "termcolor")] - { - self.buf - .style() - .set_color(Color::Black) - .set_intense(true) - .clone() - .into_value(text) - } - #[cfg(not(feature = "termcolor"))] - { - text - } - } - - fn write_header_value(&mut self, value: T) -> io::Result<()> - where - T: Display, - { - if !self.written_header_value { - self.written_header_value = true; - - let open_brace = self.subtle_style("["); - write!(self.buf, "{}{}", open_brace, value) - } else { - write!(self.buf, " {}", value) - } - } - - fn write_level(&mut self, record: &Record) -> io::Result<()> { - if !self.level { - return Ok(()); - } - - let level = { - #[cfg(feature = "termcolor")] - { - self.buf.default_styled_level(record.level()) - } - #[cfg(not(feature = "termcolor"))] - { - record.level() - } - }; - - self.write_header_value(format_args!("{:<5}", level)) - } - - fn write_timestamp(&mut self) -> io::Result<()> { - #[cfg(feature = "humantime")] - { - use self::TimestampPrecision::*; - let ts = match self.timestamp { - None => return Ok(()), - Some(Seconds) => self.buf.timestamp_seconds(), - Some(Millis) => self.buf.timestamp_millis(), - Some(Micros) => self.buf.timestamp_micros(), - Some(Nanos) => self.buf.timestamp_nanos(), - }; - - self.write_header_value(ts) - } - #[cfg(not(feature = "humantime"))] - { - // Trick the compiler to think we have used self.timestamp - // Workaround for "field is never used: `timestamp`" compiler nag. - let _ = self.timestamp; - Ok(()) - } - } - - fn write_module_path(&mut self, record: &Record) -> io::Result<()> { - if !self.module_path { - return Ok(()); - } - - if let Some(module_path) = record.module_path() { - self.write_header_value(module_path) - } else { - Ok(()) - } - } - - fn write_target(&mut self, record: &Record) -> io::Result<()> { - if !self.target { - return Ok(()); - } - - match record.target() { - "" => Ok(()), - target => self.write_header_value(target), - } - } - - fn finish_header(&mut self) -> io::Result<()> { - if self.written_header_value { - let close_brace = self.subtle_style("]"); - write!(self.buf, "{} ", close_brace) - } else { - Ok(()) - } - } - - fn write_args(&mut self, record: &Record) -> io::Result<()> { - match self.indent { - // Fast path for no indentation - None => write!(self.buf, "{}{}", record.args(), self.suffix), - - Some(indent_count) => { - // Create a wrapper around the buffer only if we have to actually indent the message - - struct IndentWrapper<'a, 'b: 'a> { - fmt: &'a mut DefaultFormat<'b>, - indent_count: usize, - } - - impl<'a, 'b> Write for IndentWrapper<'a, 'b> { - fn write(&mut self, buf: &[u8]) -> io::Result { - let mut first = true; - for chunk in buf.split(|&x| x == b'\n') { - if !first { - write!( - self.fmt.buf, - "{}{:width$}", - self.fmt.suffix, - "", - width = self.indent_count - )?; - } - self.fmt.buf.write_all(chunk)?; - first = false; - } - - Ok(buf.len()) - } - - fn flush(&mut self) -> io::Result<()> { - self.fmt.buf.flush() - } - } - - // The explicit scope here is just to make older versions of Rust happy - { - let mut wrapper = IndentWrapper { - fmt: self, - indent_count, - }; - write!(wrapper, "{}", record.args())?; - } - - write!(self.buf, "{}", self.suffix)?; - - Ok(()) - } - } - } -} - -#[cfg(test)] -mod tests { - use super::*; - - use log::{Level, Record}; - - fn write_record(record: Record, fmt: DefaultFormat) -> String { - let buf = fmt.buf.buf.clone(); - - fmt.write(&record).expect("failed to write record"); - - let buf = buf.borrow(); - String::from_utf8(buf.bytes().to_vec()).expect("failed to read record") - } - - fn write_target<'a>(target: &'a str, fmt: DefaultFormat) -> String { - write_record( - Record::builder() - .args(format_args!("log\nmessage")) - .level(Level::Info) - .file(Some("test.rs")) - .line(Some(144)) - .module_path(Some("test::path")) - .target(target) - .build(), - fmt, - ) - } - - fn write(fmt: DefaultFormat) -> String { - write_target("", fmt) - } - - #[test] - fn format_with_header() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: true, - target: false, - level: true, - written_header_value: false, - indent: None, - suffix: "\n", - buf: &mut f, - }); - - assert_eq!("[INFO test::path] log\nmessage\n", written); - } - - #[test] - fn format_no_header() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: false, - target: false, - level: false, - written_header_value: false, - indent: None, - suffix: "\n", - buf: &mut f, - }); - - assert_eq!("log\nmessage\n", written); - } - - #[test] - fn format_indent_spaces() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: true, - target: false, - level: true, - written_header_value: false, - indent: Some(4), - suffix: "\n", - buf: &mut f, - }); - - assert_eq!("[INFO test::path] log\n message\n", written); - } - - #[test] - fn format_indent_zero_spaces() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: true, - target: false, - level: true, - written_header_value: false, - indent: Some(0), - suffix: "\n", - buf: &mut f, - }); - - assert_eq!("[INFO test::path] log\nmessage\n", written); - } - - #[test] - fn format_indent_spaces_no_header() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: false, - target: false, - level: false, - written_header_value: false, - indent: Some(4), - suffix: "\n", - buf: &mut f, - }); - - assert_eq!("log\n message\n", written); - } - - #[test] - fn format_suffix() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: false, - target: false, - level: false, - written_header_value: false, - indent: None, - suffix: "\n\n", - buf: &mut f, - }); - - assert_eq!("log\nmessage\n\n", written); - } - - #[test] - fn format_suffix_with_indent() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: false, - target: false, - level: false, - written_header_value: false, - indent: Some(4), - suffix: "\n\n", - buf: &mut f, - }); - - assert_eq!("log\n\n message\n\n", written); - } - - #[test] - fn format_target() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write_target( - "target", - DefaultFormat { - timestamp: None, - module_path: true, - target: true, - level: true, - written_header_value: false, - indent: None, - suffix: "\n", - buf: &mut f, - }, - ); - - assert_eq!("[INFO test::path target] log\nmessage\n", written); - } - - #[test] - fn format_empty_target() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write(DefaultFormat { - timestamp: None, - module_path: true, - target: true, - level: true, - written_header_value: false, - indent: None, - suffix: "\n", - buf: &mut f, - }); - - assert_eq!("[INFO test::path] log\nmessage\n", written); - } - - #[test] - fn format_no_target() { - let writer = writer::Builder::new() - .write_style(WriteStyle::Never) - .build(); - - let mut f = Formatter::new(&writer); - - let written = write_target( - "target", - DefaultFormat { - timestamp: None, - module_path: true, - target: false, - level: true, - written_header_value: false, - indent: None, - suffix: "\n", - buf: &mut f, - }, - ); - - assert_eq!("[INFO test::path] log\nmessage\n", written); - } -} diff --git a/vendor/env_logger/src/fmt/writer/atty.rs b/vendor/env_logger/src/fmt/writer/atty.rs deleted file mode 100644 index 343539c15..000000000 --- a/vendor/env_logger/src/fmt/writer/atty.rs +++ /dev/null @@ -1,32 +0,0 @@ -/* -This internal module contains the terminal detection implementation. - -If the `atty` crate is available then we use it to detect whether we're -attached to a particular TTY. If the `atty` crate is not available we -assume we're not attached to anything. This effectively prevents styles -from being printed. -*/ - -#[cfg(feature = "atty")] -mod imp { - pub(in crate::fmt) fn is_stdout() -> bool { - atty::is(atty::Stream::Stdout) - } - - pub(in crate::fmt) fn is_stderr() -> bool { - atty::is(atty::Stream::Stderr) - } -} - -#[cfg(not(feature = "atty"))] -mod imp { - pub(in crate::fmt) fn is_stdout() -> bool { - false - } - - pub(in crate::fmt) fn is_stderr() -> bool { - false - } -} - -pub(in crate::fmt) use self::imp::*; diff --git a/vendor/env_logger/src/fmt/writer/mod.rs b/vendor/env_logger/src/fmt/writer/mod.rs deleted file mode 100644 index 5bb535392..000000000 --- a/vendor/env_logger/src/fmt/writer/mod.rs +++ /dev/null @@ -1,252 +0,0 @@ -mod atty; -mod termcolor; - -use self::atty::{is_stderr, is_stdout}; -use self::termcolor::BufferWriter; -use std::{fmt, io, mem, sync::Mutex}; - -pub(super) mod glob { - pub use super::termcolor::glob::*; - pub use super::*; -} - -pub(super) use self::termcolor::Buffer; - -/// Log target, either `stdout`, `stderr` or a custom pipe. -#[non_exhaustive] -pub enum Target { - /// Logs will be sent to standard output. - Stdout, - /// Logs will be sent to standard error. - Stderr, - /// Logs will be sent to a custom pipe. - Pipe(Box), -} - -impl Default for Target { - fn default() -> Self { - Target::Stderr - } -} - -impl fmt::Debug for Target { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "{}", - match self { - Self::Stdout => "stdout", - Self::Stderr => "stderr", - Self::Pipe(_) => "pipe", - } - ) - } -} - -/// Log target, either `stdout`, `stderr` or a custom pipe. -/// -/// Same as `Target`, except the pipe is wrapped in a mutex for interior mutability. -pub(super) enum WritableTarget { - /// Logs will be sent to standard output. - Stdout, - /// Logs will be sent to standard error. - Stderr, - /// Logs will be sent to a custom pipe. - Pipe(Box>), -} - -impl From for WritableTarget { - fn from(target: Target) -> Self { - match target { - Target::Stdout => Self::Stdout, - Target::Stderr => Self::Stderr, - Target::Pipe(pipe) => Self::Pipe(Box::new(Mutex::new(pipe))), - } - } -} - -impl Default for WritableTarget { - fn default() -> Self { - Self::from(Target::default()) - } -} - -impl fmt::Debug for WritableTarget { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - write!( - f, - "{}", - match self { - Self::Stdout => "stdout", - Self::Stderr => "stderr", - Self::Pipe(_) => "pipe", - } - ) - } -} -/// Whether or not to print styles to the target. -#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] -pub enum WriteStyle { - /// Try to print styles, but don't force the issue. - Auto, - /// Try very hard to print styles. - Always, - /// Never print styles. - Never, -} - -impl Default for WriteStyle { - fn default() -> Self { - WriteStyle::Auto - } -} - -/// A terminal target with color awareness. -pub(crate) struct Writer { - inner: BufferWriter, - write_style: WriteStyle, -} - -impl Writer { - pub fn write_style(&self) -> WriteStyle { - self.write_style - } - - pub(super) fn buffer(&self) -> Buffer { - self.inner.buffer() - } - - pub(super) fn print(&self, buf: &Buffer) -> io::Result<()> { - self.inner.print(buf) - } -} - -/// A builder for a terminal writer. -/// -/// The target and style choice can be configured before building. -#[derive(Debug)] -pub(crate) struct Builder { - target: WritableTarget, - write_style: WriteStyle, - is_test: bool, - built: bool, -} - -impl Builder { - /// Initialize the writer builder with defaults. - pub(crate) fn new() -> Self { - Builder { - target: Default::default(), - write_style: Default::default(), - is_test: false, - built: false, - } - } - - /// Set the target to write to. - pub(crate) fn target(&mut self, target: Target) -> &mut Self { - self.target = target.into(); - self - } - - /// Parses a style choice string. - /// - /// See the [Disabling colors] section for more details. - /// - /// [Disabling colors]: ../index.html#disabling-colors - pub(crate) fn parse_write_style(&mut self, write_style: &str) -> &mut Self { - self.write_style(parse_write_style(write_style)) - } - - /// Whether or not to print style characters when writing. - pub(crate) fn write_style(&mut self, write_style: WriteStyle) -> &mut Self { - self.write_style = write_style; - self - } - - /// Whether or not to capture logs for `cargo test`. - pub(crate) fn is_test(&mut self, is_test: bool) -> &mut Self { - self.is_test = is_test; - self - } - - /// Build a terminal writer. - pub(crate) fn build(&mut self) -> Writer { - assert!(!self.built, "attempt to re-use consumed builder"); - self.built = true; - - let color_choice = match self.write_style { - WriteStyle::Auto => { - if match &self.target { - WritableTarget::Stderr => is_stderr(), - WritableTarget::Stdout => is_stdout(), - WritableTarget::Pipe(_) => false, - } { - WriteStyle::Auto - } else { - WriteStyle::Never - } - } - color_choice => color_choice, - }; - - let writer = match mem::take(&mut self.target) { - WritableTarget::Stderr => BufferWriter::stderr(self.is_test, color_choice), - WritableTarget::Stdout => BufferWriter::stdout(self.is_test, color_choice), - WritableTarget::Pipe(pipe) => BufferWriter::pipe(self.is_test, color_choice, pipe), - }; - - Writer { - inner: writer, - write_style: self.write_style, - } - } -} - -impl Default for Builder { - fn default() -> Self { - Builder::new() - } -} - -impl fmt::Debug for Writer { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Writer").finish() - } -} - -fn parse_write_style(spec: &str) -> WriteStyle { - match spec { - "auto" => WriteStyle::Auto, - "always" => WriteStyle::Always, - "never" => WriteStyle::Never, - _ => Default::default(), - } -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn parse_write_style_valid() { - let inputs = vec![ - ("auto", WriteStyle::Auto), - ("always", WriteStyle::Always), - ("never", WriteStyle::Never), - ]; - - for (input, expected) in inputs { - assert_eq!(expected, parse_write_style(input)); - } - } - - #[test] - fn parse_write_style_invalid() { - let inputs = vec!["", "true", "false", "NEVER!!"]; - - for input in inputs { - assert_eq!(WriteStyle::Auto, parse_write_style(input)); - } - } -} diff --git a/vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs b/vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs deleted file mode 100644 index 11012fb15..000000000 --- a/vendor/env_logger/src/fmt/writer/termcolor/extern_impl.rs +++ /dev/null @@ -1,510 +0,0 @@ -use std::borrow::Cow; -use std::cell::RefCell; -use std::fmt; -use std::io::{self, Write}; -use std::rc::Rc; -use std::sync::Mutex; - -use log::Level; -use termcolor::{self, ColorChoice, ColorSpec, WriteColor}; - -use crate::fmt::{Formatter, WritableTarget, WriteStyle}; - -pub(in crate::fmt::writer) mod glob { - pub use super::*; -} - -impl Formatter { - /// Begin a new [`Style`]. - /// - /// # Examples - /// - /// Create a bold, red colored style and use it to print the log level: - /// - /// ``` - /// use std::io::Write; - /// use env_logger::fmt::Color; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let mut level_style = buf.style(); - /// - /// level_style.set_color(Color::Red).set_bold(true); - /// - /// writeln!(buf, "{}: {}", - /// level_style.value(record.level()), - /// record.args()) - /// }); - /// ``` - /// - /// [`Style`]: struct.Style.html - pub fn style(&self) -> Style { - Style { - buf: self.buf.clone(), - spec: ColorSpec::new(), - } - } - - /// Get the default [`Style`] for the given level. - /// - /// The style can be used to print other values besides the level. - pub fn default_level_style(&self, level: Level) -> Style { - let mut level_style = self.style(); - match level { - Level::Trace => level_style.set_color(Color::Cyan), - Level::Debug => level_style.set_color(Color::Blue), - Level::Info => level_style.set_color(Color::Green), - Level::Warn => level_style.set_color(Color::Yellow), - Level::Error => level_style.set_color(Color::Red).set_bold(true), - }; - level_style - } - - /// Get a printable [`Style`] for the given level. - /// - /// The style can only be used to print the level. - pub fn default_styled_level(&self, level: Level) -> StyledValue<'static, Level> { - self.default_level_style(level).into_value(level) - } -} - -pub(in crate::fmt::writer) struct BufferWriter { - inner: termcolor::BufferWriter, - test_target: Option, -} - -pub(in crate::fmt) struct Buffer { - inner: termcolor::Buffer, - has_test_target: bool, -} - -impl BufferWriter { - pub(in crate::fmt::writer) fn stderr(is_test: bool, write_style: WriteStyle) -> Self { - BufferWriter { - inner: termcolor::BufferWriter::stderr(write_style.into_color_choice()), - test_target: if is_test { - Some(WritableTarget::Stderr) - } else { - None - }, - } - } - - pub(in crate::fmt::writer) fn stdout(is_test: bool, write_style: WriteStyle) -> Self { - BufferWriter { - inner: termcolor::BufferWriter::stdout(write_style.into_color_choice()), - test_target: if is_test { - Some(WritableTarget::Stdout) - } else { - None - }, - } - } - - pub(in crate::fmt::writer) fn pipe( - is_test: bool, - write_style: WriteStyle, - pipe: Box>, - ) -> Self { - BufferWriter { - // The inner Buffer is never printed from, but it is still needed to handle coloring and other formating - inner: termcolor::BufferWriter::stderr(write_style.into_color_choice()), - test_target: if is_test { - Some(WritableTarget::Pipe(pipe)) - } else { - None - }, - } - } - - pub(in crate::fmt::writer) fn buffer(&self) -> Buffer { - Buffer { - inner: self.inner.buffer(), - has_test_target: self.test_target.is_some(), - } - } - - pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> { - if let Some(target) = &self.test_target { - // This impl uses the `eprint` and `print` macros - // instead of `termcolor`'s buffer. - // This is so their output can be captured by `cargo test` - let log = String::from_utf8_lossy(buf.bytes()); - - match target { - WritableTarget::Stderr => eprint!("{}", log), - WritableTarget::Stdout => print!("{}", log), - WritableTarget::Pipe(pipe) => write!(pipe.lock().unwrap(), "{}", log)?, - } - - Ok(()) - } else { - self.inner.print(&buf.inner) - } - } -} - -impl Buffer { - pub(in crate::fmt) fn clear(&mut self) { - self.inner.clear() - } - - pub(in crate::fmt) fn write(&mut self, buf: &[u8]) -> io::Result { - self.inner.write(buf) - } - - pub(in crate::fmt) fn flush(&mut self) -> io::Result<()> { - self.inner.flush() - } - - pub(in crate::fmt) fn bytes(&self) -> &[u8] { - self.inner.as_slice() - } - - fn set_color(&mut self, spec: &ColorSpec) -> io::Result<()> { - // Ignore styles for test captured logs because they can't be printed - if !self.has_test_target { - self.inner.set_color(spec) - } else { - Ok(()) - } - } - - fn reset(&mut self) -> io::Result<()> { - // Ignore styles for test captured logs because they can't be printed - if !self.has_test_target { - self.inner.reset() - } else { - Ok(()) - } - } -} - -impl WriteStyle { - fn into_color_choice(self) -> ColorChoice { - match self { - WriteStyle::Always => ColorChoice::Always, - WriteStyle::Auto => ColorChoice::Auto, - WriteStyle::Never => ColorChoice::Never, - } - } -} - -/// A set of styles to apply to the terminal output. -/// -/// Call [`Formatter::style`] to get a `Style` and use the builder methods to -/// set styling properties, like [color] and [weight]. -/// To print a value using the style, wrap it in a call to [`value`] when the log -/// record is formatted. -/// -/// # Examples -/// -/// Create a bold, red colored style and use it to print the log level: -/// -/// ``` -/// use std::io::Write; -/// use env_logger::fmt::Color; -/// -/// let mut builder = env_logger::Builder::new(); -/// -/// builder.format(|buf, record| { -/// let mut level_style = buf.style(); -/// -/// level_style.set_color(Color::Red).set_bold(true); -/// -/// writeln!(buf, "{}: {}", -/// level_style.value(record.level()), -/// record.args()) -/// }); -/// ``` -/// -/// Styles can be re-used to output multiple values: -/// -/// ``` -/// use std::io::Write; -/// use env_logger::fmt::Color; -/// -/// let mut builder = env_logger::Builder::new(); -/// -/// builder.format(|buf, record| { -/// let mut bold = buf.style(); -/// -/// bold.set_bold(true); -/// -/// writeln!(buf, "{}: {} {}", -/// bold.value(record.level()), -/// bold.value("some bold text"), -/// record.args()) -/// }); -/// ``` -/// -/// [`Formatter::style`]: struct.Formatter.html#method.style -/// [color]: #method.set_color -/// [weight]: #method.set_bold -/// [`value`]: #method.value -#[derive(Clone)] -pub struct Style { - buf: Rc>, - spec: ColorSpec, -} - -/// A value that can be printed using the given styles. -/// -/// It is the result of calling [`Style::value`]. -/// -/// [`Style::value`]: struct.Style.html#method.value -pub struct StyledValue<'a, T> { - style: Cow<'a, Style>, - value: T, -} - -impl Style { - /// Set the text color. - /// - /// # Examples - /// - /// Create a style with red text: - /// - /// ``` - /// use std::io::Write; - /// use env_logger::fmt::Color; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let mut style = buf.style(); - /// - /// style.set_color(Color::Red); - /// - /// writeln!(buf, "{}", style.value(record.args())) - /// }); - /// ``` - pub fn set_color(&mut self, color: Color) -> &mut Style { - self.spec.set_fg(Some(color.into_termcolor())); - self - } - - /// Set the text weight. - /// - /// If `yes` is true then text will be written in bold. - /// If `yes` is false then text will be written in the default weight. - /// - /// # Examples - /// - /// Create a style with bold text: - /// - /// ``` - /// use std::io::Write; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let mut style = buf.style(); - /// - /// style.set_bold(true); - /// - /// writeln!(buf, "{}", style.value(record.args())) - /// }); - /// ``` - pub fn set_bold(&mut self, yes: bool) -> &mut Style { - self.spec.set_bold(yes); - self - } - - /// Set the text intensity. - /// - /// If `yes` is true then text will be written in a brighter color. - /// If `yes` is false then text will be written in the default color. - /// - /// # Examples - /// - /// Create a style with intense text: - /// - /// ``` - /// use std::io::Write; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let mut style = buf.style(); - /// - /// style.set_intense(true); - /// - /// writeln!(buf, "{}", style.value(record.args())) - /// }); - /// ``` - pub fn set_intense(&mut self, yes: bool) -> &mut Style { - self.spec.set_intense(yes); - self - } - - /// Set the background color. - /// - /// # Examples - /// - /// Create a style with a yellow background: - /// - /// ``` - /// use std::io::Write; - /// use env_logger::fmt::Color; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let mut style = buf.style(); - /// - /// style.set_bg(Color::Yellow); - /// - /// writeln!(buf, "{}", style.value(record.args())) - /// }); - /// ``` - pub fn set_bg(&mut self, color: Color) -> &mut Style { - self.spec.set_bg(Some(color.into_termcolor())); - self - } - - /// Wrap a value in the style. - /// - /// The same `Style` can be used to print multiple different values. - /// - /// # Examples - /// - /// Create a bold, red colored style and use it to print the log level: - /// - /// ``` - /// use std::io::Write; - /// use env_logger::fmt::Color; - /// - /// let mut builder = env_logger::Builder::new(); - /// - /// builder.format(|buf, record| { - /// let mut style = buf.style(); - /// - /// style.set_color(Color::Red).set_bold(true); - /// - /// writeln!(buf, "{}: {}", - /// style.value(record.level()), - /// record.args()) - /// }); - /// ``` - pub fn value(&self, value: T) -> StyledValue { - StyledValue { - style: Cow::Borrowed(self), - value, - } - } - - /// Wrap a value in the style by taking ownership of it. - pub(crate) fn into_value(self, value: T) -> StyledValue<'static, T> { - StyledValue { - style: Cow::Owned(self), - value, - } - } -} - -impl<'a, T> StyledValue<'a, T> { - fn write_fmt(&self, f: F) -> fmt::Result - where - F: FnOnce() -> fmt::Result, - { - self.style - .buf - .borrow_mut() - .set_color(&self.style.spec) - .map_err(|_| fmt::Error)?; - - // Always try to reset the terminal style, even if writing failed - let write = f(); - let reset = self.style.buf.borrow_mut().reset().map_err(|_| fmt::Error); - - write.and(reset) - } -} - -impl fmt::Debug for Style { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Style").field("spec", &self.spec).finish() - } -} - -macro_rules! impl_styled_value_fmt { - ($($fmt_trait:path),*) => { - $( - impl<'a, T: $fmt_trait> $fmt_trait for StyledValue<'a, T> { - fn fmt(&self, f: &mut fmt::Formatter)->fmt::Result { - self.write_fmt(|| T::fmt(&self.value, f)) - } - } - )* - }; -} - -impl_styled_value_fmt!( - fmt::Debug, - fmt::Display, - fmt::Pointer, - fmt::Octal, - fmt::Binary, - fmt::UpperHex, - fmt::LowerHex, - fmt::UpperExp, - fmt::LowerExp -); - -// The `Color` type is copied from https://github.com/BurntSushi/ripgrep/tree/master/termcolor - -/// The set of available colors for the terminal foreground/background. -/// -/// The `Ansi256` and `Rgb` colors will only output the correct codes when -/// paired with the `Ansi` `WriteColor` implementation. -/// -/// The `Ansi256` and `Rgb` color types are not supported when writing colors -/// on Windows using the console. If they are used on Windows, then they are -/// silently ignored and no colors will be emitted. -/// -/// This set may expand over time. -/// -/// This type has a `FromStr` impl that can parse colors from their human -/// readable form. The format is as follows: -/// -/// 1. Any of the explicitly listed colors in English. They are matched -/// case insensitively. -/// 2. A single 8-bit integer, in either decimal or hexadecimal format. -/// 3. A triple of 8-bit integers separated by a comma, where each integer is -/// in decimal or hexadecimal format. -/// -/// Hexadecimal numbers are written with a `0x` prefix. -#[allow(missing_docs)] -#[non_exhaustive] -#[derive(Clone, Debug, Eq, PartialEq)] -pub enum Color { - Black, - Blue, - Green, - Red, - Cyan, - Magenta, - Yellow, - White, - Ansi256(u8), - Rgb(u8, u8, u8), -} - -impl Color { - fn into_termcolor(self) -> termcolor::Color { - match self { - Color::Black => termcolor::Color::Black, - Color::Blue => termcolor::Color::Blue, - Color::Green => termcolor::Color::Green, - Color::Red => termcolor::Color::Red, - Color::Cyan => termcolor::Color::Cyan, - Color::Magenta => termcolor::Color::Magenta, - Color::Yellow => termcolor::Color::Yellow, - Color::White => termcolor::Color::White, - Color::Ansi256(value) => termcolor::Color::Ansi256(value), - Color::Rgb(r, g, b) => termcolor::Color::Rgb(r, g, b), - } - } -} diff --git a/vendor/env_logger/src/fmt/writer/termcolor/mod.rs b/vendor/env_logger/src/fmt/writer/termcolor/mod.rs deleted file mode 100644 index f3e6768cd..000000000 --- a/vendor/env_logger/src/fmt/writer/termcolor/mod.rs +++ /dev/null @@ -1,12 +0,0 @@ -/* -This internal module contains the style and terminal writing implementation. - -Its public API is available when the `termcolor` crate is available. -The terminal printing is shimmed when the `termcolor` crate is not available. -*/ - -#[cfg_attr(feature = "termcolor", path = "extern_impl.rs")] -#[cfg_attr(not(feature = "termcolor"), path = "shim_impl.rs")] -mod imp; - -pub(in crate::fmt) use self::imp::*; diff --git a/vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs b/vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs deleted file mode 100644 index bfc31d087..000000000 --- a/vendor/env_logger/src/fmt/writer/termcolor/shim_impl.rs +++ /dev/null @@ -1,73 +0,0 @@ -use std::{io, sync::Mutex}; - -use crate::fmt::{WritableTarget, WriteStyle}; - -pub(in crate::fmt::writer) mod glob {} - -pub(in crate::fmt::writer) struct BufferWriter { - target: WritableTarget, -} - -pub(in crate::fmt) struct Buffer(Vec); - -impl BufferWriter { - pub(in crate::fmt::writer) fn stderr(_is_test: bool, _write_style: WriteStyle) -> Self { - BufferWriter { - target: WritableTarget::Stderr, - } - } - - pub(in crate::fmt::writer) fn stdout(_is_test: bool, _write_style: WriteStyle) -> Self { - BufferWriter { - target: WritableTarget::Stdout, - } - } - - pub(in crate::fmt::writer) fn pipe( - _is_test: bool, - _write_style: WriteStyle, - pipe: Box>, - ) -> Self { - BufferWriter { - target: WritableTarget::Pipe(pipe), - } - } - - pub(in crate::fmt::writer) fn buffer(&self) -> Buffer { - Buffer(Vec::new()) - } - - pub(in crate::fmt::writer) fn print(&self, buf: &Buffer) -> io::Result<()> { - // This impl uses the `eprint` and `print` macros - // instead of using the streams directly. - // This is so their output can be captured by `cargo test`. - match &self.target { - // Safety: If the target type is `Pipe`, `target_pipe` will always be non-empty. - WritableTarget::Pipe(pipe) => pipe.lock().unwrap().write_all(&buf.0)?, - WritableTarget::Stdout => print!("{}", String::from_utf8_lossy(&buf.0)), - WritableTarget::Stderr => eprint!("{}", String::from_utf8_lossy(&buf.0)), - } - - Ok(()) - } -} - -impl Buffer { - pub(in crate::fmt) fn clear(&mut self) { - self.0.clear(); - } - - pub(in crate::fmt) fn write(&mut self, buf: &[u8]) -> io::Result { - self.0.extend(buf); - Ok(buf.len()) - } - - pub(in crate::fmt) fn flush(&mut self) -> io::Result<()> { - Ok(()) - } - - #[cfg(test)] - pub(in crate::fmt) fn bytes(&self) -> &[u8] { - &self.0 - } -} diff --git a/vendor/env_logger/src/lib.rs b/vendor/env_logger/src/lib.rs deleted file mode 100644 index 850410858..000000000 --- a/vendor/env_logger/src/lib.rs +++ /dev/null @@ -1,1315 +0,0 @@ -// Copyright 2014-2015 The Rust Project Developers. See the COPYRIGHT -// file at the top-level directory of this distribution and at -// http://rust-lang.org/COPYRIGHT. -// -// Licensed under the Apache License, Version 2.0 or the MIT license -// , at your -// option. This file may not be copied, modified, or distributed -// except according to those terms. - -//! A simple logger that can be configured via environment variables, for use -//! with the logging facade exposed by the [`log` crate][log-crate-url]. -//! -//! Despite having "env" in its name, **`env_logger`** can also be configured by -//! other means besides environment variables. See [the examples][gh-repo-examples] -//! in the source repository for more approaches. -//! -//! By default, `env_logger` writes logs to `stderr`, but can be configured to -//! instead write them to `stdout`. -//! -//! ## Example -//! -//! ``` -//! use log::{debug, error, log_enabled, info, Level}; -//! -//! env_logger::init(); -//! -//! debug!("this is a debug {}", "message"); -//! error!("this is printed by default"); -//! -//! if log_enabled!(Level::Info) { -//! let x = 3 * 4; // expensive computation -//! info!("the answer was: {}", x); -//! } -//! ``` -//! -//! Assumes the binary is `main`: -//! -//! ```{.bash} -//! $ RUST_LOG=error ./main -//! [2017-11-09T02:12:24Z ERROR main] this is printed by default -//! ``` -//! -//! ```{.bash} -//! $ RUST_LOG=info ./main -//! [2017-11-09T02:12:24Z ERROR main] this is printed by default -//! [2017-11-09T02:12:24Z INFO main] the answer was: 12 -//! ``` -//! -//! ```{.bash} -//! $ RUST_LOG=debug ./main -//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message -//! [2017-11-09T02:12:24Z ERROR main] this is printed by default -//! [2017-11-09T02:12:24Z INFO main] the answer was: 12 -//! ``` -//! -//! You can also set the log level on a per module basis: -//! -//! ```{.bash} -//! $ RUST_LOG=main=info ./main -//! [2017-11-09T02:12:24Z ERROR main] this is printed by default -//! [2017-11-09T02:12:24Z INFO main] the answer was: 12 -//! ``` -//! -//! And enable all logging: -//! -//! ```{.bash} -//! $ RUST_LOG=main ./main -//! [2017-11-09T02:12:24Z DEBUG main] this is a debug message -//! [2017-11-09T02:12:24Z ERROR main] this is printed by default -//! [2017-11-09T02:12:24Z INFO main] the answer was: 12 -//! ``` -//! -//! If the binary name contains hyphens, you will need to replace -//! them with underscores: -//! -//! ```{.bash} -//! $ RUST_LOG=my_app ./my-app -//! [2017-11-09T02:12:24Z DEBUG my_app] this is a debug message -//! [2017-11-09T02:12:24Z ERROR my_app] this is printed by default -//! [2017-11-09T02:12:24Z INFO my_app] the answer was: 12 -//! ``` -//! -//! This is because Rust modules and crates cannot contain hyphens -//! in their name, although `cargo` continues to accept them. -//! -//! See the documentation for the [`log` crate][log-crate-url] for more -//! information about its API. -//! -//! ## Enabling logging -//! -//! Log levels are controlled on a per-module basis, and **by default all -//! logging is disabled except for the `error` level**. -//! -//! Logging is controlled via the **`RUST_LOG`** environment variable. The -//! value of this environment variable is a comma-separated list of *logging -//! directives*. A logging directive is of the form: -//! -//! ```text -//! example::log::target=level -//! ``` -//! -//! The log target is typically equal to the path of the module the message -//! in question originated from, though it can be overriden. -//! -//! The path is rooted in the name of the crate it was compiled for, so if -//! your program is in a file called, for example, `hello.rs`, the path would -//! simply be be `hello`. -//! -//! Furthermore, the the log can be filtered using prefix-search based on the -//! specified log target. A value of, for example, `RUST_LOG=example`, would -//! match all of the messages with targets: -//! -//! * `example` -//! * `example::test` -//! * `example::test::module::submodule` -//! * `examples::and_more_examples` -//! -//! When providing the crate name or a module path, explicitly specifying the -//! log level is optional. If omitted, all logging for the item will be -//! enabled. -//! -//! The names of the log levels that may be specified correspond to the -//! variations of the [`log::Level`][level-enum] enum from the `log` -//! crate. They are: -//! -//! * `error` -//! * `warn` -//! * `info` -//! * `debug` -//! * `trace` -//! -//! There is also a pseudo logging level, `off`, which may be specified to -//! disable all logging for a given module or for the entire application. As -//! with the logging levels, the letter case is not significant[^fn-off]. -//! -//! [^fn-off]: Similar to the universe of log level names, the `off` pseudo -//! log level feature is also provided by the underlying `log` crate. -//! -//! The letter case is not significant for the logging level names; e.g., -//! `debug`, `DEBUG`, and `dEbuG` all represent the same logging level. For -//! consistency, our convention is to use the lower case names. Where our docs -//! do use other forms, they do so in the context of specific examples, so you -//! won't be surprised if you see similar usage in the wild. -//! -//! As the log level for a module is optional, the module to enable logging for -//! is also optional. **If only a level is provided, then the global log -//! level for all modules is set to this value.** -//! -//! Some examples of valid values of `RUST_LOG` are: -//! -//! * `hello` turns on all logging for the 'hello' module -//! * `trace` turns on all logging for the application, regardless of its name -//! * `TRACE` turns on all logging for the application, regardless of its name (same as previous) -//! * `info` turns on all info logging -//! * `INFO` turns on all info logging (same as previous) -//! * `hello=debug` turns on debug logging for 'hello' -//! * `hello=DEBUG` turns on debug logging for 'hello' (same as previous) -//! * `hello,std::option` turns on hello, and std's option logging -//! * `error,hello=warn` turn on global error logging and also warn for hello -//! * `error,hello=off` turn on global error logging, but turn off logging for hello -//! * `off` turns off all logging for the application -//! * `OFF` turns off all logging for the application (same as previous) -//! -//! ## Filtering results -//! -//! A `RUST_LOG` directive may include a regex filter. The syntax is to append `/` -//! followed by a regex. Each message is checked against the regex, and is only -//! logged if it matches. Note that the matching is done after formatting the -//! log string but before adding any logging meta-data. There is a single filter -//! for all modules. -//! -//! Some examples: -//! -//! * `hello/foo` turns on all logging for the 'hello' module where the log -//! message includes 'foo'. -//! * `info/f.o` turns on all info logging where the log message includes 'foo', -//! 'f1o', 'fao', etc. -//! * `hello=debug/foo*foo` turns on debug logging for 'hello' where the log -//! message includes 'foofoo' or 'fofoo' or 'fooooooofoo', etc. -//! * `error,hello=warn/[0-9]scopes` turn on global error logging and also -//! warn for hello. In both cases the log message must include a single digit -//! number followed by 'scopes'. -//! -//! ## Capturing logs in tests -//! -//! Records logged during `cargo test` will not be captured by the test harness by default. -//! The [`Builder::is_test`] method can be used in unit tests to ensure logs will be captured: -//! -//! ``` -//! # #[macro_use] extern crate log; -//! #[cfg(test)] -//! mod tests { -//! fn init() { -//! let _ = env_logger::builder().is_test(true).try_init(); -//! } -//! -//! #[test] -//! fn it_works() { -//! init(); -//! -//! info!("This record will be captured by `cargo test`"); -//! -//! assert_eq!(2, 1 + 1); -//! } -//! } -//! ``` -//! -//! Enabling test capturing comes at the expense of color and other style support -//! and may have performance implications. -//! -//! ## Disabling colors -//! -//! Colors and other styles can be configured with the `RUST_LOG_STYLE` -//! environment variable. It accepts the following values: -//! -//! * `auto` (default) will attempt to print style characters, but don't force the issue. -//! If the console isn't available on Windows, or if TERM=dumb, for example, then don't print colors. -//! * `always` will always print style characters even if they aren't supported by the terminal. -//! This includes emitting ANSI colors on Windows if the console API is unavailable. -//! * `never` will never print style characters. -//! -//! ## Tweaking the default format -//! -//! Parts of the default format can be excluded from the log output using the [`Builder`]. -//! The following example excludes the timestamp from the log output: -//! -//! ``` -//! env_logger::builder() -//! .format_timestamp(None) -//! .init(); -//! ``` -//! -//! ### Stability of the default format -//! -//! The default format won't optimise for long-term stability, and explicitly makes no -//! guarantees about the stability of its output across major, minor or patch version -//! bumps during `0.x`. -//! -//! If you want to capture or interpret the output of `env_logger` programmatically -//! then you should use a custom format. -//! -//! ### Using a custom format -//! -//! Custom formats can be provided as closures to the [`Builder`]. -//! These closures take a [`Formatter`] and `log::Record` as arguments: -//! -//! ``` -//! use std::io::Write; -//! -//! env_logger::builder() -//! .format(|buf, record| { -//! writeln!(buf, "{}: {}", record.level(), record.args()) -//! }) -//! .init(); -//! ``` -//! -//! See the [`fmt`] module for more details about custom formats. -//! -//! ## Specifying defaults for environment variables -//! -//! `env_logger` can read configuration from environment variables. -//! If these variables aren't present, the default value to use can be tweaked with the [`Env`] type. -//! The following example defaults to log `warn` and above if the `RUST_LOG` environment variable -//! isn't set: -//! -//! ``` -//! use env_logger::Env; -//! -//! env_logger::Builder::from_env(Env::default().default_filter_or("warn")).init(); -//! ``` -//! -//! [gh-repo-examples]: https://github.com/env-logger-rs/env_logger/tree/main/examples -//! [level-enum]: https://docs.rs/log/latest/log/enum.Level.html -//! [log-crate-url]: https://docs.rs/log/ -//! [`Builder`]: struct.Builder.html -//! [`Builder::is_test`]: struct.Builder.html#method.is_test -//! [`Env`]: struct.Env.html -//! [`fmt`]: fmt/index.html - -#![doc( - html_logo_url = "https://www.rust-lang.org/logos/rust-logo-128x128-blk-v2.png", - html_favicon_url = "https://www.rust-lang.org/static/images/favicon.ico" -)] -// When compiled for the rustc compiler itself we want to make sure that this is -// an unstable crate -#![cfg_attr(rustbuild, feature(staged_api, rustc_private))] -#![cfg_attr(rustbuild, unstable(feature = "rustc_private", issue = "27812"))] -#![deny(missing_debug_implementations, missing_docs)] - -use std::{borrow::Cow, cell::RefCell, env, io}; - -use log::{LevelFilter, Log, Metadata, Record, SetLoggerError}; - -pub mod filter; -pub mod fmt; - -pub use self::fmt::glob::*; - -use self::filter::Filter; -use self::fmt::writer::{self, Writer}; -use self::fmt::{FormatFn, Formatter}; - -/// The default name for the environment variable to read filters from. -pub const DEFAULT_FILTER_ENV: &str = "RUST_LOG"; - -/// The default name for the environment variable to read style preferences from. -pub const DEFAULT_WRITE_STYLE_ENV: &str = "RUST_LOG_STYLE"; - -/// Set of environment variables to configure from. -/// -/// # Default environment variables -/// -/// By default, the `Env` will read the following environment variables: -/// -/// - `RUST_LOG`: the level filter -/// - `RUST_LOG_STYLE`: whether or not to print styles with records. -/// -/// These sources can be configured using the builder methods on `Env`. -#[derive(Debug)] -pub struct Env<'a> { - filter: Var<'a>, - write_style: Var<'a>, -} - -#[derive(Debug)] -struct Var<'a> { - name: Cow<'a, str>, - default: Option>, -} - -/// The env logger. -/// -/// This struct implements the `Log` trait from the [`log` crate][log-crate-url], -/// which allows it to act as a logger. -/// -/// The [`init()`], [`try_init()`], [`Builder::init()`] and [`Builder::try_init()`] -/// methods will each construct a `Logger` and immediately initialize it as the -/// default global logger. -/// -/// If you'd instead need access to the constructed `Logger`, you can use -/// the associated [`Builder`] and install it with the -/// [`log` crate][log-crate-url] directly. -/// -/// [log-crate-url]: https://docs.rs/log/ -/// [`init()`]: fn.init.html -/// [`try_init()`]: fn.try_init.html -/// [`Builder::init()`]: struct.Builder.html#method.init -/// [`Builder::try_init()`]: struct.Builder.html#method.try_init -/// [`Builder`]: struct.Builder.html -pub struct Logger { - writer: Writer, - filter: Filter, - format: FormatFn, -} - -/// `Builder` acts as builder for initializing a `Logger`. -/// -/// It can be used to customize the log format, change the environment variable used -/// to provide the logging directives and also set the default log level filter. -/// -/// # Examples -/// -/// ``` -/// # #[macro_use] extern crate log; -/// # use std::io::Write; -/// use env_logger::Builder; -/// use log::LevelFilter; -/// -/// let mut builder = Builder::from_default_env(); -/// -/// builder -/// .format(|buf, record| writeln!(buf, "{} - {}", record.level(), record.args())) -/// .filter(None, LevelFilter::Info) -/// .init(); -/// -/// error!("error message"); -/// info!("info message"); -/// ``` -#[derive(Default)] -pub struct Builder { - filter: filter::Builder, - writer: writer::Builder, - format: fmt::Builder, - built: bool, -} - -impl Builder { - /// Initializes the log builder with defaults. - /// - /// **NOTE:** This method won't read from any environment variables. - /// Use the [`filter`] and [`write_style`] methods to configure the builder - /// or use [`from_env`] or [`from_default_env`] instead. - /// - /// # Examples - /// - /// Create a new builder and configure filters and style: - /// - /// ``` - /// use log::LevelFilter; - /// use env_logger::{Builder, WriteStyle}; - /// - /// let mut builder = Builder::new(); - /// - /// builder - /// .filter(None, LevelFilter::Info) - /// .write_style(WriteStyle::Always) - /// .init(); - /// ``` - /// - /// [`filter`]: #method.filter - /// [`write_style`]: #method.write_style - /// [`from_env`]: #method.from_env - /// [`from_default_env`]: #method.from_default_env - pub fn new() -> Builder { - Default::default() - } - - /// Initializes the log builder from the environment. - /// - /// The variables used to read configuration from can be tweaked before - /// passing in. - /// - /// # Examples - /// - /// Initialise a logger reading the log filter from an environment variable - /// called `MY_LOG`: - /// - /// ``` - /// use env_logger::Builder; - /// - /// let mut builder = Builder::from_env("MY_LOG"); - /// builder.init(); - /// ``` - /// - /// Initialise a logger using the `MY_LOG` variable for filtering and - /// `MY_LOG_STYLE` for whether or not to write styles: - /// - /// ``` - /// use env_logger::{Builder, Env}; - /// - /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); - /// - /// let mut builder = Builder::from_env(env); - /// builder.init(); - /// ``` - pub fn from_env<'a, E>(env: E) -> Self - where - E: Into>, - { - let mut builder = Builder::new(); - builder.parse_env(env); - builder - } - - /// Applies the configuration from the environment. - /// - /// This function allows a builder to be configured with default parameters, - /// to be then overridden by the environment. - /// - /// # Examples - /// - /// Initialise a logger with filter level `Off`, then override the log - /// filter from an environment variable called `MY_LOG`: - /// - /// ``` - /// use log::LevelFilter; - /// use env_logger::Builder; - /// - /// let mut builder = Builder::new(); - /// - /// builder.filter_level(LevelFilter::Off); - /// builder.parse_env("MY_LOG"); - /// builder.init(); - /// ``` - /// - /// Initialise a logger with filter level `Off`, then use the `MY_LOG` - /// variable to override filtering and `MY_LOG_STYLE` to override whether - /// or not to write styles: - /// - /// ``` - /// use log::LevelFilter; - /// use env_logger::{Builder, Env}; - /// - /// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); - /// - /// let mut builder = Builder::new(); - /// builder.filter_level(LevelFilter::Off); - /// builder.parse_env(env); - /// builder.init(); - /// ``` - pub fn parse_env<'a, E>(&mut self, env: E) -> &mut Self - where - E: Into>, - { - let env = env.into(); - - if let Some(s) = env.get_filter() { - self.parse_filters(&s); - } - - if let Some(s) = env.get_write_style() { - self.parse_write_style(&s); - } - - self - } - - /// Initializes the log builder from the environment using default variable names. - /// - /// This method is a convenient way to call `from_env(Env::default())` without - /// having to use the `Env` type explicitly. The builder will use the - /// [default environment variables]. - /// - /// # Examples - /// - /// Initialise a logger using the default environment variables: - /// - /// ``` - /// use env_logger::Builder; - /// - /// let mut builder = Builder::from_default_env(); - /// builder.init(); - /// ``` - /// - /// [default environment variables]: struct.Env.html#default-environment-variables - pub fn from_default_env() -> Self { - Self::from_env(Env::default()) - } - - /// Applies the configuration from the environment using default variable names. - /// - /// This method is a convenient way to call `parse_env(Env::default())` without - /// having to use the `Env` type explicitly. The builder will use the - /// [default environment variables]. - /// - /// # Examples - /// - /// Initialise a logger with filter level `Off`, then configure it using the - /// default environment variables: - /// - /// ``` - /// use log::LevelFilter; - /// use env_logger::Builder; - /// - /// let mut builder = Builder::new(); - /// builder.filter_level(LevelFilter::Off); - /// builder.parse_default_env(); - /// builder.init(); - /// ``` - /// - /// [default environment variables]: struct.Env.html#default-environment-variables - pub fn parse_default_env(&mut self) -> &mut Self { - self.parse_env(Env::default()) - } - - /// Sets the format function for formatting the log output. - /// - /// This function is called on each record logged and should format the - /// log record and output it to the given [`Formatter`]. - /// - /// The format function is expected to output the string directly to the - /// `Formatter` so that implementations can use the [`std::fmt`] macros - /// to format and output without intermediate heap allocations. The default - /// `env_logger` formatter takes advantage of this. - /// - /// # Examples - /// - /// Use a custom format to write only the log message: - /// - /// ``` - /// use std::io::Write; - /// use env_logger::Builder; - /// - /// let mut builder = Builder::new(); - /// - /// builder.format(|buf, record| writeln!(buf, "{}", record.args())); - /// ``` - /// - /// [`Formatter`]: fmt/struct.Formatter.html - /// [`String`]: https://doc.rust-lang.org/stable/std/string/struct.String.html - /// [`std::fmt`]: https://doc.rust-lang.org/std/fmt/index.html - pub fn format(&mut self, format: F) -> &mut Self - where - F: Fn(&mut Formatter, &Record) -> io::Result<()> + Sync + Send, - { - self.format.custom_format = Some(Box::new(format)); - self - } - - /// Use the default format. - /// - /// This method will clear any custom format set on the builder. - pub fn default_format(&mut self) -> &mut Self { - self.format = Default::default(); - self - } - - /// Whether or not to write the level in the default format. - pub fn format_level(&mut self, write: bool) -> &mut Self { - self.format.format_level = write; - self - } - - /// Whether or not to write the module path in the default format. - pub fn format_module_path(&mut self, write: bool) -> &mut Self { - self.format.format_module_path = write; - self - } - - /// Whether or not to write the target in the default format. - pub fn format_target(&mut self, write: bool) -> &mut Self { - self.format.format_target = write; - self - } - - /// Configures the amount of spaces to use to indent multiline log records. - /// A value of `None` disables any kind of indentation. - pub fn format_indent(&mut self, indent: Option) -> &mut Self { - self.format.format_indent = indent; - self - } - - /// Configures if timestamp should be included and in what precision. - pub fn format_timestamp(&mut self, timestamp: Option) -> &mut Self { - self.format.format_timestamp = timestamp; - self - } - - /// Configures the timestamp to use second precision. - pub fn format_timestamp_secs(&mut self) -> &mut Self { - self.format_timestamp(Some(fmt::TimestampPrecision::Seconds)) - } - - /// Configures the timestamp to use millisecond precision. - pub fn format_timestamp_millis(&mut self) -> &mut Self { - self.format_timestamp(Some(fmt::TimestampPrecision::Millis)) - } - - /// Configures the timestamp to use microsecond precision. - pub fn format_timestamp_micros(&mut self) -> &mut Self { - self.format_timestamp(Some(fmt::TimestampPrecision::Micros)) - } - - /// Configures the timestamp to use nanosecond precision. - pub fn format_timestamp_nanos(&mut self) -> &mut Self { - self.format_timestamp(Some(fmt::TimestampPrecision::Nanos)) - } - - /// Configures the end of line suffix. - pub fn format_suffix(&mut self, suffix: &'static str) -> &mut Self { - self.format.format_suffix = suffix; - self - } - - /// Adds a directive to the filter for a specific module. - /// - /// # Examples - /// - /// Only include messages for info and above for logs in `path::to::module`: - /// - /// ``` - /// use env_logger::Builder; - /// use log::LevelFilter; - /// - /// let mut builder = Builder::new(); - /// - /// builder.filter_module("path::to::module", LevelFilter::Info); - /// ``` - pub fn filter_module(&mut self, module: &str, level: LevelFilter) -> &mut Self { - self.filter.filter_module(module, level); - self - } - - /// Adds a directive to the filter for all modules. - /// - /// # Examples - /// - /// Only include messages for info and above for logs in `path::to::module`: - /// - /// ``` - /// use env_logger::Builder; - /// use log::LevelFilter; - /// - /// let mut builder = Builder::new(); - /// - /// builder.filter_level(LevelFilter::Info); - /// ``` - pub fn filter_level(&mut self, level: LevelFilter) -> &mut Self { - self.filter.filter_level(level); - self - } - - /// Adds filters to the logger. - /// - /// The given module (if any) will log at most the specified level provided. - /// If no module is provided then the filter will apply to all log messages. - /// - /// # Examples - /// - /// Only include messages for info and above for logs in `path::to::module`: - /// - /// ``` - /// use env_logger::Builder; - /// use log::LevelFilter; - /// - /// let mut builder = Builder::new(); - /// - /// builder.filter(Some("path::to::module"), LevelFilter::Info); - /// ``` - pub fn filter(&mut self, module: Option<&str>, level: LevelFilter) -> &mut Self { - self.filter.filter(module, level); - self - } - - /// Parses the directives string in the same form as the `RUST_LOG` - /// environment variable. - /// - /// See the module documentation for more details. - pub fn parse_filters(&mut self, filters: &str) -> &mut Self { - self.filter.parse(filters); - self - } - - /// Sets the target for the log output. - /// - /// Env logger can log to either stdout, stderr or a custom pipe. The default is stderr. - /// - /// The custom pipe can be used to send the log messages to a custom sink (for example a file). - /// Do note that direct writes to a file can become a bottleneck due to IO operation times. - /// - /// # Examples - /// - /// Write log message to `stdout`: - /// - /// ``` - /// use env_logger::{Builder, Target}; - /// - /// let mut builder = Builder::new(); - /// - /// builder.target(Target::Stdout); - /// ``` - pub fn target(&mut self, target: fmt::Target) -> &mut Self { - self.writer.target(target); - self - } - - /// Sets whether or not styles will be written. - /// - /// This can be useful in environments that don't support control characters - /// for setting colors. - /// - /// # Examples - /// - /// Never attempt to write styles: - /// - /// ``` - /// use env_logger::{Builder, WriteStyle}; - /// - /// let mut builder = Builder::new(); - /// - /// builder.write_style(WriteStyle::Never); - /// ``` - pub fn write_style(&mut self, write_style: fmt::WriteStyle) -> &mut Self { - self.writer.write_style(write_style); - self - } - - /// Parses whether or not to write styles in the same form as the `RUST_LOG_STYLE` - /// environment variable. - /// - /// See the module documentation for more details. - pub fn parse_write_style(&mut self, write_style: &str) -> &mut Self { - self.writer.parse_write_style(write_style); - self - } - - /// Sets whether or not the logger will be used in unit tests. - /// - /// If `is_test` is `true` then the logger will allow the testing framework to - /// capture log records rather than printing them to the terminal directly. - pub fn is_test(&mut self, is_test: bool) -> &mut Self { - self.writer.is_test(is_test); - self - } - - /// Initializes the global logger with the built env logger. - /// - /// This should be called early in the execution of a Rust program. Any log - /// events that occur before initialization will be ignored. - /// - /// # Errors - /// - /// This function will fail if it is called more than once, or if another - /// library has already initialized a global logger. - pub fn try_init(&mut self) -> Result<(), SetLoggerError> { - let logger = self.build(); - - let max_level = logger.filter(); - let r = log::set_boxed_logger(Box::new(logger)); - - if r.is_ok() { - log::set_max_level(max_level); - } - - r - } - - /// Initializes the global logger with the built env logger. - /// - /// This should be called early in the execution of a Rust program. Any log - /// events that occur before initialization will be ignored. - /// - /// # Panics - /// - /// This function will panic if it is called more than once, or if another - /// library has already initialized a global logger. - pub fn init(&mut self) { - self.try_init() - .expect("Builder::init should not be called after logger initialized"); - } - - /// Build an env logger. - /// - /// The returned logger implements the `Log` trait and can be installed manually - /// or nested within another logger. - pub fn build(&mut self) -> Logger { - assert!(!self.built, "attempt to re-use consumed builder"); - self.built = true; - - Logger { - writer: self.writer.build(), - filter: self.filter.build(), - format: self.format.build(), - } - } -} - -impl Logger { - /// Creates the logger from the environment. - /// - /// The variables used to read configuration from can be tweaked before - /// passing in. - /// - /// # Examples - /// - /// Create a logger reading the log filter from an environment variable - /// called `MY_LOG`: - /// - /// ``` - /// use env_logger::Logger; - /// - /// let logger = Logger::from_env("MY_LOG"); - /// ``` - /// - /// Create a logger using the `MY_LOG` variable for filtering and - /// `MY_LOG_STYLE` for whether or not to write styles: - /// - /// ``` - /// use env_logger::{Logger, Env}; - /// - /// let env = Env::new().filter_or("MY_LOG", "info").write_style_or("MY_LOG_STYLE", "always"); - /// - /// let logger = Logger::from_env(env); - /// ``` - pub fn from_env<'a, E>(env: E) -> Self - where - E: Into>, - { - Builder::from_env(env).build() - } - - /// Creates the logger from the environment using default variable names. - /// - /// This method is a convenient way to call `from_env(Env::default())` without - /// having to use the `Env` type explicitly. The logger will use the - /// [default environment variables]. - /// - /// # Examples - /// - /// Creates a logger using the default environment variables: - /// - /// ``` - /// use env_logger::Logger; - /// - /// let logger = Logger::from_default_env(); - /// ``` - /// - /// [default environment variables]: struct.Env.html#default-environment-variables - pub fn from_default_env() -> Self { - Builder::from_default_env().build() - } - - /// Returns the maximum `LevelFilter` that this env logger instance is - /// configured to output. - pub fn filter(&self) -> LevelFilter { - self.filter.filter() - } - - /// Checks if this record matches the configured filter. - pub fn matches(&self, record: &Record) -> bool { - self.filter.matches(record) - } -} - -impl Log for Logger { - fn enabled(&self, metadata: &Metadata) -> bool { - self.filter.enabled(metadata) - } - - fn log(&self, record: &Record) { - if self.matches(record) { - // Log records are written to a thread-local buffer before being printed - // to the terminal. We clear these buffers afterwards, but they aren't shrinked - // so will always at least have capacity for the largest log record formatted - // on that thread. - // - // If multiple `Logger`s are used by the same threads then the thread-local - // formatter might have different color support. If this is the case the - // formatter and its buffer are discarded and recreated. - - thread_local! { - static FORMATTER: RefCell> = RefCell::new(None); - } - - let print = |formatter: &mut Formatter, record: &Record| { - let _ = - (self.format)(formatter, record).and_then(|_| formatter.print(&self.writer)); - - // Always clear the buffer afterwards - formatter.clear(); - }; - - let printed = FORMATTER - .try_with(|tl_buf| { - match tl_buf.try_borrow_mut() { - // There are no active borrows of the buffer - Ok(mut tl_buf) => match *tl_buf { - // We have a previously set formatter - Some(ref mut formatter) => { - // Check the buffer style. If it's different from the logger's - // style then drop the buffer and recreate it. - if formatter.write_style() != self.writer.write_style() { - *formatter = Formatter::new(&self.writer); - } - - print(formatter, record); - } - // We don't have a previously set formatter - None => { - let mut formatter = Formatter::new(&self.writer); - print(&mut formatter, record); - - *tl_buf = Some(formatter); - } - }, - // There's already an active borrow of the buffer (due to re-entrancy) - Err(_) => { - print(&mut Formatter::new(&self.writer), record); - } - } - }) - .is_ok(); - - if !printed { - // The thread-local storage was not available (because its - // destructor has already run). Create a new single-use - // Formatter on the stack for this call. - print(&mut Formatter::new(&self.writer), record); - } - } - } - - fn flush(&self) {} -} - -impl<'a> Env<'a> { - /// Get a default set of environment variables. - pub fn new() -> Self { - Self::default() - } - - /// Specify an environment variable to read the filter from. - pub fn filter(mut self, filter_env: E) -> Self - where - E: Into>, - { - self.filter = Var::new(filter_env); - - self - } - - /// Specify an environment variable to read the filter from. - /// - /// If the variable is not set, the default value will be used. - pub fn filter_or(mut self, filter_env: E, default: V) -> Self - where - E: Into>, - V: Into>, - { - self.filter = Var::new_with_default(filter_env, default); - - self - } - - /// Use the default environment variable to read the filter from. - /// - /// If the variable is not set, the default value will be used. - pub fn default_filter_or(mut self, default: V) -> Self - where - V: Into>, - { - self.filter = Var::new_with_default(DEFAULT_FILTER_ENV, default); - - self - } - - fn get_filter(&self) -> Option { - self.filter.get() - } - - /// Specify an environment variable to read the style from. - pub fn write_style(mut self, write_style_env: E) -> Self - where - E: Into>, - { - self.write_style = Var::new(write_style_env); - - self - } - - /// Specify an environment variable to read the style from. - /// - /// If the variable is not set, the default value will be used. - pub fn write_style_or(mut self, write_style_env: E, default: V) -> Self - where - E: Into>, - V: Into>, - { - self.write_style = Var::new_with_default(write_style_env, default); - - self - } - - /// Use the default environment variable to read the style from. - /// - /// If the variable is not set, the default value will be used. - pub fn default_write_style_or(mut self, default: V) -> Self - where - V: Into>, - { - self.write_style = Var::new_with_default(DEFAULT_WRITE_STYLE_ENV, default); - - self - } - - fn get_write_style(&self) -> Option { - self.write_style.get() - } -} - -impl<'a> Var<'a> { - fn new(name: E) -> Self - where - E: Into>, - { - Var { - name: name.into(), - default: None, - } - } - - fn new_with_default(name: E, default: V) -> Self - where - E: Into>, - V: Into>, - { - Var { - name: name.into(), - default: Some(default.into()), - } - } - - fn get(&self) -> Option { - env::var(&*self.name) - .ok() - .or_else(|| self.default.to_owned().map(|v| v.into_owned())) - } -} - -impl<'a, T> From for Env<'a> -where - T: Into>, -{ - fn from(filter_env: T) -> Self { - Env::default().filter(filter_env.into()) - } -} - -impl<'a> Default for Env<'a> { - fn default() -> Self { - Env { - filter: Var::new(DEFAULT_FILTER_ENV), - write_style: Var::new(DEFAULT_WRITE_STYLE_ENV), - } - } -} - -mod std_fmt_impls { - use super::*; - use std::fmt; - - impl fmt::Debug for Logger { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.debug_struct("Logger") - .field("filter", &self.filter) - .finish() - } - } - - impl fmt::Debug for Builder { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - if self.built { - f.debug_struct("Logger").field("built", &true).finish() - } else { - f.debug_struct("Logger") - .field("filter", &self.filter) - .field("writer", &self.writer) - .finish() - } - } - } -} - -/// Attempts to initialize the global logger with an env logger. -/// -/// This should be called early in the execution of a Rust program. Any log -/// events that occur before initialization will be ignored. -/// -/// # Errors -/// -/// This function will fail if it is called more than once, or if another -/// library has already initialized a global logger. -pub fn try_init() -> Result<(), SetLoggerError> { - try_init_from_env(Env::default()) -} - -/// Initializes the global logger with an env logger. -/// -/// This should be called early in the execution of a Rust program. Any log -/// events that occur before initialization will be ignored. -/// -/// # Panics -/// -/// This function will panic if it is called more than once, or if another -/// library has already initialized a global logger. -pub fn init() { - try_init().expect("env_logger::init should not be called after logger initialized"); -} - -/// Attempts to initialize the global logger with an env logger from the given -/// environment variables. -/// -/// This should be called early in the execution of a Rust program. Any log -/// events that occur before initialization will be ignored. -/// -/// # Examples -/// -/// Initialise a logger using the `MY_LOG` environment variable for filters -/// and `MY_LOG_STYLE` for writing colors: -/// -/// ``` -/// use env_logger::{Builder, Env}; -/// -/// # fn run() -> Result<(), Box<::std::error::Error>> { -/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); -/// -/// env_logger::try_init_from_env(env)?; -/// -/// Ok(()) -/// # } -/// # run().unwrap(); -/// ``` -/// -/// # Errors -/// -/// This function will fail if it is called more than once, or if another -/// library has already initialized a global logger. -pub fn try_init_from_env<'a, E>(env: E) -> Result<(), SetLoggerError> -where - E: Into>, -{ - let mut builder = Builder::from_env(env); - - builder.try_init() -} - -/// Initializes the global logger with an env logger from the given environment -/// variables. -/// -/// This should be called early in the execution of a Rust program. Any log -/// events that occur before initialization will be ignored. -/// -/// # Examples -/// -/// Initialise a logger using the `MY_LOG` environment variable for filters -/// and `MY_LOG_STYLE` for writing colors: -/// -/// ``` -/// use env_logger::{Builder, Env}; -/// -/// let env = Env::new().filter("MY_LOG").write_style("MY_LOG_STYLE"); -/// -/// env_logger::init_from_env(env); -/// ``` -/// -/// # Panics -/// -/// This function will panic if it is called more than once, or if another -/// library has already initialized a global logger. -pub fn init_from_env<'a, E>(env: E) -where - E: Into>, -{ - try_init_from_env(env) - .expect("env_logger::init_from_env should not be called after logger initialized"); -} - -/// Create a new builder with the default environment variables. -/// -/// The builder can be configured before being initialized. -/// This is a convenient way of calling [`Builder::from_default_env`]. -/// -/// [`Builder::from_default_env`]: struct.Builder.html#method.from_default_env -pub fn builder() -> Builder { - Builder::from_default_env() -} - -/// Create a builder from the given environment variables. -/// -/// The builder can be configured before being initialized. -#[deprecated( - since = "0.8.0", - note = "Prefer `env_logger::Builder::from_env()` instead." -)] -pub fn from_env<'a, E>(env: E) -> Builder -where - E: Into>, -{ - Builder::from_env(env) -} - -#[cfg(test)] -mod tests { - use super::*; - - #[test] - fn env_get_filter_reads_from_var_if_set() { - env::set_var("env_get_filter_reads_from_var_if_set", "from var"); - - let env = Env::new().filter_or("env_get_filter_reads_from_var_if_set", "from default"); - - assert_eq!(Some("from var".to_owned()), env.get_filter()); - } - - #[test] - fn env_get_filter_reads_from_default_if_var_not_set() { - env::remove_var("env_get_filter_reads_from_default_if_var_not_set"); - - let env = Env::new().filter_or( - "env_get_filter_reads_from_default_if_var_not_set", - "from default", - ); - - assert_eq!(Some("from default".to_owned()), env.get_filter()); - } - - #[test] - fn env_get_write_style_reads_from_var_if_set() { - env::set_var("env_get_write_style_reads_from_var_if_set", "from var"); - - let env = - Env::new().write_style_or("env_get_write_style_reads_from_var_if_set", "from default"); - - assert_eq!(Some("from var".to_owned()), env.get_write_style()); - } - - #[test] - fn env_get_write_style_reads_from_default_if_var_not_set() { - env::remove_var("env_get_write_style_reads_from_default_if_var_not_set"); - - let env = Env::new().write_style_or( - "env_get_write_style_reads_from_default_if_var_not_set", - "from default", - ); - - assert_eq!(Some("from default".to_owned()), env.get_write_style()); - } - - #[test] - fn builder_parse_env_overrides_existing_filters() { - env::set_var( - "builder_parse_default_env_overrides_existing_filters", - "debug", - ); - let env = Env::new().filter("builder_parse_default_env_overrides_existing_filters"); - - let mut builder = Builder::new(); - builder.filter_level(LevelFilter::Trace); - // Overrides global level to debug - builder.parse_env(env); - - assert_eq!(builder.filter.build().filter(), LevelFilter::Debug); - } -} diff --git a/vendor/env_logger/tests/init-twice-retains-filter.rs b/vendor/env_logger/tests/init-twice-retains-filter.rs deleted file mode 100644 index 673da3fd2..000000000 --- a/vendor/env_logger/tests/init-twice-retains-filter.rs +++ /dev/null @@ -1,40 +0,0 @@ -extern crate env_logger; -extern crate log; - -use std::env; -use std::process; -use std::str; - -fn main() { - if env::var("YOU_ARE_TESTING_NOW").is_ok() { - // Init from the env (which should set the max level to `Debug`) - env_logger::init(); - - assert_eq!(log::LevelFilter::Debug, log::max_level()); - - // Init again using a different max level - // This shouldn't clobber the level that was previously set - env_logger::Builder::new() - .parse_filters("info") - .try_init() - .unwrap_err(); - - assert_eq!(log::LevelFilter::Debug, log::max_level()); - return; - } - - let exe = env::current_exe().unwrap(); - let out = process::Command::new(exe) - .env("YOU_ARE_TESTING_NOW", "1") - .env("RUST_LOG", "debug") - .output() - .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); - if out.status.success() { - return; - } - - println!("test failed: {}", out.status); - println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap()); - println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap()); - process::exit(1); -} diff --git a/vendor/env_logger/tests/log-in-log.rs b/vendor/env_logger/tests/log-in-log.rs deleted file mode 100644 index 89517ff36..000000000 --- a/vendor/env_logger/tests/log-in-log.rs +++ /dev/null @@ -1,39 +0,0 @@ -#[macro_use] -extern crate log; -extern crate env_logger; - -use std::env; -use std::fmt; -use std::process; -use std::str; - -struct Foo; - -impl fmt::Display for Foo { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - info!("test"); - f.write_str("bar") - } -} - -fn main() { - env_logger::init(); - if env::var("YOU_ARE_TESTING_NOW").is_ok() { - return info!("{}", Foo); - } - - let exe = env::current_exe().unwrap(); - let out = process::Command::new(exe) - .env("YOU_ARE_TESTING_NOW", "1") - .env("RUST_LOG", "debug") - .output() - .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); - if out.status.success() { - return; - } - - println!("test failed: {}", out.status); - println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap()); - println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap()); - process::exit(1); -} diff --git a/vendor/env_logger/tests/log_tls_dtors.rs b/vendor/env_logger/tests/log_tls_dtors.rs deleted file mode 100644 index 5db87bd6c..000000000 --- a/vendor/env_logger/tests/log_tls_dtors.rs +++ /dev/null @@ -1,66 +0,0 @@ -#[macro_use] -extern crate log; -extern crate env_logger; - -use std::env; -use std::process; -use std::str; -use std::thread; - -struct DropMe; - -impl Drop for DropMe { - fn drop(&mut self) { - debug!("Dropping now"); - } -} - -fn run() { - // Use multiple thread local values to increase the chance that our TLS - // value will get destroyed after the FORMATTER key in the library - thread_local! { - static DROP_ME_0: DropMe = DropMe; - static DROP_ME_1: DropMe = DropMe; - static DROP_ME_2: DropMe = DropMe; - static DROP_ME_3: DropMe = DropMe; - static DROP_ME_4: DropMe = DropMe; - static DROP_ME_5: DropMe = DropMe; - static DROP_ME_6: DropMe = DropMe; - static DROP_ME_7: DropMe = DropMe; - static DROP_ME_8: DropMe = DropMe; - static DROP_ME_9: DropMe = DropMe; - } - DROP_ME_0.with(|_| {}); - DROP_ME_1.with(|_| {}); - DROP_ME_2.with(|_| {}); - DROP_ME_3.with(|_| {}); - DROP_ME_4.with(|_| {}); - DROP_ME_5.with(|_| {}); - DROP_ME_6.with(|_| {}); - DROP_ME_7.with(|_| {}); - DROP_ME_8.with(|_| {}); - DROP_ME_9.with(|_| {}); -} - -fn main() { - env_logger::init(); - if env::var("YOU_ARE_TESTING_NOW").is_ok() { - // Run on a separate thread because TLS values on the main thread - // won't have their destructors run if pthread is used. - // https://doc.rust-lang.org/std/thread/struct.LocalKey.html#platform-specific-behavior - thread::spawn(run).join().unwrap(); - } else { - let exe = env::current_exe().unwrap(); - let out = process::Command::new(exe) - .env("YOU_ARE_TESTING_NOW", "1") - .env("RUST_LOG", "debug") - .output() - .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); - if !out.status.success() { - println!("test failed: {}", out.status); - println!("--- stdout\n{}", str::from_utf8(&out.stdout).unwrap()); - println!("--- stderr\n{}", str::from_utf8(&out.stderr).unwrap()); - process::exit(1); - } - } -} diff --git a/vendor/env_logger/tests/regexp_filter.rs b/vendor/env_logger/tests/regexp_filter.rs deleted file mode 100644 index 40178bac7..000000000 --- a/vendor/env_logger/tests/regexp_filter.rs +++ /dev/null @@ -1,57 +0,0 @@ -#[macro_use] -extern crate log; -extern crate env_logger; - -use std::env; -use std::process; -use std::str; - -fn main() { - if env::var("LOG_REGEXP_TEST").ok() == Some(String::from("1")) { - child_main(); - } else { - parent_main() - } -} - -fn child_main() { - env_logger::init(); - info!("XYZ Message"); -} - -fn run_child(rust_log: String) -> bool { - let exe = env::current_exe().unwrap(); - let out = process::Command::new(exe) - .env("LOG_REGEXP_TEST", "1") - .env("RUST_LOG", rust_log) - .output() - .unwrap_or_else(|e| panic!("Unable to start child process: {}", e)); - str::from_utf8(out.stderr.as_ref()) - .unwrap() - .contains("XYZ Message") -} - -fn assert_message_printed(rust_log: &str) { - if !run_child(rust_log.to_string()) { - panic!("RUST_LOG={} should allow the test log message", rust_log) - } -} - -fn assert_message_not_printed(rust_log: &str) { - if run_child(rust_log.to_string()) { - panic!( - "RUST_LOG={} should not allow the test log message", - rust_log - ) - } -} - -fn parent_main() { - // test normal log severity levels - assert_message_printed("info"); - assert_message_not_printed("warn"); - - // test of regular expression filters - assert_message_printed("info/XYZ"); - assert_message_not_printed("info/XXX"); -} -- cgit v1.2.3