blob: 7442f84414614dcbedc6044953ffb33881156f45 [file] [log] [blame]
Patrick Williamsc124f4f2015-09-15 14:41:29 -05001# ex:ts=4:sw=4:sts=4:et
2# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
3"""
4BitBake 'Fetch' git implementation
5
6git fetcher support the SRC_URI with format of:
7SRC_URI = "git://some.host/somepath;OptionA=xxx;OptionB=xxx;..."
8
9Supported SRC_URI options are:
10
11- branch
12 The git branch to retrieve from. The default is "master"
13
14 This option also supports multiple branch fetching, with branches
15 separated by commas. In multiple branches case, the name option
16 must have the same number of names to match the branches, which is
17 used to specify the SRC_REV for the branch
18 e.g:
19 SRC_URI="git://some.host/somepath;branch=branchX,branchY;name=nameX,nameY"
20 SRCREV_nameX = "xxxxxxxxxxxxxxxxxxxx"
21 SRCREV_nameY = "YYYYYYYYYYYYYYYYYYYY"
22
23- tag
24 The git tag to retrieve. The default is "master"
25
26- protocol
27 The method to use to access the repository. Common options are "git",
28 "http", "https", "file", "ssh" and "rsync". The default is "git".
29
30- rebaseable
31 rebaseable indicates that the upstream git repo may rebase in the future,
32 and current revision may disappear from upstream repo. This option will
33 remind fetcher to preserve local cache carefully for future use.
34 The default value is "0", set rebaseable=1 for rebaseable git repo.
35
36- nocheckout
37 Don't checkout source code when unpacking. set this option for the recipe
38 who has its own routine to checkout code.
39 The default is "0", set nocheckout=1 if needed.
40
41- bareclone
42 Create a bare clone of the source code and don't checkout the source code
43 when unpacking. Set this option for the recipe who has its own routine to
44 checkout code and tracking branch requirements.
45 The default is "0", set bareclone=1 if needed.
46
47- nobranch
48 Don't check the SHA validation for branch. set this option for the recipe
49 referring to commit which is valid in tag instead of branch.
50 The default is "0", set nobranch=1 if needed.
51
Patrick Williamsc0f7c042017-02-23 20:41:17 -060052- usehead
Brad Bishop6e60e8b2018-02-01 10:27:11 -050053 For local git:// urls to use the current branch HEAD as the revision for use with
Patrick Williamsc0f7c042017-02-23 20:41:17 -060054 AUTOREV. Implies nobranch.
55
Patrick Williamsc124f4f2015-09-15 14:41:29 -050056"""
57
58#Copyright (C) 2005 Richard Purdie
59#
60# This program is free software; you can redistribute it and/or modify
61# it under the terms of the GNU General Public License version 2 as
62# published by the Free Software Foundation.
63#
64# This program is distributed in the hope that it will be useful,
65# but WITHOUT ANY WARRANTY; without even the implied warranty of
66# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
67# GNU General Public License for more details.
68#
69# You should have received a copy of the GNU General Public License along
70# with this program; if not, write to the Free Software Foundation, Inc.,
71# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
72
Patrick Williamsd7e96312015-09-22 08:09:05 -050073import errno
Patrick Williamsc124f4f2015-09-15 14:41:29 -050074import os
75import re
76import bb
Patrick Williamsd8c66bc2016-06-20 12:57:21 -050077import errno
Patrick Williamsc0f7c042017-02-23 20:41:17 -060078import bb.progress
Patrick Williamsc124f4f2015-09-15 14:41:29 -050079from bb.fetch2 import FetchMethod
80from bb.fetch2 import runfetchcmd
81from bb.fetch2 import logger
82
Patrick Williamsc0f7c042017-02-23 20:41:17 -060083
84class GitProgressHandler(bb.progress.LineFilterProgressHandler):
85 """Extract progress information from git output"""
86 def __init__(self, d):
87 self._buffer = ''
88 self._count = 0
89 super(GitProgressHandler, self).__init__(d)
90 # Send an initial progress event so the bar gets shown
91 self._fire_progress(-1)
92
93 def write(self, string):
94 self._buffer += string
95 stages = ['Counting objects', 'Compressing objects', 'Receiving objects', 'Resolving deltas']
96 stage_weights = [0.2, 0.05, 0.5, 0.25]
97 stagenum = 0
98 for i, stage in reversed(list(enumerate(stages))):
99 if stage in self._buffer:
100 stagenum = i
101 self._buffer = ''
102 break
103 self._status = stages[stagenum]
104 percs = re.findall(r'(\d+)%', string)
105 if percs:
106 progress = int(round((int(percs[-1]) * stage_weights[stagenum]) + (sum(stage_weights[:stagenum]) * 100)))
107 rates = re.findall(r'([\d.]+ [a-zA-Z]*/s+)', string)
108 if rates:
109 rate = rates[-1]
110 else:
111 rate = None
112 self.update(progress, rate)
113 else:
114 if stagenum == 0:
115 percs = re.findall(r': (\d+)', string)
116 if percs:
117 count = int(percs[-1])
118 if count > self._count:
119 self._count = count
120 self._fire_progress(-count)
121 super(GitProgressHandler, self).write(string)
122
123
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500124class Git(FetchMethod):
125 """Class to fetch a module or modules from git repositories"""
126 def init(self, d):
127 pass
128
129 def supports(self, ud, d):
130 """
131 Check to see if a given url can be fetched with git.
132 """
133 return ud.type in ['git']
134
135 def supports_checksum(self, urldata):
136 return False
137
138 def urldata_init(self, ud, d):
139 """
140 init git specific variable within url data
141 so that the git method like latest_revision() can work
142 """
143 if 'protocol' in ud.parm:
144 ud.proto = ud.parm['protocol']
145 elif not ud.host:
146 ud.proto = 'file'
147 else:
148 ud.proto = "git"
149
150 if not ud.proto in ('git', 'file', 'ssh', 'http', 'https', 'rsync'):
151 raise bb.fetch2.ParameterError("Invalid protocol type", ud.url)
152
153 ud.nocheckout = ud.parm.get("nocheckout","0") == "1"
154
155 ud.rebaseable = ud.parm.get("rebaseable","0") == "1"
156
157 ud.nobranch = ud.parm.get("nobranch","0") == "1"
158
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600159 # usehead implies nobranch
160 ud.usehead = ud.parm.get("usehead","0") == "1"
161 if ud.usehead:
162 if ud.proto != "file":
163 raise bb.fetch2.ParameterError("The usehead option is only for use with local ('protocol=file') git repositories", ud.url)
164 ud.nobranch = 1
165
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500166 # bareclone implies nocheckout
167 ud.bareclone = ud.parm.get("bareclone","0") == "1"
168 if ud.bareclone:
169 ud.nocheckout = 1
170
171 ud.unresolvedrev = {}
172 branches = ud.parm.get("branch", "master").split(',')
173 if len(branches) != len(ud.names):
174 raise bb.fetch2.ParameterError("The number of name and branch parameters is not balanced", ud.url)
175 ud.branches = {}
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500176 for pos, name in enumerate(ud.names):
177 branch = branches[pos]
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500178 ud.branches[name] = branch
179 ud.unresolvedrev[name] = branch
180
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600181 if ud.usehead:
182 ud.unresolvedrev['default'] = 'HEAD'
183
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500184 ud.basecmd = d.getVar("FETCHCMD_git") or "git -c core.fsyncobjectfiles=0"
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500185
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500186 ud.write_tarballs = ((d.getVar("BB_GENERATE_MIRROR_TARBALLS") or "0") != "0") or ud.rebaseable
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500187
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500188 ud.setup_revisions(d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500189
190 for name in ud.names:
191 # Ensure anything that doesn't look like a sha256 checksum/revision is translated into one
192 if not ud.revisions[name] or len(ud.revisions[name]) != 40 or (False in [c in "abcdef0123456789" for c in ud.revisions[name]]):
193 if ud.revisions[name]:
194 ud.unresolvedrev[name] = ud.revisions[name]
195 ud.revisions[name] = self.latest_revision(ud, d, name)
196
197 gitsrcname = '%s%s' % (ud.host.replace(':', '.'), ud.path.replace('/', '.').replace('*', '.'))
198 if gitsrcname.startswith('.'):
199 gitsrcname = gitsrcname[1:]
200
201 # for rebaseable git repo, it is necessary to keep mirror tar ball
202 # per revision, so that even the revision disappears from the
203 # upstream repo in the future, the mirror will remain intact and still
204 # contains the revision
205 if ud.rebaseable:
206 for name in ud.names:
207 gitsrcname = gitsrcname + '_' + ud.revisions[name]
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500208 ud.mirrortarball = 'git2_%s.tar.gz' % gitsrcname
209 ud.fullmirror = os.path.join(d.getVar("DL_DIR"), ud.mirrortarball)
210 gitdir = d.getVar("GITDIR") or (d.getVar("DL_DIR") + "/git2/")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500211 ud.clonedir = os.path.join(gitdir, gitsrcname)
212
213 ud.localfile = ud.clonedir
214
215 def localpath(self, ud, d):
216 return ud.clonedir
217
218 def need_update(self, ud, d):
219 if not os.path.exists(ud.clonedir):
220 return True
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500221 for name in ud.names:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600222 if not self._contains_ref(ud, d, name, ud.clonedir):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500223 return True
224 if ud.write_tarballs and not os.path.exists(ud.fullmirror):
225 return True
226 return False
227
228 def try_premirror(self, ud, d):
229 # If we don't do this, updating an existing checkout with only premirrors
230 # is not possible
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500231 if d.getVar("BB_FETCH_PREMIRRORONLY") is not None:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500232 return True
233 if os.path.exists(ud.clonedir):
234 return False
235 return True
236
237 def download(self, ud, d):
238 """Fetch url"""
239
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500240 # If the checkout doesn't exist and the mirror tarball does, extract it
241 if not os.path.exists(ud.clonedir) and os.path.exists(ud.fullmirror):
242 bb.utils.mkdirhier(ud.clonedir)
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500243 runfetchcmd("tar -xzf %s" % ud.fullmirror, d, workdir=ud.clonedir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500244
245 repourl = self._get_repo_url(ud)
246
247 # If the repo still doesn't exist, fallback to cloning it
248 if not os.path.exists(ud.clonedir):
249 # We do this since git will use a "-l" option automatically for local urls where possible
250 if repourl.startswith("file://"):
251 repourl = repourl[7:]
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600252 clone_cmd = "LANG=C %s clone --bare --mirror %s %s --progress" % (ud.basecmd, repourl, ud.clonedir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500253 if ud.proto.lower() != 'file':
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500254 bb.fetch2.check_network_access(d, clone_cmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600255 progresshandler = GitProgressHandler(d)
256 runfetchcmd(clone_cmd, d, log=progresshandler)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500257
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500258 # Update the checkout if needed
259 needupdate = False
260 for name in ud.names:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600261 if not self._contains_ref(ud, d, name, ud.clonedir):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500262 needupdate = True
263 if needupdate:
264 try:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600265 runfetchcmd("%s remote rm origin" % ud.basecmd, d, workdir=ud.clonedir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500266 except bb.fetch2.FetchError:
267 logger.debug(1, "No Origin")
268
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600269 runfetchcmd("%s remote add --mirror=fetch origin %s" % (ud.basecmd, repourl), d, workdir=ud.clonedir)
270 fetch_cmd = "LANG=C %s fetch -f --prune --progress %s refs/*:refs/*" % (ud.basecmd, repourl)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500271 if ud.proto.lower() != 'file':
272 bb.fetch2.check_network_access(d, fetch_cmd, ud.url)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600273 progresshandler = GitProgressHandler(d)
274 runfetchcmd(fetch_cmd, d, log=progresshandler, workdir=ud.clonedir)
275 runfetchcmd("%s prune-packed" % ud.basecmd, d, workdir=ud.clonedir)
276 runfetchcmd("%s pack-redundant --all | xargs -r rm" % ud.basecmd, d, workdir=ud.clonedir)
Patrick Williamsd7e96312015-09-22 08:09:05 -0500277 try:
278 os.unlink(ud.fullmirror)
279 except OSError as exc:
280 if exc.errno != errno.ENOENT:
281 raise
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500282 for name in ud.names:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600283 if not self._contains_ref(ud, d, name, ud.clonedir):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500284 raise bb.fetch2.FetchError("Unable to find revision %s in branch %s even from upstream" % (ud.revisions[name], ud.branches[name]))
285
286 def build_mirror_data(self, ud, d):
287 # Generate a mirror tarball if needed
Patrick Williamsd7e96312015-09-22 08:09:05 -0500288 if ud.write_tarballs and not os.path.exists(ud.fullmirror):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500289 # it's possible that this symlink points to read-only filesystem with PREMIRROR
290 if os.path.islink(ud.fullmirror):
291 os.unlink(ud.fullmirror)
292
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500293 logger.info("Creating tarball of git repository")
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500294 runfetchcmd("tar -czf %s ." % ud.fullmirror, d, workdir=ud.clonedir)
295 runfetchcmd("touch %s.done" % ud.fullmirror, d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500296
297 def unpack(self, ud, destdir, d):
298 """ unpack the downloaded src to destdir"""
299
300 subdir = ud.parm.get("subpath", "")
301 if subdir != "":
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500302 readpathspec = ":%s" % subdir
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500303 def_destsuffix = "%s/" % os.path.basename(subdir.rstrip('/'))
304 else:
305 readpathspec = ""
306 def_destsuffix = "git/"
307
308 destsuffix = ud.parm.get("destsuffix", def_destsuffix)
309 destdir = ud.destdir = os.path.join(destdir, destsuffix)
310 if os.path.exists(destdir):
311 bb.utils.prunedir(destdir)
312
313 cloneflags = "-s -n"
314 if ud.bareclone:
315 cloneflags += " --mirror"
316
Patrick Williamsd8c66bc2016-06-20 12:57:21 -0500317 runfetchcmd("%s clone %s %s/ %s" % (ud.basecmd, cloneflags, ud.clonedir, destdir), d)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500318 repourl = self._get_repo_url(ud)
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600319 runfetchcmd("%s remote set-url origin %s" % (ud.basecmd, repourl), d, workdir=destdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500320 if not ud.nocheckout:
321 if subdir != "":
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600322 runfetchcmd("%s read-tree %s%s" % (ud.basecmd, ud.revisions[ud.names[0]], readpathspec), d,
323 workdir=destdir)
324 runfetchcmd("%s checkout-index -q -f -a" % ud.basecmd, d, workdir=destdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500325 elif not ud.nobranch:
326 branchname = ud.branches[ud.names[0]]
327 runfetchcmd("%s checkout -B %s %s" % (ud.basecmd, branchname, \
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600328 ud.revisions[ud.names[0]]), d, workdir=destdir)
Andre Rosa49271d42017-09-07 11:15:55 +0200329 runfetchcmd("%s branch %s --set-upstream-to origin/%s" % (ud.basecmd, branchname, \
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600330 branchname), d, workdir=destdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500331 else:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600332 runfetchcmd("%s checkout %s" % (ud.basecmd, ud.revisions[ud.names[0]]), d, workdir=destdir)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500333
334 return True
335
336 def clean(self, ud, d):
337 """ clean the git directory """
338
339 bb.utils.remove(ud.localpath, True)
340 bb.utils.remove(ud.fullmirror)
341 bb.utils.remove(ud.fullmirror + ".done")
342
343 def supports_srcrev(self):
344 return True
345
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600346 def _contains_ref(self, ud, d, name, wd):
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500347 cmd = ""
348 if ud.nobranch:
349 cmd = "%s log --pretty=oneline -n 1 %s -- 2> /dev/null | wc -l" % (
350 ud.basecmd, ud.revisions[name])
351 else:
352 cmd = "%s branch --contains %s --list %s 2> /dev/null | wc -l" % (
353 ud.basecmd, ud.revisions[name], ud.branches[name])
354 try:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600355 output = runfetchcmd(cmd, d, quiet=True, workdir=wd)
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500356 except bb.fetch2.FetchError:
357 return False
358 if len(output.split()) > 1:
359 raise bb.fetch2.FetchError("The command '%s' gave output with more then 1 line unexpectedly, output: '%s'" % (cmd, output))
360 return output.split()[0] != "0"
361
362 def _get_repo_url(self, ud):
363 """
364 Return the repository URL
365 """
366 if ud.user:
367 username = ud.user + '@'
368 else:
369 username = ""
370 return "%s://%s%s%s" % (ud.proto, username, ud.host, ud.path)
371
372 def _revision_key(self, ud, d, name):
373 """
374 Return a unique key for the url
375 """
376 return "git:" + ud.host + ud.path.replace('/', '.') + ud.unresolvedrev[name]
377
378 def _lsremote(self, ud, d, search):
379 """
380 Run git ls-remote with the specified search string
381 """
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500382 # Prevent recursion e.g. in OE if SRCPV is in PV, PV is in WORKDIR,
383 # and WORKDIR is in PATH (as a result of RSS), our call to
384 # runfetchcmd() exports PATH so this function will get called again (!)
385 # In this scenario the return call of the function isn't actually
386 # important - WORKDIR isn't needed in PATH to call git ls-remote
387 # anyway.
388 if d.getVar('_BB_GIT_IN_LSREMOTE', False):
389 return ''
390 d.setVar('_BB_GIT_IN_LSREMOTE', '1')
391 try:
392 repourl = self._get_repo_url(ud)
393 cmd = "%s ls-remote %s %s" % \
394 (ud.basecmd, repourl, search)
395 if ud.proto.lower() != 'file':
396 bb.fetch2.check_network_access(d, cmd, repourl)
397 output = runfetchcmd(cmd, d, True)
398 if not output:
399 raise bb.fetch2.FetchError("The command %s gave empty output unexpectedly" % cmd, ud.url)
400 finally:
401 d.delVar('_BB_GIT_IN_LSREMOTE')
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500402 return output
403
404 def _latest_revision(self, ud, d, name):
405 """
406 Compute the HEAD revision for the url
407 """
408 output = self._lsremote(ud, d, "")
409 # Tags of the form ^{} may not work, need to fallback to other form
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600410 if ud.unresolvedrev[name][:5] == "refs/" or ud.usehead:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500411 head = ud.unresolvedrev[name]
412 tag = ud.unresolvedrev[name]
413 else:
414 head = "refs/heads/%s" % ud.unresolvedrev[name]
415 tag = "refs/tags/%s" % ud.unresolvedrev[name]
416 for s in [head, tag + "^{}", tag]:
Patrick Williamsc0f7c042017-02-23 20:41:17 -0600417 for l in output.strip().split('\n'):
418 sha1, ref = l.split()
419 if s == ref:
420 return sha1
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500421 raise bb.fetch2.FetchError("Unable to resolve '%s' in upstream git repository in git ls-remote output for %s" % \
422 (ud.unresolvedrev[name], ud.host+ud.path))
423
424 def latest_versionstring(self, ud, d):
425 """
426 Compute the latest release name like "x.y.x" in "x.y.x+gitHASH"
427 by searching through the tags output of ls-remote, comparing
428 versions and returning the highest match.
429 """
430 pupver = ('', '')
431
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500432 tagregex = re.compile(d.getVar('UPSTREAM_CHECK_GITTAGREGEX') or "(?P<pver>([0-9][\.|_]?)+)")
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500433 try:
434 output = self._lsremote(ud, d, "refs/tags/*")
435 except bb.fetch2.FetchError or bb.fetch2.NetworkAccess:
436 return pupver
437
438 verstring = ""
439 revision = ""
440 for line in output.split("\n"):
441 if not line:
442 break
443
444 tag_head = line.split("/")[-1]
445 # Ignore non-released branches
446 m = re.search("(alpha|beta|rc|final)+", tag_head)
447 if m:
448 continue
449
450 # search for version in the line
451 tag = tagregex.search(tag_head)
452 if tag == None:
453 continue
454
455 tag = tag.group('pver')
456 tag = tag.replace("_", ".")
457
458 if verstring and bb.utils.vercmp(("0", tag, ""), ("0", verstring, "")) < 0:
459 continue
460
461 verstring = tag
462 revision = line.split()[0]
463 pupver = (verstring, revision)
464
465 return pupver
466
467 def _build_revision(self, ud, d, name):
468 return ud.revisions[name]
469
470 def gitpkgv_revision(self, ud, d, name):
471 """
472 Return a sortable revision number by counting commits in the history
473 Based on gitpkgv.bblass in meta-openembedded
474 """
475 rev = self._build_revision(ud, d, name)
476 localpath = ud.localpath
477 rev_file = os.path.join(localpath, "oe-gitpkgv_" + rev)
478 if not os.path.exists(localpath):
479 commits = None
480 else:
481 if not os.path.exists(rev_file) or not os.path.getsize(rev_file):
482 from pipes import quote
483 commits = bb.fetch2.runfetchcmd(
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500484 "git rev-list %s -- | wc -l" % quote(rev),
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500485 d, quiet=True).strip().lstrip('0')
486 if commits:
487 open(rev_file, "w").write("%d\n" % int(commits))
488 else:
489 commits = open(rev_file, "r").readline(128).strip()
490 if commits:
491 return False, "%s+%s" % (commits, rev[:7])
492 else:
493 return True, str(rev)
494
495 def checkstatus(self, fetch, ud, d):
496 try:
497 self._lsremote(ud, d, "")
498 return True
Brad Bishop6e60e8b2018-02-01 10:27:11 -0500499 except bb.fetch2.FetchError:
Patrick Williamsc124f4f2015-09-15 14:41:29 -0500500 return False