Completed
Push — master ( f91ac5...675895 )
by John
01:28
created

external_version()   A

Complexity

Conditions 3

Size

Total Lines 13

Duplication

Lines 4
Ratio 30.77 %

Importance

Changes 0
Metric Value
cc 3
dl 4
loc 13
rs 9.4285
c 0
b 0
f 0
1
#!/usr/bin/env python3
2
"""This module contains various utilities for the scripts folder."""
3
4
import os  # path work
5
import getpass  # invisible password
6
import argparse  # generic parser
7
import sys  # getattr
8
import shutil  # folder removal
9
import glob  # file lookup
10
from bbarchivist import utilities  # little things
11
from bbarchivist import barutils  # file system work
12
from bbarchivist import archiveutils  # archive support
0 ignored issues
show
Unused Code introduced by
Unused archiveutils imported from bbarchivist
Loading history...
13
from bbarchivist import bbconstants  # constants
14
from bbarchivist import hashutils  # gpg
15
from bbarchivist import networkutils  # network tools
16
from bbarchivist import textgenerator  # writing text to file
17
from bbarchivist import smtputils  # email
18
from bbarchivist import sqlutils  # sql
19
20
__author__ = "Thurask"
21
__license__ = "WTFPL v2"
22
__copyright__ = "Copyright 2015-2016 Thurask"
23
24
25
def shortversion():
26
    """
27
    Get short app version (Git tag).
28
    """
29
    if not getattr(sys, 'frozen', False):
30
        ver = bbconstants.VERSION
31
    else:
32
        verfile = glob.glob(os.path.join(os.getcwd(), "version.txt"))[0]
33
        with open(verfile) as afile:
34
            ver = afile.read()
35
    return ver
36
37
38
def longversion():
39
    """
40
    Get long app version (Git tag + commits + hash).
41
    """
42
    if not getattr(sys, 'frozen', False):
43
        ver = (bbconstants.LONGVERSION, bbconstants.COMMITDATE)
44
    else:
45
        verfile = glob.glob(os.path.join(os.getcwd(), "longversion.txt"))[0]
46
        with open(verfile) as afile:
47
            ver = afile.read().split("\n")
48
    return ver
49
50
51
def default_parser(name=None, desc=None, flags=None, vers=None):
52
    """
53
    A generic form of argparse's ArgumentParser.
54
55
    :param name: App name.
56
    :type name: str
57
58
    :param desc: App description.
59
    :type desc: str
60
61
    :param flags: Tuple of sections to add.
62
    :type flags: tuple(str)
63
64
    :param vers: Versions: [git commit hash, git commit date]
65
    :param vers: list(str)
66
    """
67
    if vers is None:
68
        vers = longversion()
69
    parser = argparse.ArgumentParser(
70
        prog=name,
71
        description=desc,
72
        epilog="https://github.com/thurask/bbarchivist")
73
    parser.add_argument(
74
        "-v",
75
        "--version",
76
        action="version",
77
        version="{0} {1} committed {2}".format(parser.prog, vers[0], vers[1]))
78
    if flags is not None:
79
        if "folder" in flags:
80
            parser.add_argument(
81
                "-f",
82
                "--folder",
83
                dest="folder",
84
                help="Working folder",
85
                default=None,
86
                metavar="DIR",
87
                type=utilities.file_exists)
88
        if "osr" in flags:
89
            parser.add_argument(
90
                "os",
91
                help="OS version, 10.x.y.zzzz")
92
            parser.add_argument(
93
                "radio",
94
                help="Radio version, 10.x.y.zzzz",
95
                nargs="?",
96
                default=None)
97
            parser.add_argument(
98
                "swrelease",
99
                help="Software version, 10.x.y.zzzz",
100
                nargs="?",
101
                default=None)
102
    return parser
103
104
105
def external_version(parser, addition):
106
    """
107
    Modify the version string of argparse.ArgumentParser, adding something.
108
109
    :param parser: Parser to modify.
110
    :type parser: argparse.ArgumentParser
111
112
    :param addition: What to add.
113
    :type addition: str
114 View Code Duplication
    """
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
115
    verarg = [arg for arg in parser._actions if type(arg) == argparse._VersionAction][0]
