130 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
			
		
		
	
	
			130 lines
		
	
	
		
			2.7 KiB
		
	
	
	
		
			Go
		
	
	
| // registry-api-descriptor-template uses the APIDescriptor defined in the
 | |
| // api/v2 package to execute templates passed to the command line.
 | |
| //
 | |
| // For example, to generate a new API specification, one would execute the
 | |
| // following command from the repo root:
 | |
| //
 | |
| //	$ registry-api-descriptor-template docs/spec/api.md.tmpl > docs/spec/api.md
 | |
| //
 | |
| // The templates are passed in the api/v2.APIDescriptor object. Please see the
 | |
| // package documentation for fields available on that object. The template
 | |
| // syntax is from Go's standard library text/template package. For information
 | |
| // on Go's template syntax, please see golang.org/pkg/text/template.
 | |
| package main
 | |
| 
 | |
| import (
 | |
| 	"log"
 | |
| 	"net/http"
 | |
| 	"os"
 | |
| 	"path/filepath"
 | |
| 	"regexp"
 | |
| 	"text/template"
 | |
| 
 | |
| 	"github.com/distribution/distribution/v3/registry/api/errcode"
 | |
| 	v2 "github.com/distribution/distribution/v3/registry/api/v2"
 | |
| )
 | |
| 
 | |
| var spaceRegex = regexp.MustCompile(`\n\s*`)
 | |
| 
 | |
| func main() {
 | |
| 	if len(os.Args) != 2 {
 | |
| 		log.Fatalln("please specify a template to execute.")
 | |
| 	}
 | |
| 
 | |
| 	path := os.Args[1]
 | |
| 	filename := filepath.Base(path)
 | |
| 
 | |
| 	funcMap := template.FuncMap{
 | |
| 		"removenewlines": func(s string) string {
 | |
| 			return spaceRegex.ReplaceAllString(s, " ")
 | |
| 		},
 | |
| 		"statustext":    http.StatusText,
 | |
| 		"prettygorilla": prettyGorillaMuxPath,
 | |
| 	}
 | |
| 
 | |
| 	tmpl := template.Must(template.New(filename).Funcs(funcMap).ParseFiles(path))
 | |
| 
 | |
| 	data := struct {
 | |
| 		RouteDescriptors []v2.RouteDescriptor
 | |
| 		ErrorDescriptors []errcode.ErrorDescriptor
 | |
| 	}{
 | |
| 		RouteDescriptors: v2.APIDescriptor.RouteDescriptors,
 | |
| 		ErrorDescriptors: append(errcode.GetErrorCodeGroup("registry.api.v2"),
 | |
| 			// The following are part of the specification but provided by errcode default.
 | |
| 			errcode.ErrorCodeUnauthorized.Descriptor(),
 | |
| 			errcode.ErrorCodeDenied.Descriptor(),
 | |
| 			errcode.ErrorCodeUnsupported.Descriptor()),
 | |
| 	}
 | |
| 
 | |
| 	if err := tmpl.Execute(os.Stdout, data); err != nil {
 | |
| 		log.Fatalln(err)
 | |
| 	}
 | |
| }
 | |
| 
 | |
| // prettyGorillaMuxPath removes the regular expressions from a gorilla/mux
 | |
| // route string, making it suitable for documentation.
 | |
| func prettyGorillaMuxPath(s string) string {
 | |
| 	// Stateful parser that removes regular expressions from gorilla
 | |
| 	// routes. It correctly handles balanced bracket pairs.
 | |
| 
 | |
| 	var output string
 | |
| 	var label string
 | |
| 	var level int
 | |
| 
 | |
| start:
 | |
| 	if s[0] == '{' {
 | |
| 		s = s[1:]
 | |
| 		level++
 | |
| 		goto capture
 | |
| 	}
 | |
| 
 | |
| 	output += string(s[0])
 | |
| 	s = s[1:]
 | |
| 
 | |
| 	goto end
 | |
| capture:
 | |
| 	switch s[0] {
 | |
| 	case '{':
 | |
| 		level++
 | |
| 	case '}':
 | |
| 		level--
 | |
| 
 | |
| 		if level == 0 {
 | |
| 			s = s[1:]
 | |
| 			goto label
 | |
| 		}
 | |
| 	case ':':
 | |
| 		s = s[1:]
 | |
| 		goto skip
 | |
| 	default:
 | |
| 		label += string(s[0])
 | |
| 	}
 | |
| 	s = s[1:]
 | |
| 	goto capture
 | |
| skip:
 | |
| 	switch s[0] {
 | |
| 	case '{':
 | |
| 		level++
 | |
| 	case '}':
 | |
| 		level--
 | |
| 	}
 | |
| 	s = s[1:]
 | |
| 
 | |
| 	if level == 0 {
 | |
| 		goto label
 | |
| 	}
 | |
| 
 | |
| 	goto skip
 | |
| label:
 | |
| 	if label != "" {
 | |
| 		output += "<" + label + ">"
 | |
| 		label = ""
 | |
| 	}
 | |
| end:
 | |
| 	if s != "" {
 | |
| 		goto start
 | |
| 	}
 | |
| 
 | |
| 	return output
 | |
| }
 |