mirror of
https://github.com/denoland/deno.git
synced 2024-12-22 07:14:47 -05:00
refactor: use "deno_config" crate (#20260)
Moved the configuration file to https://github.com/denoland/deno_config as we will have to use it in other projects.
This commit is contained in:
parent
b1ce2e4167
commit
f9beb92818
11 changed files with 107 additions and 1936 deletions
48
Cargo.lock
generated
48
Cargo.lock
generated
|
@ -721,16 +721,6 @@ dependencies = [
|
||||||
"typenum",
|
"typenum",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "ctor"
|
|
||||||
version = "0.1.26"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "6d2301688392eb071b0bf1a37be05c469d3cc4dbbd95df672fe28ab021e6a096"
|
|
||||||
dependencies = [
|
|
||||||
"quote 1.0.32",
|
|
||||||
"syn 1.0.109",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "ctr"
|
name = "ctr"
|
||||||
version = "0.9.2"
|
version = "0.9.2"
|
||||||
|
@ -810,6 +800,7 @@ dependencies = [
|
||||||
"deno_ast",
|
"deno_ast",
|
||||||
"deno_bench_util",
|
"deno_bench_util",
|
||||||
"deno_cache_dir",
|
"deno_cache_dir",
|
||||||
|
"deno_config",
|
||||||
"deno_core",
|
"deno_core",
|
||||||
"deno_doc",
|
"deno_doc",
|
||||||
"deno_emit",
|
"deno_emit",
|
||||||
|
@ -998,6 +989,24 @@ dependencies = [
|
||||||
"url",
|
"url",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "deno_config"
|
||||||
|
version = "0.2.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "a42ff2a01961c72ef883375399677ccf046dba607dc14169b313e4a95bd26da2"
|
||||||
|
dependencies = [
|
||||||
|
"anyhow",
|
||||||
|
"deno_semver",
|
||||||
|
"indexmap 1.9.3",
|
||||||
|
"jsonc-parser",
|
||||||
|
"log",
|
||||||
|
"percent-encoding",
|
||||||
|
"pretty_assertions",
|
||||||
|
"serde",
|
||||||
|
"serde_json",
|
||||||
|
"url",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "deno_console"
|
name = "deno_console"
|
||||||
version = "0.115.0"
|
version = "0.115.0"
|
||||||
|
@ -3001,9 +3010,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "log"
|
name = "log"
|
||||||
version = "0.4.19"
|
version = "0.4.20"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
|
checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
]
|
]
|
||||||
|
@ -3359,15 +3368,6 @@ dependencies = [
|
||||||
"winapi",
|
"winapi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
|
||||||
name = "output_vt100"
|
|
||||||
version = "0.1.3"
|
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
|
||||||
checksum = "628223faebab4e3e40667ee0b2336d34a5b960ff60ea743ddfdbcf7770bcfb66"
|
|
||||||
dependencies = [
|
|
||||||
"winapi",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "outref"
|
name = "outref"
|
||||||
version = "0.5.1"
|
version = "0.5.1"
|
||||||
|
@ -3707,13 +3707,11 @@ checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "pretty_assertions"
|
name = "pretty_assertions"
|
||||||
version = "1.3.0"
|
version = "1.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a25e9bcb20aa780fd0bb16b72403a9064d6b3f22f026946029acb941a50af755"
|
checksum = "af7cee1a6c8a5b9208b3cb1061f10c0cb689087b3d8ce85fb9d2dd7a29b6ba66"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ctor",
|
|
||||||
"diff",
|
"diff",
|
||||||
"output_vt100",
|
|
||||||
"yansi",
|
"yansi",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ httparse = "1.8.0"
|
||||||
hyper = { version = "0.14.26", features = ["runtime", "http1"] }
|
hyper = { version = "0.14.26", features = ["runtime", "http1"] }
|
||||||
indexmap = { version = "1.9.2", features = ["serde"] }
|
indexmap = { version = "1.9.2", features = ["serde"] }
|
||||||
libc = "0.2.126"
|
libc = "0.2.126"
|
||||||
log = "=0.4.19"
|
log = "=0.4.20"
|
||||||
lsp-types = "=0.93.2" # used by tower-lsp and "proposed" feature is unstable in patch releases
|
lsp-types = "=0.93.2" # used by tower-lsp and "proposed" feature is unstable in patch releases
|
||||||
memmem = "0.1.1"
|
memmem = "0.1.1"
|
||||||
notify = "=5.0.0"
|
notify = "=5.0.0"
|
||||||
|
@ -110,7 +110,7 @@ os_pipe = "=1.0.1"
|
||||||
parking_lot = "0.12.0"
|
parking_lot = "0.12.0"
|
||||||
percent-encoding = "=2.3.0"
|
percent-encoding = "=2.3.0"
|
||||||
pin-project = "1.0.11" # don't pin because they yank crates from cargo
|
pin-project = "1.0.11" # don't pin because they yank crates from cargo
|
||||||
pretty_assertions = "=1.3.0"
|
pretty_assertions = "=1.4.0"
|
||||||
prost = "0.11"
|
prost = "0.11"
|
||||||
prost-build = "0.11"
|
prost-build = "0.11"
|
||||||
rand = "=0.8.5"
|
rand = "=0.8.5"
|
||||||
|
|
|
@ -47,6 +47,7 @@ winres.workspace = true
|
||||||
[dependencies]
|
[dependencies]
|
||||||
deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] }
|
deno_ast = { workspace = true, features = ["bundler", "cjs", "codegen", "dep_graph", "module_specifier", "proposal", "react", "sourcemap", "transforms", "typescript", "view", "visit"] }
|
||||||
deno_cache_dir = "=0.5.2"
|
deno_cache_dir = "=0.5.2"
|
||||||
|
deno_config = "=0.2.1"
|
||||||
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
deno_core = { workspace = true, features = ["include_js_files_for_snapshotting"] }
|
||||||
deno_doc = "=0.65.0"
|
deno_doc = "=0.65.0"
|
||||||
deno_emit = "=0.26.0"
|
deno_emit = "=0.26.0"
|
||||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -7,6 +7,7 @@ use clap::ArgMatches;
|
||||||
use clap::ColorChoice;
|
use clap::ColorChoice;
|
||||||
use clap::Command;
|
use clap::Command;
|
||||||
use clap::ValueHint;
|
use clap::ValueHint;
|
||||||
|
use deno_config::ConfigFlag;
|
||||||
use deno_core::resolve_url_or_path;
|
use deno_core::resolve_url_or_path;
|
||||||
use deno_core::url::Url;
|
use deno_core::url::Url;
|
||||||
use deno_graph::GraphKind;
|
use deno_graph::GraphKind;
|
||||||
|
@ -333,19 +334,6 @@ impl Default for TypeCheckMode {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
|
||||||
pub enum ConfigFlag {
|
|
||||||
Discover,
|
|
||||||
Path(String),
|
|
||||||
Disabled,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for ConfigFlag {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Discover
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq)]
|
#[derive(Clone, Debug, Eq, PartialEq)]
|
||||||
pub enum CaData {
|
pub enum CaData {
|
||||||
/// The string is a file path
|
/// The string is a file path
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
// Copyright 2018-2023 the Deno authors. All rights reserved. MIT license.
|
||||||
|
|
||||||
mod config_file;
|
|
||||||
mod flags;
|
mod flags;
|
||||||
mod flags_net;
|
mod flags_net;
|
||||||
mod import_map;
|
mod import_map;
|
||||||
|
@ -18,19 +17,19 @@ use deno_runtime::deno_tls::RootCertStoreProvider;
|
||||||
use deno_semver::npm::NpmPackageReqReference;
|
use deno_semver::npm::NpmPackageReqReference;
|
||||||
use indexmap::IndexMap;
|
use indexmap::IndexMap;
|
||||||
|
|
||||||
pub use config_file::BenchConfig;
|
pub use deno_config::BenchConfig;
|
||||||
pub use config_file::CompilerOptions;
|
pub use deno_config::CompilerOptions;
|
||||||
pub use config_file::ConfigFile;
|
pub use deno_config::ConfigFile;
|
||||||
pub use config_file::EmitConfigOptions;
|
pub use deno_config::EmitConfigOptions;
|
||||||
pub use config_file::FilesConfig;
|
pub use deno_config::FilesConfig;
|
||||||
pub use config_file::FmtOptionsConfig;
|
pub use deno_config::FmtOptionsConfig;
|
||||||
pub use config_file::JsxImportSourceConfig;
|
pub use deno_config::JsxImportSourceConfig;
|
||||||
pub use config_file::LintRulesConfig;
|
pub use deno_config::LintRulesConfig;
|
||||||
pub use config_file::ProseWrap;
|
pub use deno_config::ProseWrap;
|
||||||
pub use config_file::TsConfig;
|
pub use deno_config::TsConfig;
|
||||||
pub use config_file::TsConfigForEmit;
|
pub use deno_config::TsConfigForEmit;
|
||||||
pub use config_file::TsConfigType;
|
pub use deno_config::TsConfigType;
|
||||||
pub use config_file::TsTypeLib;
|
pub use deno_config::TsTypeLib;
|
||||||
pub use flags::*;
|
pub use flags::*;
|
||||||
pub use lockfile::Lockfile;
|
pub use lockfile::Lockfile;
|
||||||
pub use lockfile::LockfileError;
|
pub use lockfile::LockfileError;
|
||||||
|
@ -74,10 +73,43 @@ use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||||
use crate::util::glob::expand_globs;
|
use crate::util::glob::expand_globs;
|
||||||
use crate::version;
|
use crate::version;
|
||||||
|
|
||||||
use self::config_file::FmtConfig;
|
use deno_config::FmtConfig;
|
||||||
use self::config_file::LintConfig;
|
use deno_config::LintConfig;
|
||||||
use self::config_file::MaybeImportsResult;
|
use deno_config::TestConfig;
|
||||||
use self::config_file::TestConfig;
|
|
||||||
|
pub fn ts_config_to_emit_options(
|
||||||
|
config: deno_config::TsConfig,
|
||||||
|
) -> deno_ast::EmitOptions {
|
||||||
|
let options: deno_config::EmitConfigOptions =
|
||||||
|
serde_json::from_value(config.0).unwrap();
|
||||||
|
let imports_not_used_as_values =
|
||||||
|
match options.imports_not_used_as_values.as_str() {
|
||||||
|
"preserve" => deno_ast::ImportsNotUsedAsValues::Preserve,
|
||||||
|
"error" => deno_ast::ImportsNotUsedAsValues::Error,
|
||||||
|
_ => deno_ast::ImportsNotUsedAsValues::Remove,
|
||||||
|
};
|
||||||
|
let (transform_jsx, jsx_automatic, jsx_development) =
|
||||||
|
match options.jsx.as_str() {
|
||||||
|
"react" => (true, false, false),
|
||||||
|
"react-jsx" => (true, true, false),
|
||||||
|
"react-jsxdev" => (true, true, true),
|
||||||
|
_ => (false, false, false),
|
||||||
|
};
|
||||||
|
deno_ast::EmitOptions {
|
||||||
|
emit_metadata: options.emit_decorator_metadata,
|
||||||
|
imports_not_used_as_values,
|
||||||
|
inline_source_map: options.inline_source_map,
|
||||||
|
inline_sources: options.inline_sources,
|
||||||
|
source_map: options.source_map,
|
||||||
|
jsx_automatic,
|
||||||
|
jsx_development,
|
||||||
|
jsx_factory: options.jsx_factory,
|
||||||
|
jsx_fragment_factory: options.jsx_fragment_factory,
|
||||||
|
jsx_import_source: options.jsx_import_source,
|
||||||
|
transform_jsx,
|
||||||
|
var_decl_imports: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Indicates how cached source files should be handled.
|
/// Indicates how cached source files should be handled.
|
||||||
#[derive(Debug, Clone, Eq, PartialEq)]
|
#[derive(Debug, Clone, Eq, PartialEq)]
|
||||||
|
@ -595,10 +627,14 @@ impl CliOptions {
|
||||||
pub fn from_flags(flags: Flags) -> Result<Self, AnyError> {
|
pub fn from_flags(flags: Flags) -> Result<Self, AnyError> {
|
||||||
let initial_cwd =
|
let initial_cwd =
|
||||||
std::env::current_dir().with_context(|| "Failed getting cwd.")?;
|
std::env::current_dir().with_context(|| "Failed getting cwd.")?;
|
||||||
let maybe_config_file = ConfigFile::discover(&flags, &initial_cwd)?;
|
let maybe_config_file = ConfigFile::discover(
|
||||||
|
&flags.config_flag,
|
||||||
|
flags.config_path_args(&initial_cwd),
|
||||||
|
&initial_cwd,
|
||||||
|
)?;
|
||||||
|
|
||||||
let mut maybe_package_json = None;
|
let mut maybe_package_json = None;
|
||||||
if flags.config_flag == ConfigFlag::Disabled
|
if flags.config_flag == deno_config::ConfigFlag::Disabled
|
||||||
|| flags.no_npm
|
|| flags.no_npm
|
||||||
|| has_flag_env_var("DENO_NO_PACKAGE_JSON")
|
|| has_flag_env_var("DENO_NO_PACKAGE_JSON")
|
||||||
{
|
{
|
||||||
|
@ -890,7 +926,7 @@ impl CliOptions {
|
||||||
&self,
|
&self,
|
||||||
config_type: TsConfigType,
|
config_type: TsConfigType,
|
||||||
) -> Result<TsConfigForEmit, AnyError> {
|
) -> Result<TsConfigForEmit, AnyError> {
|
||||||
config_file::get_ts_config_for_emit(
|
deno_config::get_ts_config_for_emit(
|
||||||
config_type,
|
config_type,
|
||||||
self.maybe_config_file.as_ref(),
|
self.maybe_config_file.as_ref(),
|
||||||
)
|
)
|
||||||
|
@ -934,9 +970,19 @@ impl CliOptions {
|
||||||
|
|
||||||
/// Return any imports that should be brought into the scope of the module
|
/// Return any imports that should be brought into the scope of the module
|
||||||
/// graph.
|
/// graph.
|
||||||
pub fn to_maybe_imports(&self) -> MaybeImportsResult {
|
pub fn to_maybe_imports(
|
||||||
|
&self,
|
||||||
|
) -> Result<Vec<deno_graph::ReferrerImports>, AnyError> {
|
||||||
if let Some(config_file) = &self.maybe_config_file {
|
if let Some(config_file) = &self.maybe_config_file {
|
||||||
config_file.to_maybe_imports()
|
config_file.to_maybe_imports().map(|maybe_imports| {
|
||||||
|
maybe_imports
|
||||||
|
.into_iter()
|
||||||
|
.map(|(referrer, imports)| deno_graph::ReferrerImports {
|
||||||
|
referrer,
|
||||||
|
imports,
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
Ok(Vec::new())
|
Ok(Vec::new())
|
||||||
}
|
}
|
||||||
|
|
|
@ -474,8 +474,8 @@ impl CliFactory {
|
||||||
if let Some(ignored_options) = ts_config_result.maybe_ignored_options {
|
if let Some(ignored_options) = ts_config_result.maybe_ignored_options {
|
||||||
warn!("{}", ignored_options);
|
warn!("{}", ignored_options);
|
||||||
}
|
}
|
||||||
let emit_options: deno_ast::EmitOptions =
|
let emit_options =
|
||||||
ts_config_result.ts_config.into();
|
crate::args::ts_config_to_emit_options(ts_config_result.ts_config);
|
||||||
Ok(Arc::new(Emitter::new(
|
Ok(Arc::new(Emitter::new(
|
||||||
self.emit_cache()?.clone(),
|
self.emit_cache()?.clone(),
|
||||||
self.parsed_source_cache()?.clone(),
|
self.parsed_source_cache()?.clone(),
|
||||||
|
|
|
@ -1262,13 +1262,10 @@ impl Documents {
|
||||||
{
|
{
|
||||||
imports
|
imports
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.map(|import| {
|
.map(|(referrer, imports)| {
|
||||||
let graph_import = GraphImport::new(
|
let graph_import =
|
||||||
&import.referrer,
|
GraphImport::new(&referrer, imports, Some(self.get_resolver()));
|
||||||
import.imports,
|
(referrer, graph_import)
|
||||||
Some(self.get_resolver()),
|
|
||||||
);
|
|
||||||
(import.referrer, graph_import)
|
|
||||||
})
|
})
|
||||||
.collect()
|
.collect()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -150,7 +150,9 @@ fn bundle_module_graph(
|
||||||
graph,
|
graph,
|
||||||
deno_emit::BundleOptions {
|
deno_emit::BundleOptions {
|
||||||
bundle_type: deno_emit::BundleType::Module,
|
bundle_type: deno_emit::BundleType::Module,
|
||||||
emit_options: ts_config_result.ts_config.into(),
|
emit_options: crate::args::ts_config_to_emit_options(
|
||||||
|
ts_config_result.ts_config,
|
||||||
|
),
|
||||||
emit_ignore_directives: true,
|
emit_ignore_directives: true,
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
use crate::args::resolve_no_prompt;
|
use crate::args::resolve_no_prompt;
|
||||||
use crate::args::CaData;
|
use crate::args::CaData;
|
||||||
use crate::args::ConfigFlag;
|
|
||||||
use crate::args::Flags;
|
use crate::args::Flags;
|
||||||
use crate::args::InstallFlags;
|
use crate::args::InstallFlags;
|
||||||
use crate::args::TypeCheckMode;
|
use crate::args::TypeCheckMode;
|
||||||
|
@ -10,6 +9,7 @@ use crate::factory::CliFactory;
|
||||||
use crate::http_util::HttpClient;
|
use crate::http_util::HttpClient;
|
||||||
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
use crate::util::fs::canonicalize_path_maybe_not_exists;
|
||||||
|
|
||||||
|
use deno_config::ConfigFlag;
|
||||||
use deno_core::anyhow::Context;
|
use deno_core::anyhow::Context;
|
||||||
use deno_core::error::generic_error;
|
use deno_core::error::generic_error;
|
||||||
use deno_core::error::AnyError;
|
use deno_core::error::AnyError;
|
||||||
|
@ -491,8 +491,8 @@ fn is_in_path(dir: &Path) -> bool {
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
use crate::args::ConfigFlag;
|
|
||||||
use crate::util::fs::canonicalize_path;
|
use crate::util::fs::canonicalize_path;
|
||||||
|
use deno_config::ConfigFlag;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use test_util::testdata_path;
|
use test_util::testdata_path;
|
||||||
use test_util::TempDir;
|
use test_util::TempDir;
|
||||||
|
|
|
@ -110,25 +110,6 @@ pub fn specifier_to_file_path(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Gets the parent of this module specifier.
|
|
||||||
pub fn specifier_parent(specifier: &ModuleSpecifier) -> ModuleSpecifier {
|
|
||||||
let mut specifier = specifier.clone();
|
|
||||||
// don't use specifier.segments() because it will strip the leading slash
|
|
||||||
let mut segments = specifier.path().split('/').collect::<Vec<_>>();
|
|
||||||
if segments.iter().all(|s| s.is_empty()) {
|
|
||||||
return specifier;
|
|
||||||
}
|
|
||||||
if let Some(last) = segments.last() {
|
|
||||||
if last.is_empty() {
|
|
||||||
segments.pop();
|
|
||||||
}
|
|
||||||
segments.pop();
|
|
||||||
let new_path = format!("{}/", segments.join("/"));
|
|
||||||
specifier.set_path(&new_path);
|
|
||||||
}
|
|
||||||
specifier
|
|
||||||
}
|
|
||||||
|
|
||||||
/// `from.make_relative(to)` but with fixes.
|
/// `from.make_relative(to)` but with fixes.
|
||||||
pub fn relative_specifier(
|
pub fn relative_specifier(
|
||||||
from: &ModuleSpecifier,
|
from: &ModuleSpecifier,
|
||||||
|
@ -293,22 +274,6 @@ mod test {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_specifier_parent() {
|
|
||||||
run_test("file:///", "file:///");
|
|
||||||
run_test("file:///test", "file:///");
|
|
||||||
run_test("file:///test/", "file:///");
|
|
||||||
run_test("file:///test/other", "file:///test/");
|
|
||||||
run_test("file:///test/other.txt", "file:///test/");
|
|
||||||
run_test("file:///test/other/", "file:///test/");
|
|
||||||
|
|
||||||
fn run_test(specifier: &str, expected: &str) {
|
|
||||||
let result =
|
|
||||||
specifier_parent(&ModuleSpecifier::parse(specifier).unwrap());
|
|
||||||
assert_eq!(result.to_string(), expected);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_relative_specifier() {
|
fn test_relative_specifier() {
|
||||||
let fixtures: Vec<(&str, &str, Option<&str>)> = vec![
|
let fixtures: Vec<(&str, &str, Option<&str>)> = vec![
|
||||||
|
|
Loading…
Reference in a new issue