Merge branch 'deprecate-filename-normalize'

Deprecate wxFilename::Normalize() without flags and add convenient
GetAbsolutePath() to be used instead.

See https://github.com/wxWidgets/wxWidgets/pull/2428
This commit is contained in:
Vadim Zeitlin
2021-07-17 17:10:40 +02:00
14 changed files with 146 additions and 81 deletions

View File

@@ -70,9 +70,19 @@ enum wxPathNormalize
wxPATH_NORM_TILDE = 0x0004, // Unix only: replace ~ and ~user wxPATH_NORM_TILDE = 0x0004, // Unix only: replace ~ and ~user
wxPATH_NORM_CASE = 0x0008, // if case insensitive => tolower wxPATH_NORM_CASE = 0x0008, // if case insensitive => tolower
wxPATH_NORM_ABSOLUTE = 0x0010, // make the path absolute wxPATH_NORM_ABSOLUTE = 0x0010, // make the path absolute
wxPATH_NORM_LONG = 0x0020, // make the path the long form wxPATH_NORM_LONG = 0x0020, // make the path the long form (MSW-only)
wxPATH_NORM_SHORTCUT = 0x0040, // resolve the shortcut, if it is a shortcut wxPATH_NORM_SHORTCUT = 0x0040, // resolve the shortcut, if it is a shortcut
wxPATH_NORM_ALL = 0x00ff & ~wxPATH_NORM_CASE
// Don't use this constant, it used to correspond to the default
// Normalize() behaviour but this is deprecated now.
wxPATH_NORM_DEPR_OLD_DEFAULT= 0x00ff & ~wxPATH_NORM_CASE,
// This constant name is misleading, as it doesn't really include all the
// flags above, so its use is discouraged, please use the flags you want
// explicitly instead.
wxPATH_NORM_ALL
wxDEPRECATED_ATTR("specify the wanted flags explicitly to avoid surprises")
= wxPATH_NORM_DEPR_OLD_DEFAULT
}; };
// what exactly should GetPath() return? // what exactly should GetPath() return?
@@ -341,15 +351,21 @@ public:
// operations on the path // operations on the path
// normalize the path: with the default flags value, the path will be // normalize the path using the specified normalizations, use
// made absolute, without any ".." and "." and all environment // MakeAbsolute() for a simpler form applying the standard ones
// variables will be expanded in it
// //
// this may be done using another (than current) value of cwd // this may be done using another (than current) value of cwd
bool Normalize(int flags = wxPATH_NORM_ALL, bool Normalize(int flags,
const wxString& cwd = wxEmptyString, const wxString& cwd = wxEmptyString,
wxPathFormat format = wxPATH_NATIVE); wxPathFormat format = wxPATH_NATIVE);
// using wxPATH_NORM_ALL may give unexpected results, so avoid using
// this function and call Normalize(wxPATH_NORM_ENV_VARS | ...)
// explicitly if you really need environment variables expansion
wxDEPRECATED_MSG("specify the wanted flags explicitly to avoid surprises")
bool Normalize()
{ return Normalize(wxPATH_NORM_DEPR_OLD_DEFAULT); }
// get a path path relative to the given base directory, i.e. opposite // get a path path relative to the given base directory, i.e. opposite
// of Normalize // of Normalize
// //
@@ -361,7 +377,7 @@ public:
bool MakeRelativeTo(const wxString& pathBase = wxEmptyString, bool MakeRelativeTo(const wxString& pathBase = wxEmptyString,
wxPathFormat format = wxPATH_NATIVE); wxPathFormat format = wxPATH_NATIVE);
// make the path absolute // make the path absolute and resolve any "." and ".." in it
// //
// this may be done using another (than current) value of cwd // this may be done using another (than current) value of cwd
bool MakeAbsolute(const wxString& cwd = wxEmptyString, bool MakeAbsolute(const wxString& cwd = wxEmptyString,
@@ -369,6 +385,15 @@ public:
{ return Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE | { return Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_ABSOLUTE |
wxPATH_NORM_TILDE, cwd, format); } wxPATH_NORM_TILDE, cwd, format); }
// Convenient helper for returning the absolute path corresponding to
// the given one.
wxString GetAbsolutePath(const wxString& cwd = wxEmptyString,
wxPathFormat format = wxPATH_NATIVE) const
{
wxFileName fn(*this);
fn.MakeAbsolute(cwd, format);
return fn.GetFullPath();
}
// If the path is a symbolic link (Unix-only), indicate that all // If the path is a symbolic link (Unix-only), indicate that all
// filesystem operations on this path should be performed on the link // filesystem operations on this path should be performed on the link

