Skip to content
quarry Artifact [4c04a4ee01]
Login

Artifact [4c04a4ee01]

Artifact 4c04a4ee0142664fe6c761f7276f827091422152a62e70a2f18a9aacfe01c786:


// quarry is a multi-repository forge for zit. See docs/rfcs/.
package main

import (
	"encoding/json"
	"flag"
	"fmt"
	"net/http"
	"os"

	"craftdesign.group/quarry/internal/api"
	"craftdesign.group/quarry/internal/ops"
	"craftdesign.group/quarry/internal/web"
)

// version is stamped at build time; every page footer and the API report it
// (0001 Principle 1).
var version = "0.0.0-dev"

func main() {
	if len(os.Args) > 1 {
		switch os.Args[1] {
		case "version":
			fmt.Println("quarry", version)
			return
		case "spec":
			if err := printSpec(os.Stdout); err != nil {
				fmt.Fprintln(os.Stderr, "quarry:", err)
				os.Exit(1)
			}
			return
		case "serve":
			if err := serveCmd(os.Args[2:]); err != nil {
				fmt.Fprintln(os.Stderr, "quarry:", err)
				os.Exit(1)
			}
			return
		}
	}
	fmt.Fprintln(os.Stderr, "usage: quarry version|spec|serve")
	os.Exit(2)
}

// serveCmd runs the HTTP surface: the op-generated API plus the HTML
// pages, both consumers of one registry. Store ingest arrives with
// phase 1; until then serve answers from the ops alone.
func serveCmd(args []string) error {
	fs := flag.NewFlagSet("serve", flag.ContinueOnError)
	addr := fs.String("addr", "127.0.0.1:8080", "listen address")
	if err := fs.Parse(args); err != nil {
		return err
	}
	mux, err := buildHandler()
	if err != nil {
		return err
	}
	fmt.Println("quarry", version, "listening on", *addr)
	return http.ListenAndServe(*addr, mux)
}

// buildHandler wires the two registry consumers onto one mux.
func buildHandler() (http.Handler, error) {
	r := ops.NewRegistry()
	if err := api.RegisterAll(r, version); err != nil {
		return nil, err
	}
	apiRouter, err := api.Router(r, version)
	if err != nil {
		return nil, err
	}
	mux := http.NewServeMux()
	mux.Handle("/api/", apiRouter)
	mux.Handle("/", web.Handler(r))
	return mux, nil
}

// printSpec emits the OpenAPI document generated from the full registry —
// the same registry serve will run, so the spec cannot drift (0001 §9).
func printSpec(w *os.File) error {
	r := ops.NewRegistry()
	if err := api.RegisterAll(r, version); err != nil {
		return err
	}
	spec, err := ops.Spec(r, "quarry", version)
	if err != nil {
		return err
	}
	enc := json.NewEncoder(w)
	enc.SetIndent("", "  ")
	return enc.Encode(spec)
}