mercurial/archival.py
author the31k <the31k@thethirty.one>
Thu, 31 Aug 2017 18:24:08 +0300
changeset 34091 abf91c4f9608
parent 33545 8074e2d006c0
child 35212 760fef6aca74
permissions -rw-r--r--
branches: correctly show inactive multiheaded branches Issue being fixed here: `hg branches` incorrectly renders inactive multiheaded branches as active if they have closed heads. Example: ``` $ hg log --template '{rev}:{node|short} "{desc}" ({branch}) [parents: {parents}]\n' 4:2e2fa7af8357 "merge" (default) [parents: 0:c94e548c8c7d 3:7be622ae5832 ] 3:7be622ae5832 "2" (somebranch) [parents: 1:81c1d9458987 ] 2:be82cf30409c "close" (somebranch) [parents: ] 1:81c1d9458987 "1" (somebranch) [parents: ] 0:c94e548c8c7d "initial" (default) [parents: ] $ hg branches default 4:2e2fa7af8357 somebranch 3:7be622ae5832 ``` Branch `somebranch` have two heads, the 1st one being closed (rev 2) and the other one being merged into default (rev 3). This branch should be shown as inactive one. This happens because we intersect branch heads with repo heads to check branch activity. In this case intersection in a set with one node (rev 2). This head is closed but the branch is marked as active nevertheless. Fix is to check branch activity by intersecting only open heads set. Fixed output: ``` $ hg branches default 4:2e2fa7af8357 somebranch 3:7be622ae5832 (inactive) ``` Relevant tests for multihead branches added to test-branches suite. Implentation note about adding `iteropen` method: At first I have tried to modify `iterbranches` is such a way that it would filter out closed heads itself. For example it could have `closed=False` parameter. But in this case we would have to filter closed tips as well. Reasoning in terms of `hg branches` we actually are not allowed to do this. Also, we need to do heads filtering only if tip is not closed itself. But if it is - we are ok to skip filtering, because branch is already known to be inactive. So we can't implement heads filtering in `iterbranches` in elegant way, because we will end up with something like `closed_heads=False` or even `closed_heads_is_tip_is_open`. Finally I decided to move this logic to the `branches` function, adding `iteropen` helper method. Differential Revision: https://phab.mercurial-scm.org/D583
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     1
# archival.py - revision archival for mercurial
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     2
#
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     3
# Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com>
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     4
#
8225
46293a0c7e9f updated license to be explicit about GPL version 2
Martin Geisler <mg@lazybytes.net>
parents: 7770
diff changeset
     5
# This software may be used and distributed according to the terms of the
10263
25e572394f5c Update license to GPLv2+
Matt Mackall <mpm@selenic.com>
parents: 9614
diff changeset
     6
# GNU General Public License version 2 or any later version.
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
     7
25916
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
     8
from __future__ import absolute_import
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
     9
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    10
import gzip
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    11
import os
17628
133d13e44544 archival: add "extended-timestamp" extra block for zip archives (issue3600)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17108
diff changeset
    12
import struct
25916
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    13
import tarfile
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    14
import time
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    15
import zipfile
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    16
import zlib
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    17
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    18
from .i18n import _
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    19
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    20
from . import (
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    21
    error,
33544
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    22
    formatter,
25916
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    23
    match as matchmod,
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    24
    util,
31245
7feab0e7702d vfs: use 'vfs' module directly in 'mercurial.archival'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31226
diff changeset
    25
    vfs as vfsmod,
25916
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    26
)
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28017
diff changeset
    27
stringio = util.stringio
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    28
17429
72fa4ef2245f declare local constants instead of using magic values and comments
Mads Kiilerich <mads@kiilerich.com>
parents: 17108
diff changeset
    29
# from unzip source code:
72fa4ef2245f declare local constants instead of using magic values and comments
Mads Kiilerich <mads@kiilerich.com>
parents: 17108
diff changeset
    30
_UNX_IFREG = 0x8000
72fa4ef2245f declare local constants instead of using magic values and comments
Mads Kiilerich <mads@kiilerich.com>
parents: 17108
diff changeset
    31
_UNX_IFLNK = 0xa000
72fa4ef2245f declare local constants instead of using magic values and comments
Mads Kiilerich <mads@kiilerich.com>
parents: 17108
diff changeset
    32
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
    33
