1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
|
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
import argparse
import os
import sys
import time
from mozpack.copier import FileCopier, FileRegistry
from mozpack.errors import errors
from mozpack.files import BaseFile, FileFinder
from mozpack.manifests import InstallManifest
from mozbuild.action.util import log_build_task
from mozbuild.util import DefinesAction
COMPLETE = (
"Elapsed: {elapsed:.2f}s; From {dest}: Kept {existing} existing; "
"Added/updated {updated}; "
"Removed {rm_files} files and {rm_dirs} directories."
)
def process_manifest(destdir, paths, track, no_symlinks=False, defines={}):
if os.path.exists(track):
# We use the same format as install manifests for the tracking
# data.
manifest = InstallManifest(path=track)
remove_unaccounted = FileRegistry()
dummy_file = BaseFile()
finder = FileFinder(destdir, find_dotfiles=True)
for dest in manifest._dests:
for p, f in finder.find(dest):
remove_unaccounted.add(p, dummy_file)
remove_empty_directories = True
remove_all_directory_symlinks = True
else:
# If tracking is enabled and there is no file, we don't want to
# be removing anything.
remove_unaccounted = False
remove_empty_directories = False
remove_all_directory_symlinks = False
manifest = InstallManifest()
for path in paths:
manifest |= InstallManifest(path=path)
copier = FileCopier()
link_policy = "copy" if no_symlinks else "symlink"
manifest.populate_registry(
copier, defines_override=defines, link_policy=link_policy
)
with errors.accumulate():
result = copier.copy(
destdir,
remove_unaccounted=remove_unaccounted,
remove_all_directory_symlinks=remove_all_directory_symlinks,
remove_empty_directories=remove_empty_directories,
)
if track:
# We should record files that we actually copied.
# It is too late to expand wildcards when the track file is read.
manifest.write(path=track, expand_pattern=True)
return result
def main(argv):
parser = argparse.ArgumentParser(description="Process install manifest files.")
parser.add_argument("destdir", help="Destination directory.")
parser.add_argument("manifests", nargs="+", help="Path to manifest file(s).")
parser.add_argument(
"--no-symlinks",
action="store_true",
help="Do not install symbolic links. Always copy files",
)
parser.add_argument(
"--track",
metavar="PATH",
required=True,
help="Use installed files tracking information from the given path.",
)
parser.add_argument(
"-D",
action=DefinesAction,
dest="defines",
metavar="VAR[=VAL]",
help="Define a variable to override what is specified in the manifest",
)
args = parser.parse_args(argv)
start = time.monotonic()
result = process_manifest(
args.destdir,
args.manifests,
track=args.track,
no_symlinks=args.no_symlinks,
defines=args.defines,
)
elapsed = time.monotonic() - start
print(
COMPLETE.format(
elapsed=elapsed,
dest=args.destdir,
existing=result.existing_files_count,
updated=result.updated_files_count,
rm_files=result.removed_files_count,
rm_dirs=result.removed_directories_count,
)
)
if __name__ == "__main__":
log_build_task(main, sys.argv[1:])
|