View File

@@ -370,15 +370,7 @@ protected:
static wxString GetCanonicalPath(const wxFileName& path) static wxString GetCanonicalPath(const wxFileName& path)
{ {
wxFileName path_copy = wxFileName(path); return path.GetAbsolutePath();
if ( !path_copy.Normalize() )
{
wxFAIL_MSG(wxString::Format(wxASCII_STR("Unable to normalize path '%s'"),
path.GetFullPath()));
return wxEmptyString;
}
return path_copy.GetFullPath();
} }

View File

@@ -54,20 +54,52 @@ enum wxSizeConvention
*/ */
enum wxPathNormalize enum wxPathNormalize
{ {
//! Replace environment variables with their values. /**
//! wxFileName understands both Unix and Windows (but only under Windows) environment Replace environment variables with their values.
//! variables expansion: i.e. @c "$var", @c "$(var)" and @c "${var}" are always understood
//! and in addition under Windows @c "%var%" is also. wxFileName understands both Unix and Windows (but only under Windows) environment
variables expansion: i.e. @c "$var", @c "$(var)" and @c "${var}" are always understood
and in addition under Windows @c "%var%" is also.
Note that when this flag is used, dollar or percent signs may be
escaped with backslashes to prevent them from being used for the
variable expansion, meaning that normalizing any path with a directory
starting with a dollar sign under Windows can give unexpected results,
as normalizing @c c:\\foo\\$bar results in @c c:\\foo$bar. Because of
this, using this flag with arbitrary paths is not recommended.
*/
wxPATH_NORM_ENV_VARS = 0x0001, wxPATH_NORM_ENV_VARS = 0x0001,
wxPATH_NORM_DOTS = 0x0002, //!< Squeeze all @c ".." and @c ".". wxPATH_NORM_DOTS = 0x0002, //!< Squeeze all @c ".." and @c ".".
wxPATH_NORM_TILDE = 0x0004, //!< Replace @c "~" and @c "~user" (Unix only). wxPATH_NORM_TILDE = 0x0004, //!< Replace @c "~" and @c "~user" (Unix only).
wxPATH_NORM_CASE = 0x0008, //!< If the platform is case insensitive, make lowercase the path. wxPATH_NORM_CASE = 0x0008, //!< If the platform is case insensitive, make lowercase the path.
wxPATH_NORM_ABSOLUTE = 0x0010, //!< Make the path absolute. wxPATH_NORM_ABSOLUTE = 0x0010, //!< Make the path absolute.
wxPATH_NORM_LONG = 0x0020, //!< Expand the path to the "long" form (Windows only).
/**
Expand the path to the "long" form under Windows.
This flag converts DOS short paths in 8.3 format to long form under
Windows and does nothing under the other platforms. It is mostly
irrelevant nowadays as short paths are not used any longer in practice.
Notice that it only works for the existing file paths.
@see wxFileName::GetLongPath()
*/
wxPATH_NORM_LONG = 0x0020,
wxPATH_NORM_SHORTCUT = 0x0040, //!< Resolve the shortcut, if it is a shortcut (Windows only). wxPATH_NORM_SHORTCUT = 0x0040, //!< Resolve the shortcut, if it is a shortcut (Windows only).
//! A value indicating all normalization flags except for @c wxPATH_NORM_CASE. /**
Flags used by wxFileName::Normalize() by default.
This includes all normalization flags except for @c wxPATH_NORM_CASE
and notably does include @c wxPATH_NORM_ENV_VARS which may yield
unexpected results, as described above. Because of this, this flag is
deprecated and shouldn't be used in the new code and the existing code
should be reviewed to check if expanding environment variables is
really needed.
*/
wxPATH_NORM_ALL = 0x00ff & ~wxPATH_NORM_CASE wxPATH_NORM_ALL = 0x00ff & ~wxPATH_NORM_CASE
}; };
@@ -601,6 +633,17 @@ public:
static wxFileName FileName(const wxString& file, static wxFileName FileName(const wxString& file,
wxPathFormat format = wxPATH_NATIVE); wxPathFormat format = wxPATH_NATIVE);
/**
Returns full absolute path for this file.
This is just a convenient shortcut using MakeAbsolute() and
GetFullPath() internally.
@since 3.1.6
*/
wxString GetAbsolutePath(const wxString& cwd = wxEmptyString,
wxPathFormat format = wxPATH_NATIVE) const;
/** /**
Retrieves the value of the current working directory on the specified volume. Retrieves the value of the current working directory on the specified volume.
If the volume is empty, the program's current working directory is returned for If the volume is empty, the program's current working directory is returned for
@@ -1067,7 +1110,9 @@ public:
Normalize the path. Normalize the path.
With the default flags value, the path will be made absolute, without With the default flags value, the path will be made absolute, without
any ".." and "." and all environment variables will be expanded in it. any ".." and ".", and, for the Unix format paths, any occurrences of
tilde (@c ~) character will be replaced with the home directory of the
user following it.
Notice that in some rare cases normalizing a valid path may result in Notice that in some rare cases normalizing a valid path may result in
an invalid wxFileName object. E.g. normalizing "./" path using an invalid wxFileName object. E.g. normalizing "./" path using
@@ -1078,6 +1123,9 @@ public:
@param flags @param flags
The kind of normalization to do with the file name. It can be The kind of normalization to do with the file name. It can be
any or-combination of the ::wxPathNormalize enumeration values. any or-combination of the ::wxPathNormalize enumeration values.
These values should be explicitly specified, omitting them uses the
deprecated wxPATH_NORM_ALL value which is not recommended, see
wxPathNormalize enum for more details.
@param cwd @param cwd
If not empty, this directory will be used instead of current If not empty, this directory will be used instead of current
working directory in normalization (see @c wxPATH_NORM_ABSOLUTE). working directory in normalization (see @c wxPATH_NORM_ABSOLUTE).
@@ -1086,7 +1134,7 @@ public:
@return @true if normalization was successfully or @false otherwise. @return @true if normalization was successfully or @false otherwise.
*/ */
bool Normalize(int flags = wxPATH_NORM_ALL, bool Normalize(int flags,
const wxString& cwd = wxEmptyString, const wxString& cwd = wxEmptyString,
wxPathFormat format = wxPATH_NATIVE); wxPathFormat format = wxPATH_NATIVE);

