mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@barebox.org>
Subject: [PATCH] commands: test: add support for [[ -v var_to_check_existence ]]
Date: Tue, 20 Jan 2026 13:27:20 +0100	[thread overview]
Message-ID: <20260120122732.634300-1-a.fatoum@pengutronix.de> (raw)

From: Ahmad Fatoum <a.fatoum@barebox.org>

We currently have no way to differentiate between a variable that's set
and one that's empty, but this would be useful for scripts that source
other scripts for customization and want to verify if some variables
have been explicitly set to be empty or not, e.g. an initrd override
that's empty would mean to omit the initrd as opposed to not setting it,
which means to attempt no override.

Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
 commands/test.c       | 12 +++++++++++-
 test/py/test_shell.py | 43 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/commands/test.c b/commands/test.c
index c2f2993df406..d32536b0fd3e 100644
--- a/commands/test.c
+++ b/commands/test.c
@@ -10,6 +10,7 @@
 #include <common.h>
 #include <command.h>
 #include <fnmatch.h>
+#include <environment.h>
 #include <fs.h>
 #include <linux/stat.h>
 
@@ -34,6 +35,7 @@ typedef enum {
 	OPT_CHAR,
 	OPT_SYMBOLIC_LINK,
 	OPT_NONZERO_SIZE,
+	OPT_VAR_EXISTS,
 	OPT_MAX,
 } test_opts;
 
@@ -58,6 +60,7 @@ static char *test_options[] = {
 	[OPT_CHAR]			= "-c",
 	[OPT_SYMBOLIC_LINK]		= "-L",
 	[OPT_NONZERO_SIZE]		= "-s",
+	[OPT_VAR_EXISTS]		= "-v",
 };
 
 static int parse_opt(const char *opt)
@@ -197,6 +200,13 @@ static int do_test(int argc, char *argv[])
 			expr = (opt == OPT_ZERO) ? zero : !zero;
 			break;
 
+		case OPT_VAR_EXISTS:
+			adv = 2;
+			if (left < 2)
+				break;
+			expr = getenv(ap[1]) != NULL;
+			break;
+
 		case OPT_FILE:
 		case OPT_DIRECTORY:
 		case OPT_EXISTS:
@@ -302,7 +312,7 @@ static const char * const test_aliases[] = { "[", "[[", NULL};
 BAREBOX_CMD_HELP_START(test)
 BAREBOX_CMD_HELP_TEXT("Options:")
 BAREBOX_CMD_HELP_TEXT("\t!, =, !=, -eq, -ne, -ge, -gt, -le, -lt, -o, -a, -z, -n, -d, -e,")
-BAREBOX_CMD_HELP_TEXT("\t-s, -f, -L; see 'man test' on your PC for more information.")
+BAREBOX_CMD_HELP_TEXT("\t-s, -f, -L, -v; see 'man test' on your PC for more information.")
 BAREBOX_CMD_HELP_END
 
 BAREBOX_CMD_START(test)
diff --git a/test/py/test_shell.py b/test/py/test_shell.py
index 22a076d10e1e..23c2d5dbb0b6 100644
--- a/test/py/test_shell.py
+++ b/test/py/test_shell.py
@@ -112,3 +112,46 @@ def test_cmd_clk(barebox, barebox_config):
     assert regions >= 0
 
     assert count_dicts_in_command_output(barebox, 'clk_dump -vj') == regions
+
+
+def test_barebox_test_var_exists(barebox, barebox_config):
+    skip_disabled(barebox_config, "CONFIG_CMD_TEST", "CONFIG_CMD_ECHO")
+
+    # Create a file with variable definitions
+    barebox.run_check('echo -o /tmp/testvars "TEST_VAR=value"')
+    barebox.run_check('echo -a /tmp/testvars "EMPTY_VAR="')
+
+    # Test with unset variable - should fail
+    _, _, returncode = barebox.run('test -v NONEXISTENT_VAR')
+    assert returncode == 1
+
+    _, _, returncode = barebox.run('[[ -v NONEXISTENT_VAR ]]')
+    assert returncode == 1
+
+    # Test with set variable - should succeed
+    _, _, returncode = barebox.run('. /tmp/testvars; test -v TEST_VAR')
+    assert returncode == 0
+
+    _, _, returncode = barebox.run('. /tmp/testvars; [[ -v TEST_VAR ]]')
+    assert returncode == 0
+
+    # Test with empty but set variable - should succeed
+    _, _, returncode = barebox.run('. /tmp/testvars; test -v EMPTY_VAR')
+    assert returncode == 0
+
+    _, _, returncode = barebox.run('. /tmp/testvars; [[ -v EMPTY_VAR ]]')
+    assert returncode == 0
+
+    # Test negation with !
+    _, _, returncode = barebox.run('test ! -v NONEXISTENT_VAR')
+    assert returncode == 0
+
+    _, _, returncode = barebox.run('. /tmp/testvars; test ! -v TEST_VAR')
+    assert returncode == 1
+
+    # Test in conditional context
+    barebox.run_check('. /tmp/testvars; [[ -v TEST_VAR ]] && echo ok')
+    barebox.run_check('[[ ! -v NONEXISTENT_VAR ]] && echo ok')
+
+    # Clean up
+    barebox.run_check('rm /tmp/testvars')
-- 
2.47.3




                 reply	other threads:[~2026-01-20 12:28 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260120122732.634300-1-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=a.fatoum@barebox.org \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox