svn.py: Fix #2624 and #2644 by changing svn layout in SVNDIR (backport)
[bitbake.git] / lib / bb / fetch / svn.py
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, re
27 import sys
28 import bb
29 from   bb import data
30 from   bb.fetch import Fetch
31 from   bb.fetch import FetchError
32 from   bb.fetch import MissingParameterError
33
34 class Svn(Fetch):
35     """Class to fetch a module or modules from svn repositories"""
36     def supports(self, url, ud, d):
37         """
38         Check to see if a given url can be fetched with svn.
39         """
40         return ud.type in ['svn']
41
42     def localpath(self, url, ud, d):
43         if not "module" in ud.parm:
44             raise MissingParameterError("svn method needs a 'module' parameter")
45
46         ud.module = ud.parm["module"]
47         ud.moddir = ud.module.replace('/', '.')
48
49         ud.revision = ""
50         if 'rev' in ud.parm:
51             ud.revision = ud.parm['rev']
52
53         if ud.revision:
54             ud.date = ""
55
56         ud.localfile = data.expand('%s_%s_%s_%s_%s.tar.gz' % (ud.moddir, ud.host, ud.path.replace('/', '.'), ud.revision, ud.date), d)
57
58         return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
59
60     def forcefetch(self, url, ud, d):
61         if (ud.date == "now"):
62             return True
63         return False
64
65     def _buildsvncommand(self, ud, d, command):
66         """
67         Build up an svn commandline based on ud
68         command is "fetch", "update", "info"
69         """
70
71         basecmd = data.expand('${FETCHCMD_svn}', d)
72
73         proto = "svn"
74         if "proto" in ud.parm:
75             proto = ud.parm["proto"]
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         # either use the revision, or SRCDATE in braces, or nothing for SRCDATE = "now"
84         options = []
85         if ud.revision:
86             options.append("-r %s" % ud.revision)
87         elif ud.date != "now":
88             options.append("-r {%s}" % ud.date)
89
90         if ud.user:
91             options.append("--username %s" % ud.user)
92
93         if ud.pswd:
94             options.append("--password %s" % ud.pswd)
95
96         if command is "fetch":
97             svncmd = "%s co %s %s://%s/%s %s" % (basecmd, " ".join(options), proto, svnroot, ud.module, ud.module)
98         elif command is "update":
99             svncmd = "%s update %s" % (basecmd, " ".join(options))
100         elif command is "info":
101             svncmd = "%s info %s %s://%s/%s" % (basecmd, " ".join(options), proto, svnroot, ud.module)
102         else:
103             raise FetchError("Invalid svn command %s" % command)
104
105         if svn_rsh:
106             svncmd = "svn_RSH=\"%s\" %s" % (svn_rsh, svncmd)
107
108         return svncmd
109
110     def go(self, loc, ud, d):
111         """Fetch url"""
112
113         # try to use the tarball stash
114         if not self.forcefetch(loc, ud, d) and Fetch.try_mirror(d, ud.localfile):
115             bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists or was mirrored, skipping svn checkout." % ud.localpath)
116             return
117
118         pkg = data.expand('${PN}', d)
119         relpath = ud.path
120         if relpath.startswith('/'):
121             # Remove leading slash as os.path.join can't cope
122             relpath = relpath[1:]
123         pkgdir = os.path.join(data.expand('${SVNDIR}', d), ud.host, relpath)
124         moddir = os.path.join(pkgdir, ud.module)
125         bb.msg.debug(2, bb.msg.domain.Fetcher, "Fetch: checking for module directory '" + moddir + "'")
126
127         if os.access(os.path.join(moddir, '.svn'), os.R_OK):
128             svnupdatecmd = self._buildsvncommand(ud, d, "update")
129             bb.msg.note(1, bb.msg.domain.Fetcher, "Update " + loc)
130             # update sources there
131             os.chdir(moddir)
132             bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s" % svnupdatecmd)
133             myret = os.system(svnupdatecmd)
134         else:
135             svnfetchcmd = self._buildsvncommand(ud, d, "fetch")
136             bb.msg.note(1, bb.msg.domain.Fetcher, "Fetch " + loc)
137             # check out sources there
138             bb.mkdirhier(pkgdir)
139             os.chdir(pkgdir)
140             bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s" % svnfetchcmd)
141             myret = os.system(svnfetchcmd)
142
143         if myret != 0:
144             raise FetchError(ud.module)
145
146         os.chdir(pkgdir)
147         # tar them up to a defined filename
148         myret = os.system("tar -czf %s %s" % (ud.localpath, os.path.basename(ud.module)))
149         if myret != 0:
150             try:
151                 os.unlink(ud.localpath)
152             except OSError:
153                 pass
154             raise FetchError(ud.module)
155