Skip to content

Commit 8a7e540

Browse files
authored
feat: turn off FAILGLOB by default (#168)
1 parent af0c890 commit 8a7e540

File tree

2 files changed

+28
-29
lines changed

2 files changed

+28
-29
lines changed

src/shell/types.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ bitflags! {
3232
/// (empty) rather than returning an error.
3333
const NULLGLOB = 1 << 0;
3434
/// When set, a glob pattern that matches no files causes an error.
35-
/// This is the default for deno_task_shell (differs from bash).
3635
/// When unset, unmatched globs are passed through literally (bash default).
3736
const FAILGLOB = 1 << 1;
3837
/// When set, pipeline exit code is the rightmost non-zero exit code.
@@ -46,7 +45,7 @@ bitflags! {
4645

4746
impl Default for ShellOptions {
4847
fn default() -> Self {
49-
ShellOptions::FAILGLOB.union(ShellOptions::GLOBSTAR)
48+
ShellOptions::GLOBSTAR
5049
}
5150
}
5251

tests/integration_test.rs

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1125,7 +1125,7 @@ async fn rm() {
11251125
// rm -rf with glob pattern that matches nothing should succeed
11261126
// (when failglob is disabled, the pattern is passed literally to rm)
11271127
TestBuilder::new()
1128-
.command("shopt -u failglob && rm -rf *.nonexistent")
1128+
.command("rm -rf *.nonexistent")
11291129
.assert_exit_code(0)
11301130
.run()
11311131
.await;
@@ -1447,7 +1447,7 @@ async fn glob_basic() {
14471447
TestBuilder::new()
14481448
.file("test.txt", "test\n")
14491449
.file("test2.txt", "test2\n")
1450-
.command("cat *.ts")
1450+
.command("shopt -s failglob && cat *.ts")
14511451
.assert_stderr("glob: no matches found '$TEMP_DIR/*.ts' (run `shopt -u failglob` to pass unmatched glob patterns literally)\n")
14521452
.assert_exit_code(1)
14531453
.run()
@@ -1458,7 +1458,7 @@ async fn glob_basic() {
14581458
let error_pos = temp_dir_path.to_string_lossy().len() + 1;
14591459
builder.file("test.txt", "test\n")
14601460
.file("test2.txt", "test2\n")
1461-
.command("cat [].ts")
1461+
.command("shopt -s failglob && cat [].ts")
14621462
.assert_stderr(&format!("glob: no matches found '$TEMP_DIR/[].ts'. Pattern syntax error near position {}: invalid range pattern\n", error_pos))
14631463
.assert_exit_code(1)
14641464
.run()
@@ -1467,7 +1467,7 @@ async fn glob_basic() {
14671467
TestBuilder::new()
14681468
.file("test.txt", "test\n")
14691469
.file("test2.txt", "test2\n")
1470-
.command("cat *.ts || echo 2")
1470+
.command("shopt -s failglob && cat *.ts || echo 2")
14711471
.assert_stderr("glob: no matches found '$TEMP_DIR/*.ts' (run `shopt -u failglob` to pass unmatched glob patterns literally)\n")
14721472
.assert_stdout("2\n")
14731473
.assert_exit_code(0)
@@ -1743,10 +1743,10 @@ async fn sigpipe_from_pipeline() {
17431743

17441744
#[tokio::test]
17451745
async fn shopt() {
1746-
// query all options (default: failglob on, globstar on, nullglob off)
1746+
// query all options (default: failglob off, globstar on, nullglob off)
17471747
TestBuilder::new()
17481748
.command("shopt")
1749-
.assert_stdout("failglob\ton\nglobstar\ton\nnullglob\toff\n")
1749+
.assert_stdout("failglob\toff\nglobstar\ton\nnullglob\toff\n")
17501750
.run()
17511751
.await;
17521752

@@ -1760,8 +1760,8 @@ async fn shopt() {
17601760

17611761
TestBuilder::new()
17621762
.command("shopt failglob")
1763-
.assert_stdout("failglob\ton\n")
1764-
.assert_exit_code(0) // returns 0 when option is on
1763+
.assert_stdout("failglob\toff\n")
1764+
.assert_exit_code(1) // returns 1 when option is off
17651765
.run()
17661766
.await;
17671767

@@ -1773,11 +1773,11 @@ async fn shopt() {
17731773
.run()
17741774
.await;
17751775

1776-
// disable option
1776+
// enable failglob
17771777
TestBuilder::new()
1778-
.command("shopt -u failglob && shopt failglob")
1779-
.assert_stdout("failglob\toff\n")
1780-
.assert_exit_code(1)
1778+
.command("shopt -s failglob && shopt failglob")
1779+
.assert_stdout("failglob\ton\n")
1780+
.assert_exit_code(0)
17811781
.run()
17821782
.await;
17831783

@@ -1807,8 +1807,8 @@ async fn shopt() {
18071807

18081808
// multiple options
18091809
TestBuilder::new()
1810-
.command("shopt -s nullglob && shopt -u failglob && shopt")
1811-
.assert_stdout("failglob\toff\nglobstar\ton\nnullglob\ton\n")
1810+
.command("shopt -s nullglob && shopt -s failglob && shopt")
1811+
.assert_stdout("failglob\ton\nglobstar\ton\nnullglob\ton\n")
18121812
.run()
18131813
.await;
18141814

@@ -1831,19 +1831,19 @@ async fn shopt() {
18311831

18321832
#[tokio::test]
18331833
async fn shopt_nullglob() {
1834-
// default behavior (failglob on): unmatched glob causes error
1834+
// default behavior (failglob off): unmatched glob passed literally
18351835
TestBuilder::new()
18361836
.file("test.txt", "test\n")
18371837
.command("echo *.nonexistent")
1838-
.assert_stderr("glob: no matches found '$TEMP_DIR/*.nonexistent' (run `shopt -u failglob` to pass unmatched glob patterns literally)\n")
1839-
.assert_exit_code(1)
1838+
.assert_stdout("*.nonexistent\n")
1839+
.assert_exit_code(0)
18401840
.run()
18411841
.await;
18421842

18431843
// with nullglob: unmatched glob expands to nothing
18441844
TestBuilder::new()
18451845
.file("test.txt", "test\n")
1846-
.command("shopt -u failglob && shopt -s nullglob && echo *.nonexistent")
1846+
.command("shopt -s nullglob && echo *.nonexistent")
18471847
.assert_stdout("\n") // echo with no args outputs newline
18481848
.assert_exit_code(0)
18491849
.run()
@@ -1852,7 +1852,7 @@ async fn shopt_nullglob() {
18521852
// nullglob with other args: unmatched glob removed, other args kept
18531853
TestBuilder::new()
18541854
.file("test.txt", "test\n")
1855-
.command("shopt -u failglob && shopt -s nullglob && echo hello *.nonexistent world")
1855+
.command("shopt -s nullglob && echo hello *.nonexistent world")
18561856
.assert_stdout("hello world\n")
18571857
.assert_exit_code(0)
18581858
.run()
@@ -1861,7 +1861,7 @@ async fn shopt_nullglob() {
18611861
// nullglob: matched glob still works normally
18621862
TestBuilder::new()
18631863
.file("test.txt", "test\n")
1864-
.command("shopt -u failglob && shopt -s nullglob && cat *.txt")
1864+
.command("shopt -s nullglob && cat *.txt")
18651865
.assert_stdout("test\n")
18661866
.assert_exit_code(0)
18671867
.run()
@@ -1870,21 +1870,21 @@ async fn shopt_nullglob() {
18701870

18711871
#[tokio::test]
18721872
async fn shopt_failglob() {
1873-
// failglob on (default): unmatched glob causes error
1873+
// failglob off (default): unmatched glob passed through literally
18741874
TestBuilder::new()
18751875
.file("test.txt", "test\n")
18761876
.command("echo *.nonexistent")
1877-
.assert_stderr("glob: no matches found '$TEMP_DIR/*.nonexistent' (run `shopt -u failglob` to pass unmatched glob patterns literally)\n")
1878-
.assert_exit_code(1)
1877+
.assert_stdout("*.nonexistent\n")
1878+
.assert_exit_code(0)
18791879
.run()
18801880
.await;
18811881

1882-
// failglob off: unmatched glob passed through literally (bash default)
1882+
// failglob on: unmatched glob causes error
18831883
TestBuilder::new()
18841884
.file("test.txt", "test\n")
1885-
.command("shopt -u failglob && echo *.nonexistent")
1886-
.assert_stdout("*.nonexistent\n")
1887-
.assert_exit_code(0)
1885+
.command("shopt -s failglob && echo *.nonexistent")
1886+
.assert_stderr("glob: no matches found '$TEMP_DIR/*.nonexistent' (run `shopt -u failglob` to pass unmatched glob patterns literally)\n")
1887+
.assert_exit_code(1)
18881888
.run()
18891889
.await;
18901890

0 commit comments

Comments
 (0)