Skip to content

Commit

Permalink
fixed job parser to allow for move elements + engine fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
gabesoft committed Feb 20, 2011
1 parent 8f0aaa0 commit 4224f45
Show file tree
Hide file tree
Showing 6 changed files with 71 additions and 42 deletions.
7 changes: 6 additions & 1 deletion ProjApp/GabeSoft.FOPS.Core/Engine.fs
Expand Up @@ -72,12 +72,17 @@ type Engine(server: IOServer, ?log:Log) =

let copyFolder (copy, info, warn) (src, dst, force, excludes) =
let excludes = excludes |> List.map Wildcard.toRegex
let dstExists = server.Provider.FolderExists dst
let spec = {
Pattern = (Wildcard.matchAll src)
Exclude = (Wildcard.matchAll dst) :: excludes
Recursive = true }
let node = server.Node src |> Filter.apply spec
let fdst path = Path.combine dst (Path.part src path)
let fdst =
let dst = match dstExists with
| true -> Path.combine dst (Path.file src)
| false -> dst
fun path -> Path.combine dst (Path.part src path)
copyDeep (copy, info, warn) (fdst, force) node

let copyPattern (copy, info, warn) (src, dst, force, excludes) =
Expand Down
74 changes: 37 additions & 37 deletions ProjApp/GabeSoft.FOPS.Core/JobsParser.fs
Expand Up @@ -13,90 +13,90 @@ type ParseException (message:string, ?innerException:Exception) =
match innerException with | Some ex -> ex | None -> null)

module JobsParser =
let defaults = Map.ofList [ "force", true ]

let fail message = raise (new ParseException(message))
let lname (elem: XElement) = elem.Name.LocalName
let xname name = XName.Get (name)
let xattr name (elem: XElement) =
let private defaults = Map.ofList [ "force", true ]
let private fail message = raise (new ParseException(message))
let private lname (elem: XElement) = elem.Name.LocalName
let private xname name = XName.Get (name)
let private xattr name (elem: XElement) =
let attr = elem.Attribute(xname name)
if attr = null then None else Some attr.Value
let xelem name (parent: XContainer) =
let private xelem name (parent: XContainer) =
let elem = parent.Element(xname name)
if elem = null then None else Some elem
let xvalue (elem: option<XElement>) =
let private xvalue (elem: option<XElement>) =
elem |> Option.map(fun e -> Some e.Value)
let xsons name (parent: XContainer) =
parent.Elements (xname name)
/// Returns the children elements with the
/// specified name of the given parent element.
let private xcn name (parent: XContainer) = parent.Elements (xname name)
/// Returns all children elements of the given parent element.
let private xall (parent: XContainer) = parent.Elements()

let getRequired (v: option<string>) errorIfMissing =
let private getRequired (v: option<string>) errorIfMissing =
match v with
| None -> fail errorIfMissing
| Some e -> e

let getOptional (v: option<string>) =
let private getOptional (v: option<string>) =
match v with
| None -> String.Empty
| Some e -> e

let getAttr name elem required =
let private getAttr name elem required =
match required with
| true -> getRequired (xattr name elem)
(sprintf "'%s' is a required attribute on '%s' element" name (lname elem))
| false -> getOptional (xattr name elem)

let toBool def text =
let private toBool def text =
match bool.TryParse(text) with
| true, v -> v
| false, _ -> def

let parseExclude (elem: XElement) =
let private parseExclude (elem: XElement) =
getAttr "src" elem true

let parseCopy f (elem: XElement) =
let excludes = xsons "exclude" elem
let private parseCopy f (elem: XElement) =
let excludes = xcn "exclude" elem
|> Seq.map parseExclude
|> Seq.toList
let src = getAttr "src" elem true
let dst = getAttr "dst" elem true
let force = getAttr "force" elem false
f (src, dst, force |> toBool defaults.["force"], excludes)

let parseYank f (elem: XElement) =
let private parseYank f (elem: XElement) =
let src = getAttr "src" elem true
f (getAttr "src" elem true)

let parseItem (elem: XElement) =
let private parseItem (elem: XElement) =
match lname elem with
| "copy" -> parseCopy (Item.copy PatternMode) elem
| "copy-file" -> parseCopy (Item.copy FileMode) elem
| "copy-dir" -> parseCopy (Item.copy FolderMode) elem
| "link" -> parseCopy (Item.link PatternMode) elem
| "link-file" -> parseCopy (Item.link FileMode) elem
| "link-dir" -> parseCopy (Item.link FolderMode) elem
| "delete" -> parseYank (Item.yank PatternMode) elem
| "delete-dir" -> parseYank (Item.yank FolderMode) elem
| "copy" -> [ parseCopy (Item.copy PatternMode) elem ]
| "copy-file" -> [ parseCopy (Item.copy FileMode) elem ]
| "copy-dir" -> [ parseCopy (Item.copy FolderMode) elem ]
| "link" -> [ parseCopy (Item.link PatternMode) elem ]
| "link-file" -> [ parseCopy (Item.link FileMode) elem ]
| "link-dir" -> [ parseCopy (Item.link FolderMode) elem ]
| "delete" -> [ parseYank (Item.yank PatternMode) elem ]
| "delete-dir" -> [ parseYank (Item.yank FolderMode) elem ]
| "move-file" -> [ parseCopy (Item.copy FileMode) elem
parseYank (Item.yank FileMode) elem ]
| "move-dir" -> [ parseCopy (Item.copy FolderMode) elem
parseYank (Item.yank FolderMode) elem ]
| n -> fail (sprintf "unknown element %s" n)

