| 229 | ******************************************************************************/ |
| 230 | |
| 231 | std::unique_ptr<Project> ProjectLoader::open( |
| 232 | std::unique_ptr<TransactionalDirectory> directory, |
| 233 | const QString& filename) { |
| 234 | Q_ASSERT(directory); |
| 235 | mMigrationLog = std::nullopt; |
| 236 | |
| 237 | QElapsedTimer timer; |
| 238 | timer.start(); |
| 239 | const FilePath fp = directory->getAbsPath(filename); |
| 240 | qDebug().nospace() << "Open project " << fp.toNative() << "..."; |
| 241 | |
| 242 | // Check if the project file exists. |
| 243 | if (!directory->fileExists(filename)) { |
| 244 | throw RuntimeError(__FILE__, __LINE__, |
| 245 | tr("File does not exist: '%1'").arg(fp.toNative())); |
| 246 | } |
| 247 | |
| 248 | // Read the file format version. |
| 249 | if (!directory->fileExists(".librepcb-project")) { |
| 250 | throw RuntimeError(__FILE__, __LINE__, |
| 251 | tr("Directory does not contain a LibrePCB project: '%1'") |
| 252 | .arg(directory->getAbsPath().toNative())); |
| 253 | } |
| 254 | const Version fileFormat = |
| 255 | VersionFile::fromByteArray(directory->read(".librepcb-project")) |
| 256 | .getVersion(); |
| 257 | qDebug().noquote() << "Detected project file format:" << fileFormat.toStr(); |
| 258 | |
| 259 | // Check file format version. |
| 260 | if (fileFormat > Application::getFileFormatVersion()) { |
| 261 | throw RuntimeError( |
| 262 | __FILE__, __LINE__, |
| 263 | tr("This project was created with a newer application version.\n" |
| 264 | "You need at least LibrePCB %1 to open it.\n\n%2") |
| 265 | .arg(fileFormat.toPrettyStr(3), fp.toNative())); |
| 266 | } |
| 267 | |
| 268 | // Upgrade file format, if needed. |
| 269 | for (auto migration : FileFormatMigration::getMigrations(fileFormat)) { |
| 270 | if (!mMigrationLog) { |
| 271 | mMigrationLog = MigrationLog{filename, |
| 272 | QDateTime::currentDateTime(), |
| 273 | fileFormat, |
| 274 | Application::getFileFormatVersion(), |
| 275 | {}}; |
| 276 | } |
| 277 | qInfo().nospace().noquote() |
| 278 | << "Project file format is outdated, upgrading from v" |
| 279 | << migration->getFromVersion().toStr() << " to v" |
| 280 | << migration->getToVersion().toStr() << "..."; |
| 281 | migration->upgradeProject(*directory, mMigrationLog->messages); |
| 282 | } |
| 283 | |
| 284 | // Sort & save migration messages. |
| 285 | if (mMigrationLog) { |
| 286 | // Make sure to delete the temporary migration log (may not even exist |
| 287 | // *now*, but may exist at the time the project gets saved). |
| 288 | directory->removeFile(mMigrationLog->getRelativeFilePath(true)); |
nothing calls this directly
no test coverage detected