Implemented tilde expansion, internal stream path names are now absolute, fixed tests

This commit is contained in:
Matthias Koefferlein 2023-04-07 00:19:10 +02:00
parent c6bfb03a18
commit 19fbc5c144
6 changed files with 74 additions and 15 deletions

View File

@ -500,7 +500,7 @@ TEST(11_ErrorOnCircuitRedefinition)
msg = ex.msg ();
}
EXPECT_EQ (tl::replaced (msg, path, "?"), "Redefinition of circuit SUBCKT in ?, line 20");
EXPECT_EQ (tl::replaced (msg, tl::absolute_file_path (path), "?"), "Redefinition of circuit SUBCKT in ?, line 20");
}
TEST(12_IgnoreDuplicateGlobals)
@ -580,7 +580,7 @@ TEST(14_IncludeWithError)
reader.read (is, nl);
EXPECT_EQ (true, false); // must not happen
} catch (tl::Exception &ex) {
EXPECT_EQ (ex.msg (), "'M' element must have four nodes in " + std::string (tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "nreader14x.cir")) + ", line 3");
EXPECT_EQ (ex.msg (), "'M' element must have four nodes in " + std::string (tl::absolute_file_path (tl::combine_path (tl::combine_path (tl::testdata (), "algo"), "nreader14x.cir"))) + ", line 3");
}
}

View File

