/breezy-debian/trunk

To get this branch, use:
bzr branch https://code.breezy-vcs.org/breezy-debian/trunk
226.2.18 by Jelmer Vernooij
Add simple directory service.
1
#    directory.py -- Directory service that uses Debian Vcs-* fields
2
#    Copyright (C) 2008 Jelmer Vernooij <jelmer@samba.org>
1007 by Jelmer Vernooij
Some reformatting.
3
#
226.2.18 by Jelmer Vernooij
Add simple directory service.
4
#    This file is part of bzr-builddeb.
5
#
6
#    bzr-builddeb is free software; you can redistribute it and/or modify
7
#    it under the terms of the GNU General Public License as published by
8
#    the Free Software Foundation; either version 2 of the License, or
9
#    (at your option) any later version.
10
#
11
#    bzr-builddeb is distributed in the hope that it will be useful,
12
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
13
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
#    GNU General Public License for more details.
15
#
16
#    You should have received a copy of the GNU General Public License
17
#    along with bzr-builddeb; if not, write to the Free Software
18
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
#
20
750 by Jelmer Vernooij
use relative imports.
21
from __future__ import absolute_import
22
1022 by Jelmer Vernooij
Support subpaths in URLs.
23
import re
1057 by Jelmer Vernooij
Avoid sixish.
24
import sys
1022 by Jelmer Vernooij
Support subpaths in URLs.
25
798.1.1 by Jelmer Vernooij
Fix import - InvalidURL lives in breezy.urlutils now.
26
from ... import urlutils
825 by Jelmer Vernooij
Use deb822 for parsing source package control files.
27
from ...directory_service import directories
1049 by Jelmer Vernooij
Handle missing apt_pkg.
28
from ...errors import DependencyNotPresent
993 by Jelmer Vernooij
Attempt to fixup a common misspelling URLs in Vcs-GGit URLs.
29
from ...trace import note, warning
226.2.18 by Jelmer Vernooij
Add simple directory service.
30
825 by Jelmer Vernooij
Use deb822 for parsing source package control files.
31
from debian.deb822 import Deb822
829 by Jelmer Vernooij
Python3 compat.
32
from debian.changelog import Version
226.2.18 by Jelmer Vernooij
Add simple directory service.
33
34
993 by Jelmer Vernooij
Attempt to fixup a common misspelling URLs in Vcs-GGit URLs.
35
def fixup_broken_git_url(url):
36
    """Attempt to fix up broken Git URLs.
37
38
    A common misspelling is to add an extra ":" after the hostname
39
    """
40
    (scheme, netloc, path, params,
41
     query, fragment) = urlutils.urlparse.urlparse(url, allow_fragments=False)
42
    if '@' in netloc:
43
        credentials, host = netloc.rsplit('@', 1)
44
    else:
45
        credentials = None
46
        host = netloc
47
48
    if ':' in host and not (host[0] == '[' and host[-1] == ']'):
49
        # there *is* port
50
        host, port = host.rsplit(':', 1)
996 by Jelmer Vernooij
Handle another kind of git dated version strings.
51
        if not port or port.isdigit():
993 by Jelmer Vernooij
Attempt to fixup a common misspelling URLs in Vcs-GGit URLs.
52
            return url
1003 by Jelmer Vernooij
Handle corner case when port is not set.
53
    else:
54
        port = None
55
997 by Jelmer Vernooij
Fixup some more vcs URLs.
56
    if host in ('salsa.debian.org', 'github.com'):
1003 by Jelmer Vernooij
Handle corner case when port is not set.
57
        if '/' not in path[1:] and port:
997 by Jelmer Vernooij
Fixup some more vcs URLs.
58
            path = '%s/%s' % (port, path.lstrip('/'))
993 by Jelmer Vernooij
Attempt to fixup a common misspelling URLs in Vcs-GGit URLs.
59
        netloc = host
60
        if ":" in netloc:
61
            netloc = "[%s]" % netloc
1021 by Jelmer Vernooij
Strip git@ username for public github/salsa repositories.
62
        if (credentials is not None and
63
            not (credentials == 'git' and
64
                 scheme not in ('git', 'http', 'https'))):
