/
dependency.py
236 lines (225 loc) · 7.38 KB
/
dependency.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
from gradle import parseGradle,parserDefs
import re
from build_utils import *
import maven as mvn
import os.path as path
from manifest import Manifest
class CyclicException(Exception):
pass
class Dependency():
globalDeps = {}
def __init__(self,name):
super().__init__()
self.name=name
self.dependencies=[]
self.type = 'unresolved'
self.path = 'unresolved'
self.collected = False
self.position = -1
self.jar_files = []
self.cyclic = False
self.options = None
def getOptions(self):
return {}
def addDep(self,dep):
if dep not in self.dependencies:
self.dependencies.append(dep)
def addJars(self,jars):
self.jar_files.extend(jars)
def collect(self):
self.cyclic = True
try:
position = 1
for i in self.dependencies:
i.collect()
position+=i.position
self.position=position
except CyclicException as e:
raise CyclicException(self.name+">"+str(e))
except Exception as f:
raise f
finally:
self.cyclic = False
self.collected=True
def getLibs(self,recurse=False):
paths = list(self.jar_files)
if recurse:
for i in self.dependencies:
for j in i.getLibs(True):
if j not in paths:
paths.append(j)
return paths
def getObjs(self,recurse=False):
if self.type == "unresolved":
return []
if path.exists(self.build_path+"/obj"):
paths = wrap(self.build_path+"/obj")
else:
paths = []
if recurse:
for i in self.dependencies:
for j in i.getObjs(recurse):
if j not in paths:
paths.append(j)
return paths
def getRPath(self):
if not self.manifest:
return False
manifest = Manifest(self.manifest)
path_=self.build_path+"/gen/"+"/".join(manifest.getPackageName().split("."))+"/R.java"
if path.exists(path_):
return path_
return False
def getChildRPaths(self):
paths = []
a = self.dependencies
for i in self.dependencies:
a = i.getRPath()
if a and a not in paths:
paths.append(a)
for j in i.getChildRPaths():
if j not in paths:
paths.append(j)
return paths
#def getDexs(self):
# if not path.exists(self.dex_path):
# return []
# paths = wrap(self.dex_path)
# return paths
def listDeps(self,sep="\n"):
text = ""
text += self.name
for i in self.dependencies:
text += sep+"|--"+i.name
return text
def __str__(self):
return self.listDeps()
class ProjectDependency(Dependency):
def __init__(self,name,path):
super().__init__(name)
self.path = path
self.type = "project"
self.gradleFile = self.path+"/build.gradle"
self.options = {}
Dependency.globalDeps[self.path]=self;
def getOptions(self):
return self.options
def resolvePath(root,name):
curdir = root
for i in LIBRARY_PATHS:
if(path.exists(path.join(curdir,i,name))):
return path.normpath(path.join(curdir,i,name))
break
else:
raise Exception("Can't find Project "+name)
def collect(self):
if self.cyclic:
raise CyclicException(self.name)
if self.collected:
return
parseGradle(self)
super().collect()
class JarDependency(Dependency):
def __init__(self,name,path):
super().__init__(name)
self.path = path
Dependency.globalDeps[self.path]=self
def collect(self):
pass
class MvnDependency(Dependency):
def __init__(self,name,dep=None):
super().__init__(name)
self.dep = dep
Dependency.globalDeps[self.name]=self
def collect(self):
if self.cyclic:
raise CyclicException(self.name)
if self.collected:
return
if not self.dep:
self.dep = mvn.parseDependency(self.name)
dep=self.dep;
if not mvn.installDependency(dep):
warn(self.name +" not installed")
return False
try:
self.type = mvn.getDependencyType(stropen(mvn.dependencyToPath(dep)+".pom"))
except Exception as e:
error(e)
error("Unable to get type")
self.type="unresolved"
return False
if self.type not in ("aar","jar"):
warn(f"Unknown dependency type {self.type} for {self.name}")
self.path = mvn.dependencyToPath(dep)+"."+self.type
if self.type =="aar":
self.projectPath = mvn.dependencyToPath(dep)+".exploaded.aar/"
elif self.type == "jar":
self.projectPath = mvn.dependencyToBasePath(dep)+"/"+dep["version"]
if not path.exists(self.projectPath):
os.mkdir(self.projectPath)
if not path.exists(self.path):
error("No File for "+self.name)
return False
for i in mvn.listDependencies(dep):
name = mvn.getName(i)
obj = getMvnDependency(name,i)
self.dependencies.append(obj)
super().collect()
def getMvnDependency(name,dep=None):
for i in Dependency.globalDeps:
j = Dependency.globalDeps[i]
if j.type == "project":
continue
if mvn.isMatch(name,j.name):
obj = j
break
elif mvn.isSameArtifact(name,j.name):
if IGNORE_VERSION_CONFLICT:
obj = j
break
raise Exception(f"Version conflict {j.name} and {name}")
else:
if dep == None:
dep = mvn.parseDependency(name)
obj = MvnDependency(mvn.getName(dep),dep)
return obj
def getDependency(name,gradle):
path = ProjectDependency.resolvePath(gradle.path,name)
if Dependency.globalDeps.get(path):
return Dependency.globalDeps.get(path)
else:
return ProjectDependency(name,path)
mvn_dep = re.compile("[\"\']([^@\s]*)(@.*)*[\"\']\s*")
jar_dep = re.compile("fileTree\s*\(\s*dir\s*:\s*[\'\"](.*)[\"\']\s*,\s*include\s*:\s*\[\s*((?:[\'\"].*[\"\'],*)(?:,\s*[\'\"].*[\"\'])*\s*),?\s*\]\s*\)")
project_dep = re.compile("project\s*\(\s*[\"\']\:(.*)[\"\']\s*")
def parseDependencyEntry(lib,entry,parents):
type_ = entry["key"]
name_ = entry["value"]
if type_ not in ["implementation","api","compile"]:
info("Ignoring "+type_+" "+name_)
return True
a = re.match(mvn_dep,name_)
if a:
lib.addDep(getMvnDependency(a.group(1)))
return True
a = re.match(jar_dep,name_)
if a:
folder = a.group(1)
files = a.group(2).replace("'","").replace('"',"").split(",")
if not path.exists(lib.path+"/"+folder):
return True
for i in files:
a =glob(lib.path+"/"+folder,i)
lib.addJars(a)
return True
a = re.match(project_dep,name_)
if a:
lib.addDep(getDependency(a.group(1),lib))
return True
else:
return False
return False
parserDefs["dependencies"] = {
'__entry':parseDependencyEntry
}