Skip to content

SourceWatcher.cpp

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#include "SourceWatcher.hpp"

SourceWatcher::SourceWatcher(std::list<std::string> patterns): patterns{patterns}{
  for (auto pattern : patterns){
    auto paths = glob::rglob(pattern);
    for (auto& file : paths) {
      tracked_files[file.string()] = std::filesystem::last_write_time(file);
    }
  }
}

SourceWatcher::SourceWatcher(std::string pattern): SourceWatcher(std::list<std::string>{pattern}){
  //
}

std::tuple<std::unordered_set<std::filesystem::path>,
           std::unordered_set<std::filesystem::path>,
           std::unordered_set<std::filesystem::path>> SourceWatcher::diff(){
  std::unordered_set<std::filesystem::path> added_files;
  std::unordered_set<std::filesystem::path> modified_files;
  std::unordered_set<std::filesystem::path> deleted_files = filenames();

  for (auto pattern : patterns){
    auto paths = glob::rglob(pattern);
    for(auto& file : paths) {
      auto last_write_time = std::filesystem::last_write_time(file);

      /* Remove this file from the deleted files set as it still exists*/
      deleted_files.erase(file.string());

      /* Check file creation and modification */
      if(! tracked_files.contains(file.string())) {
        added_files.insert(file.string());
      } else if(tracked_files[file.string()] != last_write_time) {
        modified_files.insert(file.string());
      }

      /* Update the timestamp */
      tracked_files[file.string()] = last_write_time;
    }
  }

  /* Remove deleted files from the tracked_files map */
  for (auto deleted_file : deleted_files){
      tracked_files.erase(deleted_file);
  }

  return {added_files, modified_files, deleted_files};
}

bool SourceWatcher::changed(){
  auto [added_files, modified_files, deleted_files] = diff();
  return !added_files.empty() || !modified_files.empty() || !deleted_files.empty();
}

std::unordered_set<std::filesystem::path> SourceWatcher::filenames(){
  std::unordered_set<std::filesystem::path> filenames;
  for (auto pairs : tracked_files) {
    filenames.insert(pairs.first);
  }
  return filenames;
}