def tidyprefix(dest, kind, prefix):
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    34
    '''choose prefix to use for names in archive.  make sure prefix is
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    35
    safe for consumers.'''
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    36
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    37
    if prefix:
5842
111ed8c871bf Use util.normpath() instead of direct path string operation.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 4951
diff changeset
    38
        prefix = util.normpath(prefix)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    39
    else:
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    40
        if not isinstance(dest, str):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    41
            raise ValueError('dest must be string if no prefix')
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    42
        prefix = os.path.basename(dest)
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    43
        lower = prefix.lower()
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
    44
        for sfx in exts.get(kind, []):
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    45
            if lower.endswith(sfx):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    46
                prefix = prefix[:-len(sfx)]
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    47
                break
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    48
    lpfx = os.path.normpath(util.localpath(prefix))
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    49
    prefix = util.pconvert(lpfx)
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    50
    if not prefix.endswith('/'):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    51
        prefix += '/'
24953
5115d03440f4 archive: drop the leading '.' path component from the prefix (issue4634)
Matt Harbison <matt_harbison@yahoo.com>
parents: 24681
diff changeset
    52
    # Drop the leading '.' path component if present, so Windows can read the
5115d03440f4 archive: drop the leading '.' path component from the prefix (issue4634)
Matt Harbison <matt_harbison@yahoo.com>
parents: 24681
diff changeset
    53
    # zip files (issue4634)
5115d03440f4 archive: drop the leading '.' path component from the prefix (issue4634)
Matt Harbison <matt_harbison@yahoo.com>
parents: 24681
diff changeset
    54
    if prefix.startswith('./'):
5115d03440f4 archive: drop the leading '.' path component from the prefix (issue4634)
Matt Harbison <matt_harbison@yahoo.com>
parents: 24681
diff changeset
    55
        prefix = prefix[2:]
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    56
    if prefix.startswith('../') or os.path.isabs(lpfx) or '/../' in prefix:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26198
diff changeset
    57
        raise error.Abort(_('archive prefix contains illegal components'))
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    58
    return prefix
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    59
11557
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    60
exts = {
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    61
    'tar': ['.tar'],
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    62
    'tbz2': ['.tbz2', '.tar.bz2'],
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    63
    'tgz': ['.tgz', '.tar.gz'],
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    64
    'zip': ['.zip'],
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    65
    }
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    66
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    67
def guesskind(dest):
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    68
    for kind, extensions in exts.iteritems():
25149
3f0744eeaeaf cleanup: use __builtins__.any instead of util.any
Augie Fackler <augie@google.com>
parents: 24953
diff changeset
    69
        if any(dest.endswith(ext) for ext in extensions):
11557
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    70
            return kind
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    71
    return None
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    72
24681
33ab99a6ad9b archive: look for first visible revision to build repo identity (issue4591)
Yuya Nishihara <yuya@tcha.org>
parents: 24678
diff changeset
    73
def _rootctx(repo):
33ab99a6ad9b archive: look for first visible revision to build repo identity (issue4591)
Yuya Nishihara <yuya@tcha.org>
parents: 24678
diff changeset
    74
    # repo[0] may be hidden
33ab99a6ad9b archive: look for first visible revision to build repo identity (issue4591)
Yuya Nishihara <yuya@tcha.org>
parents: 24678
diff changeset
    75
    for rev in repo:
33ab99a6ad9b archive: look for first visible revision to build repo identity (issue4591)
Yuya Nishihara <yuya@tcha.org>
parents: 24678
diff changeset
    76
        return repo[rev]
33ab99a6ad9b archive: look for first visible revision to build repo identity (issue4591)
Yuya Nishihara <yuya@tcha.org>
parents: 24678
diff changeset
    77
    return repo['null']
33ab99a6ad9b archive: look for first visible revision to build repo identity (issue4591)
Yuya Nishihara <yuya@tcha.org>
parents: 24678
diff changeset
    78
24678
fbcace19534f archive: extract metadata() closure to module-level function
Yuya Nishihara <yuya@tcha.org>
parents: 24677
diff changeset
    79
def buildmetadata(ctx):
fbcace19534f archive: extract metadata() closure to module-level function
Yuya Nishihara <yuya@tcha.org>
parents: 24677
diff changeset
    80
    '''build content of .hg_archival.txt'''
