mirror of
https://git.lyx.org/repos/lyx.git
synced 2024-11-09 18:31:04 +00:00
Speed up FileName operator==, such that working with child documents on
Windows and Solaris is again possible. git-svn-id: svn://svn.lyx.org/lyx/lyx-devel/trunk@29444 a592a061-630c-0410-9148-cb99ea01b6c8
This commit is contained in:
parent
1542ddef59
commit
4053db1858
@ -921,49 +921,18 @@ docstring const FileName::relPath(string const & path) const
|
||||
}
|
||||
|
||||
|
||||
// Note: According to Qt, QFileInfo::operator== is undefined when
|
||||
// both files do not exist (Qt4.5 gives true for all non-existent
|
||||
// files, while Qt4.4 compares the filenames).
|
||||
// see:
|
||||
// http://www.qtsoftware.com/developer/task-tracker/
|
||||
// index_html?id=248471&method=entry.
|
||||
bool operator==(FileName const & l, FileName const & r)
|
||||
bool operator==(FileName const & lhs, FileName const & rhs)
|
||||
{
|
||||
// FIXME: In future use Qt.
|
||||
// Qt 4.4: We need to solve this warning from Qt documentation:
|
||||
// * Long and short file names that refer to the same file on Windows are
|
||||
// treated as if they referred to different files.
|
||||
// This is supposed to be fixed for Qt5.
|
||||
FileName const lhs(os::internal_path(l.absFilename()));
|
||||
FileName const rhs(os::internal_path(r.absFilename()));
|
||||
|
||||
if (lhs.empty())
|
||||
// QFileInfo::operator==() returns false if the two QFileInfo are empty.
|
||||
return rhs.empty();
|
||||
|
||||
if (rhs.empty())
|
||||
// Avoid unnecessary checks below.
|
||||
return false;
|
||||
|
||||
lhs.d->refresh();
|
||||
rhs.d->refresh();
|
||||
|
||||
if (!lhs.d->fi.isSymLink() && !rhs.d->fi.isSymLink()) {
|
||||
// Qt already checks if the filesystem is case sensitive or not.
|
||||
// see note above why the extra check with fileName is needed.
|
||||
return lhs.d->fi == rhs.d->fi
|
||||
&& lhs.d->fi.fileName() == rhs.d->fi.fileName();
|
||||
// Firstly, compare the filenames.
|
||||
if (QString::compare(toqstr(lhs.absFilename()),
|
||||
toqstr(rhs.absFilename()),
|
||||
os::isFilesystemCaseSensitive() ?
|
||||
Qt::CaseSensitive : Qt::CaseInsensitive) == 0) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// FIXME: When/if QFileInfo support symlink comparison, remove this code.
|
||||
QFileInfo fi1(lhs.d->fi);
|
||||
if (fi1.isSymLink())
|
||||
fi1 = QFileInfo(fi1.symLinkTarget());
|
||||
QFileInfo fi2(rhs.d->fi);
|
||||
if (fi2.isSymLink())
|
||||
fi2 = QFileInfo(fi2.symLinkTarget());
|
||||
// see note above why the extra check with fileName is needed.
|
||||
return fi1 == fi2 && fi1.fileName() == fi2.fileName();
|
||||
// They don't match, so check whether they point to the same file.
|
||||
return os::isSameFile(lhs.toFilesystemEncoding(), rhs.toFilesystemEncoding());
|
||||
}
|
||||
|
||||
|
||||
|
@ -112,6 +112,9 @@ bool canAutoOpenFile(std::string const & ext, auto_open_mode const mode = VIEW);
|
||||
*/
|
||||
bool autoOpenFile(std::string const & filename, auto_open_mode const mode = VIEW);
|
||||
|
||||
/// Check whether two filenames point to the same file.
|
||||
bool isSameFile(std::string const & fileone, std::string const & filetwo);
|
||||
|
||||
} // namespace os
|
||||
} // namespace support
|
||||
} // namespace lyx
|
||||
|
@ -6,6 +6,7 @@
|
||||
* \author Ruurd A. Reitsma
|
||||
* \author Claus Hentschel
|
||||
* \author Angus Leeming
|
||||
* \author Enrico Forestieri
|
||||
*
|
||||
* Full author contact details are available in file CREDITS.
|
||||
*
|
||||
@ -26,8 +27,8 @@
|
||||
#include <shellapi.h>
|
||||
#include <shlwapi.h>
|
||||
#include <limits.h>
|
||||
|
||||
#include <sys/cygwin.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
using namespace std;
|
||||
|
||||
@ -281,6 +282,21 @@ bool autoOpenFile(string const & filename, auto_open_mode const mode)
|
||||
win_path.c_str(), NULL, NULL, 1)) > 32;
|
||||
}
|
||||
|
||||
|
||||
bool isSameFile(string const & fileone, string const & filetwo)
|
||||
{
|
||||
struct stat st1;
|
||||
struct stat st2;
|
||||
|
||||
if (::stat(fileone.c_str(), &st1) == 0
|
||||
&& ::stat(filetwo.c_str(), &st2) == 0) {
|
||||
return st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev;
|
||||
}
|
||||
|
||||
// One or both files cannot be accessed.
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace os
|
||||
} // namespace support
|
||||
} // namespace lyx
|
||||
|
@ -17,6 +17,8 @@
|
||||
#include "support/FileName.h"
|
||||
#include "support/lstrings.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <Carbon/Carbon.h>
|
||||
#endif
|
||||
@ -215,6 +217,21 @@ bool autoOpenFile(string const & filename, auto_open_mode const mode)
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
bool isSameFile(string const & fileone, string const & filetwo)
|
||||
{
|
||||
struct stat st1;
|
||||
struct stat st2;
|
||||
|
||||
if (::stat(fileone.c_str(), &st1) == 0
|
||||
&& ::stat(filetwo.c_str(), &st2) == 0) {
|
||||
return st1.st_ino == st2.st_ino && st1.st_dev == st2.st_dev;
|
||||
}
|
||||
|
||||
// One or both files cannot be accessed.
|
||||
return false;
|
||||
}
|
||||
|
||||
} // namespace os
|
||||
} // namespace support
|
||||
} // namespace lyx
|
||||
|
@ -389,6 +389,43 @@ bool autoOpenFile(string const & filename, auto_open_mode const mode)
|
||||
to_local8bit(from_utf8(filename)).c_str(), NULL, NULL, 1)) > 32;
|
||||
}
|
||||
|
||||
|
||||
bool isSameFile(string const & fileone, string const & filetwo)
|
||||
{
|
||||
HANDLE h1 = CreateFile(fileone.c_str(), 0,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
HANDLE h2 = CreateFile(filetwo.c_str(), 0,
|
||||
FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
|
||||
if (h1 == INVALID_HANDLE_VALUE || h2 == INVALID_HANDLE_VALUE) {
|
||||
// One or both files cannot be accessed.
|
||||
if (h1 != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(h1);
|
||||
if (h2 != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(h2);
|
||||
return false;
|
||||
}
|
||||
|
||||
BY_HANDLE_FILE_INFORMATION info1;
|
||||
BY_HANDLE_FILE_INFORMATION info2;
|
||||
bool samefile = false;
|
||||
if (GetFileInformationByHandle(h1, &info1) != 0
|
||||
&& GetFileInformationByHandle(h2, &info2) != 0) {
|
||||
// Serial number of the volumes containing the files.
|
||||
ULONG st1_dev = info1.dwVolumeSerialNumber;
|
||||
ULONG st2_dev = info2.dwVolumeSerialNumber;
|
||||
// Unique identifiers associated to the files on the volumes.
|
||||
ULONGLONG highbits = info1.nFileIndexHigh & 0x0000FFFF;
|
||||
ULONGLONG st1_ino = (highbits << sizeof(ULONG)) | info1.nFileIndexLow;
|
||||
highbits = info2.nFileIndexHigh & 0x0000FFFF;
|
||||
ULONGLONG st2_ino = (highbits << sizeof(ULONG)) | info2.nFileIndexLow;
|
||||
samefile = st1_ino == st2_ino && st1_dev == st2_dev;
|
||||
}
|
||||
CloseHandle(h1);
|
||||
CloseHandle(h2);
|
||||
return samefile;
|
||||
}
|
||||
|
||||
} // namespace os
|
||||
} // namespace support
|
||||
} // namespace lyx
|
||||
|
Loading…
Reference in New Issue
Block a user