2 ignored issues
show
Coding Style Best Practice introduced by
It seems like _actions was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
Coding Style Best Practice introduced by
It seems like _VersionAction was declared protected and should not be accessed from this context.

Prefixing a member variable _ is usually regarded as the equivalent of declaring it with protected visibility that exists in other languages. Consequentially, such a member should only be accessed from the same class or a child class:

class MyParent:
    def __init__(self):
        self._x = 1;
        self.y = 2;

class MyChild(MyParent):
    def some_method(self):
        return self._x    # Ok, since accessed from a child class

class AnotherClass:
    def some_method(self, instance_of_my_child):
        return instance_of_my_child._x   # Would be flagged as AnotherClass is not
                                         # a child class of MyParent
Loading history...
116
    verarg.version = "{1}{0}".format(addition, verarg.version)
117
    return parser
118
119
120
def return_radio_version(osversion, radioversion=None):
121
    """
122
    Increment radio version, if need be.
123
124
    :param osversion: OS version.
125
    :type osversion: str
126
127
    :param radioversion: Radio version, None if incremented.
128
    :type radioversion: str
129
    """
130
    if radioversion is None:
131
        radioversion = utilities.increment(osversion, 1)
132
    return radioversion
133
134
135
def return_sw_checked(softwareversion, osversion):
136
    """
137
    Check software existence, return boolean.
138
139
    :param softwareversion: Software release version.
140
    :type softwareversion: str
141
142
    :param osversion: OS version.
143 View Code Duplication
    :type osversion: str
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
144
    """
145
    if softwareversion is None:
146
        serv = bbconstants.SERVERS["p"]
147
        softwareversion = networkutils.sr_lookup(osversion, serv)
148
        if softwareversion == "SR not in system":
149
            print("SOFTWARE RELEASE NOT FOUND")
150
            cont = utilities.s2b(input("INPUT MANUALLY? Y/N: "))
151
            if cont:
152
                softwareversion = input("SOFTWARE RELEASE: ")
153
                swchecked = False
154
            else:
155
                print("\nEXITING...")
156
                raise SystemExit  # bye bye
157
        else:
158
            swchecked = True
159
    else:
160
        swchecked = True
161
    return softwareversion, swchecked
162
163
164
def return_radio_sw_checked(altsw, radioversion):
165
    """
166
    Check radio software existence, return boolean.
167
168
    :param altsw: Software release version.
169
    :type altsw: str
170
171
    :param radioversion: Radio version.
172
    :type radioversion: str
173
    """
174
    if altsw == "checkme":
175
        serv = bbconstants.SERVERS["p"]
176
        testos = utilities.increment(radioversion, -1)
177
        altsw = networkutils.sr_lookup(testos, serv)
178
        if altsw == "SR not in system":
179
            print("RADIO SOFTWARE RELEASE NOT FOUND")
180
            cont = utilities.s2b(input("INPUT MANUALLY? Y/N: "))
181
            if cont:
182
                altsw = input("SOFTWARE RELEASE: ")
183
                altchecked = False
184
            else:
185
                print("\nEXITING...")
186
                raise SystemExit  # bye bye
187
        else:
188
            altchecked = True
189
    else:
190
        altchecked = True
191
    return altsw, altchecked
192
193
194
def check_sw(baseurl, softwareversion, swchecked):
195
    """
196
    Check existence of software release.
197
198
    :param baseurl: Base URL (from http to hashed SW release).
199
    :type basurl: str
200
201
    :param softwareversion: Software release.
202
    :type softwareversion: str
203
204
    :param swchecked: If we checked the sw release already.
205
    :type swchecked: bool
206
    """
207
    print("CHECKING SOFTWARE RELEASE AVAILABILITY...")
208
    if not swchecked:
209
        avlty = networkutils.availability(baseurl)
210
        if avlty:
211
            print("SOFTWARE RELEASE {0} EXISTS".format(softwareversion))
212
        else:
213
            print("SOFTWARE RELEASE {0} NOT FOUND".format(softwareversion))
214
            cont = utilities.s2b(input("CONTINUE? Y/N: "))
