blob: 6a84575a65b72be3ae7cf3bf71f19fb7094530a4 [file] [log] [blame]
Benjamin Gordon1f4537f2019-12-06 09:10:56 -07001# Copyright 2020 The Chromium OS Authors. All rights reserved.
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5"""Run xz from PATH with a thread for each core in the system."""
6
Ben Pastenec6bf5492020-08-28 17:35:01 -07007from __future__ import division
Benjamin Gordon1f4537f2019-12-06 09:10:56 -07008
Ben Pastenec6bf5492020-08-28 17:35:01 -07009import multiprocessing
Benjamin Gordon1f4537f2019-12-06 09:10:56 -070010import os
Mike Frysinger687ab9d2020-02-06 00:35:15 -050011
Ben Pastenec6bf5492020-08-28 17:35:01 -070012from chromite.lib import commandline
13from chromite.lib import osutils
14from chromite.utils import memoize
15
Benjamin Gordon1f4537f2019-12-06 09:10:56 -070016
Ben Pastenec6bf5492020-08-28 17:35:01 -070017@memoize.Memoize
18def HasPixz():
19 """Returns path to pixz if it's on PATH or None otherwise."""
20 return osutils.Which('pixz')
21
22
23@memoize.Memoize
24def GetJobCount():
25 """Returns half of the total number of the machine's CPUs as a string.
26
27 Returns half rather than all of them to avoid starving out other parallel
28 processes on the same machine.
29 """
30 return str(int(max(1, multiprocessing.cpu_count() / 2)))
31
32
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070033def GetDecompressCommand(stdout):
Ben Pastenec6bf5492020-08-28 17:35:01 -070034 """Returns decompression command."""
35 if HasPixz():
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070036 cmd = ['pixz', '-d', '-p', GetJobCount()]
37 if stdout:
38 # Explicitly tell pixz the file is the input, so it will dump the output
39 # to stdout, instead of automatically choosing an output name.
40 cmd.append('-i')
41 return cmd
42 if stdout:
43 return ['xz', '-dc']
Ben Pastenec6bf5492020-08-28 17:35:01 -070044 return ['xz', '-d']
45
46
47def GetParser():
48 """Return a command line parser."""
49 parser = commandline.ArgumentParser(description=__doc__)
50 parser.add_argument(
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070051 '-d',
52 '--decompress',
53 '--uncompress',
Ben Pastenec6bf5492020-08-28 17:35:01 -070054 help='Decompress rather than compress.',
55 action='store_true')
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070056 parser.add_argument(
57 '-c',
58 dest='stdout',
59 action='store_true',
60 help="Write to standard output and don't delete input files.")
Ben Pastenec6bf5492020-08-28 17:35:01 -070061 return parser
62
63
Benjamin Gordon1f4537f2019-12-06 09:10:56 -070064def main(argv):
Ben Pastenec6bf5492020-08-28 17:35:01 -070065 parser = GetParser()
66 known_args, argv = parser.parse_known_args()
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070067 if '-i' in argv or '-o' in argv:
68 parser.error('It is invalid to use -i or -o with xz_auto')
69
Ben Pastenec6bf5492020-08-28 17:35:01 -070070 # xz doesn't support multi-threaded decompression, so try using pixz for that.
71 if known_args.decompress:
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070072 args = GetDecompressCommand(known_args.stdout)
Ben Pastenec6bf5492020-08-28 17:35:01 -070073 os.execvp(args[0], args + argv)
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070074 else:
75 cmd = ['xz', '-T0']
76 if known_args.stdout:
77 cmd.append('-c')
78 os.execvp(cmd[0], cmd + argv)