# HG changeset patch
# Node ID 622d5f64d902adb94f748e7e66bb74cacb29b5cb
# Parent  ec8986e1d9bad6043367df146ac077d345e7ff20
diff --git a/birb/birbenv.c b/birb/birbenv.c
new file mode 100644
--- /dev/null
+++ b/birb/birbenv.c
@@ -0,0 +1,78 @@
+/*
+ * Copyright (C) 2024 Birb Developers
+ *
+ * Birb is the legal property of its developers, whose names are too
+ * numerous to list here. Please refer to the AUTHORS file distributed
+ * with this source distribution
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "birbenv.h"
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
+gboolean
+birb_env_append(const char *variable, const char *value, const char *separator)
+{
+	const char * existing = NULL;
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail(variable != NULL, FALSE);
+	g_return_val_if_fail(variable[0] != '\0', FALSE);
+	g_return_val_if_fail(value != NULL, FALSE);
+	g_return_val_if_fail(separator != NULL, FALSE);
+
+	existing = g_getenv(variable);
+	if(existing != NULL) {
+		char *new_value = NULL;
+
+		new_value = g_build_path(separator, existing, value, NULL);
+
+		ret = g_setenv(variable, new_value, TRUE);
+		g_free(new_value);
+	} else {
+		ret = g_setenv(variable, value, TRUE);
+	}
+
+	return ret;
+}
+
+gboolean
+birb_env_prepend(const char *variable, const char *value,
+                 const char *separator)
+{
+	const char *existing = NULL;
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail(variable != NULL, FALSE);
+	g_return_val_if_fail(variable[0] != '\0', FALSE);
+	g_return_val_if_fail(value != NULL, FALSE);
+	g_return_val_if_fail(separator != NULL, FALSE);
+
+	existing = g_getenv(variable);
+	if(existing != NULL) {
+		char *new_value = NULL;
+
+		new_value = g_build_path(separator, value, existing, NULL);
+
+		ret = g_setenv(variable, new_value, TRUE);
+		g_free(new_value);
+	} else {
+		ret = g_setenv(variable, value, TRUE);
+	}
+
+	return ret;
+}
diff --git a/birb/birbenv.h b/birb/birbenv.h
new file mode 100644
--- /dev/null
+++ b/birb/birbenv.h
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2024 Birb Developers
+ *
+ * Birb is the legal property of its developers, whose names are too
+ * numerous to list here. Please refer to the AUTHORS file distributed
+ * with this source distribution
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#if !defined(BIRB_GLOBAL_HEADER_INSIDE) && !defined(BIRB_COMPILATION)
+# error "only <birb.h> may be included directly"
+#endif
+
+#ifndef BIRB_ENV_H
+#define BIRB_ENV_H
+
+#include <glib.h>
+
+#include "birbversion.h"
+
+G_BEGIN_DECLS
+
+/**
+ * birb_env_append:
+ * @variable: the variable to append to
+ * @value: the value to append
+ * @separator: the separator to use
+ *
+ * Appends a value to an environment variable with the given separator.
+ *
+ * This is meant to be used to add an addition value to a multi-value
+ * environment variable like `PATH`, `GI_TYPELIB_PATH`, etc
+ *
+ * See the documentation for [func@GLib.setenv] for potential issues with this
+ * function.
+ *
+ * Returns: false if the environment variable could not be set.
+ *
+ * Since: 0.3
+ */
+BIRB_AVAILABLE_IN_0_3
+gboolean birb_env_append(const char *variable, const char *value, const char *separator);
+
+/**
+ * birb_env_prepend:
+ * @variable: the variable to prepend to
+ * @value: the value to prepend
+ * @separator: the separator to use
+ *
+ * Prepends a value to an environment variable with the given separator.
+ *
+ * This is meant to be used to add an addition value to a multi-value
+ * environment variable like `PATH`, `GI_TYPELIB_PATH`, etc
+ *
+ * See the documentation for [func@GLib.setenv] for potential issues with this
+ * function.
+ *
+ * Returns: false if the environment variable could not be set.
+ *
+ * Since: 0.3
+ */
+BIRB_AVAILABLE_IN_0_3
+gboolean birb_env_prepend(const char *variable, const char *value, const char *separator);
+
+G_BEGIN_DECLS
+
+#endif /* BIRB_ENV_H */
diff --git a/birb/meson.build b/birb/meson.build
--- a/birb/meson.build
+++ b/birb/meson.build
@@ -4,6 +4,7 @@
   'birbactionmenu.c',
   'birbcustomfilter.c',
   'birbdatetime.c',
