Repository: ast-grep/ast-grep (language: rust)

Issue:
[feature] reduce binary size
# ⭐ Suggestion

See sub-issues, we can have a smaller installation packages.

# 💻 Use Cases

faster compilation
faster installation
more eco-friendly


Discussion / hints:

Fix patch:
diff --git a/.gitignore b/.gitignore
index 664f9a9166..94b85f8021 100644
--- a/.gitignore
+++ b/.gitignore
@@ -152,7 +152,6 @@ __pycache__/
 .Python
 .venv/
 env/
-bin/
 build/
 develop-eggs/
 dist/
diff --git a/crates/cli/Cargo.toml b/crates/cli/Cargo.toml
index 97f59fd6d2..53528897b5 100644
--- a/crates/cli/Cargo.toml
+++ b/crates/cli/Cargo.toml
@@ -3,7 +3,7 @@ name = "ast-grep"
 description = "Search and Rewrite code at large scale using precise AST pattern"
 keywords = ["ast", "pattern", "codemod", "search", "rewrite"]
 categories = ["command-line-utilities", "development-tools", "parsing"]
-default-run = "sg"
+default-run = "ast-grep"
 # use relative path because maturin does not recognize
 readme = "../../README.md"
 license-file = "../../LICENSE"
@@ -18,12 +18,12 @@ repository.workspace = true
 rust-version.workspace = true
 
 [[bin]]
-name = "sg"
+name = "ast-grep"
 path = "src/main.rs"
 
 [[bin]]
-name = "ast-grep"
-path = "src/bin/ast-grep.rs"
+name = "sg"
+path = "src/bin/alias.rs"
 
 [dependencies]
 ast-grep-core.workspace = true
@@ -58,4 +58,4 @@ tempfile = "3.10.1"
 [package.metadata.binstall]
 pkg-url = "{ repo }/releases/download/v{ version }/app-{ target }{ archive-suffix }"
 bin-dir = "app-{ target }/{ bin }{ binary-ext }"
-disabled-strategies = ["quick-install"]
+disabled-strategies = ["quick-install"]
\ No newline at end of file
diff --git a/crates/cli/src/bin/alias.rs b/crates/cli/src/bin/alias.rs
new file mode 100644
index 0000000000..4a2abf73ce
--- /dev/null
+++ b/crates/cli/src/bin/alias.rs
@@ -0,0 +1,16 @@
+// The alias command `sg` redirects everything to ast-grep
+// we need this to avoid "multiple build target" warning
+// See https://github.com/rust-lang/cargo/issues/5930
+fn main() -> std::io::Result<()> {
+  // redirect to ast-grep
+  use std::env::args;
+  use std::process::{Command, Stdio};
+  let mut child = Command::new("ast-grep")
+    .args(args().skip(1))
+    .stdin(Stdio::inherit())
+    .stdout(Stdio::inherit())
+    .stderr(Stdio::inherit())
+    .spawn()?;
+  let status = child.wait()?;
+  std::process::exit(status.code().unwrap_or(1))
+}
diff --git a/crates/cli/src/bin/ast-grep.rs b/crates/cli/src/bin/ast-grep.rs
deleted file mode 100644
index d03411254e..0000000000
--- a/crates/cli/src/bin/ast-grep.rs
+++ /dev/null
@@ -1,9 +0,0 @@
-// This file is exactly the same as main.rs
-// we need this to avoid "multiple build target" warning
-// See https://github.com/rust-lang/cargo/issues/5930
-use anyhow::Result;
-use ast_grep::execute_main;
-
-fn main() -> Result<()> {
-  execute_main()
-}


Test patch:
diff --git a/crates/cli/tests/run_test.rs b/crates/cli/tests/run_test.rs
index 9efdf15bbc..a7726557a5 100644
--- a/crates/cli/tests/run_test.rs
+++ b/crates/cli/tests/run_test.rs
@@ -9,7 +9,7 @@ use predicates::str::contains;
 #[test]
 fn test_simple_infer_lang() -> Result<()> {
   let dir = create_test_files([("a.ts", "console.log(123)"), ("b.rs", "console.log(456)")])?;
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["-p", "console.log($A)"])
     .assert()