View File

@@ -574,17 +574,9 @@ MyFrame::MyFrame()
m_fileHistory = new wxFileHistory(); m_fileHistory = new wxFileHistory();
m_fileHistory->UseMenu(m_fileHistoryMenu); m_fileHistory->UseMenu(m_fileHistoryMenu);
wxFileName fn( "menu.cpp" ); m_fileHistory->AddFileToHistory( wxFileName("menu.cpp").GetAbsolutePath() );
fn.Normalize(); m_fileHistory->AddFileToHistory( wxFileName("Makefile.in").GetAbsolutePath() );
m_fileHistory->AddFileToHistory( fn.GetFullPath() ); m_fileHistory->AddFileToHistory( wxFileName("minimal", "minimal", "cpp").GetAbsolutePath() );
fn = "Makefile.in";
fn.Normalize();
m_fileHistory->AddFileToHistory( fn.GetFullPath() );
fn.Assign("minimal", "minimal", "cpp");
fn.Normalize();
m_fileHistory->AddFileToHistory( fn.GetFullPath() );
fileMenu->AppendSubMenu(m_fileHistoryMenu, "Sample file history"); fileMenu->AppendSubMenu(m_fileHistoryMenu, "Sample file history");
#endif #endif

View File

@@ -601,8 +601,7 @@ void AppFrame::CreateMenu ()
void AppFrame::FileOpen (wxString fname) void AppFrame::FileOpen (wxString fname)
{ {
wxFileName w(fname); w.Normalize(); fname = w.GetFullPath(); m_edit->LoadFile (wxFileName(fname).GetAbsolutePath());
m_edit->LoadFile (fname);
m_edit->SelectNone(); m_edit->SelectNone();
} }

