fetch: Add bzr fetcher
[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 update %s" % (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         # Updating is disabled until bzr supports the syntax "bzr update -r X" to specify a revision
105         if 0 and os.access(os.path.join(ud.pkgdir, os.path.basename(ud.pkgdir), '.bzr'), os.R_OK):
106             bzrcmd = self._buildbzrcommand(ud, d, "update")
107             bb.msg.debug(1, bb.msg.domain.Fetcher, "BZR Update %s" % loc)
108             os.chdir(os.path.join (ud.pkgdir, os.path.basename(ud.path)))
109             runfetchcmd(bzrcmd, d)
110         else:
111             os.system("rm -rf %s" % os.path.join(ud.pkgdir, os.path.basename(ud.pkgdir)))
112             bzrcmd = self._buildbzrcommand(ud, d, "fetch")
113             bb.msg.debug(1, bb.msg.domain.Fetcher, "BZR Checkout %s" % loc)
114             bb.mkdirhier(ud.pkgdir)
115             os.chdir(ud.pkgdir)
116             bb.msg.debug(1, bb.msg.domain.Fetcher, "Running %s" % bzrcmd)
117             runfetchcmd(bzrcmd, d)
118
119         os.chdir(ud.pkgdir)
120         # tar them up to a defined filename
121         try:
122             runfetchcmd("tar -czf %s %s" % (ud.localpath, os.path.basename(ud.pkgdir)), d)
123         except:
124             t, v, tb = sys.exc_info()
125             try:
126                 os.unlink(ud.localpath)
127             except OSError:
128                 pass
129             raise t, v, tb
130
131     def suppports_srcrev(self):
132         return True
133
134     def _revision_key(self, url, ud, d):
135         """
136         Return a unique key for the url
137         """
138         return "bzr:" + ud.pkgdir
139
140     def _latest_revision(self, url, ud, d):
141         """
142         Return the latest upstream revision number
143         """
144         bb.msg.debug(2, bb.msg.domain.Fetcher, "BZR fetcher hitting network for %s" % url)
145
146         output = runfetchcmd(self._buildbzrcommand(ud, d, "revno"), d, True)
147
148         for line in output.splitlines():
149             revision = line
150
151         return revision
152
153     def _sortable_revision(self, url, ud, d):
154         """
155         Return a sortable revision number which in our case is the revision number
156         (use the cached version to avoid network access)
157         """
158
159         return self.latest_revision(url, ud, d)