Skip to content

Instantly share code, notes, and snippets.

@landonf
Last active August 29, 2015 13:56
Show Gist options
  • Save landonf/9163945 to your computer and use it in GitHub Desktop.
Save landonf/9163945 to your computer and use it in GitHub Desktop.
Example of monadic error handling posted to Twitter
/**
* Fetch credentials from git's credential interface.
*
* @param scheme The URL scheme (eg, http, https).
* @param host The destination host.
* @param realm The authentication realm (eg, HTTP Basic realm).
* @param user The username if known; otherwise, the git credential interface will attempt to fill in this information.
* @return Returns credentials, or a string explaining why credentials could not be fetched.
*/
private def getGitCredentials (scheme: String, host: String, realm: String, user: Option[String]): Result[KeychainError, Credentials] = {
import scala.sys.process._
for (
/* Fetch the configured git credential helper */
helper <- executeCommand(Seq("git", "config", "credential.helper"));
/* Generate the request we'll submit to the helper */
request <- new ByteArrayInputStream(Seq(
Some(s"protocol=$scheme"),
Some(s"host=$host"),
Some(s"realm=$realm"),
user.map(s => s"username=$s")
).flatten.mkString("\n").getBytes(StandardCharsets.UTF_8)).success;
/* Execute the git-credential-$helper and parse the results */
lines <- executeCommand(Seq(s"git-credential-$helper", "fill") #< request);
parsed <- KeychainGitResultParser.parseInput(lines);
/* Extract the credentials */
username <- parsed.get("username").toSuccess(AccountNotFound("No username returned in git credential output"));
password <- parsed.get("password").toSuccess(AccountNotFound("No password returned in git credential output"))
) yield Credentials(realm, host, username, password)
}
private def getGitCredentials (scheme: String, host: String, realm: String, user: Option[String]): Result[KeychainError, Credentials] = {
import scala.sys.process._
/* Fetch the configured git credential helper */
executeCommand(Seq("git", "config", "credential.helper")).flatMap { helper =>
/* Generate the request we'll submit to the helper */
val request = new ByteArrayInputStream(Seq(
Some(s"protocol=$scheme"),
Some(s"host=$host"),
Some(s"realm=$realm"),
user.map(s => s"username=$s")
).flatten.mkString("\n").getBytes(StandardCharsets.UTF_8))
/* Execute the git-credential-$helper and read the output */
executeCommand(Seq(s"git-credential-$helper", "fill") #< request).flatMap { lines =>
KeychainGitResultParser.parseInput(lines).flatMap { parsed =>
/* Extract the credentials */
parsed.get("username").toSuccess(AccountNotFound("No username returned in git credential output")).flatMap { username =>
parsed.get("password").toSuccess(AccountNotFound("No password returned in git credential output")).map { password
Credentials(realm, host, username, password)
}
}
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment