Skip to content

Instantly share code, notes, and snippets.

@xv
Last active June 29, 2021 02:09
Show Gist options
  • Save xv/cba9b18ff142420c2040b632f8960258 to your computer and use it in GitHub Desktop.
Save xv/cba9b18ff142420c2040b632f8960258 to your computer and use it in GitHub Desktop.
F# snippet to fetch and return the hash identifier of last commit in the specified repository using regex pattern matching.
open System.IO
open System.Net
open System.Text.RegularExpressions
open System
/// <summary>
/// Fetches the Id (SHA1 hash) of the most recent GitHub Git commit in the
/// specified repository.
/// </summary>
///
/// <param name="username">The target GitHub username.</param>
/// <param name="repoName">The target repo.</param>
///
/// <param name="shortHash">
/// Specifies if the function should only return the first 7 characters of the
/// hash value rather than the full 41 characters.
/// </param>
///
/// <returns>
/// The most recent commit Id.
/// </returns>
///
/// <remarks>
/// GitHub has a limit of 50 requests/hour for unauthenticated users.
/// See: https://developer.github.com/v3/#rate-limiting
/// </remarks>
let getLastCommit (username: string, repoName: string, shortHash: bool) =
let mutable ret = String.Empty
try
// GitHub requires TLS 1.2 as of Feb 01 2018
// .NET Framework 4.5 or up is required to set this protocol
ServicePointManager.SecurityProtocol <- SecurityProtocolType.Tls12
let url = sprintf "https://api.github.com/repos/%s/%s/git/refs/heads/master"
username repoName
let req = WebRequest.Create url :?> HttpWebRequest
req.Method <- "GET"
req.ContentType <- "application/json; charset=utf-8"
req.UserAgent <- "Mozilla/5.0 (Windows NT 10.0; Win64; x64) \
AppleWebKit/537.36 (KHTML, like Gecko) \
Chrome/60.0.3112.113 Safari/537.36"
use res = req.GetResponse() :?> HttpWebResponse
if (res.StatusCode = HttpStatusCode.OK) then
use reader = new StreamReader(res.GetResponseStream())
let output = reader.ReadToEnd()
let pattern = "\"sha\"\\s*:\\s*\"((?=[ -~])[^\"]+)\""
let match' = Regex.Match(output, pattern)
let commitHash =
if match'.Success then
let matchVal = match'.Groups.[1].Value
if shortHash then matchVal.[0..6] else matchVal
else
"Could not get commit ID. Regex matching wasn't successful."
ret <- commitHash
with | :? WebException as ex ->
if ex.Status = WebExceptionStatus.ProtocolError && ex.Response <> null then
// Custom messages for common API exceptions
let commonEx =
use exRes = ex.Response :?> HttpWebResponse
match exRes.StatusCode with
| HttpStatusCode.NotFound -> "No commits or repository not found."
| HttpStatusCode.Forbidden -> "Access to information is forbidden."
| _ -> ex.Message
ret <- commonEx
else
ret <- ex.Message
ret
[<EntryPoint>]
let main argv =
let user, repo = "microsoft", "dotnet"
let commitHash = getLastCommit(user, repo, false)
let result = sprintf "Last commit in the repo '%s/%s': %s" user repo commitHash
Console.WriteLine(result)
Console.ReadKey() |> ignore
0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment