|
13 | 13 | import subprocess
|
14 | 14 | import platform
|
15 | 15 | import time
|
| 16 | +import sys |
16 | 17 | from python.runfiles import runfiles
|
17 | 18 |
|
18 | 19 | runfiles = runfiles.Create()
|
19 | 20 | assert runfiles, "Installer should be run with `bazel run`"
|
20 | 21 |
|
21 | 22 | parser = argparse.ArgumentParser(description=__doc__)
|
22 |
| -parser.add_argument("--destdir", type=pathlib.Path, required=True, |
23 |
| - help="Desination directory, relative to `--build-file`") |
24 |
| -parser.add_argument("--pkg-install-script", required=True, |
25 |
| - help="The wrapped `pkg_install` installation script rlocation") |
26 |
| -parser.add_argument("--build-file", |
27 |
| - help="BUILD.bazel rlocation relative to which the installation should take place") |
28 |
| -parser.add_argument("--ripunzip", |
29 |
| - help="ripunzip executable rlocation. Must be provided if `--zip-manifest` is.") |
30 |
| -parser.add_argument("--zip-manifest", |
31 |
| - help="The rlocation of a file containing newline-separated `prefix:zip_file` entries") |
32 |
| -parser.add_argument("--cleanup", action=argparse.BooleanOptionalAction, default=True, |
33 |
| - help="Whether to wipe the destination directory before installing (true by default)") |
| 23 | +parser.add_argument( |
| 24 | + "--destdir", |
| 25 | + type=pathlib.Path, |
| 26 | + required=True, |
| 27 | + help="Desination directory, relative to `--build-file`", |
| 28 | +) |
| 29 | +parser.add_argument( |
| 30 | + "--pkg-install-script", |
| 31 | + required=True, |
| 32 | + help="The wrapped `pkg_install` installation script rlocation", |
| 33 | +) |
| 34 | +parser.add_argument( |
| 35 | + "--build-file", |
| 36 | + help="BUILD.bazel rlocation relative to which the installation should take place", |
| 37 | +) |
| 38 | +parser.add_argument( |
| 39 | + "--ripunzip", help="ripunzip executable rlocation. Must be provided if `--zip-manifest` is." |
| 40 | +) |
| 41 | +parser.add_argument( |
| 42 | + "--zip-manifest", |
| 43 | + help="The rlocation of a file containing newline-separated `prefix:zip_file` entries", |
| 44 | +) |
| 45 | +parser.add_argument( |
| 46 | + "--cleanup", |
| 47 | + action=argparse.BooleanOptionalAction, |
| 48 | + default=True, |
| 49 | + help="Whether to wipe the destination directory before installing (true by default)", |
| 50 | +) |
34 | 51 | opts = parser.parse_args()
|
35 | 52 | if opts.zip_manifest and not opts.ripunzip:
|
36 | 53 | parser.error("Provide `--ripunzip` when specifying `--zip-manifest`")
|
|
45 | 62 |
|
46 | 63 | _WIN_FILE_IN_USE_ERROR_CODE = 32
|
47 | 64 |
|
48 |
| -if destdir.exists() and opts.cleanup: |
49 |
| - if platform.system() == 'Windows': |
| 65 | + |
| 66 | +def rmdir(dir: pathlib.Path): |
| 67 | + if platform.system() == "Windows": |
50 | 68 | # On Windows we might have virus scanner still looking at the path so
|
51 | 69 | # attempt removal a couple of times sleeping between each attempt.
|
52 | 70 | for retry_delay in [1, 2, 2]:
|
53 | 71 | try:
|
54 |
| - shutil.rmtree(destdir) |
| 72 | + shutil.rmtree(dir) |
55 | 73 | break
|
56 | 74 | except OSError as e:
|
57 | 75 | if e.winerror == _WIN_FILE_IN_USE_ERROR_CODE:
|
58 | 76 | time.sleep(retry_delay)
|
59 | 77 | else:
|
60 | 78 | raise
|
61 | 79 | else:
|
62 |
| - shutil.rmtree(destdir) |
| 80 | + shutil.rmtree(dir) |
63 | 81 | else:
|
64 |
| - shutil.rmtree(destdir) |
| 82 | + shutil.rmtree(dir) |
| 83 | + |
| 84 | + |
| 85 | +if destdir.exists() and opts.cleanup: |
| 86 | + rmdir(destdir) |
| 87 | + |
| 88 | +class RetryException(Exception): |
| 89 | + pass |
| 90 | + |
| 91 | +attempts = 0 |
| 92 | +success = False |
| 93 | +while attempts < 3 and success is False: |
| 94 | + destdir.mkdir(parents=True, exist_ok=True) |
| 95 | + subprocess.run([script, "--destdir", destdir], check=True) |
65 | 96 |
|
66 |
| -destdir.mkdir(parents=True, exist_ok=True) |
67 |
| -subprocess.run([script, "--destdir", destdir], check=True) |
| 97 | + if opts.zip_manifest: |
| 98 | + ripunzip = runfiles.Rlocation(opts.ripunzip) |
| 99 | + zip_manifest = runfiles.Rlocation(opts.zip_manifest) |
| 100 | + with open(zip_manifest) as manifest: |
| 101 | + for line in manifest: |
| 102 | + prefix, _, zip = line.partition(":") |
| 103 | + assert zip, f"missing prefix for {prefix}, you should use prefix:zip format" |
| 104 | + zip = zip.strip() |
| 105 | + dest = destdir / prefix |
| 106 | + dest.mkdir(parents=True, exist_ok=True) |
| 107 | + command = [ripunzip, "unzip-file", zip, "-d", dest] |
| 108 | + print(f"Running ", *command) |
| 109 | + ret = subprocess.run(command) |
| 110 | + success = ret.returncode == 0 |
| 111 | + if not success: |
| 112 | + print(f"Failed to unzip {zip} to {dest}, retrying installation...") |
| 113 | + attempts += 1 |
| 114 | + rmdir(destdir) |
| 115 | + break |
68 | 116 |
|
69 |
| -if opts.zip_manifest: |
70 |
| - ripunzip = runfiles.Rlocation(opts.ripunzip) |
71 |
| - zip_manifest = runfiles.Rlocation(opts.zip_manifest) |
72 |
| - with open(zip_manifest) as manifest: |
73 |
| - for line in manifest: |
74 |
| - prefix, _, zip = line.partition(":") |
75 |
| - assert zip, f"missing prefix for {prefix}, you should use prefix:zip format" |
76 |
| - zip = zip.strip() |
77 |
| - dest = destdir / prefix |
78 |
| - dest.mkdir(parents=True, exist_ok=True) |
79 |
| - subprocess.run([ripunzip, "unzip-file", zip, "-d", dest], check=True) |
| 117 | +sys.exit(ret.returncode) |
0 commit comments