993 by Jelmer Vernooij
Attempt to fixup a common misspelling URLs in Vcs-GGit URLs.
65
            netloc = '%s@%s' % (credentials, netloc)
997 by Jelmer Vernooij
Fixup some more vcs URLs.
66
        if host == 'salsa.debian.org':
67
            scheme = 'https'
68
        if host == 'salsa.debian.org' and path.startswith('/cgit/'):
69
            path = path[5:]
993 by Jelmer Vernooij
Attempt to fixup a common misspelling URLs in Vcs-GGit URLs.
70
        new_url = urlutils.urlparse.urlunparse(
71
            (scheme, netloc, path, params, query, fragment))
1001 by Jelmer Vernooij
Only print message about fixing up URLs if something actually changed.
72
        if url != new_url:
73
            warning('Fixing up URL: %s -> %s', url, new_url)
993 by Jelmer Vernooij
Attempt to fixup a common misspelling URLs in Vcs-GGit URLs.
74
        return new_url
75
    return url
76
77
824 by Jelmer Vernooij
Split out vcs_git_url_to_bzr_url and vcs_bzr_url_to_bzr_url.
78
def vcs_git_url_to_bzr_url(url):
79
    """Convert a Vcs-Git string to a Breezy URL."""
826 by Jelmer Vernooij
heavy refactoring of .directory.
80
1022 by Jelmer Vernooij
Support subpaths in URLs.
81
    # some packages seem to use [PATH] behind the URL to
826 by Jelmer Vernooij
heavy refactoring of .directory.
82
    # indicate a subdirectory inside of the versioned tree.
83
    # (this is not documented in policy)
84
1022 by Jelmer Vernooij
Support subpaths in URLs.
85
    m = re.finditer(r' \[([^] ]+)\]', url)
86
    try:
87
        m = next(m)
88
        url = url[:m.start()] + url[m.end():]
89
        subpath = m.group(1)
90
    except StopIteration:
91
        subpath = None
92
824 by Jelmer Vernooij
Split out vcs_git_url_to_bzr_url and vcs_bzr_url_to_bzr_url.
93
    from breezy.git.urls import git_url_to_bzr_url
94
    if ' -b ' in url:
95
        (url, branch) = url.split(' -b ', 1)
96
    else:
97
        branch = None
993 by Jelmer Vernooij
Attempt to fixup a common misspelling URLs in Vcs-GGit URLs.
98
99
    url = fixup_broken_git_url(url)
824 by Jelmer Vernooij
Split out vcs_git_url_to_bzr_url and vcs_bzr_url_to_bzr_url.
100
    url = git_url_to_bzr_url(url)
101
    if branch:
102
        branch = urlutils.quote(branch, '')
103
        url = urlutils.join_segment_parameters(
855 by Jelmer Vernooij
Fix Python 3 compatibility.
104
            url, {'branch': branch})
1022 by Jelmer Vernooij
Support subpaths in URLs.
105
    if subpath:
106
        url = urlutils.join(url, subpath)
824 by Jelmer Vernooij
Split out vcs_git_url_to_bzr_url and vcs_bzr_url_to_bzr_url.
107
    return url
108
109
110
def vcs_bzr_url_to_bzr_url(url):
111
    return directories.dereference(url)
112
113
826 by Jelmer Vernooij
heavy refactoring of .directory.
114
def vcs_darcs_url_to_bzr_url(url):
115
    return url
116
117
118
def vcs_hg_url_to_bzr_url(url):
1024 by Jelmer Vernooij
Support -b in Vcs-Hg URLs.
119
    if ' -b ' in url:
120
        (url, branch) = url.split(' -b ', 1)
121
    else:
122
        branch = None
123
124
    if branch:
125
        branch = urlutils.quote(branch, '')
126
        url = urlutils.join_segment_parameters(
127
            url, {'branch': branch})
826 by Jelmer Vernooij
heavy refactoring of .directory.
128
    return url
129
130
131
def vcs_svn_url_to_bzr_url(url):
132
    return url
