#
# 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))
}