View File

@@ -748,9 +748,7 @@ void WebFrame::OnLoadScheme(wxCommandEvent& WXUNUSED(evt))
pathlist.Add("../help"); pathlist.Add("../help");
pathlist.Add("../../../samples/help"); pathlist.Add("../../../samples/help");
wxFileName helpfile(pathlist.FindValidPath("doc.zip")); wxString path = wxFileName(pathlist.FindValidPath("doc.zip")).GetAbsolutePath();
helpfile.MakeAbsolute();
wxString path = helpfile.GetFullPath();
//Under MSW we need to flip the slashes //Under MSW we need to flip the slashes
path.Replace("\\", "/"); path.Replace("\\", "/");
path = "wxfs:///" + path + ";protocol=zip/doc.htm"; path = "wxfs:///" + path + ";protocol=zip/doc.htm";

View File

@@ -1765,14 +1765,14 @@ bool wxFileName::MakeRelativeTo(const wxString& pathBase, wxPathFormat format)
// get cwd only once - small time saving // get cwd only once - small time saving
wxString cwd = wxGetCwd(); wxString cwd = wxGetCwd();
// Normalize both paths to be absolute but avoid expanding environment // Bring both paths to canonical form.
// variables in them, this could be unexpected. MakeAbsolute(cwd, format);
const int normFlags = wxPATH_NORM_DOTS | fnBase.MakeAbsolute(cwd, format);
wxPATH_NORM_TILDE |
wxPATH_NORM_ABSOLUTE | // Do this here for compatibility, as we used to do it before.
wxPATH_NORM_LONG; Normalize(wxPATH_NORM_LONG, cwd, format);
Normalize(normFlags, cwd, format); fnBase.Normalize(wxPATH_NORM_LONG, cwd, format);
fnBase.Normalize(normFlags, cwd, format);
bool withCase = IsCaseSensitive(format); bool withCase = IsCaseSensitive(format);
@@ -1841,8 +1841,20 @@ bool wxFileName::SameAs(const wxFileName& filepath, wxPathFormat format) const
// get cwd only once - small time saving // get cwd only once - small time saving
wxString cwd = wxGetCwd(); wxString cwd = wxGetCwd();
fn1.Normalize(wxPATH_NORM_ALL | wxPATH_NORM_CASE, cwd, format);
fn2.Normalize(wxPATH_NORM_ALL | wxPATH_NORM_CASE, cwd, format); // apply really all normalizations here
const int normAll =
wxPATH_NORM_ENV_VARS |
wxPATH_NORM_DOTS |
wxPATH_NORM_TILDE |
wxPATH_NORM_CASE |
wxPATH_NORM_ABSOLUTE |
wxPATH_NORM_LONG |
wxPATH_NORM_SHORTCUT
;
fn1.Normalize(normAll, cwd, format);
fn2.Normalize(normAll, cwd, format);
if ( fn1.GetFullPath() == fn2.GetFullPath() ) if ( fn1.GetFullPath() == fn2.GetFullPath() )
return true; return true;
@@ -2619,9 +2631,7 @@ static wxString EscapeFileNameCharsInURL(const char *in)
// Returns the file URL for a native path // Returns the file URL for a native path
wxString wxFileName::FileNameToURL(const wxFileName& filename) wxString wxFileName::FileNameToURL(const wxFileName& filename)
{ {
wxFileName fn = filename; wxString url = filename.GetAbsolutePath(wxString(), wxPATH_NATIVE);
fn.Normalize(wxPATH_NORM_DOTS | wxPATH_NORM_TILDE | wxPATH_NORM_ABSOLUTE);
wxString url = fn.GetFullPath(wxPATH_NATIVE);
#ifndef __UNIX__ #ifndef __UNIX__
// unc notation, wxMSW // unc notation, wxMSW

View File

@@ -77,9 +77,7 @@ wxString wxStandardPathsBase::GetExecutablePath() const
if ( path.empty() ) if ( path.empty() )
return argv0; // better than nothing return argv0; // better than nothing
wxFileName filename(path); return wxFileName(path).GetAbsolutePath();
filename.Normalize();
return filename.GetFullPath();
} }
wxStandardPaths& wxAppTraitsBase::GetStandardPaths() wxStandardPaths& wxAppTraitsBase::GetStandardPaths()

