hgext/fastexport.py
author Matt Harbison <matt_harbison@yahoo.com>
Thu, 24 Oct 2024 22:47:31 -0400
changeset 52127 fd200f5bcaea
parent 51863 f4733654f144
permissions -rw-r--r--
wireprototypes: make `baseprotocolhandler` methods abstract The documentation says it's an abstract base class, so let's enforce it. The `typing.Protocol` class is already an ABC, but it only prevents instantiation if there are abstract attrs that are missing. For example, from `hg debugshell`: >>> from mercurial import wireprototypes >>> x = wireprototypes.baseprotocolhandler() Traceback (most recent call last): File "<console>", line 1, in <module> TypeError: Can't instantiate abstract class baseprotocolhandler with abstract method name >>> class fake(wireprototypes.baseprotocolhandler): ... pass ... >>> x = fake() Traceback (most recent call last): File "<console>", line 1, in <module> TypeError: Can't instantiate abstract class fake with abstract method name That's great, but it doesn't protect against calling non-abstract methods at runtime, rather it depends on the protocol type hint being added to method signatures or class attrs, and then running a type checker to notice when an instance is assigned that doesn't conform to the protocol. We don't widely use type hints yet, and do have a lot of class hierarchy in the repository area, which could lead to surprises like this: >>> class fake(wireprototypes.baseprotocolhandler): ... @property ... def name(self) -> bytes: ... return b'name' ... >>> z = fake() >>> z.client() >>> print(z.client()) None Oops. That was supposed to return `bytes`. So not only is a bad/unexpected value returned, but it's one that violates the type hints (since the base client() method will be annotated to return bytes). With this change, we get: >>> from mercurial import wireprototypes >>> class fake(wireprototypes.baseprotocolhandler): ... @property ... def name(self) -> bytes: ... return b'name' ... >>> x = fake() Traceback (most recent call last): File "<console>", line 1, in <module> TypeError: Can't instantiate abstract class fake with abstract methods addcapabilities, checkperm, client, getargs, getpayload, getprotocaps, mayberedirectstdio So this looks like a reasonable safety harness to me, and lets us catch problems by running the standard tests while the type hints are being added, and pytype is improved. We should probably do this for all Protocol class methods that don't supply a method implementation.
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
     1
# Copyright 2020 Joerg Sonnenberger <joerg@bec.de>
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
     2
#
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
     3
# This software may be used and distributed according to the terms of the
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
     4
# GNU General Public License version 2 or any later version.
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
     5
"""export repositories as git fast-import stream"""
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
     6
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
     7
# The format specification for fast-import streams can be found at
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
     8
# https://git-scm.com/docs/git-fast-import#_input_format
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
     9
51863
f4733654f144 typing: add `from __future__ import annotations` to most files
Matt Harbison <matt_harbison@yahoo.com>
parents: 50994
diff changeset
    10
from __future__ import annotations
f4733654f144 typing: add `from __future__ import annotations` to most files
Matt Harbison <matt_harbison@yahoo.com>
parents: 50994
diff changeset
    11
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    12
import re
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    13
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    14
from mercurial.i18n import _
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    15
from mercurial.node import hex, nullrev
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    16
from mercurial.utils import stringutil
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    17
from mercurial import (
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    18
    error,
48116
5ced12cfa41b errors: raise InputError on bad revset to revrange() iff provided by the user
Martin von Zweigbergk <martinvonz@google.com>
parents: 44821
diff changeset
    19
    logcmdutil,
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    20
    registrar,
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    21
    scmutil,
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    22
)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    23
from .convert import convcmd
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    24
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    25
# Note for extension authors: ONLY specify testedwith = 'ships-with-hg-core' for
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    26
# extensions which SHIP WITH MERCURIAL. Non-mainline extensions should
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    27
# be specifying the version(s) of Mercurial they are tested with, or
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    28
# leave the attribute unspecified.
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    29
testedwith = b"ships-with-hg-core"
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    30
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    31
cmdtable = {}
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    32
command = registrar.command(cmdtable)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    33
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    34
GIT_PERSON_PROHIBITED = re.compile(b'[<>\n"]')
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    35
GIT_EMAIL_PROHIBITED = re.compile(b"[<> \n]")
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    36
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    37
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    38
def convert_to_git_user(authormap, user, rev):
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    39
    mapped_user = authormap.get(user, user)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    40
    user_person = stringutil.person(mapped_user)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    41
    user_email = stringutil.email(mapped_user)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    42
    if GIT_EMAIL_PROHIBITED.match(user_email) or GIT_PERSON_PROHIBITED.match(
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    43
        user_person
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    44
    ):
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    45
        raise error.Abort(
44690
44aff45b556d fastexport: make a diagnostics message more localizable
Joerg Sonnenberger <joerg@bec.de>
parents: 44280
diff changeset
    46
            _(b"Unable to parse user into person and email for revision %s")
44aff45b556d fastexport: make a diagnostics message more localizable
Joerg Sonnenberger <joerg@bec.de>
parents: 44280
diff changeset
    47
            % rev
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    48
        )
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    49
    if user_person:
