OutputFileHandler.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036 #include "OutputFileHandler.hpp"
00037
00038 #include <cstdlib>
00039
00040 #include "ArchiveLocationInfo.hpp"
00041 #include "BoostFilesystem.hpp"
00042 #include "Exception.hpp"
00043 #include "FileFinder.hpp"
00044 #include "GetCurrentWorkingDirectory.hpp"
00045 #include "PetscTools.hpp"
00046
00047
00048 const std::string OutputFileHandler::SIG_FILE_NAME(".chaste_deletable_folder");
00049
00057 void CleanFolder(const fs::path& rPath, bool isTop=true);
00058
00059 void CleanFolder(const fs::path& rPath, bool isTop)
00060 {
00061 assert(fs::is_directory(rPath));
00062 fs::directory_iterator end_iter;
00063
00064 for (fs::directory_iterator dir_iter(rPath); dir_iter != end_iter; ++dir_iter)
00065 {
00066 if (fs::is_directory(dir_iter->status()))
00067 {
00068 CleanFolder(dir_iter->path(), false);
00069 }
00070 else
00071 {
00072 const fs::path& r_item_path(dir_iter->path());
00073 if (!isTop || PATH_LEAF_NAME(r_item_path)[0] != '.')
00074 {
00075 fs::remove(r_item_path);
00076 }
00077 }
00078 }
00079
00080 if (!isTop)
00081 {
00082 fs::remove(rPath);
00083 }
00084 }
00085
00086
00087 OutputFileHandler::OutputFileHandler(const std::string& rDirectory,
00088 bool cleanOutputDirectory)
00089 {
00090 CommonConstructor(rDirectory, cleanOutputDirectory);
00091 }
00092
00093
00094 OutputFileHandler::OutputFileHandler(const FileFinder& rDirectory,
00095 bool cleanOutputDirectory)
00096 {
00097 FileFinder output_root("", RelativeTo::ChasteTestOutput);
00098 std::string relative_path;
00099 try
00100 {
00101 relative_path = rDirectory.GetRelativePath(output_root);
00102 }
00103 catch (const Exception&)
00104 {
00105 EXCEPTION("The location provided to OutputFileHandler must be inside CHASTE_TEST_OUTPUT; '"
00106 << rDirectory.GetAbsolutePath() << "' is not under '"
00107 << output_root.GetAbsolutePath() << "'.");
00108 }
00109 if (*output_root.GetAbsolutePath().rbegin() != '/' && !relative_path.empty())
00110 {
00111 assert(*relative_path.begin() == '/');
00112 relative_path.erase(0, 1);
00113 }
00114 CommonConstructor(relative_path, cleanOutputDirectory);
00115 }
00116
00117
00118 void OutputFileHandler::CommonConstructor(const std::string &rDirectory,
00119 bool cleanOutputDirectory)
00120 {
00121
00122 if (rDirectory.find("..") != std::string::npos)
00123 {
00124 EXCEPTION("Will not create directory: " + rDirectory +
00125 " due to it potentially being above, and cleaning, CHASTE_TEST_OUTPUT.");
00126
00127 }
00128
00129
00130
00131
00132 if (fs::path(rDirectory).has_root_path())
00133 {
00134 EXCEPTION("The constructor argument to OutputFileHandler must be a relative path; '"
00135 << rDirectory << "' is absolute.");
00136 }
00137
00138 mDirectory = MakeFoldersAndReturnFullPath(rDirectory);
00139
00140
00141 if (rDirectory != "" && cleanOutputDirectory)
00142 {
00143 FileFinder signature_file(mDirectory + SIG_FILE_NAME, RelativeTo::Absolute);
00144 if (!signature_file.Exists())
00145 {
00146 EXCEPTION("Cannot delete " + mDirectory + " because signature file \"" + SIG_FILE_NAME + "\" is not present.");
00147 }
00148
00149
00150 if (PetscTools::AmMaster())
00151 {
00152 CleanFolder(mDirectory);
00153 }
00154
00155 PetscTools::Barrier("OutputFileHandler");
00156 }
00157 }
00158
00159 std::string OutputFileHandler::GetChasteTestOutputDirectory()
00160 {
00161 char *chaste_test_output = getenv("CHASTE_TEST_OUTPUT");
00162 FileFinder directory_root;
00163 if (chaste_test_output == NULL || *chaste_test_output == 0)
00164 {
00165
00166 directory_root.SetPath("testoutput", RelativeTo::CWD);
00167 }
00168 else
00169 {
00170 directory_root.SetPath(chaste_test_output, RelativeTo::AbsoluteOrCwd);
00171 }
00172
00173
00174 std::string chaste_test_output_directory = directory_root.GetAbsolutePath();
00175 AddTrailingSlash(chaste_test_output_directory);
00176 return chaste_test_output_directory;
00177 }
00178
00179 std::string OutputFileHandler::MakeFoldersAndReturnFullPath(const std::string& rDirectory) const
00180 {
00181 fs::path output_root(GetChasteTestOutputDirectory());
00182 fs::path rel_path(rDirectory);
00183
00184 if (!rel_path.empty() && (*(--rel_path.end())) == ".")
00185 {
00186
00187 rel_path.remove_leaf();
00188 }
00189
00190
00191 if (PetscTools::AmMaster())
00192 {
00193 try
00194 {
00195
00196 fs::create_directories(output_root);
00197
00198
00199 fs::path next_folder(output_root);
00200 for (fs::path::iterator path_iter = rel_path.begin(); path_iter != rel_path.end(); ++path_iter)
00201 {
00202 next_folder /= *path_iter;
00203 bool created_dir = fs::create_directory(next_folder);
00204 if (created_dir)
00205 {
00206
00207 fs::ofstream sig_file(next_folder / SIG_FILE_NAME);
00208 sig_file.close();
00209 }
00210 }
00211 }
00212 catch (const fs::filesystem_error& e)
00213 {
00214 TERMINATE("Error making test output folder: " << e.what());
00215 }
00216 }
00217
00218
00219 PetscTools::Barrier("OutputFileHandler::MakeFoldersAndReturnFullPath");
00220
00221 std::string path_with_slash = (output_root / rel_path).string();
00222 AddTrailingSlash(path_with_slash);
00223 return path_with_slash;
00224 }
00225
00226 std::string OutputFileHandler::GetOutputDirectoryFullPath() const
00227 {
00228 return mDirectory;
00229 }
00230
00231 std::string OutputFileHandler::GetRelativePath() const
00232 {
00233 FileFinder output_root("", RelativeTo::ChasteTestOutput);
00234 std::string relative_path = FindFile("").GetRelativePath(output_root);
00235 if (!relative_path.empty() && *relative_path.rbegin() == '/')
00236 {
00237 relative_path.erase(--relative_path.end());
00238 }
00239 return relative_path;
00240 }
00241
00242 out_stream OutputFileHandler::OpenOutputFile(const std::string& rFileName,
00243 std::ios_base::openmode mode) const
00244 {
00245 out_stream p_output_file(new std::ofstream((mDirectory+rFileName).c_str(), mode));
00246 if (!p_output_file->is_open())
00247 {
00248 EXCEPTION("Could not open file \"" + rFileName + "\" in " + mDirectory);
00249 }
00250 return p_output_file;
00251 }
00252
00253 out_stream OutputFileHandler::OpenOutputFile(const std::string& rFileName,
00254 unsigned number,
00255 const std::string& rFileFormat,
00256 std::ios_base::openmode mode) const
00257 {
00258 std::stringstream string_stream;
00259 string_stream << rFileName << number << rFileFormat;
00260 return OpenOutputFile(string_stream.str(), mode);
00261 }
00262
00263 void OutputFileHandler::SetArchiveDirectory() const
00264 {
00265 FileFinder dir(GetOutputDirectoryFullPath(), RelativeTo::Absolute);
00266 ArchiveLocationInfo::SetArchiveDirectory(dir);
00267 }
00268
00269 void OutputFileHandler::AddTrailingSlash(std::string& rDirectory)
00270 {
00271
00272 if (rDirectory!="" && !( *(rDirectory.end()-1) == '/'))
00273 {
00274 rDirectory = rDirectory + "/";
00275 }
00276 }
00277
00278 FileFinder OutputFileHandler::CopyFileTo(const FileFinder& rSourceFile) const
00279 {
00280 if (!rSourceFile.IsFile())
00281 {
00282 EXCEPTION("Can only copy single files:\n" << rSourceFile.GetAbsolutePath() << " is not a file.");
00283 }
00284 fs::path from_path(rSourceFile.GetAbsolutePath());
00285 fs::path to_path(GetOutputDirectoryFullPath());
00286 to_path /= from_path.leaf();
00287 if (PetscTools::AmMaster())
00288 {
00289 try
00290 {
00291 fs::copy_file(from_path, to_path);
00292 }
00293 catch (const fs::filesystem_error& e)
00294 {
00295 TERMINATE("Error copying file '" << rSourceFile.GetAbsolutePath() << "': " << e.what());
00296 }
00297 }
00298 PetscTools::Barrier("OutputFileHandler::CopyFileTo");
00299 return FileFinder(to_path.string(), RelativeTo::Absolute);
00300 }
00301
00302 FileFinder OutputFileHandler::FindFile(std::string leafName) const
00303 {
00304 return FileFinder(GetOutputDirectoryFullPath() + leafName, RelativeTo::Absolute);
00305 }