fbcace19534f archive: extract metadata() closure to module-level function
Yuya Nishihara <yuya@tcha.org>
parents: 24677
diff changeset
    81
    repo = ctx.repo()
33544
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    82
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    83
    default = (
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    84
        r'repo: {root}\n'
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    85
        r'node: {ifcontains(rev, revset("wdir()"),'
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    86
                            r'"{p1node}{dirty}", "{node}")}\n'
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    87
        r'branch: {branch|utf8}\n'
25615
dc707fb35550 archive: report the node as "{p1node}+" when archiving a dirty wdir()
Matt Harbison <matt_harbison@yahoo.com>
parents: 25601
diff changeset
    88
33544
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    89
        # {tags} on ctx includes local tags and 'tip', with no current way to
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    90
        # limit that to global tags.  Therefore, use {latesttag} as a substitute
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    91
        # when the distance is 0, since that will be the list of global tags on
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    92
        # ctx.
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    93
        r'{ifeq(latesttagdistance, 0, latesttag % "tag: {tag}\n",'
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    94
                       r'"{latesttag % "latesttag: {tag}\n"}'
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    95
                       r'latesttagdistance: {latesttagdistance}\n'
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    96
                       r'changessincelatesttag: {changessincelatesttag}\n")}'
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    97
    )
24678
fbcace19534f archive: extract metadata() closure to module-level function
Yuya Nishihara <yuya@tcha.org>
parents: 24677
diff changeset
    98
33544
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    99
    opts = {
33545
8074e2d006c0 archive: add an experimental config to control the metadata file template
Matt Harbison <matt_harbison@yahoo.com>
parents: 33544
diff changeset
   100
        'template': repo.ui.config('experimental', 'archivemetatemplate',
8074e2d006c0 archive: add an experimental config to control the metadata file template
Matt Harbison <matt_harbison@yahoo.com>
parents: 33544
diff changeset
   101
                                   default)
33544
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   102
    }
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   103
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   104
    out = util.stringio()
24678
fbcace19534f archive: extract metadata() closure to module-level function
Yuya Nishihara <yuya@tcha.org>
parents: 24677
diff changeset
   105
33544
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   106
    fm = formatter.formatter(repo.ui, out, 'archive', opts)
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   107
    fm.startitem()
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   108
    fm.context(ctx=ctx)
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   109
    fm.data(root=_rootctx(repo).hex())
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   110
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   111
    if ctx.rev() is None:
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   112
        dirty = ''
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   113
        if ctx.dirty(missing=True):
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   114
            dirty = '+'
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   115
        fm.data(dirty=dirty)
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   116
    fm.end()
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   117
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   118
    return out.getvalue()
11557
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   119
8778
c5f36402daad use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8527
diff changeset
   120
class tarit(object):
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   121
    '''write archive to tar file or stream.  can write uncompressed,
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   122
    or compress with gzip or bzip2.'''
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   123
4652
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   124
    class GzipFileWithTime(gzip.GzipFile):
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   125
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   126
        def __init__(self, *args, **kw):
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   127
            timestamp = None
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   128
            if 'timestamp' in kw:
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   129
                timestamp = kw.pop('timestamp')
8527
f9a80054dd3c use 'x is None' instead of 'x == None'
Martin Geisler <mg@lazybytes.net>
parents: 8312
diff changeset
   130
            if timestamp is None:
4652
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   131
                self.timestamp = time.time()
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   132
            else:
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   133
                self.timestamp = timestamp
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   134
            gzip.GzipFile.__init__(self, *args, **kw)
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   135
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   136
        def _write_gzip_header(self):
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   137
            self.fileobj.write('\037\213')             # magic header
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   138
            self.fileobj.write('\010')                 # compression method
26198
1a781a986611 archival: drop self.filename - deprecated in py2.6
timeless@mozdev.org
parents: 25916
diff changeset
   139
            fname = self.name
13102
2956945c3bee archival: don't set gzip filename header when there's no filename
Brodie Rao <brodie@bitheap.org>
parents: 12323
diff changeset
   140
            if fname and fname.endswith('.gz'):