215
            if not cont:
216
                print("\nEXITING...")
217
                raise SystemExit
218
    else:
219
        print("SOFTWARE RELEASE {0} EXISTS".format(softwareversion))
220
221
222
def check_radio_sw(alturl, altsw, altchecked):
223
    """
224
    Check existence of radio software release.
225
226
    :param alturl: Radio base URL (from http to hashed SW release).
227
    :type alturl: str
228
229
    :param altsw: Radio software release.
230
    :type altsw: str
231
232
    :param altchecked: If we checked the sw release already.
233
    :type altchecked: bool
234
    """
235
    print("CHECKING RADIO SOFTWARE RELEASE...")
236
    if not altchecked:
237
        altavlty = networkutils.availability(alturl)
238
        if altavlty:
239
            print("SOFTWARE RELEASE {0} EXISTS".format(altsw))
240
        else:
241
            print("SOFTWARE RELEASE {0} NOT FOUND".format(altsw))
242
            cont = utilities.s2b(input("CONTINUE? Y/N: "))
243
            if not cont:
244
                print("\nEXITING...")
245
                raise SystemExit
246
    else:
247
        print("SOFTWARE RELEASE {0} EXISTS".format(altsw))
248
249
250
def check_os_single(osurl, osversion, device):
251
    """
252
    Check existence of single OS link.
253
254
    :param radiourl: Radio URL to check.
255
    :type radiourl: str
256
257
    :param radioversion: Radio version.
258
    :type radioversion: str
259
260
    :param device: Device family.
261
    :type device: int
262
    """
263
    osav = networkutils.availability(osurl)
264
    if not osav:
265
        print("{0} NOT AVAILABLE FOR {1}".format(osversion, bbconstants.DEVICES[device]))
266
        cont = utilities.s2b(input("CONTINUE? Y/N: "))
267
        if not cont:
268
            print("\nEXITING...")
269
            raise SystemExit
270
271
272
def check_os_bulk(osurls):
273
    """
274
    Check existence of list of OS links.
275
276
    :param osurls: OS URLs to check.
277
    :type osurls: list(str)
278
    """
279
    for url in osurls:
280
        osav = networkutils.availability(url)
281
        if osav:
282
            break
283
    else:
284
        print("OS VERSION NOT FOUND")
285
        cont = utilities.s2b(input("CONTINUE? Y/N: "))
286
        if not cont:
287
            print("\nEXITING...")
288
            raise SystemExit
289
290
291
def check_radio_single(radiourl, radioversion):
292
    """
293
    Check existence of single radio link.
294
295
    :param radiourl: Radio URL to check.
296
    :type radiourl: str
297
298
    :param radioversion: Radio version.
299
    :type radioversion: str
300
    """
301
    radav = networkutils.availability(radiourl)
302
    if not radav:
303
        print("RADIO VERSION NOT FOUND")
304
        cont = utilities.s2b(input("INPUT MANUALLY? Y/N: "))
305
        if cont:
306
            rad2 = input("RADIO VERSION: ")
307
            radiourl = radiourl.replace(radioversion, rad2)
308
            radioversion = rad2
309
        else:
310
            going = utilities.s2b(input("KEEP GOING? Y/N: "))
311
            if not going:
312
                print("\nEXITING...")
313
                raise SystemExit
314
    return radiourl, radioversion
315
316
317
def check_radio_bulk(radiourls, radioversion):
318
    """
319
    Check existence of list of radio links.
320
321
    :param radiourls: Radio URLs to check.
322
    :type radiourls: list(str)
323
324
    :param radioversion: Radio version.
325
    :type radioversion: str
326
    """
327
    for url in radiourls:
328
        radav = networkutils.availability(url)
329
        if radav:
330
            break
331
    else:
332
        print("RADIO VERSION NOT FOUND")
333
        cont = utilities.s2b(input("INPUT MANUALLY? Y/N: "))
334
        if cont:
335
            rad2 = input("RADIO VERSION: ")
336
            radiourls = [url.replace(radioversion, rad2) for url in radiourls]
337
            radioversion = rad2
338
        else:
