147 auto instrumentDirs = Mantid::Kernel::ConfigService::Instance().getInstrumentDirectories();
148 std::filesystem::path installPath(instrumentDirs.back());
149 std::filesystem::create_directories(installPath);
150 std::filesystem::path localPath(instrumentDirs[0]);
151 std::filesystem::create_directories(localPath);
154 std::filesystem::path gitHubJsonFile = localPath /
"github.json";
155 Poco::DateTime gitHubJsonDate(1900, 1, 1);
156 bool forceUpdate = this->
getProperty(
"ForceUpdate");
157 if ((!forceUpdate) && std::filesystem::exists(gitHubJsonFile) && std::filesystem::is_regular_file(gitHubJsonFile)) {
158 auto ftime = std::filesystem::last_write_time(gitHubJsonFile);
159 auto sctp = std::chrono::time_point_cast<std::chrono::system_clock::duration>(
160 ftime - std::filesystem::file_time_type::clock::now() + std::chrono::system_clock::now());
161 std::time_t cftime = std::chrono::system_clock::to_time_t(sctp);
162 gitHubJsonDate = Poco::Timestamp::fromEpochTime(cftime);
167 headers.emplace(
"if-modified-since",
168 Poco::DateTimeFormatter::format(gitHubJsonDate, Poco::DateTimeFormat::HTTP_FORMAT));
169 std::string gitHubInstrumentRepoUrl = ConfigService::Instance().getString(
"UpdateInstrumentDefinitions.URL");
170 if (gitHubInstrumentRepoUrl.empty()) {
171 throw std::runtime_error(
"Property UpdateInstrumentDefinitions.URL is not defined, "
172 "this should point to the location of the instrument "
173 "directory in the github API "
175 "https://api.github.com/repos/mantidproject/mantid/contents/"
180 doDownloadFile(gitHubInstrumentRepoUrl, gitHubJsonFile.string(), headers);
191 std::filesystem::path installRepoFile = localPath /
"install.json";
193 std::filesystem::path localRepoFile = localPath /
"local.json";
197 if (std::filesystem::file_size(gitHubJsonFile) == 0) {
198 std::stringstream msg;
199 msg <<
"Encountered empty file \"" << gitHubJsonFile.string() <<
"\" while determining what to download";
200 throw std::runtime_error(msg.str());
204 ::Json::CharReaderBuilder readerBuilder;
205 Json::Value serverContents;
206 std::ifstream fileStream(gitHubJsonFile.string(), std::ios::in);
209 Json::parseFromStream(readerBuilder, fileStream, &serverContents, &errors);
210 if (errors.size() != 0) {
211 throw std::runtime_error(
"Unable to parse server JSON file \"" + gitHubJsonFile.string() +
"\"");
215 std::unordered_set<std::string> repoFilenames;
217 for (
auto &serverElement : serverContents) {
218 std::string elementName = serverElement.get(
"name",
"").asString();
219 repoFilenames.insert(elementName);
220 std::filesystem::path filePath = localPath / elementName;
221 if (filePath.extension().string() !=
".xml")
223 std::string sha = serverElement.get(
"sha",
"").asString();
224 std::string downloadUrl = getDownloadUrl(serverElement);
232 if ((sha != installSha) && (sha != localSha)) {
233 fileMap.emplace(downloadUrl,
235 }
else if ((!localSha.empty()) && (sha == installSha) && (sha != localSha))
237 fileMap.emplace(downloadUrl, filePath.string());
297 const std::unordered_set<std::string> &filenamesToKeep)
const {
300 std::vector<std::filesystem::path> filesToDelete;
303 for (
auto const &it : std::filesystem::directory_iterator{directoryPath}) {
304 auto const entryPath = it.path();
305 if (entryPath.extension().string() !=
".xml")
307 if (filenamesToKeep.find(entryPath.filename().string()) == filenamesToKeep.end()) {
308 g_log.
debug() <<
"File not found in remote instrument repository, will "
310 << entryPath.filename().string() <<
'\n';
311 filesToDelete.emplace_back(entryPath);
314 }
catch (Poco::Exception &ex) {
315 g_log.
error() <<
"DownloadInstrument: failed to list the directory: " << directoryPath <<
" : " << ex.className()
316 <<
" : " << ex.displayText() <<
'\n';
318 }
catch (std::exception &ex) {
319 std::stringstream ss;
320 ss <<
"unknown exception while checking local file system. " << ex.what() <<
". Input = " << directoryPath;
321 throw std::runtime_error(ss.str());
326 for (
const auto &filepath : filesToDelete) {
327 std::filesystem::remove(filepath);
329 }
catch (Poco::Exception &ex) {
330 g_log.
error() <<
"DownloadInstrument: failed to delete file: " << ex.className() <<
" : " << ex.displayText()
333 }
catch (std::exception &ex) {
334 std::stringstream ss;
335 ss <<
"unknown exception while deleting file: " << ex.what();
336 throw std::runtime_error(ss.str());
339 g_log.
debug() << filesToDelete.size() <<
" Files deleted.\n";
341 return filesToDelete.size();
358 const std::string &localFilePath,
360 std::filesystem::path localFile(localFilePath);
361 if (std::filesystem::exists(localFile)) {
362 auto perms = std::filesystem::status(localFile).permissions();
363 if ((perms & std::filesystem::perms::owner_write) == std::filesystem::perms::none) {
364 std::stringstream msg;
365 msg <<
"Cannot write file \"" << localFilePath <<
"\"";
366 throw std::runtime_error(msg.str());
369 localFile = std::filesystem::path(localFilePath).parent_path();
370 auto perms = std::filesystem::status(localFile).permissions();
371 if ((perms & std::filesystem::perms::owner_write) == std::filesystem::perms::none) {
372 std::stringstream msg;
373 msg <<
"Cannot write file \"" << localFilePath <<
"\"";
374 throw std::runtime_error(msg.str());
379 inetHelper.
headers().insert(headers.begin(), headers.end());
380 const auto retStatus = inetHelper.
downloadFile(urlFile, localFilePath);