2956945c3bee archival: don't set gzip filename header when there's no filename
Brodie Rao <brodie@bitheap.org>
parents: 12323
diff changeset
   141
                fname = fname[:-3]
4652
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   142
            flags = 0
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   143
            if fname:
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   144
                flags = gzip.FNAME
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   145
            self.fileobj.write(chr(flags))
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   146
            gzip.write32u(self.fileobj, long(self.timestamp))
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   147
            self.fileobj.write('\002')
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   148
            self.fileobj.write('\377')
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   149
            if fname:
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   150
                self.fileobj.write(fname + '\000')
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   151
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   152
    def __init__(self, dest, mtime, kind=''):
2477
857591c586e0 use commit time as mtime for file archives.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2353
diff changeset
   153
        self.mtime = mtime
13400
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13144
diff changeset
   154
        self.fileobj = None
4652
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   155
30488
798bcb1274dd archival: simplify code and drop message about Python 2.5
Augie Fackler <augie@google.com>
parents: 29894
diff changeset
   156
        def taropen(mode, name='', fileobj=None):
4652
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   157
            if kind == 'gz':
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   158
                mode = mode[0]
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   159
                if not fileobj:
4731
1d5a2ee683b0 Fix tgz archival on Windows.
csaba.henk@creo.hu
parents: 4685
diff changeset
   160
                    fileobj = open(name, mode + 'b')
4652
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   161
                gzfileobj = self.GzipFileWithTime(name, mode + 'b',
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   162
                                                  zlib.Z_BEST_COMPRESSION,
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   163
                                                  fileobj, timestamp=mtime)
13400
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13144
diff changeset
   164
                self.fileobj = gzfileobj
4652
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   165
                return tarfile.TarFile.taropen(name, mode, gzfileobj)
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   166
            else:
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   167
                return tarfile.open(name, mode + kind, fileobj)
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   168
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   169
        if isinstance(dest, str):
30488
798bcb1274dd archival: simplify code and drop message about Python 2.5
Augie Fackler <augie@google.com>
parents: 29894
diff changeset
   170
            self.z = taropen('w:', name=dest)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   171
        else:
30488
798bcb1274dd archival: simplify code and drop message about Python 2.5
Augie Fackler <augie@google.com>
parents: 29894
diff changeset
   172
            self.z = taropen('w|', fileobj=dest)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   173
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   174
    def addfile(self, name, mode, islink, data):
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   175
        i = tarfile.TarInfo(name)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   176
        i.mtime = self.mtime
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   177
        i.size = len(data)
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   178
        if islink:
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   179
            i.type = tarfile.SYMTYPE
25658
e93036747902 global: mass rewrite to use modern octal syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25615
diff changeset
   180
            i.mode = 0o777
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   181
            i.linkname = data
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   182
            data = None
7770
fd3e5ff53a31 fix disappearing symlinks [issue1509]
Peter van Dijk <mercurial-bugs@selenic.com>
parents: 6913
diff changeset
   183
            i.size = 0
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   184
        else:
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   185
            i.mode = mode
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28017
diff changeset
   186
            data = stringio(data)
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   187
        self.z.addfile(i, data)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   188
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   189
    def done(self):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   190
        self.z.close()
13400
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13144
diff changeset
   191
        if self.fileobj:
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13144
diff changeset
   192
            self.fileobj.close()
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   193
8778
c5f36402daad use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8527
diff changeset
   194
class tellable(object):
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   195
    '''provide tell method for zipfile.ZipFile when writing to http
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   196
    response file object.'''
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   197
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   198
    def __init__(self, fp):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   199
        self.fp = fp
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   200
        self.offset = 0
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   201
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   202
    def __getattr__(self, key):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   203
        return getattr(self.fp, key)
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   204
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   205
    def write(self, s):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   206
        self.fp.write(s)
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   207
        self.offset += len(s)
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   208
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   209
    def tell(self):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   210
        return self.offset
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   211
8778
c5f36402daad use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8527
diff changeset
   212
class zipit(object):
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   213
    '''write archive to zip file or stream.  can write uncompressed,
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   214
    or compressed with deflate.'''
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   215
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   216
    def __init__(self, dest, mtime, compress=True):
2168
dd4ec4576cc8 Proper check to see if zip dest needs to be wrapped in tellable
Colin McMillen <mcmillen@cs.cmu.edu>
parents: 2112
diff changeset
   217
        if not isinstance(dest, str):
