xref: /openbmc/openbmc/poky/bitbake/lib/bb/fetch2/svn.py (revision eb8dc403)
1# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' implementation for svn.
5
6"""
7
8# Copyright (C) 2003, 2004  Chris Larson
9# Copyright (C) 2004        Marcin Juszkiewicz
10#
11# This program is free software; you can redistribute it and/or modify
12# it under the terms of the GNU General Public License version 2 as
13# published by the Free Software Foundation.
14#
15# This program is distributed in the hope that it will be useful,
16# but WITHOUT ANY WARRANTY; without even the implied warranty of
17# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18# GNU General Public License for more details.
19#
20# You should have received a copy of the GNU General Public License along
21# with this program; if not, write to the Free Software Foundation, Inc.,
22# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23#
24# Based on functions from the base bb module, Copyright 2003 Holger Schurig
25
26import os
27import sys
28import logging
29import bb
30import re
31from   bb.fetch2 import FetchMethod
32from   bb.fetch2 import FetchError
33from   bb.fetch2 import MissingParameterError
34from   bb.fetch2 import runfetchcmd
35from   bb.fetch2 import logger
36
37class Svn(FetchMethod):
38    """Class to fetch a module or modules from svn repositories"""
39    def supports(self, ud, d):
40        """
41        Check to see if a given url can be fetched with svn.
42        """
43        return ud.type in ['svn']
44
45    def urldata_init(self, ud, d):
46        """
47        init svn specific variable within url data
48        """
49        if not "module" in ud.parm:
50            raise MissingParameterError('module', ud.url)
51
52        ud.basecmd = d.getVar('FETCHCMD_svn')
53
54        ud.module = ud.parm["module"]
55
56        if not "path_spec" in ud.parm:
57            ud.path_spec = ud.module
58        else:
59            ud.path_spec = ud.parm["path_spec"]
60
61        # Create paths to svn checkouts
62        relpath = self._strip_leading_slashes(ud.path)
63        ud.pkgdir = os.path.join(d.expand('${SVNDIR}'), ud.host, relpath)
64        ud.moddir = os.path.join(ud.pkgdir, ud.module)
65
66        ud.setup_revisions(d)
67
68        if 'rev' in ud.parm:
69            ud.revision = ud.parm['rev']
70
71        ud.localfile = d.expand('%s_%s_%s_%s_.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.path.replace('/', '.'), ud.revision))
72
73    def _buildsvncommand(self, ud, d, command):
74        """
75        Build up an svn commandline based on ud
76        command is "fetch", "update", "info"
77        """
78
79        proto = ud.parm.get('protocol', 'svn')
80
81        svn_ssh = None
82        if proto == "svn+ssh" and "ssh" in ud.parm:
83            svn_ssh = ud.parm["ssh"]
84
85        svnroot = ud.host + ud.path
86
87        options = []
88
89        options.append("--no-auth-cache")
90
91        if ud.user:
92            options.append("--username %s" % ud.user)
93
94        if ud.pswd:
95            options.append("--password %s" % ud.pswd)
96
97        if command == "info":
98            svncmd = "%s info %s %s://%s/%s/" % (ud.basecmd, " ".join(options), proto, svnroot, ud.module)
99        elif command == "log1":
100            svncmd = "%s log --limit 1 %s %s://%s/%s/" % (ud.basecmd, " ".join(options), proto, svnroot, ud.module)
101        else:
102            suffix = ""
103            if ud.revision:
104                options.append("-r %s" % ud.revision)
105                suffix = "@%s" % (ud.revision)
106
107            if command == "fetch":
108                transportuser = ud.parm.get("transportuser", "")
109                svncmd = "%s co %s %s://%s%s/%s%s %s" % (ud.basecmd, " ".join(options), proto, transportuser, svnroot, ud.module, suffix, ud.path_spec)
110            elif command == "update":
111                svncmd = "%s update %s" % (ud.basecmd, " ".join(options))
112            else:
113                raise FetchError("Invalid svn command %s" % command, ud.url)
114
115        if svn_ssh:
116            svncmd = "SVN_SSH=\"%s\" %s" % (svn_ssh, svncmd)
117
118        return svncmd
119
120    def download(self, ud, d):
121        """Fetch url"""
122
123        logger.debug(2, "Fetch: checking for module directory '" + ud.moddir + "'")
124
125        if os.access(os.path.join(ud.moddir, '.svn'), os.R_OK):
126            svnupdatecmd = self._buildsvncommand(ud, d, "update")
127            logger.info("Update " + ud.url)
128            # We need to attempt to run svn upgrade first in case its an older working format
129            try:
130                runfetchcmd(ud.basecmd + " upgrade", d, workdir=ud.moddir)
131            except FetchError:
132                pass
133            logger.debug(1, "Running %s", svnupdatecmd)
134            bb.fetch2.check_network_access(d, svnupdatecmd, ud.url)
135            runfetchcmd(svnupdatecmd, d, workdir=ud.moddir)
136        else:
137            svnfetchcmd = self._buildsvncommand(ud, d, "fetch")
138            logger.info("Fetch " + ud.url)
139            # check out sources there
140            bb.utils.mkdirhier(ud.pkgdir)
141            logger.debug(1, "Running %s", svnfetchcmd)
142            bb.fetch2.check_network_access(d, svnfetchcmd, ud.url)
143            runfetchcmd(svnfetchcmd, d, workdir=ud.pkgdir)
144
145        scmdata = ud.parm.get("scmdata", "")
146        if scmdata == "keep":
147            tar_flags = ""
148        else:
149            tar_flags = "--exclude='.svn'"
150
151        # tar them up to a defined filename
152        runfetchcmd("tar %s -czf %s %s" % (tar_flags, ud.localpath, ud.path_spec), d,
153                    cleanup=[ud.localpath], workdir=ud.pkgdir)
154
155    def clean(self, ud, d):
156        """ Clean SVN specific files and dirs """
157
158        bb.utils.remove(ud.localpath)
159        bb.utils.remove(ud.moddir, True)
160
161
162    def supports_srcrev(self):
163        return True
164
165    def _revision_key(self, ud, d, name):
166        """
167        Return a unique key for the url
168        """
169        return "svn:" + ud.moddir
170
171    def _latest_revision(self, ud, d, name):
172        """
173        Return the latest upstream revision number
174        """
175        bb.fetch2.check_network_access(d, self._buildsvncommand(ud, d, "log1"), ud.url)
176
177        output = runfetchcmd("LANG=C LC_ALL=C " + self._buildsvncommand(ud, d, "log1"), d, True)
178
179        # skip the first line, as per output of svn log
180        # then we expect the revision on the 2nd line
181        revision = re.search('^r([0-9]*)', output.splitlines()[1]).group(1)
182
183        return revision
184
185    def sortable_revision(self, ud, d, name):
186        """
187        Return a sortable revision number which in our case is the revision number
188        """
189
190        return False, self._build_revision(ud, d)
191
192    def _build_revision(self, ud, d):
193        return ud.revision
194