Skip to content

Commit 4fb9289

Browse files
committed
Add script to assist in moving PR's
1 parent ea0f3a1 commit 4fb9289

File tree

1 file changed

+220
-0
lines changed

1 file changed

+220
-0
lines changed

scripts/move-pr-to-intel-llvm.py

Lines changed: 220 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,220 @@
1+
#!/usr/bin/env python3
2+
3+
# Copyright (C) 2024 Intel Corporation
4+
#
5+
# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions.
6+
# See LICENSE.TXT
7+
# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
8+
9+
"""
10+
Use this script to move an existing pull request in the
11+
https://github.com/oneapi-src/unified-runtime project to a new pull request
12+
targeting the top-level unified-runtime directory of the
13+
https://github.com/intel/llvm project.
14+
15+
Git operations are performed on both repositories.
16+
17+
GitHub interactions are performed using the gh command-line tool which must
18+
reside on the PATH and be authenticated.
19+
"""
20+
21+
import argparse
22+
import os
23+
import shutil
24+
import subprocess
25+
from subprocess import PIPE
26+
import sys
27+
28+
verbose = False
29+
30+
31+
def error(*args, **kwargs):
32+
print("\033[31merror:\033[0m", *args, file=sys.stderr, **kwargs)
33+
exit(1)
34+
35+
36+
def run(command, **kwargs):
37+
if verbose:
38+
print(command)
39+
result = subprocess.run(command, **kwargs)
40+
result.check_returncode()
41+
return result
42+
43+
44+
def main():
45+
global verbose
46+
47+
cli = argparse.ArgumentParser(
48+
description=__doc__, formatter_class=argparse.RawTextHelpFormatter
49+
)
50+
cli.add_argument(
51+
"-v",
52+
"--verbose",
53+
action="store_true",
54+
help="enable printing verbose output",
55+
)
56+
cli.add_argument(
57+
"--ur-dir",
58+
default=".",
59+
help="local directory containing a clone of oneapi-src/unified-runtime",
60+
)
61+
cli.add_argument(
62+
"--ur-remote",
63+
default="origin",
64+
help="unified-runtime remote to fetch from, defaults to 'origin'",
65+
)
66+
cli.add_argument(
67+
"--ur-branch",
68+
default=None,
69+
help="unified-runtime branch to move, defaults to current branch",
70+
)
71+
# TODO: cli.add_argument("--ur-pr", default=None, help="unified-runtime pull request id to move")
72+
cli.add_argument(
73+
"intel_llvm_dir",
74+
help="local directory containing a clone of intel/llvm",
75+
)
76+
cli.add_argument(
77+
"--intel-llvm-remote",
78+
default="origin",
79+
help="intel/llvm remote to fetch from, defaults to 'origin'",
80+
)
81+
cli.add_argument(
82+
"--intel-llvm-base-branch",
83+
default=None,
84+
help="intel/llvm branch to base new branch upon, defaults to 'sycl'",
85+
)
86+
cli.add_argument(
87+
"--intel-llvm-branch",
88+
default=None,
89+
help="intel/llvm remote branch to create, defaults to --ur-branch",
90+
)
91+
92+
args = cli.parse_args()
93+
verbose = args.verbose
94+
95+
# validate git is usable
96+
git = shutil.which("git")
97+
if not git:
98+
error("git command not found")
99+
100+
# validate gh is usable
101+
gh = shutil.which("gh")
102+
if not gh:
103+
error(
104+
"gh command not found, see https://cli.github.com/ for install instructions",
105+
)
106+
gh_auth_status = run([gh, "auth", "status"], stdout=PIPE)
107+
if "Logged in" not in gh_auth_status.stdout.decode():
108+
error("gh is not authenticated, please run 'gh auth login'")
109+
110+
# get UR branch if not already set
111+
if not args.ur_branch:
112+
ur_branch = run(
113+
[git, "-C", args.ur_dir, "rev-parse", "--abbrev-ref", "HEAD"],
114+
stdout=PIPE,
115+
)
116+
args.ur_branch = ur_branch.stdout.decode().strip()
117+
if not args.intel_llvm_branch:
118+
args.intel_llvm_branch = args.ur_branch
119+
120+
# validate args.ur_remote
121+
ur_remote_url = run(
122+
[
123+
git,
124+
"-C",
125+
args.ur_dir,
126+
"config",
127+
"--get",
128+
f"remote.{args.ur_remote}.url",
129+
],
130+
stdout=PIPE,
131+
)
132+
ur_remote_url = ur_remote_url.stdout.decode().strip()
133+
if "oneapi-src/unified-runtime" in ur_remote_url:
134+
error(
135+
f"'{args.ur_remote}' remote URL does not contain",
136+
"'oneapi-src/unified-runtime', specify the correct remote using",
137+
"the --ur-remote command-line option",
138+
)
139+
140+
# TODO: check if ur local branch and remote tracking branch are in sync
141+
142+
# check how far behind origin/main the feature branch is
143+
rev_list = run(
144+
[
145+
git,
146+
"-C",
147+
args.ur_dir,
148+
"rev-list",
149+
"--left-right",
150+
"--count",
151+
f"{args.ur_remote}/main...{args.ur_branch}",
152+
],
153+
stdout=PIPE,
154+
)
155+
rev_list = rev_list.stdout.decode().strip().split()
156+
assert len(rev_list) == 2
157+
behind, ahead = rev_list
158+
if int(behind) > 0:
159+
error(
160+
f"rebase required, feature branch '{args.ur_branch}' is {behind}",
161+
f"commits behind '{args.ur_remote}/main'",
162+
)
163+
164+
return
165+
166+
run([git, "-C", args.ur_dir, "fetch", args.ur_remote])
167+
168+
# Use git format-patch to create a list of patches from the feature branch
169+
patches = run(
170+
[
171+
git,
172+
"-C",
173+
args.ur_dir,
174+
"format-patch",
175+
"--output-directory",
176+
args.intel_llvm_dir,
177+
f"{args.ur_remote}/main..{args.ur_branch}",
178+
],
179+
stdout=PIPE,
180+
)
181+
patches = patches.stdout.decode().strip()
182+
print(patches)
183+
patches = patches.split("\n")
184+
185+
# TODO: sync with upstream
186+
# run([git, "-C", args.intel_llvm_dir, "fetch", args.intel_llvm_remote])
187+
188+
# TODO: check if feature branch already exists
189+
190+
# create feature branch on intel/llvm
191+
run(
192+
[
193+
git,
194+
"-C",
195+
args.intel_llvm_dir,
196+
"branch",
197+
args.intel_llvm_branch,
198+
f"{args.intel_llvm_remote}/{args.intel_llvm_base_branch}",
199+
]
200+
)
201+
run([git, "-C", args.intel_llvm_dir, "checkout", args.intel_llvm_branch])
202+
203+
# Use git am to apply list of patches to intel/llvm
204+
run(
205+
[git, "-C", args.intel_llvm_dir, "am", "--directory=unified-runtime"]
206+
+ patches
207+
)
208+
209+
# clean up patch files
210+
for patch in patches:
211+
os.remove(patch)
212+
213+
# TODO: create pull request with feature branch
214+
215+
216+
if __name__ == "__main__":
217+
try:
218+
main()
219+
except KeyboardInterrupt:
220+
exit(130)

0 commit comments

Comments
 (0)