Completed
Push — master ( 1f2fd3...fc852d )
by John
01:20
created

archivist_compressor()   B

Complexity

Conditions 3

Size

Total Lines 25

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
dl 0
loc 25
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
    # 
0 ignored issues
show
Coding Style introduced by
Trailing whitespace
Loading history...
214
    scriptutils.check_sw(baseurl, softwareversion, swchecked)
215
    if altsw:
216
        scriptutils.check_radio_sw(alturl, altsw, altchecked)
217
218
219
def archivist_download(download=True):
220
    """
221
    Download function.
222
223
    :param download: Whether to download bar files. True by default.
224
    :type download: bool
225
    """
226
    if download:
227
        print("BEGIN DOWNLOADING...")
228
        networkutils.download_bootstrap(radiourls + osurls, localdir, 3)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'radiourls'
Loading history...
Comprehensibility Best Practice introduced by
Undefined variable 'osurls'
Loading history...
Comprehensibility Best Practice introduced by
Undefined variable 'localdir'
Loading history...
229
        print("ALL FILES DOWNLOADED")
230
231
232
def archivist_integritybars(integrity, osurls, radiourls):
233
    """
234
    Check integrity of bar files, redownload if necessary.
235
236
    :param integrity: Whether to test downloaded files. True by default.
237
    :type integrity: bool
238
239
    :param osurls: OS file list.
240
    :type osurls: list(str)
241
242
    :param radiourls: Radio file list.
243
    :type radiourls: list(str)
244
    """
245
    if integrity:
246
        urllist = osurls + radiourls
247
        scriptutils.test_bar_files(localdir, urllist)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'localdir'
Loading history...
248
249
250
def archivist_extractbars(extract, localdir):
251
    """
252
    Extract signed files from bar files.
253
254
    :param extract: Whether to extract bar files. True by default.
255
    :type extract: bool
256
257
    :param localdir: Working directory. Local by default.
258
    :type localdir: str
259
    """
260
    if extract:
261
        print("EXTRACTING...")
262
        barutils.extract_bars(localdir)
263
264
265
def archivist_integritysigned(integrity, localdir):
266
    """
267
    Check integrity of signed files.
268
269
    :param integrity: Whether to test downloaded files. True by default.
270
    :type integrity: bool
271
272
    :param localdir: Working directory. Local by default.
273
    :type localdir: str
274
    """
275
    if integrity:
276
        scriptutils.test_signed_files(localdir)
277
278
279
def archivist_movebars(dirs, localdir):
280
    """
281
    Move bar files.
282
283
    :param dirs: List of OS/radio bar/loader/zipped folders.
284
    :type dirs: list(str)
285
286
    :param localdir: Working directory. Local by default.
287
    :type localdir: str
288
    """
289
    print("MOVING BAR FILES...")
290
    barutils.move_bars(localdir, dirs[0], dirs[1])
291
292
293
def archivist_generateloaders(osversion, radioversion, radios, localdir, altsw, core):
294
    """
295
    Generate loaders.
296
297
    :param osversion: OS version, 10.x.y.zzzz. Required.
298
    :type osversion: str
299
300
    :param radioversion: Radio version, 10.x.y.zzzz. Can be guessed.
301
    :type radioversion: str
302
303
    :param radios: Whether to create radio autoloaders. True by default.
304
    :type radios: bool
305
306
    :param localdir: Working directory. Local by default.
307
    :type localdir: str
308
309
    :param altsw: Radio software release, if not the same as OS.
310
    :type altsw: str
311
312
    :param core: Whether to create a core/radio loader. Default is false.
313
    :type core: bool
314
    """
315
    print("GENERATING LOADERS...")
316
    altradio = altsw is not None
317
    loadergen.generate_loaders(osversion, radioversion, radios, localdir, altradio, core)
