Phase 2: Rust Workspace Transformation (Part 1)
- Renamed directory: codex-backend-openapi-models -> llmx-backend-openapi-models
- Updated all Cargo.toml files:
- Package names: codex-* -> llmx-*
- Library names: codex_* -> llmx_*
- Workspace dependencies updated
- Renamed Rust source files:
- codex*.rs -> llmx*.rs (all modules)
- codex_conversation -> llmx_conversation
- codex_delegate -> llmx_delegate
- codex_message_processor -> llmx_message_processor
- codex_tool_* -> llmx_tool_*
- Updated all Rust imports:
- use codex_* -> use llmx_*
- mod codex* -> mod llmx*
- Updated environment variables in code:
- CODEX_HOME -> LLMX_HOME
- .codex -> .llmx paths
- Updated protocol crate lib name for proper linking
Note: Some compilation errors remain (type inference issues) but all
renaming is complete. Will fix compilation in next phase.
🤖 Generated with Claude Code
This commit is contained in:
@@ -1,14 +1,14 @@
|
||||
[package]
|
||||
edition = "2024"
|
||||
name = "codex-cli"
|
||||
name = "llmx-cli"
|
||||
version = { workspace = true }
|
||||
|
||||
[[bin]]
|
||||
name = "codex"
|
||||
name = "llmx"
|
||||
path = "src/main.rs"
|
||||
|
||||
[lib]
|
||||
name = "codex_cli"
|
||||
name = "llmx_cli"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[lints]
|
||||
@@ -18,22 +18,22 @@ workspace = true
|
||||
anyhow = { workspace = true }
|
||||
clap = { workspace = true, features = ["derive"] }
|
||||
clap_complete = { workspace = true }
|
||||
codex-app-server = { workspace = true }
|
||||
codex-app-server-protocol = { workspace = true }
|
||||
codex-arg0 = { workspace = true }
|
||||
codex-chatgpt = { workspace = true }
|
||||
codex-cloud-tasks = { path = "../cloud-tasks" }
|
||||
codex-common = { workspace = true, features = ["cli"] }
|
||||
codex-core = { workspace = true }
|
||||
codex-exec = { workspace = true }
|
||||
codex-login = { workspace = true }
|
||||
codex-mcp-server = { workspace = true }
|
||||
codex-process-hardening = { workspace = true }
|
||||
codex-protocol = { workspace = true }
|
||||
codex-responses-api-proxy = { workspace = true }
|
||||
codex-rmcp-client = { workspace = true }
|
||||
codex-stdio-to-uds = { workspace = true }
|
||||
codex-tui = { workspace = true }
|
||||
llmx-app-server = { workspace = true }
|
||||
llmx-app-server-protocol = { workspace = true }
|
||||
llmx-arg0 = { workspace = true }
|
||||
llmx-chatgpt = { workspace = true }
|
||||
llmx-cloud-tasks = { path = "../cloud-tasks" }
|
||||
llmx-common = { workspace = true, features = ["cli"] }
|
||||
llmx-core = { workspace = true }
|
||||
llmx-exec = { workspace = true }
|
||||
llmx-login = { workspace = true }
|
||||
llmx-mcp-server = { workspace = true }
|
||||
llmx-process-hardening = { workspace = true }
|
||||
llmx-protocol = { workspace = true }
|
||||
llmx-responses-api-proxy = { workspace = true }
|
||||
llmx-rmcp-client = { workspace = true }
|
||||
llmx-stdio-to-uds = { workspace = true }
|
||||
llmx-tui = { workspace = true }
|
||||
ctor = { workspace = true }
|
||||
libc = { workspace = true }
|
||||
owo-colors = { workspace = true }
|
||||
@@ -51,7 +51,7 @@ tokio = { workspace = true, features = [
|
||||
tracing = { workspace = true }
|
||||
|
||||
[target.'cfg(target_os = "windows")'.dependencies]
|
||||
codex_windows_sandbox = { package = "codex-windows-sandbox", path = "../windows-sandbox-rs" }
|
||||
codex_windows_sandbox = { package = "llmx-windows-sandbox", path = "../windows-sandbox-rs" }
|
||||
|
||||
[dev-dependencies]
|
||||
assert_cmd = { workspace = true }
|
||||
|
||||
@@ -5,15 +5,15 @@ mod seatbelt;
|
||||
|
||||
use std::path::PathBuf;
|
||||
|
||||
use codex_common::CliConfigOverrides;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config::ConfigOverrides;
|
||||
use codex_core::exec_env::create_env;
|
||||
use codex_core::landlock::spawn_command_under_linux_sandbox;
|
||||
use llmx_common::CliConfigOverrides;
|
||||
use llmx_core::config::Config;
|
||||
use llmx_core::config::ConfigOverrides;
|
||||
use llmx_core::exec_env::create_env;
|
||||
use llmx_core::landlock::spawn_command_under_linux_sandbox;
|
||||
#[cfg(target_os = "macos")]
|
||||
use codex_core::seatbelt::spawn_command_under_seatbelt;
|
||||
use codex_core::spawn::StdioPolicy;
|
||||
use codex_protocol::config_types::SandboxMode;
|
||||
use llmx_core::seatbelt::spawn_command_under_seatbelt;
|
||||
use llmx_core::spawn::StdioPolicy;
|
||||
use llmx_protocol::config_types::SandboxMode;
|
||||
|
||||
use crate::LandlockCommand;
|
||||
use crate::SeatbeltCommand;
|
||||
@@ -136,12 +136,12 @@ async fn run_command_under_sandbox(
|
||||
if let SandboxType::Windows = sandbox_type {
|
||||
#[cfg(target_os = "windows")]
|
||||
{
|
||||
use codex_windows_sandbox::run_windows_sandbox_capture;
|
||||
use llmx_windows_sandbox::run_windows_sandbox_capture;
|
||||
|
||||
let policy_str = match &config.sandbox_policy {
|
||||
codex_core::protocol::SandboxPolicy::DangerFullAccess => "workspace-write",
|
||||
codex_core::protocol::SandboxPolicy::ReadOnly => "read-only",
|
||||
codex_core::protocol::SandboxPolicy::WorkspaceWrite { .. } => "workspace-write",
|
||||
llmx_core::protocol::SandboxPolicy::DangerFullAccess => "workspace-write",
|
||||
llmx_core::protocol::SandboxPolicy::ReadOnly => "read-only",
|
||||
llmx_core::protocol::SandboxPolicy::WorkspaceWrite { .. } => "workspace-write",
|
||||
};
|
||||
|
||||
let sandbox_cwd = sandbox_policy_cwd.clone();
|
||||
|
||||
@@ -3,7 +3,7 @@ mod exit_status;
|
||||
pub mod login;
|
||||
|
||||
use clap::Parser;
|
||||
use codex_common::CliConfigOverrides;
|
||||
use llmx_common::CliConfigOverrides;
|
||||
|
||||
#[derive(Debug, Parser)]
|
||||
pub struct SeatbeltCommand {
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
use codex_app_server_protocol::AuthMode;
|
||||
use codex_common::CliConfigOverrides;
|
||||
use codex_core::CodexAuth;
|
||||
use codex_core::auth::AuthCredentialsStoreMode;
|
||||
use codex_core::auth::CLIENT_ID;
|
||||
use codex_core::auth::login_with_api_key;
|
||||
use codex_core::auth::logout;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config::ConfigOverrides;
|
||||
use codex_login::ServerOptions;
|
||||
use codex_login::run_device_code_login;
|
||||
use codex_login::run_login_server;
|
||||
use codex_protocol::config_types::ForcedLoginMethod;
|
||||
use llmx_app_server_protocol::AuthMode;
|
||||
use llmx_common::CliConfigOverrides;
|
||||
use llmx_core::CodexAuth;
|
||||
use llmx_core::auth::AuthCredentialsStoreMode;
|
||||
use llmx_core::auth::CLIENT_ID;
|
||||
use llmx_core::auth::login_with_api_key;
|
||||
use llmx_core::auth::logout;
|
||||
use llmx_core::config::Config;
|
||||
use llmx_core::config::ConfigOverrides;
|
||||
use llmx_login::ServerOptions;
|
||||
use llmx_login::run_device_code_login;
|
||||
use llmx_login::run_login_server;
|
||||
use llmx_protocol::config_types::ForcedLoginMethod;
|
||||
use std::io::IsTerminal;
|
||||
use std::io::Read;
|
||||
use std::path::PathBuf;
|
||||
|
||||
@@ -3,25 +3,25 @@ use clap::CommandFactory;
|
||||
use clap::Parser;
|
||||
use clap_complete::Shell;
|
||||
use clap_complete::generate;
|
||||
use codex_arg0::arg0_dispatch_or_else;
|
||||
use codex_chatgpt::apply_command::ApplyCommand;
|
||||
use codex_chatgpt::apply_command::run_apply_command;
|
||||
use codex_cli::LandlockCommand;
|
||||
use codex_cli::SeatbeltCommand;
|
||||
use codex_cli::WindowsCommand;
|
||||
use codex_cli::login::read_api_key_from_stdin;
|
||||
use codex_cli::login::run_login_status;
|
||||
use codex_cli::login::run_login_with_api_key;
|
||||
use codex_cli::login::run_login_with_chatgpt;
|
||||
use codex_cli::login::run_login_with_device_code;
|
||||
use codex_cli::login::run_logout;
|
||||
use codex_cloud_tasks::Cli as CloudTasksCli;
|
||||
use codex_common::CliConfigOverrides;
|
||||
use codex_exec::Cli as ExecCli;
|
||||
use codex_responses_api_proxy::Args as ResponsesApiProxyArgs;
|
||||
use codex_tui::AppExitInfo;
|
||||
use codex_tui::Cli as TuiCli;
|
||||
use codex_tui::update_action::UpdateAction;
|
||||
use llmx_arg0::arg0_dispatch_or_else;
|
||||
use llmx_chatgpt::apply_command::ApplyCommand;
|
||||
use llmx_chatgpt::apply_command::run_apply_command;
|
||||
use llmx_cli::LandlockCommand;
|
||||
use llmx_cli::SeatbeltCommand;
|
||||
use llmx_cli::WindowsCommand;
|
||||
use llmx_cli::login::read_api_key_from_stdin;
|
||||
use llmx_cli::login::run_login_status;
|
||||
use llmx_cli::login::run_login_with_api_key;
|
||||
use llmx_cli::login::run_login_with_chatgpt;
|
||||
use llmx_cli::login::run_login_with_device_code;
|
||||
use llmx_cli::login::run_logout;
|
||||
use llmx_cloud_tasks::Cli as CloudTasksCli;
|
||||
use llmx_common::CliConfigOverrides;
|
||||
use llmx_exec::Cli as ExecCli;
|
||||
use llmx_responses_api_proxy::Args as ResponsesApiProxyArgs;
|
||||
use llmx_tui::AppExitInfo;
|
||||
use llmx_tui::Cli as TuiCli;
|
||||
use llmx_tui::update_action::UpdateAction;
|
||||
use owo_colors::OwoColorize;
|
||||
use std::path::PathBuf;
|
||||
use supports_color::Stream;
|
||||
@@ -32,9 +32,9 @@ mod wsl_paths;
|
||||
|
||||
use crate::mcp_cmd::McpCli;
|
||||
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config::ConfigOverrides;
|
||||
use codex_core::features::is_known_feature_key;
|
||||
use llmx_core::config::Config;
|
||||
use llmx_core::config::ConfigOverrides;
|
||||
use llmx_core::features::is_known_feature_key;
|
||||
|
||||
/// Codex CLI
|
||||
///
|
||||
@@ -259,7 +259,7 @@ fn format_exit_messages(exit_info: AppExitInfo, color_enabled: bool) -> Vec<Stri
|
||||
|
||||
let mut lines = vec![format!(
|
||||
"{}",
|
||||
codex_core::protocol::FinalOutput::from(token_usage)
|
||||
llmx_core::protocol::FinalOutput::from(token_usage)
|
||||
)];
|
||||
|
||||
if let Some(session_id) = conversation_id {
|
||||
@@ -369,8 +369,8 @@ enum FeaturesSubcommand {
|
||||
List,
|
||||
}
|
||||
|
||||
fn stage_str(stage: codex_core::features::Stage) -> &'static str {
|
||||
use codex_core::features::Stage;
|
||||
fn stage_str(stage: llmx_core::features::Stage) -> &'static str {
|
||||
use llmx_core::features::Stage;
|
||||
match stage {
|
||||
Stage::Experimental => "experimental",
|
||||
Stage::Beta => "beta",
|
||||
@@ -385,7 +385,7 @@ fn stage_str(stage: codex_core::features::Stage) -> &'static str {
|
||||
#[ctor::ctor]
|
||||
#[cfg(not(debug_assertions))]
|
||||
fn pre_main_hardening() {
|
||||
codex_process_hardening::pre_main_hardening();
|
||||
llmx_process_hardening::pre_main_hardening();
|
||||
}
|
||||
|
||||
fn main() -> anyhow::Result<()> {
|
||||
@@ -413,7 +413,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
||||
&mut interactive.config_overrides,
|
||||
root_config_overrides.clone(),
|
||||
);
|
||||
let exit_info = codex_tui::run_main(interactive, codex_linux_sandbox_exe).await?;
|
||||
let exit_info = llmx_tui::run_main(interactive, codex_linux_sandbox_exe).await?;
|
||||
handle_app_exit(exit_info)?;
|
||||
}
|
||||
Some(Subcommand::Exec(mut exec_cli)) => {
|
||||
@@ -421,10 +421,10 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
||||
&mut exec_cli.config_overrides,
|
||||
root_config_overrides.clone(),
|
||||
);
|
||||
codex_exec::run_main(exec_cli, codex_linux_sandbox_exe).await?;
|
||||
llmx_exec::run_main(exec_cli, codex_linux_sandbox_exe).await?;
|
||||
}
|
||||
Some(Subcommand::McpServer) => {
|
||||
codex_mcp_server::run_main(codex_linux_sandbox_exe, root_config_overrides).await?;
|
||||
llmx_mcp_server::run_main(codex_linux_sandbox_exe, root_config_overrides).await?;
|
||||
}
|
||||
Some(Subcommand::Mcp(mut mcp_cli)) => {
|
||||
// Propagate any root-level config overrides (e.g. `-c key=value`).
|
||||
@@ -433,16 +433,16 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
||||
}
|
||||
Some(Subcommand::AppServer(app_server_cli)) => match app_server_cli.subcommand {
|
||||
None => {
|
||||
codex_app_server::run_main(codex_linux_sandbox_exe, root_config_overrides).await?;
|
||||
llmx_app_server::run_main(codex_linux_sandbox_exe, root_config_overrides).await?;
|
||||
}
|
||||
Some(AppServerSubcommand::GenerateTs(gen_cli)) => {
|
||||
codex_app_server_protocol::generate_ts(
|
||||
llmx_app_server_protocol::generate_ts(
|
||||
&gen_cli.out_dir,
|
||||
gen_cli.prettier.as_deref(),
|
||||
)?;
|
||||
}
|
||||
Some(AppServerSubcommand::GenerateJsonSchema(gen_cli)) => {
|
||||
codex_app_server_protocol::generate_json(&gen_cli.out_dir)?;
|
||||
llmx_app_server_protocol::generate_json(&gen_cli.out_dir)?;
|
||||
}
|
||||
},
|
||||
Some(Subcommand::Resume(ResumeCommand {
|
||||
@@ -457,7 +457,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
||||
last,
|
||||
config_overrides,
|
||||
);
|
||||
let exit_info = codex_tui::run_main(interactive, codex_linux_sandbox_exe).await?;
|
||||
let exit_info = llmx_tui::run_main(interactive, codex_linux_sandbox_exe).await?;
|
||||
handle_app_exit(exit_info)?;
|
||||
}
|
||||
Some(Subcommand::Login(mut login_cli)) => {
|
||||
@@ -506,7 +506,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
||||
&mut cloud_cli.config_overrides,
|
||||
root_config_overrides.clone(),
|
||||
);
|
||||
codex_cloud_tasks::run_main(cloud_cli, codex_linux_sandbox_exe).await?;
|
||||
llmx_cloud_tasks::run_main(cloud_cli, codex_linux_sandbox_exe).await?;
|
||||
}
|
||||
Some(Subcommand::Sandbox(sandbox_args)) => match sandbox_args.cmd {
|
||||
SandboxCommand::Macos(mut seatbelt_cli) => {
|
||||
@@ -514,7 +514,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
||||
&mut seatbelt_cli.config_overrides,
|
||||
root_config_overrides.clone(),
|
||||
);
|
||||
codex_cli::debug_sandbox::run_command_under_seatbelt(
|
||||
llmx_cli::debug_sandbox::run_command_under_seatbelt(
|
||||
seatbelt_cli,
|
||||
codex_linux_sandbox_exe,
|
||||
)
|
||||
@@ -525,7 +525,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
||||
&mut landlock_cli.config_overrides,
|
||||
root_config_overrides.clone(),
|
||||
);
|
||||
codex_cli::debug_sandbox::run_command_under_landlock(
|
||||
llmx_cli::debug_sandbox::run_command_under_landlock(
|
||||
landlock_cli,
|
||||
codex_linux_sandbox_exe,
|
||||
)
|
||||
@@ -536,7 +536,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
||||
&mut windows_cli.config_overrides,
|
||||
root_config_overrides.clone(),
|
||||
);
|
||||
codex_cli::debug_sandbox::run_command_under_windows(
|
||||
llmx_cli::debug_sandbox::run_command_under_windows(
|
||||
windows_cli,
|
||||
codex_linux_sandbox_exe,
|
||||
)
|
||||
@@ -551,12 +551,12 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
||||
run_apply_command(apply_cli, None).await?;
|
||||
}
|
||||
Some(Subcommand::ResponsesApiProxy(args)) => {
|
||||
tokio::task::spawn_blocking(move || codex_responses_api_proxy::run_main(args))
|
||||
tokio::task::spawn_blocking(move || llmx_responses_api_proxy::run_main(args))
|
||||
.await??;
|
||||
}
|
||||
Some(Subcommand::StdioToUds(cmd)) => {
|
||||
let socket_path = cmd.socket_path;
|
||||
tokio::task::spawn_blocking(move || codex_stdio_to_uds::run(socket_path.as_path()))
|
||||
tokio::task::spawn_blocking(move || llmx_stdio_to_uds::run(socket_path.as_path()))
|
||||
.await??;
|
||||
}
|
||||
Some(Subcommand::Features(FeaturesCli { sub })) => match sub {
|
||||
@@ -581,7 +581,7 @@ async fn cli_main(codex_linux_sandbox_exe: Option<PathBuf>) -> anyhow::Result<()
|
||||
};
|
||||
|
||||
let config = Config::load_with_cli_overrides(cli_kv_overrides, overrides).await?;
|
||||
for def in codex_core::features::FEATURES.iter() {
|
||||
for def in llmx_core::features::FEATURES.iter() {
|
||||
let name = def.key;
|
||||
let stage = stage_str(def.stage);
|
||||
let enabled = config.features.enabled(def.id);
|
||||
@@ -686,8 +686,8 @@ fn print_completion(cmd: CompletionCommand) {
|
||||
mod tests {
|
||||
use super::*;
|
||||
use assert_matches::assert_matches;
|
||||
use codex_core::protocol::TokenUsage;
|
||||
use codex_protocol::ConversationId;
|
||||
use llmx_core::protocol::TokenUsage;
|
||||
use llmx_protocol::ConversationId;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
fn finalize_from_args(args: &[&str]) -> TuiCli {
|
||||
@@ -824,11 +824,11 @@ mod tests {
|
||||
assert_eq!(interactive.config_profile.as_deref(), Some("my-profile"));
|
||||
assert_matches!(
|
||||
interactive.sandbox_mode,
|
||||
Some(codex_common::SandboxModeCliArg::WorkspaceWrite)
|
||||
Some(llmx_common::SandboxModeCliArg::WorkspaceWrite)
|
||||
);
|
||||
assert_matches!(
|
||||
interactive.approval_policy,
|
||||
Some(codex_common::ApprovalModeCliArg::OnRequest)
|
||||
Some(llmx_common::ApprovalModeCliArg::OnRequest)
|
||||
);
|
||||
assert!(interactive.full_auto);
|
||||
assert_eq!(
|
||||
|
||||
@@ -5,21 +5,21 @@ use anyhow::Result;
|
||||
use anyhow::anyhow;
|
||||
use anyhow::bail;
|
||||
use clap::ArgGroup;
|
||||
use codex_common::CliConfigOverrides;
|
||||
use codex_common::format_env_display::format_env_display;
|
||||
use codex_core::config::Config;
|
||||
use codex_core::config::ConfigOverrides;
|
||||
use codex_core::config::edit::ConfigEditsBuilder;
|
||||
use codex_core::config::find_codex_home;
|
||||
use codex_core::config::load_global_mcp_servers;
|
||||
use codex_core::config::types::McpServerConfig;
|
||||
use codex_core::config::types::McpServerTransportConfig;
|
||||
use codex_core::features::Feature;
|
||||
use codex_core::mcp::auth::compute_auth_statuses;
|
||||
use codex_core::protocol::McpAuthStatus;
|
||||
use codex_rmcp_client::delete_oauth_tokens;
|
||||
use codex_rmcp_client::perform_oauth_login;
|
||||
use codex_rmcp_client::supports_oauth_login;
|
||||
use llmx_common::CliConfigOverrides;
|
||||
use llmx_common::format_env_display::format_env_display;
|
||||
use llmx_core::config::Config;
|
||||
use llmx_core::config::ConfigOverrides;
|
||||
use llmx_core::config::edit::ConfigEditsBuilder;
|
||||
use llmx_core::config::find_codex_home;
|
||||
use llmx_core::config::load_global_mcp_servers;
|
||||
use llmx_core::config::types::McpServerConfig;
|
||||
use llmx_core::config::types::McpServerTransportConfig;
|
||||
use llmx_core::features::Feature;
|
||||
use llmx_core::mcp::auth::compute_auth_statuses;
|
||||
use llmx_core::protocol::McpAuthStatus;
|
||||
use llmx_rmcp_client::delete_oauth_tokens;
|
||||
use llmx_rmcp_client::perform_oauth_login;
|
||||
use llmx_rmcp_client::supports_oauth_login;
|
||||
|
||||
/// [experimental] Launch Codex as an MCP server or manage configured MCP servers.
|
||||
///
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use codex_core::config::load_global_mcp_servers;
|
||||
use codex_core::config::types::McpServerTransportConfig;
|
||||
use llmx_core::config::load_global_mcp_servers;
|
||||
use llmx_core::config::types::McpServerTransportConfig;
|
||||
use predicates::str::contains;
|
||||
use pretty_assertions::assert_eq;
|
||||
use tempfile::TempDir;
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
use std::path::Path;
|
||||
|
||||
use anyhow::Result;
|
||||
use codex_core::config::edit::ConfigEditsBuilder;
|
||||
use codex_core::config::load_global_mcp_servers;
|
||||
use codex_core::config::types::McpServerTransportConfig;
|
||||
use llmx_core::config::edit::ConfigEditsBuilder;
|
||||
use llmx_core::config::load_global_mcp_servers;
|
||||
use llmx_core::config::types::McpServerTransportConfig;
|
||||
use predicates::prelude::PredicateBooleanExt;
|
||||
use predicates::str::contains;
|
||||
use pretty_assertions::assert_eq;
|
||||
|
||||
Reference in New Issue
Block a user