diff options
| -rw-r--r-- | meta/classes/compress_doc.bbclass | 213 |
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 | ||
| 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" | ||
| 33 | python 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 | |||
| 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 | # 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 | |||
| 147 | def _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 | |||
| 158 | def 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 | ||
| 185 | def 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 | |||
