mercurial/archival.py
author Matt Harbison <matt_harbison@yahoo.com>
Wed, 25 Sep 2024 01:16:47 -0400
changeset 51900 77a9c7d8a7ba
parent 51863 f4733654f144
permissions -rw-r--r--
statichttprepo: stop shadowing the `bytes` builtin PyCharm flagged it, but I also misunderstood when looking at the code, because the name implied a byte string, not a number.
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
51863
f4733654f144 typing: add `from __future__ import annotations` to most files
Matt Harbison <matt_harbison@yahoo.com>
parents: 51861
diff changeset
     8
from __future__ import annotations
25916
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
51859
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
    15
import typing
25916
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    16
import zipfile
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    17
import zlib
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    18
51859
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
    19
from typing import (
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
    20
    Optional,
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
    21
)
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
    22
25916
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    23
from .i18n import _
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
    24
from .node import nullrev
43085
eef9a2d67051 py3: manually import pycompat.open into files that need it
Gregory Szorc <gregory.szorc@gmail.com>
parents: 43077
diff changeset
    25
from .pycompat import open
25916
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    26
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    27
from . import (
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    28
    error,
33544
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
    29
    formatter,
25916
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    30
    match as matchmod,
36707
bfe23afea361 archival: fsdecode paths before passing to tar or zip objects
Augie Fackler <augie@google.com>
parents: 36447
diff changeset
    31
    pycompat,
36139
b72c6ff4e4c0 archive: migrate to the fileprefetch callback mechanism
Matt Harbison <matt_harbison@yahoo.com>
parents: 36036
diff changeset
    32
    scmutil,
25916
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    33
    util,
31235
7feab0e7702d vfs: use 'vfs' module directly in 'mercurial.archival'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31216
diff changeset
    34
    vfs as vfsmod,
25916
c1777ece502a archival: use absolute_import
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25725
diff changeset
    35
)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
    36
48012
406a7e629946 archival: force a `CompressionError` to bytes before passing to `error.Abort`
Matt Harbison <matt_harbison@yahoo.com>
parents: 45942
diff changeset
    37
from .utils import stringutil
406a7e629946 archival: force a `CompressionError` to bytes before passing to `error.Abort`
Matt Harbison <matt_harbison@yahoo.com>
parents: 45942
diff changeset
    38
51859
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
    39
if typing.TYPE_CHECKING:
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
    40
    from . import (
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
    41
        localrepo,
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
    42
    )
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
    43
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28017
diff changeset
    44
stringio = util.stringio
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    45
17429
72fa4ef2245f declare local constants instead of using magic values and comments
Mads Kiilerich <mads@kiilerich.com>
parents: 17108
diff changeset
    46
# from unzip source code:
72fa4ef2245f declare local constants instead of using magic values and comments
Mads Kiilerich <mads@kiilerich.com>
parents: 17108
diff changeset
    47
_UNX_IFREG = 0x8000
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
    48
_UNX_IFLNK = 0xA000
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
    49
17429
72fa4ef2245f declare local constants instead of using magic values and comments
Mads Kiilerich <mads@kiilerich.com>
parents: 17108
diff changeset
    50
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
    51
def tidyprefix(dest, kind, prefix):
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45083
diff changeset
    52
    """choose prefix to use for names in archive.  make sure prefix is
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45083
diff changeset
    53
    safe for consumers."""
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    54
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    55
    if prefix:
5842
111ed8c871bf Use util.normpath() instead of direct path string operation.
Shun-ichi GOTO <shunichi.goto@gmail.com>
parents: 4951
diff changeset
    56
        prefix = util.normpath(prefix)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    57
    else:
36437
745b0df08514 py3: use bytes instead of str in isinstance
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36139
diff changeset
    58
        if not isinstance(dest, bytes):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    59
            raise ValueError(b'dest must be string if no prefix')
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    60
        prefix = os.path.basename(dest)
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    61
        lower = prefix.lower()
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
    62
        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
    63
            if lower.endswith(sfx):
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
    64
                prefix = prefix[: -len(sfx)]
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    65
                break
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    66
    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
    67
    prefix = util.pconvert(lpfx)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    68
    if not prefix.endswith(b'/'):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    69
        prefix += b'/'