318
319
320
def archivist_integrityloaders(integrity, localdir):
321
    """
322
    Check integrity of build loaders.
323
324
    :param integrity: Whether to test downloaded files. True by default.
325
    :type integrity: bool
326
327
    :param localdir: Working directory. Local by default.
328
    :type localdir: str
329
    """
330
    if integrity:
331
        scriptutils.test_loader_files(localdir)
332
333
334
def archivist_removesigned(signed, localdir):
335
    """
336
    Remove signed files.
337
338
    :param signed: Whether to delete signed files. True by default.
339
    :type signed: bool
340
341
    :param localdir: Working directory. Local by default.
342
    :type localdir: str
343
    """
344
    if signed:
345
        print("REMOVING SIGNED FILES...")
346
        barutils.remove_signed_files(localdir)
347
348
349
def archivist_compressor(compressed, integrity, localdir, compmethod, szexe):
350
    """
351
    Compress and optionally verify loaders.
352
353
    :param compressed: Whether to compress files. True by default.
354
    :type compressed: bool
355
356
    :param integrity: Whether to test downloaded files. True by default.
357
    :type integrity: bool
358
359
    :param localdir: Working directory. Local by default.
360
    :type localdir: str
361
362
    :param compmethod: Compression method. Default is "7z", fallback "zip".
363
    :type compmethod: str
364
365
    :param szexe: Path to 7z executable.
366
    :type szexe: str
367
    """
368
    if compressed:
369
        print("COMPRESSING...")
370
        archiveutils.compress(localdir, compmethod, szexe, True)
371
        if integrity:
372
            print("TESTING ARCHIVES...")
373
            archiveutils.verify(localdir, compmethod, szexe, True)
374
375
376
def archivist_moveloaders(dirs, localdir):
377
    """
378
    Move loaders.
379
380
    :param dirs: List of OS/radio bar/loader/zipped folders.
381
    :type dirs: list(str)
382
383
    :param localdir: Working directory. Local by default.
384
    :type localdir: str
385
    """
386
    print("MOVING LOADERS...")
387
    barutils.move_loaders(localdir, dirs[2], dirs[3], dirs[4], dirs[5])
388
389
390
def archivist_gethashes(dirs, hashed, compressed, deleted, radios, osversion, radioversion, softwareversion, oldstyle):
391
    """
392
    Make new-style info files.
393
394
    :param dirs: List of OS/radio bar/loader/zipped folders.
395
    :type dirs: list(str)
396
397
    :param hashed: Whether to hash files. True by default.
398
    :type hashed: bool
399
400
    :param compressed: Whether to compress files. True by default.
401
    :type compressed: bool
402
403
    :param deleted: Whether to delete uncompressed files. True by default.
404
    :type deleted: bool
405
406
    :param radios: Whether to create radio autoloaders. True by default.
407
    :type radios: bool
408
409
    :param osversion: OS version, 10.x.y.zzzz. Required.
410
    :type osversion: str
411
412
    :param radioversion: Radio version, 10.x.y.zzzz. Can be guessed.
413
    :type radioversion: str
414
415
    :param softwareversion: Software release, 10.x.y.zzzz. Can be guessed.
416
    :type softwareversion: str
417
418
    :param oldstyle: Whether to make old-style checksum files. Default is false.
419
    :type oldstyle: bool
420
    """
421
    if hashed and not oldstyle:
422
        scriptutils.bulk_info(dirs, osversion, compressed, deleted, radios,
423
                                  radioversion, softwareversion)
424
425
def archivist_getoldhashes(dirs, hashed, compressed, deleted, radios, hashdict, oldstyle):
426
    """
427
    Make old-style checksum files.
428
429
    :param dirs: List of OS/radio bar/loader/zipped folders.
430
    :type dirs: list(str)
431
432
    :param hashed: Whether to hash files. True by default.
433
    :type hashed: bool
434
435
    :param compressed: Whether to compress files. True by default.
436
    :type compressed: bool
437
438
    :param deleted: Whether to delete uncompressed files. True by default.
439
    :type deleted: bool
440
441
    :param radios: Whether to create radio autoloaders. True by default.
442
    :type radios: bool
443
444
    :param hashdict: Dictionary of hash rules, in ~\bbarchivist.ini.
445
    :type hashdict: dict({str: bool})
446
447
    :param oldstyle: Whether to make old-style checksum files. Default is false.
448
    :type oldstyle: bool
449
    """