dd4ec4576cc8 Proper check to see if zip dest needs to be wrapped in tellable
Colin McMillen <mcmillen@cs.cmu.edu>
parents: 2112
diff changeset
   218
            try:
dd4ec4576cc8 Proper check to see if zip dest needs to be wrapped in tellable
Colin McMillen <mcmillen@cs.cmu.edu>
parents: 2112
diff changeset
   219
                dest.tell()
2169
4564794b6f55 Combine catching exceptions added in dd4ec4576cc8 in one except statement.
Thomas Arendsen Hein <thomas@intevation.de>
parents: 2168
diff changeset
   220
            except (AttributeError, IOError):
2168
dd4ec4576cc8 Proper check to see if zip dest needs to be wrapped in tellable
Colin McMillen <mcmillen@cs.cmu.edu>
parents: 2112
diff changeset
   221
                dest = tellable(dest)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   222
        self.z = zipfile.ZipFile(dest, 'w',
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   223
                                 compress and zipfile.ZIP_DEFLATED or
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   224
                                 zipfile.ZIP_STORED)
12319
381f131220ad archive: set date to 1980 for very old zip files
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   225
381f131220ad archive: set date to 1980 for very old zip files
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   226
        # Python's zipfile module emits deprecation warnings if we try
381f131220ad archive: set date to 1980 for very old zip files
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   227
        # to store files with a date before 1980.
381f131220ad archive: set date to 1980 for very old zip files
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   228
        epoch = 315532800 # calendar.timegm((1980, 1, 1, 0, 0, 0, 1, 1, 0))
381f131220ad archive: set date to 1980 for very old zip files
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   229
        if mtime < epoch:
381f131220ad archive: set date to 1980 for very old zip files
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   230
            mtime = epoch
381f131220ad archive: set date to 1980 for very old zip files
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   231
17628
133d13e44544 archival: add "extended-timestamp" extra block for zip archives (issue3600)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17108
diff changeset
   232
        self.mtime = mtime
2477
857591c586e0 use commit time as mtime for file archives.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2353
diff changeset
   233
        self.date_time = time.gmtime(mtime)[:6]
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   234
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   235
    def addfile(self, name, mode, islink, data):
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   236
        i = zipfile.ZipInfo(name, self.date_time)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   237
        i.compress_type = self.z.compression
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   238
        # unzip will not honor unix file modes unless file creator is
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   239
        # set to unix (id 3).
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   240
        i.create_system = 3
17429
72fa4ef2245f declare local constants instead of using magic values and comments
Mads Kiilerich <mads@kiilerich.com>
parents: 17108
diff changeset
   241
        ftype = _UNX_IFREG
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   242
        if islink:
25658
e93036747902 global: mass rewrite to use modern octal syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25615
diff changeset
   243
            mode = 0o777
17429
72fa4ef2245f declare local constants instead of using magic values and comments
Mads Kiilerich <mads@kiilerich.com>
parents: 17108
diff changeset
   244
            ftype = _UNX_IFLNK
29894
31a6d5e14508 py3: remove use of *L syntax
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28861
diff changeset
   245
        i.external_attr = (mode | ftype) << 16
17628
133d13e44544 archival: add "extended-timestamp" extra block for zip archives (issue3600)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17108
diff changeset
   246
        # add "extended-timestamp" extra block, because zip archives
133d13e44544 archival: add "extended-timestamp" extra block for zip archives (issue3600)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17108
diff changeset
   247
        # without this will be extracted with unexpected timestamp,
133d13e44544 archival: add "extended-timestamp" extra block for zip archives (issue3600)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17108
diff changeset
   248
        # if TZ is not configured as GMT
