This is an automated email from the ASF dual-hosted git repository. morningman pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/doris-cli.git
commit 9a22771bad43fd7f10ac7c0028ea2b8f5034de48 Author: Mingyu Chen (Rayner) <[email protected]> AuthorDate: Fri May 29 12:13:08 2026 +0800 Remove VeloDB branding; rename error types to Doris* - Reword VeloDB textual mentions to Doris-only in README, Cargo.toml, config/products.toml, and code comments/error messages - Rename VeloError -> DorisError and VeloResult -> DorisResult across src/ - Genericize leftover velo-derived tokens: velo_err variable and the "velo::socks5" tracing target -> "doris::socks5" No "selectdb" references existed in the repo. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]> --- Cargo.toml | 2 +- README.md | 8 +++---- config/products.toml | 2 +- src/commands/auth.rs | 2 +- src/commands/profile/fetch.rs | 2 +- src/commands/profile/summary.rs | 2 +- src/config/environment.rs | 14 ++++++------ src/config/store.rs | 44 +++++++++++++++++++------------------- src/connection/http.rs | 34 ++++++++++++++--------------- src/connection/mysql.rs | 20 ++++++++--------- src/connection/socks5_forwarder.rs | 10 ++++----- src/error.rs | 26 +++++++++++----------- src/main.rs | 4 ++-- 13 files changed, 85 insertions(+), 85 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 25f9563..e008050 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,7 +8,7 @@ resolver = "3" name = "doriscli" version = "0.3.8" edition = "2021" -description = "Doris CLI — SQL, profiles, and tablet analysis against a Doris/VeloDB kernel" +description = "Doris CLI — SQL, profiles, and tablet analysis against a Doris kernel" [[bin]] name = "doriscli" diff --git a/README.md b/README.md index 83c80f5..f6958e0 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ -# doris-cli +# Apache Doris CLI -A fast, scriptable CLI for the **Apache Doris / VeloDB kernel**. It connects over the +A fast, scriptable CLI for the **Apache Doris kernel**. It connects over the MySQL protocol (+ the FE HTTP API), executes, and returns **structured JSON** — a "tool, not a brain": all the intelligence lives in the layer above (an agent, a script, your shell). Every command prints machine-readable output and exits; there @@ -93,7 +93,7 @@ doriscli auth remove <name> ``` `auth add` probes the FE HTTP port and, if it doesn't answer, suggests common -alternatives (8080 for VeloDB Cloud FEs, 8030/8040 for Apache Doris) so `profile` +alternatives (8080 for cloud FEs, 8030/8040 for self-hosted Apache Doris) so `profile` commands work later. ### `sql` — execute queries @@ -193,7 +193,7 @@ DORIS_HOST=fe.internal DORIS_USER=admin DORIS_PASSWORD=*** \ ## Connecting to a cloud-hosted kernel doris-cli talks to any reachable Doris FE — including a cloud cluster — as long as -you give it the resolved host/port. Compute-group routing (VeloDB Cloud) is handled +you give it the resolved host/port. Compute-group routing is handled by `--init-sql` (or `DORIS_INIT_SQL`), which runs `USE @<compute-group>` right after connecting: diff --git a/config/products.toml b/config/products.toml index c92b879..18c45db 100644 --- a/config/products.toml +++ b/config/products.toml @@ -1,5 +1,5 @@ [products.doris] binary = "doriscli" -about = "Doris CLI - SQL, profiles, and tablet analysis against a Doris/VeloDB kernel" +about = "Doris CLI - SQL, profiles, and tablet analysis against a Doris kernel" config_dir = ".doris" env_prefix = "DORIS" diff --git a/src/commands/auth.rs b/src/commands/auth.rs index 300fa59..8c63c10 100644 --- a/src/commands/auth.rs +++ b/src/commands/auth.rs @@ -95,7 +95,7 @@ async fn run_add(args: AddArgs, store: &mut Store) -> anyhow::Result<Value> { } fn common_http_ports_except(configured: u16) -> Vec<u16> { - // 8080: VeloDB Cloud FE HTTP (routed through Stream Load port). + // 8080: Cloud FE HTTP (routed through Stream Load port). // 8030: Apache Doris / self-hosted default. [8080, 8030, 8040] .into_iter() diff --git a/src/commands/profile/fetch.rs b/src/commands/profile/fetch.rs index e1698ba..866c5c9 100644 --- a/src/commands/profile/fetch.rs +++ b/src/commands/profile/fetch.rs @@ -52,7 +52,7 @@ impl fmt::Display for FetchFailure { "Could not fetch profile '{}'.\n\ REST v2 with is_all_node=true aggregates profiles across FEs server-side,\n\ so this usually means the HTTP port is wrong or the profile has been evicted.\n\ - VeloDB Cloud uses --http-port 8080; self-hosted Doris uses 8030.\n\ + Cloud deployments use --http-port 8080; self-hosted Doris uses 8030.\n\ Run `{} auth status` to check connectivity.\n\ Attempts:\n{}", self.query_id, diff --git a/src/commands/profile/summary.rs b/src/commands/profile/summary.rs index b3d1f4b..ed4d2e1 100644 --- a/src/commands/profile/summary.rs +++ b/src/commands/profile/summary.rs @@ -71,7 +71,7 @@ fn build_fallback_note(failure: &super::fetch::FetchFailure) -> String { .any(|a| a.result.starts_with("Connection failed")); if any_unreachable { return format!( - "HTTP endpoint unreachable on configured port. VeloDB Cloud uses \ + "HTTP endpoint unreachable on configured port. Cloud deployments use \ --http-port 8080; self-hosted Doris uses 8030. Run `{} auth status` \ to verify, or re-add auth with the right port.", failure.binary diff --git a/src/config/environment.rs b/src/config/environment.rs index 29d3b28..f9138ec 100644 --- a/src/config/environment.rs +++ b/src/config/environment.rs @@ -1,4 +1,4 @@ -use crate::error::{VeloError, VeloResult}; +use crate::error::{DorisError, DorisResult}; use crate::product::ProductProfile; use serde::{Deserialize, Serialize}; @@ -55,7 +55,7 @@ pub struct Socks5Config { impl Socks5Config { /// Build from env vars. Returns None unless both host and port are set. - /// user/pass default to "admin"/"admin" per VeloDB BYOC convention. + /// user/pass default to "admin"/"admin" by convention. pub fn from_env(product: &ProductProfile) -> Option<Self> { let host = std::env::var(product.env_key("SOCKS5_HOST")).ok()?; let port: u16 = std::env::var(product.env_key("SOCKS5_PORT")) @@ -75,22 +75,22 @@ impl Socks5Config { } /// Parse `user:pass@host:port` (matches the Go mysql-client reference). - pub fn parse_flag(s: &str) -> VeloResult<Self> { + pub fn parse_flag(s: &str) -> DorisResult<Self> { let (auth, hostport) = s.split_once('@').ok_or_else(|| { - VeloError::config(format!( + DorisError::config(format!( "--socks5 must be in 'user:pass@host:port' form, got '{s}'" )) })?; let (user, pass) = auth.split_once(':').ok_or_else(|| { - VeloError::config(format!("--socks5 auth must be 'user:pass', got '{auth}'")) + DorisError::config(format!("--socks5 auth must be 'user:pass', got '{auth}'")) })?; let (host, port_s) = hostport.rsplit_once(':').ok_or_else(|| { - VeloError::config(format!( + DorisError::config(format!( "--socks5 host must be 'host:port', got '{hostport}'" )) })?; let port: u16 = port_s.parse().map_err(|_| { - VeloError::config(format!("--socks5 port '{port_s}' is not a valid u16")) + DorisError::config(format!("--socks5 port '{port_s}' is not a valid u16")) })?; Ok(Socks5Config { host: host.to_string(), diff --git a/src/config/store.rs b/src/config/store.rs index 194f216..e966dfd 100644 --- a/src/config/store.rs +++ b/src/config/store.rs @@ -1,5 +1,5 @@ use crate::config::environment::{Environment, EnvironmentConfig, EnvironmentCredentials}; -use crate::error::{VeloError, VeloResult}; +use crate::error::{DorisError, DorisResult}; use crate::product::ProductProfile; use serde::{Deserialize, Serialize}; use std::collections::BTreeMap; @@ -78,32 +78,32 @@ impl Store { /// Load config from the product config directory (creates directory if needed). /// In stateless mode, returns an in-memory Store with no filesystem I/O. - pub fn load(product: &'static ProductProfile) -> VeloResult<Self> { + pub fn load(product: &'static ProductProfile) -> DorisResult<Self> { if Self::is_stateless(product) { return Ok(Self::stateless(product)); } let config_dir = Self::config_dir(product)?; std::fs::create_dir_all(&config_dir) - .map_err(|e| VeloError::config(format!("Failed to create config directory: {e}")))?; + .map_err(|e| DorisError::config(format!("Failed to create config directory: {e}")))?; let config_path = config_dir.join("config.toml"); let creds_path = config_dir.join("credentials.toml"); let config: ConfigFile = if config_path.exists() { let text = std::fs::read_to_string(&config_path) - .map_err(|e| VeloError::config(format!("Failed to read config: {e}")))?; + .map_err(|e| DorisError::config(format!("Failed to read config: {e}")))?; toml::from_str(&text) - .map_err(|e| VeloError::config(format!("Invalid config.toml: {e}")))? + .map_err(|e| DorisError::config(format!("Invalid config.toml: {e}")))? } else { ConfigFile::default() }; let credentials: CredentialsFile = if creds_path.exists() { let text = std::fs::read_to_string(&creds_path) - .map_err(|e| VeloError::config(format!("Failed to read credentials: {e}")))?; + .map_err(|e| DorisError::config(format!("Failed to read credentials: {e}")))?; toml::from_str(&text) - .map_err(|e| VeloError::config(format!("Invalid credentials.toml: {e}")))? + .map_err(|e| DorisError::config(format!("Invalid credentials.toml: {e}")))? } else { CredentialsFile::default() }; @@ -117,7 +117,7 @@ impl Store { } /// Resolve an environment by name, applying env var overrides. - pub fn resolve_env(&self, name: &str) -> VeloResult<Environment> { + pub fn resolve_env(&self, name: &str) -> DorisResult<Environment> { // Stateless shortcut — never touch config files. if Self::is_stateless(self.product) { return Ok(Self::resolve_stateless(self.product, name)); @@ -125,9 +125,9 @@ impl Store { let env_config = self.config.environments.get(name).ok_or_else(|| { if self.config.environments.is_empty() { - VeloError::AuthRequired + DorisError::AuthRequired } else { - VeloError::EnvNotFound { + DorisError::EnvNotFound { name: name.to_string(), } } @@ -180,7 +180,7 @@ impl Store { name: &str, config: EnvironmentConfig, creds: EnvironmentCredentials, - ) -> VeloResult<()> { + ) -> DorisResult<()> { self.config.environments.insert(name.to_string(), config); self.credentials .environments @@ -195,9 +195,9 @@ impl Store { } /// Set the default environment. - pub fn set_default(&mut self, name: &str) -> VeloResult<()> { + pub fn set_default(&mut self, name: &str) -> DorisResult<()> { if !self.config.environments.contains_key(name) { - return Err(VeloError::EnvNotFound { + return Err(DorisError::EnvNotFound { name: name.to_string(), }); } @@ -216,7 +216,7 @@ impl Store { } /// Remove an environment. - pub fn remove_env(&mut self, name: &str) -> VeloResult<()> { + pub fn remove_env(&mut self, name: &str) -> DorisResult<()> { self.config.environments.remove(name); self.credentials.environments.remove(name); if self.config.default_env.as_deref() == Some(name) { @@ -226,9 +226,9 @@ impl Store { } /// Save config and credentials to disk. - fn save(&self) -> VeloResult<()> { + fn save(&self) -> DorisResult<()> { let config_dir = self.config_dir.as_ref().ok_or_else(|| { - VeloError::config(format!( + DorisError::config(format!( "Cannot modify config in stateless mode ({} + {} set). \ Unset those env vars to use {}/ config files.", self.product.env_key("HOST"), @@ -238,17 +238,17 @@ impl Store { })?; let config_text = toml::to_string_pretty(&self.config) - .map_err(|e| VeloError::config(format!("Failed to serialize config: {e}")))?; + .map_err(|e| DorisError::config(format!("Failed to serialize config: {e}")))?; let creds_text = toml::to_string_pretty(&self.credentials) - .map_err(|e| VeloError::config(format!("Failed to serialize credentials: {e}")))?; + .map_err(|e| DorisError::config(format!("Failed to serialize credentials: {e}")))?; let config_path = config_dir.join("config.toml"); let creds_path = config_dir.join("credentials.toml"); std::fs::write(&config_path, config_text) - .map_err(|e| VeloError::config(format!("Failed to write config: {e}")))?; + .map_err(|e| DorisError::config(format!("Failed to write config: {e}")))?; std::fs::write(&creds_path, creds_text) - .map_err(|e| VeloError::config(format!("Failed to write credentials: {e}")))?; + .map_err(|e| DorisError::config(format!("Failed to write credentials: {e}")))?; // Set restrictive permissions on credentials file (Unix only) #[cfg(unix)] @@ -261,9 +261,9 @@ impl Store { Ok(()) } - fn config_dir(product: &ProductProfile) -> VeloResult<PathBuf> { + fn config_dir(product: &ProductProfile) -> DorisResult<PathBuf> { let home = - dirs::home_dir().ok_or_else(|| VeloError::config("Cannot determine home directory"))?; + dirs::home_dir().ok_or_else(|| DorisError::config("Cannot determine home directory"))?; Ok(home.join(&product.config_dir)) } } diff --git a/src/connection/http.rs b/src/connection/http.rs index 9ead709..de3e922 100644 --- a/src/connection/http.rs +++ b/src/connection/http.rs @@ -1,5 +1,5 @@ use crate::config::Environment; -use crate::error::{VeloError, VeloResult}; +use crate::error::{DorisError, DorisResult}; use serde_json::Value; pub struct HttpConnection { @@ -69,7 +69,7 @@ impl HttpConnection { } Err(e) => { tracing::warn!( - target = "velo::socks5", + target = "doris::socks5", "Invalid SOCKS5 proxy URL '{proxy_url}': {e} — HTTP will go direct" ); } @@ -164,10 +164,10 @@ fn short_err(e: &reqwest::Error) -> String { } impl HttpConnection { - /// Fetch profile text via REST v2 Manager API (works on VeloDB Cloud port 8080). + /// Fetch profile text via REST v2 Manager API (works on cloud port 8080). /// Endpoint: GET /rest/v2/manager/query/profile/text/{query_id}?is_all_node=true /// Response: {"msg":"success","code":0,"data":{"profile":"Summary:\n..."}} - pub async fn get_profile_text_v2(&self, query_id: &str) -> VeloResult<String> { + pub async fn get_profile_text_v2(&self, query_id: &str) -> DorisResult<String> { let url = format!( "{}/rest/v2/manager/query/profile/text/{}?is_all_node=true", self.base_url, query_id @@ -180,7 +180,7 @@ impl HttpConnection { .send() .await .map_err(|e| { - VeloError::connection_with_source( + DorisError::connection_with_source( format!("REST v2 profile request failed: {url}"), e, ) @@ -189,10 +189,10 @@ impl HttpConnection { let status = resp.status().as_u16(); if status != 200 { let body = resp.text().await.unwrap_or_default(); - return Err(VeloError::Http { status, body }); + return Err(DorisError::Http { status, body }); } - let json: Value = resp.json().await.map_err(|e| VeloError::Http { + let json: Value = resp.json().await.map_err(|e| DorisError::Http { status, body: format!("Failed to parse JSON response: {e}"), })?; @@ -205,7 +205,7 @@ impl HttpConnection { .and_then(|v| v.as_str()) .or_else(|| json.get("msg").and_then(|v| v.as_str())) .unwrap_or("Unknown error"); - return Err(VeloError::Http { + return Err(DorisError::Http { status, body: msg.to_string(), }); @@ -216,12 +216,12 @@ impl HttpConnection { .and_then(|d| d.get("profile")) .and_then(|p| p.as_str()) .map(|s| s.to_string()) - .ok_or_else(|| VeloError::Parse("No 'profile' field in REST v2 response".to_string())) + .ok_or_else(|| DorisError::Parse("No 'profile' field in REST v2 response".to_string())) } /// Fetch profile text from legacy FE HTTP API. /// Endpoint: GET /api/profile/text/{query_id} - pub async fn get_profile_text(&self, query_id: &str) -> VeloResult<String> { + pub async fn get_profile_text(&self, query_id: &str) -> DorisResult<String> { let url = format!("{}/api/profile/text/{}", self.base_url, query_id); let resp = self .client @@ -230,17 +230,17 @@ impl HttpConnection { .send() .await .map_err(|e| { - VeloError::connection_with_source(format!("HTTP request failed: {url}"), e) + DorisError::connection_with_source(format!("HTTP request failed: {url}"), e) })?; let status = resp.status().as_u16(); - let body = resp.text().await.map_err(|e| VeloError::Http { + let body = resp.text().await.map_err(|e| DorisError::Http { status, body: e.to_string(), })?; if status != 200 { - return Err(VeloError::Http { status, body }); + return Err(DorisError::Http { status, body }); } Ok(body) @@ -249,7 +249,7 @@ impl HttpConnection { /// Fetch list of recent queries via REST v2 Manager API. /// Endpoint: GET /rest/v2/manager/query/query_info?is_all_node=true #[allow(dead_code)] - pub async fn get_query_list(&self) -> VeloResult<Value> { + pub async fn get_query_list(&self) -> DorisResult<Value> { let url = format!( "{}/rest/v2/manager/query/query_info?is_all_node=true", self.base_url @@ -262,10 +262,10 @@ impl HttpConnection { .send() .await .map_err(|e| { - VeloError::connection_with_source(format!("REST v2 query list failed: {url}"), e) + DorisError::connection_with_source(format!("REST v2 query list failed: {url}"), e) })?; - let json: Value = resp.json().await.map_err(|e| VeloError::Http { + let json: Value = resp.json().await.map_err(|e| DorisError::Http { status: 0, body: format!("Failed to parse JSON: {e}"), })?; @@ -275,7 +275,7 @@ impl HttpConnection { /// Test HTTP connectivity. #[allow(dead_code)] - pub async fn ping(&self) -> VeloResult<u128> { + pub async fn ping(&self) -> DorisResult<u128> { let start = std::time::Instant::now(); let url = format!("{}/api/health", self.base_url); let _ = self diff --git a/src/connection/mysql.rs b/src/connection/mysql.rs index 81174af..09240f7 100644 --- a/src/connection/mysql.rs +++ b/src/connection/mysql.rs @@ -1,6 +1,6 @@ use crate::config::Environment; use crate::connection::socks5_forwarder::Socks5Forwarder; -use crate::error::{VeloError, VeloResult}; +use crate::error::{DorisError, DorisResult}; use mysql_async::prelude::*; use mysql_async::{Conn, Opts, OptsBuilder, Row, Value as MysqlValue}; use serde_json::{Map, Value}; @@ -19,9 +19,9 @@ pub struct QueryResult { } impl MysqlConnection { - /// Connect to a Doris/VeloDB instance. Routes through SOCKS5 when `env.socks5` + /// Connect to a Doris instance. Routes through SOCKS5 when `env.socks5` /// is set, via a loopback forwarder (mysql_async 0.34 has no native proxy hook). - pub async fn connect(env: &Environment) -> VeloResult<Self> { + pub async fn connect(env: &Environment) -> DorisResult<Self> { let (dial_host, dial_port, forwarder, error_hint) = if let Some(s5) = &env.socks5 { let fwd = Socks5Forwarder::spawn(s5, env.host.clone(), env.mysql_port).await?; let port = fwd.local_addr.port(); @@ -40,7 +40,7 @@ impl MysqlConnection { let pool = mysql_async::Pool::new(Opts::from(opts)); let conn = pool.get_conn().await.map_err(|e| { - VeloError::connection_with_source( + DorisError::connection_with_source( format!( "Failed to connect to {}:{} as '{}'{}", env.host, env.mysql_port, env.user, error_hint @@ -61,12 +61,12 @@ impl MysqlConnection { } /// Execute a SQL query and return structured results. - pub async fn query(&mut self, sql: &str) -> VeloResult<QueryResult> { + pub async fn query(&mut self, sql: &str) -> DorisResult<QueryResult> { let rows: Vec<Row> = self .conn .query(sql) .await - .map_err(|e| VeloError::sql(format!("{e}")))?; + .map_err(|e| DorisError::sql(format!("{e}")))?; if rows.is_empty() { return Ok(QueryResult { @@ -99,16 +99,16 @@ impl MysqlConnection { } /// Execute a statement that doesn't return results (SET, USE, etc.). - pub async fn exec(&mut self, sql: &str) -> VeloResult<()> { + pub async fn exec(&mut self, sql: &str) -> DorisResult<()> { self.conn .query_drop(sql) .await - .map_err(|e| VeloError::sql(format!("{e}")))?; + .map_err(|e| DorisError::sql(format!("{e}")))?; Ok(()) } /// Get the last query ID from the current session. - pub async fn last_query_id(&mut self) -> VeloResult<String> { + pub async fn last_query_id(&mut self) -> DorisResult<String> { let result = self.query("SELECT last_query_id()").await?; if let Some(row) = result.rows.first() { if let Some(Value::String(qid)) = row.values().next() { @@ -119,7 +119,7 @@ impl MysqlConnection { } /// Test connection by running SELECT 1, returns latency in ms. - pub async fn ping(&mut self) -> VeloResult<u128> { + pub async fn ping(&mut self) -> DorisResult<u128> { let start = std::time::Instant::now(); self.query("SELECT 1").await?; Ok(start.elapsed().as_millis()) diff --git a/src/connection/socks5_forwarder.rs b/src/connection/socks5_forwarder.rs index b4cd9d7..cf01245 100644 --- a/src/connection/socks5_forwarder.rs +++ b/src/connection/socks5_forwarder.rs @@ -10,7 +10,7 @@ //! on the connection struct and let Drop abort the accept task. use crate::config::Socks5Config; -use crate::error::{VeloError, VeloResult}; +use crate::error::{DorisError, DorisResult}; use std::net::SocketAddr; use tokio::net::TcpListener; use tokio::task::JoinHandle; @@ -28,15 +28,15 @@ impl Socks5Forwarder { socks5: &Socks5Config, target_host: String, target_port: u16, - ) -> VeloResult<Self> { + ) -> DorisResult<Self> { let listener = TcpListener::bind("127.0.0.1:0").await.map_err(|e| { - VeloError::connection_with_source( + DorisError::connection_with_source( "Failed to bind SOCKS5 forwarder loopback listener".to_string(), e, ) })?; let local_addr = listener.local_addr().map_err(|e| { - VeloError::connection_with_source( + DorisError::connection_with_source( "Failed to read SOCKS5 forwarder local addr".to_string(), e, ) @@ -65,7 +65,7 @@ impl Socks5Forwarder { Ok(s) => s, Err(e) => { tracing::warn!( - target = "velo::socks5", + target = "doris::socks5", "SOCKS5 dial to {host}:{port} via {proxy_addr} failed: {e}" ); return; diff --git a/src/error.rs b/src/error.rs index d1628ab..66821b6 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,7 +1,7 @@ use crate::product::ProductProfile; #[derive(Debug, thiserror::Error)] -pub enum VeloError { +pub enum DorisError { #[error("Connection failed: {message}")] Connection { message: String, @@ -32,53 +32,53 @@ pub enum VeloError { Io(#[from] std::io::Error), } -impl VeloError { +impl DorisError { pub fn connection_with_source( msg: impl Into<String>, src: impl std::error::Error + Send + Sync + 'static, ) -> Self { - VeloError::Connection { + DorisError::Connection { message: msg.into(), source: Some(Box::new(src)), } } pub fn sql(msg: impl Into<String>) -> Self { - VeloError::Sql { + DorisError::Sql { message: msg.into(), } } pub fn config(msg: impl Into<String>) -> Self { - VeloError::Config(msg.into()) + DorisError::Config(msg.into()) } #[allow(dead_code)] pub fn parse(msg: impl Into<String>) -> Self { - VeloError::Parse(msg.into()) + DorisError::Parse(msg.into()) } } -/// Result type alias for VeloError -pub type VeloResult<T> = Result<T, VeloError>; +/// Result type alias for DorisError +pub type DorisResult<T> = Result<T, DorisError>; -/// Format a VeloError for user-facing display -impl VeloError { +/// Format a DorisError for user-facing display +impl DorisError { pub fn user_message(&self, product: &ProductProfile) -> String { match self { - VeloError::Connection { message, .. } => { + DorisError::Connection { message, .. } => { format!( "Error: {message}\n\nCheck your connection settings with `{} auth status`.", product.binary ) } - VeloError::EnvNotFound { name } => { + DorisError::EnvNotFound { name } => { format!( "Error: Environment '{name}' not found.\n\nRun `{} auth list` to see available environments.", product.binary ) } - VeloError::AuthRequired => { + DorisError::AuthRequired => { format!( "Error: No authentication configured.\n\nRun `{} auth add <name> --host <host> --user <user> --password <pass>` to get started.", product.binary diff --git a/src/main.rs b/src/main.rs index ca2454e..85b7295 100644 --- a/src/main.rs +++ b/src/main.rs @@ -39,8 +39,8 @@ async fn main_for(product: &'static ProductProfile) { } } Err(e) => { - if let Some(velo_err) = e.downcast_ref::<crate::error::VeloError>() { - eprintln!("{}", velo_err.user_message(product)); + if let Some(doris_err) = e.downcast_ref::<crate::error::DorisError>() { + eprintln!("{}", doris_err.user_message(product)); } else { eprintln!("Error: {e}"); } --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
