Completed
Push — master ( fc852d...be5f5b )
by John
01:18
created

archivist_gethashes()   B

Complexity

Conditions 3

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
dl 0
loc 34
rs 8.8571
c 0
b 0
f 0
1
#!/usr/bin/env python3
2
"""Download bar files, create autoloaders."""
3
4
import os  # filesystem read
5
import sys  # load arguments
6
from bbarchivist import scriptutils  # script stuff
7
from bbarchivist import utilities  # input validation
8
from bbarchivist import decorators  # timer
9
from bbarchivist import barutils  # file/folder work
10
from bbarchivist import archiveutils  # archive work
11
from bbarchivist import networkutils  # download/lookup
12
from bbarchivist import loadergen  # cap, in Python
13
from bbarchivist import hashutils  # hashes, GPG
14
15
__author__ = "Thurask"
16
__license__ = "WTFPL v2"
17
__copyright__ = "Copyright 2015-2016 Thurask"
18
19
20
@decorators.timer
21
def grab_args():
22
    """
23
    Parse arguments from argparse/questionnaire.
24
25
    Invoke :func:`archivist.archivist_main` with those arguments.
26
    """
27
    if len(sys.argv) > 1:
28
        parser = scriptutils.default_parser("bb-archivist", "Create many autoloaders",
29
                                            ("folder", "osr"))
30
        negategroup = parser.add_argument_group(
31
            "negators",
32
            "Disable program functionality")
33
        negategroup.add_argument(
34
            "-no",
35
            "--no-download",
36
            dest="download",
37
            help="Don't download files",
38
            action="store_false",
39
            default=True)
40
        negategroup.add_argument(
41
            "-ni",
42
            "--no-integrity",
43
            dest="integrity",
44
            help="Don't test bar files after download",
45
            action="store_false",
46
            default=True)
47
        negategroup.add_argument(
48
            "-nx",
49
            "--no-extract",
50
            dest="extract",
51
            help="Don't extract bar files",
52
            action="store_false",
53
            default=True)
54
        negategroup.add_argument(
55
            "-nr",
56
            "--no-radios",
57
            dest="radloaders",
58
            help="Don't make radio autoloaders",
59
            action="store_false",
60
            default=True)
61
        negategroup.add_argument(
62
            "-ns",
63
            "--no-rmsigned",
64
            dest="signed",
65
            help="Don't remove signed files",
66
            action="store_false",
67
            default=True)
68
        negategroup.add_argument(
69
            "-nc",
70
            "--no-compress",
71
            dest="compress",
72
            help="Don't compress loaders",
73
            action="store_false",
74
            default=True)
75
        negategroup.add_argument(
76
            "-nd",
77
            "--no-delete",
78
            dest="delete",
79
            help="Don't delete uncompressed loaders",
80
            action="store_false",
81
            default=True)
82
        negategroup.add_argument(
83
            "-nv",
84
            "--no-verify",
85
            dest="verify",
86
            help="Don't verify created loaders",
87
            action="store_false",
88
            default=True)
89
        if not getattr(sys, 'frozen', False):
90
            parser.add_argument(
91
                "-g",
92
                "--gpg",
93
                dest="gpg",
94
                help="Enable GPG signing. Set up GnuPG.",
95
                action="store_true",
96
                default=False)
97
        parser.add_argument(
98
            "-r",
99
            "--radiosw",
100
            dest="altsw",
101
            metavar="SW",
102
            help="Radio software version; use without software to guess",
103
            nargs="?",
104
            const="checkme",
105
            default=None)
106
        parser.add_argument(
107
            "-m",
108
            "--method",
109
            dest="method",
110
            metavar="METHOD",
111
            help="Compression method",
112
            nargs="?",
113
            type=utilities.valid_method,
114
            default=None)
115
        parser.add_argument(
116
            "-c",
117
            "--core",
118
            dest="core",
119
            help="Make core/radio loaders",
120
            default=False,
121
            action="store_true")
