Skip to content

Commit b3482cc

Browse files
committed
internal/modindex/cmd: Command for maintaining module cache indexes
Presently the command will create or update the index of the module cache, or clean out obsolete indexes. An index is obsolete if it is both more that an hour old, and not a current index pointed to by some index-name file. Change-Id: Ie3a79587e0e230ae7ab0b7d854c97003ace783ff Reviewed-on: https://go-review.googlesource.com/c/tools/+/616838 LUCI-TryBot-Result: Go LUCI <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 454be60 commit b3482cc

File tree

1 file changed

+148
-0
lines changed
  • internal/modindex/gomodindex

1 file changed

+148
-0
lines changed

internal/modindex/gomodindex/cmd.go

Lines changed: 148 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,148 @@
1+
// Copyright 2024 The Go Authors. All rights reserved.
2+
// Use of this source code is governed by a BSD-style
3+
// license that can be found in the LICENSE file.
4+
5+
// A command for building and maintaing the module cache
6+
// a.out <flags> <command> <args>
7+
// The commands are 'create' which builds a new index,
8+
// 'update', which attempts to update an existing index,
9+
// 'query', which looks up things in the index.
10+
// 'clean', which remove obsolete index files.
11+
// If the command is invoked with no arguments, it defaults to 'create'.
12+
package main
13+
14+
import (
15+
"bytes"
16+
"flag"
17+
"fmt"
18+
"log"
19+
"os"
20+
"os/exec"
21+
"path/filepath"
22+
"strings"
23+
"time"
24+
25+
"golang.org/x/tools/internal/modindex"
26+
)
27+
28+
var verbose = flag.Int("v", 0, "how much information to print")
29+
30+
type cmd struct {
31+
name string
32+
f func(string)
33+
doc string
34+
}
35+
36+
var cmds = []cmd{
37+
{"create", index, "create a clean index of GOMODCACHE"},
38+
{"update", update, "if there is an existing index of GOMODCACHE, update it. Otherise create one."},
39+
{"clean", clean, "removed unreferenced indexes more than an hour old"},
40+
{"query", query, "not yet implemented"},
41+
}
42+
43+
func goEnv(s string) string {
44+
out, err := exec.Command("go", "env", s).Output()
45+
if err != nil {
46+
return ""
47+
}
48+
out = bytes.TrimSpace(out)
49+
return string(out)
50+
}
51+
52+
func main() {
53+
flag.Parse()
54+
log.SetFlags(log.Lshortfile)
55+
cachedir := goEnv("GOMODCACHE")
56+
if cachedir == "" {
57+
log.Fatal("can't find GOMODCACHE")
58+
}
59+
if flag.NArg() == 0 {
60+
index(cachedir)
61+
return
62+
}
63+
for _, c := range cmds {
64+
if flag.Arg(0) == c.name {
65+
c.f(cachedir)
66+
return
67+
}
68+
}
69+
flag.Usage()
70+
}
71+
72+
func init() {
73+
var sb strings.Builder
74+
fmt.Fprintf(&sb, "usage:\n")
75+
for _, c := range cmds {
76+
fmt.Fprintf(&sb, "'%s': %s\n", c.name, c.doc)
77+
}
78+
msg := sb.String()
79+
flag.Usage = func() {
80+
fmt.Fprint(os.Stderr, msg)
81+
}
82+
}
83+
84+
func index(dir string) {
85+
modindex.IndexModCache(dir, true)
86+
}
87+
88+
func update(dir string) {
89+
modindex.IndexModCache(dir, false)
90+
}
91+
92+
func query(dir string) {
93+
panic("implement")
94+
}
95+
func clean(_ string) {
96+
des, err := modindex.IndexDir()
97+
if err != nil {
98+
log.Fatal(err)
99+
}
100+
// look at the files starting with 'index'
101+
// the current ones of each version are pointed to by
102+
// index-name-%d files. Any others more than an hour old
103+
// are deleted.
104+
dis, err := os.ReadDir(des)
105+
if err != nil {
106+
log.Fatal(err)
107+
}
108+
cutoff := time.Now().Add(-time.Hour)
109+
var inames []string // older files named index*
110+
curnames := make(map[string]bool) // current versions of index (different CurrentVersion)
111+
for _, de := range dis {
112+
if !strings.HasPrefix(de.Name(), "index") {
113+
continue
114+
}
115+
if strings.HasPrefix(de.Name(), "index-name-") {
116+
buf, err := os.ReadFile(filepath.Join(des, de.Name()))
117+
if err != nil {
118+
log.Print(err)
119+
continue
120+
}
121+
curnames[string(buf)] = true
122+
if *verbose > 1 {
123+
log.Printf("latest index is %s", string(buf))
124+
}
125+
}
126+
info, err := de.Info()
127+
if err != nil {
128+
log.Print(err)
129+
continue
130+
}
131+
if info.ModTime().Before(cutoff) && !strings.HasPrefix(de.Name(), "index-name-") {
132+
// add to the list of files to be removed. index-name-%d files are never removed
133+
inames = append(inames, de.Name())
134+
if *verbose > 0 {
135+
log.Printf("%s:%s", de.Name(), cutoff.Sub(info.ModTime()))
136+
}
137+
}
138+
}
139+
for _, nm := range inames {
140+
if curnames[nm] {
141+
continue
142+
}
143+
err := os.Remove(filepath.Join(des, nm))
144+
if err != nil && *verbose > 0 {
145+
log.Printf("%s not removed (%v)", nm, err)
146+
}
147+
}
148+
}

0 commit comments

Comments
 (0)