339
            going = utilities.s2b(input("KEEP GOING? Y/N: "))
340
            if not going:
341
                print("\nEXITING...")
342
                raise SystemExit
343
    return radiourls, radioversion
344
345
346
def get_baseurls(softwareversion, altsw=None):
347
    """
348
    Generate base URLs for bar links.
349
350
    :param softwareversion: Software version.
351
    :type softwareversion: str
352
353
    :param altsw: Radio software version, if necessary.
354
    :type altsw: str
355
    """
356
    baseurl = networkutils.create_base_url(softwareversion)
357
    alturl = networkutils.create_base_url(altsw) if altsw else None
358
    return baseurl, alturl
359
360
361
def get_sz_executable(compmethod):
362
    """
363
    Get 7z executable.
364
365
    :param compmethod: Compression method.
366
    :type compmethod: str
367
    """
368
    if compmethod != "7z":
369
        szexe = ""
370
    else:
371
        print("CHECKING PRESENCE OF 7ZIP...")
372
        psz = utilities.prep_seven_zip(True)
373
        if psz:
374
            print("7ZIP OK")
375
            szexe = utilities.get_seven_zip(False)
376
        else:
377
            szexe = ""
378
            print("7ZIP NOT FOUND")
379
            cont = utilities.s2b(input("CONTINUE? Y/N "))
380
            if cont:
381
                print("FALLING BACK TO ZIP...")
382
                compmethod = "zip"
383
            else:
384
                print("\nEXITING...")
385
                raise SystemExit  # bye bye
386
    return compmethod, szexe
387
388
389
def test_bar_files(localdir, urllist):
390
    """
391
    Test bar files after download.
392
393
    :param localdir: Directory.
394
    :type localdir: str
395
396
    :param urllist: List of URLs to check.
397
    :type urllist: list(str)
398
    """
399
    brokenlist = []
400
    print("TESTING BAR FILES...")
401
    for file in os.listdir(localdir):
402
        if file.endswith(".bar"):
403
            print("TESTING: {0}".format(file))
404
            thepath = os.path.abspath(os.path.join(localdir, file))
405
            brokens = barutils.bar_tester(thepath)
406
            if brokens is not None:
407
                os.remove(brokens)
408
                for url in urllist:
409
                    if brokens in url:
410
                        brokenlist.append(url)
411
    if brokenlist:
412
        print("SOME FILES ARE BROKEN!")
413
        lprint(brokenlist)
414
        raise SystemExit
415
    else:
416
        print("BAR FILES DOWNLOADED OK")
417
418
419
def test_signed_files(localdir):
420
    """
421
    Test signed files after extract.
422
423
    :param localdir: Directory.
424
    :type localdir: str
425
    """
426
    print("TESTING SIGNED FILES...")
427
    for file in os.listdir(localdir):
428
        if file.endswith(".bar"):
429
            print("TESTING: {0}".format(file))
430
            signname, signhash = barutils.retrieve_sha512(file)
431
            sha512ver = barutils.verify_sha512(signname, signhash)
432
            if not sha512ver:
433
                print("{0} IS BROKEN".format((file)))
434
                break
435
    else:
436
        print("ALL FILES EXTRACTED OK")
437
438
439
def test_loader_files(localdir):
440
    """
441
    Test loader files after creation.
442
443
    :param localdir: Directory.
444
    :type localdir: str
445
    """
446
    if not utilities.is_windows():
447
        pass
448
    else:
449
        print("TESTING LOADER FILES...")
450
        brokens = utilities.verify_bulk_loaders(localdir)
451
        if brokens:
452
            print("BROKEN FILES:")
453
            lprint(brokens)
454
            raise SystemExit
455
        else:
456
            print("ALL FILES CREATED OK")
457
458
459
def test_single_loader(loaderfile):
460
    """
461
    Test single loader file after creation.
462
463
    :param loaderfile: File to check.
464
    :type loaderfile: str
465
    """
466
    if not utilities.is_windows():
467
        pass
468
    else:
469
        print("TESTING LOADER...")
470
        if not utilities.verify_loader_integrity(loaderfile):