24953
5115d03440f4 archive: drop the leading '.' path component from the prefix (issue4634)
Matt Harbison <matt_harbison@yahoo.com>
parents: 24681
diff changeset
    70
    # 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
    71
    # zip files (issue4634)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    72
    if prefix.startswith(b'./'):
24953
5115d03440f4 archive: drop the leading '.' path component from the prefix (issue4634)
Matt Harbison <matt_harbison@yahoo.com>
parents: 24681
diff changeset
    73
        prefix = prefix[2:]
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    74
    if prefix.startswith(b'../') or os.path.isabs(lpfx) or b'/../' in prefix:
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    75
        raise error.Abort(_(b'archive prefix contains illegal components'))
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    76
    return prefix
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
    77
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
    78
11557
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    79
exts = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    80
    b'tar': [b'.tar'],
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    81
    b'tbz2': [b'.tbz2', b'.tar.bz2'],
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    82
    b'tgz': [b'.tgz', b'.tar.gz'],
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    83
    b'zip': [b'.zip'],
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
    84
    b'txz': [b'.txz', b'.tar.xz'],
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
    85
}
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
    86
11557
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    87
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    88
def guesskind(dest):
48913
f254fc73d956 global: bulk replace simple pycompat.iteritems(x) with x.items()
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48893
diff changeset
    89
    for kind, extensions in exts.items():
25149
3f0744eeaeaf cleanup: use __builtins__.any instead of util.any
Augie Fackler <augie@google.com>
parents: 24953
diff changeset
    90
        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
    91
            return kind
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    92
    return None
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
    93
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
    94
24681
33ab99a6ad9b archive: look for first visible revision to build repo identity (issue4591)
Yuya Nishihara <yuya@tcha.org>
parents: 24678
diff changeset
    95
def _rootctx(repo):
33ab99a6ad9b archive: look for first visible revision to build repo identity (issue4591)
Yuya Nishihara <yuya@tcha.org>
parents: 24678
diff changeset
    96
    # 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
    97
    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
    98
        return repo[rev]
39894
d739f423bf06 repo: look up nullrev context by revnum, not symbolic name
Martin von Zweigbergk <martinvonz@google.com>
parents: 38381
diff changeset
    99
    return repo[nullrev]
24681
33ab99a6ad9b archive: look for first visible revision to build repo identity (issue4591)
Yuya Nishihara <yuya@tcha.org>
parents: 24678
diff changeset
   100
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   101
35905
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   102
# {tags} on ctx includes local tags and 'tip', with no current way to limit
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   103
# that to global tags.  Therefore, use {latesttag} as a substitute when
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   104
# the distance is 0, since that will be the list of global tags on ctx.
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   105
_defaultmetatemplate = br'''
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   106
repo: {root}
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   107
node: {ifcontains(rev, revset("wdir()"), "{p1node}{dirty}", "{node}")}
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   108
branch: {branch|utf8}
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   109
{ifeq(latesttagdistance, 0, join(latesttag % "tag: {tag}", "\n"),
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   110
      separate("\n",
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   111
               join(latesttag % "latesttag: {tag}", "\n"),
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   112
               "latesttagdistance: {latesttagdistance}",
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   113
               "changessincelatesttag: {changessincelatesttag}"))}
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   114
'''[
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   115
    1:
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   116
]  # drop leading '\n'
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   117
35905
887bbce7f491 archive: rewrite default metadata template as a multi-line bytes literal
Yuya Nishihara <yuya@tcha.org>
parents: 35349
diff changeset
   118
24678
fbcace19534f archive: extract metadata() closure to module-level function
Yuya Nishihara <yuya@tcha.org>
parents: 24677
diff changeset
   119
def buildmetadata(ctx):
fbcace19534f archive: extract metadata() closure to module-level function
Yuya Nishihara <yuya@tcha.org>
parents: 24677
diff changeset
   120
    '''build content of .hg_archival.txt'''
fbcace19534f archive: extract metadata() closure to module-level function
Yuya Nishihara <yuya@tcha.org>
parents: 24677
diff changeset
   121
    repo = ctx.repo()
33544
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   122
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   123
    opts = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   124
        b'template': repo.ui.config(
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   125
            b'experimental', b'archivemetatemplate', _defaultmetatemplate
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   126
        )