122
        parser.add_argument(
123
            "-o",
124
            "--old-style",
125
            dest="oldstyle",
126
            help="Make old-style checksum files",
127
            default=False,
128
            action="store_true")
129
        parser.set_defaults(compmethod="7z")
130
        args = parser.parse_args(sys.argv[1:])
131
        if args.folder is None:
132
            args.folder = os.getcwd()
133
        if getattr(sys, 'frozen', False):
134
            args.gpg = False
135
            hashdict = hashutils.verifier_config_loader(os.getcwd())
136
            args.method = "7z"
137
        else:
138
            hashdict = hashutils.verifier_config_loader()
139
        hashutils.verifier_config_writer(hashdict)
140
        if args.method is None:
141
            compmethod = archiveutils.compress_config_loader()
142
            archiveutils.compress_config_writer(compmethod)
143
        else:
144
            compmethod = args.method
145
        archivist_main(args.os, args.radio, args.swrelease,
146
                       args.folder, args.radloaders,
147
                       args.compress, args.delete, args.verify,
148
                       hashdict, args.download,
149
                       args.extract, args.signed, compmethod, args.gpg,
150
                       args.integrity, args.altsw, args.core, args.oldstyle)
151
    else:
152
        questionnaire()
153
154
155
def questionnaire():
156
    """
157
    Questions to ask if no arguments given.
158
    """
159
    localdir = os.getcwd()
160
    osversion = input("OS VERSION (REQUIRED): ")
161
    radioversion = input("RADIO VERSION (PRESS ENTER TO GUESS): ")
162
    radioversion = None if not radioversion else radioversion
163
    softwareversion = input("OS SOFTWARE RELEASE (PRESS ENTER TO GUESS): ")
164
    softwareversion = None if not softwareversion else softwareversion
165
    altcheck = utilities.s2b(input("USING ALTERNATE RADIO (Y/N)?: "))
166
    if altcheck:
167
        altsw = input("RADIO SOFTWARE RELEASE (PRESS ENTER TO GUESS): ")
168
        if not altsw:
169
            altsw = "checkme"
170
    else:
171
        altsw = None
172
    radios = utilities.s2b(input("CREATE RADIO LOADERS (Y/N)?: "))
173
    compressed = utilities.s2b(input("COMPRESS LOADERS (Y/N)?: "))
174
    deleted = utilities.s2b(input("DELETE UNCOMPRESSED LOADERS (Y/N)?: ")) if compressed else False
175
    hashed = utilities.s2b(input("GENERATE HASHES (Y/N)?: "))
176
    if getattr(sys, 'frozen', False):
177
        hashdict = hashutils.verifier_config_loader(os.getcwd())
178
        compmethod = "7z"
179
    else:
180
        hashdict = hashutils.verifier_config_loader()
181
        hashutils.verifier_config_writer(hashdict)
182
        compmethod = archiveutils.compress_config_loader()
183
    print(" ")
184
    archivist_main(osversion, radioversion, softwareversion,
185
                   localdir, radios, compressed, deleted, hashed,
186
                   hashdict, download=True, extract=True, signed=True,
187
                   compmethod=compmethod, gpg=False, integrity=True,
188
                   altsw=None, core=False, oldstyle=False)
189
190
191
def archivist_checksw(baseurl, softwareversion, swchecked, alturl, altsw, altchecked):
192
    """
193
    Check availability of software releases.
194
195
    :param baseurl: Base URL for download links.
196
    :type baseurl: str
197
198
    :param softwareversion: Software release, 10.x.y.zzzz. Can be guessed.
199
    :type softwareversion: str
200
201
    :param swchecked: If we checked the sw release already.
202
    :type swchecked: bool
203
204
    :param alturl: Alternate radio base URL.
205
    :type alturl: str
206
207
    :param altsw: Radio software release, if not the same as OS.
208
    :type altsw: str
209
210
    :param altchecked: If we checked the radio sw release already.
211
    :type altchecked: bool
212
    """