471
            print("{0} IS BROKEN!".format(os.path.basename(loaderfile)))
472
            raise SystemExit
473
        else:
474
            print("LOADER CREATED OK")
475
476
477
def enter_to_exit(checkfreeze=True):
478
    """
479
    Press enter to exit a script.
480
481
    :param checkfreeze: If this triggers only in frozen executables. Default is true.
482
    :type checkfreeze: bool
483
    """
484
    greenlight = bool(getattr(sys, 'frozen', False)) if checkfreeze else True
485
    if greenlight:
486
        print("")
487
        smeg = input("Press Enter to exit")
488
        if smeg or not smeg:
489
            raise SystemExit
490
491
492
def prod_avail(results, mailer=False, osversion=None, password=None):
493
    """
494
    Clean availability for production lookups for autolookup script.
495
496
    :param results: Result dict.
497
    :type results: dict(str: str)
498
499
    :param mailer: If we're mailing links. Default is false.
500
    :type mailer: bool
501
502
    :param osversion: OS version.
503
    :type osversion: str
504
505
    :param password: Email password.
506
    :type password: str
507
    """
508
    prel = results['p']
509
    if prel != "SR not in system" and prel is not None:
510
        pav = "PD"
511
        baseurl = networkutils.create_base_url(prel)
512
        avail = networkutils.availability(baseurl)
513
        is_avail = "Available" if avail else "Unavailable"
514
        if avail and mailer:
515
            sqlutils.prepare_sw_db()
516
            if not sqlutils.check_exists(osversion, prel):
517
                rad = utilities.increment(osversion, 1)
518
                linkgen(osversion, rad, prel, temp=True)
519
                smtputils.prep_email(osversion, prel, password)
520
    else:
521
        pav = "  "
522
        is_avail = "Unavailable"
523
    return prel, pav, is_avail
524
525
526
def linkgen(osversion, radioversion=None, softwareversion=None, altsw=None, temp=False):
527
    """
528
    Generate debrick/core/radio links for given OS, radio, software release.
529
530
    :param osversion: OS version, 10.x.y.zzzz.
531
    :type osversion: str
532
533
    :param radioversion: Radio version, 10.x.y.zzzz. Can be guessed.
534
    :type radioversion: str
535
536
    :param softwareversion: Software version, 10.x.y.zzzz. Can be guessed.
537
    :type softwareversion: str
538
539
    :param altsw: Radio software release, if not the same as OS.
540
    :type altsw: str
541
542
    :param temp: If file we write to is temporary.
543
    :type temp: bool
544
    """
545
    radioversion = return_radio_version(osversion, radioversion)
546
    softwareversion, swc = return_sw_checked(softwareversion, osversion)
547
    del swc
548
    if altsw is not None:
549
        altsw, aswc = return_radio_sw_checked(altsw, radioversion)
550
        del aswc
551
    baseurl = networkutils.create_base_url(softwareversion)
552
553
    # List of debrick urls
554
    oses, cores, radios = textgenerator.url_gen(osversion, radioversion, softwareversion)
555
    if altsw is not None:
556
        del radios
557
        dbks, cors, radios = textgenerator.url_gen(osversion, radioversion, altsw)
558
        del dbks
559
        del cors
560
561
    avlty = networkutils.availability(baseurl)
562
    textgenerator.write_links(softwareversion, osversion, radioversion, oses, cores, radios,
563
                              avlty, False, None, temp, altsw)
564
565
566
def clean_swrel(swrelset):
567
    """
568
    Clean a list of software release lookups.
569
570
    :param swrelset: List of software releases.
571
    :type swrelset: set(str)
572
    """
573
    for i in swrelset:
574
        if i != "SR not in system" and i is not None:
575
            swrelease = i
576
            break
577
    else:
578
        swrelease = ""
579
    return swrelease
580
581
582
def autolookup_printer(out, avail, log=False, quiet=False, record=None):
583
    """
584
    Print autolookup results, logging if specified.
585
586
    :param out: Output block.
587
    :type out: str
588
589
    :param avail: Availability. Can be "Available" or "Unavailable".
590
    :type avail: str
591
592
    :param log: If we're logging to file.
593
    :type log: bool
594
595
    :param quiet: If we only note available entries.
596
    :type quiet: bool
597
598
    :param record: If we're logging, the file to log to.
599
    :type record: str
600
    """
