| Patrick Williams | c124f4f | 2015-09-15 14:41:29 -0500 | [diff] [blame] | 1 | # ex:ts=4:sw=4:sts=4:et | 
|  | 2 | # -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*- | 
|  | 3 | """ | 
|  | 4 | BitBake '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 |  | 
|  | 26 | import os | 
|  | 27 | import sys | 
|  | 28 | import logging | 
|  | 29 | import bb | 
|  | 30 | import re | 
|  | 31 | from   bb import data | 
|  | 32 | from   bb.fetch2 import FetchMethod | 
|  | 33 | from   bb.fetch2 import FetchError | 
|  | 34 | from   bb.fetch2 import MissingParameterError | 
|  | 35 | from   bb.fetch2 import runfetchcmd | 
|  | 36 | from   bb.fetch2 import logger | 
|  | 37 |  | 
|  | 38 | class Svn(FetchMethod): | 
|  | 39 | """Class to fetch a module or modules from svn repositories""" | 
|  | 40 | def supports(self, ud, d): | 
|  | 41 | """ | 
|  | 42 | Check to see if a given url can be fetched with svn. | 
|  | 43 | """ | 
|  | 44 | return ud.type in ['svn'] | 
|  | 45 |  | 
|  | 46 | def urldata_init(self, ud, d): | 
|  | 47 | """ | 
|  | 48 | init svn specific variable within url data | 
|  | 49 | """ | 
|  | 50 | if not "module" in ud.parm: | 
|  | 51 | raise MissingParameterError('module', ud.url) | 
|  | 52 |  | 
|  | 53 | ud.basecmd = d.getVar('FETCHCMD_svn', True) | 
|  | 54 |  | 
|  | 55 | ud.module = ud.parm["module"] | 
|  | 56 |  | 
|  | 57 | # Create paths to svn checkouts | 
|  | 58 | relpath = self._strip_leading_slashes(ud.path) | 
|  | 59 | ud.pkgdir = os.path.join(data.expand('${SVNDIR}', d), ud.host, relpath) | 
|  | 60 | ud.moddir = os.path.join(ud.pkgdir, ud.module) | 
|  | 61 |  | 
|  | 62 | ud.setup_revisons(d) | 
|  | 63 |  | 
|  | 64 | if 'rev' in ud.parm: | 
|  | 65 | ud.revision = ud.parm['rev'] | 
|  | 66 |  | 
|  | 67 | ud.localfile = data.expand('%s_%s_%s_%s_.tar.gz' % (ud.module.replace('/', '.'), ud.host, ud.path.replace('/', '.'), ud.revision), d) | 
|  | 68 |  | 
|  | 69 | def _buildsvncommand(self, ud, d, command): | 
|  | 70 | """ | 
|  | 71 | Build up an svn commandline based on ud | 
|  | 72 | command is "fetch", "update", "info" | 
|  | 73 | """ | 
|  | 74 |  | 
|  | 75 | proto = ud.parm.get('protocol', 'svn') | 
|  | 76 |  | 
|  | 77 | svn_rsh = None | 
|  | 78 | if proto == "svn+ssh" and "rsh" in ud.parm: | 
|  | 79 | svn_rsh = ud.parm["rsh"] | 
|  | 80 |  | 
|  | 81 | svnroot = ud.host + ud.path | 
|  | 82 |  | 
|  | 83 | options = [] | 
|  | 84 |  | 
|  | 85 | options.append("--no-auth-cache") | 
|  | 86 |  | 
|  | 87 | if ud.user: | 
|  | 88 | options.append("--username %s" % ud.user) | 
|  | 89 |  | 
|  | 90 | if ud.pswd: | 
|  | 91 | options.append("--password %s" % ud.pswd) | 
|  | 92 |  | 
|  | 93 | if command == "info": | 
|  | 94 | svncmd = "%s info %s %s://%s/%s/" % (ud.basecmd, " ".join(options), proto, svnroot, ud.module) | 
|  | 95 | elif command == "log1": | 
|  | 96 | svncmd = "%s log --limit 1 %s %s://%s/%s/" % (ud.basecmd, " ".join(options), proto, svnroot, ud.module) | 
|  | 97 | else: | 
|  | 98 | suffix = "" | 
|  | 99 | if ud.revision: | 
|  | 100 | options.append("-r %s" % ud.revision) | 
|  | 101 | suffix = "@%s" % (ud.revision) | 
|  | 102 |  | 
|  | 103 | if command == "fetch": | 
|  | 104 | transportuser = ud.parm.get("transportuser", "") | 
|  | 105 | svncmd = "%s co %s %s://%s%s/%s%s %s" % (ud.basecmd, " ".join(options), proto, transportuser, svnroot, ud.module, suffix, ud.module) | 
|  | 106 | elif command == "update": | 
|  | 107 | svncmd = "%s update %s" % (ud.basecmd, " ".join(options)) | 
|  | 108 | else: | 
|  | 109 | raise FetchError("Invalid svn command %s" % command, ud.url) | 
|  | 110 |  | 
|  | 111 | if svn_rsh: | 
|  | 112 | svncmd = "svn_RSH=\"%s\" %s" % (svn_rsh, svncmd) | 
|  | 113 |  | 
|  | 114 | return svncmd | 
|  | 115 |  | 
|  | 116 | def download(self, ud, d): | 
|  | 117 | """Fetch url""" | 
|  | 118 |  | 
|  | 119 | logger.debug(2, "Fetch: checking for module directory '" + ud.moddir + "'") | 
|  | 120 |  | 
|  | 121 | if os.access(os.path.join(ud.moddir, '.svn'), os.R_OK): | 
|  | 122 | svnupdatecmd = self._buildsvncommand(ud, d, "update") | 
|  | 123 | logger.info("Update " + ud.url) | 
|  | 124 | # update sources there | 
|  | 125 | os.chdir(ud.moddir) | 
|  | 126 | # We need to attempt to run svn upgrade first in case its an older working format | 
|  | 127 | try: | 
|  | 128 | runfetchcmd(ud.basecmd + " upgrade", d) | 
|  | 129 | except FetchError: | 
|  | 130 | pass | 
|  | 131 | logger.debug(1, "Running %s", svnupdatecmd) | 
|  | 132 | bb.fetch2.check_network_access(d, svnupdatecmd, ud.url) | 
|  | 133 | runfetchcmd(svnupdatecmd, d) | 
|  | 134 | else: | 
|  | 135 | svnfetchcmd = self._buildsvncommand(ud, d, "fetch") | 
|  | 136 | logger.info("Fetch " + ud.url) | 
|  | 137 | # check out sources there | 
|  | 138 | bb.utils.mkdirhier(ud.pkgdir) | 
|  | 139 | os.chdir(ud.pkgdir) | 
|  | 140 | logger.debug(1, "Running %s", svnfetchcmd) | 
|  | 141 | bb.fetch2.check_network_access(d, svnfetchcmd, ud.url) | 
|  | 142 | runfetchcmd(svnfetchcmd, d) | 
|  | 143 |  | 
|  | 144 | scmdata = ud.parm.get("scmdata", "") | 
|  | 145 | if scmdata == "keep": | 
|  | 146 | tar_flags = "" | 
|  | 147 | else: | 
|  | 148 | tar_flags = "--exclude '.svn'" | 
|  | 149 |  | 
|  | 150 | os.chdir(ud.pkgdir) | 
|  | 151 | # tar them up to a defined filename | 
|  | 152 | runfetchcmd("tar %s -czf %s %s" % (tar_flags, ud.localpath, ud.module), d, cleanup = [ud.localpath]) | 
|  | 153 |  | 
|  | 154 | def clean(self, ud, d): | 
|  | 155 | """ Clean SVN specific files and dirs """ | 
|  | 156 |  | 
|  | 157 | bb.utils.remove(ud.localpath) | 
|  | 158 | bb.utils.remove(ud.moddir, True) | 
|  | 159 |  | 
|  | 160 |  | 
|  | 161 | def supports_srcrev(self): | 
|  | 162 | return True | 
|  | 163 |  | 
|  | 164 | def _revision_key(self, ud, d, name): | 
|  | 165 | """ | 
|  | 166 | Return a unique key for the url | 
|  | 167 | """ | 
|  | 168 | return "svn:" + ud.moddir | 
|  | 169 |  | 
|  | 170 | def _latest_revision(self, ud, d, name): | 
|  | 171 | """ | 
|  | 172 | Return the latest upstream revision number | 
|  | 173 | """ | 
|  | 174 | bb.fetch2.check_network_access(d, self._buildsvncommand(ud, d, "log1")) | 
|  | 175 |  | 
|  | 176 | output = runfetchcmd("LANG=C LC_ALL=C " + self._buildsvncommand(ud, d, "log1"), d, True) | 
|  | 177 |  | 
|  | 178 | # skip the first line, as per output of svn log | 
|  | 179 | # then we expect the revision on the 2nd line | 
|  | 180 | revision = re.search('^r([0-9]*)', output.splitlines()[1]).group(1) | 
|  | 181 |  | 
|  | 182 | return revision | 
|  | 183 |  | 
|  | 184 | def sortable_revision(self, ud, d, name): | 
|  | 185 | """ | 
|  | 186 | Return a sortable revision number which in our case is the revision number | 
|  | 187 | """ | 
|  | 188 |  | 
|  | 189 | return False, self._build_revision(ud, d) | 
|  | 190 |  | 
|  | 191 | def _build_revision(self, ud, d): | 
|  | 192 | return ud.revision |