Pudu programming language
Menu
Package

@chrismichaelps / pudu-lang-docgen

Documentation publishing for Pudu: articles, API references, navigation, search, and static websites

0.1.0Apache-2.01

InstallClose

Repository.pudu

Pudu79 lines3.6 KB

GitHub ↗
1/** @Docgen.Repository.Module — source repository identity and file history from their raw forms */2module PuduLangDocgen.Repository34import Std.Map as Map56/// Environment variables naming a repository address or a branch, in the order they are7/// trusted: explicit overrides first, then continuous integration services.8const BRANCH_VARIABLES: Array[Str] = [9  "DOCGEN_SOURCE_BRANCH_NAME", "GITHUB_HEAD_REF", "GITHUB_REF_NAME", "CI_COMMIT_REF_NAME", "BUILD_SOURCEBRANCHNAME",10  "APPVEYOR_REPO_BRANCH", "GIT_BRANCH", "TEAMCITY_BUILD_BRANCH"11]1213/// A remote address as a browsable HTTPS address without credentials or `.git`.14/// `git@host:owner/repo.git` and `ssh://git@host/owner/repo` both become `https://host/owner/repo`.15export fn normalize(remote: Str) -> Str {16  var address = remote.trim()17  if address.isEmpty() { return "" }18  if address.startsWith("git@") && address.contains(":") {19    let rest = address.drop(4)20    let colon = rest.indexOf(":")21    address = "https://" + rest.take(colon) + "/" + rest.drop(colon + 1)22  } else if address.startsWith("ssh://") {23    let rest = address.drop(6)24    let hostStart = if rest.contains("@") { rest.indexOf("@") + 1 } else { 0 }25    address = "https://" + rest.drop(hostStart)26  } else if address.startsWith("http://") || address.startsWith("https://") {27    let scheme = if address.startsWith("https://") { "https://" } else { "http://" }28    let rest = address.drop(scheme.length())29    let slash = rest.indexOf("/")30    let authority = if slash < 0 { rest } else { rest.take(slash) }31    if authority.contains("@") {32      let at = authority.split("@")33      address = scheme + at[at.length() - 1] + rest.drop(authority.length())34    }35  } else { return "" }36  if address.endsWith("/") { address = address.take(address.length() - 1) }37  if address.endsWith(".git") { address = address.take(address.length() - 4) }38  address39}4041/// The repository address and branch environment variables name, when they name them.42/// `DOCGEN_SOURCE_REPOSITORY_URL` and `DOCGEN_SOURCE_BRANCH_NAME` override every service.43export fn fromEnvironment(variables: &Array[(Str, Str)]) -> (Str, Str) {44  let found = mapOf(*variables)45  var repo = Map.getOr(&found, "DOCGEN_SOURCE_REPOSITORY_URL", "")46  if repo.isEmpty() {47    let github = Map.getOr(&found, "GITHUB_REPOSITORY", "")48    if !github.isEmpty() { repo = Map.getOr(&found, "GITHUB_SERVER_URL", "https://github.com") + "/" + github }49  }50  for name in ["CI_PROJECT_URL", "BUILD_REPOSITORY_URI", "GIT_URL"] {51    if repo.isEmpty() { repo = Map.getOr(&found, name, "") }52  }53  if repo.isEmpty() {54    let appveyor = Map.getOr(&found, "APPVEYOR_REPO_NAME", "")55    let provider = Map.getOr(&found, "APPVEYOR_REPO_PROVIDER", "github")56    if !appveyor.isEmpty() { repo = "https://" + (if provider == "gitLab" { "gitlab.com" } else if provider == "bitBucket" { "bitbucket.org" } else { "github.com" }) + "/" + appveyor }57  }58  var branch = ""59  for name in BRANCH_VARIABLES {60    if branch.isEmpty() { branch = Map.getOr(&found, name, "") }61  }62  if branch.startsWith("origin/") { branch = branch.drop(7) }63  if branch.startsWith("refs/heads/") { branch = branch.drop(11) }64  (normalize(repo), branch)65}6667/// The latest change date of each file from log text that lists `@YYYY-MM-DD` lines followed68/// by the files each change touched, newest first.69export fn history(log: Str) -> Map[Str, Str] {70  var found: Map[Str, Str] = mapOf([])71  var date = ""72  for line in log.split("\n") {73    let held = line.trim()74    if held.startsWith("@") { date = held.drop(1) }75      else if !held.isEmpty() && !date.isEmpty() && !Map.containsKey(&found, held) { found = Map.insert(&found, held, date) }76  }77  found78}79