1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | const fs = require("fs");
|
4 | const path = require("path");
|
5 | const yaml = require("js-yaml");
|
6 | const dep_graph_1 = require("@snyk/dep-graph");
|
7 | const utils_1 = require("./utils");
|
8 | class LockfileParser {
|
9 | constructor(hash, rootPkgInfo) {
|
10 | this.rootPkgInfo = undefined;
|
11 | this.rootPkgInfo = rootPkgInfo;
|
12 | this.internalData = hash;
|
13 | }
|
14 | static async readFile(lockfilePath) {
|
15 | const rootName = path.basename(path.dirname(path.resolve(lockfilePath)));
|
16 | return new Promise((resolve, reject) => {
|
17 | fs.readFile(lockfilePath, { encoding: 'utf8' }, (err, fileContents) => {
|
18 | if (err) {
|
19 | reject(err);
|
20 | }
|
21 | try {
|
22 | const parser = this.readContents(fileContents, {
|
23 | name: rootName,
|
24 | version: '0.0.0',
|
25 | });
|
26 | resolve(parser);
|
27 | }
|
28 | catch (err) {
|
29 | reject(err);
|
30 | }
|
31 | });
|
32 | });
|
33 | }
|
34 | static readFileSync(lockfilePath) {
|
35 | const fileContents = fs.readFileSync(lockfilePath, 'utf8');
|
36 | const rootName = path.basename(path.dirname(path.resolve(lockfilePath)));
|
37 | return this.readContents(fileContents, {
|
38 | name: rootName,
|
39 | version: '0.0.0',
|
40 | });
|
41 | }
|
42 | static readContents(contents, rootPkgInfo) {
|
43 | return new LockfileParser(yaml.safeLoad(contents), rootPkgInfo);
|
44 | }
|
45 | toDepGraph() {
|
46 | const builder = new dep_graph_1.DepGraphBuilder(this.pkgManager, this.rootPkgInfo);
|
47 | const allDeps = {};
|
48 |
|
49 | this.internalData.PODS.forEach((elem) => {
|
50 | let pkgInfo;
|
51 | let pkgDeps;
|
52 | if (typeof elem === 'string') {
|
53 |
|
54 |
|
55 | pkgInfo = utils_1.pkgInfoFromSpecificationString(elem);
|
56 | pkgDeps = [];
|
57 | }
|
58 | else {
|
59 |
|
60 |
|
61 |
|
62 | const objKey = Object.keys(elem)[0];
|
63 | pkgInfo = utils_1.pkgInfoFromSpecificationString(objKey);
|
64 | pkgDeps = elem[objKey].map(utils_1.pkgInfoFromDependencyString);
|
65 | }
|
66 | const nodeId = this.nodeIdForPkgInfo(pkgInfo);
|
67 | builder.addPkgNode(pkgInfo, nodeId, {
|
68 | labels: this.nodeInfoLabelsForPod(pkgInfo.name),
|
69 | });
|
70 | allDeps[nodeId] = pkgDeps;
|
71 | });
|
72 |
|
73 |
|
74 | this.internalData.DEPENDENCIES.map(utils_1.pkgInfoFromDependencyString).forEach((pkgInfo) => {
|
75 | builder.connectDep(builder.rootNodeId, this.nodeIdForPkgInfo(pkgInfo));
|
76 | });
|
77 |
|
78 | Object.entries(allDeps).forEach(([nodeId, pkgDeps]) => pkgDeps.forEach((pkgInfo) => {
|
79 | const depNodeId = this.nodeIdForPkgInfo(pkgInfo);
|
80 | if (!allDeps[depNodeId]) {
|
81 |
|
82 |
|
83 |
|
84 |
|
85 | return;
|
86 | }
|
87 | builder.connectDep(nodeId, depNodeId);
|
88 | }));
|
89 | return builder.build();
|
90 | }
|
91 |
|
92 |
|
93 | nodeIdForPkgInfo(pkgInfo) {
|
94 | return pkgInfo.name;
|
95 | }
|
96 |
|
97 |
|
98 | nodeInfoLabelsForPod(podName) {
|
99 | let nodeInfoLabels = {
|
100 | checksum: this.checksumForPod(podName),
|
101 | };
|
102 | const repository = this.repositoryForPod(podName);
|
103 | if (repository) {
|
104 | nodeInfoLabels = Object.assign(Object.assign({}, nodeInfoLabels), { repository });
|
105 | }
|
106 | const externalSourceInfo = this.externalSourceInfoForPod(podName);
|
107 | if (externalSourceInfo) {
|
108 | nodeInfoLabels = Object.assign(Object.assign({}, nodeInfoLabels), { externalSourcePodspec: externalSourceInfo[':podspec'], externalSourcePath: externalSourceInfo[':path'], externalSourceGit: externalSourceInfo[':git'], externalSourceTag: externalSourceInfo[':tag'], externalSourceCommit: externalSourceInfo[':commit'], externalSourceBranch: externalSourceInfo[':branch'] });
|
109 | }
|
110 | const checkoutOptions = this.checkoutOptionsForPod(podName);
|
111 | if (checkoutOptions) {
|
112 | nodeInfoLabels = Object.assign(Object.assign({}, nodeInfoLabels), { checkoutOptionsPodspec: checkoutOptions[':podspec'], checkoutOptionsPath: checkoutOptions[':path'], checkoutOptionsGit: checkoutOptions[':git'], checkoutOptionsTag: checkoutOptions[':tag'], checkoutOptionsCommit: checkoutOptions[':commit'], checkoutOptionsBranch: checkoutOptions[':branch'] });
|
113 | }
|
114 |
|
115 |
|
116 | Object.entries(nodeInfoLabels).forEach(([key, value]) => {
|
117 | if (value === null || value === undefined) {
|
118 | delete nodeInfoLabels[key];
|
119 | }
|
120 | });
|
121 | return nodeInfoLabels;
|
122 | }
|
123 |
|
124 | checksumForPod(podName) {
|
125 | const rootName = utils_1.rootSpecName(podName);
|
126 | return this.internalData['SPEC CHECKSUMS'][rootName];
|
127 | }
|
128 |
|
129 | repositoryForPod(podName) {
|
130 |
|
131 | const specRepos = this.internalData['SPEC REPOS'];
|
132 | if (!specRepos) {
|
133 | return undefined;
|
134 | }
|
135 | const rootName = utils_1.rootSpecName(podName);
|
136 | const specRepoEntry = Object.entries(specRepos).find(([, deps]) => deps.includes(rootName));
|
137 | if (specRepoEntry) {
|
138 | return specRepoEntry[0];
|
139 | }
|
140 | return undefined;
|
141 | }
|
142 |
|
143 | externalSourceInfoForPod(podName) {
|
144 |
|
145 | const externalSources = this.internalData['EXTERNAL SOURCES'];
|
146 | if (!externalSources) {
|
147 | return undefined;
|
148 | }
|
149 | const externalSourceEntry = externalSources[utils_1.rootSpecName(podName)];
|
150 | if (externalSourceEntry) {
|
151 | return externalSourceEntry;
|
152 | }
|
153 | return undefined;
|
154 | }
|
155 |
|
156 | checkoutOptionsForPod(podName) {
|
157 |
|
158 | const checkoutOptions = this.internalData['CHECKOUT OPTIONS'];
|
159 | if (!checkoutOptions) {
|
160 | return undefined;
|
161 | }
|
162 | const checkoutOptionsEntry = checkoutOptions[utils_1.rootSpecName(podName)];
|
163 | if (checkoutOptionsEntry) {
|
164 | return checkoutOptionsEntry;
|
165 | }
|
166 | return undefined;
|
167 | }
|
168 | get repositories() {
|
169 |
|
170 | const specRepos = this.internalData['SPEC REPOS'];
|
171 | if (!specRepos) {
|
172 | return [];
|
173 | }
|
174 | return Object.keys(specRepos).map((nameOrUrl) => {
|
175 | return { alias: nameOrUrl };
|
176 | });
|
177 | }
|
178 | get pkgManager() {
|
179 | return {
|
180 | name: 'cocoapods',
|
181 | version: this.cocoapodsVersion,
|
182 | repositories: this.repositories,
|
183 | };
|
184 | }
|
185 |
|
186 |
|
187 | get cocoapodsVersion() {
|
188 | return this.internalData.COCOAPODS || 'unknown';
|
189 | }
|
190 |
|
191 |
|
192 | get podfileChecksum() {
|
193 | return this.internalData['PODFILE CHECKSUM'];
|
194 | }
|
195 | }
|
196 | exports.default = LockfileParser;
|
197 |
|
\ | No newline at end of file |