Skip to content

Commit

Permalink
Add a data structure to manage version information
Browse files Browse the repository at this point in the history
  • Loading branch information
mah0x211 committed Mar 2, 2023
1 parent 8e1828b commit f7bd169
Show file tree
Hide file tree
Showing 9 changed files with 399 additions and 234 deletions.
73 changes: 22 additions & 51 deletions fetch.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,77 +9,57 @@ import (
"regexp"
)

type ParseFunc func(body []byte) List
type ParseFunc func(body []byte) *Versions

var (
ReSemVer = regexp.MustCompile(`(?s)^\d+(?:\.\d+){1,2}`)
ReLuaRocksVer = regexp.MustCompile(`(?si)href="(luarocks-([^"]+?)\.tar\.gz).*?href="(luarocks-[^"]+?\.tar\.gz\.asc)"`)
ReLuaJitVer = regexp.MustCompile(`(?i)([0-9a-f]+?)\s+(LuaJIT-([^\s]+?)\.tar\.gz)`)
ReLuaVer = regexp.MustCompile(`(?si)<tr>\s*<td class="name"><a href="(lua-([^"]+?)\.tar\.gz).+?class="sum">([0-9a-f]+)</td>\s*</tr>`)
)

func isSemVer(ver string) bool {
return ReSemVer.MatchString(ver)
}

