summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--meta/classes/compress_doc.bbclass213
1 files changed, 213 insertions, 0 deletions
diff --git a/meta/classes/compress_doc.bbclass b/meta/classes/compress_doc.bbclass
new file mode 100644
index 0000000000..6a4e635982
--- /dev/null
+++ b/meta/classes/compress_doc.bbclass
@@ -0,0 +1,213 @@
1# Compress man pages in ${mandir} and info pages in ${infodir}
2#
3# 1. The doc will be compressed to gz format by default.
4#
5# 2. It will automatically correct the compressed doc which is not
6# in ${DOC_COMPRESS} but in ${DOC_COMPRESS_LIST} to the format
7# of ${DOC_COMPRESS} policy
8#
9# 3. It is easy to add a new type compression by editing
10# local.conf, such as:
11# DOC_COMPRESS_LIST_append = ' abc'
12# DOC_COMPRESS = 'abc'
13# DOC_COMPRESS_CMD[abc] = 'abc compress cmd ***'
14# DOC_DECOMPRESS_CMD[abc] = 'abc decompress cmd ***'
15
16# All supported compression policy
17DOC_COMPRESS_LIST ?= "gz xz bz2"
18
19# Compression policy, must be one of ${DOC_COMPRESS_LIST}
20DOC_COMPRESS ?= "gz"
21
22# Compression shell command
23DOC_COMPRESS_CMD[gz] ?= 'gzip -v -9 -n'
24DOC_COMPRESS_CMD[bz2] ?= "bzip2 -v -9"
25DOC_COMPRESS_CMD[xz] ?= "xz -v"
26
27# Decompression shell command
28DOC_DECOMPRESS_CMD[gz] ?= 'gunzip -v'
29DOC_DECOMPRESS_CMD[bz2] ?= "bunzip2 -v"
30DOC_DECOMPRESS_CMD[xz] ?= "unxz -v"
31
32PACKAGE_PREPROCESS_FUNCS += "package_do_compress_doc"
33python package_do_compress_doc() {
34 compress_mode = d.getVar('DOC_COMPRESS', True)
35 compress_list = (d.getVar('DOC_COMPRESS_LIST', True) or '').split()
36 if compress_mode not in compress_list:
37 bb.fatal('Compression policy %s not supported (not listed in %s)\n' % (compress_mode, compress_list))
38
39 dvar = d.getVar('PKGD', True)
40 compress_cmds = {}
41 decompress_cmds = {}
42 for mode in compress_list:
43 compress_cmds[mode] = d.getVarFlag('DOC_COMPRESS_CMD', mode)
44 decompress_cmds[mode] = d.getVarFlag('DOC_DECOMPRESS_CMD', mode)
45
46 mandir = os.path.abspath(dvar + os.sep + d.getVar("mandir", True))
47 if os.path.exists(mandir):
48 # Decompress doc files which format is not compress_mode
49 decompress_doc(mandir, compress_mode, decompress_cmds)
50 compress_doc(mandir, compress_mode, compress_cmds)
51
52 infodir = os.path.abspath(dvar + os.sep + d.getVar("infodir", True))
53 if os.path.exists(infodir):
54 # Decompress doc files which format is not compress_mode
55 decompress_doc(infodir, compress_mode, decompress_cmds)
56 compress_doc(infodir, compress_mode, compress_cmds)
57}
58
59def _get_compress_format(file, compress_format_list):
60 for compress_format in compress_format_list:
61 compress_suffix = '.' + compress_format
62 if file.endswith(compress_suffix):
63 return compress_format
64
65 return ''
66
67# Collect hardlinks to dict, each element in dict lists hardlinks
68# which points to the same doc file.
69# {hardlink10: [hardlink11, hardlink12],,,}
70# The hardlink10, hardlink11 and hardlink12 are the same file.
71def _collect_hardlink(hardlink_dict, file):
72 for hardlink in hardlink_dict:
73 # Add to the existed hardlink
74 if os.path.samefile(hardlink, file):
75 hardlink_dict[hardlink].append(file)
76 return hardlink_dict
77
78 hardlink_dict[file] = []
79 return hardlink_dict
80
81def _process_hardlink(hardlink_dict, compress_mode, shell_cmds, decompress=False):
82 for target in hardlink_dict:
83 if decompress:
84 compress_format = _get_compress_format(target, shell_cmds.keys())
85 cmd = "%s -f %s" % (shell_cmds[compress_format], target)
86 bb.note('decompress hardlink %s' % target)
87 else:
88 cmd = "%s -f %s" % (shell_cmds[compress_mode], target)
89 bb.note('compress hardlink %s' % target)
90 (retval, output) = oe.utils.getstatusoutput(cmd)
91 if retval:
92 bb.warn("de/compress file failed %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else ""))
93 return
94
95 for hardlink_dup in hardlink_dict[target]:
96 if decompress:
97 # Remove compress suffix
98 compress_suffix = '.' + compress_format
99 new_hardlink = hardlink_dup[:-len(compress_suffix)]
100 new_target = target[:-len(compress_suffix)]
101 else:
102 # Append compress suffix
103 compress_suffix = '.' + compress_mode
104 new_hardlink = hardlink_dup + compress_suffix
105 new_target = target + compress_suffix
106
107 bb.note('hardlink %s-->%s' % (new_hardlink, new_target))
108 if not os.path.exists(new_hardlink):
109 os.link(new_target, new_hardlink)
110 if os.path.exists(hardlink_dup):
111 os.unlink(hardlink_dup)
112
113def _process_symlink(file, compress_format, decompress=False):
114 compress_suffix = '.' + compress_format
115 if decompress:
116 # Remove compress suffix
117 new_linkname = file[:-len(compress_suffix)]
118 new_source = os.readlink(file)[:-len(compress_suffix)]
119 else:
120 # Append compress suffix
121 new_linkname = file + compress_suffix
122 new_source = os.readlink(file) + compress_suffix
123
124 bb.note('symlink %s-->%s' % (new_linkname, new_source))
125 if not os.path.exists(new_linkname):
126 os.symlink(new_source, new_linkname)
127
128 os.unlink(file)
129
130def _is_info(file):
131 flags = '.info .info-'.split()
132 for flag in flags:
133 if flag in os.path.basename(file):
134 return True
135
136 return False
137
138def _is_man(file):
139 # It refers MANSECT-var in man(1.6g)'s man.config
140 flags = '.1:.1p:.8:.2:.3:.3p:.4:.5:.6:.7:.9:.0p:.tcl:.n:.l:.p:.o'.split(':')
141 for flag in flags:
142 if os.path.basename(file).endswith(flag):
143 return True
144
145 return False
146
147def _is_compress_doc(file, compress_format_list):
148 compress_format = _get_compress_format(file, compress_format_list)
149 compress_suffix = '.' + compress_format
150 if file.endswith(compress_suffix):
151 # Remove the compress suffix
152 uncompress_file = file[:-len(compress_suffix)]
153 if _is_info(uncompress_file) or _is_man(uncompress_file):
154 return True, compress_format
155
156 return False, ''
157
158def compress_doc(topdir, compress_mode, compress_cmds):
159 hardlink_dict = {}
160 for root, dirs, files in os.walk(topdir):
161 for f in files:
162 file = os.path.join(root, f)
163 if os.path.isdir(file):
164 continue
165
166 if _is_info(file) or _is_man(file):
167 # Symlink
168 if os.path.islink(file):
169 _process_symlink(file, compress_mode)
170 # Hardlink
171 elif os.lstat(file).st_nlink > 1:
172 _collect_hardlink(hardlink_dict, file)
173 # Normal file
174 elif os.path.isfile(file):
175 cmd = "%s %s" % (compress_cmds[compress_mode], file)
176 (retval, output) = oe.utils.getstatusoutput(cmd)
177 if retval:
178 bb.warn("compress failed %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else ""))
179 continue
180 bb.note('compress file %s' % file)
181
182 _process_hardlink(hardlink_dict, compress_mode, compress_cmds)
183
184# Decompress doc files which format is not compress_mode
185def decompress_doc(topdir, compress_mode, decompress_cmds):
186 hardlink_dict = {}
187 decompress = True
188 for root, dirs, files in os.walk(topdir):
189 for f in files:
190 file = os.path.join(root, f)
191 if os.path.isdir(file):
192 continue
193
194 res, compress_format = _is_compress_doc(file, decompress_cmds.keys())
195 # Decompress files which format is not compress_mode
196 if res and compress_mode!=compress_format:
197 # Symlink
198 if os.path.islink(file):
199 _process_symlink(file, compress_format, decompress)
200 # Hardlink
201 elif os.lstat(file).st_nlink > 1:
202 _collect_hardlink(hardlink_dict, file)
203 # Normal file
204 elif os.path.isfile(file):
205 cmd = "%s %s" % (decompress_cmds[compress_format], file)
206 (retval, output) = oe.utils.getstatusoutput(cmd)
207 if retval:
208 bb.warn("decompress failed %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else ""))
209 continue
210 bb.note('decompress file %s' % file)
211
212 _process_hardlink(hardlink_dict, compress_mode, decompress_cmds, decompress)
213