git.py: Handle tag=master correctly (from poky)
[bitbake.git] / lib / bb / fetch / git.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' git implementation
5
6 """
7
8 #Copyright (C) 2005 Richard Purdie
9 #
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License version 2 as
12 # published by the Free Software Foundation.
13 #
14 # This program is distributed in the hope that it will be useful,
15 # but WITHOUT ANY WARRANTY; without even the implied warranty of
16 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 # GNU General Public License for more details.
18 #
19 # You should have received a copy of the GNU General Public License along
20 # with this program; if not, write to the Free Software Foundation, Inc.,
21 # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22
23 import os, re
24 import bb
25 from   bb    import data
26 from   bb.fetch import Fetch
27 from   bb.fetch import FetchError
28 from   bb.fetch import runfetchcmd
29
30 def prunedir(topdir):
31     # Delete everything reachable from the directory named in 'topdir'.
32     # CAUTION:  This is dangerous!
33     for root, dirs, files in os.walk(topdir, topdown=False):
34         for name in files:
35             os.remove(os.path.join(root, name))
36         for name in dirs:
37             os.rmdir(os.path.join(root, name))
38
39 class Git(Fetch):
40     """Class to fetch a module or modules from git repositories"""
41     def supports(self, url, ud, d):
42         """
43         Check to see if a given url can be fetched with git.
44         """
45         return ud.type in ['git']
46
47     def localpath(self, url, ud, d):
48
49         ud.proto = "rsync"
50         if 'protocol' in ud.parm:
51             ud.proto = ud.parm['protocol']
52
53         tag = data.getVar("SRCREV", d, 0)
54         if 'tag' in ud.parm and len(tag) == 40:
55             ud.tag = ud.parm['tag']
56         elif tag and "get_srcrev" not in tag and len(tag) == 40:
57             ud.tag = tag
58         else:
59             ud.tag = self.latest_revision(url, ud, d)
60
61         ud.localfile = data.expand('git_%s%s_%s.tar.gz' % (ud.host, ud.path.replace('/', '.'), ud.tag), d)
62
63         return os.path.join(data.getVar("DL_DIR", d, True), ud.localfile)
64
65     def go(self, loc, ud, d):
66         """Fetch url"""
67
68         if Fetch.try_mirror(d, ud.localfile):
69             bb.msg.debug(1, bb.msg.domain.Fetcher, "%s already exists (or was stashed). Skipping git checkout." % ud.localpath)
70             return
71
72         gitsrcname = '%s%s' % (ud.host, ud.path.replace('/', '.'))
73
74         repofilename = 'git_%s.tar.gz' % (gitsrcname)
75         repofile = os.path.join(data.getVar("DL_DIR", d, 1), repofilename)
76         repodir = os.path.join(data.expand('${GITDIR}', d), gitsrcname)
77
78         coname = '%s' % (ud.tag)
79         codir = os.path.join(repodir, coname)
80
81         if not os.path.exists(repodir):
82             if Fetch.try_mirror(d, repofilename):    
83                 bb.mkdirhier(repodir)
84                 os.chdir(repodir)
85                 runfetchcmd("tar -xzf %s" % (repofile), d)
86             else:
87                 runfetchcmd("git clone -n %s://%s%s %s" % (ud.proto, ud.host, ud.path, repodir), d)
88
89         os.chdir(repodir)
90         # Remove all but the .git directory
91         runfetchcmd("rm * -Rf", d)
92         runfetchcmd("git pull %s://%s%s" % (ud.proto, ud.host, ud.path), d)
93         runfetchcmd("git pull --tags %s://%s%s" % (ud.proto, ud.host, ud.path), d)
94         runfetchcmd("git prune-packed", d)
95         runfetchcmd("git pack-redundant --all | xargs -r rm", d)
96         # old method of downloading tags
97         #runfetchcmd("rsync -a --verbose --stats --progress rsync://%s%s/ %s" % (ud.host, ud.path, os.path.join(repodir, ".git", "")), d)
98
99         os.chdir(repodir)
100         bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git repository")
101         runfetchcmd("tar -czf %s %s" % (repofile, os.path.join(".", ".git", "*") ), d)
102
103         if os.path.exists(codir):
104             prunedir(codir)
105
106         bb.mkdirhier(codir)
107         os.chdir(repodir)
108         runfetchcmd("git read-tree %s" % (ud.tag), d)
109         runfetchcmd("git checkout-index -q -f --prefix=%s -a" % (os.path.join(codir, "git", "")), d)
110
111         os.chdir(codir)
112         bb.msg.note(1, bb.msg.domain.Fetcher, "Creating tarball of git checkout")
113         runfetchcmd("tar -czf %s %s" % (ud.localpath, os.path.join(".", "*") ), d)
114
115         os.chdir(repodir)
116         prunedir(codir)
117
118     def suppports_srcrev(self):
119         return True
120
121     def _revision_key(self, url, ud, d):
122         """
123         Return a unique key for the url
124         """
125         return "git:" + ud.host + ud.path.replace('/', '.')
126
127     def _latest_revision(self, url, ud, d):
128
129         output = runfetchcmd("git ls-remote %s://%s%s" % (ud.proto, ud.host, ud.path), d, True)
130         return output.split()[0]
131