let parseJob (elem: XElement) =
let id = getAttr "id" elem true
let baseSrc = getAttr "base-src" elem false
let baseDst = getAttr "base-dst" elem false
let items = xsons "copy" elem
|> Seq.append (xsons "copy-file" elem)
|> Seq.append (xsons "copy-dir" elem)
|> Seq.append (xsons "link" elem)
|> Seq.append (xsons "link-file" elem)
|> Seq.append (xsons "link-dir" elem)
|> Seq.append (xsons "delete" elem)
|> Seq.append (xsons "delete-dir" elem)
let items = xall elem
|> Seq.map parseItem
|> Seq.toList
|> Seq.concat
|> Seq.toList
new Job(items, id, baseSrc, baseDst)

let parseDocument (xdoc: XDocument) =
xdoc.Root
|> xsons "job"
|> xcn "job"
|> Seq.map parseJob
|> Seq.toList

Expand Down
2 changes: 1 addition & 1 deletion ProjTest/GabeSoft.FOPS.Test/EngineTests.fs
Expand Up @@ -154,7 +154,7 @@ let ``Copy dir should copy source inside existing directory`` () =
let job = Item.copy FolderMode (src, dst, true, []) |> mkJob
let paths = [ @"C:\a\b\f1.txt"
@"C:\a\b\c\f2.txt"
@"C:\e\f" ]
@"C:\e\f\" ]
Given (mkServer paths, job)
|> When running_job
|> Called <@fun x -> x.Copy@>(paths.[0], @"C:\e\f\b\f1.txt")
Expand Down
2 changes: 1 addition & 1 deletion ProjTest/GabeSoft.FOPS.Test/Files/jobs4.xml
Expand Up @@ -8,7 +8,7 @@
<link src="Dir1\*\cache\?*\f*.pd?" dst="C:\Dest" >
<exclude src="Dir1\*\cache\a\f*.pdb" />
</link>
<yank src="C:\Temp\*\obj\*.*" />
<delete src="C:\Temp\*\obj\*.*" />
</job>
<job id="j2">
<copy src="Code\Proj\*\*.*" dst="Output">
Expand Down
6 changes: 4 additions & 2 deletions ProjTest/GabeSoft.FOPS.Test/Files/jobs5.xml
Expand Up @@ -14,6 +14,10 @@
<!-- fops -cf -src=C:\source\b\f2.pdf -dst=C:dest\f3.pdf -->
<!-- fops -l -src=C:\a\b\?*\* -dst=C:\e\f -->

<!-- copy/move behavior: -->
<!-- if dst exists copy the source inside destination -->
<!-- otherwise copy the source as the destination -->

<!-- TODO: add force (delete read-only) & recursive to delete ?-->
<!-- <delete-dir src="a\b" force="true" recursive="true"/>-->

Expand All @@ -23,8 +27,6 @@
<delete src="a\b\c\f1.pdb" />
<delete-dir src="a\b" />
<copy-file src="b\f2.pdf" dst="c\f3.pdf" />
<!-- if dst exists copy the source inside destination -->
<!-- otherwise copy the source as the destination -->
<copy-dir src="b\e\" dst="\">
<exclude src="*\*.tmp" />
<exclude src="*\bin\*.pdb" />
Expand Down
22 changes: 22 additions & 0 deletions ProjTest/GabeSoft.FOPS.Test/JobsParserTests.fs
Expand Up @@ -125,6 +125,21 @@ let expected_full_paths jobs =
printMethod (ok)
List.forall id ok

let expected_order jobs =
let job = get_job_with_id "j4" jobs
let actual = job.Items |> List.map (function
| Copy (_, _, _, _, m) -> "copy", m
| Link (_, _, _, _, m) -> "link", m
| Yank (_, m) -> "yank", m)
let expected = [
"yank", PatternMode; "yank", PatternMode; "yank", FolderMode;
"copy", FileMode; "copy", FolderMode; "copy", PatternMode;
"link", PatternMode;
"copy", FileMode; "yank", FileMode;
"copy", FolderMode; "yank", FolderMode]
printMethod (expected.Length, actual.Length)
expected = actual

[<Scenario>]
let ``Can find the jobs files`` () =
Given paths
Expand Down Expand Up @@ -200,3 +215,10 @@ let ``Job id is a required attribute`` () =
Given file3
|> When parsing
|> Verify

[<Scenario>]
let ``Can populate the items in order`` () =
Given file5
|> When parsing
|> It should have expected_order
|> Verify

0 comments on commit 4224f45

Please sign in to comment.