blob: 27b8cb742f8f06d718ff9ec315d1767353e1b59d [file] [log] [blame]
Diana Picus3b2ef822016-10-13 16:53:18 +03001"""This is the main tool for handling llvm builds, bisects etc."""
2
3import os
Diana Picusadb07c42017-11-22 16:12:57 +01004from sys import argv
Diana Picus3b2ef822016-10-13 16:53:18 +03005from sys import exit
6
Diana Picus95226d42017-11-01 13:16:54 +01007from modules.llvm import LLVMSubproject
8from modules.llvm import LLVMSourceConfig
9from modules.llvm import get_remote_branch
10from modules.llvm import push_branch
11
Diana Picus3b2ef822016-10-13 16:53:18 +030012from linaropy.git.clone import Clone
13from linaropy.proj import Proj
14
15from argparse import Action, ArgumentParser, RawTextHelpFormatter
Diana Picusefc7bda2017-06-09 19:14:08 +020016from functools import partial
Diana Picus3b2ef822016-10-13 16:53:18 +030017
18
19def die(message, config_to_dump=None):
20 """Print an error message and exit."""
Diana Picusb4307602017-04-05 19:48:39 +020021 print(message)
Diana Picus3b2ef822016-10-13 16:53:18 +030022
23 if config_to_dump is not None:
24 dump_config(config_to_dump)
25
26 exit(1)
27
Diana Picus3d1a3012017-03-14 17:38:32 +010028
Diana Picus3d1a3012017-03-14 17:38:32 +010029def get_worktree_root(env):
Diana Picus81089db2017-05-05 22:26:49 +020030 """Get the path to the LLVM worktree corresponding to env."""
31 return os.path.join(env, "llvm")
Diana Picus3b2ef822016-10-13 16:53:18 +030032
33
34def dump_config(config):
35 """Dump the list of projects that are enabled in the given config."""
36
Diana Picusb4307602017-04-05 19:48:39 +020037 print("Projects linked:")
Diana Picus3b2ef822016-10-13 16:53:18 +030038 enabled = config.get_enabled_subprojects()
39 if not enabled:
Diana Picusb4307602017-04-05 19:48:39 +020040 print("none")
Diana Picus3b2ef822016-10-13 16:53:18 +030041 else:
42 for subproj in sorted(enabled):
Diana Picusb4307602017-04-05 19:48:39 +020043 print(" + {}".format(subproj))
Diana Picus3b2ef822016-10-13 16:53:18 +030044
45
46def projects(args):
47 """Add/remove subprojects based on the values in args."""
48
49 proj = Proj()
Diana Picus3d1a3012017-03-14 17:38:32 +010050
51 llvm_worktree_root = get_worktree_root(args.env)
Diana Picus81089db2017-05-05 22:26:49 +020052 llvm_repos_root = args.repos
Diana Picus3b2ef822016-10-13 16:53:18 +030053 config = LLVMSourceConfig(proj, llvm_worktree_root)
54
55 if not args.add and not args.remove:
56 # Nothing to change, just print the current configuration
57 dump_config(config)
58 exit(0)
59
60 to_add = {}
61 if args.add:
62 for subproj in args.add:
63 repo = Clone(proj, os.path.join(llvm_repos_root, subproj))
64 to_add[subproj] = repo
65
66 try:
67 config.update(to_add, args.remove)
68 except (EnvironmentError, ValueError) as exc:
69 die("Failed to update subprojects because:\n{}".format(str(exc)))
70
71 dump_config(config)
72
Diana Picusefc7bda2017-06-09 19:14:08 +020073
Diana Picus95226d42017-11-01 13:16:54 +010074def push_current_branch(args):
Diana Picusefc7bda2017-06-09 19:14:08 +020075 """Push current branch to origin."""
76
77 proj = Proj()
78
79 llvm_worktree_root = get_worktree_root(args.env)
80 config = LLVMSourceConfig(proj, llvm_worktree_root)
81
Diana Picus95226d42017-11-01 13:16:54 +010082 llvm_worktree = Clone(proj, llvm_worktree_root)
83 local_branch = llvm_worktree.getbranch()
Diana Picusefc7bda2017-06-09 19:14:08 +020084
85 try:
Diana Picus95226d42017-11-01 13:16:54 +010086 remote_branch = get_remote_branch(llvm_worktree, local_branch)
87 config.for_each_enabled(partial(push_branch, proj, local_branch,
88 remote_branch))
89 print("Pushed to {}".format(remote_branch))
90 except (EnvironmentError, RuntimeError) as exc:
Diana Picusefc7bda2017-06-09 19:14:08 +020091 die("Failed to push branch because: " + str(exc) + str(exc.__cause__))
92
Diana Picus95226d42017-11-01 13:16:54 +010093
Diana Picus3b2ef822016-10-13 16:53:18 +030094##########################################################################
95# Command line parsing #
96##########################################################################
97
98# If we decide we want shorthands for the subprojects, we can append to this
99# list
Diana Picusb4307602017-04-05 19:48:39 +0200100valid_subprojects = list(LLVMSubproject.get_all_subprojects().keys())
Diana Picus3b2ef822016-10-13 16:53:18 +0300101
102options = ArgumentParser(formatter_class=RawTextHelpFormatter)
Diana Picus81089db2017-05-05 22:26:49 +0200103options.add_argument(
104 '--env',
105 required=True,
106 help="Path to the environment to update.")
Diana Picus3d1a3012017-03-14 17:38:32 +0100107
Diana Picusadb07c42017-11-22 16:12:57 +0100108subcommands = options.add_subparsers(dest="subcommand")
Diana Picus3b2ef822016-10-13 16:53:18 +0300109
110# Subcommand for adding / removing subprojects
Diana Picus36317e82017-10-31 15:35:24 +0100111projs = subcommands.add_parser(
112 "projects", help="Add/remove LLVM subprojects.\n"
113 "Adding a subproject will create a worktree for it "
114 "somewhere in the LLVM source tree, on the same git "
115 "branch as LLVM itself.\n"
116 "Removing a subproject will remove the worktree, but "
117 "not the underlying git branch.")
Diana Picus3b2ef822016-10-13 16:53:18 +0300118projs.set_defaults(run_command=projects)
119
120# TODO: Overwriting previous values is not necessarily what users expect (so for
121# instance --add S1 S2 --remove S3 --add S4 would lead to adding only S4). We
122# can do better by using action='append', which would create a list (of lists?
123# or of lists and scalars?) that we can flatten to obtain all the values passed
124# by the user.
125projs.add_argument(
126 '-a', '--add',
127 nargs='+',
128 choices=valid_subprojects,
129 metavar='subproject',
Diana Picus36317e82017-10-31 15:35:24 +0100130 help="Enable given subprojects. Valid values are:\n\t{}\n".format(
Diana Picus3b2ef822016-10-13 16:53:18 +0300131 "\n\t".join(valid_subprojects)))
132projs.add_argument(
133 '-r', '--remove',
134 nargs='+',
135 choices=valid_subprojects,
136 metavar='subproject',
Diana Picus36317e82017-10-31 15:35:24 +0100137 help="Disable given subprojects.")
Diana Picusadb07c42017-11-22 16:12:57 +0100138projs.add_argument(
139 '--repos',
140 help="Path to the directory containing the repositories for all LLVM "
141 "subprojects.")
Diana Picus3b2ef822016-10-13 16:53:18 +0300142
Diana Picusefc7bda2017-06-09 19:14:08 +0200143# Subcommand for pushing the current branch to origin
144push = subcommands.add_parser(
145 "push",
Diana Picus36317e82017-10-31 15:35:24 +0100146 help="Push current branch to origin linaro-local/<user>/<branch>, "
147 "for all enabled subprojects.")
Diana Picus95226d42017-11-01 13:16:54 +0100148push.set_defaults(run_command=push_current_branch)
Diana Picusefc7bda2017-06-09 19:14:08 +0200149
Diana Picus3b2ef822016-10-13 16:53:18 +0300150args = options.parse_args()
Diana Picusadb07c42017-11-22 16:12:57 +0100151if args.subcommand == "projects" and args.add and not args.repos:
152 projs.error(
153 "When adding a subproject you must also pass the --repos argument")
Diana Picus3b2ef822016-10-13 16:53:18 +0300154args.run_command(args)