-
Notifications
You must be signed in to change notification settings - Fork 195
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix OpenStudio Windows crashed during save attempt #4026
Changes from all commits
7de76c9
a30f69b
09b7c8a
b43d1d2
c0d8ae9
73db0ed
59d6a2a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -88,6 +88,8 @@ namespace openstudio { | |
namespace model { | ||
bool replaceDir(const openstudio::path &sourceDir, const openstudio::path &destinationDir) | ||
{ | ||
bool result = true; | ||
|
||
// Path **must** exist for `canonical()` to work, `weakly_canonical()` doesn't require this | ||
const auto src = openstudio::filesystem::weakly_canonical(sourceDir); | ||
const auto dest = openstudio::filesystem::weakly_canonical(destinationDir); | ||
|
@@ -100,21 +102,22 @@ namespace model { | |
} | ||
|
||
// If the source dir doesn't exist, there's a problem | ||
if (!openstudio::filesystem::exists(src) || !openstudio::filesystem::is_directory(src)) | ||
{ | ||
if (!openstudio::filesystem::exists(src) || !openstudio::filesystem::is_directory(src)) { | ||
LOG_FREE(Error, "replaceDir", "Source directory does not exist: " << toString(src)); | ||
return false; | ||
} | ||
|
||
// If the dest dir exists, remove it | ||
if (openstudio::filesystem::exists(dest)) | ||
{ | ||
// If the dest dir exists, remove all entries in it | ||
if (openstudio::filesystem::exists(dest)) { | ||
if (openstudio::filesystem::is_directory(dest)) { | ||
try { | ||
openstudio::filesystem::remove_all(dest); | ||
} catch (const std::exception &e) { | ||
LOG_FREE(Error, "replaceDir", "Destination directory could not be removed: " << toString(dest) << "error: " << e.what()); | ||
return false; | ||
for (openstudio::filesystem::directory_iterator end_dir_it, it(dest); it != end_dir_it; ++it) { | ||
openstudio::filesystem::path path = it->path(); | ||
try { | ||
openstudio::filesystem::remove_all(path); | ||
} catch (const std::exception& e) { | ||
LOG_FREE(Error, "replaceDir", "Error deleting: " << toString(path) << e.what()); | ||
result = false; | ||
} | ||
} | ||
} else { | ||
LOG_FREE(Error, "replaceDir", "Destination exists and is not a directory, aborting: " << toString(dest)); | ||
|
@@ -123,15 +126,19 @@ namespace model { | |
} | ||
|
||
// Now we recreate it, and it must work! | ||
if (!openstudio::filesystem::create_directory(dest)) | ||
{ | ||
LOG_FREE(Error, "replaceDir", "Could not create destination directory: " << toString(dest)); | ||
return false; | ||
if (!openstudio::filesystem::exists(dest)) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @macumber As far as I can tell you're actually no longer trying to remove the directory itself above (should you be after you tried removing everything inside?), so this block is pointless no? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No I think you can hit this if you open a bare OSM file with no companion directory, the companion directory would be created in temp and then would be synched back. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good point! |
||
try { | ||
if (!openstudio::filesystem::create_directory(dest)) { | ||
LOG_FREE(Error, "replaceDir", "Could not create destination directory: " << toString(dest)); | ||
return false; | ||
} | ||
} catch (const std::exception& e) { | ||
LOG_FREE(Error, "replaceDir", "Error creating directory: " << toString(dest) << e.what()); | ||
return false; | ||
} | ||
} | ||
|
||
bool result = true; | ||
for (const auto& dirEnt : openstudio::filesystem::recursive_directory_iterator{src}) | ||
{ | ||
for (const auto& dirEnt : openstudio::filesystem::recursive_directory_iterator{src}) { | ||
const auto& path = dirEnt.path(); | ||
auto relativePathStr = path.string(); | ||
boost::replace_first(relativePathStr, src.string(), ""); | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So before: try to remove entire companion dir.
Now : try to remove all files directly under companion dir, and all subfolders.
To avoid more problems (eg a single file is opened with a handle on it in the files/ subfolder), we should do the same logic recursively, no?
Make safeDeleteDir() function or something: if file try delete, if directory call safeDeleteDir.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah I think that would work too, but the main thing is don't throw an unhandled exception if we try to delete something (file or folder) and it fails. Just log the file and return false. We should try to clean out as many files as we can.