+ if ( (!prjHasUNCName && fileHasUNCName)
+ || ( prjHasUNCName && !fileHasUNCName) )
Maybe I'm a little pedantic here, but couldn't that be written as...
if(prjHasUNCName != fileHasUNCName)
?
Anyway, here's the core of your patch:
@@ -358,12 +380,37 @@
for (FilesList::iterator it = m_Files.begin(); it != m_Files.end(); ++it)
{
ProjectFile* f = (*it);
-
if (!f)
continue;
wxString fileName = f->file.GetFullPath();
- f->relativeToCommonTopLevelPath = fileName.Right(fileName.Length() - m_CommonTopLevelPath.Length());
+ fileHasUNCName = fileName.StartsWith(_T("\\\\"));
+
+ if ( (prjHasUNCName && fileHasUNCName)
+ || ( !prjHasUNCName
+ && !fileHasUNCName
+ && vol.IsSameAs(f->file.GetVolume()) ) )
+ {
+ wxFileName relFileCTLP(f->file);
+ relFileCTLP.MakeRelativeTo( m_CommonTopLevelPath );
+ wxFileName relFileBase(f->file);
+ relFileBase.MakeRelativeTo( GetBasePath() );
+
+ // The commented (old) method to obtain the relativeToCommonTopLevelPath is fast, but does *not* work, if you save
+ // the project on a different drive in a sub-folder of an existing source file on that (different) drive:
+ // I.e.: Project on C:\Folder\Project.cbp has file C:\Folder\SubFolder\foo.cpp and D:\Folder\bar.cpp
+ // Saved the project under D:\Folder\SubFolder\ProjectNew.cbp would cause a wrong computation of bar.cpp otherwise!!!
+// f->relativeToCommonTopLevelPath = fileName.Right(fileName.Length() - m_CommonTopLevelPath.Length());
+ // Using wxFileName instead, although its costly:
+ f->relativeToCommonTopLevelPath = relFileCTLP.GetFullPath();
+ f->relativeFilename = relFileBase.GetFullPath();
+ }
+ else
+ {
+ f->relativeToCommonTopLevelPath = fileName;
+ f->relativeFilename = fileName;
+ }
+
It looks pretty good to me; It uses wxFilename only when necessary. Anyway, I'm thinking that these two lines
+ f->relativeToCommonTopLevelPath = relFileCTLP.GetFullPath();
+ f->relativeFilename = relFileBase.GetFullPath();
could be optimized further by adding a path "cache" and comparing the file's relative pathname (the path without the filename) with the last file's pathname, and using the last calculated relativeToCommonTopLevelPath and relativeFilename instead of just calling wxFilename right away. This was my original proposal, btw, but all the other optimizations submitted here seem pretty rad
EDIT: OH, WAIT A MINUTE!!! I re-read that patch again...
+ if ( (prjHasUNCName && fileHasUNCName)
+ || ( !prjHasUNCName
+ && !fileHasUNCName
+ && vol.IsSameAs(f->file.GetVolume()) ) )
+ {
This is the precondition for the fast calculation, right? And then you're just undoing all the optimizations here! If the only failing case happens when the old project's drive is different than the current one, why not add a condition that specifically says so?
if(prjHasChangedDrives) { // prjHasChangedDrives is the real issue here, isn't it?
// If it has either changed windows drives or UNC network drives, we should use the full method;
// Otherwise, the fast one.
// Calculating prjHasChangedDrives should be trivial, anyway.
wxFileName relFileCTLP(f->file);
relFileCTLP.MakeRelativeTo( m_CommonTopLevelPath );
wxFileName relFileBase(f->file);
relFileBase.MakeRelativeTo( GetBasePath() );
f->relativeToCommonTopLevelPath = relFileCTLP.GetFullPath();
f->relativeFilename = relFileBase.GetFullPath();
} else {
f->relativeToCommonTopLevelPath = fileName.Right(fileName.Length() - m_CommonTopLevelPath.Length());
}