+2021-01-23 Lancelot SIX <lsix@lancelotsix.com>
+
+ * Makefile.in (SELFTESTS_SRCS): Add
+ unittests/gdb_tilde_expand-selftests.c.
+ * unittests/gdb_tilde_expand-selftests.c: New file.
+
2021-01-22 Andrew Burgess <andrew.burgess@embecosm.com>
PR cli/25956
unittests/filtered_iterator-selftests.c \
unittests/format_pieces-selftests.c \
unittests/function-view-selftests.c \
+ unittests/gdb_tilde_expand-selftests.c \
unittests/gmp-utils-selftests.c \
unittests/lookup_name_info-selftests.c \
unittests/memory-map-selftests.c \
--- /dev/null
+/* Self tests for gdb_tilde_expand
+
+ Copyright (C) 2021 Free Software Foundation, Inc.
+
+ This file is part of GDB.
+
+ 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 3 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 <http://www.gnu.org/licenses/>. */
+
+#include "gdbsupport/common-defs.h"
+#include "gdbsupport/selftest.h"
+#include <cstdlib>
+
+#include "gdbsupport/gdb_tilde_expand.h"
+
+namespace selftests {
+namespace gdb_tilde_expand_tests {
+
+static void
+do_test ()
+{
+ /* Home directory of the user running the test. */
+ const char *c_home = std::getenv ("HOME");
+
+ /* Skip the test if $HOME is not available in the environment. */
+ if (c_home == nullptr)
+ return;
+
+ const std::string home (c_home);
+
+ /* Basic situation. */
+ SELF_CHECK (home == gdb_tilde_expand ("~"));
+
+ /* When given a path that begins by a tilde and refers to a file that
+ does not exist, gdb_tilde expand must still be able to do the tilde
+ expansion. */
+ SELF_CHECK (gdb_tilde_expand ("~/non/existent/directory")
+ == home + "/non/existent/directory");
+
+ /* gdb_tilde_expand only expands tilde and does not try to do any other
+ substitution. */
+ SELF_CHECK (gdb_tilde_expand ("~/*/a.out") == home + "/*/a.out");
+
+ /* gdb_tilde_expand does no modification to a non tilde leading path. */
+ SELF_CHECK (gdb_tilde_expand ("/some/abs/path") == "/some/abs/path");
+ SELF_CHECK (gdb_tilde_expand ("relative/path") == "relative/path");
+
+ /* If $USER is available in the env variables, check the '~user'
+ expansion. */
+ const char *c_user = std::getenv ("USER");
+ if (c_user != nullptr)
+ {
+ const std::string user (c_user);
+ SELF_CHECK (gdb_tilde_expand (("~" + user).c_str ()) == home);
+ SELF_CHECK (gdb_tilde_expand (("~" + user + "/a/b").c_str ())
+ == home + "/a/b");
+ }
+
+ /* Check that an error is thrown when trying to expand home of a unknown
+ user. */
+ try
+ {
+ gdb_tilde_expand ("~no_one_should_have_that_login/a");
+ SELF_CHECK (false);
+ }
+ catch (const gdb_exception_error &e)
+ {
+ SELF_CHECK (e.error == GENERIC_ERROR);
+ SELF_CHECK
+ (*e.message
+ == "Could not find a match for '~no_one_should_have_that_login'.");
+ }
+}
+
+} /* namespace gdb_tilde_expand_tests */
+} /* namespace selftests */
+
+void _initialize_gdb_tilde_expand_selftests ();
+void
+_initialize_gdb_tilde_expand_selftests ()
+{
+ selftests::register_test
+ ("gdb_tilde_expand", selftests::gdb_tilde_expand_tests::do_test);
+}
+2021-01-23 Lancelot SIX <lsix@lancelotsix.com>
+
+ * gdb_tilde_expand.cc (gdb_tilde_expand): Improve
+ implementation.
+ (gdb_tilde_expand_up): Delegate logic to gdb_tilde_expand.
+ * gdb_tilde_expand.h (gdb_tilde_expand): Update description.
+
2021-01-22 Simon Marchi <simon.marchi@polymtl.ca>
* common-debug.h (debug_prefixed_printf_cond_nofunc): New.
along with this program. If not, see <http://www.gnu.org/licenses/>. */
#include "common-defs.h"
+#include <algorithm>
+#include "filenames.h"
#include "gdb_tilde_expand.h"
#include <glob.h>
std::string
gdb_tilde_expand (const char *dir)
{
- gdb_glob glob (dir, GLOB_TILDE_CHECK, NULL);
-
- gdb_assert (glob.pathc () > 0);
- /* "glob" may return more than one match to the path provided by the
- user, but we are only interested in the first match. */
- std::string expanded_dir = glob.pathv ()[0];
-
- return expanded_dir;
+ if (dir[0] != '~')
+ return std::string (dir);
+
+ /* This function uses glob in order to expand the ~. However, this function
+ will fail to expand if the actual dir we are looking for does not exist.
+ Given "~/does/not/exist", glob will fail.
+
+ In order to avoid such limitation, we only use glob to expand "~" and keep
+ "/does/not/exist" unchanged.
+
+ Similarly, to expand ~gdb/might/not/exist, we only expand "~gdb" using
+ glob and leave "/might/not/exist" unchanged. */
+ const std::string d (dir);
+
+ /* Look for the first dir separator (if any) and split d around it. */
+ const auto first_sep
+ = std::find_if (d.cbegin (), d.cend(),
+ [] (const char c) -> bool
+ {
+ return IS_DIR_SEPARATOR (c);
+ });
+ const std::string to_expand (d.cbegin (), first_sep);
+ const std::string remainder (first_sep, d.cend ());
+
+ const gdb_glob glob (to_expand.c_str (), GLOB_TILDE_CHECK, nullptr);
+
+ gdb_assert (glob.pathc () == 1);
+ return std::string (glob.pathv ()[0]) + remainder;
}
/* See gdbsupport/gdb_tilde_expand.h. */
gdb::unique_xmalloc_ptr<char>
gdb_tilde_expand_up (const char *dir)
{
- gdb_glob glob (dir, GLOB_TILDE_CHECK, NULL);
-
- gdb_assert (glob.pathc () > 0);
- /* "glob" may return more than one match to the path provided by the
- user, but we are only interested in the first match. */
- return make_unique_xstrdup (glob.pathv ()[0]);
+ const std::string expanded = gdb_tilde_expand (dir);
+ return make_unique_xstrdup (expanded.c_str ());
}
#ifndef COMMON_GDB_TILDE_EXPAND_H
#define COMMON_GDB_TILDE_EXPAND_H
-/* Perform path expansion (i.e., tilde expansion) on DIR, and return
- the full path. */
+/* Perform tilde expansion on DIR, and return the full path. */
extern std::string gdb_tilde_expand (const char *dir);
/* Same as GDB_TILDE_EXPAND, but return the full path as a