File: bundle.py

package info (click to toggle)
hg-git 1.2.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid, trixie
  • size: 1,244 kB
  • sloc: python: 8,702; sh: 185; makefile: 23
file content (135 lines) | stat: -rw-r--r-- 3,920 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
import io

from mercurial import bundle2
from mercurial import exchange
from mercurial import exthelper

from mercurial.node import bin, hex


eh = exthelper.exthelper()

CAPABILITY_MAP = b'exp-hg-git-map'
CAPABILITY_TAGS = b'exp-hg-git-tags'
BUNDLEPART_MAP = b'exp-hg-git-map'
BUNDLEPART_TAGS = b'exp-hg-git-tags'


@eh.wrapfunction(bundle2, 'getrepocaps')
def getrepocaps(orig, repo, **kwargs):
    caps = orig(repo, **kwargs)

    if repo.ui.configbool(b'experimental', b'hg-git-serve'):
        caps[CAPABILITY_MAP] = ()
        caps[CAPABILITY_TAGS] = ()

    return caps


def addpartrevgitmap(repo, bundler, outgoing):
    if repo.githandler:
        # this is different from what we store in the repository,
        # and uses binary node ids: <20 bytes> <20 bytes>
        repo.ui.debug(b'bundling git map\n')

        chunks = (
            bin(repo.githandler._map_hg[hex(hgnode)]) + hgnode
            for hgnode in outgoing.missing
            if hex(hgnode) in repo.githandler._map_hg
        )

        bundler.newpart(BUNDLEPART_MAP, data=chunks, mandatory=False)


def addpartrevgittags(repo, bundler, outgoing):
    if repo.githandler.tags:
        # this is consistent with the format used in the repository:
        # <40 hex digits> <space> <tag name> <newline>
        repo.ui.debug(b'bundling git tags\n')

        chunks = (
            b"%s %s\n" % (sha, name)
            for name, sha in sorted(repo.githandler.tags.items())
            if bin(sha) in outgoing.missing
        )

        bundler.newpart(BUNDLEPART_TAGS, data=chunks, mandatory=False)


@eh.wrapfunction(bundle2, '_addpartsfromopts')
def _addpartsfromopts(orig, ui, repo, bundler, source, outgoing, opts):
    orig(ui, repo, bundler, source, outgoing, opts)

    if opts.get(CAPABILITY_MAP, False) or ui.configbool(
        b'experimental', b'hg-git-bundle'
    ):
        addpartrevgitmap(repo, bundler, outgoing)

    if opts.get(CAPABILITY_TAGS, False) or ui.configbool(
        b'experimental', b'hg-git-bundle'
    ):
        addpartrevgittags(repo, bundler, outgoing)


@eh.extsetup
def install_server_support(ui):
    @bundle2.parthandler(BUNDLEPART_MAP)
    def handlebundlemap(op, inpart):
        ui.debug(b'unbundling git map\n')

        while not inpart.consumed:
            # this is different from what we store in the repository,
            # and uses binary node ids: <20 bytes> <20 bytes>
            gitsha = hex(inpart.read(20))
            hgsha = hex(inpart.read(20))

            if gitsha and hgsha:
                op.repo.githandler.map_set(gitsha, hgsha)

        op.repo.githandler.save_map()

    @exchange.getbundle2partsgenerator(BUNDLEPART_MAP)
    def gitmapbundle(
        bundler, repo, source, bundlecaps=None, b2caps=None, **kwargs
    ):
        if b2caps is None or CAPABILITY_MAP not in b2caps:
            return

        ui.debug(b'bundling git map\n')

        outgoing = exchange._computeoutgoing(
            repo,
            kwargs['heads'],
            kwargs['common'],
        )

        addpartrevgitmap(repo, bundler, outgoing)

    @bundle2.parthandler(BUNDLEPART_TAGS)
    def handlebundletags(op, inpart):
        with io.BytesIO() as buf:
            while not inpart.consumed:
                buf.write(inpart.read())

            buf.seek(0)

            # we're consistent, and always load everything, so just
            # let the handler do its thing
            op.repo.githandler._read_tags_from(buf)

        op.repo.githandler.save_tags()

    @exchange.getbundle2partsgenerator(BUNDLEPART_TAGS)
    def gittagbundle(
        bundler, repo, source, bundlecaps=None, b2caps=None, **kwargs
    ):
        if b2caps is None or CAPABILITY_TAGS not in b2caps:
            return

        outgoing = exchange._computeoutgoing(
            repo,
            kwargs['heads'],
            kwargs['common'],
        )

        addpartrevgittags(repo, bundler, outgoing)