// Copyright (C) 2024 Umorpha Systems // SPDX-License-Identifier: AGPL-3.0-or-later package gitcache import ( "fmt" "regexp" "strings" ) func URL2NS(url string) string { // > Clients MUST strip a trailing `/`, if present, from the // > user supplied `$GIT_URL` string // -- gitprotocol-http(5) url = strings.TrimRight(url, "/") var id strings.Builder id.Grow(len(url)) for _, r := range url { switch { case r == '!', // our own escape // see: git-check-ref-format(1) r <= ' ', r == '\x7F', // never: ASCII control characters r == '~', r == '^', r == ':', // never: gitrevision meaning r == '?', r == '*', r == '[', // never: refspec pattern r == '\\', // never: backslash r == '.', r == '@', r == '/': // sometimes: special rules fmt.Fprintf(&id, "!%02x", r) default: id.WriteRune(r) } } return id.String() } var reEsc = regexp.MustCompile("![0-9a-f]{2}") func hex2int(h byte) byte { switch { case '0' <= h && h <= '9': return h - '0' case 'a' <= h && h <= 'f': return h - 'a' default: panic("should not happen") } } func NS2URL(id string) string { return reEsc.ReplaceAllStringFunc(id, func(esc string) string { r := rune(hex2int(esc[1]))<<4 | rune(hex2int(esc[2])) return string([]rune{r}) }) }