601
    if not quiet:
602
        avail = "Available"  # force things
603
    if avail == "Available":
604
        if log:
605
            with open(record, "a") as rec:
606
                rec.write("{0}\n".format(out))
607
        print(out)
608
609
610
def autolookup_output(osversion, swrelease, avail, avpack, sql=False):
611
    """
612
    Prepare autolookup block, and add to SQL database.
613
614
    :param osversion: OS version.
615
    :type osversion: str
616
617
    :param swrelease: Software release.
618
    :type swrelease: str
619
620
    :param avail: "Unavailable" or "Available".
621
    :type avail: str
622
623
    :param avpack: Availabilities: alpha 1 and 2, beta 1 and 2, production.
624
    :type avpack: list(str)
625
626
    :param sql: If we're adding this to our SQL database.
627
    :type sql: bool
628
    """
629
    if sql:
630
        sqlutils.prepare_sw_db()
631
        if not sqlutils.check_exists(osversion, swrelease):
632
            sqlutils.insert(osversion, swrelease, avail.lower())
633
    avblok = "[{0}|{1}|{2}|{3}|{4}]".format(*avpack)
1 ignored issue
show
Coding Style introduced by
Usage of * or ** arguments should usually be done with care.

Generally, there is nothing wrong with usage of * or ** arguments. For readability of the code base, we suggest to not over-use these language constructs though.

For more information, we can recommend this blog post from Ned Batchelder including its comments which also touches this aspect.

Loading history...
634
    out = "OS {0} - SR {1} - {2} - {3}".format(osversion, swrelease, avblok, avail)
635
    return out
636
637
638
def export_cchecker(files, npc, hwid, osv, radv, swv, upgrade=False, forced=None):
639
    """
640
    Write carrierchecker lookup links to file.
641
642
    :param files: List of file URLs.
643
    :type files: list(str)
644
645
    :param npc: MCC + MNC (ex. 302220).
646
    :type npc: int
647
648
    :param hwid: Device hardware ID.
649
    :type hwid: str
650
651
    :param osv: OS version.
652
    :type osv: str
653
654
    :param radv: Radio version.
655
    :type radv: str
656
657
    :param swv: Software release.
658
    :type swv: str
659
660
    :param upgrade: Whether or not to use upgrade files. Default is false.
661
    :type upgrade: bool
662
663
    :param forced: Force a software release. None to go for latest.
664
    :type forced: str
665
    """
666
    if files:
667
        if not upgrade:
668
            newfiles = networkutils.carrier_query(npc, hwid, True, False, forced)
669
            cleanfiles = newfiles[3]
670
        else:
671
            cleanfiles = files
672
        osurls, coreurls, radiourls = textgenerator.url_gen(osv, radv, swv)
673
        stoppers = ["8960", "8930", "8974", "m5730", "winchester"]
674
        finals = [link for link in cleanfiles if all(word not in link for word in stoppers)]
675
        textgenerator.write_links(swv, osv, radv, osurls, coreurls, radiourls, True, True, finals)
676
        print("\nFINISHED!!!")
677
    else:
678
        print("CANNOT EXPORT, NO SOFTWARE RELEASE")
679
680
681
def generate_blitz_links(files, osv, radv, swv):
682
    """
683
    Generate blitz URLs (i.e. all OS and radio links).
684
    :param files: List of file URLs.
685
    :type files: list(str)
686
687
    :param osv: OS version.
688
    :type osv: str
689
690
    :param radv: Radio version.
691
    :type radv: str
692
693
    :param swv: Software release.
694
    :type swv: str
695
    """
696
    baseurl = networkutils.create_base_url(swv)
697
    suffix = "nto+armle-v7+signed.bar"