213
    scriptutils.check_sw(baseurl, softwareversion, swchecked)
214
    if altsw:
215
        scriptutils.check_radio_sw(alturl, altsw, altchecked)
216
217
218
def archivist_download(download=True, osurls, radiourls, localdir):
219
    """
220
    Download function.
221
222
    :param download: Whether to download bar files. True by default.
223
    :type download: bool
224
225
    :param osurls: OS file list.
226
    :type osurls: list(str)
227
228
    :param radiourls: Radio file list.
229
    :type radiourls: list(str)
230
231
    :param localdir: Working directory. Local by default.
232
    :type localdir: str
233
    """
234
    if download:
235
        print("BEGIN DOWNLOADING...")
236
        networkutils.download_bootstrap(radiourls + osurls, localdir, 3)
237
        print("ALL FILES DOWNLOADED")
238
239
240
def archivist_integritybars(integrity, osurls, radiourls):
241
    """
242
    Check integrity of bar files, redownload if necessary.
243
244
    :param integrity: Whether to test downloaded files. True by default.
245
    :type integrity: bool
246
247
    :param osurls: OS file list.
248
    :type osurls: list(str)
249
250
    :param radiourls: Radio file list.
251
    :type radiourls: list(str)
252
    """
253
    if integrity:
254
        urllist = osurls + radiourls
255
        scriptutils.test_bar_files(localdir, urllist)
256
257
258
def archivist_extractbars(extract, localdir):
259
    """
260
    Extract signed files from bar files.
261
262
    :param extract: Whether to extract bar files. True by default.
263
    :type extract: bool
264
265
    :param localdir: Working directory. Local by default.
266
    :type localdir: str
267
    """
268
    if extract:
269
        print("EXTRACTING...")
270
        barutils.extract_bars(localdir)
271
272
273
def archivist_integritysigned(integrity, localdir):
274
    """
275
    Check integrity of signed files.
276
277
    :param integrity: Whether to test downloaded files. True by default.
278
    :type integrity: bool
279
280
    :param localdir: Working directory. Local by default.
281
    :type localdir: str
282
    """
283
    if integrity:
284
        scriptutils.test_signed_files(localdir)
285
286
287
def archivist_movebars(dirs, localdir):
288
    """
289
    Move bar files.
290
291
    :param dirs: List of OS/radio bar/loader/zipped folders.
292
    :type dirs: list(str)
293
294
    :param localdir: Working directory. Local by default.
295
    :type localdir: str
296
    """
297
    print("MOVING BAR FILES...")
298
    barutils.move_bars(localdir, dirs[0], dirs[1])
299
300
301
def archivist_generateloaders(osversion, radioversion, radios, localdir, altsw, core):
302
    """
303
    Generate loaders.
304
305
    :param osversion: OS version, 10.x.y.zzzz. Required.
306
    :type osversion: str
307
308
    :param radioversion: Radio version, 10.x.y.zzzz. Can be guessed.
309
    :type radioversion: str
310
311
    :param radios: Whether to create radio autoloaders. True by default.
312
    :type radios: bool
313
314
    :param localdir: Working directory. Local by default.
315
    :type localdir: str
316
317
    :param altsw: Radio software release, if not the same as OS.
318
    :type altsw: str
319
320
    :param core: Whether to create a core/radio loader. Default is false.
321
    :type core: bool
322
    """
323
    print("GENERATING LOADERS...")
324
    altradio = altsw is not None
325
    loadergen.generate_loaders(osversion, radioversion, radios, localdir, altradio, core)
326
327
328
def archivist_integrityloaders(integrity, localdir):
329
    """
330
    Check integrity of build loaders.
331
332
    :param integrity: Whether to test downloaded files. True by default.
333
    :type integrity: bool
334
335
    :param localdir: Working directory. Local by default.
336
    :type localdir: str
337
    """