450
    if hashed and oldstyle:
451
        scriptutils.bulk_hash(dirs, compressed, deleted, radios, hashdict)
452
453
454
def archivist_gpg(gpg, dirs, compressed, deleted, radios):
455
    """
456
    GPG-sign everything.
457
458
    :param gpg: Whether to use GnuPG verification. False by default.
459
    :type gpg: bool
460
461
    :param dirs: List of OS/radio bar/loader/zipped folders.
462
    :type dirs: list(str)
463
464
    :param compressed: Whether to compress files. True by default.
465
    :type compressed: bool
466
467
    :param deleted: Whether to delete uncompressed files. True by default.
468
    :type deleted: bool
469
470
    :param radios: Whether to create radio autoloaders. True by default.
471
    :type radios: bool
472
    """
473
    if gpg:
474
        scriptutils.bulk_verify(dirs, compressed, deleted, radios)
475
476
477
def archivist_deleteuncompressed(dirs, deleted, radios):
478
    """
479
    Delete uncompressed loaders.
480
481
    :param dirs: List of OS/radio bar/loader/zipped folders.
482
    :type dirs: list(str)
483
484
    :param deleted: Whether to delete uncompressed files. True by default.
485
    :type deleted: bool
486
487
    :param radios: Whether to create radio autoloaders. True by default.
488
    :type radios: bool
489
    """
490
    if deleted:
491
        print("DELETING UNCOMPRESSED LOADERS...")
492
        barutils.remove_unpacked_loaders(dirs[2], dirs[3], radios)
493
494
495
def archivist_removeemptyfolders(localdir):
496
    """
497
    Delete empty folders.
498
499
    :param localdir: Working directory. Local by default.
500
    :type localdir: str
501
    """
502
    print("REMOVING EMPTY FOLDERS...")
503
    barutils.remove_empty_folders(localdir)
504
505
506
def archivist_main(osversion, radioversion=None, softwareversion=None,
507
                   localdir=None, radios=True, compressed=True, deleted=True,
508
                   hashed=True, hashdict=None, download=True,
509
                   extract=True, signed=True, compmethod="7z",
510
                   gpg=False, integrity=True, altsw=None,
511
                   core=False, oldstyle=False):
512
    """
513
    Wrap around multi-autoloader creation code.
514
    Some combination of creating, downloading, hashing,
515
    compressing and moving autoloaders.
516
517
    :param osversion: OS version, 10.x.y.zzzz. Required.
518
    :type osversion: str
519
520
    :param radioversion: Radio version, 10.x.y.zzzz. Can be guessed.
521
    :type radioversion: str
522
523
    :param softwareversion: Software release, 10.x.y.zzzz. Can be guessed.
524
    :type softwareversion: str
525
526
    :param localdir: Working directory. Local by default.
527
    :type localdir: str
528
529
    :param radios: Whether to create radio autoloaders. True by default.
530
    :type radios: bool
531
532
    :param compressed: Whether to compress files. True by default.
533
    :type compressed: bool
534
535
    :param deleted: Whether to delete uncompressed files. True by default.
536
    :type deleted: bool
537
538
    :param hashed: Whether to hash files. True by default.
539
    :type hashed: bool
540
541
    :param hashdict: Dictionary of hash rules, in ~\bbarchivist.ini.
542
    :type hashdict: dict({str: bool})
543
544
    :param download: Whether to download bar files. True by default.
545
    :type download: bool
546
547
    :param extract: Whether to extract bar files. True by default.
548
    :type extract: bool
549
550
    :param signed: Whether to delete signed files. True by default.
551
    :type signed: bool
552
553
    :param compmethod: Compression method. Default is "7z", fallback "zip".
554
    :type compmethod: str
555
556
    :param gpg: Whether to use GnuPG verification. False by default.
557
    :type gpg: bool
558
559
    :param integrity: Whether to test downloaded files. True by default.
560
    :type integrity: bool
561
562
    :param altsw: Radio software release, if not the same as OS.
563
    :type altsw: str
564
565
    :param core: Whether to create a core/radio loader. Default is false.
566
    :type core: bool
567
568
    :param oldstyle: Whether to make old-style checksum files. Default is false.
569
    :type oldstyle: bool
570
    """