133d13e44544 archival: add "extended-timestamp" extra block for zip archives (issue3600)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17108
diff changeset
   249
        i.extra += struct.pack('<hhBl',
133d13e44544 archival: add "extended-timestamp" extra block for zip archives (issue3600)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17108
diff changeset
   250
                               0x5455,     # block type: "extended-timestamp"
133d13e44544 archival: add "extended-timestamp" extra block for zip archives (issue3600)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17108
diff changeset
   251
                               1 + 4,      # size of this block
133d13e44544 archival: add "extended-timestamp" extra block for zip archives (issue3600)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17108
diff changeset
   252
                               1,          # "modification time is present"
18301
49ad7030ecc4 archival: pass integer to struct.pack int field instead of float
Mads Kiilerich <madski@unity3d.com>
parents: 17629
diff changeset
   253
                               int(self.mtime)) # last modification (UTC)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   254
        self.z.writestr(i, data)
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   255
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   256
    def done(self):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   257
        self.z.close()
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   258
8778
c5f36402daad use new style classes
Benoit Boissinot <benoit.boissinot@ens-lyon.org>
parents: 8527
diff changeset
   259
class fileit(object):
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   260
    '''write archive as files in directory.'''
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   261
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   262
    def __init__(self, name, mtime):
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   263
        self.basedir = name
31245
7feab0e7702d vfs: use 'vfs' module directly in 'mercurial.archival'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31226
diff changeset
   264
        self.opener = vfsmod.vfs(self.basedir)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   265
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   266
    def addfile(self, name, mode, islink, data):
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   267
        if islink:
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   268
            self.opener.symlink(data, name)
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   269
            return
4830
74f36b1027f4 archive: use util.opener when archiving files.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4731
diff changeset
   270
        f = self.opener(name, "w", atomictemp=True)
74f36b1027f4 archive: use util.opener when archiving files.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4731
diff changeset
   271
        f.write(data)
15057
774da7121fc9 atomictempfile: make close() consistent with other file-like objects.
Greg Ward <greg@gerg.ca>
parents: 13970
diff changeset
   272
        f.close()
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   273
        destfile = os.path.join(self.basedir, name)
4830
74f36b1027f4 archive: use util.opener when archiving files.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4731
diff changeset
   274
        os.chmod(destfile, mode)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   275
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   276
    def done(self):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   277
        pass
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   278
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   279
archivers = {
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   280
    'files': fileit,
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   281
    'tar': tarit,
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   282
    'tbz2': lambda name, mtime: tarit(name, mtime, 'bz2'),
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   283
    'tgz': lambda name, mtime: tarit(name, mtime, 'gz'),
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   284
    'uzip': lambda name, mtime: zipit(name, mtime, False),
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   285
    'zip': zipit,
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   286
    }
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   287
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   288
def archive(repo, dest, node, kind, decode=True, matchfn=None,
24172
e0f06228bb66 archive: change the default prefix to '' from None
Matt Harbison <matt_harbison@yahoo.com>
parents: 23645
diff changeset
   289
            prefix='', mtime=None, subrepos=False):
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   290
    '''create archive of repo as it was at node.
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   291
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   292
    dest can be name of directory, name of archive file, or file
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   293
    object to write archive to.
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   294
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   295
    kind is type of archive to create.
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   296
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   297
    decode tells whether to put files through decode filters from
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   298
    hgrc.
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   299
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   300
    matchfn is function to filter names of files to write to archive.
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   301
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   302
    prefix is name of path to put before every archive member.'''
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   303
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   304
    if kind == 'files':
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   305
        if prefix:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26198
diff changeset
   306
            raise error.Abort(_('cannot give prefix when archiving to files'))
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   307
    else:
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   308
        prefix = tidyprefix(dest, kind, prefix)
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   309
4951
667290b6c95e archive: delay extraction of file revisions
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4831
diff changeset
   310
    def write(name, mode, islink, getdata):
667290b6c95e archive: delay extraction of file revisions
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4831
diff changeset
   311
        data = getdata()
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   312
        if decode:
4005
656e06eebda7 replace filehandle version of wwrite with wwritedata
Matt Mackall <mpm@selenic.com>
parents: 3968
diff changeset
   313
            data = repo.wwritedata(name, data)
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   314
        archiver.addfile(prefix + name, mode, islink, data)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   315
6019
b70a530bdb93 cleanly abort on unknown archive type (issue966)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 4951
diff changeset
   316
    if kind not in archivers:
26587
56b2bcea2529 error: get Abort from 'error' instead of 'util'
Pierre-Yves David <pierre-yves.david@fb.com>
parents: 26198
diff changeset
   317
        raise error.Abort(_("unknown archive type '%s'") % kind)