133
134
135
vcs_field_to_bzr_url_converters = [
136
    ("Bzr", vcs_bzr_url_to_bzr_url),
137
    ("Darcs", vcs_darcs_url_to_bzr_url),
138
    ("Svn", vcs_svn_url_to_bzr_url),
139
    ("Git", vcs_git_url_to_bzr_url),
140
    ("Hg", vcs_hg_url_to_bzr_url)
141
]
142
143
1094 by Jelmer Vernooij
Split out functionality for finding VCS URL.
144
def source_package_vcs(control):
145
    """Extract the Vcs URL from a source package.
146
147
    Args:
148
      control: A source control paragraph
149
    Returns:
150
      Tuple with Vcs type and Vcs URL
151
    Raises:
152
      KeyError: When no Vcs header was found
153
    """
154
    for prefix in ['Vcs-', 'XS-Vcs-', 'X-Vcs']:
155
        for field, value in control.items():
156
            if field.startswith(prefix):
157
                vcs_type = field[len(prefix):]
158
                if vcs_type == 'Browser':
159
                    continue
160
                return vcs_type, value
161
    raise KeyError
162
163
826 by Jelmer Vernooij
heavy refactoring of .directory.
164
def source_package_vcs_url(control):
165
    """Extract a Breezy-compatible URL from a source package.
166
    """
1094 by Jelmer Vernooij
Split out functionality for finding VCS URL.
167
    (vcs_type, vcs_url) = source_package_vcs(control)
1096 by Jelmer Vernooij
Fix apt: directory.
168
    return vcs_type, dict(vcs_field_to_bzr_url_converters)[vcs_type](vcs_url)
826 by Jelmer Vernooij
heavy refactoring of .directory.
169
170
922 by Jelmer Vernooij
Add a 'vcs:' location resolver that uses the location provided by
171
class AptDirectory(object):
226.2.18 by Jelmer Vernooij
Add simple directory service.
172
    """Simple Bazaar directory service which uses dpkg Vcs-* fields."""
173
174
    def look_up(self, name, url):
175
        if "/" in name:
176
            (name, version) = name.split("/", 1)
177
        else:
178
            version = None
179
1049 by Jelmer Vernooij
Handle missing apt_pkg.
180
        try:
181
            import apt_pkg
182
        except ImportError as e:
183
            raise DependencyNotPresent('apt_pkg', e)
226.2.19 by Jelmer Vernooij
Use apt_pkg rather than parsing the output of apt-cache.
184
        apt_pkg.init()
185
811 by Jelmer Vernooij
Simplify handling of apt: URLs.
186
        sources = apt_pkg.SourceRecords()
226.2.18 by Jelmer Vernooij
Add simple directory service.
187
826 by Jelmer Vernooij
heavy refactoring of .directory.
188
        by_version = {}
822 by Jelmer Vernooij
Add dgit: directory.
189
        while sources.lookup(name):
826 by Jelmer Vernooij
heavy refactoring of .directory.
190
            by_version[sources.version] = sources.record
226.2.18 by Jelmer Vernooij
Add simple directory service.
191
826 by Jelmer Vernooij
heavy refactoring of .directory.
192
        if len(by_version) == 0:
193
            raise urlutils.InvalidURL(path=url, extra='package not found')
226.2.18 by Jelmer Vernooij
Add simple directory service.
194
195
        if version is None:
196
            # Try the latest version
829 by Jelmer Vernooij
Python3 compat.
197
            version = sorted(by_version, key=Version)[-1]
226.2.18 by Jelmer Vernooij
Add simple directory service.
198
1007 by Jelmer Vernooij
Some reformatting.
199
        if version not in by_version:
200
            raise urlutils.InvalidURL(
201
                path=url, extra='version %s not found' % version)
811 by Jelmer Vernooij
Simplify handling of apt: URLs.
202
826 by Jelmer Vernooij
heavy refactoring of .directory.
203
        control = Deb822(by_version[version])
204
205
        try:
882.1.2 by Jelmer Vernooij
Return Vcs type in source_package_vcs_url.
206
            vcs, url = source_package_vcs_url(control)
826 by Jelmer Vernooij
heavy refactoring of .directory.
207
        except KeyError:
1007 by Jelmer Vernooij
Some reformatting.
208
            note("Retrieving Vcs locating from %s Debian version %s", name,
209
                 version)
