diff --git a/src/app/FakeLib/FakeLib.fsproj b/src/app/FakeLib/FakeLib.fsproj index c844691a954..2c5b204d8b2 100644 --- a/src/app/FakeLib/FakeLib.fsproj +++ b/src/app/FakeLib/FakeLib.fsproj @@ -98,7 +98,7 @@ - + @@ -163,6 +163,7 @@ + diff --git a/src/app/FakeLib/RoboCopyHelper.fs b/src/app/FakeLib/RoboCopyHelper.fs new file mode 100644 index 00000000000..097f6071446 --- /dev/null +++ b/src/app/FakeLib/RoboCopyHelper.fs @@ -0,0 +1,54 @@ +/// Contains a task to use [robocopy](https://en.wikipedia.org/wiki/Robocopy) on Windows. +module Fake.RoboCopyHelper + +type RoboCopyOptions = { Mirror: bool } + +/// Executes a RoboCopy command with options +/// ## Parameters +/// - `source` - The source directory +/// - `destination` - The target directory +/// - `options` - The options to pass to robocopy +let private roboCopyWithOptions (source:string) (destination:string) (options:RoboCopyOptions) = + let args = + "/D /c robocopy " + + (source.TrimEnd('\\') |> FullName |> toParam) + + (destination.TrimEnd('\\') |> FullName |> toParam) + + if options.Mirror then " /MIR /IT" + else " /IT" + + let exitcode = ExecProcess (fun info -> + info.FileName <- "CMD.exe" + info.Arguments <- args) System.TimeSpan.MaxValue + + // Exit codes from https://support.microsoft.com/en-us/kb/954404 + let exitCodeWithMessage = + match exitcode with + | 0 -> (exitcode, "No files were copied. No failure was encountered. No files were mismatched. The files already exist in the destination directory; therefore, the copy operation was skipped.") + | 1 -> (exitcode, "All files were copied successfully.") + | 2 -> (exitcode, "There are some additional files in the destination directory that are not present in the source directory. No files were copied.") + | 3 -> (exitcode, "Some files were copied. Additional files were present. No failure was encountered.") + | 4 -> (exitcode, "Some Mismatched files or directories were detected. Examine the output log. Housekeeping might be required.") + | 5 -> (exitcode, "Some files were copied. Some files were mismatched. No failure was encountered.") + | 6 -> (exitcode, "Additional files and mismatched files exist. No files were copied and no failures were encountered. This means that the files already exist in the destination directory. ") + | 7 -> (exitcode, "Files were copied, a file mismatch was present, and additional files were present.") + | 8 -> (exitcode, "Several files did not copy.") + | _ -> (exitcode, "UNKNOWN ERROR") + + match exitCodeWithMessage with + | (exitcode, message) when exitcode < 2 -> tracefn "Succeeded in RoboCopy From: %s To: %s \n%s\n" source destination message |> ignore + | (exitcode, message) when exitcode < 8 -> traceImportant <| sprintf "Important notice in RoboCopy From: %s To: %s \n%s\n" source destination message |> ignore + | (_, _) -> failwithf "Error during RoboCopy From: %s To: %s" source destination + +/// Executes a RoboCopy command +/// ## Parameters +/// - `source` - The source directory +/// - `destination` - The target directory +let RoboCopy (source:string) (destination:string) = + roboCopyWithOptions source destination { Mirror = false } + +/// Executes a RoboCopy mirror command (potentially destructive) +/// ## Parameters +/// - `source` - The source directory +/// - `destination` - The target directory +let RoboCopyMirror (source:string) (destination:string) = + roboCopyWithOptions source destination { Mirror = true }