33544
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   127
    }
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   128
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   129
    out = util.stringio()
24678
fbcace19534f archive: extract metadata() closure to module-level function
Yuya Nishihara <yuya@tcha.org>
parents: 24677
diff changeset
   130
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   131
    fm = formatter.formatter(repo.ui, out, b'archive', opts)
33544
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   132
    fm.startitem()
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   133
    fm.context(ctx=ctx)
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   134
    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
   135
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   136
    if ctx.rev() is None:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   137
        dirty = b''
33544
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   138
        if ctx.dirty(missing=True):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   139
            dirty = b'+'
33544
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   140
        fm.data(dirty=dirty)
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   141
    fm.end()
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   142
4c4e95cae33a archive: use a templater to build the metadata file
Matt Harbison <matt_harbison@yahoo.com>
parents: 33499
diff changeset
   143
    return out.getvalue()
11557
57bdc2239535 archival: move commands.archive.guess_type to archival.guesskind
Martin Geisler <mg@lazybytes.net>
parents: 10282
diff changeset
   144
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   145
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48913
diff changeset
   146
class tarit:
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45083
diff changeset
   147
    """write archive to tar file or stream.  can write uncompressed,
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45083
diff changeset
   148
    or compress with gzip or bzip2."""
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   149
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   150
    def __init__(self, dest, mtime, kind=b''):
2477
857591c586e0 use commit time as mtime for file archives.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2353
diff changeset
   151
        self.mtime = mtime
13400
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13144
diff changeset
   152
        self.fileobj = None
4652
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   153
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   154
        def taropen(mode, name=b'', fileobj=None):
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   155
            if kind == b'gz':
36447
588048a6a8d3 py3: slice over bytes or use .startswith() to prevent getting ascii values
Pulkit Goyal <7895pulkit@gmail.com>
parents: 36437
diff changeset
   156
                mode = mode[0:1]
4652
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   157
                if not fileobj:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   158
                    fileobj = open(name, mode + b'b')
48882
640e1cb6a7de archival: remove GzipFileWithTime
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48875
diff changeset
   159
                gzfileobj = gzip.GzipFile(
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   160
                    name,
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   161
                    pycompat.sysstr(mode + b'b'),
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   162
                    zlib.Z_BEST_COMPRESSION,
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   163
                    fileobj,
44473
6c36a521572e gzip: rename the argument to `mtime` to match upstream python
Pierre-Yves David <pierre-yves.david@octobus.net>
parents: 43506
diff changeset
   164
                    mtime=mtime,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   165
                )
13400
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13144
diff changeset
   166
                self.fileobj = gzfileobj
51861
f81e0ce5103a typing: simplify archive.gz writing and drop a few pytype suppressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51859
diff changeset
   167
                return tarfile.TarFile.taropen(name, "w", gzfileobj)
4652
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   168
            else:
45048
2c0043977b6d archival: abort if compression method is unavailable
Manuel Jacob <me@manueljacob.de>
parents: 44577
diff changeset
   169
                try:
2c0043977b6d archival: abort if compression method is unavailable
Manuel Jacob <me@manueljacob.de>
parents: 44577
diff changeset
   170
                    return tarfile.open(
2c0043977b6d archival: abort if compression method is unavailable
Manuel Jacob <me@manueljacob.de>
parents: 44577
diff changeset
   171
                        name, pycompat.sysstr(mode + kind), fileobj
2c0043977b6d archival: abort if compression method is unavailable
Manuel Jacob <me@manueljacob.de>
parents: 44577
diff changeset
   172
                    )
2c0043977b6d archival: abort if compression method is unavailable
Manuel Jacob <me@manueljacob.de>
parents: 44577
diff changeset
   173
                except tarfile.CompressionError as e:
48012
406a7e629946 archival: force a `CompressionError` to bytes before passing to `error.Abort`
Matt Harbison <matt_harbison@yahoo.com>
parents: 45942
diff changeset
   174
                    raise error.Abort(stringutil.forcebytestr(e))
4652
06de65673ec2 timestamp of gzip archives taken from changeset context
csaba.henk@creo.hu
parents: 4370
diff changeset
   175