@@ -22,7 +22,7 @@ fn test_simple_infer_lang() -> Result<()> {
 #[test]
 fn test_simple_specific_lang() -> Result<()> {
   let dir = create_test_files([("a.ts", "console.log(123)"), ("b.rs", "console.log(456)")])?;
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["-p", "console.log($A)", "-l", "rs"])
     .assert()
@@ -38,7 +38,7 @@ fn test_js_in_html() -> Result<()> {
     ("a.html", "<script>alert(1)</script>"),
     ("b.js", "alert(456)"),
   ])?;
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["-p", "alert($A)", "-l", "js"])
     .assert()
@@ -51,7 +51,7 @@ fn test_js_in_html() -> Result<()> {
 #[test]
 fn test_inspect() -> Result<()> {
   let dir = create_test_files([("a.js", "alert(1)"), ("b.js", "alert(456)")])?;
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["-p", "alert($A)", "-l", "js", "--inspect", "entity"])
     .assert()
@@ -64,7 +64,7 @@ fn test_inspect() -> Result<()> {
 #[test]
 fn test_debug_query() -> Result<()> {
   // should not print pattern if invalid
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .args(["-p", "foo;bar;", "-l", "js", "--debug-query"])
     .assert()
     .failure()
@@ -72,7 +72,7 @@ fn test_debug_query() -> Result<()> {
     .stderr(contains("Cannot parse query as a valid pattern"));
 
   // should  print debug tree even for invalid pattern
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .args(["-p", "foo;bar;", "-l", "js", "--debug-query=ast"])
     .assert()
     .failure()
diff --git a/crates/cli/tests/scan_test.rs b/crates/cli/tests/scan_test.rs
index 5084b3ae00..eb74744a63 100644
--- a/crates/cli/tests/scan_test.rs
+++ b/crates/cli/tests/scan_test.rs
@@ -52,13 +52,13 @@ fn sg(s: &str) -> Result<()> {
 fn test_sg_scan() -> Result<()> {
   let dir = setup()?;
   let config = dir.path().join("sgconfig.yml");
-  let ret = sg(&format!("sg scan -c {}", config.display()));
+  let ret = sg(&format!("ast-grep scan -c {}", config.display()));
   assert!(ret.is_ok());
-  let ret = sg(&format!("sg scan -c={}", config.display()));
+  let ret = sg(&format!("ast-grep scan -c={}", config.display()));
   assert!(ret.is_ok());
-  let ret = sg(&format!("sg scan --config {}", config.display()));
+  let ret = sg(&format!("ast-grep scan --config {}", config.display()));
   assert!(ret.is_ok());
-  let ret = sg(&format!("sg scan --config={}", config.display()));
+  let ret = sg(&format!("ast-grep scan --config={}", config.display()));
   assert!(ret.is_ok());
   drop(dir);
   Ok(())
@@ -67,7 +67,7 @@ fn test_sg_scan() -> Result<()> {
 #[test]
 fn test_sg_rule_off() -> Result<()> {
   let dir = setup()?;
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["scan"])
     .assert()
@@ -81,7 +81,7 @@ fn test_sg_rule_off() -> Result<()> {
 #[test]
 fn test_sg_scan_inline_rules() -> Result<()> {
   let inline_rules = "{id: test, language: ts, rule: {pattern: console.log($A)}}";
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .args(["scan", "--stdin", "--inline-rules", inline_rules, "--json"])
     .write_stdin("console.log(123)")
     .assert()
@@ -103,7 +103,7 @@ rule: { pattern: None }
 #[test]
 fn test_sg_scan_multiple_rules_in_one_file() -> Result<()> {
   let dir = create_test_files([("rule.yml", MULTI_RULES), ("test.ts", "Some(123) + None")])?;
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["scan", "-r", "rule.yml"])
     .assert()
@@ -118,7 +118,7 @@ fn test_sg_scan_multiple_rules_in_one_file() -> Result<()> {
 #[test]
 fn test_sg_scan_py_empty_text() -> Result<()> {
   let inline_rules = "{id: test, language: py, rule: {pattern: None}}";
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .args(["scan", "--stdin", "--inline-rules", inline_rules])
     .write_stdin("\n\n\n\n\nNone")
     .assert()
@@ -132,7 +132,7 @@ fn test_sg_scan_html() -> Result<()> {
     ("rule.yml", RULE1),
     ("test.html", "<script lang=ts>Some(123)</script>"),
   ])?;
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["scan", "-r", "rule.yml", "--inspect=summary"])
     .assert()
@@ -151,7 +151,7 @@ fn test_scan_unused_suppression() -> Result<()> {
     ("rules/rule.yml", RULE1),
     ("test.ts", "None(123) // ast-grep-ignore"),
   ])?;
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["scan"])
     .assert()
@@ -167,25 +167,25 @@ fn test_unused_suppression_only_in_scan() -> Result<()> {
     ("rules/rule.yml", RULE1),
     ("test.ts", "None(123) // ast-grep-ignore"),
   ])?;
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["scan", "-r", "rules/rule.yml"])
     .assert()
     .success()
     .stdout(contains("unused-suppression").not());
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["scan", "--filter", "on-rule"])
     .assert()
     .success()
     .stdout(contains("unused-suppression").not());
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["scan", "--off", "on-rule"])
     .assert()
     .success()
     .stdout(contains("unused-suppression").not());
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["scan", "--inline-rules", RULE1])
     .assert()
@@ -201,7 +201,7 @@ fn test_scan_unused_suppression_off() -> Result<()> {
     ("rules/rule.yml", RULE1),
     ("test.ts", "None(123) // ast-grep-ignore"),
   ])?;
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["scan", "--off"])
     .assert()
