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
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
|
#
# Copyright OpenEmbedded Contributors
#
# SPDX-License-Identifier: MIT
#
# Compress man pages in ${mandir} and info pages in ${infodir}
#
# 1. The doc will be compressed to gz format by default.
#
# 2. It will automatically correct the compressed doc which is not
# in ${DOC_COMPRESS} but in ${DOC_COMPRESS_LIST} to the format
# of ${DOC_COMPRESS} policy
#
# 3. It is easy to add a new type compression by editing
# local.conf, such as:
# DOC_COMPRESS_LIST:append = ' abc'
# DOC_COMPRESS = 'abc'
# DOC_COMPRESS_CMD[abc] = 'abc compress cmd ***'
# DOC_DECOMPRESS_CMD[abc] = 'abc decompress cmd ***'
# All supported compression policy
DOC_COMPRESS_LIST ?= "gz xz bz2"
# Compression policy, must be one of ${DOC_COMPRESS_LIST}
DOC_COMPRESS ?= "gz"
# Compression shell command
DOC_COMPRESS_CMD[gz] ?= 'gzip -v -9 -n'
DOC_COMPRESS_CMD[bz2] ?= "bzip2 -v -9"
DOC_COMPRESS_CMD[xz] ?= "xz -v"
# Decompression shell command
DOC_DECOMPRESS_CMD[gz] ?= 'gunzip -v'
DOC_DECOMPRESS_CMD[bz2] ?= "bunzip2 -v"
DOC_DECOMPRESS_CMD[xz] ?= "unxz -v"
PACKAGE_PREPROCESS_FUNCS += "package_do_compress_doc compress_doc_updatealternatives"
python package_do_compress_doc() {
compress_mode = d.getVar('DOC_COMPRESS')
compress_list = (d.getVar('DOC_COMPRESS_LIST') or '').split()
if compress_mode not in compress_list:
bb.fatal('Compression policy %s not supported (not listed in %s)\n' % (compress_mode, compress_list))
dvar = d.getVar('PKGD')
compress_cmds = {}
decompress_cmds = {}
for mode in compress_list:
compress_cmds[mode] = d.getVarFlag('DOC_COMPRESS_CMD', mode)
decompress_cmds[mode] = d.getVarFlag('DOC_DECOMPRESS_CMD', mode)
mandir = os.path.abspath(dvar + os.sep + d.getVar("mandir"))
if os.path.exists(mandir):
# Decompress doc files which format is not compress_mode
decompress_doc(mandir, compress_mode, decompress_cmds)
compress_doc(mandir, compress_mode, compress_cmds)
infodir = os.path.abspath(dvar + os.sep + d.getVar("infodir"))
if os.path.exists(infodir):
# Decompress doc files which format is not compress_mode
decompress_doc(infodir, compress_mode, decompress_cmds)
compress_doc(infodir, compress_mode, compress_cmds)
}
def _get_compress_format(file, compress_format_list):
for compress_format in compress_format_list:
compress_suffix = '.' + compress_format
if file.endswith(compress_suffix):
return compress_format
return ''
# Collect hardlinks to dict, each element in dict lists hardlinks
# which points to the same doc file.
# {hardlink10: [hardlink11, hardlink12],,,}
# The hardlink10, hardlink11 and hardlink12 are the same file.
def _collect_hardlink(hardlink_dict, file):
for hardlink in hardlink_dict:
# Add to the existed hardlink
if os.path.samefile(hardlink, file):
hardlink_dict[hardlink].append(file)
return hardlink_dict
hardlink_dict[file] = []
return hardlink_dict
def _process_hardlink(hardlink_dict, compress_mode, shell_cmds, decompress=False):
import subprocess
for target in hardlink_dict:
if decompress:
compress_format = _get_compress_format(target, shell_cmds.keys())
cmd = "%s -f %s" % (shell_cmds[compress_format], target)
bb.note('decompress hardlink %s' % target)
else:
cmd = "%s -f %s" % (shell_cmds[compress_mode], target)
bb.note('compress hardlink %s' % target)
(retval, output) = subprocess.getstatusoutput(cmd)
if retval:
bb.warn("de/compress file failed %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else ""))
return
for hardlink_dup in hardlink_dict[target]:
if decompress:
# Remove compress suffix
compress_suffix = '.' + compress_format
new_hardlink = hardlink_dup[:-len(compress_suffix)]
new_target = target[:-len(compress_suffix)]
else:
# Append compress suffix
compress_suffix = '.' + compress_mode
new_hardlink = hardlink_dup + compress_suffix
new_target = target + compress_suffix
bb.note('hardlink %s-->%s' % (new_hardlink, new_target))
if not os.path.exists(new_hardlink):
os.link(new_target, new_hardlink)
if os.path.exists(hardlink_dup):
os.unlink(hardlink_dup)
def _process_symlink(file, compress_format, decompress=False):
compress_suffix = '.' + compress_format
if decompress:
# Remove compress suffix
new_linkname = file[:-len(compress_suffix)]
new_source = os.readlink(file)[:-len(compress_suffix)]
else:
# Append compress suffix
new_linkname = file + compress_suffix
new_source = os.readlink(file) + compress_suffix
bb.note('symlink %s-->%s' % (new_linkname, new_source))
if not os.path.exists(new_linkname):
os.symlink(new_source, new_linkname)
os.unlink(file)
def _is_info(file):
flags = '.info .info-'.split()
for flag in flags:
if flag in os.path.basename(file):
return True
return False
def _is_man(file):
import re
# It refers MANSECT-var in man(1.6g)'s man.config
# ".1:.1p:.8:.2:.3:.3p:.4:.5:.6:.7:.9:.0p:.tcl:.n:.l:.p:.o"
# Not start with '.', and contain the above colon-seperate element
p = re.compile(r'[^\.]+\.([1-9lnop]|0p|tcl)')
if p.search(file):
return True
return False
def _is_compress_doc(file, compress_format_list):
compress_format = _get_compress_format(file, compress_format_list)
compress_suffix = '.' + compress_format
if file.endswith(compress_suffix):
# Remove the compress suffix
uncompress_file = file[:-len(compress_suffix)]
if _is_info(uncompress_file) or _is_man(uncompress_file):
return True, compress_format
return False, ''
def compress_doc(topdir, compress_mode, compress_cmds):
import subprocess
hardlink_dict = {}
for root, dirs, files in os.walk(topdir):
for f in files:
file = os.path.join(root, f)
if os.path.isdir(file):
continue
if _is_info(file) or _is_man(file):
# Symlink
if os.path.islink(file):
_process_symlink(file, compress_mode)
# Hardlink
elif os.lstat(file).st_nlink > 1:
_collect_hardlink(hardlink_dict, file)
# Normal file
elif os.path.isfile(file):
cmd = "%s %s" % (compress_cmds[compress_mode], file)
(retval, output) = subprocess.getstatusoutput(cmd)
if retval:
bb.warn("compress failed %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else ""))
continue
bb.note('compress file %s' % file)
_process_hardlink(hardlink_dict, compress_mode, compress_cmds)
# Decompress doc files which format is not compress_mode
def decompress_doc(topdir, compress_mode, decompress_cmds):
import subprocess
hardlink_dict = {}
decompress = True
for root, dirs, files in os.walk(topdir):
for f in files:
file = os.path.join(root, f)
if os.path.isdir(file):
continue
res, compress_format = _is_compress_doc(file, decompress_cmds.keys())
# Decompress files which format is not compress_mode
if res and compress_mode!=compress_format:
# Symlink
if os.path.islink(file):
_process_symlink(file, compress_format, decompress)
# Hardlink
elif os.lstat(file).st_nlink > 1:
_collect_hardlink(hardlink_dict, file)
# Normal file
elif os.path.isfile(file):
cmd = "%s %s" % (decompress_cmds[compress_format], file)
(retval, output) = subprocess.getstatusoutput(cmd)
if retval:
bb.warn("decompress failed %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else ""))
continue
bb.note('decompress file %s' % file)
_process_hardlink(hardlink_dict, compress_mode, decompress_cmds, decompress)
python compress_doc_updatealternatives () {
if not bb.data.inherits_class('update-alternatives', d):
return
mandir = d.getVar("mandir")
infodir = d.getVar("infodir")
compress_mode = d.getVar('DOC_COMPRESS')
for pkg in (d.getVar('PACKAGES') or "").split():
old_names = (d.getVar('ALTERNATIVE:%s' % pkg) or "").split()
new_names = []
for old_name in old_names:
old_link = d.getVarFlag('ALTERNATIVE_LINK_NAME', old_name)
old_target = d.getVarFlag('ALTERNATIVE_TARGET_%s' % pkg, old_name) or \
d.getVarFlag('ALTERNATIVE_TARGET', old_name) or \
d.getVar('ALTERNATIVE_TARGET_%s' % pkg) or \
d.getVar('ALTERNATIVE_TARGET') or \
old_link
# Sometimes old_target is specified as relative to the link name.
old_target = os.path.join(os.path.dirname(old_link), old_target)
# The updatealternatives used for compress doc
if mandir in old_target or infodir in old_target:
new_name = old_name + '.' + compress_mode
new_link = old_link + '.' + compress_mode
new_target = old_target + '.' + compress_mode
d.delVarFlag('ALTERNATIVE_LINK_NAME', old_name)
d.setVarFlag('ALTERNATIVE_LINK_NAME', new_name, new_link)
if d.getVarFlag('ALTERNATIVE_TARGET_%s' % pkg, old_name):
d.delVarFlag('ALTERNATIVE_TARGET_%s' % pkg, old_name)
d.setVarFlag('ALTERNATIVE_TARGET_%s' % pkg, new_name, new_target)
elif d.getVarFlag('ALTERNATIVE_TARGET', old_name):
d.delVarFlag('ALTERNATIVE_TARGET', old_name)
d.setVarFlag('ALTERNATIVE_TARGET', new_name, new_target)
elif d.getVar('ALTERNATIVE_TARGET_%s' % pkg):
d.setVar('ALTERNATIVE_TARGET_%s' % pkg, new_target)
elif d.getVar('ALTERNATIVE_TARGET'):
d.setVar('ALTERNATIVE_TARGET', new_target)
new_names.append(new_name)
if new_names:
d.setVar('ALTERNATIVE:%s' % pkg, ' '.join(new_names))
}
|