bzr.py: bzr fetcher tweaks from Robert Schuster (#2913)
[bitbake.git] / lib / bb / fetch / bzr.py
1 """
2 BitBake 'Fetch' implementation for bzr.
3
4 """
5
6 # Copyright (C) 2007 Ross Burton
7 # Copyright (C) 2007 Richard Purdie
8 #
9 #   Classes for obtaining upstream sources for the
10 #   BitBake build tools.
11 #   Copyright (C) 2003, 2004  Chris Larson
12 #
13 # This program is free software; you can redistribute it and/or modify
14 # it under the terms of the GNU General Public License version 2 as
15 # published by the Free Software Foundation.
16 #
17 # This program is distributed in the hope that it will be useful,
18 # but WITHOUT ANY WARRANTY; without even the implied warranty of
19 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20 # GNU General Public License for more details.
21 #
22 # You should have received a copy of the GNU General Public License along
23 # with this program; if not, write to the Free Software Foundation, Inc.,
24 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
25
26 import os
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 from bb.fetch import runfetchcmd
34
35 class Bzr(Fetch):
36     def supports(self, url, ud, d):
37         return ud.type in ['bzr']
38
39     def localpath (self, url, ud, d):
40
41         # Create paths to bzr checkouts
42         relpath = ud.path
43         if relpath.startswith('/'):
44             # Remove leading slash as os.path.join can't cope
45             relpath = relpath[1:]
46         ud.pkgdir = os.path.join(data.expand('${BZRDIR}', d), ud.host, relpath)
47
48         if 'rev' in ud.parm:
49             ud.revision = ud.parm['rev']
50         else:
51             # ***Nasty hack***
52             rev = data.getVar("SRCREV", d, 0)
53             if rev and "get_srcrev" in rev:
54                 ud.revision = self.latest_revision(url, ud, d)
55             elif rev:
56                 ud.revision = rev
57             else:
58                 ud.revision = ""
59
60         
61         ud.localfile = data.expand('bzr_%s_%s_%s.tar.gz' % (ud.host, ud.path.replace('/', '.'), ud.revision), d)
62         
63         return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
64
65     def _buildbzrcommand(self, ud, d, command):
66         """
67         Build up an bzr commandline based on ud
68         command is "fetch", "update", "revno"
69         """
70
71         basecmd = data.expand('${FETCHCMD_bzr}', d)
72
73         proto = "http"
74         if "proto" in ud.parm:
75             proto = ud.parm["proto"]
76
77         bzrroot = ud.host + ud.path
78
79         options = []
80
81         if command is "revno":
82             bzrcmd = "%s revno %s %s://%s" % (basecmd, " ".join(options), proto, bzrroot)
83         else:
84             if ud.revision:
85                 options.append("-r %s" % ud.revision)
86
87             if command is "fetch":
88                 bzrcmd = "%s co %s %s://%s" % (basecmd, " ".join(options), proto, bzrroot)
89             elif command is "update":
90                 bzrcmd = "%s pull %s --overwrite" % (basecmd, " ".join(options))
91             else:
92                 raise FetchError("Invalid bzr command %s" % command)
93
94         return bzrcmd
95
96     def go(self, loc, ud, d):
97         """Fetch url"""
98
99         # try to use the tarball stash
100         if Fetch.try_mirror(d, ud.localfile):
101             bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists or was mirrored, skipping bzr checkout." % ud.localpath)
102             return
103
104         if os.access(os.path.join(ud.pkgdir, os.path.basename(ud.pkgdir), '.bzr'), os.R_OK):
105             bzrcmd = self._buildbzrcommand(ud, d, "update")
106             bb.msg.debug(1, bb.msg.domain.Fetcher, "BZR Update %s" % loc)
107             os.chdir(os.path.join (ud.pkgdir, os.path.basename(ud.path)))
108             runfetchcmd(bzrcmd, d)
109         else:
110             os.system("rm -rf %s" % os.path.join(ud.pkgdir, os.path.basename(ud.pkgdir)))
111             bzrcmd = self._buildbzrcommand(ud, d, "fetch")
112             bb.msg.debug(1, bb.msg.domain.Fetcher, "BZR Checkout %s" % loc)
113             bb.mkdirhier(ud.pkgdir)
114             os.chdir(ud.pkgdir)
115             bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s" % bzrcmd)
116             runfetchcmd(bzrcmd, d)
117
118         os.chdir(ud.pkgdir)
119         # tar them up to a defined filename
120         try:
121             runfetchcmd("tar -czf %s %s" % (ud.localpath, os.path.basename(ud.pkgdir)), d)
122         except:
123             t, v, tb = sys.exc_info()
124             try:
125                 os.unlink(ud.localpath)
126             except OSError:
127                 pass
128             raise t, v, tb
129
130     def suppports_srcrev(self):
131         return True
132
133     def _revision_key(self, url, ud, d):
134         """
135         Return a unique key for the url
136         """
137         return "bzr:" + ud.pkgdir
138
139     def _latest_revision(self, url, ud, d):
140         """
141         Return the latest upstream revision number
142         """
143         bb.msg.debug(2, bb.msg.domain.Fetcher, "BZR fetcher hitting network for %s" % url)
144
145         output = runfetchcmd(self._buildbzrcommand(ud, d, "revno"), d, True)
146
147         return output.strip()
148
149     def _sortable_revision(self, url, ud, d):
150         """
151         Return a sortable revision number which in our case is the revision number
152         (use the cached version to avoid network access)
153         """
154
155         return self.latest_revision(url, ud, d)