Skip to content

Commit

Permalink
Make the Globbing independent for use in Paket
Browse files Browse the repository at this point in the history
  • Loading branch information
forki committed Mar 11, 2015
1 parent 770b9f4 commit 5df0a99
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 79 deletions.
5 changes: 3 additions & 2 deletions src/app/FakeLib/FakeLib.fsproj
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
Expand Down Expand Up @@ -56,7 +56,8 @@
<Compile Include="ProcessHelper.fs" />
<Compile Include="AppVeyor.fs" />
<Compile Include="TaskRunnerHelper.fs" />
<Compile Include="Globbing\FileSystem.fs" />
<Compile Include="Globbing\Globbing.fs" />
<Compile Include="Globbing\FileSystem.fs" />
<Compile Include="UnitTest\UnitTestCommon.fs" />
<Compile Include="UnitTest\UnitTestHelper.fs" />
<Compile Include="UnitTest\NUnit\Xml.fs" />
Expand Down
79 changes: 2 additions & 77 deletions src/app/FakeLib/Globbing/FileSystem.fs
Original file line number Diff line number Diff line change
Expand Up @@ -7,81 +7,6 @@ open System.Collections.Generic
open System.IO
open System.Text.RegularExpressions

/// Combines two path strings using Path.Combine
let inline private combinePaths path1 (path2 : string) = Path.Combine(path1, path2.TrimStart [| '\\'; '/' |])

/// Combines two path strings using Path.Combine
let inline private (@@) path1 path2 = combinePaths path1 path2

type private SearchOption =
| Directory of string
| Drive of string
| Recursive
| FilePattern of string

let private checkSubDirs absolute (dir : string) root =
if dir.Contains "*" then Directory.EnumerateDirectories(root, dir, SearchOption.TopDirectoryOnly) |> Seq.toList
else
let path = Path.Combine(root, dir)

let di =
if absolute then new DirectoryInfo(dir)
else new DirectoryInfo(path)
if di.Exists then [ di.FullName ]
else []

let rec private buildPaths acc (input : SearchOption list) =
match input with
| [] -> acc
| Directory(name) :: t ->
let subDirs =
acc
|> List.map (checkSubDirs false name)
|> List.concat
buildPaths subDirs t
| Drive(name) :: t ->
let subDirs =
acc
|> List.map (checkSubDirs true name)
|> List.concat
buildPaths subDirs t
| Recursive :: [] ->
let dirs =
Seq.collect (fun dir -> Directory.EnumerateFileSystemEntries(dir, "*", SearchOption.AllDirectories)) acc
|> Seq.toList
buildPaths (acc @ dirs) []
| Recursive :: t ->
let dirs =
Seq.collect (fun dir -> Directory.EnumerateDirectories(dir, "*", SearchOption.AllDirectories)) acc
|> Seq.toList
buildPaths (acc @ dirs) t
| FilePattern(pattern) :: t -> Seq.collect (fun dir -> Directory.EnumerateFiles(dir, pattern)) acc |> Seq.toList

let private isDrive =
let regex = Regex(@"^[A-Za-z]:$", RegexOptions.Compiled)
fun dir -> regex.IsMatch dir

let inline private normalizePath (p : string) =
p.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar)
let inline private normalizeOutputPath (p : string) =
p.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar)
.TrimEnd(Path.DirectorySeparatorChar)

let private search (baseDir : string) (input : string) =
let baseDir = normalizePath baseDir
let input = normalizePath input
let input = input.Replace(baseDir, "")
let filePattern = Path.GetFileName(input)
input.Split([| '/'; '\\' |], StringSplitOptions.RemoveEmptyEntries)
|> Seq.map (function
| "**" -> Recursive
| a when a = filePattern -> FilePattern(a)
| a when isDrive a -> Directory(a + "\\")
| a -> Directory(a))
|> Seq.toList
|> buildPaths [ baseDir ]
|> List.map normalizeOutputPath

/// Internal representation of a file set.
type FileIncludes =
{ BaseDirectory : string
Expand All @@ -105,14 +30,14 @@ type FileIncludes =
let excludes =
seq {
for pattern in this.Excludes do
yield! search this.BaseDirectory pattern
yield! Globbing.search this.BaseDirectory pattern
}
|> Set.ofSeq

let files =
seq {
for pattern in this.Includes do
yield! search this.BaseDirectory pattern
yield! Globbing.search this.BaseDirectory pattern
}
|> Seq.filter (fun x -> not (Set.contains x excludes))
|> Seq.filter (fun x -> hashSet.Add x)
Expand Down
76 changes: 76 additions & 0 deletions src/app/FakeLib/Globbing/Globbing.fs
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
/// This module contains a file pattern globbing implementation.
module Fake.Globbing

open System
open System.Collections.Generic
open System.IO
open System.Text.RegularExpressions

type private SearchOption =
| Directory of string
| Drive of string
| Recursive
| FilePattern of string

let private checkSubDirs absolute (dir : string) root =
if dir.Contains "*" then Directory.EnumerateDirectories(root, dir, SearchOption.TopDirectoryOnly) |> Seq.toList
else
let path = Path.Combine(root, dir)

let di =
if absolute then new DirectoryInfo(dir)
else new DirectoryInfo(path)
if di.Exists then [ di.FullName ]
else []

let rec private buildPaths acc (input : SearchOption list) =
match input with
| [] -> acc
| Directory(name) :: t ->
let subDirs =
acc
|> List.map (checkSubDirs false name)
|> List.concat
buildPaths subDirs t
| Drive(name) :: t ->
let subDirs =
acc
|> List.map (checkSubDirs true name)
|> List.concat
buildPaths subDirs t
| Recursive :: [] ->
let dirs =
Seq.collect (fun dir -> Directory.EnumerateFileSystemEntries(dir, "*", SearchOption.AllDirectories)) acc
|> Seq.toList
buildPaths (acc @ dirs) []
| Recursive :: t ->
let dirs =
Seq.collect (fun dir -> Directory.EnumerateDirectories(dir, "*", SearchOption.AllDirectories)) acc
|> Seq.toList
buildPaths (acc @ dirs) t
| FilePattern(pattern) :: t -> Seq.collect (fun dir -> Directory.EnumerateFiles(dir, pattern)) acc |> Seq.toList

let private isDrive =
let regex = Regex(@"^[A-Za-z]:$", RegexOptions.Compiled)
fun dir -> regex.IsMatch dir

let inline private normalizePath (p : string) =
p.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar)
let inline private normalizeOutputPath (p : string) =
p.Replace('\\', Path.DirectorySeparatorChar).Replace('/', Path.DirectorySeparatorChar)
.TrimEnd(Path.DirectorySeparatorChar)

let internal search (baseDir : string) (input : string) =
let baseDir = normalizePath baseDir
let input = normalizePath input
let input = input.Replace(baseDir, "")
let filePattern = Path.GetFileName(input)
input.Split([| '/'; '\\' |], StringSplitOptions.RemoveEmptyEntries)
|> Seq.map (function
| "**" -> Recursive
| a when a = filePattern -> FilePattern(a)
| a when isDrive a -> Directory(a + "\\")
| a -> Directory(a))
|> Seq.toList
|> buildPaths [ baseDir ]
|> List.map normalizeOutputPath

0 comments on commit 5df0a99

Please sign in to comment.