571
    radioversion = scriptutils.return_radio_version(osversion, radioversion)
572
    softwareversion, swchecked = scriptutils.return_sw_checked(softwareversion, osversion)
573
    if altsw == "checkme":
574
        altsw, altchecked = scriptutils.return_radio_sw_checked(altsw, radioversion)
575
    if localdir is None:
576
        localdir = os.getcwd()
577
    if hashed and hashdict is None:
578
        hashdict = hashutils.verifier_config_loader()
579
        hashutils.verifier_config_writer(hashdict)
580
    scriptutils.standard_preamble("archivist", osversion, softwareversion, radioversion, altsw)
581
    # Generate download URLs
582
    baseurl, alturl = scriptutils.get_baseurls(softwareversion, altsw)
583
    osurls, radiourls, cores = utilities.generate_urls(baseurl, osversion, radioversion, True)
584
    osurls = cores if core else osurls
585
    for idx, url in enumerate(osurls):
586
        if "qc8960.factory_sfi" in url:
587
            vzwurl = url
588
            vzwindex = idx
589
            break
590
    if not networkutils.availability(vzwurl):
591
        osurls[vzwindex] = osurls[vzwindex].replace("qc8960.factory_sfi", "qc8960.verizon_sfi")
592
    osurls = list(set(osurls))  # pop duplicates
593
    if altsw:
594
        radiourls2 = [x.replace(baseurl, alturl) for x in radiourls]
595
        radiourls = radiourls2
596
        del radiourls2
597
    archivist_checksw(baseurl, softwareversion, swchecked, alturl, altsw, altchecked)
598
    # Check availability of OS, radio
599
    scriptutils.check_os_bulk(osurls)
600
    radiourls, radioversion = scriptutils.check_radio_bulk(radiourls, radioversion)
601
    # Get 7z executable
602
    compmethod, szexe = scriptutils.get_sz_executable(compmethod)
603
    # Make dirs: bd_o, bd_r, ld_o, ld_r, zd_o, zd_r
604
    dirs = barutils.make_dirs(localdir, osversion, radioversion)
605
    archivist_download(download)
606
    archivist_integritybars(integrity, osurls, radiourls)
607
    archivist_extractbars(extract, localdir)
608
    archivist_integritysigned(extract, localdir)
609
    archivist_movebars(dirs, localdir)
610
    archivist_generateloaders(osversion, radioversion, radios, localdir, altsw, core)
611
    archivist_integrityloaders(integrity, localdir)
612
    archivist_removesigned(signed, localdir)
613
    archivist_compressor(compressed, integrity, localdir, compmethod, szexe)
614
    archivist_moveloaders(dirs, localdir)
615
    archivist_gethashes(dirs, hashed, compressed, deleted, radios, osversion, radioversion, softwareversion, oldstyle)
616
    archivist_getoldhashes(dirs, hashed, compressed, deleted, radios, hashdict, oldstyle)
617
    archivist_gpg(gpg, dirs, compressed, deleted, radios)
618
    archivist_deleteuncompressed(dirs, deleted, radios)
619
    archivist_removeemptyfolders(localdir)
620
    print("\nFINISHED!")
621
622
623
if __name__ == "__main__":
624
    grab_args()
625
    decorators.enter_to_exit(False)
626