# -*- coding: utf-8 -*-
"""archive with keyword expansion into selected files
"""

from __future__ import absolute_import


__version__ = "0.0.dev1"

__author__ = "Franz Glasner"


import os

from mercurial.i18n import _
from mercurial import (archival, commands, cmdutil, error, pycompat,
                       scmutil, util)


testedwith = "4.3.2"


cmdtable = {}

command = cmdutil.command(cmdtable)


@command('kwarchive',
    [('', 'no-decode', None, _('do not pass files through decoders')),
    ('p', 'prefix', '', _('directory prefix for files in archive'),
     _('PREFIX')),
    ('r', 'rev', '', _('revision to distribute'), _('REV')),
    ('t', 'type', '', _('type of distribution to create'), _('TYPE')),
    ] + cmdutil.subrepoopts + cmdutil.walkopts,
    _('[OPTION]... DEST'))
def kwarchive(ui, repo, dest, **opts):
    '''create an unversioned archive of a repository revision with some keywords expanded

    By default, the revision used is the parent of the working
    directory; use -r/--rev to specify a different revision.

    The archive type is automatically detected based on file
    extension (to override, use -t/--type).

    .. container:: verbose

      Examples:

      - create a zip file containing the 1.0 release::

          hg archive -r 1.0 project-1.0.zip

      - create a tarball excluding .hg files::

          hg archive project.tar.gz -X ".hg*"

    Valid types are:

    :``files``: a directory full of files (default)
    :``tar``:   tar archive, uncompressed
    :``tbz2``:  tar archive, compressed using bzip2
    :``tgz``:   tar archive, compressed using gzip
    :``uzip``:  zip archive, uncompressed
    :``zip``:   zip archive, compressed using deflate

    The exact name of the destination archive or directory is given
    using a format string; see :hg:`help export` for details.

    Each member added to an archive file has a directory prefix
    prepended. Use -p/--prefix to specify a format string for the
    prefix. The default is the basename of the archive, with suffixes
    removed.

    Returns 0 on success.
    '''

    opts = pycompat.byteskwargs(opts)
    ctx = scmutil.revsingle(repo, opts.get('rev'))
    if not ctx:
        raise error.Abort(_('no working directory: please specify a revision'))
    node = ctx.node()
    dest = cmdutil.makefilename(repo, dest, node)
    if os.path.realpath(dest) == repo.root:
        raise error.Abort(_('repository root cannot be destination'))

    kind = opts.get('type') or archival.guesskind(dest) or 'files'
    prefix = opts.get('prefix')

    if dest == '-':
        if kind == 'files':
            raise error.Abort(_('cannot archive plain files to stdout'))
        dest = cmdutil.makefileobj(repo, dest)
        if not prefix:
            prefix = os.path.basename(repo.root) + '-%h'

    prefix = cmdutil.makefilename(repo, prefix, node)
    matchfn = scmutil.match(ctx, [], opts)

    #
    # Monkey patch archival's archivers classes so that an archiver's "addfile()"
    # expands keywords
    #
    for ac in ("fileit", "tarit", "zipit",):
        patch_archiver_class(ac)

    archival.archive(repo, dest, node, kind, not opts.get('no_decode'),
                     matchfn, prefix, subrepos=opts.get('subrepos'))

    # XXX FIXME: Should the original methods be restored here?


def patch_archiver_class(archivername):
    """Patch an archiver class and return the original unbound method"""

    archiver_class = getattr(archival, archivername)
    orig_addfile = getattr(archiver_class, "addfile")

    def new_addfile(self, name, mode, isline, data):
        print "==> ARCHIVER(%s)" % archivername, name, mode, isline
        return orig_addfile(self, name, mode, isline, data)

    setattr(archiver_class, "addfile", new_addfile)
    return orig_addfile


def filter2(s, params, ui, **kwargs):
    print "=============>", repr(params), repr(kwargs)
    return s
