@@ -6,105 +6,106 @@ open System.Xml.Linq
66open System.IO .Compression
77open Paket
88open System.Text
9+ open System.Text .RegularExpressions
910open System.Xml
1011
1112let nuspecId = " nuspec"
1213let corePropsId = " coreProp"
1314let contentTypePath = " [Content_Types].xml"
1415
15- let contentTypeDoc fileList =
16+ let contentTypeDoc fileList =
1617 let declaration = XDeclaration( " 1.0" , " UTF-8" , " yes" )
1718 let ns = XNamespace.Get " http://schemas.openxmlformats.org/package/2006/content-types"
1819 let root = XElement( ns + " Types" )
19-
20+
2021 let defaultNode extension contentType =
2122 let def = XElement( ns + " Default" )
2223 def.SetAttributeValue( XName.Get " Extension" , extension)
2324 def.SetAttributeValue( XName.Get " ContentType" , contentType)
2425 def
25-
26- let knownExtensions =
26+
27+ let knownExtensions =
2728 Map.ofList [ " rels" , " application/vnd.openxmlformats-package.relationships+xml"
2829 " psmdcp" , " application/vnd.openxmlformats-package.core-properties+xml" ]
29-
30+
3031 let ext path = Path.GetExtension( path) .TrimStart([| '.' |]) .ToLowerInvariant()
31-
32- let fType ext =
32+
33+ let fType ext =
3334 knownExtensions
3435 |> Map.tryFind ext
35- |> function
36+ |> function
3637 | Some ft -> ft
3738 | None -> " application/octet"
38-
39- let contentTypes =
39+
40+ let contentTypes =
4041 fileList
41- |> Seq.choose ( fun f ->
42+ |> Seq.choose ( fun f ->
4243 let e = ext f
43- if String.IsNullOrWhiteSpace e then
44+ if String.IsNullOrWhiteSpace e then
4445 None
4546 else Some( e, fType e))
4647 |> Seq.distinct
4748 |> Seq.iter ( fun ( ex , ct ) -> defaultNode ex ct |> root.Add)
48-
49+
4950 XDocument( declaration, box root)
5051
51- let nuspecDoc ( info : CompleteInfo ) =
52+ let nuspecDoc ( info : CompleteInfo ) =
5253 let core , optional = info
5354 let declaration = XDeclaration( " 1.0" , " UTF-8" , " yes" )
5455 let ns = XNamespace.Get " http://schemas.microsoft.com/packaging/2011/10/nuspec.xsd"
5556 let root = XElement( ns + " package" )
56-
57- let addChildNode ( parent : XElement ) name value =
57+
58+ let addChildNode ( parent : XElement ) name value =
5859 let node = XElement( ns + name)
5960 node.SetValue value
6061 parent.Add node
61-
62+
6263 let metadataNode = XElement( ns + " metadata" )
6364 root.Add metadataNode
6465 let (!!) = addChildNode metadataNode
65-
66- let (!!?) nodeName strOpt =
66+
67+ let (!!?) nodeName strOpt =
6768 match strOpt with
6869 | Some s -> addChildNode metadataNode nodeName s
6970 | None -> ()
70-
71- let buildFrameworkReferencesNode libName =
71+
72+ let buildFrameworkReferencesNode libName =
7273 let element = XElement( ns + " frameworkAssembly" )
7374 element.SetAttributeValue( XName.Get " assemblyName" , libName)
7475 element
75-
76- let buildFrameworkReferencesNode frameworkAssembliesList =
76+
77+ let buildFrameworkReferencesNode frameworkAssembliesList =
7778 if frameworkAssembliesList = [] then () else
7879 let d = XElement( ns + " frameworkAssemblies" )
7980 frameworkAssembliesList |> List.iter ( buildFrameworkReferencesNode >> d.Add)
8081 metadataNode.Add d
8182
82- let buildDependencyNode ( Id , ( VersionRequirement ( range , _ ))) =
83+ let buildDependencyNode ( Id , ( VersionRequirement ( range , _ ))) =
8384 let dep = XElement( ns + " dependency" )
8485 dep.SetAttributeValue( XName.Get " id" , Id)
8586
8687 match range.FormatInNuGetSyntax() with
8788 | " 0" -> ()
8889 | versionStr -> dep.SetAttributeValue( XName.Get " version" , versionStr)
8990 dep
90-
91- let buildDependenciesNode dependencyList =
91+
92+ let buildDependenciesNode dependencyList =
9293 if dependencyList = [] then () else
9394 let d = XElement( ns + " dependencies" )
9495 dependencyList |> List.iter ( buildDependencyNode >> d.Add)
9596 metadataNode.Add d
9697
97- let buildReferenceNode ( fileName ) =
98+ let buildReferenceNode ( fileName ) =
9899 let dep = XElement( ns + " reference" )
99100 dep.SetAttributeValue( XName.Get " file" , fileName)
100101 dep
101102
102- let buildReferencesNode referenceList =
103+ let buildReferencesNode referenceList =
103104 if referenceList = [] then () else
104105 let d = XElement( ns + " references" )
105106 referenceList |> List.iter ( buildReferenceNode >> d.Add)
106107 metadataNode.Add d
107-
108+
108109 !! " id" core.Id
109110 match core.Version with
110111 | Some v -> !! " version" <| v.ToString()
@@ -133,20 +134,20 @@ let nuspecDoc (info:CompleteInfo) =
133134
134135let corePropsPath = sprintf " package/services/metadata/core-properties/%s .psmdcp" corePropsId
135136
136- let corePropsDoc ( core : CompleteCoreInfo ) =
137+ let corePropsDoc ( core : CompleteCoreInfo ) =
137138 let declaration = XDeclaration( " 1.0" , " UTF-8" , " yes" )
138139 let ns = XNamespace.Get " http://schemas.openxmlformats.org/package/2006/metadata/core-properties"
139140 let dc = XNamespace.Get " http://purl.org/dc/elements/1.1/"
140141 let dcterms = XNamespace.Get " http://purl.org/dc/terms/"
141142 let xsi = XNamespace.Get " http://www.w3.org/2001/XMLSchema-instance"
142- let root =
143+ let root =
143144 XElement
144- ( ns + " Relationships" , XAttribute( XName.Get " xmlns" , ns.NamespaceName),
145- XAttribute( XNamespace.Xmlns + " dc" , dc.NamespaceName),
146- XAttribute( XNamespace.Xmlns + " dcterms" , dcterms.NamespaceName),
145+ ( ns + " Relationships" , XAttribute( XName.Get " xmlns" , ns.NamespaceName),
146+ XAttribute( XNamespace.Xmlns + " dc" , dc.NamespaceName),
147+ XAttribute( XNamespace.Xmlns + " dcterms" , dcterms.NamespaceName),
147148 XAttribute( XNamespace.Xmlns + " xsi" , xsi.NamespaceName))
148-
149- let (!!) ( ns : XNamespace ) name value =
149+
150+ let (!!) ( ns : XNamespace ) name value =
150151 let node = XElement( ns + name)
151152 node.SetValue value
152153 root.Add node
@@ -161,12 +162,12 @@ let corePropsDoc (core : CompleteCoreInfo) =
161162
162163let relsPath = " _rels/.rels"
163164
164- let relsDoc ( core : CompleteCoreInfo ) =
165+ let relsDoc ( core : CompleteCoreInfo ) =
165166 let declaration = XDeclaration( " 1.0" , " UTF-8" , " yes" )
166167 let ns = XNamespace.Get " http://schemas.openxmlformats.org/package/2006/relationships"
167168 let root = XElement( ns + " Relationships" )
168-
169- let r type' target id' =
169+
170+ let r type' target id' =
170171 let rel = XElement( ns + " Relationship" )
171172 rel.SetAttributeValue( XName.Get " Type" , type')
172173 rel.SetAttributeValue( XName.Get " Target" , target)
@@ -176,31 +177,60 @@ let relsDoc (core : CompleteCoreInfo) =
176177 r " http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties" ( " /" + corePropsPath) corePropsId
177178 XDocument( declaration, box root)
178179
179- let xDocWriter ( xDoc : XDocument ) ( stream : System.IO.Stream ) =
180+ let xDocWriter ( xDoc : XDocument ) ( stream : System.IO.Stream ) =
180181 let settings = new XmlWriterSettings( Indent = true , Encoding = Encoding.UTF8)
181182 use xmlWriter = XmlWriter.Create( stream, settings)
182183 xDoc.WriteTo xmlWriter
183184 xmlWriter.Flush()
184185
185- let writeNupkg ( core : CompleteCoreInfo ) optional =
186+ let writeNupkg ( core : CompleteCoreInfo ) optional =
186187 [ core.NuspecFileName, nuspecDoc( core, optional) |> xDocWriter
187188 corePropsPath, corePropsDoc core |> xDocWriter
188189 relsPath, relsDoc core |> xDocWriter ]
189190
190- let Write ( core : CompleteCoreInfo ) optional workingDir outputDir =
191+ let Write ( core : CompleteCoreInfo ) optional workingDir outputDir =
191192 let outputPath = Path.Combine( outputDir, core.PackageFileName)
192193 if File.Exists outputPath then
193194 File.Delete outputPath
194195
195196 use zipToCreate = new FileStream( outputPath, FileMode.Create)
196197 use zipFile = new ZipArchive( zipToCreate, ZipArchiveMode.Create)
197198
198- let entries = System.Collections.Generic.List<_>()
199-
200- let addEntry path writerF =
199+ let entries = System.Collections.Generic.List<_>()
200+
201+ let fixRelativePath ( p : string ) =
202+ let isWinDrive = Regex( @" ^\w:\\.*" , RegexOptions.Compiled) .IsMatch
203+ let isNixRoot = Regex( @" ^\/.*" , RegexOptions.Compiled) .IsMatch
204+
205+ let prepend , path =
206+ match p with
207+ | s when isWinDrive s -> [| s.Substring( 0 , 3 )|], s.Substring( 3 )
208+ | s when isNixRoot s -> [| " /" |], s.Substring( 1 )
209+ | s when String.IsNullOrWhiteSpace s -> failwith " Empty exclusion path!"
210+ | s -> [||], s
211+
212+ path.Split( '\\' , '/' )
213+ |> Array.fold ( fun ( xs : string []) x ->
214+ match x with
215+ | s when " .." .Equals s -> Array.sub xs 0 ( xs.Length-1 )
216+ | s when " ." .Equals s -> xs
217+ | _ -> Array.append xs [| x|]) [||]
218+ |> Array.append prepend
219+ |> Array.fold ( fun p' x -> Path.Combine( p', x)) " "
220+
221+ let exclusions =
222+ optional.FilesExcluded
223+ |> List.map ( fun e -> Path.Combine( workingDir, e) |> fixRelativePath)
224+ |> List.map Fake.Globbing.isMatch
225+
226+ let isExcluded p =
227+ let path = DirectoryInfo( p) .FullName
228+ exclusions |> List.exists ( fun f -> f path)
229+
230+ let addEntry path writerF =
201231 if entries.Contains( path) then () else
202232 entries.Add path |> ignore
203- let entry = zipFile.CreateEntry( path)
233+ let entry = zipFile.CreateEntry( path)
204234 use stream = entry.Open()
205235 writerF stream
206236 stream.Close()
@@ -211,7 +241,7 @@ let Write (core : CompleteCoreInfo) optional workingDir outputDir =
211241 zipFile.CreateEntryFromFile( source, path) |> ignore
212242
213243 let ensureValidTargetName ( target : string ) =
214- let target =
244+ let target =
215245 target.Replace( " " , " %20" ) .Replace( " \\ " , " /" )
216246 |> fun s -> if s.StartsWith( " ./" ) then s.Remove( 0 , 2 ) else s
217247
@@ -222,35 +252,39 @@ let Write (core : CompleteCoreInfo) optional workingDir outputDir =
222252 | t -> t + " /"
223253
224254 // adds all files in a directory to the zipFile
225- let rec addDir source target =
226- let target = ensureValidTargetName target
227- for file in Directory.EnumerateFiles( source, " *.*" , SearchOption.TopDirectoryOnly) do
228- let fi = FileInfo file
229- let path = Path.Combine( target, fi.Name)
230- addEntryFromFile path fi.FullName
255+ let rec addDir source target =
256+ if not <| isExcluded source then
257+ let target = ensureValidTargetName target
258+ for file in Directory.EnumerateFiles( source, " *.*" , SearchOption.TopDirectoryOnly) do
259+ if not <| isExcluded file then
260+ let fi = FileInfo file
261+ let path = Path.Combine( target, fi.Name)
231262
232- for dir in Directory.EnumerateDirectories( source, " *" , SearchOption.TopDirectoryOnly) do
233- let di = DirectoryInfo dir
234- addDir di.FullName ( Path.Combine( target, di.Name))
263+ addEntryFromFile path fi.FullName
264+
265+ for dir in Directory.EnumerateDirectories( source, " *" , SearchOption.TopDirectoryOnly) do
266+ let di = DirectoryInfo dir
267+ addDir di.FullName ( Path.Combine( target, di.Name))
235268
236269 // add files
237270 for fileName, targetFileName in optional.Files do
238271 let targetFileName = ensureValidTargetName targetFileName
239272 let source = Path.Combine( workingDir, fileName)
240273 if Directory.Exists source then
241274 addDir source targetFileName
242- else
275+ else
243276 if File.Exists source then
244- let fi = FileInfo( source)
245- let path = Path.Combine( targetFileName, fi.Name)
246- addEntryFromFile path source
247- else
277+ if not <| isExcluded source then
278+ let fi = FileInfo( source)
279+ let path = Path.Combine( targetFileName, fi.Name)
280+ addEntryFromFile path source
281+ else
248282 failwithf " Could not find source file %s " source
249283
250284 // add metadata
251- for path, writer in writeNupkg core optional do
285+ for path, writer in writeNupkg core optional do
252286 addEntry path writer
253-
287+
254288 entries
255289 |> Seq.toList
256290 |> contentTypeDoc
0 commit comments