View File

@@ -429,9 +429,7 @@ void wxFileDialog::SetPath(const wxString& path)
// we need an absolute path for GTK native chooser so ensure that we have // we need an absolute path for GTK native chooser so ensure that we have
// it: use the initial directory if it was set or just CWD otherwise (this // it: use the initial directory if it was set or just CWD otherwise (this
// is the default behaviour if m_dir is empty) // is the default behaviour if m_dir is empty)
wxFileName fn(path); m_fc.SetPath(wxFileName(path).GetAbsolutePath(m_dir));
fn.MakeAbsolute(m_dir);
m_fc.SetPath(fn.GetFullPath());
} }
void wxFileDialog::SetDirectory(const wxString& dir) void wxFileDialog::SetDirectory(const wxString& dir)

View File

@@ -817,9 +817,7 @@ wxFSFile* wxChmFSHandler::OpenFile(wxFileSystem& WXUNUSED(fs),
// now work on the right location // now work on the right location
if (right.Contains(wxT(".."))) if (right.Contains(wxT("..")))
{ {
wxFileName abs(right); right = wxFileName(right).GetAbsolutePath(wxT("/"));
abs.MakeAbsolute(wxT("/"));
right = abs.GetFullPath();
} }
// a workaround for absolute links to root // a workaround for absolute links to root

View File

@@ -314,12 +314,7 @@ wxString wxXmlResource::ConvertFileNameToURL(const wxString& filename)
{ {
// Make the name absolute filename, because the app may // Make the name absolute filename, because the app may
// change working directory later: // change working directory later:
wxFileName fn(fnd); fnd = wxFileName(fnd).GetAbsolutePath();
if (fn.IsRelative())
{
fn.MakeAbsolute();
fnd = fn.GetFullPath();
}
#if wxUSE_FILESYSTEM #if wxUSE_FILESYSTEM
fnd = wxFileSystem::FileNameToURL(fnd); fnd = wxFileSystem::FileNameToURL(fnd);
#endif #endif

View File

@@ -36,6 +36,10 @@
#include "testfile.h" #include "testfile.h"
#include "testdate.h" #include "testdate.h"
// Use a hack to keep using wxPATH_NORM_ALL in this test code without getting
// deprecation warnings for it.
#define wxPATH_NORM_ALL wxPATH_NORM_DEPR_OLD_DEFAULT
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// test data // test data
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
@@ -201,8 +205,8 @@ TEST_CASE("wxFileName::Comparison", "[filename]")
{ {
wxFileName fn1(wxT("/tmp/file1")); wxFileName fn1(wxT("/tmp/file1"));
wxFileName fn2(wxT("/tmp/dir2/../file2")); wxFileName fn2(wxT("/tmp/dir2/../file2"));
fn1.Normalize(); fn1.MakeAbsolute();
fn2.Normalize(); fn2.MakeAbsolute();
CHECK(fn1.GetPath() == fn2.GetPath()); CHECK(fn1.GetPath() == fn2.GetPath());
} }
@@ -258,6 +262,14 @@ TEST_CASE("wxFileName::Normalize", "[filename]")
if (cwd.Contains(wxT(':'))) if (cwd.Contains(wxT(':')))
cwd = cwd.AfterFirst(wxT(':')); cwd = cwd.AfterFirst(wxT(':'));
static const char* pathWithEnvVar =
#ifdef __WINDOWS__
"%ABCDEF%/g/h/i"
#else
"$(ABCDEF)/g/h/i"
#endif
;
static const struct FileNameTest static const struct FileNameTest
{ {
const char *original; const char *original;
@@ -267,11 +279,7 @@ TEST_CASE("wxFileName::Normalize", "[filename]")
} tests[] = } tests[] =
{ {
// test wxPATH_NORM_ENV_VARS // test wxPATH_NORM_ENV_VARS
#ifdef __WINDOWS__ { pathWithEnvVar, wxPATH_NORM_ENV_VARS, "abcdef/g/h/i", wxPATH_UNIX },
{ "%ABCDEF%/g/h/i", wxPATH_NORM_ENV_VARS, "abcdef/g/h/i", wxPATH_UNIX },
#else
{ "$(ABCDEF)/g/h/i", wxPATH_NORM_ENV_VARS, "abcdef/g/h/i", wxPATH_UNIX },
#endif
// test wxPATH_NORM_DOTS // test wxPATH_NORM_DOTS
{ "a/.././b/c/../../", wxPATH_NORM_DOTS, "", wxPATH_UNIX }, { "a/.././b/c/../../", wxPATH_NORM_DOTS, "", wxPATH_UNIX },
@@ -317,6 +325,9 @@ TEST_CASE("wxFileName::Normalize", "[filename]")
{ ".\\foo", wxPATH_NORM_LONG, ".\\foo", wxPATH_DOS }, { ".\\foo", wxPATH_NORM_LONG, ".\\foo", wxPATH_DOS },
{ "..\\Makefile.in", wxPATH_NORM_LONG, "..\\Makefile.in", wxPATH_DOS }, { "..\\Makefile.in", wxPATH_NORM_LONG, "..\\Makefile.in", wxPATH_DOS },
{ "..\\foo", wxPATH_NORM_LONG, "..\\foo", wxPATH_DOS }, { "..\\foo", wxPATH_NORM_LONG, "..\\foo", wxPATH_DOS },
// test default behaviour with deprecated wxPATH_NORM_ALL
{ pathWithEnvVar, wxPATH_NORM_ALL, "CWD/abcdef/g/h/i", wxPATH_UNIX },
}; };
// set the env var ABCDEF // set the env var ABCDEF
@@ -345,6 +356,11 @@ TEST_CASE("wxFileName::Normalize", "[filename]")
); );
} }
// Check that paths are made absolute, but environment variables are not
// expanded in them.
CHECK( wxFileName(pathWithEnvVar).GetAbsolutePath()
== wxFileName(wxGetCwd() + "/" + pathWithEnvVar).GetFullPath() );
// MSW-only test for wxPATH_NORM_LONG: notice that we only run it if short // MSW-only test for wxPATH_NORM_LONG: notice that we only run it if short
// names generation is not disabled for this system as otherwise the file // names generation is not disabled for this system as otherwise the file
// MKINST~1 doesn't exist at all and normalizing it fails (it's possible // MKINST~1 doesn't exist at all and normalizing it fails (it's possible

View File

@@ -44,9 +44,7 @@ wxString AutoCaptureMechanism::default_dir = wxT("screenshots");
/* static */ /* static */
wxString AutoCaptureMechanism::GetDefaultDirectoryAbsPath() wxString AutoCaptureMechanism::GetDefaultDirectoryAbsPath()
{ {
wxFileName output = wxFileName::DirName(GetDefaultDirectory()); return wxFileName::DirName(GetDefaultDirectory()).GetAbsolutePath();
output.MakeAbsolute();
return output.GetFullPath();
} }
/* static */ /* static */

View File

@@ -337,9 +337,7 @@ void XmlResApp::ParseParams(const wxCmdLineParser& cmdline)
} }
if (!parOutput.empty()) if (!parOutput.empty())
{ {
wxFileName fn(parOutput); parOutput = wxFileName(parOutput).GetAbsolutePath();
fn.Normalize();
parOutput = fn.GetFullPath();
parOutputPath = wxPathOnly(parOutput); parOutputPath = wxPathOnly(parOutput);
} }
if (!parOutputPath) parOutputPath = wxT("."); if (!parOutputPath) parOutputPath = wxT(".");