@ -24,6 +24,7 @@
#include "tlStream.h"
#include "tlLog.h"
#include "tlInternational.h"
#include "tlEnv.h"
#include <cctype>
@ -59,6 +60,7 @@
# include <unistd.h>
# include <dirent.h>
# include <dlfcn.h>
# include <pwd.h>
#endif
@ -629,7 +631,7 @@ bool chdir (const std::string &path)
static std::pair<std::string, bool> absolute_path_of_existing (const std::string &s)
{
#if defined (_WIN32)
#if defined(_WIN32)
wchar_t *fp = _wfullpath (NULL, tl::to_wstring (s).c_str (), 0);
if (fp == NULL) {
@ -657,6 +659,11 @@ static std::pair<std::string, bool> absolute_path_of_existing (const std::string
bool is_absolute (const std::string &s)
{
// ~ paths are always absolute, because the home directory is
if (s.size () > 0 && s[0] == '~') {
return true;
}
std::vector<std::string> parts = split_path (s);
if (parts.size () > 1 && is_drive (parts [0])) {
return is_part_with_separator (parts [1]);
@ -669,6 +676,11 @@ bool is_absolute (const std::string &s)
std::string absolute_file_path (const std::string &s)
{
// ~ paths are always absolute, because the home directory is
if (s.size () > 0 && s[0] == '~') {
return get_home_path () + std::string (s, 1);
}
std::vector<std::string> parts = split_path (s);
if (parts.empty ()) {
return current_dir ();
@ -854,10 +866,34 @@ bool is_same_file (const std::string &a, const std::string &b)
#endif
}
std::string
get_home_path ()
{
#if !defined(_WIN32)
if (tl::has_env ("HOME")) {
return tl::get_env ("HOME");
} else {
struct passwd *pwd = getpwuid (getuid ());
if (pwd) {
return std::string (pwd->pw_dir);
}
}
tl::warn << tl::to_string (tr ("Unable to get home directory (set HOME environment variable)"));
#else
if (tl::has_env ("HOMEDRIVE") && tl::has_env ("HOMEPATH")) {
return tl::get_env ("HOMEDRIVE") + tl::get_env ("HOMEPATH");
} else if (tl::has_env ("HOMESHARE") && tl::has_env ("HOMEPATH")) {
return tl::get_env ("HOMESHARE") + tl::get_env ("HOMEPATH");
}
tl::warn << tl::to_string (tr ("Unable to get home directory (no HOMEDRIVE/HOMEPATH or HOMESHARE/HOMEPATH environment variables)"));
#endif
return std::string (".");
}
static std::string
get_inst_path_internal ()
{
#ifdef _WIN32
#if defined(_WIN32)
wchar_t buffer[MAX_PATH];
int len;

View File

@ -194,6 +194,11 @@ bool TL_PUBLIC chdir (const std::string &path);
*/
std::vector<std::string> TL_PUBLIC split_path (const std::string &p, bool keep_last = false);
/**
* @brief Gets the home directory path
*/
std::string TL_PUBLIC get_home_path ();
/**
* @brief Gets the path of the currently running process
*/

View File

@ -666,15 +666,15 @@ TextInputStream::reset ()
InputFile::InputFile (const std::string &path)
: m_fd (-1)
{
m_source = path;
m_source = tl::absolute_file_path (path);;
#if defined(_WIN32)
int fd = _wopen (tl::to_wstring (path).c_str (), _O_BINARY | _O_RDONLY | _O_SEQUENTIAL);
int fd = _wopen (tl::to_wstring (m_source).c_str (), _O_BINARY | _O_RDONLY | _O_SEQUENTIAL);
if (fd < 0) {
throw FileOpenErrorException (m_source, errno);
}
m_fd = fd;
#else
int fd = open (path.c_str (), O_RDONLY);
int fd = open (m_source.c_str (), O_RDONLY);
if (fd < 0) {
throw FileOpenErrorException (m_source, errno);
}
@ -747,15 +747,15 @@ InputFile::filename () const
InputZLibFile::InputZLibFile (const std::string &path)
: mp_d (new ZLibFilePrivate ())
{
m_source = path;
m_source = tl::absolute_file_path (path);
#if defined(_WIN32)
int fd = _wopen (tl::to_wstring (path).c_str (), _O_BINARY | _O_RDONLY | _O_SEQUENTIAL);
int fd = _wopen (tl::to_wstring (m_source).c_str (), _O_BINARY | _O_RDONLY | _O_SEQUENTIAL);
if (fd < 0) {
throw FileOpenErrorException (m_source, errno);
}
mp_d->zs = gzdopen (fd, "rb");
#else
mp_d->zs = gzopen (tl::string_to_system (path).c_str (), "rb");
mp_d->zs = gzopen (tl::string_to_system (m_source).c_str (), "rb");
#endif
if (mp_d->zs == NULL) {
throw FileOpenErrorException (m_source, errno);
@ -1035,10 +1035,10 @@ OutputStream::seek (size_t pos)
// OutputFileBase implementation
OutputFileBase::OutputFileBase (const std::string &path, int keep_backups)
: m_keep_backups (keep_backups), m_path (path), m_has_error (false)
: m_keep_backups (keep_backups), m_path (tl::absolute_file_path (path)), m_has_error (false)
{
if (tl::file_exists (path)) {
m_backup_path = path + ".~backup";
if (tl::file_exists (m_path)) {
m_backup_path = m_path + ".~backup";
if (tl::file_exists (m_backup_path)) {
if (! tl::rm_file (m_backup_path)) {
tl::warn << tl::sprintf (tl::to_string (tr ("Could not create backup file: unable to remove existing file '%s'")), m_backup_path);
@ -1046,8 +1046,8 @@ OutputFileBase::OutputFileBase (const std::string &path, int keep_backups)
}
}
if (! m_backup_path.empty ()) {
if (! tl::rename_file (path, tl::filename (m_backup_path))) {
tl::warn << tl::sprintf (tl::to_string (tr ("Could not create backup file: unable to rename original file '%s' to backup file")), path, m_backup_path);
if (! tl::rename_file (m_path, tl::filename (m_backup_path))) {
tl::warn << tl::sprintf (tl::to_string (tr ("Could not create backup file: unable to rename original file '%s' to backup file")), m_path, m_backup_path);
m_backup_path = std::string ();
}
}

View File

@ -401,6 +401,8 @@ TEST (10)
EXPECT_EQ (tl::extension_last ("\\hello\\.world.gz"), "gz");
EXPECT_EQ (tl::extension_last ("/hello//world/"), "");
EXPECT_EQ (tl::is_absolute ("~/world"), true);
EXPECT_EQ (tl::is_absolute ("~"), true);
EXPECT_EQ (tl::is_absolute ("world"), false);
EXPECT_EQ (tl::is_absolute ("world/"), false);
EXPECT_EQ (tl::is_absolute ("hello//world/"), false);
@ -796,3 +798,18 @@ TEST (18)
EXPECT_EQ (is.read_all (), "hello, world!\n");
}
}
// get_home_path
TEST (19)
{
std::string home = tl::get_home_path ();
// no specific value, just something ...
EXPECT_EQ (home.size () > 5, true);
}
// absolute path with "~" expansion
TEST (20)
{
EXPECT_EQ (tl::absolute_file_path ("~"), tl::get_home_path ());
EXPECT_EQ (tl::absolute_file_path (tl::combine_path ("~", "test")), tl::combine_path (tl::get_home_path (), "test"));
}

View File

@ -167,6 +167,7 @@ END
nl = RBA::Netlist::new
input = File.join($ut_testsrc, "testdata", "algo", "nreader6.cir")
input = File.absolute_path(input)
mydelegate = MyNetlistSpiceReaderDelegate::new