Compare commits

...

1 Commits

Author SHA1 Message Date
Andrei Eternal
9325b89f07 Basic handling of env variable snapshots that contain newlines and quotes 2026-01-28 15:31:06 -08:00

View File

@@ -235,6 +235,17 @@ export_lines=$(export -p | awk '
name=line
sub(/^(export|declare -x|typeset -x) /, "", name)
sub(/=.*/, "", name)
tmp=line
gsub(/\\"/, "", tmp)
quote_count=gsub(/"/, "", tmp)
if ((quote_count % 2) == 1 && line !~ /\\$/) {
next
}
if (line ~ /\\$/) {
while (line ~ /\\$/ && (getline continuation) > 0) {
line = line "\n" continuation
}
}
if (name ~ /^(EXCLUDED_EXPORTS)$/) {
next
}
@@ -279,6 +290,17 @@ export_lines=$(export -p | awk '
name=line
sub(/^(export|declare -x|typeset -x) /, "", name)
sub(/=.*/, "", name)
tmp=line
gsub(/\\"/, "", tmp)
quote_count=gsub(/"/, "", tmp)
if ((quote_count % 2) == 1 && line !~ /\\$/) {
next
}
if (line ~ /\\$/) {
while (line ~ /\\$/ && (getline continuation) > 0) {
line = line "\n" continuation
}
}
if (name ~ /^(EXCLUDED_EXPORTS)$/) {
next
}
@@ -336,6 +358,17 @@ if export -p >/dev/null 2>&1; then
name=line
sub(/^(export|declare -x|typeset -x) /, "", name)
sub(/=.*/, "", name)
tmp=line
gsub(/\\"/, "", tmp)
quote_count=gsub(/"/, "", tmp)
if ((quote_count % 2) == 1 && line !~ /\\$/) {
next
}
if (line ~ /\\$/) {
while (line ~ /\\$/ && (getline continuation) > 0) {
line = line "\n" continuation
}
}
if (name ~ /^(EXCLUDED_EXPORTS)$/) {
next
}
@@ -528,6 +561,38 @@ mod tests {
Ok(())
}
#[cfg(unix)]
#[test]
fn bash_snapshot_handles_multiline_exports() -> Result<()> {
let output = Command::new("/bin/bash")
.arg("-c")
.arg(bash_snapshot_script())
.env_clear()
.env("HOME", "/nonexistent")
.env("PATH", "/usr/bin:/bin")
.env("BASH_ENV", "/dev/null")
.env("CODEX_MULTILINE_EXPORT", "line-1\nline-2")
.output()?;
assert!(output.status.success());
let stdout = String::from_utf8_lossy(&output.stdout);
let snapshot = strip_snapshot_preamble(&stdout)?;
let dir = tempdir()?;
let path = dir.path().join("snapshot.sh");
std::fs::write(&path, snapshot)?;
let syntax_check = Command::new("/bin/bash").arg("-n").arg(&path).output()?;
assert!(
syntax_check.status.success(),
"snapshot should be valid bash: {}",
String::from_utf8_lossy(&syntax_check.stderr)
);
Ok(())
}
#[cfg(unix)]
#[tokio::test]
async fn try_new_creates_and_deletes_snapshot_file() -> Result<()> {