-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathacpm
executable file
·582 lines (512 loc) · 20 KB
/
acpm
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
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
#!/usr/bin/env python
import os, sys, urllib, shutil, zipfile
# notice that this requires a connection to the web in order to properly work
# MAJOR TODO: remove swearings from remarks
##=====COMMANDS FUNCTIONS=====##
##=====ListRepo=====##
#This function access the content of the file
#"content.acpm" in the repo and print the structure
#of the componet that there are in the repo.
def ListRepo(): # online
file_url = repo_url + "content.acpm" # repo_url is hardcoded, but is little what we can do in this situation
# so, content.acpm is an YAML
print "Trying to access \'" + file_url + "\'..."
try:
# the contents of the repo are listed in the YAML
# so, the repo contents are kinda displayed offline
f = urllib.urlopen(file_url)
content = f.read()
f.close()
yaml_obj = {} # dictionary
# now we are going to replace the YAML library usage with our own parser
yaml_obj = loadYAML(content)
# as structure being hardcoded, there is a tight relation between the local stuff and the repo, they use the same file structure
# however, this tight relation is the purpose of the reference platform itself
# this works kinda like list(), but reading the repo YAML
for x in structure:
print x.upper() + ":"
if yaml_obj[x] != None:
for y in sorted(yaml_obj[x].iterkeys()): # why this must be sorted? it is sorted for an homogeneous key display
print " " + y + ": " + yaml_obj[x][y]
print ""
else:
print ""
except:
print "!!! Error: Could not access the repository."
sys.exit(1)
##=====List=====##
#This function list the structure of local components
def List(): # I guess I understood this
localpath = os.getcwd()
for x in structure: # structure is hardcoded, so it will only look the appropriate folders, but I can't see if there is an alternative to this crappy list
mypath = localpath + "/" + x
print x.upper() + ":"
if os.path.isdir(mypath):
tmpdirlist = os.listdir(mypath)
for y in tmpdirlist: # here is were the magic is done
if os.path.isdir(mypath + "/" + y):
print " ", y, "-", getDescriptionText(mypath + "/" + y)
print ""
##=====Get=====##
#This function try to get the component from the repo
#if t find, the function dowanload the component package
#and unpack it.
#if not, returns error.
# FIXME: set exception Types on first try/except block
def Get(Type, name): # online / I guess I understood it
# smart way to do the stuff
if Type != None:
lst = []
lst.append(Type)
else:
# copies the structure itself, not the reference to it (safer)
lst = list(structure)
# bulletproof
try:
component = findRepoComponent(name, lst)
# FIXME: check this for other errors that aren't a bad component Type or web issues
# bad component Type
except KeyError:
print "!!! Error: invalid component Type."
sys.exit(1)
# if not connected to the web
except:
print "!!! Error: could not access the repository."
sys.exit(1)
# "component" is a string
if component != None:
# my guess is this thing - "target" - is the component .acpmpack URL
target = os.getcwd() + "/" + component.split("/")[-2] + "/"
# my guess is this is the file name that will be on the local file system, the .acpmpack
fileName = component.split("/")[-1]
try:
download(component, target, fileName)
except:
print "!!! Error: Component " + name + " not found"
sys.exit(1)
else:
print "!!! Error: Component " + name + " not found"
sys.exit(1)
print "Component " + name + " was downloaded successfully."
# after downloading, extracts the stuff; target + fileName is the path of the downloaded .acpmpack
Unpack(target + fileName)
##=====Put=====##
#Packs a component and copies it to a specific path
def Put(Type, name):
if not os.path.exists(put_path):
os.mkdir(put_path)
if name == None or name == "all":
print "Error! Must specify the component!"
sys.exit(1)
Pack(Type, name)
if Type != None:
if not os.path.exists(put_path + "/" + Type):
os.mkdir(put_path + "/" + Type)
shutil.copyfile(Type + "/" + name + ".acpmpack", put_path + "/" + Type + "/" + name + ".acpmpack")
else:
for x in structure:
if os.path.exists(os.getcwd() + "/" + x + "/" + name + ".acpmpack"):
if not os.path.exists(put_path + "/" + x):
os.mkdir(put_path + "/" + x)
shutil.copyfile(x + "/" + name + ".acpmpack", put_path + "/" + x + "/" + name + ".acpmpack")
print "Component " + name + " was successfully copied to " + put_path
##=====Pack=====##
#This function pack the component or platfomrs.
#It compress all files in a acpmpack file.
def Pack(Type, name):
# my initial hunch is that this function gets all the components you have on your acpm local package
source_files = ""
component = ""
if Type == None and name == None:
# magic
for x in structure:
for y in os.listdir(os.getcwd() + "/" + x):
Pack(x, y)
else:
if Type == None and name == "all":
# this if is to get ALL the stuff
localpath = os.getcwd()
# walks in the file system getting each source file
for x in structure:
# note that localpath is kinda the same, but x alters itself on each iteration, being each one of the contents of the list structure
# I noticed that the list structure is kinda the base of all this thing
mypath = localpath + "/" + x + "/"
if os.path.exists(mypath):
source_files = source_files + x + "/ "
# my hunch is that, in the end, source_files = "platforms/ processors/ ip/ is/ sw/ wrappers/ Makefile"
source_files = source_files.split()
source_files.append("Makefile")
package_file = "all.acpmpack"
elif Type == None and name != None: # None must be the NULL of python
# gets just one component in the "acpm package", like the mips1, or quad_mips
component = findLocalComponent(name, structure)
if component != None:
source_files = component.split("/")[-3] + "/" + component.split("/")[-2] + "/"
source_files = [source_files]
package_file = component.split("/")[-3] + "/" + name + ".acpmpack"
else:
print "!!! Error: Component " + name + " not found"
sys.exit(1) # interesting, might be as same as raise SystemExit --> nope, SystemExit == sys.exit(0)
else:
# this works just like the elif above
lst = []
lst.append(Type)
# bulletproof
try:
component = findLocalComponent(name, lst)
except:
print "!!! Error: invalid component Type."
sys.exit(1)
if component != None:
source_files = component.split("/")[-3] + "/" + component.split("/")[-2] + "/"
source_files = [source_files]
package_file = component.split("/")[-3] + "/" + name + ".acpmpack"
else:
print "!!! Error: Component " + name + " not found"
sys.exit(1)
print "Packing " + package_file + "..."
# bulletproof
try:
utilities = ZipUtilities()
utilities.toZip(source_files,package_file)
print "Done."
except:
print "!!! Error: unable to pack, please try again."
sys.exit(1)
##=====Unpack=====##
#This function unpack the component package
def Unpack(package): # I guess I understood this
if not os.path.exists(package):
print "!!! Error: Package " + package + " doesn't exists."
sys.exit(1)
else:
# this is the anti-pack
print "Unpacking " + package + " ..."
# bulletproof
try:
z = zipfile.ZipFile(package,"a")
z.extractall()
z.close()
print "Done."
except:
print "!!! Error: unable to unpack, please try again."
sys.exit(1)
##=====Create=====##
#This function create the component specified
#if exist a local copy of the template component
#the functions copy it with the new name,
#if not, the function try to get in the repo.
def Create(Type, name): # calls get, so this is online / I guess I understood how this works - at least from the inside - but the result isn't obvious to me
# might need online testing
# there is a need to already be a template in the local repo, otherwise, it will search it online
# so, the template is a dir tree?
list = []
list.append(Type) # there is a REAL need here for the Type
# bulletproof
try:
component = findLocalComponent("template", list)
print component
except:
print "!!! Error: invalid component Type."
sys.exit(1)
if component != None:
target = os.getcwd() + "/" + Type + "/"
try:
# my guess is this copies the whole filesystem tree under component to target + name (sorry for the kinda obvious stuff)
shutil.copytree(component, target + name)
except:
print "!!! Error: Component template of " + Type + " not found"
sys.exit(1)
else:
# here is where it will look for the template so it can be downloaded and unpacked in the local repo
Get(Type, "template")
##=====Start=====##
#This function download the start.package
#and unpack it. This File has the structure of dir
#and the main Makefile.
def Start(): # online / I guess I understood this
target = os.getcwd() + "/"
fileName = "start.acpmpack"
try:
# gets the base acpmpack...
download(repo_url + fileName, target, fileName)
except:
print "!!! Error: File start.acpmpack not found."
sys.exit(1)
# ...and unpacks it
Unpack(target + fileName)
# creates the reference platform dir structure
for folder in structure:
os.mkdir(folder)
print "The main structure was created successfully."
##=====Repo=====##
#This function creates the "content.acpm" file.
#The function gets all components in the local structure
#and put it in a YAML file.
def Repo(): # I guess I understood this
# this works just like list(), but put the contents in a file
localpath = os.getcwd()
f = open(localpath + "/content.acpm", "w")
for x in structure:
mypath = localpath + "/" + x
f.write(x + ":\n")
tmpdirlist = os.listdir(mypath)
for y in tmpdirlist:
if os.path.isdir(mypath + "/" + y):
f.write(" " + y + ": " + getDescriptionText(mypath + "/" + y) + "\n")
f.write("\n")
f.close()
print "The file 'content.acpm' was created successfully."
##=====Help=====##
#This function shows the help contents.
def Help(): # trivial
print """
-c, --create create
-g, --get get
-h, --help help
-l, --list list
-lr, --listrepo listrepo
-pa, --pack pack
-pu, --put put
-r, --repo repo
-s, --start start
-u, --unpack unpack
"""
##=====AUX FUNCTIONS=====##
##=====getDescripitionText=====##
#This function gets the content of the file
#"desc.txt" and return it
#if the file doesn't exist, it returns none
def getDescriptionText(path): # I guess I undertood pretty well how this works
path = path + "/desc.txt"
try:
f = open(path, "r")
desc = f.read()
f.close()
return desc
except:
return "No description provided."
##=====download=====##
#This function gets a file in the repo and copy it
#to the user local path
def download(source, target, name): # online / I guess I understood it
# all this can generate exceptions, as being file operations
webFile = urllib.urlopen(source) # opens the webfile in the local memory (kinda obvious)
localFile = open(target + name, 'w') # creates a local file (not *that* obvious, but still obvious)
localFile.write(webFile.read()) # writes into it (obvious)
webFile.close() # closes webfile (obvious)
localFile.close() # closes local file (obvious)
##=====findLocalComponent=====##
#This function search for the component in the users local path
#if it founds, returns the path to the component
#if not, return none
def findLocalComponent(name, lst): # I guess I understood it
path = os.getcwd()
# gets the full file system tree below path, both dirs and files
tmpdirlist = os.listdir(path)
for x in lst: # list can be structure or a subset of structure, AFAIK
tmpdirlist = os.listdir(path + "/" + x)
# if there is what it is searching for in the tmplist, it tests if it is a dir and returns it
if name in tmpdirlist:
if os.path.isdir(path + "/" + x + "/" + name):
return path + "/" + x + "/" + name + "/"
return None
##=====findRepoComponent=====##
#This function search for the component in the repo
#if it founds, returns the path to the component
#if not, return none
def findRepoComponent(name, lst): # online / I guess I understood it
# this works just like findLocalComponent when seen from the outside, but reads the repo yaml file and searches it
file_url = repo_url + "content.acpm"
f = urllib.urlopen(file_url)
content = f.read()
f.close()
# here "content" is the yaml file
yaml_obj = {}
yaml_obj = loadYAML(content)
compName = name.split(".")[0]
for x in lst:
if yaml_obj[x] != None:
if compName in yaml_obj[x].iterkeys():
# if found the component, returns its path
return repo_url + x + "/" + name + ".acpmpack"
return None
##=====smartGetRepo=====##
#This function gets the appropriate repo URL
#and generates the repo.cfg file, which can
#be edited to add alternative repos
# TODO: test properly
# tested offline and with crippled internet access (a.k.a. "Unicamp-Visitante")
def smartGetRepo():
hardcoded_repo_url = "http://www.students.ic.unicamp.br/~ra103501/acpm_repo/" # Matheus Boy
# hardcoded_repo_url = "http://www.students.ic.unicamp.br/~ra063091/repo/" - Matheus Nagliati
# not satisfied with this "test"
# something like file.exists() would be much more elegant than this try/except
try:
f = open("repo.cfg","r")
repo_str = f.read()
f.close()
repo_list = repo_str.split("\n")
repo_list.remove("")
try:
for repo in repo_list:
a = urllib.urlopen(repo + "content.acpm")
b = a.getcode()
a.close()
if b == 200:
return repo
except:
# if there isn't a available repo in the repo.cfg, returns the default
return hardcoded_repo_url
# if there is no config file, creates it
except:
f = open("repo.cfg","w")
f.write(hardcoded_repo_url+"\n")
f.close()
print "Repo config file created"
return hardcoded_repo_url
##=====smartGetPutPath=====##
# TODO: properly document this
def smartGetPutPath():
default_path = os.getcwd() + "/put"
try:
f = open("put_path.cfg","r")
repo_str = f.read()
f.close()
repo_list = repo_str.split("\n")
return repo_list[0]
# if there is no config file, creates it
except:
f = open("put_path.cfg","w")
f.write(default_path + "\n")
f.close()
print "Put path config file created"
return default_path
##=====loadYAML=====##
# TODO: properly document this
def loadYAML(content):
dic = {}
superiorLevel = ''
content = content.split("\n")
# builds the dictionary
for line in content:
if line != "":
# heavy wizardry \/
[key, value] = line.split(':')
if (key[0] == ' '):
# removes the whitespaces before the key name
key = key.lstrip()
# subtree
dic[superiorLevel][key] = value
else:
# tree
dic[key] = {}
superiorLevel = key
# cleans the dictionary
for l in structure:
if dic[l] == {}:
dic[l] = None
return dic
##=====AUX CLASS=====##
##=====ZipUtilities=====##
# TODO: properly document this
class ZipUtilities:
# this method now takes a list as arg
def toZip(self, files_to_zip, filename):
zip_file = zipfile.ZipFile(filename, "w")
for file_to_zip in files_to_zip:
if os.path.isfile(file_to_zip):
zip_file.write(file_to_zip)
else:
self.addFolderToZip(zip_file, file_to_zip)
zip_file.close()
# aux method
def addFolderToZip(self, zip_file, folder):
for file_ in os.listdir(folder):
full_path = os.path.join(folder, file_)
if os.path.isfile(full_path):
zip_file.write(full_path)
elif os.path.isdir(full_path):
self.addFolderToZip(zip_file, full_path)
##=====DEFINES=====##
# a.k.a. HARDCODED STUFF
##=====repo location=====#
repo_url = smartGetRepo()
##=====put path=====#
put_path = smartGetPutPath()
##=====list of supported commands=====#
commands={ # dictionary -- the key is the short action and the value is the action itself
"lr":"listrepo", "l":"list", "g":"get", "pu":"put",
"pa":"pack", "u":"unpack", "c":"create",
"s":"start", "r":"repo", "h":"help"
}
##=====structure of plataform=====#
structure = ["platforms", "processors", "ip", "is", "sw", "wrappers"]
# here begins the magic... and I guess I undertood it
execline = [] # this is a "shortcut" to the action itself -- line... would it be a queue (FIFO)?
# get cmdline args
cmdline=sys.argv[1:] # my guess is here where the arguments are caught (this remark is redundant due to the original developer remark above)
if cmdline==[]:
print "!!! Error: Invalid action."
sys.exit(1)
elif len(cmdline) > 3: # this is kinda a magic number...
print "!!! Error: Too many arguments"
sys.exit(1)
cmd = cmdline[0]
#identify the command and add it to an execution line
if cmd[0:1]=="-" and cmd[1:2]=="-": # test for the --command
values = commands.values()
if cmd[2:] in values:
execline.append(cmd[2:])
else:
print "!!! Error: " + cmd + " is an invalid action."
sys.exit(1)
elif cmd[0:1]=="-" and cmd[1:2]!="-": # test for the -cm
if commands.has_key(cmd[1:]):
execline.append(commands[cmd[1:]])
else:
print "!!! Error: "+cmd+" is an invalid short action."
sys.exit(1)
else:
print "!!! Error: " + cmd + " is an invalid action."
sys.exit(1)
execline.extend(cmdline[1:]);
action = execline[0]
# execline:
# [0]: action
# [1]: Type
# [2]: name
if len(execline) != 1:
if len(execline) == 2:
Type = None
name = execline[1]
else:
Type = execline[1]
name = execline[2]
else:
Type = None
name = None
# switch with the functions calls
if action == "listrepo":
ListRepo()
elif action == "list":
List()
elif action == "get":
Get(Type, name)
elif action == "put":
Put(Type, name)
elif action == "pack":
Pack(Type, name)
elif action == "unpack":
Unpack(name)
elif action == "create":
Create(Type, name)
elif action == "repo":
Repo()
elif action == "start":
Start()
elif action == "help":
Help()
else:
print "!!! Error: No command found" # how the hell am I going to get this error?
sys.exit(1) # maybe this is an equivalent to "raise SystemExit", or "raise SystemExit" is syntatic sugar for this? --> no, SystemExit equals sys.exit(0)