diff options
Diffstat (limited to 'src/3rdParty/efsw/DirectorySnapshot.cpp')
-rwxr-xr-x | src/3rdParty/efsw/DirectorySnapshot.cpp | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/src/3rdParty/efsw/DirectorySnapshot.cpp b/src/3rdParty/efsw/DirectorySnapshot.cpp new file mode 100755 index 0000000..6049e4a --- /dev/null +++ b/src/3rdParty/efsw/DirectorySnapshot.cpp | |||
@@ -0,0 +1,212 @@ | |||
1 | #include <efsw/DirectorySnapshot.hpp> | ||
2 | #include <efsw/FileSystem.hpp> | ||
3 | |||
4 | namespace efsw { | ||
5 | |||
6 | DirectorySnapshot::DirectorySnapshot() {} | ||
7 | |||
8 | DirectorySnapshot::DirectorySnapshot( std::string directory ) { | ||
9 | init( directory ); | ||
10 | } | ||
11 | |||
12 | DirectorySnapshot::~DirectorySnapshot() {} | ||
13 | |||
14 | void DirectorySnapshot::init( std::string directory ) { | ||
15 | setDirectoryInfo( directory ); | ||
16 | initFiles(); | ||
17 | } | ||
18 | |||
19 | bool DirectorySnapshot::exists() { | ||
20 | return DirectoryInfo.exists(); | ||
21 | } | ||
22 | |||
23 | void DirectorySnapshot::deleteAll( DirectorySnapshotDiff& Diff ) { | ||
24 | FileInfo fi; | ||
25 | |||
26 | for ( FileInfoMap::iterator it = Files.begin(); it != Files.end(); it++ ) { | ||
27 | fi = it->second; | ||
28 | |||
29 | if ( fi.isDirectory() ) { | ||
30 | Diff.DirsDeleted.push_back( fi ); | ||
31 | } else { | ||
32 | Diff.FilesDeleted.push_back( fi ); | ||
33 | } | ||
34 | } | ||
35 | |||
36 | Files.clear(); | ||
37 | } | ||
38 | |||
39 | void DirectorySnapshot::setDirectoryInfo( std::string directory ) { | ||
40 | DirectoryInfo = FileInfo( directory ); | ||
41 | } | ||
42 | |||
43 | void DirectorySnapshot::initFiles() { | ||
44 | Files = FileSystem::filesInfoFromPath( DirectoryInfo.Filepath ); | ||
45 | |||
46 | FileInfoMap::iterator it = Files.begin(); | ||
47 | std::list<std::string> eraseFiles; | ||
48 | |||
49 | /// Remove all non regular files and non directories | ||
50 | for ( ; it != Files.end(); it++ ) { | ||
51 | if ( !it->second.isRegularFile() && !it->second.isDirectory() ) { | ||
52 | eraseFiles.push_back( it->first ); | ||
53 | } | ||
54 | } | ||
55 | |||
56 | for ( std::list<std::string>::iterator eit = eraseFiles.begin(); eit != eraseFiles.end(); | ||
57 | eit++ ) { | ||
58 | Files.erase( *eit ); | ||
59 | } | ||
60 | } | ||
61 | |||
62 | DirectorySnapshotDiff DirectorySnapshot::scan() { | ||
63 | DirectorySnapshotDiff Diff; | ||
64 | |||
65 | Diff.clear(); | ||
66 | |||
67 | FileInfo curFI( DirectoryInfo.Filepath ); | ||
68 | |||
69 | Diff.DirChanged = DirectoryInfo != curFI; | ||
70 | |||
71 | if ( Diff.DirChanged ) { | ||
72 | DirectoryInfo = curFI; | ||
73 | } | ||
74 | |||
75 | /// If the directory was erased, create the events for files and directories deletion | ||
76 | if ( !curFI.exists() ) { | ||
77 | deleteAll( Diff ); | ||
78 | |||
79 | return Diff; | ||
80 | } | ||
81 | |||
82 | FileInfoMap files = FileSystem::filesInfoFromPath( DirectoryInfo.Filepath ); | ||
83 | |||
84 | if ( files.empty() && Files.empty() ) { | ||
85 | return Diff; | ||
86 | } | ||
87 | |||
88 | FileInfo fi; | ||
89 | FileInfoMap FilesCpy; | ||
90 | FileInfoMap::iterator it; | ||
91 | FileInfoMap::iterator fiIt; | ||
92 | |||
93 | if ( Diff.DirChanged ) { | ||
94 | FilesCpy = Files; | ||
95 | } | ||
96 | |||
97 | for ( it = files.begin(); it != files.end(); it++ ) { | ||
98 | fi = it->second; | ||
99 | |||
100 | /// File existed before? | ||
101 | fiIt = Files.find( it->first ); | ||
102 | |||
103 | if ( fiIt != Files.end() ) { | ||
104 | /// Erase from the file list copy | ||
105 | FilesCpy.erase( it->first ); | ||
106 | |||
107 | /// File changed? | ||
108 | if ( ( *fiIt ).second != fi ) { | ||
109 | /// Update the new file info | ||
110 | Files[it->first] = fi; | ||
111 | |||
112 | /// handle modified event | ||
113 | if ( fi.isDirectory() ) { | ||
114 | Diff.DirsModified.push_back( fi ); | ||
115 | } else { | ||
116 | Diff.FilesModified.push_back( fi ); | ||
117 | } | ||
118 | } | ||
119 | } | ||
120 | /// Only add regular files or directories | ||
121 | else if ( fi.isRegularFile() || fi.isDirectory() ) { | ||
122 | /// New file found | ||
123 | Files[it->first] = fi; | ||
124 | |||
125 | FileInfoMap::iterator fit; | ||
126 | std::string oldFile = ""; | ||
127 | |||
128 | /// Check if the same inode already existed | ||
129 | if ( ( fit = nodeInFiles( fi ) ) != Files.end() ) { | ||
130 | oldFile = fit->first; | ||
131 | |||
132 | /// Avoid firing a Delete event | ||
133 | FilesCpy.erase( fit->first ); | ||
134 | |||
135 | /// Delete the old file name | ||
136 | Files.erase( fit->first ); | ||
137 | |||
138 | if ( fi.isDirectory() ) { | ||
139 | Diff.DirsMoved.push_back( std::make_pair( oldFile, fi ) ); | ||
140 | } else { | ||
141 | Diff.FilesMoved.push_back( std::make_pair( oldFile, fi ) ); | ||
142 | } | ||
143 | } else { | ||
144 | if ( fi.isDirectory() ) { | ||
145 | Diff.DirsCreated.push_back( fi ); | ||
146 | } else { | ||
147 | Diff.FilesCreated.push_back( fi ); | ||
148 | } | ||
149 | } | ||
150 | } | ||
151 | } | ||
152 | |||
153 | if ( !Diff.DirChanged ) { | ||
154 | return Diff; | ||
155 | } | ||
156 | |||
157 | /// The files or directories that remains were deleted | ||
158 | for ( it = FilesCpy.begin(); it != FilesCpy.end(); it++ ) { | ||
159 | fi = it->second; | ||
160 | |||
161 | if ( fi.isDirectory() ) { | ||
162 | Diff.DirsDeleted.push_back( fi ); | ||
163 | } else { | ||
164 | Diff.FilesDeleted.push_back( fi ); | ||
165 | } | ||
166 | |||
167 | /// Remove the file or directory from the list of files | ||
168 | Files.erase( it->first ); | ||
169 | } | ||
170 | |||
171 | return Diff; | ||
172 | } | ||
173 | |||
174 | FileInfoMap::iterator DirectorySnapshot::nodeInFiles( FileInfo& fi ) { | ||
175 | FileInfoMap::iterator it; | ||
176 | |||
177 | if ( FileInfo::inodeSupported() ) { | ||
178 | for ( it = Files.begin(); it != Files.end(); it++ ) { | ||
179 | if ( it->second.sameInode( fi ) && it->second.Filepath != fi.Filepath ) { | ||
180 | return it; | ||
181 | } | ||
182 | } | ||
183 | } | ||
184 | |||
185 | return Files.end(); | ||
186 | } | ||
187 | |||
188 | void DirectorySnapshot::addFile( std::string path ) { | ||
189 | std::string name( FileSystem::fileNameFromPath( path ) ); | ||
190 | Files[name] = FileInfo( path ); | ||
191 | } | ||
192 | |||
193 | void DirectorySnapshot::removeFile( std::string path ) { | ||
194 | std::string name( FileSystem::fileNameFromPath( path ) ); | ||
195 | |||
196 | FileInfoMap::iterator it = Files.find( name ); | ||
197 | |||
198 | if ( Files.end() != it ) { | ||
199 | Files.erase( it ); | ||
200 | } | ||
201 | } | ||
202 | |||
203 | void DirectorySnapshot::moveFile( std::string oldPath, std::string newPath ) { | ||
204 | removeFile( oldPath ); | ||
205 | addFile( newPath ); | ||
206 | } | ||
207 | |||
208 | void DirectorySnapshot::updateFile( std::string path ) { | ||
209 | addFile( path ); | ||
210 | } | ||
211 | |||
212 | } // namespace efsw | ||