36709
7f9a6f5f7612 archival: our filenames are bytes, not strs
Augie Fackler <augie@google.com>
parents: 36708
diff changeset
   176
        if isinstance(dest, bytes):
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   177
            self.z = taropen(b'w:', name=dest)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   178
        else:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   179
            self.z = taropen(b'w|', fileobj=dest)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   180
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   181
    def addfile(self, name, mode, islink, data):
36707
bfe23afea361 archival: fsdecode paths before passing to tar or zip objects
Augie Fackler <augie@google.com>
parents: 36447
diff changeset
   182
        name = pycompat.fsdecode(name)
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   183
        i = tarfile.TarInfo(name)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   184
        i.mtime = self.mtime
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   185
        i.size = len(data)
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   186
        if islink:
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   187
            i.type = tarfile.SYMTYPE
25658
e93036747902 global: mass rewrite to use modern octal syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25615
diff changeset
   188
            i.mode = 0o777
36707
bfe23afea361 archival: fsdecode paths before passing to tar or zip objects
Augie Fackler <augie@google.com>
parents: 36447
diff changeset
   189
            i.linkname = pycompat.fsdecode(data)
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   190
            data = None
7770
fd3e5ff53a31 fix disappearing symlinks [issue1509]
Peter van Dijk <mercurial-bugs@selenic.com>
parents: 6913
diff changeset
   191
            i.size = 0
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   192
        else:
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   193
            i.mode = mode
28861
86db5cb55d46 pycompat: switch to util.stringio for py3 compat
timeless <timeless@mozdev.org>
parents: 28017
diff changeset
   194
            data = stringio(data)
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   195
        self.z.addfile(i, data)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   196
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   197
    def done(self):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   198
        self.z.close()
13400
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13144
diff changeset
   199
        if self.fileobj:
14f3795a5ed7 explicitly close files
Dan Villiom Podlaski Christiansen <danchr@gmail.com>
parents: 13144
diff changeset
   200
            self.fileobj.close()
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   201
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   202
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48913
diff changeset
   203
class zipit:
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45083
diff changeset
   204
    """write archive to zip file or stream.  can write uncompressed,
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45083
diff changeset
   205
    or compressed with deflate."""
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   206
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   207
    def __init__(self, dest, mtime, compress=True):
40247
844deb408a5b archival: don't try and fsdecode non-{bytes,str} objects
Augie Fackler <augie@google.com>
parents: 39894
diff changeset
   208
        if isinstance(dest, bytes):
844deb408a5b archival: don't try and fsdecode non-{bytes,str} objects
Augie Fackler <augie@google.com>
parents: 39894
diff changeset
   209
            dest = pycompat.fsdecode(dest)
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   210
        self.z = zipfile.ZipFile(
43506
9f70512ae2cf cleanup: remove pointless r-prefixes on single-quoted strings
Augie Fackler <augie@google.com>
parents: 43487
diff changeset
   211
            dest, 'w', compress and zipfile.ZIP_DEFLATED or zipfile.ZIP_STORED
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   212
        )
12319
381f131220ad archive: set date to 1980 for very old zip files
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   213
381f131220ad archive: set date to 1980 for very old zip files
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   214
        # 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
   215
        # to store files with a date before 1980.
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   216
        epoch = 315532800  # calendar.timegm((1980, 1, 1, 0, 0, 0, 1, 1, 0))
12319
381f131220ad archive: set date to 1980 for very old zip files
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   217
        if mtime < epoch:
381f131220ad archive: set date to 1980 for very old zip files
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   218
            mtime = epoch
381f131220ad archive: set date to 1980 for very old zip files
Martin Geisler <mg@aragost.com>
parents: 10282
diff changeset
   219
17628
133d13e44544 archival: add "extended-timestamp" extra block for zip archives (issue3600)
FUJIWARA Katsunori <foozy@lares.dti.ne.jp>
parents: 17108
diff changeset
   220
        self.mtime = mtime
2477
857591c586e0 use commit time as mtime for file archives.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents: 2353
diff changeset
   221
        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
   222
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   223
    def addfile(self, name, mode, islink, data):
36707
bfe23afea361 archival: fsdecode paths before passing to tar or zip objects
Augie Fackler <augie@google.com>
parents: 36447
diff changeset
   224
        i = zipfile.ZipInfo(pycompat.fsdecode(name), self.date_time)
