anchor.diff:  open HttpListenerHelper
   open Fake.SshRsaModule
   
  +/// Authentication token received from a successful login
   type AuthToken = 
       | AuthToken of Guid
   
  -let mutable private authToken : Guid option = None
  +let mutable private authToken : AuthToken option = None
   
   /// A http response type.
   type Response = 
  
positive.code:     { Name : string
        Version : string }
  
  
  let buildExceptionString (r:Response) =
      let msgs = 
          r.Messages
          |> Seq.map(fun m -> sprintf "  %s %s" (m.Timestamp.ToString("yyyy-MM-dd hh::mm:ss.fff")) m.Message)
          |> fun arr -> String.Join("\r\n", arr)
      sprintf "%O\r\n\r\nDeploy messages\r\n{\r\n%s\r\n}\r\n" r.Exception  msgs
  
  
  /// Authenticate against the given server with the given userId and private key
  let authenticate server userId serverpathToPrivateKeyFile passwordForPrivateKey = 
      let privateKey = loadPrivateKey serverpathToPrivateKeyFile passwordForPrivateKey
      let challenge = REST.ExecuteGetCommand null null (server + "/login/" + userId)
      let signature = challenge |> Convert.FromBase64String |> privateKey.Sign |> Convert.ToBase64String 
  
      let postData = sprintf "challenge=%s&signature=%s" (HttpUtility.UrlEncode challenge) (HttpUtility.UrlEncode signature)
      let response = REST.ExecutePost (server + "/login") "x" "x" postData
      authToken <- response.Trim([|'"'|]) |> Guid.Parse |> Some
      authToken
  
  /// Returns all releases of the given app from the given server.
  let getReleasesFor server appname status = 
      if String.IsNullOrEmpty(appname) then server + "/deployments?status=" + status
      else server + "/deployments/" + appname + "?status=" + status
      |> get (Json.deserialize<DeploymentResponse>)
  
  /// Performs a rollback of the given app on the server.
  let rollbackTo server appname version = 
      put (server + "/deployments/" + appname + "?version=" + version) [||] |> wrapFailure
  
  /// Returns all active releases from the given server.
  let getAllActiveReleases server = getReleasesFor server null "active" |> wrapFailure
  
negative.code:     with exn -> Choice2Of2 exn
  
  /// Posts the given file to the given URL.
  let private post url file timeout = uploadFile "POST" url file timeout >> processResponse
  
  /// Puts the given body to the given URL.
  let private put url timeout = uploadData "PUT" url timeout >> processResponse
  
  type DeployStatus = 
      | Active
  