338
    if integrity:
339
        scriptutils.test_loader_files(localdir)
340
341
342
def archivist_removesigned(signed, localdir):
343
    """
344
    Remove signed files.
345
346
    :param signed: Whether to delete signed files. True by default.
347
    :type signed: bool
348
349
    :param localdir: Working directory. Local by default.
350
    :type localdir: str
351
    """
352
    if signed:
353
        print("REMOVING SIGNED FILES...")
354
        barutils.remove_signed_files(localdir)
355
356
357
def archivist_compressor(compressed, integrity, localdir, compmethod, szexe):
358
    """
359
    Compress and optionally verify loaders.
360
361
    :param compressed: Whether to compress files. True by default.
362
    :type compressed: bool
363
364
    :param integrity: Whether to test downloaded files. True by default.
365
    :type integrity: bool
366
367
    :param localdir: Working directory. Local by default.
368
    :type localdir: str
369
370
    :param compmethod: Compression method. Default is "7z", fallback "zip".
371
    :type compmethod: str
372
373
    :param szexe: Path to 7z executable.
374
    :type szexe: str
375
    """
376
    if compressed:
377
        print("COMPRESSING...")
378
        archiveutils.compress(localdir, compmethod, szexe, True)
379
        if integrity:
380
            print("TESTING ARCHIVES...")
381
            archiveutils.verify(localdir, compmethod, szexe, True)
382
383
384
def archivist_moveloaders(dirs, localdir):
385
    """
386
    Move loaders.
387
388
    :param dirs: List of OS/radio bar/loader/zipped folders.
389
    :type dirs: list(str)
390
391
    :param localdir: Working directory. Local by default.
392
    :type localdir: str
393
    """
394
    print("MOVING LOADERS...")
395
    barutils.move_loaders(localdir, dirs[2], dirs[3], dirs[4], dirs[5])
396
397
398
def archivist_gethashes(dirs, hashed, compressed, deleted, radios, osversion, radioversion, softwareversion, oldstyle):
399
    """
400
    Make new-style info files.
401
402
    :param dirs: List of OS/radio bar/loader/zipped folders.
403
    :type dirs: list(str)
404
405
    :param hashed: Whether to hash files. True by default.
406
    :type hashed: bool
407
408
    :param compressed: Whether to compress files. True by default.
409
    :type compressed: bool
410
411
    :param deleted: Whether to delete uncompressed files. True by default.
412
    :type deleted: bool
413
414
    :param radios: Whether to create radio autoloaders. True by default.
415
    :type radios: bool
416
417
    :param osversion: OS version, 10.x.y.zzzz. Required.
418
    :type osversion: str
419
420
    :param radioversion: Radio version, 10.x.y.zzzz. Can be guessed.
421
    :type radioversion: str
422
423
    :param softwareversion: Software release, 10.x.y.zzzz. Can be guessed.
424
    :type softwareversion: str
425
426
    :param oldstyle: Whether to make old-style checksum files. Default is false.
427
    :type oldstyle: bool
428
    """
429
    if hashed and not oldstyle:
430
        scriptutils.bulk_info(dirs, osversion, compressed, deleted, radios,
431
                                  radioversion, softwareversion)
432
433
def archivist_getoldhashes(dirs, hashed, compressed, deleted, radios, hashdict, oldstyle):
434
    """
435
    Make old-style checksum files.
436
437
    :param dirs: List of OS/radio bar/loader/zipped folders.
438
    :type dirs: list(str)
439
440
    :param hashed: Whether to hash files. True by default.
441
    :type hashed: bool
442
443
    :param compressed: Whether to compress files. True by default.
444
    :type compressed: bool
445
446
    :param deleted: Whether to delete uncompressed files. True by default.
447
    :type deleted: bool
448
449
    :param radios: Whether to create radio autoloaders. True by default.
450
    :type radios: bool
451
452
    :param hashdict: Dictionary of hash rules, in ~\bbarchivist.ini.
453
    :type hashdict: dict({str: bool})
454
455
    :param oldstyle: Whether to make old-style checksum files. Default is false.
456
    :type oldstyle: bool
457
    """