43487
d5bef33ab83c archival: suppress some incorrect pytype failures
Augie Fackler <augie@google.com>
parents: 43106
diff changeset
   225
        i.compress_type = self.z.compression  # pytype: disable=attribute-error
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   226
        # 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
   227
        # set to unix (id 3).
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   228
        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
   229
        ftype = _UNX_IFREG
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   230
        if islink:
25658
e93036747902 global: mass rewrite to use modern octal syntax
Gregory Szorc <gregory.szorc@gmail.com>
parents: 25615
diff changeset
   231
            mode = 0o777
17429
72fa4ef2245f declare local constants instead of using magic values and comments
Mads Kiilerich <mads@kiilerich.com>
parents: 17108
diff changeset
   232
            ftype = _UNX_IFLNK
29890
31a6d5e14508 py3: remove use of *L syntax
Pulkit Goyal <7895pulkit@gmail.com>
parents: 28861
diff changeset
   233
        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
   234
        # 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
   235
        # 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
   236
        # if TZ is not configured as GMT
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   237
        i.extra += struct.pack(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   238
            b'<hhBl',
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   239
            0x5455,  # block type: "extended-timestamp"
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   240
            1 + 4,  # size of this block
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   241
            1,  # "modification time is present"
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   242
            int(self.mtime),
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   243
        )  # last modification (UTC)
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   244
        self.z.writestr(i, data)
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   245
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   246
    def done(self):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   247
        self.z.close()
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   248
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   249
48946
642e31cb55f0 py3: use class X: instead of class X(object):
Gregory Szorc <gregory.szorc@gmail.com>
parents: 48913
diff changeset
   250
class fileit:
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   251
    '''write archive as files in directory.'''
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   252
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   253
    def __init__(self, name, mtime):
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   254
        self.basedir = name
31235
7feab0e7702d vfs: use 'vfs' module directly in 'mercurial.archival'
Pierre-Yves David <pierre-yves.david@ens-lyon.org>
parents: 31216
diff changeset
   255
        self.opener = vfsmod.vfs(self.basedir)
35202
760fef6aca74 archive: pass thru mtime for directory archives, like other archive types do
James May <james.may@draeger.com>
parents: 33545
diff changeset
   256
        self.mtime = mtime
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   257
4831
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   258
    def addfile(self, name, mode, islink, data):
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   259
        if islink:
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   260
            self.opener.symlink(data, name)
6f08bc1bd00b archive: add symlink support
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4830
diff changeset
   261
            return
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   262
        f = self.opener(name, b"w", atomictemp=False)
4830
74f36b1027f4 archive: use util.opener when archiving files.
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4731
diff changeset
   263
        f.write(data)
15057
774da7121fc9 atomictempfile: make close() consistent with other file-like objects.
Greg Ward <greg@gerg.ca>
parents: 13970
diff changeset
   264
        f.close()
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   265
        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
   266
        os.chmod(destfile, mode)
35202
760fef6aca74 archive: pass thru mtime for directory archives, like other archive types do
James May <james.may@draeger.com>
parents: 33545
diff changeset
   267
        if self.mtime is not None:
