backport Git support from 1.8.16 to 1.4.2
authorAndreas Oberritter <obi@saftware.de>
Wed, 4 Nov 2009 18:16:02 +0000 (19:16 +0100)
committerAndreas Oberritter <obi@saftware.de>
Wed, 4 Nov 2009 18:16:02 +0000 (19:16 +0100)
lib/bb/fetch/git.py

index 49235c1..09625b9 100644 (file)
@@ -41,20 +41,63 @@ def rungitcmd(cmd,d):
 
     # Need to export PATH as git is likely to be in metadata paths 
     # rather than host provided
-    pathcmd = 'export PATH=%s; %s' % (data.expand('${PATH}', d), cmd)
+    cmd = 'export PATH=%s; %s' % (data.expand('${PATH}', d), cmd)
+
+    # redirect stderr to stdout
+    stdout_handle = os.popen(cmd + " 2>&1", "r")
+    output = ""
+
+    while 1:
+        line = stdout_handle.readline()
+        if not line:
+            break
+        print line
+        output += line
+
+    status =  stdout_handle.close() or 0
+    signal = status >> 8
+    exitstatus = status & 0xff
+
+    if signal:
+        raise FetchError("Fetch command %s failed with signal %s, output:\n%s" % (cmd, signal, output))
+    elif status != 0:
+        raise FetchError("Fetch command %s failed with exit code %s, output:\n%s" % (cmd, status, output))
+
+    return output
+
+def contains_ref(tag, d):
+    output = rungitcmd("git log --pretty=oneline -n 1 %s -- 2> /dev/null | wc -l" % tag, d)
+    return output.split()[0] != "0"
+
+def latest_revision(proto, user, host, path, branch):
+    """
+    Compute the HEAD revision for the url
+    """
+    if user:
+        username = user + '@'
+    else:
+        username = ""
+
+    output = rungitcmd("git ls-remote %s://%s%s%s %s" % (proto, username, host, path, branch), d)
+    return output.split()[0]
 
-    myret = os.system(pathcmd)
+def getbranch(parm):
+    if 'branch' in parm:
+        branch = parm['branch']
+    else:
+        branch = "master"
+    if not branch:
+        branch = "master"
 
-    if myret != 0:
-        raise FetchError("Git: %s failed" % pathcmd)
+    return branch
 
-def gettag(parm):
+def gettag(parm, proto, user, host, path, branch):
     if 'tag' in parm:
         tag = parm['tag']
     else:
-        tag = ""
-    if not tag:
-        tag = "master"
+        tag = latest_revision(proto, user, host, path, branch)
+    if not tag or tag == "master":
+        tag = latest_revision(proto, user, host, path, branch)
 
     return tag
 
@@ -76,7 +119,9 @@ def localfile(url, d):
     if "localpath" in parm:
         return parm["localpath"]
 
-    tag = gettag(parm)
+    proto = getprotocol(parm)
+    branch = getbranch(parm)
+    tag = gettag(parm, proto, user, host, path, branch)
 
     return data.expand('git_%s%s_%s.tar.gz' % (host, path.replace('/', '.'), tag), d)
 
@@ -104,8 +149,14 @@ class Git(Fetch):
         for loc in urls:
             (type, host, path, user, pswd, parm) = bb.decodeurl(data.expand(loc, d))
 
-            tag = gettag(parm)
             proto = getprotocol(parm)
+            branch = getbranch(parm)
+            tag = gettag(parm, proto, user, host, path, branch)
+
+            if user:
+                username = user + '@'
+            else:
+                username = ""
 
             gitsrcname = '%s%s' % (host, path.replace('/', '.'))
 
@@ -116,27 +167,22 @@ class Git(Fetch):
             coname = '%s' % (tag)
             codir = os.path.join(repodir, coname)
 
-            cofile = self.localpath(loc, d)
-
-            # tag=="master" must always update
-            if (tag != "master") and Fetch.try_mirror(d, localfile(loc, d)):
-                bb.debug(1, "%s already exists (or was stashed). Skipping git checkout." % cofile)
-                continue
-
             if not os.path.exists(repodir):
                 if Fetch.try_mirror(d, repofilename):    
                     bb.mkdirhier(repodir)
                     os.chdir(repodir)
                     rungitcmd("tar -xzf %s" % (repofile),d)
                 else:
-                    rungitcmd("git clone -n %s://%s%s %s" % (proto, host, path, repodir),d)
+                    rungitcmd("git clone -n %s://%s%s%s %s" % (proto, username, host, path, repodir),d)
 
             os.chdir(repodir)
-            rungitcmd("git pull %s://%s%s" % (proto, host, path),d)
-            rungitcmd("git pull --tags %s://%s%s" % (proto, host, path),d)
-            rungitcmd("git prune-packed", d)
-            # old method of downloading tags
-            #rungitcmd("rsync -a --verbose --stats --progress rsync://%s%s/ %s" % (host, path, os.path.join(repodir, ".git", "")),d)
+            # Remove all but the .git directory
+            if not contains_ref(tag, d):
+                rungitcmd("rm * -Rf", d)
+                rungitcmd("git fetch %s://%s%s%s %s" % (proto, username, host, path, branch), d)
+                rungitcmd("git fetch --tags %s://%s%s%s" % (proto, username, host, path), d)
+                rungitcmd("git prune-packed", d)
+                rungitcmd("git pack-redundant --all | xargs -r rm", d)
 
             os.chdir(repodir)
             bb.note("Creating tarball of git repository")
@@ -152,4 +198,4 @@ class Git(Fetch):
 
             os.chdir(codir)
             bb.note("Creating tarball of git checkout")
-            rungitcmd("tar -czf %s %s" % (cofile, os.path.join(".", "*") ),d)
+            rungitcmd("tar -czf %s %s" % (self.localpath(loc, d), os.path.join(".", "*") ),d)