Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .github/workflows/benchmark.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ jobs:
sudo apt-get update
sudo apt-get install -y hyperfine zsh
eval "$(/home/linuxbrew/.linuxbrew/bin/brew shellenv)"
env -u HOMEBREW_ASK brew update
brew install --no-ask atuin fnm fzf zoxide

mapfile -t insecure_dirs < <(
Expand Down
4 changes: 4 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ install_with_manager() {

case "${manager}" in
brew)
if [[ "${HOMEBREW_UPDATED:-0}" != "1" ]]; then
env -u HOMEBREW_ASK brew update
HOMEBREW_UPDATED=1
fi
brew install --no-ask "$@"
;;
apt-get)
Expand Down
2 changes: 1 addition & 1 deletion src/steps/bootstrap.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ async function installZshViaManager(manager) {

p.log.step("Installing Zsh...");
if (manager === "brew") {
await runStream("brew install --no-ask zsh");
await runStream("env -u HOMEBREW_ASK brew update && brew install --no-ask zsh");
} else if (manager === "apt-get") {
Comment on lines 137 to 139

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

在成功执行 brew update 并安装 Zsh 后,建议调用 setHomebrewUpdated(true)

这样可以确保后续通过 brewInstall 安装其他软件时,不会再次触发冗余且缓慢的 brew update,从而显著提升整体安装效率。

注意

  1. 需要在文件顶部导入 setHomebrewUpdated
    import { commandExists, run, runStream, setHomebrewUpdated } from "../utils/shell.js";
  2. 需要在 tests/bootstrap.test.jsshell.js 模块 mock 中添加 setHomebrewUpdated: vi.fn(),以避免测试报错。
Suggested change
if (manager === "brew") {
await runStream("brew install --no-ask zsh");
await runStream("env -u HOMEBREW_ASK brew update && brew install --no-ask zsh");
} else if (manager === "apt-get") {
if (manager === "brew") {
await runStream("env -u HOMEBREW_ASK brew update && brew install --no-ask zsh");
setHomebrewUpdated(true);
} else if (manager === "apt-get") {

await runStream("sudo apt-get update && sudo apt-get install -y zsh");
} else if (manager === "dnf") {
Expand Down
23 changes: 21 additions & 2 deletions src/utils/shell.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,23 @@ export class ShellCommandError extends Error {
}
}

let homebrewUpdated = false;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

为了支持在其他模块和测试中更新或重置 homebrewUpdated 的状态,建议导出一个 setHomebrewUpdated 辅助函数。

这样做有两个主要好处:

  1. 避免重复更新:在 src/steps/bootstrap.js 中执行 brew update 后,可以将其设置为 true,从而避免后续调用 brewInstall 时再次触发缓慢的 brew update
  2. 测试隔离:在单元测试中,可以在 beforeEach 中将其重置为 false,防止测试用例之间共享全局状态导致测试不稳定。
let homebrewUpdated = false;

export function setHomebrewUpdated(value) {
  homebrewUpdated = value;
}


export function brewUpdate() {
if (homebrewUpdated) return;

const cmd = "env -u HOMEBREW_ASK brew update";
try {
execSync(cmd, { stdio: "inherit" });
homebrewUpdated = true;
} catch (error) {
throw new ShellCommandError(cmd, {
code: error.status,
signal: error.signal,
});
}
}

/**
* Run a shell command synchronously. Returns stdout as string.
* Throws on non-zero exit.
Expand Down Expand Up @@ -57,13 +74,15 @@ export function brewInstalled(name) {
* Install a Homebrew formula or cask. Returns true on success.
*/
export function brewInstall(name, { cask = false } = {}) {
brewUpdate();
const args = cask ? ["install", "--no-ask", "--cask", name] : ["install", "--no-ask", name];
const cmd = `brew ${args.join(" ")}`;
try {
execSync(`brew ${args.join(" ")}`, { stdio: "inherit" });
execSync(cmd, { stdio: "inherit" });
return true;
} catch (error) {
if (error.signal === "SIGINT" || error.status === 130) {
throw new ShellCommandError(`brew ${args.join(" ")}`, {
throw new ShellCommandError(cmd, {
code: error.status,
signal: error.signal,
});
Expand Down
4 changes: 3 additions & 1 deletion tests/bootstrap.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,9 @@ describe("bootstrap step", () => {

await bootstrap({ platform: "darwin" });

expect(runStream).toHaveBeenCalledWith(expect.stringContaining("brew install --no-ask zsh"));
expect(runStream).toHaveBeenCalledWith(
"env -u HOMEBREW_ASK brew update && brew install --no-ask zsh"
);
});

test("supports Linux package manager selection", async () => {
Expand Down
2 changes: 2 additions & 0 deletions tests/shell.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,12 @@ describe("shell utilities", () => {

test("installs Homebrew packages without prompting", () => {
expect(brewInstall("jq")).toBe(true);
expect(execSync).toHaveBeenCalledWith("env -u HOMEBREW_ASK brew update", { stdio: "inherit" });
expect(execSync).toHaveBeenCalledWith("brew install --no-ask jq", { stdio: "inherit" });

expect(brewInstall("ghostty", { cask: true })).toBe(true);
expect(execSync).toHaveBeenCalledWith("brew install --no-ask --cask ghostty", { stdio: "inherit" });
expect(execSync.mock.calls.filter(([command]) => command.includes("brew update"))).toHaveLength(1);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

由于 homebrewUpdatedsrc/utils/shell.js 中的模块级全局变量,它会在不同的测试用例之间共享。

在当前测试中,第一个 brewInstall("jq") 会将 homebrewUpdated 设为 true。这会导致后续的测试(例如 "propagates Ctrl-C from Homebrew installs")在调用 brewInstall 时直接跳过 brewUpdate()

为了保证测试的隔离性,建议在 beforeEach 中重置该状态:

  1. 在文件顶部导入 setHomebrewUpdated
    import { brewInstall, runStream, setHomebrewUpdated } from "../src/utils/shell.js";
  2. beforeEach 中重置状态:
    beforeEach(() => {
      vi.clearAllMocks();
      setHomebrewUpdated(false);
    });

});

test("propagates Ctrl-C from Homebrew installs", () => {
Expand Down