+  'birbenv.c',
   'birbfilter.c',
   'birbqueuedoutputstream.c',
   'birbstringobject.c',
@@ -15,6 +16,7 @@
   'birbassert.h',
   'birbcustomfilter.h',
   'birbdatetime.h',
+  'birbenv.h',
   'birbfilter.h',
   'birbqueuedoutputstream.h',
   'birbstringobject.h',
diff --git a/birb/tests/meson.build b/birb/tests/meson.build
--- a/birb/tests/meson.build
+++ b/birb/tests/meson.build
@@ -2,6 +2,7 @@
   'action_menu',
   'custom_filter',
   'date_time',
+  'env',
   'filter',
   'queued_output_stream',
   'string_object',
diff --git a/birb/tests/test_env.c b/birb/tests/test_env.c
new file mode 100644
--- /dev/null
+++ b/birb/tests/test_env.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (C) 2023 Birb Developers
+ *
+ * Birb is the legal property of its developers, whose names are too
+ * numerous to list here. Please refer to the AUTHORS file distributed
+ * with this source distribution
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+ */
+
+#include <glib.h>
+
+#include <birb.h>
+
+/******************************************************************************
+ * Append tests
+ *****************************************************************************/
+static void
+test_birb_env_append_new(void) {
+	const char *value = NULL;
+
+	birb_env_append("TEST_BIRB_APPEND_NEW", "new-value",
+	                G_SEARCHPATH_SEPARATOR_S);
+
+	value = g_getenv("TEST_BIRB_APPEND_NEW");
+	g_assert_cmpstr(value, ==, "new-value");
+}
+
+static void
+test_birb_env_append_existing(void) {
+	const char *value = NULL;
+
+	g_setenv("TEST_BRIB_APPEND_EXISTING", "abc123", TRUE);
+
+	birb_env_append("TEST_BRIB_APPEND_EXISTING", "xyz789",
+	                G_SEARCHPATH_SEPARATOR_S);
+
+	value = g_getenv("TEST_BRIB_APPEND_EXISTING");
+	g_assert_cmpstr(value, ==, "abc123" G_SEARCHPATH_SEPARATOR_S "xyz789");
+}
+
+/******************************************************************************
+ * Prepend tests
+ *****************************************************************************/
+static void
+test_birb_env_prepend_new(void) {
+	const char *value = NULL;
+
+	birb_env_append("TEST_BIRB_PREPEND_NEW", "new-value",
+	                G_SEARCHPATH_SEPARATOR_S);
+
+	value = g_getenv("TEST_BIRB_PREPEND_NEW");
+	g_assert_cmpstr(value, ==, "new-value");
+}
+
+static void
+test_birb_env_prepend_existing(void) {
+	const char *value = NULL;
+
+	g_setenv("TEST_BRIB_PREPEND_EXISTING", "abc123", TRUE);
+
+	birb_env_prepend("TEST_BRIB_PREPEND_EXISTING", "xyz789",
+	                G_SEARCHPATH_SEPARATOR_S);
+
+	value = g_getenv("TEST_BRIB_PREPEND_EXISTING");
+	g_assert_cmpstr(value, ==, "xyz789" G_SEARCHPATH_SEPARATOR_S "abc123");
+}
+
+/******************************************************************************
+ * Main
+ *****************************************************************************/
+int
+main(int argc, char **argv) {
+	g_test_init(&argc, &argv, NULL);
+
+	g_test_set_nonfatal_assertions();
+
+	g_test_add_func("/env/append/new", test_birb_env_append_new);
+	g_test_add_func("/env/append/existing", test_birb_env_append_existing);
+
+	g_test_add_func("/env/prepend/new", test_birb_env_prepend_new);
+	g_test_add_func("/env/prepend/existing", test_birb_env_prepend_existing);
+
+	return g_test_run();
+}
