1import os
2import subprocess
3
4def find_git(env=None):
5    """Find the git binary."""
6    if env is not None and 'GIT' in env:
7        return env.get_flat('GIT')
8
9    # Get version from GIT
10    if os.path.exists("/usr/bin/git"):
11        # this is useful when doing make dist without configuring
12        return "/usr/bin/git"
13
14    return None
15
16
17def has_submodules(path):
18    """Check whether a source directory is git-versioned and has submodules.
19
20    :param path: Path to Samba source directory
21    """
22    return (os.path.isdir(os.path.join(path, ".git")) and
23            os.path.isfile(os.path.join(path, ".gitmodules")))
24
25
26def read_submodule_status(path, env=None):
27    """Check status of submodules.
28
29    :param path: Path to git directory
30    :param env: Optional waf environment
31    :return: Yields tuples with submodule relpath and status
32        (one of: 'out-of-date', 'not-checked-out', 'up-to-date')
33    :raise RuntimeError: raised when parsing of 'git submodule status' output
34        fails.
35    """
36    if not has_submodules(path):
37        # No point in running git.
38        return
39    git = find_git(env)
40    if git is None:
41        return
42    p = subprocess.Popen([git, "submodule", "status"], stdout=subprocess.PIPE,
43        cwd=path)
44    (stdout, stderr) = p.communicate(None)
45    for l in stdout.splitlines():
46        l = l.rstrip()
47        status = l[0]
48        l = l[1:]
49        parts = l.split(" ")
50        if len(parts) > 2 and status in ("-", "+"):
51            yield (parts[1], "out-of-date")
52        elif len(parts) == 2 and status == "-":
53            yield (parts[1], "not-checked-out")
54        elif len(parts) > 2 and status == " ":
55            yield (parts[1], "up-to-date")
56        else:
57            raise RuntimeError("Unable to parse submodule status: %r, %r" % (status, parts))
58