/- Copyright (c) 2017 Microsoft Corporation. All rights reserved. Released under Apache 2.0 license as described in the file LICENSE. Authors: Gabriel Ebner, Sebastian Ullrich, Mac Malone -/ import Lake.LeanVersion open System namespace Lake.Git def upstreamBranch := "master" def defaultRevision : Option String → String | none => upstreamBranch | some branch => branch def execGit (args : Array String) (repo : Option FilePath := none) : IO PUnit := do let child ← IO.Process.spawn { cmd := "git", args, cwd := repo, stdout := IO.Process.Stdio.null, stderr := IO.Process.Stdio.null } let exitCode ← child.wait if exitCode != 0 then throw <| IO.userError <| "git exited with code " ++ toString exitCode def captureGit (args : Array String) (repo : Option FilePath := none) : IO String := do let out ← IO.Process.output {cmd := "git", args, cwd := repo} if out.exitCode != 0 then throw <| IO.userError <| "git exited with code " ++ toString out.exitCode return out.stdout def clone (url : String) (dir : FilePath) := execGit #["clone", url, dir.toString] def quietInit (repo : Option FilePath := none) := execGit #["init", "-q"] repo def fetch (repo : Option FilePath := none) := execGit #["fetch"] repo def checkoutBranch (branch : String) (repo : Option FilePath := none) := execGit #["checkout", "-B", branch] repo def checkoutDetach (hash : String) (repo : Option FilePath := none) := execGit #["checkout", "--detach", hash] repo def parseRevision (rev : String) (repo : Option FilePath := none) : IO String := do let rev ← captureGit #["rev-parse", "-q", "--verify", rev] repo rev.trim -- remove newline at end def headRevision (repo : Option FilePath := none) : IO String := parseRevision "HEAD" repo def parseOriginRevision (rev : String) (repo : Option FilePath := none) : IO String := (parseRevision ("origin/" ++ rev) repo) <|> parseRevision rev repo <|> throw (IO.userError s!"cannot find revision {rev} in repository {repo}") def latestOriginRevision (branch : Option String) (repo : Option FilePath := none) : IO String := do execGit #["fetch"] repo parseOriginRevision (defaultRevision branch) repo def revisionExists (rev : String) (repo : Option FilePath := none) : IO Bool := do try discard <| parseRevision (rev ++ "^{commit}") repo true catch _ => false