698
    coreurls = [
699
        "{0}/winchester.factory_sfi-{1}-{2}".format(baseurl, osv, suffix),
700
        "{0}/qc8960.factory_sfi-{1}-{2}".format(baseurl, osv, suffix),
701
        "{0}/qc8960.factory_sfi_hybrid_qc8x30-{1}-{2}".format(baseurl, osv, suffix),
702
        "{0}/qc8974.factory_sfi_hybrid_qc8974-{1}-{2}".format(baseurl, osv, suffix)
703
    ]
704
    radiourls = [
705
        "{0}/m5730-{1}-{2}".format(baseurl, radv, suffix),
706
        "{0}/qc8960-{1}-{2}".format(baseurl, radv, suffix),
707
        "{0}/qc8960.wtr-{1}-{2}".format(baseurl, radv, suffix),
708
        "{0}/qc8960.wtr5-{1}-{2}".format(baseurl, radv, suffix),
709
        "{0}/qc8930.wtr5-{1}-{2}".format(baseurl, radv, suffix),
710
        "{0}/qc8974.wtr2-{1}-{2}".format(baseurl, radv, suffix)
711
    ]
712
    return files + coreurls + radiourls
713
714
715
def package_blitz(bardir, swv):
716
    """
717
    Package and verify a blitz package.
718
719
    :param bardir: Path to folder containing bar files.
720
    :type bardir: str
721
722
    :param swv: Software version.
723
    :type swv: str
724
    """
725
    print("\nCREATING BLITZ...")
726
    barutils.create_blitz(bardir, swv)
727
    print("\nTESTING BLITZ...")
728
    zipver = barutils.zip_verify("Blitz-{0}.zip".format(swv))
0 ignored issues
show
Bug introduced by
The Module bbarchivist.barutils does not seem to have a member named zip_verify.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
729
    if not zipver:
730
        print("BLITZ FILE IS BROKEN")
731
        raise SystemExit
732
    else:
733
        shutil.rmtree(bardir)
734
735
736
def purge_dross(files):
737
    """
738
    Get rid of Nuance/retaildemo apps in a list of apps.
739
740
    :param files: List of URLs.
741
    :type files: list(str)
742
    """
743
    crap = [
744
        "sin_ji",
745
        "common",
746
        "xander",
747
        "kate",
748
        "ava",
749
        "amelie",
750
        "thomas",
751
        "anna",
752
        "alice",
753
        "kyoko",
754
        "sora",
755
        "li_li",
756
        "mei_jia",
757
        "nora",
758
        "zosia",
759
        "luciana",
760
        "joana",
761
        "milena",
762
        "marisol",
763
        "angelica",
764
        "arw",
765
        "bgb",
766
        "cah",
767
        "czc",
768
        "dad",
769
        "dun",
770
        "ena",
771
        "eni",
772
        "fif",
773
        "frc",
774
        "frf",
775
        "ged",
776
        "grg",
777
        "iti",
778
        "jpj",
779
        "kok",
780
        "mnc",
781
        "mnt",
782
        "non",
783
        "plp",
784
        "ptb",
785
        "ptp",
786
        "rur",
787
        "spe",
788
        "spm",
789
        "sws",
790
        "trt",
791
        "retaildemo"]
792
    files2 = [file for file in files if all(word not in file for word in crap)]
793
    return files2
794
795
796
def slim_preamble(appname):
797
    """
798
    Standard app name header.
799
800
    :param appname: Name of app.
801
    :type appname: str
802
    """
803
    print("~~~{0} VERSION {1}~~~".format(appname.upper(), shortversion()))
804
805
806
def lprint(iterable):
807
    """
808
    A oneliner for 'for item in x: print item'.
809
810
    :param iterable: Iterable to print.
811
    :type iterable: list/tuple
812
    """
813
    for item in iterable:
814
        print(item)
815
816
817
def standard_preamble(appname, osversion, softwareversion, radioversion, altsw=None):
818
    """
819
    Standard app name, OS, radio and software (plus optional radio software) print block.
820
821
    :param appname: Name of app.
822
    :type appname: str
823
824
    :param osversion: OS version, 10.x.y.zzzz. Required.
825
    :type osversion: str
826
827
    :param radioversion: Radio version, 10.x.y.zzzz. Can be guessed.
828
    :type radioversion: str
829
830
    :param softwareversion: Software release, 10.x.y.zzzz. Can be guessed.
831
    :type softwareversion: str
832
833
    :param altsw: Radio software release, if not the same as OS.
834
    :type altsw: str
835
    """
