| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 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 | 
|  | 17 | DOC_COMPRESS_LIST ?= "gz xz bz2" | 
|  | 18 |  | 
|  | 19 | # Compression policy, must be one of ${DOC_COMPRESS_LIST} | 
|  | 20 | DOC_COMPRESS ?= "gz" | 
|  | 21 |  | 
|  | 22 | # Compression shell command | 
|  | 23 | DOC_COMPRESS_CMD[gz] ?= 'gzip -v -9 -n' | 
|  | 24 | DOC_COMPRESS_CMD[bz2] ?= "bzip2 -v -9" | 
|  | 25 | DOC_COMPRESS_CMD[xz] ?= "xz -v" | 
|  | 26 |  | 
|  | 27 | # Decompression shell command | 
|  | 28 | DOC_DECOMPRESS_CMD[gz] ?= 'gunzip -v' | 
|  | 29 | DOC_DECOMPRESS_CMD[bz2] ?= "bunzip2 -v" | 
|  | 30 | DOC_DECOMPRESS_CMD[xz] ?= "unxz -v" | 
|  | 31 |  | 
|  | 32 | PACKAGE_PREPROCESS_FUNCS += "package_do_compress_doc compress_doc_updatealternatives" | 
|  | 33 | python package_do_compress_doc() { | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 34 | compress_mode = d.getVar('DOC_COMPRESS') | 
|  | 35 | compress_list = (d.getVar('DOC_COMPRESS_LIST') or '').split() | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 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 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 39 | dvar = d.getVar('PKGD') | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 40 | compress_cmds = {} | 
|  | 41 | decompress_cmds = {} | 
|  | 42 | for mode in compress_list: | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 43 | compress_cmds[mode] = d.getVarFlag('DOC_COMPRESS_CMD', mode) | 
|  | 44 | decompress_cmds[mode] = d.getVarFlag('DOC_DECOMPRESS_CMD', mode) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 45 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 46 | mandir = os.path.abspath(dvar + os.sep + d.getVar("mandir")) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 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 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 52 | infodir = os.path.abspath(dvar + os.sep + d.getVar("infodir")) | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 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 |  | 
|  | 59 | def _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. | 
|  | 71 | def _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 |  | 
|  | 81 | def _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 |  | 
|  | 113 | def _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 |  | 
|  | 130 | def _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 |  | 
|  | 138 | def _is_man(file): | 
|  | 139 | import re | 
|  | 140 |  | 
|  | 141 | # It refers MANSECT-var in man(1.6g)'s man.config | 
|  | 142 | # ".1:.1p:.8:.2:.3:.3p:.4:.5:.6:.7:.9:.0p:.tcl:.n:.l:.p:.o" | 
|  | 143 | # Not start with '.', and contain the above colon-seperate element | 
|  | 144 | p = re.compile(r'[^\.]+\.([1-9lnop]|0p|tcl)') | 
|  | 145 | if p.search(file): | 
|  | 146 | return True | 
|  | 147 |  | 
|  | 148 | return False | 
|  | 149 |  | 
|  | 150 | def _is_compress_doc(file, compress_format_list): | 
|  | 151 | compress_format = _get_compress_format(file, compress_format_list) | 
|  | 152 | compress_suffix = '.' + compress_format | 
|  | 153 | if file.endswith(compress_suffix): | 
|  | 154 | # Remove the compress suffix | 
|  | 155 | uncompress_file = file[:-len(compress_suffix)] | 
|  | 156 | if _is_info(uncompress_file) or _is_man(uncompress_file): | 
|  | 157 | return True, compress_format | 
|  | 158 |  | 
|  | 159 | return False, '' | 
|  | 160 |  | 
|  | 161 | def compress_doc(topdir, compress_mode, compress_cmds): | 
|  | 162 | hardlink_dict = {} | 
|  | 163 | for root, dirs, files in os.walk(topdir): | 
|  | 164 | for f in files: | 
|  | 165 | file = os.path.join(root, f) | 
|  | 166 | if os.path.isdir(file): | 
|  | 167 | continue | 
|  | 168 |  | 
|  | 169 | if _is_info(file) or _is_man(file): | 
|  | 170 | # Symlink | 
|  | 171 | if os.path.islink(file): | 
|  | 172 | _process_symlink(file, compress_mode) | 
|  | 173 | # Hardlink | 
|  | 174 | elif os.lstat(file).st_nlink > 1: | 
|  | 175 | _collect_hardlink(hardlink_dict, file) | 
|  | 176 | # Normal file | 
|  | 177 | elif os.path.isfile(file): | 
|  | 178 | cmd = "%s %s" % (compress_cmds[compress_mode], file) | 
|  | 179 | (retval, output) = oe.utils.getstatusoutput(cmd) | 
|  | 180 | if retval: | 
|  | 181 | bb.warn("compress failed %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else "")) | 
|  | 182 | continue | 
|  | 183 | bb.note('compress file %s' % file) | 
|  | 184 |  | 
|  | 185 | _process_hardlink(hardlink_dict, compress_mode, compress_cmds) | 
|  | 186 |  | 
|  | 187 | # Decompress doc files which format is not compress_mode | 
|  | 188 | def decompress_doc(topdir, compress_mode, decompress_cmds): | 
|  | 189 | hardlink_dict = {} | 
|  | 190 | decompress = True | 
|  | 191 | for root, dirs, files in os.walk(topdir): | 
|  | 192 | for f in files: | 
|  | 193 | file = os.path.join(root, f) | 
|  | 194 | if os.path.isdir(file): | 
|  | 195 | continue | 
|  | 196 |  | 
|  | 197 | res, compress_format = _is_compress_doc(file, decompress_cmds.keys()) | 
|  | 198 | # Decompress files which format is not compress_mode | 
|  | 199 | if res and compress_mode!=compress_format: | 
|  | 200 | # Symlink | 
|  | 201 | if os.path.islink(file): | 
|  | 202 | _process_symlink(file, compress_format, decompress) | 
|  | 203 | # Hardlink | 
|  | 204 | elif os.lstat(file).st_nlink > 1: | 
|  | 205 | _collect_hardlink(hardlink_dict, file) | 
|  | 206 | # Normal file | 
|  | 207 | elif os.path.isfile(file): | 
|  | 208 | cmd = "%s %s" % (decompress_cmds[compress_format], file) | 
|  | 209 | (retval, output) = oe.utils.getstatusoutput(cmd) | 
|  | 210 | if retval: | 
|  | 211 | bb.warn("decompress failed %s (cmd was %s)%s" % (retval, cmd, ":\n%s" % output if output else "")) | 
|  | 212 | continue | 
|  | 213 | bb.note('decompress file %s' % file) | 
|  | 214 |  | 
|  | 215 | _process_hardlink(hardlink_dict, compress_mode, decompress_cmds, decompress) | 
|  | 216 |  | 
|  | 217 | python compress_doc_updatealternatives () { | 
|  | 218 | if not bb.data.inherits_class('update-alternatives', d): | 
|  | 219 | return | 
|  | 220 |  | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 221 | mandir = d.getVar("mandir") | 
|  | 222 | infodir = d.getVar("infodir") | 
|  | 223 | compress_mode = d.getVar('DOC_COMPRESS') | 
|  | 224 | for pkg in (d.getVar('PACKAGES') or "").split(): | 
|  | 225 | old_names = (d.getVar('ALTERNATIVE_%s' % pkg) or "").split() | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 226 | new_names = [] | 
|  | 227 | for old_name in old_names: | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 228 | old_link     = d.getVarFlag('ALTERNATIVE_LINK_NAME', old_name) | 
|  | 229 | old_target   = d.getVarFlag('ALTERNATIVE_TARGET_%s' % pkg, old_name) or \ | 
|  | 230 | d.getVarFlag('ALTERNATIVE_TARGET', old_name) or \ | 
|  | 231 | d.getVar('ALTERNATIVE_TARGET_%s' % pkg) or \ | 
|  | 232 | d.getVar('ALTERNATIVE_TARGET') or \ | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 233 | old_link | 
|  | 234 | # Sometimes old_target is specified as relative to the link name. | 
|  | 235 | old_target   = os.path.join(os.path.dirname(old_link), old_target) | 
|  | 236 |  | 
|  | 237 | # The updatealternatives used for compress doc | 
|  | 238 | if mandir in old_target or infodir in old_target: | 
|  | 239 | new_name = old_name + '.' + compress_mode | 
|  | 240 | new_link = old_link + '.' + compress_mode | 
|  | 241 | new_target = old_target + '.' + compress_mode | 
|  | 242 | d.delVarFlag('ALTERNATIVE_LINK_NAME', old_name) | 
|  | 243 | d.setVarFlag('ALTERNATIVE_LINK_NAME', new_name, new_link) | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 244 | if d.getVarFlag('ALTERNATIVE_TARGET_%s' % pkg, old_name): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 245 | d.delVarFlag('ALTERNATIVE_TARGET_%s' % pkg, old_name) | 
|  | 246 | d.setVarFlag('ALTERNATIVE_TARGET_%s' % pkg, new_name, new_target) | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 247 | elif d.getVarFlag('ALTERNATIVE_TARGET', old_name): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 248 | d.delVarFlag('ALTERNATIVE_TARGET', old_name) | 
|  | 249 | d.setVarFlag('ALTERNATIVE_TARGET', new_name, new_target) | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 250 | elif d.getVar('ALTERNATIVE_TARGET_%s' % pkg): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 251 | d.setVar('ALTERNATIVE_TARGET_%s' % pkg, new_target) | 
| Brad Bishop | 6e60e8b | 2018-02-01 10:27:11 -0500 | [diff] [blame] | 252 | elif d.getVar('ALTERNATIVE_TARGET'): | 
| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 253 | d.setVar('ALTERNATIVE_TARGET', new_target) | 
|  | 254 |  | 
|  | 255 | new_names.append(new_name) | 
|  | 256 |  | 
|  | 257 | if new_names: | 
|  | 258 | d.setVar('ALTERNATIVE_%s' % pkg, ' '.join(new_names)) | 
|  | 259 | } | 
|  | 260 |  |