826 by Jelmer Vernooij
heavy refactoring of .directory.
210
            raise urlutils.InvalidURL(path=url, extra='no VCS URL found')
812 by Jelmer Vernooij
Display resolved branch URL in apt: directory.
211
1007 by Jelmer Vernooij
Some reformatting.
212
        note("Resolved package URL from Debian package %s/%s: %s",
213
             name, version, url)
812 by Jelmer Vernooij
Display resolved branch URL in apt: directory.
214
        return url
725.1.1 by Jelmer Vernooij
Use register-lazy.
215
216
822 by Jelmer Vernooij
Add dgit: directory.
217
class DgitDirectory(object):
824 by Jelmer Vernooij
Split out vcs_git_url_to_bzr_url and vcs_bzr_url_to_bzr_url.
218
    """Directory that looks up the URL according to a Dgit control field."""
822 by Jelmer Vernooij
Add dgit: directory.
219
220
    def look_up(self, name, url):
221
        if "/" in name:
222
            (name, version) = name.split("/", 1)
223
        else:
224
            version = None
225
1049 by Jelmer Vernooij
Handle missing apt_pkg.
226
        try:
227
            import apt_pkg
228
        except ImportError as e:
229
            raise DependencyNotPresent('apt_pkg', e)
230
822 by Jelmer Vernooij
Add dgit: directory.
231
        apt_pkg.init()
232
233
        sources = apt_pkg.SourceRecords()
234
235
        urls = {}
236
        while sources.lookup(name):
825 by Jelmer Vernooij
Use deb822 for parsing source package control files.
237
            control = Deb822(sources.record)
238
            pkg_version = control["Version"]
239
            try:
240
                urls[pkg_version] = control["Dgit"].split(' ')
241
            except KeyError:
242
                pass
822 by Jelmer Vernooij
Add dgit: directory.
243
244
        if len(urls) == 0:
245
            raise urlutils.InvalidURL(path=url, extra='no URLs found')
246
247
        if version is None:
248
            # Try the latest version
844 by Jelmer Vernooij
Avoid using cmp in sorted.
249
            version = sorted(urls, key=Version)[-1]
822 by Jelmer Vernooij
Add dgit: directory.
250
922 by Jelmer Vernooij
Add a 'vcs:' location resolver that uses the location provided by
251
        if version not in urls:
252
            raise urlutils.InvalidURL(
253
                path=url, extra='version %s not found' % version)
822 by Jelmer Vernooij
Add dgit: directory.
254
828 by Jelmer Vernooij
Cope with Dgit headers without location.
255
        if len(urls[version]) < 3:
256
            raise urlutils.InvalidURL(
257
                path=url,
258
                extra='dgit header does not have location information')
259
822 by Jelmer Vernooij
Add dgit: directory.
260
        url = urlutils.join_segment_parameters(
261
                urls[version][3],
262
                {"tag": urlutils.quote(urls[version][2], '')})
263
264
        note("Resolved package URL from Debian package %s/%s: %s",
265
             name, version, url)
266
        return url
267
268
922 by Jelmer Vernooij
Add a 'vcs:' location resolver that uses the location provided by
269
class VcsDirectory(object):
270
    """Use local Vcs Directory."""
271
272
    def look_up(self, name, url):
273
        from debian.deb822 import Deb822
274
        with open('debian/control', 'r') as f:
275
            source = Deb822(f)
276
            vcs, url = source_package_vcs_url(source)
277
            return url
278
279
725.1.1 by Jelmer Vernooij
Use register-lazy.
280
def upstream_branch_alias(b):
750 by Jelmer Vernooij
use relative imports.
281
    from .util import debuild_config
779 by Jelmer Vernooij
Use with statement for locks, use Tree.is_versioned.
282
    with b.lock_read():
725.1.1 by Jelmer Vernooij
Use register-lazy.
283
        tree = b.basis_tree()
945 by Jelmer Vernooij
Drop often misused working_tree argument from debuild_config.
284
        config = debuild_config(tree)
725.1.1 by Jelmer Vernooij
Use register-lazy.
285
        return directories.dereference(config.upstream_branch)