Allow relative paths on non-existent directories #4271
Conversation
@@ -1416,7 +1416,7 @@ QString SampleBuffer::tryToMakeRelative( const QString & file ) | |||
if( QFileInfo( file ).isRelative() == false ) | |||
{ | |||
// Normalize the path | |||
QString f = QFileInfo( file ).canonicalFilePath().replace( QDir::separator(), '/' ); | |||
QString f( QDir::cleanPath( file ).replace( QDir::separator(), '/' ) ); |
PhysSong
Mar 23, 2018
Member
Just a reminder, .replace( QDir::separator(), '/' )
can be removed when Qt4 support is completely dropped later.
Just a reminder, .replace( QDir::separator(), '/' )
can be removed when Qt4 support is completely dropped later.
tresf
Mar 23, 2018
Author
Member
Just a reminder, .replace( QDir::separator(), '/' )
can be removed when Qt4 support is completely dropped later.
Good to know... can you elaborate? Is the default behavior to use /
in Qt5? If so where is this documented and is this across all Qt functions?
Just a reminder,
.replace( QDir::separator(), '/' )
can be removed when Qt4 support is completely dropped later.
Good to know... can you elaborate? Is the default behavior to use /
in Qt5? If so where is this documented and is this across all Qt functions?
tresf
Mar 23, 2018
Author
Member
Documented in http://doc.qt.io/qt-5/qdir.html#cleanPath
Yeah that doesn't have any "since qt5" warnings, so I just thought it was an example. Thanks for clarification.
Documented in http://doc.qt.io/qt-5/qdir.html#cleanPath
Yeah that doesn't have any "since qt5" warnings, so I just thought it was an example. Thanks for clarification.
tresf
Mar 23, 2018
•
Author
Member
For comparison:
4.8:
Removes all multiple directory separators "/"
and resolves any "."
s or ".."
s found in the path, path
.
5.x:
Returns path with directory separators normalized (converted to "/"
) and redundant ones removed, and "."
s and ".."
s resolved (as far as possible).
So I hope you understand my hesitation. :)
For comparison:
4.8:
Removes all multiple directory separators
"/"
and resolves any"."
s or".."
s found in the path,path
.
5.x:
Returns path with directory separators normalized (converted to
"/"
) and redundant ones removed, and"."
s and".."
s resolved (as far as possible).
So I hope you understand my hesitation. :)
tresf
Mar 23, 2018
Author
Member
Hmm.... Here's the code for posterity...
static QString qt_cleanPath(const QString &path, bool *ok)
--
{
if (path.isEmpty())
return path;
QString name = path;
QChar dir_separator = QDir::separator();
if (dir_separator != QLatin1Char('/'))
name.replace(dir_separator, QLatin1Char('/'));
QString ret = qt_normalizePathSegments(name, OSSupportsUncPaths, ok);
// Strip away last slash except for root directories
if (ret.length() > 1 && ret.endsWith(QLatin1Char('/'))) {
#if defined (Q_OS_WIN)
# if defined(Q_OS_WINRT)
if (!((ret.length() == 3 \|\| ret.length() == QDir::rootPath().length()) && ret.at(1) == QLatin1Char(':')))
# else
if (!(ret.length() == 3 && ret.at(1) == QLatin1Char(':')))
# endif
#endif
ret.chop(1);
}
return ret;
}
The only function that seems like it would touch \\
would be the qt_normalizePathSegments.cpp
, but that specifically says in the source
// This method is shared with QUrl, so it doesn't deal with QDir::separator() ...
I guess I'll take your word for it. :)
Hmm.... Here's the code for posterity...
static QString qt_cleanPath(const QString &path, bool *ok)
--
{
if (path.isEmpty())
return path;
QString name = path;
QChar dir_separator = QDir::separator();
if (dir_separator != QLatin1Char('/'))
name.replace(dir_separator, QLatin1Char('/'));
QString ret = qt_normalizePathSegments(name, OSSupportsUncPaths, ok);
// Strip away last slash except for root directories
if (ret.length() > 1 && ret.endsWith(QLatin1Char('/'))) {
#if defined (Q_OS_WIN)
# if defined(Q_OS_WINRT)
if (!((ret.length() == 3 \|\| ret.length() == QDir::rootPath().length()) && ret.at(1) == QLatin1Char(':')))
# else
if (!(ret.length() == 3 && ret.at(1) == QLatin1Char(':')))
# endif
#endif
ret.chop(1);
}
return ret;
}
The only function that seems like it would touch \\
would be the qt_normalizePathSegments.cpp
, but that specifically says in the source
// This method is shared with QUrl, so it doesn't deal with QDir::separator() ...
I guess I'll take your word for it. :)
Wallacoloo
Mar 23, 2018
Member
@tresf it's about a third of the way down in that qt_cleanPath
function:
name.replace(dir_separator, QLatin1Char('/'));
How do you feel about adding a short code comment explaining why we run .replace( QDir::separator(), '/' )
(maybe just linking to #4271 ) so that nobody else accidentally removes it, forgetting about Qt4 support?
@tresf it's about a third of the way down in that qt_cleanPath
function:
name.replace(dir_separator, QLatin1Char('/'));
How do you feel about adding a short code comment explaining why we run .replace( QDir::separator(), '/' )
(maybe just linking to #4271 ) so that nobody else accidentally removes it, forgetting about Qt4 support?
PhysSong
Mar 23, 2018
Member
Looking into Qt4's code, I found that even Qt 4.0 has the replacement logic. So we can safely remove that.
Looking into Qt4's code, I found that even Qt 4.0 has the replacement logic. So we can safely remove that.
tresf
Mar 23, 2018
Author
Member
dir_separator
, got it! Missed that one. Thanks!
So we can safely remove that.
Agreed. Will do.
dir_separator
, got it! Missed that one. Thanks!
So we can safely remove that.
Agreed. Will do.
I haven't actually tested any of this code myself (e.g for regressions to #4267). For starters, I was confused that @PhysSong I'll let you merge this one since you're the bug submitter and the most likely to have tested this. :) |
Seems like a lot of chatter over a string replacement, but this knowledge is only going to benefit the project for years to come. Thanks for the digging. |
I found some more places where |
@PhysSong Given this PR is from a tresf branch, I don't think you can easily add your own changes on top of this PR. I would say merge this one and then create a new PR for your changes. |
Actually GitHub allows PRs to be modified now. It's a great feature especially for abandoned ones. we do it fairly often now. :) |
What I'd like to do is using index 141085dd2..62bebff7c 100644
--- a/src/core/SampleBuffer.cpp
+++ b/src/core/SampleBuffer.cpp
@@ -1425,7 +1425,7 @@ QString SampleBuffer::tryToMakeRelative( const QString & file )
// Iterate over all valid "data:/" searchPaths
for ( const QString & path : QDir::searchPaths( "data" ) )
{
- QString samplesPath = QString( path + samplesSuffix ).replace( QDir::separator(), '/' );
+ QString samplesPath = QDir::cleanPath( path + samplesSuffix ) + "/";
if ( f.startsWith( samplesPath ) )
{
return QString( f ).mid( samplesPath.length() ); |
Not sure how well the |
@@ -1425,7 +1425,7 @@ QString SampleBuffer::tryToMakeRelative( const QString & file ) | |||
// Iterate over all valid "data:/" searchPaths | |||
for ( const QString & path : QDir::searchPaths( "data" ) ) | |||
{ | |||
QString samplesPath = QString( path + samplesSuffix ).replace( QDir::separator(), '/' ); | |||
QString samplesPath = QDir::cleanPath( path + samplesSuffix ) + "/"; |
tresf
Mar 27, 2018
Author
Member
I believe ensureTrailingSlash
may be better here. The previous logic doesn't add any slashes.
I believe ensureTrailingSlash
may be better here. The previous logic doesn't add any slashes.
PhysSong
Mar 27, 2018
Member
Maybe, but don't have to be. QDir::cleanPath
always strips trailing slash and previous logic always gives a path with trailing slash.
BTW, ensureTrailingSlash
is defined in ConfigManager.cpp
. If you want to use that function, you should move that into an header first.
Maybe, but don't have to be. QDir::cleanPath
always strips trailing slash and previous logic always gives a path with trailing slash.
BTW, ensureTrailingSlash
is defined in ConfigManager.cpp
. If you want to use that function, you should move that into an header first.
Didn't know about trailing slash strip. That's nice. Looks good then. Merge? |
Switch
SampleBuffer::tryToMakeRelative(...)
to usecleanPath
instead ofcanonicalFilePath
.canonicalFilePath
has several limitations including: