9 from scripts.common import git
10 from scripts.common import Colors
13 SCRIPTDIR = os.path.normpath(os.path.dirname(__file__))
14 SUBPROJECTS_DIR = os.path.normpath(os.path.join(SCRIPTDIR, "subprojects"))
17 def repo_has_branch(repo_dir, branch):
21 git("describe", branch, repository_path=repo_dir)
22 except subprocess.CalledProcessError:
26 def parse_wrapfile(wrapf):
27 cgp = configparser.ConfigParser()
29 if 'wrap-git' not in cgp:
31 section = cgp['wrap-git']
32 return section['directory'], section['revision']
34 def get_wrap_subprojects(srcdir, gst_branch):
36 Parses wrap files in the subprojects directory for the specified source
37 tree and gets the revisions for all common repos.
39 for wrapf in glob.glob(os.path.join(srcdir, 'subprojects', '*.wrap')):
40 entries = parse_wrapfile(wrapf)
44 repo_name, repo_branch = entries
45 parent_repo_dir = os.path.join(SUBPROJECTS_DIR, repo_name)
46 if not os.path.exists(os.path.join(parent_repo_dir, '.git')):
48 # If a branch of the same name exists in the gst subproject, use it
49 if repo_name.startswith('gst') and repo_has_branch(parent_repo_dir, gst_branch):
50 repo_branch = gst_branch
52 yield repo_name, repo_branch, parent_repo_dir
54 def checkout_worktree(repo_name, repo_dir, worktree_dir, branch, force=False):
55 print('Checking out worktree for project {!r} into {!r} '
56 '(branch {})'.format(repo_name, worktree_dir, branch))
58 args = ["worktree", "add"]
61 args += [worktree_dir, branch]
62 git(*args, repository_path=repo_dir)
63 except subprocess.CalledProcessError as e:
64 out = getattr(e, "output", b"").decode()
65 print("\nCould not checkout worktree %s, please fix and try again."
66 " Error:\n\n%s %s" % (repo_dir, out, e))
70 commit_message = git("show", "--shortstat", repository_path=repo_dir).split("\n")
71 print(u" -> %s%s%s - %s" % (Colors.HEADER, repo_dir, Colors.ENDC,
72 commit_message[4].strip()))
75 def checkout_subprojects(worktree_dir, branch):
76 worktree_subdir = os.path.join(worktree_dir, "subprojects")
78 for repo_name, repo_branch, parent_repo_dir in get_wrap_subprojects(worktree_dir, branch):
79 workdir = os.path.normpath(os.path.join(worktree_subdir, repo_name))
80 if not checkout_worktree(repo_name, parent_repo_dir, workdir, repo_branch, force=True):
85 def remove_worktree(worktree_dir):
86 worktree_subdir = os.path.join(worktree_dir, "subprojects")
88 for repo_name, _, parent_repo_dir in get_wrap_subprojects(worktree_dir, None):
89 workdir = os.path.normpath(os.path.join(worktree_subdir, repo_name))
90 if not os.path.exists(workdir):
93 subprojdir = os.path.normpath(os.path.join(SUBPROJECTS_DIR, repo_name))
94 if not os.path.exists(subprojdir):
97 print('Removing worktree {!r}'.format(workdir))
99 git('worktree', 'remove', '-f', workdir, repository_path=subprojdir)
100 except subprocess.CalledProcessError as e:
101 out = getattr(e, "output", b"").decode()
102 print('Ignoring error while removing worktree {!r}:\n\n{}'.format(workdir, out))
105 git('worktree', 'remove', '-f', worktree_dir, repository_path=SCRIPTDIR)
106 except subprocess.CalledProcessError:
107 print('Failed to remove worktree {!r}'.format(worktree_dir))
112 if __name__ == "__main__":
113 parser = argparse.ArgumentParser(prog="gst-worktree")
114 parser.add_argument("--no-color", default=False, action='store_true',
115 help="Do not output ANSI colors")
117 subparsers = parser.add_subparsers(help='The sub-command to run', dest='command')
119 parser_add = subparsers.add_parser('add',
120 help='Create a worktree for gst-build and all subprojects')
121 parser_add.add_argument('worktree_dir', type=str,
122 help='Directory where to create the new worktree')
123 parser_add.add_argument('branch', type=str, default=None,
124 help='Branch to checkout')
126 parser_rm = subparsers.add_parser('rm',
127 help='Remove a gst-build worktree and the subproject worktrees inside it')
128 parser_rm.add_argument('worktree_dir', type=str,
129 help='Worktree directory to remove')
131 options = parser.parse_args()
133 if options.no_color or not Colors.can_enable():
136 if not options.command:
140 worktree_dir = os.path.abspath(options.worktree_dir)
142 if options.command == 'add':
143 if not checkout_worktree('gst-build', SCRIPTDIR, worktree_dir, options.branch):
145 if not checkout_subprojects(worktree_dir, options.branch):
147 elif options.command == 'rm':
148 if not os.path.exists(worktree_dir):
149 print('Cannot remove worktree directory {!r}, it does not exist'.format(worktree_dir))
151 if not remove_worktree(worktree_dir):