50994
a97f2b50219b fastexport: simplify code
Joerg Sonnenberger <joerg@bec.de>
parents: 50875
diff changeset
    50
        return b'"%s" <%s>' % (user_person, user_email)
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    51
    else:
50994
a97f2b50219b fastexport: simplify code
Joerg Sonnenberger <joerg@bec.de>
parents: 50875
diff changeset
    52
        return b"<%s>" % user_email
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    53
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    54
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    55
def convert_to_git_date(date):
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    56
    timestamp, utcoff = date
44821
edffab2cf0ea fastexport: adjust output to be more canonical
Joerg Sonnenberger <joerg@bec.de>
parents: 44811
diff changeset
    57
    tzsign = b"+" if utcoff <= 0 else b"-"
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    58
    if utcoff % 60 != 0:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    59
        raise error.Abort(
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    60
            _(b"UTC offset in %b is not an integer number of seconds") % (date,)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    61
        )
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    62
    utcoff = abs(utcoff) // 60
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    63
    tzh = utcoff // 60
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    64
    tzmin = utcoff % 60
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    65
    return b"%d " % int(timestamp) + tzsign + b"%02d%02d" % (tzh, tzmin)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    66
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    67
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    68
def convert_to_git_ref(branch):
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    69
    # XXX filter/map depending on git restrictions
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    70
    return b"refs/heads/" + branch
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    71
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    72
50401
dd42156b6441 fastexport: rework newline logic
Felipe Contreras <felipe.contreras@gmail.com>
parents: 48875
diff changeset
    73
def write_data(buf, data, add_newline=False):
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    74
    buf.append(b"data %d\n" % len(data))
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    75
    buf.append(data)
50401
dd42156b6441 fastexport: rework newline logic
Felipe Contreras <felipe.contreras@gmail.com>
parents: 48875
diff changeset
    76
    if add_newline or data[-1:] != b"\n":
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    77
        buf.append(b"\n")
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    78
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    79
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    80
def export_commit(ui, repo, rev, marks, authormap):
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    81
    ctx = repo[rev]
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    82
    revid = ctx.hex()
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    83
    if revid in marks:
44811
5d309906ed0e fastexport: downgrade message about already exported changesets to debug
Joerg Sonnenberger <joerg@bec.de>
parents: 44690
diff changeset
    84
        ui.debug(b"warning: revision %s already exported, skipped\n" % revid)
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    85
        return
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    86
    parents = [p for p in ctx.parents() if p.rev() != nullrev]
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    87
    for p in parents:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    88
        if p.hex() not in marks:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    89
            ui.warn(
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    90
                _(b"warning: parent %s of %s has not been exported, skipped\n")
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    91
                % (p, revid)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    92
            )
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    93
            return
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    94
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    95
    # For all files modified by the commit, check if they have already
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    96
    # been exported and otherwise dump the blob with the new mark.
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    97
    for fname in ctx.files():
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    98
        if fname not in ctx:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
    99
            continue
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   100
        filectx = ctx.filectx(fname)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   101
        filerev = hex(filectx.filenode())
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   102
        if filerev not in marks:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   103
            mark = len(marks) + 1
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   104
            marks[filerev] = mark
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   105
            data = filectx.data()
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   106
            buf = [b"blob\n", b"mark :%d\n" % mark]
50401
dd42156b6441 fastexport: rework newline logic
Felipe Contreras <felipe.contreras@gmail.com>
parents: 48875
diff changeset
   107
            write_data(buf, data, True)
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   108
            ui.write(*buf, keepprogressbar=True)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   109
            del buf
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   110
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   111
    # Assign a mark for the current revision for references by
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   112
    # latter merge commits.
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   113
    mark = len(marks) + 1
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   114
    marks[revid] = mark
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   115
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   116
    ref = convert_to_git_ref(ctx.branch())
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   117
    buf = [
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   118
        b"commit %s\n" % ref,
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   119
        b"mark :%d\n" % mark,
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   120
        b"committer %s %s\n"
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   121
        % (
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   122
            convert_to_git_user(authormap, ctx.user(), revid),
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   123
            convert_to_git_date(ctx.date()),
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   124
        ),
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   125
    ]
