git-worktree: Parse wrap files instead of meson introspect

meson introspect is the wrong approach since it:

* Requires a pre-existing build directory for some branch
* Gives us potentially incorrect information since it tells us
  subproject details for the current branch, not the branch we're
  checking out.
* Does not allow us to share the git repos for non-gst repos since it
  can't tell us the git branches for them.

Instead, parse the wrap files in the branch we're checking out since
they're just INI-style config files.
This commit is contained in:
Nirbheek Chauhan 2019-11-23 16:56:34 +05:30
parent d72ce5f14e
commit a950c286ba

View file

@ -1,45 +1,56 @@
#!/usr/bin/env python3 #!/usr/bin/env python3
import argparse
import json
import os import os
import glob
import argparse
import subprocess import subprocess
import xml.etree.ElementTree as ET import configparser
import sys
from scripts.common import git from scripts.common import git
from scripts.common import Colors from scripts.common import Colors
from scripts.common import get_meson
from scripts.common import accept_command
SCRIPTDIR = os.path.normpath(os.path.dirname(__file__)) SCRIPTDIR = os.path.normpath(os.path.dirname(__file__))
SUBPROJECTS_DIR = os.path.normpath(os.path.join(SCRIPTDIR, "subprojects"))
def repo_has_branch(repo_dir, branch):
def checkout_subprojects(worktree_dir, branch): try:
subprojects_dir = os.path.join(SCRIPTDIR, "subprojects") git("describe", branch, repository_path=repo_dir)
worktree_subdir = os.path.join(worktree_dir, "subprojects") except subprocess.CalledProcessError:
return False
meson = get_meson()
installed_s = subprocess.check_output(meson + ['introspect', options.builddir, '--projectinfo'])
for subproj in json.loads(installed_s.decode())["subprojects"]:
repo_name = subproj["name"]
if not repo_name.startswith("gst"):
continue
repo_dir = os.path.normpath(os.path.join(SCRIPTDIR, subprojects_dir, repo_name))
if not os.path.exists(os.path.join(repo_dir, '.git')):
continue
workdir = os.path.normpath(os.path.join(worktree_subdir, repo_name))
if not checkout_worktree(repo_name, repo_dir, workdir, branch):
return False
return True return True
def parse_wrapfile(wrapf):
cgp = configparser.ConfigParser()
cgp.read(wrapf)
if 'wrap-git' not in cgp:
return None
section = cgp['wrap-git']
return section['directory'], section['revision']
def get_wrap_subprojects(srcdir, gst_branch):
'''
Parses wrap files in the subprojects directory for the specified source
tree and gets the revisions for all common repos.
'''
for wrapf in glob.glob(os.path.join(srcdir, 'subprojects', '*.wrap')):
entries = parse_wrapfile(wrapf)
if not entries:
continue
repo_name, repo_branch = entries
parent_repo_dir = os.path.join(SUBPROJECTS_DIR, repo_name)
if not os.path.exists(os.path.join(parent_repo_dir, '.git')):
continue
# If a branch of the same name exists in the gst subproject, use it
if repo_name.startswith('gst') and repo_has_branch(parent_repo_dir, gst_branch):
repo_branch = gst_branch
yield repo_name, repo_branch, parent_repo_dir
def checkout_worktree(repo_name, repo_dir, worktree_dir, branch): def checkout_worktree(repo_name, repo_dir, worktree_dir, branch):
print("Checking out worktree %s in %s (branch %s)" % (repo_name, worktree_dir, branch)) print('Checking out worktree for project {!r} into {!r} '
'(branch {})'.format(repo_name, worktree_dir, branch))
try: try:
git("worktree", "add", worktree_dir, branch, repository_path=repo_dir) git("worktree", "add", worktree_dir, branch, repository_path=repo_dir)
except Exception as e: except Exception as e:
@ -52,12 +63,21 @@ def checkout_worktree(repo_name, repo_dir, worktree_dir, branch):
commit_message = git("show", "--shortstat", repository_path=repo_dir).split("\n") commit_message = git("show", "--shortstat", repository_path=repo_dir).split("\n")
print(u" -> %s%s%s - %s" % (Colors.HEADER, repo_dir, Colors.ENDC, print(u" -> %s%s%s - %s" % (Colors.HEADER, repo_dir, Colors.ENDC,
commit_message[4].strip())) commit_message[4].strip()))
return True
def checkout_subprojects(worktree_dir, branch):
worktree_subdir = os.path.join(worktree_dir, "subprojects")
for repo_name, repo_branch, parent_repo_dir in get_wrap_subprojects(worktree_dir, branch):
workdir = os.path.normpath(os.path.join(worktree_subdir, repo_name))
if not checkout_worktree(repo_name, parent_repo_dir, workdir, repo_branch):
return False
return True return True
if __name__ == "__main__": if __name__ == "__main__":
parser = argparse.ArgumentParser(prog="git-update") parser = argparse.ArgumentParser(prog="git-worktree")
parser.add_argument('worktree_dir', metavar='worktree_dir', type=str, parser.add_argument('worktree_dir', metavar='worktree_dir', type=str,
@ -68,19 +88,11 @@ if __name__ == "__main__":
default=False, default=False,
action='store_true', action='store_true',
help="Do not output ansi colors.") help="Do not output ansi colors.")
parser.add_argument("--builddir", '-C',
default=os.path.join(SCRIPTDIR, "build"),
help="The meson build directory")
options = parser.parse_args() options = parser.parse_args()
if options.no_color or not Colors.can_enable(): if options.no_color or not Colors.can_enable():
Colors.disable() Colors.disable()
if not os.path.exists(options.builddir):
print("GStreamer not built in %s\n\nBuild it and try again" %
options.builddir)
exit(1)
options.worktree_dir = os.path.abspath(options.worktree_dir) options.worktree_dir = os.path.abspath(options.worktree_dir)
if not checkout_worktree('gst-build', SCRIPTDIR, options.worktree_dir, options.branch): if not checkout_worktree('gst-build', SCRIPTDIR, options.worktree_dir, options.branch):
exit(1) exit(1)