blob: 8bc65e6f39558c9d8b178b2c5265d4fe65a23227 [file] [log] [blame]
Benjamin Gordon1f4537f2019-12-06 09:10:56 -07001# -*- coding: utf-8 -*-
2# Copyright 2020 The Chromium OS Authors. All rights reserved.
3# Use of this source code is governed by a BSD-style license that can be
4# found in the LICENSE file.
5
6"""Run xz from PATH with a thread for each core in the system."""
7
Ben Pastenec6bf5492020-08-28 17:35:01 -07008from __future__ import division
Benjamin Gordon1f4537f2019-12-06 09:10:56 -07009from __future__ import print_function
10
Ben Pastenec6bf5492020-08-28 17:35:01 -070011import multiprocessing
Benjamin Gordon1f4537f2019-12-06 09:10:56 -070012import os
Mike Frysinger687ab9d2020-02-06 00:35:15 -050013import sys
14
Ben Pastenec6bf5492020-08-28 17:35:01 -070015from chromite.lib import commandline
16from chromite.lib import osutils
17from chromite.utils import memoize
18
Mike Frysinger687ab9d2020-02-06 00:35:15 -050019assert sys.version_info >= (3, 6), 'This module requires Python 3.6+'
Benjamin Gordon1f4537f2019-12-06 09:10:56 -070020
21
Ben Pastenec6bf5492020-08-28 17:35:01 -070022@memoize.Memoize
23def HasPixz():
24 """Returns path to pixz if it's on PATH or None otherwise."""
25 return osutils.Which('pixz')
26
27
28@memoize.Memoize
29def GetJobCount():
30 """Returns half of the total number of the machine's CPUs as a string.
31
32 Returns half rather than all of them to avoid starving out other parallel
33 processes on the same machine.
34 """
35 return str(int(max(1, multiprocessing.cpu_count() / 2)))
36
37
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070038def GetDecompressCommand(stdout):
Ben Pastenec6bf5492020-08-28 17:35:01 -070039 """Returns decompression command."""
40 if HasPixz():
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070041 cmd = ['pixz', '-d', '-p', GetJobCount()]
42 if stdout:
43 # Explicitly tell pixz the file is the input, so it will dump the output
44 # to stdout, instead of automatically choosing an output name.
45 cmd.append('-i')
46 return cmd
47 if stdout:
48 return ['xz', '-dc']
Ben Pastenec6bf5492020-08-28 17:35:01 -070049 return ['xz', '-d']
50
51
52def GetParser():
53 """Return a command line parser."""
54 parser = commandline.ArgumentParser(description=__doc__)
55 parser.add_argument(
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070056 '-d',
57 '--decompress',
58 '--uncompress',
Ben Pastenec6bf5492020-08-28 17:35:01 -070059 help='Decompress rather than compress.',
60 action='store_true')
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070061 parser.add_argument(
62 '-c',
63 dest='stdout',
64 action='store_true',
65 help="Write to standard output and don't delete input files.")
Ben Pastenec6bf5492020-08-28 17:35:01 -070066 return parser
67
68
Benjamin Gordon1f4537f2019-12-06 09:10:56 -070069def main(argv):
Ben Pastenec6bf5492020-08-28 17:35:01 -070070 parser = GetParser()
71 known_args, argv = parser.parse_known_args()
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070072 if '-i' in argv or '-o' in argv:
73 parser.error('It is invalid to use -i or -o with xz_auto')
74
Ben Pastenec6bf5492020-08-28 17:35:01 -070075 # xz doesn't support multi-threaded decompression, so try using pixz for that.
76 if known_args.decompress:
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070077 args = GetDecompressCommand(known_args.stdout)
Ben Pastenec6bf5492020-08-28 17:35:01 -070078 os.execvp(args[0], args + argv)
Tiancong Wangac3fc4a2020-09-11 10:44:03 -070079 else:
80 cmd = ['xz', '-T0']
81 if known_args.stdout:
82 cmd.append('-c')
83 os.execvp(cmd[0], cmd + argv)