func parseLuaRocksVers(body []byte) List {
list := make(List)
func parseLuaRocksVers(body []byte) *Versions {
vers := NewVersions()
for _, m := range ReLuaRocksVer.FindAllSubmatch(body, -1) {
if !bytes.HasPrefix(m[3], m[1]) {
continue
}
name := string(m[1])
ver := string(m[2])
sum := "pgp:" + string(m[3])
if isSemVer(ver) {
list[ver] = &ListItem{
Name: name,
Ver: ver,
Sum: sum,
Ext: ".tar.gz",
}
if !vers.Add(name, ver, sum, ".tar.gz") {
printf("ignore unsupported version: %q", name)
}
}

return list
return vers
}

func parseLuaJitVers(body []byte) List {
list := make(List)
func parseLuaJitVers(body []byte) *Versions {
vers := NewVersions()
for _, m := range ReLuaJitVer.FindAllSubmatch(body, -1) {
sum := "sha256:" + string(m[1])
name := string(m[2])
ver := string(m[3])
if isSemVer(ver) {
list[ver] = &ListItem{
Name: name,
Ver: ver,
Sum: sum,
Ext: ".tar.gz",
}
if !vers.Add(name, ver, sum, ".tar.gz") {
printf("ignore unsupported version: %q", name)
}
}

return list
return vers
}

func parseLuaVers(body []byte) List {
list := make(List)
func parseLuaVers(body []byte) *Versions {
vers := NewVersions()
for _, m := range ReLuaVer.FindAllSubmatch(body, -1) {
name := string(m[1])
ver := string(m[2])
sum := "sha256:" + string(m[3])
if isSemVer(ver) {
list[ver] = &ListItem{
Name: name,
Ver: ver,
Sum: sum,
Ext: ".tar.gz",
}
if !vers.Add(name, ver, sum, ".tar.gz") {
printf("ignore unsupported version: %q", name)
}
}

return list
return vers
}

func cmdFetch() {
Expand Down Expand Up @@ -107,25 +87,16 @@ func cmdFetch() {
eprintf("failed to read body: %v", err)
}

list := target.parse(b)
if err = writeVersionFile(target.cfg.VersionFile, list); err != nil {
vers := target.parse(b)
if err = vers.WriteFile(target.cfg.VersionFile); err != nil {
eprintf("failed to write version file: %v", err)
}

vers := []string{}
maxlen := 0
for ver := range list {
if len(ver) > maxlen {
maxlen = len(ver)
}
vers = append(vers, ver)
}
sortVersions(vers)
items, maxlen := vers.GetList()
format := fmt.Sprintf("%%-%ds %%s", maxlen)

for _, ver := range vers {
url := target.cfg.DownloadURL + filepath.Clean(list[ver].Name)
printf(format, ver, url)
for _, item := range items {
url := target.cfg.DownloadURL + filepath.Clean(item.Name)
printf(format, item.Ver, url)
}

printf("")
Expand Down
12 changes: 6 additions & 6 deletions fetch_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ func Test_parseLuaRocksVers(t *testing.T) {
exp := []string{"luarocks-3.5.0.tar.gz", "luarocks-3.4.0.tar.gz", "luarocks-3.3.1.tar.gz", "luarocks-3.3.0.tar.gz", "luarocks-3.2.1.tar.gz", "luarocks-3.2.0.tar.gz", "luarocks-3.1.3.tar.gz", "luarocks-3.1.2.tar.gz", "luarocks-3.1.1.tar.gz", "luarocks-3.1.0.tar.gz", "luarocks-3.0.4.tar.gz", "luarocks-3.0.3.tar.gz", "luarocks-3.0.2.tar.gz", "luarocks-3.0.1.tar.gz", "luarocks-3.0.1-rc2.tar.gz", "luarocks-3.0.1-rc1.tar.gz", "luarocks-3.0.0.tar.gz", "luarocks-3.0.0-rc2.tar.gz", "luarocks-3.0.0-rc1.tar.gz", "luarocks-3.0.0beta2.tar.gz", "luarocks-3.0.0beta1.tar.gz", "luarocks-2.4.4.tar.gz", "luarocks-2.4.3.tar.gz", "luarocks-2.4.2.tar.gz", "luarocks-2.4.1.tar.gz", "luarocks-2.4.0.tar.gz", "luarocks-2.3.0.tar.gz", "luarocks-2.3.0-rc2.tar.gz", "luarocks-2.3.0-rc1.tar.gz", "luarocks-2.2.3-rc2.tar.gz", "luarocks-2.2.3-rc1.tar.gz", "luarocks-2.2.2.tar.gz", "luarocks-2.2.1.tar.gz", "luarocks-2.2.0.tar.gz", "luarocks-2.2.0beta1.tar.gz", "luarocks-2.1.2.tar.gz", "luarocks-2.1.1.tar.gz", "luarocks-2.1.0.tar.gz", "luarocks-2.1.0-rc3.tar.gz", "luarocks-2.1.0-rc2.tar.gz", "luarocks-2.1.0-rc1.tar.gz", "luarocks-2.0.13.tar.gz", "luarocks-2.0.12.tar.gz", "luarocks-2.0.11.tar.gz", "luarocks-2.0.10.tar.gz", "luarocks-2.0.9.1.tar.gz", "luarocks-2.0.9.tar.gz", "luarocks-2.0.9-rc2.tar.gz", "luarocks-2.0.9-rc1.tar.gz", "luarocks-2.0.8.tar.gz", "luarocks-2.0.8-rc2.tar.gz", "luarocks-2.0.8-rc1.tar.gz", "luarocks-2.0.7.1.tar.gz", "luarocks-2.0.7.tar.gz", "luarocks-2.0.6.tar.gz", "luarocks-2.0.6-rc1.tar.gz", "luarocks-2.0.5.tar.gz", "luarocks-2.0.5-rc1.tar.gz", "luarocks-2.0.4.1.tar.gz", "luarocks-2.0.4.tar.gz", "luarocks-2.0.4-rc3.tar.gz", "luarocks-2.0.4-rc2.tar.gz", "luarocks-2.0.4-rc1.tar.gz", "luarocks-2.0.3.tar.gz", "luarocks-2.0.3-rc2.tar.gz", "luarocks-2.0.3-rc1.tar.gz", "luarocks-2.0.2.tar.gz", "luarocks-2.0.1.tar.gz", "luarocks-2.0.tar.gz", "luarocks-1.0.1.tar.gz", "luarocks-1.0.tar.gz", "luarocks-0.6.0.2.tar.gz", "luarocks-0.5.2.tar.gz", "luarocks-0.5.1.tar.gz", "luarocks-0.5.tar.gz", "luarocks-0.4.3.tar.gz", "luarocks-0.4.2.tar.gz", "luarocks-0.4.1.tar.gz", "luarocks-0.4.tar.gz", "luarocks-0.3.2.tar.gz", "luarocks-0.3.1.tar.gz", "luarocks-0.3.tar.gz", "luarocks-0.2.tar.gz", "luarocks-0.1.tar.gz"}
names := []string{}

for ver, item := range parseLuaRocksVers([]byte(LuaRocksHTML)) {
list, _ := parseLuaRocksVers([]byte(LuaRocksHTML)).GetList()
for _, item := range list {
names = append(names, item.Name)
assert.Equal(t, ver, item.Ver)
}
sort.Strings(exp)
sort.Strings(names)
Expand All @@ -24,9 +24,9 @@ func Test_parseLuaJitVers(t *testing.T) {
exp := []string{"LuaJIT-2.1.0-beta3.tar.gz", "LuaJIT-2.0.5.tar.gz", "LuaJIT-1.1.8.tar.gz", "LuaJIT-1.0.3.tar.gz"}
names := []string{}

for ver, item := range parseLuaJitVers([]byte(LuaJitHTML)) {
list, _ := parseLuaJitVers([]byte(LuaJitHTML)).GetList()
for _, item := range list {
names = append(names, item.Name)
assert.Equal(t, ver, item.Ver)
}
sort.Strings(exp)
sort.Strings(names)
Expand All @@ -37,9 +37,9 @@ func Test_parseLuaVers(t *testing.T) {
exp := []string{"lua-5.4.4.tar.gz", "lua-5.4.3.tar.gz", "lua-5.4.2.tar.gz", "lua-5.4.1.tar.gz", "lua-5.4.0.tar.gz", "lua-5.3.6.tar.gz", "lua-5.3.5.tar.gz", "lua-5.3.4.tar.gz", "lua-5.3.3.tar.gz", "lua-5.3.2.tar.gz", "lua-5.3.1.tar.gz", "lua-5.3.0.tar.gz", "lua-5.2.4.tar.gz", "lua-5.2.3.tar.gz", "lua-5.2.2.tar.gz", "lua-5.2.1.tar.gz", "lua-5.2.0.tar.gz", "lua-5.1.5.tar.gz", "lua-5.1.4.tar.gz", "lua-5.1.3.tar.gz", "lua-5.1.2.tar.gz", "lua-5.1.1.tar.gz", "lua-5.1.tar.gz", "lua-5.0.3.tar.gz", "lua-5.0.2.tar.gz", "lua-5.0.1.tar.gz", "lua-5.0.tar.gz", "lua-4.0.1.tar.gz", "lua-4.0.tar.gz", "lua-3.2.2.tar.gz", "lua-3.2.1.tar.gz", "lua-3.2.tar.gz", "lua-3.1.tar.gz", "lua-3.0.tar.gz", "lua-2.5.tar.gz", "lua-2.4.tar.gz", "lua-2.2.tar.gz", "lua-2.1.tar.gz", "lua-1.1.tar.gz", "lua-1.0.tar.gz"}
names := []string{}

for ver, item := range parseLuaVers([]byte(LuaHTML)) {
list, _ := parseLuaVers([]byte(LuaHTML)).GetList()
for _, item := range list {
names = append(names, item.Name)
assert.Equal(t, ver, item.Ver)
}
sort.Strings(names)
sort.Strings(exp)
Expand Down
14 changes: 9 additions & 5 deletions install.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,19 +323,23 @@ func cmdInstall(cfg *TargetConfig, opts []string) {
if len(opts) == 0 {
cmdHelp(1, "no version specified")
}
ver := opts[0]
opts = opts[1:]

item, err := getVerInfo(cfg.VersionFile, ver)
vers, err := NewVersionsFromFile(cfg.VersionFile)
if err != nil {
fatalf("failed to get version info: %v", err)
} else if item == nil {
fatalf("failed to read version file %q: %v", cfg.VersionFile, err)
}

ver := opts[0]
opts = opts[1:]
item := vers.GetItem(ver)
if item == nil {
fatalf("%s version %q does not defined in %q", cfg.Name, ver, cfg.VersionFile)
} else if item.Ext != ".tar.gz" {
fatalf("unsupported media-type %q", item.Name)
}
url := cfg.DownloadURL + filepath.Clean(item.Name)

printf("install %q", item.Ver)
printf("download %q", url)
data, err := download(url)
if err != nil {
Expand Down
27 changes: 15 additions & 12 deletions list.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,14 @@ func listRocks(luadir string) {
maxlen := 0
for _, info := range infos {
ver := info.Name()
if isSemVer(ver) {
if IsSemVer(ver) {
vers = append(vers, ver)
if len(ver) > maxlen {
maxlen = len(ver)
}
}
}
sortVersions(vers)
SortVersions(vers)

if len(vers) > 0 {
format := fmt.Sprintf(" %%s %%-%ds", maxlen)
Expand Down Expand Up @@ -87,18 +87,21 @@ func cmdList() {
continue
}

vers := []string{}
dirs := []string{}
vers, err := NewVersionsFromFile(cfg.VersionFile)
if err != nil {
eprintf("failed to read version file %q: %v", cfg.VersionFile, err)
continue
}

inst_vers := []string{}
inst_dirs := []string{}
maxlen := 0
for _, info := range infos {
ver := info.Name()
dir := filepath.Join(cfg.RootDir, ver)

// verify version
if item, err := getVerInfo(cfg.VersionFile, ver); err != nil {
eprintf("failed to get version info: %v", err)
break
} else if item == nil {
if item := vers.GetItem(ver); item == nil {
// ignore unknown file/directory
eprintf("ignore unknown version: %s (%q)", ver, dir)
continue
Expand All @@ -109,13 +112,13 @@ func cmdList() {
maxlen = len(ver)
}

dirs = append(dirs, dir)
vers = append(vers, ver)
inst_dirs = append(inst_dirs, dir)
inst_vers = append(inst_vers, ver)
}

format := fmt.Sprintf("%%-%ds (%%s)", maxlen)
for i, v := range vers {
dir := dirs[i]
for i, v := range inst_vers {
dir := inst_dirs[i]
if dir == CurrentUsed {
printf(format+" (used)", v, dir)
} else {
Expand Down
48 changes: 0 additions & 48 deletions main.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
package main

import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -216,52 +214,6 @@ func writeFile(file string, perm os.FileMode, src io.Reader) error {
return nil
}

type ListItem struct {
Name string
Ver string
Sum string
Ext string
}

type List map[string]*ListItem

func writeVersionFile(file string, list List) error {
if b, err := json.MarshalIndent(list, "", " "); err != nil {
return err
} else if err = writeFile(file, 0, bytes.NewReader(b)); err != nil {
return err
}
return nil
}

func readVersionFile(file string) (List, error) {
f, err := os.Open(file)
if err != nil {
return nil, err
}
defer f.Close()

b, err := ioutil.ReadAll(f)
if err != nil {
return nil, err
}

list := make(List)
if err = json.Unmarshal(b, &list); err != nil {
return nil, err
}
return list, nil
}

func getVerInfo(file string, ver string) (*ListItem, error) {
if list, err := readVersionFile(file); err != nil {
return nil, fmt.Errorf("failed to read version file: %w", err)
} else if item, ok := list[ver]; ok {
return item, nil
}
return nil, nil
}

func hasRequiredDirs() bool {
// create required directories
for _, dir := range []string{
Expand Down
11 changes: 7 additions & 4 deletions uninstall.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,15 @@ func cmdUninstall(cfg *TargetConfig, opts []string) {
if len(opts) == 0 {
cmdHelp(1, "no version specified")
}
ver := opts[0]

item, err := getVerInfo(cfg.VersionFile, ver)
vers, err := NewVersionsFromFile(cfg.VersionFile)
if err != nil {
fatalf("failed to get version info: %v", err)
} else if item == nil {
fatalf("failed to read version file %q: %v", cfg.VersionFile, err)
}

ver := opts[0]
item := vers.GetItem(ver)
if item == nil {
fatalf("%s version %q does not defined in %q", cfg.Name, ver, cfg.VersionFile)
}

Expand Down
11 changes: 7 additions & 4 deletions use.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ func cmdUse(cfg *TargetConfig, opts []string) {
if len(opts) == 0 {
cmdHelp(1, "no version specified")
}
ver := opts[0]

item, err := getVerInfo(cfg.VersionFile, ver)
vers, err := NewVersionsFromFile(cfg.VersionFile)
if err != nil {
fatalf("failed to get version info: %v", err)
} else if item == nil {
fatalf("failed to read version file %q: %v", cfg.VersionFile, err)
}

ver := opts[0]
item := vers.GetItem(ver)
if item == nil {
fatalf("%s version %q does not defined in %q", cfg.Name, ver, cfg.VersionFile)
}

Expand Down
Loading

0 comments on commit f7bd169

Please sign in to comment.