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 out_stream OutputFileHandler::OpenOutputFile(const std::string& rFileName,
00232 std::ios_base::openmode mode) const
00233 {
00234 out_stream p_output_file(new std::ofstream((mDirectory+rFileName).c_str(), mode));
00235 if (!p_output_file->is_open())
00236 {
00237 EXCEPTION("Could not open file \"" + rFileName + "\" in " + mDirectory);
00238 }
00239 return p_output_file;
00240 }
00241
00242 out_stream OutputFileHandler::OpenOutputFile(const std::string& rFileName,
00243 unsigned number,
00244 const std::string& rFileFormat,
00245 std::ios_base::openmode mode) const
00246 {
00247 std::stringstream string_stream;
00248 string_stream << rFileName << number << rFileFormat;
00249 return OpenOutputFile(string_stream.str(), mode);
00250 }
00251
00252 void OutputFileHandler::SetArchiveDirectory() const
00253 {
00254 FileFinder dir(GetOutputDirectoryFullPath(), RelativeTo::Absolute);
00255 ArchiveLocationInfo::SetArchiveDirectory(dir);
00256 }
00257
00258 void OutputFileHandler::AddTrailingSlash(std::string& rDirectory)
00259 {
00260
00261 if (rDirectory!="" && !( *(rDirectory.end()-1) == '/'))
00262 {
00263 rDirectory = rDirectory + "/";
00264 }
00265 }
00266
00267 FileFinder OutputFileHandler::CopyFileTo(const FileFinder& rSourceFile) const
00268 {
00269 if (!rSourceFile.IsFile())
00270 {
00271 EXCEPTION("Can only copy single files:\n" << rSourceFile.GetAbsolutePath() << " is not a file.");
00272 }
00273 fs::path from_path(rSourceFile.GetAbsolutePath());
00274 fs::path to_path(GetOutputDirectoryFullPath());
00275 to_path /= from_path.leaf();
00276 if (PetscTools::AmMaster())
00277 {
00278 try
00279 {
00280 fs::copy_file(from_path, to_path);
00281 }
00282 catch (const fs::filesystem_error& e)
00283 {
00284 TERMINATE("Error copying file '" << rSourceFile.GetAbsolutePath() << "': " << e.what());
00285 }
00286 }
00287 PetscTools::Barrier("OutputFileHandler::CopyFileTo");
00288 return FileFinder(to_path.string(), RelativeTo::Absolute);
00289 }
00290
00291 FileFinder OutputFileHandler::FindFile(std::string leafName) const
00292 {
00293 return FileFinder(GetOutputDirectoryFullPath() + leafName, RelativeTo::Absolute);
00294 }