diff --git a/examples/quickstart/Cargo.toml b/examples/quickstart/Cargo.toml index fec215bd..d3c5022d 100644 --- a/examples/quickstart/Cargo.toml +++ b/examples/quickstart/Cargo.toml @@ -11,8 +11,8 @@ authors = [ actix-web = "3.3.2" anyhow = "1.0.36" async-std = { version = "1.8.0", features = ["attributes"] } -#sqlx = { path = "../../sqlx", features = ["tokio", "mysql", "blocking", "async-std", "actix"] } -sqlx = { path = "../../sqlx", features = ["tokio", "mysql"] } tokio = { version = "1.0.1", features = ["rt", "rt-multi-thread", "macros"] } log = "0.4" env_logger = "0.8.2" +#sqlx = { path = "../../sqlx", features = ["tokio", "mysql"] } +sqlx = { path = "../../sqlx", features = ["blocking", "mysql"] } diff --git a/examples/quickstart/src/main.rs b/examples/quickstart/src/main.rs index 481d7111..3ffa03b6 100644 --- a/examples/quickstart/src/main.rs +++ b/examples/quickstart/src/main.rs @@ -1,9 +1,19 @@ use sqlx::mysql::MySqlConnection; use sqlx::prelude::*; -#[tokio::main] -async fn main() -> anyhow::Result<()> { - let _conn = ::connect("mysql://root:password@localhost:3307").await?; +// #[tokio::main] +// async fn main() -> anyhow::Result<()> { +// env_logger::try_init()?; +// +// let _conn = ::connect("mysql://root:password@localhost").await?; +// +// Ok(()) +// } + +fn main() -> anyhow::Result<()> { + env_logger::try_init()?; + + let _conn = ::connect("mysql://root:password@localhost")?; Ok(()) } diff --git a/sqlx-core/src/connection.rs b/sqlx-core/src/connection.rs index 94f0813f..f51e1b67 100644 --- a/sqlx-core/src/connection.rs +++ b/sqlx-core/src/connection.rs @@ -46,6 +46,7 @@ where /// ``` /// #[cfg(feature = "async")] + #[must_use] fn connect(url: &str) -> BoxFuture<'_, crate::Result> where Self: Sized, diff --git a/sqlx-core/src/io/buf.rs b/sqlx-core/src/io/buf.rs index b807673c..838b2662 100644 --- a/sqlx-core/src/io/buf.rs +++ b/sqlx-core/src/io/buf.rs @@ -4,14 +4,15 @@ use bytes::{Buf, Bytes}; use bytestring::ByteString; use memchr::memchr; -// UNSAFE: _unchecked string methods -// intended for use when the protocol is *known* to always produce -// valid UTF-8 data - +#[allow(clippy::module_name_repetitions)] pub trait BufExt: Buf { + /// # Safety + /// This function is unsafe because it does not check the bytes that are read are valid UTF-8. #[allow(unsafe_code)] unsafe fn get_str_unchecked(&mut self, n: usize) -> ByteString; + /// # Safety + /// This function is unsafe because it does not check the bytes that are read are valid UTF-8. #[allow(unsafe_code)] unsafe fn get_str_nul_unchecked(&mut self) -> io::Result; } diff --git a/sqlx-core/src/io/buf_stream.rs b/sqlx-core/src/io/buf_stream.rs index 089055d1..681be40f 100644 --- a/sqlx-core/src/io/buf_stream.rs +++ b/sqlx-core/src/io/buf_stream.rs @@ -123,7 +123,7 @@ macro_rules! read { #[cfg(feature = "async")] impl BufStream where - S: AsyncRead + AsyncWrite + Unpin, + S: AsyncRead + AsyncWrite + Send + Unpin, { pub async fn flush_async(&mut self) -> crate::Result<()> { // write as much as we can each time and move the cursor as we write from the buffer diff --git a/sqlx-core/src/io/write.rs b/sqlx-core/src/io/write.rs index 272d978b..0934b13b 100644 --- a/sqlx-core/src/io/write.rs +++ b/sqlx-core/src/io/write.rs @@ -1,3 +1,4 @@ +#[allow(clippy::module_name_repetitions)] pub trait WriteExt { fn write_str_nul(&mut self, s: &str); fn write_maybe_str_nul(&mut self, s: Option<&str>); diff --git a/sqlx-core/src/lib.rs b/sqlx-core/src/lib.rs index 26a542f5..4ea61584 100644 --- a/sqlx-core/src/lib.rs +++ b/sqlx-core/src/lib.rs @@ -6,13 +6,11 @@ #![warn(rust_2018_idioms)] #![warn(future_incompatible)] #![warn(clippy::pedantic)] -#![warn(clippy::cargo_common_metadata)] #![warn(clippy::multiple_crate_versions)] #![warn(clippy::cognitive_complexity)] #![warn(clippy::future_not_send)] #![warn(clippy::missing_const_for_fn)] #![warn(clippy::needless_borrow)] -#![warn(clippy::redundant_pub_crate)] #![warn(clippy::string_lit_as_bytes)] #![warn(clippy::use_self)] #![warn(clippy::useless_let_if_seq)] diff --git a/sqlx-core/src/runtime.rs b/sqlx-core/src/runtime.rs index 494d506c..172edc3f 100644 --- a/sqlx-core/src/runtime.rs +++ b/sqlx-core/src/runtime.rs @@ -30,6 +30,7 @@ pub trait Runtime: 'static + Send + Sync { } #[cfg(feature = "async")] +#[allow(clippy::module_name_repetitions)] pub trait AsyncRuntime: Runtime { /// Opens a TCP connection to a remote host at the specified port. fn connect_tcp( diff --git a/sqlx-core/src/runtime/mock.rs b/sqlx-core/src/runtime/mock.rs index 433221d0..22af2de3 100644 --- a/sqlx-core/src/runtime/mock.rs +++ b/sqlx-core/src/runtime/mock.rs @@ -19,6 +19,7 @@ pub struct Mock; #[derive(Debug)] #[doc(hidden)] +#[allow(clippy::module_name_repetitions)] pub struct MockStream { port: u16, rbuf: BytesMut, @@ -58,6 +59,7 @@ impl crate::blocking::Runtime for Mock { } impl Mock { + #[must_use] pub fn stream() -> MockStream { let port = MOCK_STREAM_PORT.fetch_add(1, Ordering::SeqCst) + 1; @@ -74,7 +76,8 @@ impl Mock { } impl MockStream { - pub fn port(&self) -> u16 { + #[must_use] + pub const fn port(&self) -> u16 { self.port } } @@ -97,7 +100,8 @@ impl std::io::Read for MockStream { } // no bytes in the buffer, ask the channel for more - let message = self.read.recv().map_err(|_| std::io::ErrorKind::ConnectionAborted)?; + #[allow(clippy::map_err_ignore)] + let message = self.read.recv().map_err(|_err| std::io::ErrorKind::ConnectionAborted)?; self.rbuf.extend_from_slice(&message); // loop around and now send out this message diff --git a/sqlx-mysql/src/io/buf.rs b/sqlx-mysql/src/io/buf.rs index 41b7f7b1..a031974c 100644 --- a/sqlx-mysql/src/io/buf.rs +++ b/sqlx-mysql/src/io/buf.rs @@ -39,6 +39,7 @@ impl MySqlBufExt for Bytes { #[allow(unsafe_code)] unsafe fn get_str_lenenc_unchecked(&mut self) -> ByteString { + #[allow(clippy::cast_possible_truncation)] let len = self.get_uint_lenenc() as usize; self.get_str_unchecked(len) @@ -50,6 +51,7 @@ impl MySqlBufExt for Bytes { } fn get_bytes_lenenc(&mut self) -> Bytes { + #[allow(clippy::cast_possible_truncation)] let len = self.get_uint_lenenc() as usize; self.split_to(len) diff --git a/sqlx-mysql/src/io/write.rs b/sqlx-mysql/src/io/write.rs index b631610e..2396f2b1 100644 --- a/sqlx-mysql/src/io/write.rs +++ b/sqlx-mysql/src/io/write.rs @@ -13,16 +13,22 @@ impl MySqlWriteExt for Vec { if value < 251 { // if the value is < 251, it is stored as a 1-byte integer + + #[allow(clippy::cast_possible_truncation)] self.push(value as u8); } else if value < 0x1_00_00 { // if the value is ≥ 251 and < (2 ** 16), it is stored as fc + 2-byte integer self.reserve(3); self.push(0xfc); + + #[allow(clippy::cast_possible_truncation)] self.extend_from_slice(&(value as u16).to_le_bytes()); } else if value < 0x1_00_00_00 { // if the value is ≥ (2 ** 16) and < (2 ** 24), it is stored as fd + 3-byte integer self.reserve(4); self.push(0xfd); + + #[allow(clippy::cast_possible_truncation)] self.extend_from_slice(&(value as u32).to_le_bytes()[..3]); } else { // if the value is ≥ (2 ** 24) and < (2 ** 64) it is stored as fe + 8-byte integer diff --git a/sqlx-mysql/src/lib.rs b/sqlx-mysql/src/lib.rs index 402ff353..eed1c02d 100644 --- a/sqlx-mysql/src/lib.rs +++ b/sqlx-mysql/src/lib.rs @@ -8,13 +8,11 @@ #![warn(rust_2018_idioms)] #![warn(future_incompatible)] #![warn(clippy::pedantic)] -#![warn(clippy::cargo_common_metadata)] #![warn(clippy::multiple_crate_versions)] #![warn(clippy::cognitive_complexity)] #![warn(clippy::future_not_send)] #![warn(clippy::missing_const_for_fn)] #![warn(clippy::needless_borrow)] -#![warn(clippy::redundant_pub_crate)] #![warn(clippy::string_lit_as_bytes)] #![warn(clippy::use_self)] #![warn(clippy::useless_let_if_seq)] diff --git a/sqlx-mysql/src/options.rs b/sqlx-mysql/src/options.rs index fe9c8bdb..fd61fbd1 100644 --- a/sqlx-mysql/src/options.rs +++ b/sqlx-mysql/src/options.rs @@ -26,6 +26,7 @@ mod parse; /// /// - Only a single host is supported. /// +#[allow(clippy::module_name_repetitions)] pub struct MySqlConnectOptions where Rt: Runtime, @@ -84,41 +85,49 @@ where Rt: Runtime, { /// Returns the hostname of the database server. + #[must_use] pub fn get_host(&self) -> &str { - self.address.as_ref().left().map(|(host, _)| &**host).unwrap_or(default::HOST) + self.address.as_ref().left().map_or(default::HOST, |(host, _)| &**host) } /// Returns the TCP port number of the database server. + #[must_use] pub fn get_port(&self) -> u16 { - self.address.as_ref().left().map(|(_, port)| *port).unwrap_or(default::PORT) + self.address.as_ref().left().map_or(default::PORT, |(_, port)| *port) } /// Returns the path to the Unix domain socket, if one is configured. + #[must_use] pub fn get_socket(&self) -> Option<&Path> { - self.address.as_ref().right().map(|buf| buf.as_path()) + self.address.as_ref().right().map(PathBuf::as_path) } /// Returns the default database name. + #[must_use] pub fn get_database(&self) -> Option<&str> { self.database.as_deref() } /// Returns the username to be used for authentication. + #[must_use] pub fn get_username(&self) -> Option<&str> { self.username.as_deref() } /// Returns the password to be used for authentication. + #[must_use] pub fn get_password(&self) -> Option<&str> { self.password.as_deref() } /// Returns the character set for the connection. + #[must_use] pub fn get_charset(&self) -> &str { &self.charset } /// Returns the timezone for the connection. + #[must_use] pub fn get_timezone(&self) -> &str { &self.timezone } diff --git a/sqlx-mysql/src/options/default.rs b/sqlx-mysql/src/options/default.rs index 289a0b01..42b845e2 100644 --- a/sqlx-mysql/src/options/default.rs +++ b/sqlx-mysql/src/options/default.rs @@ -31,6 +31,7 @@ where Rt: Runtime, { /// Creates a default set of options ready for configuration. + #[must_use] pub fn new() -> Self { Self::default() } diff --git a/sqlx-mysql/src/protocol/auth_plugin.rs b/sqlx-mysql/src/protocol/auth_plugin.rs index 59eb05ac..36e398af 100644 --- a/sqlx-mysql/src/protocol/auth_plugin.rs +++ b/sqlx-mysql/src/protocol/auth_plugin.rs @@ -1,6 +1,5 @@ use std::error::Error as StdError; use std::fmt::Debug; -use std::str::FromStr; use bytes::buf::Chain; use bytes::Bytes; @@ -34,10 +33,8 @@ pub(crate) trait AuthPlugin: 'static + Debug + Send + Sync { ) -> Result>>; } -impl FromStr for Box { - type Err = Error; - - fn from_str(s: &str) -> Result { +impl dyn AuthPlugin { + pub(crate) fn parse(s: &str) -> Result> { match s { _ if s == CachingSha2AuthPlugin.name() => Ok(Box::new(CachingSha2AuthPlugin)), _ if s == Sha256AuthPlugin.name() => Ok(Box::new(Sha256AuthPlugin)), @@ -68,7 +65,7 @@ fn err_msg(plugin: &'static str, message: &str) -> Error { )) } -fn err(plugin: &'static str, error: E) -> Error +fn err(plugin: &'static str, error: &E) -> Error where E: StdError, { diff --git a/sqlx-mysql/src/protocol/auth_plugin/caching_sha2.rs b/sqlx-mysql/src/protocol/auth_plugin/caching_sha2.rs index d1ab6175..4932e2d6 100644 --- a/sqlx-mysql/src/protocol/auth_plugin/caching_sha2.rs +++ b/sqlx-mysql/src/protocol/auth_plugin/caching_sha2.rs @@ -65,7 +65,7 @@ impl super::AuthPlugin for CachingSha2AuthPlugin { AUTH_CONTINUE => { // ruh roh, we need to ask for the RSA public key, so we can // encrypt our password directly and send it - return Ok(Some(vec![0x2_u8])); + Ok(Some(vec![0x2_u8])) } _ => { diff --git a/sqlx-mysql/src/protocol/auth_plugin/rsa.rs b/sqlx-mysql/src/protocol/auth_plugin/rsa.rs index 2f086229..d6b21bc6 100644 --- a/sqlx-mysql/src/protocol/auth_plugin/rsa.rs +++ b/sqlx-mysql/src/protocol/auth_plugin/rsa.rs @@ -23,29 +23,29 @@ pub(crate) fn encrypt( super::xor_eq(&mut pass, &*nonce); // client sends an RSA encrypted password - let pkey = parse_rsa_pub_key(plugin, key)?; + let public = parse_rsa_pub_key(plugin, key)?; let padding = PaddingScheme::new_oaep::(); - pkey.encrypt(&mut rng(), padding, &pass[..]).map_err(|err| super::err(plugin, err)) + public.encrypt(&mut rng(), padding, &pass[..]).map_err(|err| super::err(plugin, &err)) } // https://docs.rs/rsa/0.3.0/rsa/struct.RSAPublicKey.html?search=#example-1 fn parse_rsa_pub_key(plugin: &'static str, key: &[u8]) -> Result { - let key = from_utf8(key).map_err(|err| super::err(plugin, err))?; + let key = from_utf8(key).map_err(|err| super::err(plugin, &err))?; // Takes advantage of the knowledge that we know // we are receiving a PKCS#8 RSA Public Key at all // times from MySQL let encoded = - key.lines().filter(|line| !line.starts_with("-")).fold(String::new(), |mut data, line| { - data.push_str(&line); + key.lines().filter(|line| !line.starts_with('-')).fold(String::new(), |mut data, line| { + data.push_str(line); data }); - let der = base64::decode(&encoded).map_err(|err| super::err(plugin, err))?; + let der = base64::decode(&encoded).map_err(|err| super::err(plugin, &err))?; - RSAPublicKey::from_pkcs8(&der).map_err(|err| super::err(plugin, err)) + RSAPublicKey::from_pkcs8(&der).map_err(|err| super::err(plugin, &err)) } fn to_asciz(s: &str) -> Vec { diff --git a/sqlx-mysql/src/protocol/auth_switch.rs b/sqlx-mysql/src/protocol/auth_switch.rs index 1fd84ca4..772b79c3 100644 --- a/sqlx-mysql/src/protocol/auth_switch.rs +++ b/sqlx-mysql/src/protocol/auth_switch.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use bytes::{buf::Chain, Buf, Bytes}; use sqlx_core::io::{BufExt, Deserialize}; use sqlx_core::Result; @@ -32,7 +30,7 @@ impl Deserialize<'_, Capabilities> for AuthSwitch { let plugin_data = buf.chain(Bytes::new()); - let plugin = >::from_str(&*name)?; + let plugin = AuthPlugin::parse(&*name)?; Ok(Self { plugin, plugin_data }) } diff --git a/sqlx-mysql/src/protocol/capabilities.rs b/sqlx-mysql/src/protocol/capabilities.rs index 8e47ed7b..6382ca18 100644 --- a/sqlx-mysql/src/protocol/capabilities.rs +++ b/sqlx-mysql/src/protocol/capabilities.rs @@ -5,76 +5,76 @@ bitflags::bitflags! { pub struct Capabilities: u64 { // use the improved version of "old password auth" // assumed to be set since 4.1 - const LONG_PASSWORD = 0x00000001; + const LONG_PASSWORD = 0x0000_0001; // send found (read: matched) rows instead of affected rows in the EOF packet - const FOUND_ROWS = 0x00000002; + const FOUND_ROWS = 0x0000_0002; // longer flags for column metadata // not used if PROTOCOL_41 is used (long flags are always received) - const LONG_FLAG = 0x00000004; + const LONG_FLAG = 0x0000_0004; // database (schema) name can be specified on connect in Handshake Response Packet - const CONNECT_WITH_DB = 0x00000008; + const CONNECT_WITH_DB = 0x0000_0008; // do not permit `database.table.column` - const NO_SCHEMA = 0x00000010; + const NO_SCHEMA = 0x0000_0010; // compression protocol supported // todo: expose in MySqlConnectOptions - const COMPRESS = 0x00000020; + const COMPRESS = 0x0000_0020; // legacy flag to enable special ODBC handling // no handling since MySQL v3.22 - const ODBC = 0x00000040; + const ODBC = 0x0000_0040; // enable LOAD DATA LOCAL - const LOCAL_FILES = 0x00000080; + const LOCAL_FILES = 0x0000_0080; // SQL parser can ignore spaces before '(' - const IGNORE_SPACE = 0x00000100; + const IGNORE_SPACE = 0x0000_0100; // uses the 4.1+ protocol - const PROTOCOL_41 = 0x00000200; + const PROTOCOL_41 = 0x0000_0200; // this is an interactive client // wait_timeout versus wait_interactive_timeout. - const INTERACTIVE = 0x00000400; + const INTERACTIVE = 0x0000_0400; // use SSL encryption for this session - const SSL = 0x00000800; + const SSL = 0x0000_0800; // EOF packets will contain transaction status flags - const TRANSACTIONS = 0x00002000; + const TRANSACTIONS = 0x0000_2000; // support native 4.1+ authentication - const SECURE_CONNECTION = 0x00008000; + const SECURE_CONNECTION = 0x0000_8000; // can handle multiple statements in COM_QUERY and COM_STMT_PREPARE - const MULTI_STATEMENTS = 0x00010000; + const MULTI_STATEMENTS = 0x0001_0000; // can send multiple result sets for COM_QUERY - const MULTI_RESULTS = 0x00020000; + const MULTI_RESULTS = 0x0002_0000; // can send multiple result sets for COM_STMT_EXECUTE - const PS_MULTI_RESULTS = 0x00040000; + const PS_MULTI_RESULTS = 0x0004_0000; // supports authentication plugins - const PLUGIN_AUTH = 0x00080000; + const PLUGIN_AUTH = 0x0008_0000; // permits connection attributes - const CONNECT_ATTRS = 0x00100000; + const CONNECT_ATTRS = 0x0010_0000; // enable authentication response packet to be larger than 255 bytes. - const PLUGIN_AUTH_LENENC_DATA = 0x00200000; + const PLUGIN_AUTH_LENENC_DATA = 0x0020_0000; // can handle connection for a user account with expired passwords - const CAN_HANDLE_EXPIRED_PASSWORDS = 0x00400000; + const CAN_HANDLE_EXPIRED_PASSWORDS = 0x0040_0000; // capable of handling server state change information in an OK packet - const SESSION_TRACK = 0x00800000; + const SESSION_TRACK = 0x0080_0000; // client no longer needs EOF_Packet and will use OK_Packet instead. - const DEPRECATE_EOF = 0x01000000; + const DEPRECATE_EOF = 0x0100_0000; } } diff --git a/sqlx-mysql/src/protocol/handshake.rs b/sqlx-mysql/src/protocol/handshake.rs index 4f4183f7..2ca377c3 100644 --- a/sqlx-mysql/src/protocol/handshake.rs +++ b/sqlx-mysql/src/protocol/handshake.rs @@ -1,5 +1,3 @@ -use std::str::FromStr; - use bytes::buf::Chain; use bytes::{Buf, Bytes}; use bytestring::ByteString; @@ -103,7 +101,7 @@ impl Deserialize<'_, Capabilities> for Handshake { // read to NUL or read to the end if we can't find a NUL - let auth_plugin_name_end = memchr(b'\0', &buf).unwrap_or(buf.len()); + let auth_plugin_name_end = memchr(b'\0', &buf).unwrap_or_else(|| buf.len()); // UNSAFE: auth plugin names are known to be ASCII #[allow(unsafe_code)] @@ -123,7 +121,7 @@ impl Deserialize<'_, Capabilities> for Handshake { status, auth_plugin_data: auth_plugin_data_1.chain(auth_plugin_data_2), auth_plugin: auth_plugin_name - .map(|name| >::from_str(&name)) + .map(|name| AuthPlugin::parse(&name)) .transpose()? .unwrap_or_else(|| Box::new(NativeAuthPlugin)), }) diff --git a/sqlx-mysql/src/protocol/handshake_response.rs b/sqlx-mysql/src/protocol/handshake_response.rs index 4d3af879..4467ef1f 100644 --- a/sqlx-mysql/src/protocol/handshake_response.rs +++ b/sqlx-mysql/src/protocol/handshake_response.rs @@ -19,6 +19,9 @@ pub(crate) struct HandshakeResponse<'a> { impl Serialize<'_, Capabilities> for HandshakeResponse<'_> { fn serialize_with(&self, buf: &mut Vec, capabilities: Capabilities) -> Result<()> { + // the truncation is the intent + // capability bits over 32 are MariaDB only (and we don't currently support them) + #[allow(clippy::cast_possible_truncation)] buf.extend_from_slice(&(capabilities.bits() as u32).to_le_bytes()); buf.extend_from_slice(&self.max_packet_size.to_le_bytes()); buf.push(self.charset); @@ -36,7 +39,11 @@ impl Serialize<'_, Capabilities> for HandshakeResponse<'_> { debug_assert!(auth_response.len() <= u8::max_value().into()); buf.reserve(1 + auth_response.len()); + + // in debug mode, we assert that the auth response is not too big + #[allow(clippy::cast_possible_truncation)] buf.push(auth_response.len() as u8); + buf.extend_from_slice(auth_response); } else { buf.reserve(1 + auth_response.len()); diff --git a/sqlx/src/lib.rs b/sqlx/src/lib.rs index 4f22da11..c33ed1ba 100644 --- a/sqlx/src/lib.rs +++ b/sqlx/src/lib.rs @@ -4,7 +4,6 @@ #![warn(rust_2018_idioms)] #![warn(future_incompatible)] #![warn(clippy::pedantic)] -#![warn(clippy::cargo_common_metadata)] #![warn(clippy::multiple_crate_versions)] #![warn(clippy::cognitive_complexity)] #![warn(clippy::future_not_send)] diff --git a/tests/x.py b/tests/x.py index 706db69d..da8823a5 100755 --- a/tests/x.py +++ b/tests/x.py @@ -69,6 +69,53 @@ def run_check(project_name: str): ], cwd=project_dir, comment=f"check {project} +async,+blocking") +def run_clippy(project_name: str): + project = f"sqlx-{project_name}" + tag = f"clippy:{project_name}" + + if argv.target is not None and argv.target not in tag: + return + + if argv.list_targets: + print(tag) + return + + # update timestamp so clippy will run + Path(f"{project}/src/lib.rs").touch() + + run([ + "cargo", "clippy", + "--manifest-path", f"{project}/Cargo.toml", + ], cwd=project_dir, comment=f"clippy {project}") + + # update timestamp so clippy will run + Path(f"{project}/src/lib.rs").touch() + + run([ + "cargo", "clippy", + "--manifest-path", f"{project}/Cargo.toml", + "--features", "blocking", + ], cwd=project_dir, comment=f"clippy {project} +blocking") + + # update timestamp so clippy will run + Path(f"{project}/src/lib.rs").touch() + + run([ + "cargo", "clippy", + "--manifest-path", f"{project}/Cargo.toml", + "--features", "async", + ], cwd=project_dir, comment=f"clippy {project} +async") + + # update timestamp so clippy will run + Path(f"{project}/src/lib.rs").touch() + + run([ + "cargo", "clippy", + "--manifest-path", f"{project}/Cargo.toml", + "--features", "blocking,async", + ], cwd=project_dir, comment=f"clippy {project} +async,+blocking") + + def run_unit_test(project_name: str): project = f"sqlx-{project_name}" tag = f"unit:{project_name}" @@ -121,6 +168,10 @@ def main(): run_check("core") run_check("mysql") + # run checks + run_clippy("core") + run_clippy("mysql") + # run unit tests, collect test binary filenames run_unit_test("core") run_unit_test("mysql")