458
    if hashed and oldstyle:
459
        scriptutils.bulk_hash(dirs, compressed, deleted, radios, hashdict)
460
461
462
def archivist_gpg(gpg, dirs, compressed, deleted, radios):
463
    """
464
    GPG-sign everything.
465
466
    :param gpg: Whether to use GnuPG verification. False by default.
467
    :type gpg: bool
468
469
    :param dirs: List of OS/radio bar/loader/zipped folders.
470
    :type dirs: list(str)
471
472
    :param compressed: Whether to compress files. True by default.
473
    :type compressed: bool
474
475
    :param deleted: Whether to delete uncompressed files. True by default.
476
    :type deleted: bool
477
478
    :param radios: Whether to create radio autoloaders. True by default.
479
    :type radios: bool
480
    """
481
    if gpg:
482
        scriptutils.bulk_verify(dirs, compressed, deleted, radios)
483
484
485
def archivist_deleteuncompressed(dirs, deleted, radios):
486
    """
487
    Delete uncompressed loaders.
488
489
    :param dirs: List of OS/radio bar/loader/zipped folders.
490
    :type dirs: list(str)
491
492
    :param deleted: Whether to delete uncompressed files. True by default.
493
    :type deleted: bool
494
495
    :param radios: Whether to create radio autoloaders. True by default.
496
    :type radios: bool
497
    """
498
    if deleted:
499
        print("DELETING UNCOMPRESSED LOADERS...")
500
        barutils.remove_unpacked_loaders(dirs[2], dirs[3], radios)
501
502
503
def archivist_removeemptyfolders(localdir):
504
    """
505
    Delete empty folders.
506
507
    :param localdir: Working directory. Local by default.
508
    :type localdir: str
509
    """
510
    print("REMOVING EMPTY FOLDERS...")
511
    barutils.remove_empty_folders(localdir)
512
513
514
def archivist_main(osversion, radioversion=None, softwareversion=None,
515
                   localdir=None, radios=True, compressed=True, deleted=True,
516
                   hashed=True, hashdict=None, download=True,
517
                   extract=True, signed=True, compmethod="7z",
518
                   gpg=False, integrity=True, altsw=None,
519
                   core=False, oldstyle=False):
520
    """
521
    Wrap around multi-autoloader creation code.
522
    Some combination of creating, downloading, hashing,
523
    compressing and moving autoloaders.
524
525
    :param osversion: OS version, 10.x.y.zzzz. Required.
526
    :type osversion: str
527
528
    :param radioversion: Radio version, 10.x.y.zzzz. Can be guessed.
529
    :type radioversion: str
530
531
    :param softwareversion: Software release, 10.x.y.zzzz. Can be guessed.
532
    :type softwareversion: str
533
534
    :param localdir: Working directory. Local by default.
535
    :type localdir: str
536
537
    :param radios: Whether to create radio autoloaders. True by default.
538
    :type radios: bool
539
540
    :param compressed: Whether to compress files. True by default.
541
    :type compressed: bool
542
543
    :param deleted: Whether to delete uncompressed files. True by default.
544
    :type deleted: bool
545
546
    :param hashed: Whether to hash files. True by default.
547
    :type hashed: bool
548
549
    :param hashdict: Dictionary of hash rules, in ~\bbarchivist.ini.
550
    :type hashdict: dict({str: bool})
551
552
    :param download: Whether to download bar files. True by default.
553
    :type download: bool
554
555
    :param extract: Whether to extract bar files. True by default.
556
    :type extract: bool
557
558
    :param signed: Whether to delete signed files. True by default.
559
    :type signed: bool
560
561
    :param compmethod: Compression method. Default is "7z", fallback "zip".
562
    :type compmethod: str
563
564
    :param gpg: Whether to use GnuPG verification. False by default.
565
    :type gpg: bool
566
567
    :param integrity: Whether to test downloaded files. True by default.
568
    :type integrity: bool
569
570
    :param altsw: Radio software release, if not the same as OS.
571
    :type altsw: str
572
573
    :param core: Whether to create a core/radio loader. Default is false.
574
    :type core: bool
575
576
    :param oldstyle: Whether to make old-style checksum files. Default is false.
577
    :type oldstyle: bool
578
    """
