From 816227d035283b4da35d1e6c191f2a0501165add Mon Sep 17 00:00:00 2001 From: Amaan Qureshi Date: Fri, 23 Oct 2026 21:12:45 -0400 Subject: [PATCH] build: check completions in a test instead of writing them from build.rs (#1338) Co-authored-by: Ajeet D'Souza <98ajeet@gmail.com> --- CHANGELOG.md | 1 + build.rs | 40 +++++++++++++++++++++++++--------------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index af69282..de4c2ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Bash/Zsh: fix `z` failing on Cygwin/MSYS2 due to `cygpath` being passed a bad string. - Nushell: `z` now handles relative paths through symlinked directories. - POSIX: fix `z` failing to enter directories whose names start with `-`. +- Build: fix compilation failing when the source directory is read-only. ## [0.10.0] - 2026-07-04 diff --git a/build.rs b/build.rs index 7b3a60f..f203982 100644 --- a/build.rs +++ b/build.rs @@ -1,9 +1,11 @@ #[path = "src/cmd/cmd.rs"] mod cmd; -use std::{env, io}; +use std::path::Path; +use std::{env, fs, io}; use clap::CommandFactory as _; +use clap_complete::Generator; use clap_complete::shells::{Bash, Elvish, Fish, PowerShell, Zsh}; use clap_complete_fig::Fig; use clap_complete_nushell::Nushell; @@ -16,21 +18,29 @@ fn main() -> io::Result<()> { println!("cargo:rerun-if-changed=src/"); println!("cargo:rerun-if-changed=templates/"); println!("cargo:rerun-if-changed=tests/"); - generate_completions() -} -fn generate_completions() -> io::Result<()> { - const BIN_NAME: &str = env!("CARGO_PKG_NAME"); - const OUT_DIR: &str = "contrib/completions"; - let cmd = &mut Cmd::command(); - - clap_complete::generate_to(Bash, cmd, BIN_NAME, OUT_DIR)?; - clap_complete::generate_to(Elvish, cmd, BIN_NAME, OUT_DIR)?; - clap_complete::generate_to(Fig, cmd, BIN_NAME, OUT_DIR)?; - clap_complete::generate_to(Fish, cmd, BIN_NAME, OUT_DIR)?; - clap_complete::generate_to(Nushell, cmd, BIN_NAME, OUT_DIR)?; - clap_complete::generate_to(PowerShell, cmd, BIN_NAME, OUT_DIR)?; - clap_complete::generate_to(Zsh, cmd, BIN_NAME, OUT_DIR)?; + generate_completions(Bash)?; + generate_completions(Elvish)?; + generate_completions(Fig)?; + generate_completions(Fish)?; + generate_completions(Nushell)?; + generate_completions(PowerShell)?; + generate_completions(Zsh)?; Ok(()) } + +/// Writes a shell's completions only if they differ from the committed file. +fn generate_completions(generator: impl Generator) -> io::Result<()> { + const BIN_NAME: &str = env!("CARGO_PKG_NAME"); + const OUT_DIR: &str = "contrib/completions"; + + let path = Path::new(OUT_DIR).join(generator.file_name(BIN_NAME)); + let mut generated = Vec::new(); + clap_complete::generate(generator, &mut Cmd::command(), BIN_NAME, &mut generated); + + if !fs::read(&path).is_ok_and(|content| content == generated) { + fs::write(&path, generated)?; + } + Ok(()) +}