forked from fsprojects/FAKE
-
Notifications
You must be signed in to change notification settings - Fork 0
/
FileSystem.fs
116 lines (94 loc) · 3.81 KB
/
FileSystem.fs
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
/// This module contains a file pattern globbing implementation.
[<AutoOpen>]
module Fake.FileSystem
open System
open System.Collections.Generic
open System.IO
open System.Text.RegularExpressions
/// Internal representation of a file set.
type FileIncludes =
{ BaseDirectory : string
Includes : string list
Excludes : string list }
/// Adds the given pattern to the file includes
member this.And pattern = { this with Includes = this.Includes @ [ pattern ] }
/// Ignores files with the given pattern
member this.ButNot pattern = { this with Excludes = pattern :: this.Excludes }
/// Sets a directory as BaseDirectory.
member this.SetBaseDirectory(dir : string) = { this with BaseDirectory = dir.TrimEnd(Path.DirectorySeparatorChar) }
/// Checks if a particular file is matched
member this.IsMatch (path : string) =
let fullDir pattern =
if Path.IsPathRooted(pattern) then
pattern
else
System.IO.Path.Combine(this.BaseDirectory, pattern)
let included =
this.Includes
|> Seq.exists(fun fileInclude ->
Globbing.isMatch (fullDir fileInclude) path
)
let excluded =
this.Excludes
|> Seq.exists(fun fileExclude ->
Globbing.isMatch (fullDir fileExclude) path
)
included && not excluded
interface IEnumerable<string> with
member this.GetEnumerator() =
let hashSet = HashSet()
let excludes =
seq {
for pattern in this.Excludes do
yield! Globbing.search this.BaseDirectory pattern
}
|> Set.ofSeq
let files =
seq {
for pattern in this.Includes do
yield! Globbing.search this.BaseDirectory pattern
}
|> Seq.filter (fun x -> not (Set.contains x excludes))
|> Seq.filter (fun x -> hashSet.Add x)
files.GetEnumerator()
member this.GetEnumerator() = (this :> IEnumerable<string>).GetEnumerator() :> System.Collections.IEnumerator
let private defaultBaseDir = Path.GetFullPath "."
/// Include files
let Include x =
{ BaseDirectory = defaultBaseDir
Includes = [ x ]
Excludes = [] }
/// Sets a directory as baseDirectory for fileIncludes.
let SetBaseDir (dir : string) (fileIncludes : FileIncludes) = fileIncludes.SetBaseDirectory dir
/// Add Include operator
let inline (++) (x : FileIncludes) pattern = x.And pattern
/// Exclude operator
let inline (--) (x : FileIncludes) pattern = x.ButNot pattern
/// Includes a single pattern and scans the files - !! x = AllFilesMatching x
let inline (!!) x = Include x
/// Looks for a tool first in its default path, if not found the in ./packages/ and then
/// in all subfolders of the root folder - returns the tool file name.
let findToolInSubPath toolname defaultPath =
try
let tools = !! (defaultPath @@ "/**/" @@ toolname)
if Seq.isEmpty tools then
let packages = !! ("./packages/**/" @@ toolname)
if Seq.isEmpty packages then
let root = !! ("./**/" @@ toolname)
Seq.head root
else
Seq.head packages
else
Seq.head tools
with
| _ -> defaultPath @@ toolname
/// Looks for a tool in all subfolders - returns the folder where the tool was found.
let findToolFolderInSubPath toolname defaultPath =
try
let tools = !! ("./**/" @@ toolname)
if Seq.isEmpty tools then defaultPath
else
let fi = FileInfo (Seq.head tools)
fi.Directory.FullName
with
| _ -> defaultPath