| 359 | args.reserve(entry.info->canonical->arguments.size() + entry.info->patch.size()); |
| 360 | for(const char* arg: entry.info->canonical->arguments) { |
| 361 | args.emplace_back(arg); |
| 362 | } |
| 363 | for(const char* arg: entry.info->patch) { |
| 364 | args.emplace_back(arg); |
| 365 | } |
| 366 | snapshot[entry.file].emplace_back(canonical_command_hash(args, entry.info->directory)); |
| 367 | } |
| 368 | |
| 369 | // A file's entries have no inherent order, so sort each list to make the |
| 370 | // comparison in reload_and_diff() order-independent. |
| 371 | for(auto& bucket: snapshot) { |
| 372 | ranges::sort(bucket.second); |
| 373 | } |
| 374 | |
| 375 | return snapshot; |
| 376 | } |
| 377 | |
| 378 | std::optional<CDBDiff> CompilationDatabase::reload_and_diff(llvm::StringRef path) { |
| 379 | auto before = command_hash_snapshot(); |
| 380 | if(!load(path)) { |
| 381 | // Unreadable or unparsable (e.g. still locked by the generator): |
| 382 | // the old entries were kept, and the caller must not treat this as |
| 383 | // "no change" — it has to retry. |
| 384 | return std::nullopt; |
| 385 | } |
| 386 | auto after = command_hash_snapshot(); |
| 387 | |
| 388 | CDBDiff diff; |
| 389 | |
| 390 | for(auto& bucket: after) { |
| 391 | auto it = before.find(bucket.first); |
| 392 | if(it == before.end()) { |
| 393 | diff.added.push_back(bucket.first); |
| 394 | } else if(it->second != bucket.second) { |
| 395 | diff.changed.push_back(bucket.first); |
| 396 | } |