@@ -212,19 +212,19 @@ fn test_scan_unused_suppression_off() -> Result<()> {
 #[test]
 fn test_severity_override() -> Result<()> {
   let dir = setup()?;
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["scan", "--error"])
     .assert()
     .failure()
     .stdout(contains("error"));
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["scan", "--error=on-rule"])
     .assert()
     .failure()
     .stdout(contains("error"));
-  Command::cargo_bin("sg")?
+  Command::cargo_bin("ast-grep")?
     .current_dir(dir.path())
     .args(["scan", "--error=not-exist"])
     .assert()
diff --git a/crates/cli/tests/verify_test.rs b/crates/cli/tests/verify_test.rs
index db3bea1471..c2822b314e 100644
--- a/crates/cli/tests/verify_test.rs
+++ b/crates/cli/tests/verify_test.rs
@@ -57,7 +57,7 @@ fn test_sg_test() -> Result<()> {
   let dir = setup()?;
   let config = dir.path().join("sgconfig.yml");
   let ret = sg(&format!(
-    "sg test -c {} --skip-snapshot-tests",
+    "ast-grep test -c {} --skip-snapshot-tests",
     config.display()
   ));
   assert!(ret.is_ok());
@@ -81,7 +81,7 @@ fn test_sg_test_error() -> Result<()> {
   let dir = setup_error()?;
   let config = dir.path().join("sgconfig.yml");
   let ret = sg(&format!(
-    "sg test -c {} --skip-snapshot-tests",
+    "ast-grep test -c {} --skip-snapshot-tests",
     config.display()
   ));
   assert!(ret.is_err());
@@ -95,12 +95,12 @@ fn test_sg_test_filter() -> Result<()> {
   let dir = setup_error()?;
   let config = dir.path().join("sgconfig.yml");
   let ret = sg(&format!(
-    "sg test -c {} --skip-snapshot-tests -f error-rule",
+    "ast-grep test -c {} --skip-snapshot-tests -f error-rule",
     config.display()
   ));
   assert!(ret.is_ok());
   let ret = sg(&format!(
-    "sg test -c {} --skip-snapshot-tests -f test-rule",
+    "ast-grep test -c {} --skip-snapshot-tests -f test-rule",
     config.display()
   ));
   assert!(ret.is_err());