From ff6b9198628c064cdbc970310f560ff66c85a655bed01e93e41e327e8da7e527 Mon Sep 17 00:00:00 2001 From: Sergey Matveev Date: Mon, 14 Aug 2023 18:07:43 +0300 Subject: [PATCH] Initial commit --- README | 32 ++++++++++++++++++++++++++++++++ USAGE | 23 +++++++++++++++++++++++ go.mod | 5 +++++ go.sum | 4 ++++ main.go | 26 ++++++++++++++++++++++++++ mk-goget | 24 ++++++++++++++++++++++++ mk-list | 11 +++++++++++ mk-mod | 32 ++++++++++++++++++++++++++++++++ 8 files changed, 157 insertions(+) create mode 100644 README create mode 100644 USAGE create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go create mode 100755 mk-goget create mode 100755 mk-list create mode 100755 mk-mod diff --git a/README b/README new file mode 100644 index 0000000..622ec91 --- /dev/null +++ b/README @@ -0,0 +1,32 @@ +prepro -- prepare GOPROXY and go-import friendly website + +Go modules (https://go.dev/ref/mod), that are not located on hard-coded +well-known hosting platforms like GitHub, are discovered by go-get using +the go-import-protocol: it requests special URL, based on module's name, +to get HTML with tag. That tag will redirect +go-get further either to VCS, or to GOPROXY-capable URL. + +If VCS is in use, then go-get will invoke external utilities to checkout +the code from VCS. After that, it will create ZIP-archive with the +snapshot of the code and store it locally in cache directory. + +GOPROXY protocol can be treated just like a HTTP-transport to that cache +directory. Only several prepared static files per each module's version +is enough. + +* VCS solution is usually quicker to setup, because development VCS + repositories are publicly available in most cases too +* VCS requires corresponding external tools to be installed. Hardly + either Fossil or GNU Bazaar are often installed on many systems +* VCS checkout requires more disk space: for the VCS itself and for the + cached module's archive +* VCS is slower to check and download in general, because it requires + several round-trips during the handshake between server and client +* GOPROXY is easier to scale on multiple hosts, because you have to + replicate only several static files + +Another advantage of GOPROXY is actually the reason why "prepro" was +born: current go-get can not handle SHA256-driven Git repositories. It +git-init-s empty repository first and then tries to git-fetch it, that +won't work if git-init was not aware of SHA256-based format. GOPROXY +gives easy ability to make that module's repository publicly fetchable. diff --git a/USAGE b/USAGE new file mode 100644 index 0000000..ea0d790 --- /dev/null +++ b/USAGE @@ -0,0 +1,23 @@ +mk-mod utility creates GOPROXY-compatible version of the module in the +current directory: + mk-mod VCS-URL VCS-PATH MODULE-NAME VERSION. +Only Git VCS is supported. Git tag's name must be equal to VERSION. + +mk-list utility collects all known versions in current GOPROXY directory +and creates corresponding "list" files. + +mk-goget creates go-import-compatible static files: + mk-goget VCS-WEB-URL MODULE-NAME. + +For example: + mkdir proxy + cd proxy + mk-mod https://git.cypherpunks.ru/balloon.git ~w/balloon go.cypherpunks.ru/balloon v1.1.1 + mk-mod https://git.cypherpunks.ru/balloon.git ~w/balloon go.cypherpunks.ru/balloon/v2 v2.0.0 + mk-list + cd .. + + mkdir goget + cd goget + mk-goget "http://www.git.cypherpunks.ru/?p=balloon.git" go.cypherpunks.ru/balloon + mk-goget "http://www.git.cypherpunks.ru/?p=balloon.git" go.cypherpunks.ru/balloon/v2 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..5e62cbd --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module go.cypherpunks.ru/prepro + +go 1.21.0 + +require golang.org/x/mod v0.12.0 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..6a42504 --- /dev/null +++ b/go.sum @@ -0,0 +1,4 @@ +golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= +golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= +golang.org/x/tools v0.1.12 h1:VveCTK38A2rkS8ZqFY25HIDFscX5X9OoEhJd3quQmXU= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/main.go b/main.go new file mode 100644 index 0000000..2a0524b --- /dev/null +++ b/main.go @@ -0,0 +1,26 @@ +package main + +import ( + "flag" + "log" + "os" + + "golang.org/x/mod/module" + "golang.org/x/mod/zip" +) + +func main() { + modName := flag.String("mod", "", "Module name") + version := flag.String("version", "", "Version") + root := flag.String("vcs", "", "Path to VCS root") + sub := flag.String("sub", "", "Optional subdirectory path") + flag.Parse() + err := zip.CreateFromVCS( + os.Stdout, + module.Version{Path: *modName, Version: *version}, + *root, *version, *sub, + ) + if err != nil { + log.Fatal(err) + } +} diff --git a/mk-goget b/mk-goget new file mode 100755 index 0000000..850103e --- /dev/null +++ b/mk-goget @@ -0,0 +1,24 @@ +#!/usr/bin/env zsh + +set -e + +vcsurl=$1 +modname=$2 + +cols=(${(s#/#)modname}) +[[ ${cols[-1]} =~ v[0-9]+ ]] || cols=($cols v1) +moddir=${(j:/:)cols[1,-2]} +v=${cols[-1]} +[[ -s $moddir/$v ]] && exit +mkdir -p $moddir +cat > $moddir/$v < + + + + + +$modname + + +EOF diff --git a/mk-list b/mk-list new file mode 100755 index 0000000..67cbc44 --- /dev/null +++ b/mk-list @@ -0,0 +1,11 @@ +#!/usr/bin/env zsh + +set -e +setopt EXTENDED_GLOB +for d (**/*(/)) { + list=() + for f ($d/*.info(onN)) list=($list $f:t:r) + [[ ${#list} != 0 ]] || continue + print ${(F)list} > $d/list + touch -r $d/${list[-1]}.info $d/list +} diff --git a/mk-mod b/mk-mod new file mode 100755 index 0000000..ba13815 --- /dev/null +++ b/mk-mod @@ -0,0 +1,32 @@ +#!/usr/bin/env zsh + +set -e + +vcsurl=$1 +vcspath=$2 +modname=$3 +version=$4 + +dst=$modname/@v +mkdir -p $dst +cd $dst +[[ -s $version.zip ]] && exit + +prepro=$0:h:a/prepro +zmodload -F zsh/datetime b:strftime +git -C $vcspath cat-file -p $version | while read line ; do + [[ $line =~ ^object ]] && hsh=${${=line}[-1]} + [[ $line =~ ^tagger ]] && { + strftime -s sec -r "%s %z" "${${=line}[-2,-1]}" + break + } +done +[[ -n $hsh ]] +[[ -n $sec ]] +strftime -s when %Y-%m-%dT%H:%M:%SZ $sec + +$prepro -vcs $vcspath -mod $modname -version $version > $version.zip +unzip -p $version.zip ${modname}@${version}/go.mod > $version.mod +printf '{"Version":"%s","Time":"%s","Origin":{"VCS":"git","URL":"%s","Ref":"refs/tags/%s","Hash":"%s"}}' \ + $version $when $vcsurl $version $hsh > $version.info +touch -d $when $version.info $version.mod $version.zip -- 2.48.1