github.com/joey-fossa/fossa-cli@v0.7.34-0.20190708193710-569f1e8679f0/buildtools/cocoapods/lockfile.go (about) 1 package cocoapods 2 3 import ( 4 "path/filepath" 5 "regexp" 6 "strings" 7 8 "github.com/fossas/fossa-cli/files" 9 ) 10 11 type RawLockfile struct { 12 Pods []interface{} `yaml:"PODS"` // Transitive dependencies (this is actually `[](map[string][]string | string)`) 13 Dependencies []string `yaml:"DEPENDENCIES"` // Direct dependencies 14 CheckoutOptions map[string]map[string]string `yaml:"CHECKOUT OPTIONS"` 15 ExternalSources map[string]map[string]string `yaml:"EXTERNAL SOURCES"` 16 SpecRepos map[string][]string `yaml:"SPEC REPOS"` 17 } 18 19 type Lockfile struct { 20 Pods []Spec 21 Dependencies []Requirement 22 CheckoutOptions map[string]CheckoutOptions 23 ExternalSources map[string]ExternalSource 24 SpecRepos map[string][]string 25 } 26 27 type Spec struct { 28 Name string 29 Version string 30 Dependencies []Requirement 31 } 32 33 type Requirement struct { 34 Name string 35 Version string 36 Repository string 37 Branch string 38 Tag string 39 40 Original string 41 } 42 43 func (r *Requirement) String() string { 44 return r.Original 45 } 46 47 type CheckoutOptions struct { 48 Git string 49 Commit string 50 Tag string 51 } 52 53 type ExternalSource struct { 54 Git string 55 Branch string 56 Tag string 57 58 Path string 59 } 60 61 func FromLockfile(filename ...string) (Lockfile, error) { 62 var raw RawLockfile 63 err := files.ReadYAML(&raw, filepath.Join(filename...)) 64 65 var lockfile Lockfile 66 // Parse pods. 67 for _, rawPod := range raw.Pods { 68 switch r := rawPod.(type) { 69 case map[interface{}]interface{}: 70 for pod, deps := range r { 71 var reqs []Requirement 72 dep := ParseRequirement(pod.(string)) 73 for _, req := range deps.([]interface{}) { 74 reqs = append(reqs, ParseRequirement(req.(string))) 75 } 76 lockfile.Pods = append(lockfile.Pods, Spec{ 77 Name: dep.Name, 78 Version: dep.Version, 79 Dependencies: reqs, 80 }) 81 } 82 case string: 83 dep := ParseRequirement(r) 84 lockfile.Pods = append(lockfile.Pods, Spec{ 85 Name: dep.Name, 86 Version: dep.Version, 87 }) 88 default: 89 panic(rawPod) 90 } 91 } 92 93 // Parse dependencies. 94 for _, dep := range raw.Dependencies { 95 lockfile.Dependencies = append(lockfile.Dependencies, ParseRequirement(dep)) 96 } 97 98 // Parse checkout options. 99 lockfile.CheckoutOptions = make(map[string]CheckoutOptions) 100 for dep, options := range raw.CheckoutOptions { 101 lockfile.CheckoutOptions[dep] = CheckoutOptions{ 102 Git: options[":git"], 103 Commit: options[":commit"], 104 Tag: options[":tag"], 105 } 106 } 107 108 // Parse external sources. 109 lockfile.ExternalSources = make(map[string]ExternalSource) 110 for dep, options := range raw.ExternalSources { 111 lockfile.ExternalSources[dep] = ExternalSource{ 112 Git: options[":git"], 113 Branch: options[":branch"], 114 Tag: options[":tag"], 115 Path: options[":path"], 116 } 117 } 118 119 // Parse spec repos. 120 lockfile.SpecRepos = raw.SpecRepos 121 122 return lockfile, err 123 } 124 125 func ParseRequirement(req string) Requirement { 126 splits := strings.Split(req, " ") 127 name := splits[0] 128 versionSpecifier := strings.TrimPrefix(strings.TrimSuffix(strings.Join(splits[1:], " "), ")"), "(") 129 130 if strings.HasPrefix(versionSpecifier, "from ") { 131 repoRegexp := regexp.MustCompile("from `(.*?)`") 132 branchRegexp := regexp.MustCompile("branch `(.*?)`") 133 tagRegexp := regexp.MustCompile("tag `(.*?)`") 134 135 repoMatches := repoRegexp.FindStringSubmatch(versionSpecifier) 136 repo := "" 137 if len(repoMatches) == 2 { 138 repo = repoMatches[1] 139 } 140 branchMatches := branchRegexp.FindStringSubmatch(versionSpecifier) 141 branch := "" 142 if len(branchMatches) == 2 { 143 branch = branchMatches[1] 144 } 145 tagMatches := tagRegexp.FindStringSubmatch(versionSpecifier) 146 tag := "" 147 if len(tagMatches) == 2 { 148 tag = tagMatches[1] 149 } 150 151 return Requirement{ 152 Name: name, 153 Repository: repo, 154 Branch: branch, 155 Tag: tag, 156 157 Original: req, 158 } 159 } 160 return Requirement{ 161 Name: name, 162 Version: versionSpecifier, 163 164 Original: req, 165 } 166 }