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