z_mirror/fmm

git clone https://git.raiguard.me/z_mirror/fmm

Caleb HeuerConsider a nil version to be equal8f22b8d

predep-parsing
2.4 KiB114 linesraw
1package main
2
3import (
4	"encoding/json"
5	"strings"
6)
7
8type Dependency struct {
9	Ident ModIdent
10	Kind  DependencyKind
11	Req   VersionCmpRes
12}
13
14type DependencyKind uint8
15
16const (
17	DependencyRequired DependencyKind = iota
18	DependencyOptional
19	DependencyHiddenOptional
20	DependencyIncompatible
21	DependencyNoLoadOrder
22)
23
24func newDependency(input string) (*Dependency, error) {
25	input = strings.TrimSpace(input)
26
27	kind := DependencyRequired
28	if strings.HasPrefix(input, "!") {
29		kind = DependencyIncompatible
30		input = strings.TrimPrefix(input, "!")
31	} else if strings.HasPrefix(input, "?") {
32		kind = DependencyOptional
33		input = strings.TrimPrefix(input, "?")
34	} else if strings.HasPrefix(input, "(?)") {
35		kind = DependencyHiddenOptional
36		input = strings.TrimPrefix(input, "(?)")
37	} else if strings.HasPrefix(input, "~") {
38		kind = DependencyNoLoadOrder
39		input = strings.TrimPrefix(input, "~")
40	}
41
42	// Iterate in reverse and find the first non-digit and non-dot
43	var ver *Version = nil
44	for i := len(input) - 1; i >= 0; i-- {
45		if i > 0 && !(input[i] == '.' || (input[i] >= '0' && input[i] <= '9')) {
46			parsed, err := newVersion(input[i:])
47			if err == nil {
48				ver = parsed
49				input = strings.TrimSpace(input[:i])
50			}
51			break
52		}
53	}
54
55	req := VersionAny
56	if strings.HasSuffix(input, "<=") {
57		req = VersionLtEq
58		input = strings.TrimSuffix(input, "<=")
59	} else if strings.Contains(input, "<") {
60		req = VersionLt
61		input = strings.TrimSuffix(input, "<")
62	} else if strings.Contains(input, ">=") {
63		req = VersionGtEq
64		input = strings.TrimSuffix(input, ">=")
65	} else if strings.Contains(input, ">") {
66		req = VersionGt
67		input = strings.TrimSuffix(input, ">")
68	} else if strings.Contains(input, "=") {
69		req = VersionEq
70		input = strings.TrimSuffix(input, "=")
71	}
72
73	name := strings.TrimSpace(input)
74
75	return &Dependency{
76		Ident: ModIdent{name, ver},
77		Kind:  kind,
78		Req:   req,
79	}, nil
80}
81
82func (d *Dependency) Test(mod *ModIdent) bool {
83	if d.Ident.Name != mod.Name {
84		return false
85	}
86
87	if d.Kind == DependencyIncompatible {
88		return false
89	}
90
91	if d.Req == VersionAny {
92		return true
93	}
94
95	return d.Req&mod.Version.cmp(d.Ident.Version) > 0
96}
97
98func (d *Dependency) UnmarshalJSON(data []byte) error {
99	var s string
100	if err := json.Unmarshal(data, &s); err != nil {
101		return err
102	}
103
104	dep, err := newDependency(s)
105	if err != nil {
106		return err
107	}
108
109	d.Ident = dep.Ident
110	d.Kind = dep.Kind
111	d.Req = dep.Req
112
113	return nil
114}