fix(git-master): emit csh-compatible setenv syntax for csh/tcsh shells
buildShellAwareGitPrefix incorrectly returned raw bash VAR=value prefix for csh, which does not support inline env assignment. Now routes csh through buildEnvPrefix() to emit setenv syntax. Also sets code block lang to csh and skips bash block regex prefixing for csh. Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -231,6 +231,18 @@ describe("#given buildShellAwareGitPrefix", () => {
|
||||
})
|
||||
})
|
||||
|
||||
describe("#when shell type is csh", () => {
|
||||
it("#then returns csh setenv syntax", () => {
|
||||
const result = buildShellAwareGitPrefix("GIT_MASTER=1", "csh")
|
||||
expect(result).toBe("setenv GIT_MASTER 1;")
|
||||
})
|
||||
|
||||
it("#then handles multiple env vars", () => {
|
||||
const result = buildShellAwareGitPrefix("CI=true GIT_MASTER=1", "csh")
|
||||
expect(result).toBe("setenv CI true; setenv GIT_MASTER 1;")
|
||||
})
|
||||
})
|
||||
|
||||
describe("#when prefix is empty", () => {
|
||||
it("#then returns empty string", () => {
|
||||
const result = buildShellAwareGitPrefix("", "powershell")
|
||||
@@ -319,4 +331,61 @@ describe("#given PowerShell shell detection in injectGitMasterConfig", () => {
|
||||
expect(result).not.toContain("$env:")
|
||||
})
|
||||
})
|
||||
|
||||
describe("#when shell is csh (SHELL set to /bin/csh)", () => {
|
||||
it("#then emits setenv prefix syntax in csh code block", () => {
|
||||
process.env.SHELL = "/bin/csh"
|
||||
delete process.env.PSModulePath
|
||||
delete process.env.MSYSTEM
|
||||
Object.defineProperty(process, "platform", { value: "linux" })
|
||||
|
||||
const result = injectGitMasterConfig(SAMPLE_TEMPLATE, {
|
||||
commit_footer: false,
|
||||
include_co_authored_by: false,
|
||||
git_env_prefix: "GIT_MASTER=1",
|
||||
})
|
||||
|
||||
expect(result).toContain("setenv GIT_MASTER 1;")
|
||||
expect(result).toContain("```csh")
|
||||
expect(result).not.toContain("```bash\nsetenv")
|
||||
})
|
||||
|
||||
it("#then does NOT prefix bash code blocks with setenv syntax", () => {
|
||||
process.env.SHELL = "/bin/csh"
|
||||
delete process.env.PSModulePath
|
||||
delete process.env.MSYSTEM
|
||||
Object.defineProperty(process, "platform", { value: "linux" })
|
||||
|
||||
const result = injectGitMasterConfig(SAMPLE_TEMPLATE, {
|
||||
commit_footer: false,
|
||||
include_co_authored_by: false,
|
||||
git_env_prefix: "GIT_MASTER=1",
|
||||
})
|
||||
|
||||
const bashBlockMatch = result.match(/```bash\r?\n([\s\S]*?)```/g)
|
||||
if (bashBlockMatch) {
|
||||
for (const block of bashBlockMatch) {
|
||||
expect(block).not.toContain("setenv")
|
||||
}
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe("#when shell is tcsh (SHELL set to /usr/local/bin/tcsh)", () => {
|
||||
it("#then emits setenv prefix syntax in csh code block", () => {
|
||||
process.env.SHELL = "/usr/local/bin/tcsh"
|
||||
delete process.env.PSModulePath
|
||||
delete process.env.MSYSTEM
|
||||
Object.defineProperty(process, "platform", { value: "darwin" })
|
||||
|
||||
const result = injectGitMasterConfig(SAMPLE_TEMPLATE, {
|
||||
commit_footer: false,
|
||||
include_co_authored_by: false,
|
||||
git_env_prefix: "GIT_MASTER=1",
|
||||
})
|
||||
|
||||
expect(result).toContain("setenv GIT_MASTER 1;")
|
||||
expect(result).toContain("```csh")
|
||||
})
|
||||
})
|
||||
})
|
||||
|
||||
@@ -26,15 +26,17 @@ export function parseBashEnvPrefix(prefix: string): Record<string, string> {
|
||||
/**
|
||||
* Build the shell-aware command prefix for git commands.
|
||||
* Uses the shared shell detection and env prefix builder to emit correct syntax
|
||||
* for PowerShell ($env:VAR='value';), cmd (set VAR="value" &&), or unix (VAR=value).
|
||||
* for PowerShell ($env:VAR='value';), cmd (set VAR="value" &&),
|
||||
* csh (setenv VAR value;), or unix (VAR=value).
|
||||
*
|
||||
* For unix shells, we use the inline VAR=value prefix style (not export) to match
|
||||
* the original behavior where the env var applies only to the immediately following command.
|
||||
* For csh/tcsh, we use setenv syntax since csh does not support inline VAR=value.
|
||||
*/
|
||||
export function buildShellAwareGitPrefix(bashPrefix: string, shellType?: ShellType): string {
|
||||
if (!bashPrefix) return ""
|
||||
const resolvedShellType = shellType ?? detectShellType()
|
||||
if (resolvedShellType === "unix" || resolvedShellType === "csh") {
|
||||
if (resolvedShellType === "unix") {
|
||||
return bashPrefix
|
||||
}
|
||||
const envRecord = parseBashEnvPrefix(bashPrefix)
|
||||
@@ -48,8 +50,8 @@ export function injectGitMasterConfig(template: string, config?: GitMasterConfig
|
||||
|
||||
const shellType = detectShellType()
|
||||
const shellPrefix = gitEnvPrefix ? buildShellAwareGitPrefix(gitEnvPrefix, shellType) : ""
|
||||
const codeBlockLang = shellType === "powershell" ? "pwsh" : "bash"
|
||||
const skipBashBlockPrefixing = shellType === "powershell" || shellType === "cmd"
|
||||
const codeBlockLang = shellType === "powershell" ? "pwsh" : shellType === "csh" ? "csh" : "bash"
|
||||
const skipBashBlockPrefixing = shellType === "powershell" || shellType === "cmd" || shellType === "csh"
|
||||
|
||||
let result = gitEnvPrefix ? injectGitEnvPrefix(template, shellPrefix, codeBlockLang) : template
|
||||
|
||||
|
||||
Reference in New Issue
Block a user