20
17
public FilePath (string path)
18
: this ((string) null, path)
25
23
public FilePath (FilePath other, string child)
24
: this ((string) other, child)
27
this.path = Path.Combine (other.path, child);
30
29
public FilePath (string other, string child)
32
this.path = Path.Combine (other, child);
34
while (child != null && child.Length > 0 && (child[0] == Path.DirectorySeparatorChar || child[0] == Path.AltDirectorySeparatorChar))
35
child = child.Substring (1);
37
if (!string.IsNullOrEmpty(other) && other[other.Length - 1] == Path.VolumeSeparatorChar)
38
other += Path.DirectorySeparatorChar;
40
this.path = Path.Combine (other, child);
35
44
public static implicit operator FilePath (string name)
58
67
public bool CanWrite ()
61
var info = GetUnixFileInfo (path);
62
return info != null && info.CanAccess (Mono.Unix.Native.AccessModes.W_OK);
65
return ((File.GetAttributes (path) & FileAttributes.ReadOnly) == 0);
69
return FileHelper.Instance.CanWrite (this);
68
72
public bool CreateNewFile ()
75
File.Open (path, FileMode.CreateNew).Close ();
72
File.OpenWrite (path).Close ();
76
82
public static FilePath CreateTempFile ()
104
110
public bool Delete ()
107
if (RunningOnLinux) {
108
var info = GetUnixFileInfo (path);
109
if (info != null && info.Exists) {
114
// If the directory is not empty we return false. JGit relies on this
121
if (Directory.Exists (path)) {
122
if (Directory.GetFileSystemEntries (path).Length != 0)
124
MakeDirWritable (path);
125
Directory.Delete (path, true);
128
else if (File.Exists(path)) {
129
MakeFileWritable (path);
113
return FileHelper.Instance.Delete (this);
134
114
} catch (Exception exception) {
135
115
Console.WriteLine (exception);
144
124
public bool Exists ()
146
if (RunningOnLinux) {
147
var info = GetUnixFileInfo (path);
148
return info != null && info.Exists;
151
return (File.Exists (path) || Directory.Exists (path));
126
return FileHelper.Instance.Exists (this);
154
129
public FilePath GetAbsoluteFile ()
196
171
public bool IsDirectory ()
199
if (RunningOnLinux) {
200
var info = GetUnixFileInfo (path);
201
return info != null && info.Exists && info.FileType == FileTypes.Directory;
203
} catch (DirectoryNotFoundException) {
204
// If the file /foo/bar exists and we query to see if /foo/bar/baz exists, we get a
205
// DirectoryNotFound exception for Mono.Unix. In this case the directory definitely
209
return Directory.Exists (path);
173
return FileHelper.Instance.IsDirectory (this);
212
176
public bool IsFile ()
214
if (RunningOnLinux) {
215
var info = GetUnixFileInfo (path);
216
return info != null && info.Exists && (info.FileType == FileTypes.RegularFile || info.FileType == FileTypes.SymbolicLink);
219
return File.Exists (path);
178
return FileHelper.Instance.IsFile (this);
222
181
public long LastModified ()
224
if (RunningOnLinux) {
225
var info = GetUnixFileInfo (path);
226
return info != null && info.Exists ? info.LastWriteTimeUtc.ToMillisecondsSinceEpoch() : 0;
229
var info2 = new FileInfo(path);
230
return info2.Exists ? info2.LastWriteTimeUtc.ToMillisecondsSinceEpoch() : 0;
183
return FileHelper.Instance.LastModified (this);
233
186
public long Length ()
235
if (RunningOnLinux) {
236
var info = GetUnixFileInfo (path);
237
return info != null && info.Exists ? info.Length : 0;
240
// If you call .Length on a file that doesn't exist, an exception is thrown
241
var info2 = new FileInfo (path);
242
return info2.Exists ? info2.Length : 0;
188
return FileHelper.Instance.Length (this);
245
191
public string[] List ()
283
private void MakeDirWritable (string dir)
229
static void MakeDirWritable (string dir)
285
foreach (string file in Directory.GetFiles (dir)) {
286
MakeFileWritable (file);
288
foreach (string subdir in Directory.GetDirectories (dir)) {
289
MakeDirWritable (subdir);
231
FileHelper.Instance.MakeDirWritable (dir);
293
private void MakeFileWritable (string file)
234
static void MakeFileWritable (string file)
295
if (RunningOnLinux) {
296
var info = GetUnixFileInfo (file);
298
info.FileAccessPermissions |= (FileAccessPermissions.GroupWrite | FileAccessPermissions.OtherWrite | FileAccessPermissions.UserWrite);
302
FileAttributes fileAttributes = File.GetAttributes (file);
303
if ((fileAttributes & FileAttributes.ReadOnly) != 0) {
304
fileAttributes &= ~FileAttributes.ReadOnly;
305
File.SetAttributes (file, fileAttributes);
236
FileHelper.Instance.MakeFileWritable (file);
309
239
public bool Mkdir ()
338
268
public bool RenameTo (string name)
341
if (RunningOnLinux) {
342
var symlink = GetUnixFileInfo (path) as UnixSymbolicLinkInfo;
343
if (symlink != null) {
344
var newFile = new UnixSymbolicLinkInfo (name);
345
newFile.CreateSymbolicLinkTo (symlink.ContentsPath);
349
File.Move (path, name);
356
public void SetLastModified (long milis)
358
// FIXME: I don't know how to change the modified time on a symlink
359
DateTime utcDateTime = Extensions.MillisToDateTimeOffset (milis, 0L).UtcDateTime;
360
File.SetLastWriteTimeUtc (path, utcDateTime);
363
public void SetReadOnly ()
365
if (RunningOnLinux) {
366
var info = GetUnixFileInfo (path);
368
info.FileAccessPermissions &= ~ (FileAccessPermissions.GroupWrite | FileAccessPermissions.OtherWrite | FileAccessPermissions.UserWrite);
372
var fileAttributes = File.GetAttributes (this.path) | FileAttributes.ReadOnly;
373
File.SetAttributes (path, fileAttributes);
270
return FileHelper.Instance.RenameTo (this, name);
273
public bool SetLastModified (long milis)
275
return FileHelper.Instance.SetLastModified(this, milis);
278
public bool SetReadOnly ()
280
return FileHelper.Instance.SetReadOnly (this);
376
283
public Uri ToURI ()
381
288
// Don't change the case of this method, since ngit does reflection on it
382
289
public bool canExecute ()
384
if (RunningOnLinux) {
385
UnixFileInfo fi = new UnixFileInfo (path);
388
return 0 != (fi.FileAccessPermissions & (FileAccessPermissions.UserExecute | FileAccessPermissions.GroupExecute | FileAccessPermissions.OtherExecute));
291
return FileHelper.Instance.CanExecute (this);
394
294
// Don't change the case of this method, since ngit does reflection on it
395
295
public bool setExecutable (bool exec)
397
if (RunningOnLinux) {
398
UnixFileInfo fi = new UnixFileInfo (path);
399
FileAccessPermissions perms = fi.FileAccessPermissions;
401
if (perms.HasFlag (FileAccessPermissions.UserRead))
402
perms |= FileAccessPermissions.UserExecute;
403
if (perms.HasFlag (FileAccessPermissions.OtherRead))
404
perms |= FileAccessPermissions.OtherExecute;
405
if ((perms.HasFlag (FileAccessPermissions.GroupRead)))
406
perms |= FileAccessPermissions.GroupExecute;
408
if (perms.HasFlag (FileAccessPermissions.UserRead))
409
perms &= ~FileAccessPermissions.UserExecute;
410
if (perms.HasFlag (FileAccessPermissions.OtherRead))
411
perms &= ~FileAccessPermissions.OtherExecute;
412
if ((perms.HasFlag (FileAccessPermissions.GroupRead)))
413
perms &= ~FileAccessPermissions.GroupExecute;
415
fi.FileAccessPermissions = perms;
297
return FileHelper.Instance.SetExecutable (this, exec);
422
300
public string GetParent ()
436
static UnixFileSystemInfo GetUnixFileInfo (string path)
439
return Mono.Unix.UnixFileInfo.GetFileSystemEntry (path);
440
} catch (DirectoryNotFoundException ex) {
441
// If we have a file /foo/bar and probe the path /foo/bar/baz, we get a DirectoryNotFound exception
442
// because 'bar' is a file and therefore 'baz' cannot possibly exist. This is annoying.
443
var inner = ex.InnerException as UnixIOException;
444
if (inner != null && inner.ErrorCode == Mono.Unix.Native.Errno.ENOTDIR)
450
314
static internal string pathSeparator {
451
315
get { return Path.PathSeparator.ToString (); }