Download
86 lines 2.1 KiBGoModified 2026-10-28 raw
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
package admin

import (
	"fmt"
	"io"
	"os"
	"path/filepath"
	"strings"

	"code.bruce-hill.com/repo-renderer/internal/config"
	"code.bruce-hill.com/repo-renderer/internal/gitx"
	"code.bruce-hill.com/repo-renderer/internal/mirror"
)

// repos are the names of the repositories in git_dir, sorted.
func repos(cfg *config.Config) ([]string, error) {
	ents, err := os.ReadDir(cfg.GitDir)
	if err != nil {
		return nil, err
	}
	var names []string
	for _, e := range ents {
		if name, ok := strings.CutSuffix(e.Name(), ".git"); ok && e.IsDir() && config.ValidRepoName(name) {
			names = append(names, name)
		}
	}
	return names, nil
}

// List writes the index's layout: each section, with its repositories,
// sorted, their tags and their mirrors (the hosts, marked if the last
// push there failed), and then those in no section.
func List(w io.Writer, cfg *config.Config) error {
	names, err := repos(cfg)
	if err != nil {
		return err
	}
	in := map[string][]string{}
	for _, name := range names {
		dir := filepath.Join(cfg.GitDir, name+".git")
		r := gitx.Repo{Dir: dir}
		section, tags, err := r.Placement()
		if err != nil {
			return err
		}
		mirrors, err := r.Mirrors()
		if err != nil {
			return err
		}
		row := name
		if len(tags) > 0 {
			row += " [" + strings.Join(tags, ", ") + "]"
		}
		if len(mirrors) > 0 {
			failures := mirror.Failures(dir)
			var to []string
			for _, m := range mirrors {
				label := m
				if host, port := mirror.Host(m); host != "" {
					label = mirror.Entry(host, port)
				}
				if mirror.Failed(failures, m) {
					label += " (last push failed)"
				}
				to = append(to, label)
			}
			row += " -> " + strings.Join(to, ", ")
		}
		if section != "" && cfg.SectionIndex(section) < 0 {
			row += " (its section, " + section + ", isn't in the config)"
			section = ""
		}
		in[section] = append(in[section], row)
	}
	for _, s := range cfg.Sections {
		fmt.Fprintf(w, "%s (%s):\n", s.Title, s.Name)
		for _, row := range in[s.Name] {
			fmt.Fprintf(w, "    %s\n", row)
		}
	}
	fmt.Fprintln(w, "In no section, so private:")
	for _, row := range in[""] {
		fmt.Fprintf(w, "    %s\n", row)
	}
	return nil
}