760fef6aca74 archive: pass thru mtime for directory archives, like other archive types do
James May <james.may@draeger.com>
parents: 33545
diff changeset
   268
            os.utime(destfile, (self.mtime, self.mtime))
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   269
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   270
    def done(self):
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   271
        pass
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   272
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   273
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   274
archivers = {
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   275
    b'files': fileit,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   276
    b'tar': tarit,
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   277
    b'tbz2': lambda name, mtime: tarit(name, mtime, b'bz2'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   278
    b'tgz': lambda name, mtime: tarit(name, mtime, b'gz'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   279
    b'txz': lambda name, mtime: tarit(name, mtime, b'xz'),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   280
    b'uzip': lambda name, mtime: zipit(name, mtime, False),
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   281
    b'zip': zipit,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   282
}
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   283
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   284
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   285
def archive(
51859
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
   286
    repo: "localrepo.localrepository",
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
   287
    dest,  # TODO: should be bytes, but could be Callable
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   288
    node,
51859
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
   289
    kind: bytes,
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
   290
    decode: bool = True,
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   291
    match=None,
51859
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
   292
    prefix: bytes = b'',
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
   293
    mtime: Optional[float] = None,
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
   294
    subrepos: bool = False,
b60f25f00e94 typing: add explicit hints for recent pytype regressions
Matt Harbison <matt_harbison@yahoo.com>
parents: 51838
diff changeset
   295
) -> int:
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45083
diff changeset
   296
    """create archive of repo as it was at node.
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   297
51838
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   298
    dest can be name of directory, name of archive file, a callable, or file
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   299
    object to write archive to. If it is a callable, it will called to open
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   300
    the actual file object before the first archive member is written.
2112
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
    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
   303
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   304
    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
   305
    hgrc.
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   306
40407
3d76a8e627a6 archive: change "matcnfn" argument to a real matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 40247
diff changeset
   307
    match is a matcher to filter names of files to write to archive.
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   308
35202
760fef6aca74 archive: pass thru mtime for directory archives, like other archive types do
James May <james.may@draeger.com>
parents: 33545
diff changeset
   309
    prefix is name of path to put before every archive member.
760fef6aca74 archive: pass thru mtime for directory archives, like other archive types do
James May <james.may@draeger.com>
parents: 33545
diff changeset
   310
760fef6aca74 archive: pass thru mtime for directory archives, like other archive types do
James May <james.may@draeger.com>
parents: 33545
diff changeset
   311
    mtime is the modified time, in seconds, or None to use the changeset time.
760fef6aca74 archive: pass thru mtime for directory archives, like other archive types do
James May <james.may@draeger.com>
parents: 33545
diff changeset
   312
760fef6aca74 archive: pass thru mtime for directory archives, like other archive types do
James May <james.may@draeger.com>
parents: 33545
diff changeset
   313
    subrepos tells whether to include subrepos.
45942
89a2afe31e82 formating: upgrade to black 20.8b1
Augie Fackler <raf@durin42.com>
parents: 45083
diff changeset
   314
    """
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   315
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   316
    if kind == b'files':
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   317
        if prefix:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   318
            raise error.Abort(_(b'cannot give prefix when archiving to files'))
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   319
    else:
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   320
        prefix = tidyprefix(dest, kind, prefix)
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   321
51838
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   322
    archiver = None
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   323
    ctx = repo[node]
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   324
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   325
    def opencallback():
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   326
        """Return the archiver instance, creating it if necessary.
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   327
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   328
        This function is called when the first actual entry is created.
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   329
        It may be called multiple times from different layers.
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   330
        When serving the archive via hgweb, no errors should happen after
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   331
        this point.
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   332
        """
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   333
        nonlocal archiver
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   334
        if archiver is None:
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   335
            if callable(dest):
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   336
                output = dest()
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   337
            else:
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   338
                output = dest
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   339
            archiver = archivers[kind](output, mtime or ctx.date()[0])
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   340
            assert archiver is not None
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   341
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   342
            if repo.ui.configbool(b"ui", b"archivemeta"):
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   343
                metaname = b'.hg_archival.txt'
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   344
                if match(metaname):
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   345
                    write(metaname, 0o644, False, lambda: buildmetadata(ctx))
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   346
        return archiver
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   347
4951
667290b6c95e archive: delay extraction of file revisions
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4831
diff changeset
   348
    def write(name, mode, islink, getdata):
51838
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   349
        if archiver is None:
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   350
            opencallback()
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   351
        assert archiver is not None, "archive should be opened by now"
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   352
4951
667290b6c95e archive: delay extraction of file revisions
Alexis S. L. Carvalho <alexis@cecm.usp.br>
parents: 4831
diff changeset
   353
        data = getdata()
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   354
        if decode:
4005
656e06eebda7 replace filehandle version of wwrite with wwritedata
Matt Mackall <mpm@selenic.com>
parents: 3968
diff changeset
   355
            data = repo.wwritedata(name, data)
11558
d8f6458434ec archival: remove prefix argument from archivers
Martin Geisler <mg@lazybytes.net>
parents: 11557
diff changeset
   356
        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
   357
6019
b70a530bdb93 cleanly abort on unknown archive type (issue966)
Dirkjan Ochtman <dirkjan@ochtman.nl>
parents: 4951
diff changeset
   358
    if kind not in archivers:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   359
        raise error.Abort(_(b"unknown archive type '%s'") % kind)
6749
51b0e799352f manifest: remove execf/linkf methods
Matt Mackall <mpm@selenic.com>
parents: 6747
diff changeset
   360
40408
997997eb8367 archive: create alwaysmatcher when no matcher provided
Martin von Zweigbergk <martinvonz@google.com>
parents: 40407
diff changeset
   361
    if not match:
997997eb8367 archive: create alwaysmatcher when no matcher provided
Martin von Zweigbergk <martinvonz@google.com>
parents: 40407
diff changeset
   362
        match = scmutil.matchall(repo)
997997eb8367 archive: create alwaysmatcher when no matcher provided
Martin von Zweigbergk <martinvonz@google.com>
parents: 40407
diff changeset
   363
44284
e786d69c665d archival: use walk() instead of matches() on manifest
Augie Fackler <augie@google.com>
parents: 43506
diff changeset
   364
    files = list(ctx.manifest().walk(match))
16919
51932c835b74 archive: make progress only show files that are actually archived
Thomas Arendsen Hein <thomas@intevation.de>
parents: 15057
diff changeset
   365
    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
   366
    if total:
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   367
        files.sort()
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   368
        scmutil.prefetchfiles(
45072
a56ba57c837d scmutil: allowing different files to be prefetched per revision
Rodrigo Damazio Bovendorp <rdamazio@google.com>
parents: 44577
diff changeset
   369
            repo, [(ctx.rev(), scmutil.matchfiles(repo, files))]
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   370
        )
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   371
        progress = repo.ui.makeprogress(
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   372
            _(b'archiving'), unit=_(b'files'), total=total
43076
2372284d9457 formatting: blacken the codebase
Augie Fackler <augie@google.com>
parents: 42940
diff changeset
   373
        )
38381
1a2ff11e8a88 archival: use progress helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 37762
diff changeset
   374
        progress.update(0)
1a2ff11e8a88 archival: use progress helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 37762
diff changeset
   375
        for f in files:
18967
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   376
            ff = ctx.flags(f)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   377
            write(f, b'x' in ff and 0o755 or 0o644, b'l' in ff, ctx[f].data)
38381
1a2ff11e8a88 archival: use progress helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 37762
diff changeset
   378
            progress.increment(item=f)
1a2ff11e8a88 archival: use progress helper
Martin von Zweigbergk <martinvonz@google.com>
parents: 37762
diff changeset
   379
        progress.complete()
12323
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12321
diff changeset
   380
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12321
diff changeset
   381
    if subrepos:
18364
6252b4f1c4b4 subrepos: process subrepos in sorted order
Mads Kiilerich <mads@kiilerich.com>
parents: 18344
diff changeset
   382
        for subpath in sorted(ctx.substate):
25601
3ec8351fa6ed archive: support 'wdir()'
Matt Harbison <matt_harbison@yahoo.com>
parents: 25149
diff changeset
   383
            sub = ctx.workingsub(subpath)
40407
3d76a8e627a6 archive: change "matcnfn" argument to a real matcher
Martin von Zweigbergk <martinvonz@google.com>
parents: 40247
diff changeset
   384
            submatch = matchmod.subdirmatcher(subpath, match)
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   385
            subprefix = prefix + subpath + b'/'
51838
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   386
            total += sub.archive(opencallback, subprefix, 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
   387
88d1b59f6906 archive: raise error.Abort if the file pattern matches no files
Angel Ezquerra <angel.ezquerra@gmail.com>
parents: 18364
diff changeset
   388
    if total == 0:
43077
687b865b95ad formatting: byteify all mercurial/ and hgext/ string literals
Augie Fackler <augie@google.com>
parents: 43076
diff changeset
   389
        raise error.Abort(_(b'no files match the archive pattern'))
12323
f00953d9533c subrepo: add support for 'hg archive'
Martin Geisler <mg@aragost.com>
parents: 12321
diff changeset
   390
51838
3b8d92f71d92 archive: defer opening the output until a file is matched
Joerg Sonnenberger <joerg@bec.de>
parents: 49803
diff changeset
   391
    assert archiver is not None, "archive should have been opened before"
2112
2b03c6733efa add "archive" command, like "cvs export" only better.
Vadim Gelfer <vadim.gelfer@gmail.com>
parents:
diff changeset
   392
    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
   393
    return total