50401
dd42156b6441 fastexport: rework newline logic
Felipe Contreras <felipe.contreras@gmail.com>
parents: 48875
diff changeset
   126
    write_data(buf, ctx.description())
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   127
    if parents:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   128
        buf.append(b"from :%d\n" % marks[parents[0].hex()])
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   129
    if len(parents) == 2:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   130
        buf.append(b"merge :%d\n" % marks[parents[1].hex()])
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   131
        p0ctx = repo[parents[0]]
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   132
        files = ctx.manifest().diff(p0ctx.manifest())
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   133
    else:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   134
        files = ctx.files()
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   135
    filebuf = []
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   136
    for fname in files:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   137
        if fname not in ctx:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   138
            filebuf.append((fname, b"D %s\n" % fname))
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   139
        else:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   140
            filectx = ctx.filectx(fname)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   141
            filerev = filectx.filenode()
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   142
            fileperm = b"755" if filectx.isexec() else b"644"
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   143
            changed = b"M %s :%d %s\n" % (fileperm, marks[hex(filerev)], fname)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   144
            filebuf.append((fname, changed))
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   145
    filebuf.sort()
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   146
    buf.extend(changed for (fname, changed) in filebuf)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   147
    del filebuf
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   148
    buf.append(b"\n")
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   149
    ui.write(*buf, keepprogressbar=True)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   150
    del buf
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   151
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   152
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   153
isrev = re.compile(b"^[0-9a-f]{40}$")
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   154
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   155
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   156
@command(
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   157
    b"fastexport",
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   158
    [
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   159
        (b"r", b"rev", [], _(b"revisions to export"), _(b"REV")),
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   160
        (b"i", b"import-marks", b"", _(b"old marks file to read"), _(b"FILE")),
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   161
        (b"e", b"export-marks", b"", _(b"new marks file to write"), _(b"FILE")),
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   162
        (
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   163
            b"A",
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   164
            b"authormap",
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   165
            b"",
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   166
            _(b"remap usernames using this file"),
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   167
            _(b"FILE"),
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   168
        ),
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   169
    ],
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   170
    _(b"[OPTION]... [REV]..."),
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   171
    helpcategory=command.CATEGORY_IMPORT_EXPORT,
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   172
)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   173
def fastexport(ui, repo, *revs, **opts):
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   174
    """export repository as git fast-import stream
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   175
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   176
    This command lets you dump a repository as a human-readable text stream.
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   177
    It can be piped into corresponding import routines like "git fast-import".
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   178
    Incremental dumps can be created by using marks files.
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   179
    """
50875
00081fa564ed fastexport: migrate `opts` to native kwargs
Matt Harbison <matt_harbison@yahoo.com>
parents: 50401
diff changeset
   180
    revs += tuple(opts.get("rev", []))
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   181
    if not revs:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   182
        revs = scmutil.revrange(repo, [b":"])
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   183
    else:
48116
5ced12cfa41b errors: raise InputError on bad revset to revrange() iff provided by the user
Martin von Zweigbergk <martinvonz@google.com>
parents: 44821
diff changeset
   184
        revs = logcmdutil.revrange(repo, revs)
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   185
    if not revs:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   186
        raise error.Abort(_(b"no revisions matched"))
50875
00081fa564ed fastexport: migrate `opts` to native kwargs
Matt Harbison <matt_harbison@yahoo.com>
parents: 50401
diff changeset
   187
    authorfile = opts.get("authormap")
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   188
    if authorfile:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   189
        authormap = convcmd.readauthormap(ui, authorfile)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   190
    else:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   191
        authormap = {}
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   192
50875
00081fa564ed fastexport: migrate `opts` to native kwargs
Matt Harbison <matt_harbison@yahoo.com>
parents: 50401
diff changeset
   193
    import_marks = opts.get("import_marks")
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   194
    marks = {}
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   195
    if import_marks:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   196
        with open(import_marks, "rb") as import_marks_file:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   197
            for line in import_marks_file:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   198
                line = line.strip()
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   199
                if not isrev.match(line) or line in marks:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   200
                    raise error.Abort(_(b"Corrupted marks file"))
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   201
                marks[line] = len(marks) + 1
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   202
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   203
    revs.sort()
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   204
    with ui.makeprogress(
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   205
        _(b"exporting"), unit=_(b"revisions"), total=len(revs)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   206
    ) as progress:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   207
        for rev in revs:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   208
            export_commit(ui, repo, rev, marks, authormap)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   209
            progress.increment()
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   210
50875
00081fa564ed fastexport: migrate `opts` to native kwargs
Matt Harbison <matt_harbison@yahoo.com>
parents: 50401
diff changeset
   211
    export_marks = opts.get("export_marks")
44280
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   212
    if export_marks:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   213
        with open(export_marks, "wb") as export_marks_file:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   214
            output_marks = [None] * len(marks)
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   215
            for k, v in marks.items():
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   216
                output_marks[v - 1] = k
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   217
            for k in output_marks:
93a05cb223da hgext: initial version of fastexport extension
Joerg Sonnenberger <joerg@bec.de>
parents:
diff changeset
   218
                export_marks_file.write(k + b"\n")