836
    slim_preamble(appname)
837
    print("OS VERSION: {0}".format(osversion))
838
    print("OS SOFTWARE VERSION: {0}".format(softwareversion))
839
    print("RADIO VERSION: {0}".format(radioversion))
840
    if altsw is not None:
841
        print("RADIO SOFTWARE VERSION: {0}".format(altsw))
842
843
844
def verify_gpg_credentials():
845
    """
846
    Read GPG key/pass from file, verify if incomplete.
847
    """
848
    gpgkey, gpgpass = hashutils.gpg_config_loader()
849
    if gpgkey is None or gpgpass is None:
850
        print("NO PGP KEY/PASS FOUND")
851
        cont = utilities.s2b(input("CONTINUE (Y/N)?: "))
852
        if cont:
853
            if gpgkey is None:
854
                gpgkey = input("PGP KEY (0x12345678): ")
855
                if not gpgkey.startswith("0x"):
856
                    gpgkey = "0x{0}".format(gpgkey)   # add preceding 0x
857
            if gpgpass is None:
858
                gpgpass = getpass.getpass(prompt="PGP PASSPHRASE: ")
859
                writebool = utilities.s2b(input("SAVE PASSPHRASE (Y/N)?:"))
860
            else:
861
                writebool = False
862
            gpgpass2 = gpgpass if writebool else None
863
            hashutils.gpg_config_writer(gpgkey, gpgpass2)
864
        else:
865
            gpgkey = None
866
    return gpgkey, gpgpass
867
868
869
def bulk_hash(dirs, compressed=True, deleted=True, radios=True, hashdict=None):
870
    """
871
    Hash files in several folders based on flags.
872
873
    :param dirs: Folders: [OS_bars, radio_bars, OS_exes, radio_exes, OS_zips, radio_zips]
874
    :type dirs: list(str)
875
876
    :param compressed: Whether to hash compressed files. True by default.
877
    :type compressed: bool
878
879
    :param deleted: Whether to delete uncompressed files. True by default.
880
    :type deleted: bool
881
882
    :param radios: Whether to hash radio autoloaders. True by default.
883
    :type radios: bool
884
885
    :param hashdict: Dictionary of hash rules, in ~\bbarchivist.ini.
886
    :type hashdict: dict({str: bool})
887
    """
888
    print("HASHING LOADERS...")
889
    if compressed:
890
        hashutils.verifier(dirs[4], hashdict)
891
        if radios:
892
            hashutils.verifier(dirs[5], hashdict)
893
    if not deleted:
894
        hashutils.verifier(dirs[2], hashdict)
895
        if radios:
896
            hashutils.verifier(dirs[3], hashdict)
897
898
899
def bulk_verify(dirs, compressed=True, deleted=True, radios=True):
900
    """
901
    Verify files in several folders based on flags.
902
903
    :param dirs: Folders: [OS_bars, radio_bars, OS_exes, radio_exes, OS_zips, radio_zips]
904
    :type dirs: list(str)
905
906
    :param compressed: Whether to hash compressed files. True by default.
907
    :type compressed: bool
908
909
    :param deleted: Whether to delete uncompressed files. True by default.
910
    :type deleted: bool
911
912
    :param radios: Whether to hash radio autoloaders. True by default.
913
    :type radios: bool
914
    """
915
    gpgkey, gpgpass = verify_gpg_credentials()
916
    if gpgpass is not None and gpgkey is not None:
917
        print("VERIFYING LOADERS...")
918
        print("KEY: {0}".format(gpgkey))
919
        if compressed:
920
            hashutils.gpgrunner(dirs[4], gpgkey, gpgpass, True)
921
            if radios:
922
                hashutils.gpgrunner(dirs[5], gpgkey, gpgpass, True)
923
        if not deleted:
924
            hashutils.gpgrunner(dirs[2], gpgkey, gpgpass, True)
925
            if radios:
926
                hashutils.gpgrunner(dirs[3], gpgkey, gpgpass, True)
927