6749
51b0e799352f manifest: remove execf/linkf methods
Matt Mackall <mpm@selenic.com>
parents: 6747
diff changeset
   318
51b0e799352f manifest: remove execf/linkf methods
Matt Mackall <mpm@selenic.com>
parents: 6747
diff changeset
   319
    ctx = repo[node]
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   320
    archiver = archivers[kind](dest, mtime or ctx.date()[0])
6749
51b0e799352f manifest: remove execf/linkf methods
Matt Mackall <mpm@selenic.com>
parents: 6747
diff changeset
   321
33499
0407a51b9d8c codemod: register core configitems using a script
Jun Wu <quark@fb.com>
parents: 33363
diff changeset
   322
    if repo.ui.configbool("ui", "archivemeta"):
16919
51932c835b74 archive: make progress only show files that are actually archived
Thomas Arendsen Hein <thomas@intevation.de>
parents: 15057
diff changeset
   323
        name = '.hg_archival.txt'
51932c835b74 archive: make progress only show files that are actually archived
Thomas Arendsen Hein <thomas@intevation.de>
parents: 15057
diff changeset
   324
        if not matchfn or matchfn(name):
25658
e93036747902 global: mass rewrite to use modern octal syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25615
diff changeset
   325
            write(name, 0o644, False, lambda: buildmetadata(ctx))
9614
58edd448da4f archive: add branch and tag informations to the .hg_archival.txt file
Gilles Moris <gilles.moris@free.fr>
parents: 8778
diff changeset
   326
16919
51932c835b74 archive: make progress only show files that are actually archived
Thomas Arendsen Hein <thomas@intevation.de>
parents: 15057
diff changeset
   327
    if matchfn:
51932c835b74 archive: make progress only show files that are actually archived
Thomas Arendsen Hein <thomas@intevation.de>
parents: 15057
diff changeset
   328
        files = [f for f in ctx.manifest().keys() if matchfn(f)]
51932c835b74 archive: make progress only show files that are actually archived
Thomas Arendsen Hein <thomas@intevation.de>
parents: 15057
diff changeset
   329
    else:
51932c835b74 archive: make progress only show files that are actually archived
Thomas Arendsen Hein <thomas@intevation.de>
parents: 15057
diff changeset
   330
        files = ctx.manifest().keys()
51932c835b74 archive: make progress only show files that are actually archived
Thomas Arendsen Hein <thomas@intevation.de>
parents: 15057
diff changeset
   331
    total = len(files)
18967
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   332
    if total:
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   333
        files.sort()
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   334
        repo.ui.progress(_('archiving'), 0, unit=_('files'), total=total)
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   335
        for i, f in enumerate(files):
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   336
            ff = ctx.flags(f)
25658
e93036747902 global: mass rewrite to use modern octal syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25615
diff changeset
   337
            write(f, 'x' in ff and 0o755 or 0o644, 'l' in ff, ctx[f].data)
18967
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   338
            repo.ui.progress(_('archiving'), i + 1, item=f,
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   339
                             unit=_('files'), total=total)
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   340
        repo.ui.progress(_('archiving'), None)
12323
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12321
diff changeset
   341
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12321
diff changeset
   342
    if subrepos:
18364
6252b4f1c4b4 subrepos: process subrepos in sorted order
Mads Kiilerich <mads@kiilerich.com>
parents: 18344
diff changeset
   343
        for subpath in sorted(ctx.substate):
25601
3ec8351fa6ed archive: support 'wdir()'
Matt Harbison <matt_harbison@yahoo.com>
parents: 25149
diff changeset
   344
            sub = ctx.workingsub(subpath)
28017
d3f1b7ee5e70 match: rename "narrowmatcher" to "subdirmatcher" (API)
Martin von Zweigbergk <martinvonz@google.com>
parents: 26587
diff changeset
   345
            submatch = matchmod.subdirmatcher(subpath, matchfn)
31116
b44ab288358e subrepo: run the repo decoders when archiving
Matt Harbison <matt_harbison@yahoo.com>
parents: 30488
diff changeset
   346
            total += sub.archive(archiver, prefix, submatch, decode)
18967
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   347
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   348
    if total == 0:
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   349
        raise error.Abort(_('no files match the archive pattern'))
12323
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12321
diff changeset
   350
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   351
    archiver.done()
18967
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   352
    return total