forked from cake-build/cake
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathFakeFileSystemTree.cs
More file actions
268 lines (224 loc) · 8.14 KB
/
FakeFileSystemTree.cs
File metadata and controls
268 lines (224 loc) · 8.14 KB
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
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Cake.Core;
using Cake.Core.IO;
namespace Cake.Testing
{
internal sealed class FakeFileSystemTree
{
private readonly PathComparer _comparer;
private readonly FakeDirectory _root;
public PathComparer Comparer
{
get { return _comparer; }
}
public FakeFileSystemTree(ICakeEnvironment environment)
{
if (environment == null)
{
throw new ArgumentNullException("environment");
}
if (environment.WorkingDirectory == null)
{
throw new ArgumentException("Working directory not set.");
}
if (environment.WorkingDirectory.IsRelative)
{
throw new ArgumentException("Working directory cannot be relative.");
}
_comparer = new PathComparer(environment.IsUnix());
_root = new FakeDirectory(this, "/");
_root.Create();
}
public FakeDirectory CreateDirectory(DirectoryPath path)
{
return CreateDirectory(new FakeDirectory(this, path));
}
public FakeDirectory CreateDirectory(FakeDirectory directory)
{
var path = directory.Path;
var queue = new Queue<string>(path.Segments);
FakeDirectory current = null;
var children = _root.Content;
while (queue.Count > 0)
{
// Get the segment.
var currentSegment = queue.Dequeue();
var parent = current;
// Calculate the current path.
path = parent != null ? parent.Path.Combine(currentSegment) : new DirectoryPath(currentSegment);
if (!children.Directories.ContainsKey(path))
{
current = queue.Count == 0 ? directory : new FakeDirectory(this, path);
current.Parent = parent ?? _root;
current.Hidden = false;
children.Add(current);
}
else
{
current = children.Directories[path];
}
current.Exists = true;
children = current.Content;
}
return directory;
}
public void CreateFile(FakeFile file)
{
// Get the directory that the file exists in.
var directory = FindDirectory(file.Path.GetDirectory());
if (directory == null)
{
file.Exists = false;
throw new DirectoryNotFoundException(string.Format("Could not find a part of the path '{0}'.", file.Path.FullPath));
}
if (!directory.Content.Files.ContainsKey(file.Path))
{
// Add the file to the directory.
file.Exists = true;
directory.Content.Add(file);
}
}
public void DeleteDirectory(FakeDirectory fakeDirectory, bool recursive)
{
var root = new Stack<FakeDirectory>();
var result = new Stack<FakeDirectory>();
if (fakeDirectory.Exists)
{
root.Push(fakeDirectory);
}
while (root.Count > 0)
{
var node = root.Pop();
result.Push(node);
var directories = node.Content.Directories;
if (directories.Count > 0 && !recursive)
{
throw new IOException("The directory is not empty.");
}
foreach (var child in directories)
{
root.Push(child.Value);
}
}
while (result.Count > 0)
{
var directory = result.Pop();
var files = directory.Content.Files.Select(x => x).ToArray();
if (files.Length > 0 && !recursive)
{
throw new IOException("The directory is not empty.");
}
foreach (var file in files)
{
// Delete the file.
DeleteFile(file.Value);
}
// Delete the directory.
directory.Parent.Content.Remove(directory);
directory.Exists = false;
}
}
public void DeleteFile(FakeFile file)
{
if (!file.Exists)
{
throw new FileNotFoundException("File does not exist.", file.Path.FullPath);
}
// Find the directory.
var directory = FindDirectory(file.Path.GetDirectory());
// Remove the file from the directory.
directory.Content.Remove(file);
// Reset all properties.
file.Exists = false;
file.Content = null;
file.ContentLength = 0;
}
public FakeDirectory FindDirectory(DirectoryPath path)
{
// Want the root?
if (path.Segments.Length == 0)
{
return _root;
}
var queue = new Queue<string>(path.Segments);
FakeDirectory current = null;
var children = _root.Content;
while (queue.Count > 0)
{
// Set the parent.
var parent = current;
// Calculate the current path.
var segment = queue.Dequeue();
path = parent != null ? parent.Path.Combine(segment) : new DirectoryPath(segment);
// Find the current path.
if (!children.Directories.ContainsKey(path))
{
return null;
}
current = children.Directories[path];
children = current.Content;
}
return current;
}
public FakeFile FindFile(FilePath path)
{
var directory = FindDirectory(path.GetDirectory());
if (directory != null)
{
if (directory.Content.Files.ContainsKey(path))
{
return directory.Content.Files[path];
}
}
return null;
}
public void CopyFile(FakeFile file, FilePath destination, bool overwrite)
{
if (!file.Exists)
{
throw new FileNotFoundException("File do not exist.");
}
// Already exists?
var destinationFile = FindFile(destination);
if (destinationFile != null)
{
if (!overwrite)
{
const string format = "{0} exists and overwrite is false.";
var message = string.Format(format, destination.FullPath);
throw new IOException(message);
}
}
// Directory exists?
var directory = FindDirectory(destination.GetDirectory());
if (directory == null || !directory.Exists)
{
throw new DirectoryNotFoundException("The destination path {0} do not exist.");
}
// Make sure the file exist.
if (destinationFile == null)
{
destinationFile = new FakeFile(this, destination);
}
// Copy the data from the original file to the destination.
using (var input = file.OpenRead())
using (var output = destinationFile.OpenWrite())
{
input.CopyTo(output);
}
}
public void MoveFile(FakeFile fakeFile, FilePath destination)
{
// Copy the file to the new location.
CopyFile(fakeFile, destination, false);
// Delete the original file.
fakeFile.Delete();
}
}
}