From 5df0a99e789975e9e5da219e987e079a44615f4d Mon Sep 17 00:00:00 2001 From: Steffen Forkmann Date: Wed, 11 Mar 2015 12:34:39 +0100 Subject: [PATCH] Make the Globbing independent for use in Paket --- src/app/FakeLib/FakeLib.fsproj | 5 +- src/app/FakeLib/Globbing/FileSystem.fs | 79 +------------------------- src/app/FakeLib/Globbing/Globbing.fs | 76 +++++++++++++++++++++++++ 3 files changed, 81 insertions(+), 79 deletions(-) create mode 100644 src/app/FakeLib/Globbing/Globbing.fs diff --git a/src/app/FakeLib/FakeLib.fsproj b/src/app/FakeLib/FakeLib.fsproj index b3f8b79e7f9..972fe715826 100644 --- a/src/app/FakeLib/FakeLib.fsproj +++ b/src/app/FakeLib/FakeLib.fsproj @@ -1,4 +1,4 @@ - + @@ -56,7 +56,8 @@ - + + diff --git a/src/app/FakeLib/Globbing/FileSystem.fs b/src/app/FakeLib/Globbing/FileSystem.fs index c602531c0c4..f8f4abd3505 100644 --- a/src/app/FakeLib/Globbing/FileSystem.fs +++ b/src/app/FakeLib/Globbing/FileSystem.fs @@ -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 @@ -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) diff --git a/src/app/FakeLib/Globbing/Globbing.fs b/src/app/FakeLib/Globbing/Globbing.fs new file mode 100644 index 00000000000..a7834f18832 --- /dev/null +++ b/src/app/FakeLib/Globbing/Globbing.fs @@ -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 \ No newline at end of file