579
    radioversion = scriptutils.return_radio_version(osversion, radioversion)
580
    softwareversion, swchecked = scriptutils.return_sw_checked(softwareversion, osversion)
581
    if altsw == "checkme":
582
        altsw, altchecked = scriptutils.return_radio_sw_checked(altsw, radioversion)
583
    if localdir is None:
584
        localdir = os.getcwd()
585
    if hashed and hashdict is None:
586
        hashdict = hashutils.verifier_config_loader()
587
        hashutils.verifier_config_writer(hashdict)
588
    scriptutils.standard_preamble("archivist", osversion, softwareversion, radioversion, altsw)
589
    # Generate download URLs
590
    baseurl, alturl = scriptutils.get_baseurls(softwareversion, altsw)
591
    osurls, radiourls, cores = utilities.generate_urls(baseurl, osversion, radioversion, True)
592
    osurls = cores if core else osurls
593
    for idx, url in enumerate(osurls):
594
        if "qc8960.factory_sfi" in url:
595
            vzwurl = url
596
            vzwindex = idx
597
            break
598
    if not networkutils.availability(vzwurl):
599
        osurls[vzwindex] = osurls[vzwindex].replace("qc8960.factory_sfi", "qc8960.verizon_sfi")
600
    osurls = list(set(osurls))  # pop duplicates
601
    if altsw:
602
        radiourls2 = [x.replace(baseurl, alturl) for x in radiourls]
603
        radiourls = radiourls2
604
        del radiourls2
605
    archivist_checksw(baseurl, softwareversion, swchecked, alturl, altsw, altchecked)
606
    # Check availability of OS, radio
607
    scriptutils.check_os_bulk(osurls)
608
    radiourls, radioversion = scriptutils.check_radio_bulk(radiourls, radioversion)
609
    # Get 7z executable
610
    compmethod, szexe = scriptutils.get_sz_executable(compmethod)
611
    # Make dirs: bd_o, bd_r, ld_o, ld_r, zd_o, zd_r
612
    dirs = barutils.make_dirs(localdir, osversion, radioversion)
613
    archivist_download(download, osurls, radiourls, localdir)
614
    archivist_integritybars(integrity, osurls, radiourls)
615
    archivist_extractbars(extract, localdir)
616
    archivist_integritysigned(extract, localdir)
617
    archivist_movebars(dirs, localdir)
618
    archivist_generateloaders(osversion, radioversion, radios, localdir, altsw, core)
619
    archivist_integrityloaders(integrity, localdir)
620
    archivist_removesigned(signed, localdir)
621
    archivist_compressor(compressed, integrity, localdir, compmethod, szexe)
622
    archivist_moveloaders(dirs, localdir)
623
    archivist_gethashes(dirs, hashed, compressed, deleted, radios, osversion, radioversion, softwareversion, oldstyle)
624
    archivist_getoldhashes(dirs, hashed, compressed, deleted, radios, hashdict, oldstyle)
625
    archivist_gpg(gpg, dirs, compressed, deleted, radios)
626
    archivist_deleteuncompressed(dirs, deleted, radios)
627
    archivist_removeemptyfolders(localdir)
628
    print("\nFINISHED!")
629
630
631
if __name__ == "__main__":
632
    grab_args()
633
    decorators.enter_to_exit(False)
634