Skip to content

Commit ebfd33c

Browse files
committed
feat: use a submodule for ninja sources
1 parent 8e50166 commit ebfd33c

File tree

8 files changed

+64
-196
lines changed

8 files changed

+64
-196
lines changed

.github/workflows/build.yml

+4-2
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ jobs:
6464
steps:
6565
- uses: actions/checkout@v4
6666
with:
67-
fetch-depth: 0 # required for versioneer to find tags
67+
fetch-depth: 0 # required for setuptools_scm to find tags
68+
submodules: 'recursive'
6869

6970
- name: Set up QEMU
7071
uses: docker/[email protected]
@@ -97,7 +98,8 @@ jobs:
9798
steps:
9899
- uses: actions/checkout@v4
99100
with:
100-
fetch-depth: 0 # required for versioneer to find tags
101+
fetch-depth: 0 # required for setuptools_scm to find tags
102+
submodules: 'recursive'
101103

102104
- name: Build SDist
103105
run: pipx run build --sdist

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[submodule "ninja-upstream"]
2+
path = ninja-upstream
3+
url = https://github.com/Kitware/ninja.git

CMakeLists.txt

+5-39
Original file line numberDiff line numberDiff line change
@@ -7,52 +7,18 @@ set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_MODULE_PATH})
77
# Options
88
option(BUILD_VERBOSE "Display additional information while building (e.g download progress, ...)" OFF)
99
option(RUN_NINJA_TEST "Run Ninja test suite" ON)
10-
set(ARCHIVE_DOWNLOAD_DIR "${CMAKE_BINARY_DIR}" CACHE PATH "Directory where to download archives")
1110

12-
include(NinjaUrls)
13-
14-
function(check_archive_var archive_var)
15-
if(NOT DEFINED "${archive_var}_url")
16-
message(FATAL_ERROR "Failed to determine which archive to download: '${archive_var}_url' variable is not defined")
17-
endif()
18-
if(NOT DEFINED "${archive_var}_sha256")
19-
message(FATAL_ERROR "Could you make sure variable '${archive_var}_sha256' is defined ?")
20-
endif()
21-
endfunction()
22-
23-
set(src_archive "unix_source")
24-
if(WIN32)
25-
set(src_archive "windows_source")
26-
endif()
27-
check_archive_var("${src_archive}")
28-
29-
message(STATUS "*********************************************")
11+
message(STATUS "************************************")
3012
message(STATUS "Ninja Python Distribution")
3113
message(STATUS "")
32-
message(STATUS " BUILD_VERBOSE : ${BUILD_VERBOSE}")
33-
message(STATUS " RUN_NINJA_TEST : ${RUN_NINJA_TEST}")
34-
message(STATUS "")
35-
message(STATUS " ARCHIVE_DOWNLOAD_DIR : ${ARCHIVE_DOWNLOAD_DIR}")
36-
message(STATUS "")
37-
message(STATUS " src_archive : ${src_archive}")
38-
message(STATUS " <src_archive>_url : ${${src_archive}_url}")
39-
message(STATUS " <src_archive>_sha256 : ${${src_archive}_sha256}")
40-
message(STATUS "*********************************************")
41-
42-
set(ep_download_no_progress_args)
43-
if(NOT BUILD_VERBOSE)
44-
set(ep_download_no_progress_args
45-
DOWNLOAD_NO_PROGRESS 1
46-
)
47-
endif()
14+
message(STATUS " BUILD_VERBOSE : ${BUILD_VERBOSE}")
15+
message(STATUS " RUN_NINJA_TEST : ${RUN_NINJA_TEST}")
16+
message(STATUS "************************************")
4817

4918
include(FetchContent)
5019
FetchContent_Declare(
5120
ninja
52-
URL ${${src_archive}_url}
53-
URL_HASH SHA256=${${src_archive}_sha256}
54-
DOWNLOAD_DIR ${ARCHIVE_DOWNLOAD_DIR}
55-
${ep_download_no_progress_args}
21+
SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/ninja-upstream
5622
)
5723
FetchContent_MakeAvailable(ninja)
5824

NinjaUrls.cmake

-8
This file was deleted.

constraints.txt

-2
This file was deleted.

ninja-upstream

Submodule ninja-upstream added at 95dee2a

noxfile.py

+1-4
Original file line numberDiff line numberDiff line change
@@ -95,16 +95,13 @@ def bump(session: nox.Session) -> None:
9595
else:
9696
version = args.version
9797

98-
deps = nox.project.load_toml("scripts/update_ninja_version.py")["dependencies"]
99-
session.install(*deps)
100-
10198
extra = ["--quiet"] if args.commit else []
10299
session.run("python", "scripts/update_ninja_version.py", "--upstream-repository", args.upstream_repository, version, *extra)
103100

104101
if args.commit:
105102
session.run("git", "switch", "-c", f"update-to-ninja-{version}", external=True)
106103
files = (
107-
"NinjaUrls.cmake",
104+
"ninja-upstream",
108105
"README.rst",
109106
"tests/test_ninja.py",
110107
"docs/update_ninja_version.rst",

scripts/update_ninja_version.py

+50-141
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,19 @@
1-
# /// script
2-
# dependencies = ["requests"]
3-
# ///
4-
51
"""
6-
Command line executable allowing to update NinjaUrls.cmake, documentation
2+
Command line executable allowing to update upstream sources, documentation
73
and tests given a Ninja version.
84
"""
95
from __future__ import annotations
106

117
import argparse
128
import contextlib
13-
import hashlib
149
import os
1510
import re
16-
import tempfile
11+
import shutil
12+
import subprocess
1713
import textwrap
14+
from pathlib import Path
1815

19-
from requests import request
20-
21-
ROOT_DIR = os.path.join(os.path.dirname(__file__), "..")
22-
23-
REQ_BUFFER_SIZE = 65536 # Chunk size when iterating a download body
16+
ROOT_DIR = Path(__file__).parent.parent.resolve(strict=True)
2417

2518

2619
@contextlib.contextmanager
@@ -31,133 +24,57 @@ def _log(txt, verbose=True):
3124
if verbose:
3225
print(f"{txt} - done")
3326

34-
35-
def _download_file(download_url, filename):
36-
response = request(
37-
method='GET',
38-
url=download_url,
39-
allow_redirects=False,
40-
headers={'Accept': 'application/octet-stream'},
41-
stream=True)
42-
while response.status_code == 302:
43-
response = request(
44-
'GET', response.headers['Location'], allow_redirects=False,
45-
stream=True
46-
)
47-
with open(filename, 'w+b') as f:
48-
for chunk in response.iter_content(chunk_size=REQ_BUFFER_SIZE):
49-
f.write(chunk)
50-
51-
return filename
52-
53-
54-
def _hash_sum(filepath, algorithm="sha256", block_size=2 ** 20):
55-
hasher = hashlib.new(algorithm)
56-
with open(filepath, mode="rb") as fd:
57-
while True:
58-
data = fd.read(block_size)
59-
if not data:
60-
break
61-
hasher.update(data)
62-
63-
return hasher.hexdigest()
64-
65-
66-
def _download_and_compute_sha256(url, filename):
67-
filepath = os.path.join(tempfile.gettempdir(), filename)
68-
with _log(f"Downloading {url}"):
69-
_download_file(url, filepath)
70-
sha256 = _hash_sum(filepath, algorithm="sha256")
71-
return url, sha256
72-
73-
74-
def get_ninja_archive_urls_and_sha256s(upstream_repository, version, verbose=False):
75-
tag_name = f"v{version}"
76-
files_base_url = f"https://github.com/{upstream_repository}/archive/{tag_name}"
77-
78-
with _log(f"Collecting URLs and SHA256s from '{files_base_url}'"):
79-
80-
# Get SHA256s and URLs
81-
urls = {
82-
"unix_source": _download_and_compute_sha256(files_base_url + ".tar.gz", tag_name + ".tar.gz"),
83-
"win_source": _download_and_compute_sha256(files_base_url + ".zip", tag_name + ".zip"),
84-
}
85-
86-
if verbose:
87-
for identifier, (url, sha256) in urls.items():
88-
print(f"[{identifier}]\n{url}\n{sha256}\n")
89-
90-
return urls
91-
92-
93-
def generate_cmake_variables(urls_and_sha256s):
94-
template_inputs = {}
95-
96-
# Get SHA256s and URLs
97-
for var_prefix, urls_and_sha256s_values in urls_and_sha256s.items():
98-
template_inputs[f"{var_prefix}_url"] = urls_and_sha256s_values[0]
99-
template_inputs[f"{var_prefix}_sha256"] = urls_and_sha256s_values[1]
100-
101-
return textwrap.dedent(
102-
"""
103-
#-----------------------------------------------------------------------------
104-
# Ninja sources
105-
set(unix_source_url "{unix_source_url}")
106-
set(unix_source_sha256 "{unix_source_sha256}")
107-
108-
set(windows_source_url "{win_source_url}")
109-
set(windows_source_sha256 "{win_source_sha256}")
110-
"""
111-
).format(**template_inputs)
112-
113-
114-
def update_cmake_urls_script(upstream_repository, version):
115-
content = generate_cmake_variables(get_ninja_archive_urls_and_sha256s(upstream_repository, version))
116-
cmake_urls_filename = "NinjaUrls.cmake"
117-
cmake_urls_filepath = os.path.join(ROOT_DIR, cmake_urls_filename)
118-
119-
msg = f"Updating '{cmake_urls_filename}' with Ninja version {version}"
120-
with _log(msg), open(cmake_urls_filepath, "w") as cmake_file:
121-
cmake_file.write(content)
122-
123-
124-
def _update_file(filepath, regex, replacement, verbose=True):
27+
@contextlib.contextmanager
28+
def chdir(path: Path):
29+
origin = Path().absolute()
30+
os.chdir(path)
31+
try:
32+
yield
33+
finally:
34+
os.chdir(origin)
35+
36+
37+
def update_submodule(upstream_repository, version):
38+
with chdir(ROOT_DIR):
39+
subprocess.run(["git", "submodule", "deinit", "-f", "ninja-upstream"], check=True)
40+
subprocess.run(["git", "rm", "-f", "ninja-upstream"], check=True)
41+
shutil.rmtree(ROOT_DIR / ".git/modules/ninja-upstream")
42+
subprocess.run(["git", "submodule", "add", f"https://github.com/{upstream_repository}.git", "ninja-upstream"], check=True)
43+
subprocess.run(["git", "submodule", "update", "--init", "--recursive", "ninja-upstream"], check=True)
44+
with chdir(ROOT_DIR / "ninja-upstream"):
45+
subprocess.run(["git", "fetch", "--tags"], check=True)
46+
subprocess.run(["git", "checkout", f"v{version}"], check=True)
47+
48+
49+
def _update_file(filepath: Path, regex, replacement, verbose=True):
12550
msg = f"Updating {os.path.relpath(filepath, ROOT_DIR)}"
12651
with _log(msg, verbose=verbose):
12752
pattern = re.compile(regex)
128-
with open(filepath) as doc_file:
53+
with filepath.open() as doc_file:
12954
lines = doc_file.readlines()
13055
updated_content = []
13156
for line in lines:
13257
updated_content.append(re.sub(pattern, replacement, line))
133-
with open(filepath, "w") as doc_file:
58+
with filepath.open("w") as doc_file:
13459
doc_file.writelines(updated_content)
13560

13661

13762
def update_docs(upstream_repository, version):
13863
pattern = re.compile(r"ninja \d+.\d+.\d+(\.[\w\-]+)*")
13964
replacement = f"ninja {version}"
140-
_update_file(
141-
os.path.join(ROOT_DIR, "README.rst"),
142-
pattern, replacement)
65+
_update_file(ROOT_DIR / "README.rst", pattern, replacement)
14366

14467
pattern = re.compile(r"(?<=v)\d+.\d+.\d+(?:\.[\w\-]+)*(?=(?:\.zip|\.tar\.gz|\/))")
14568
replacement = version
146-
_update_file(
147-
os.path.join(ROOT_DIR, "docs/update_ninja_version.rst"),
148-
pattern, replacement)
69+
_update_file(ROOT_DIR / "docs/update_ninja_version.rst", pattern, replacement)
14970

15071
pattern = re.compile(r"(?<!v)\d+.\d+.\d+(?:\.[\w\-]+)*")
15172
replacement = version
152-
_update_file(
153-
os.path.join(ROOT_DIR, "docs/update_ninja_version.rst"),
154-
pattern, replacement, verbose=False)
73+
_update_file(ROOT_DIR / "docs/update_ninja_version.rst", pattern, replacement, verbose=False)
15574

15675
pattern = re.compile(r"github\.com\/[\w\-_]+\/[\w\-_]+(?=\/(?:release|archive))")
15776
replacement = "github.com/" + upstream_repository
158-
_update_file(
159-
os.path.join(ROOT_DIR, "docs/update_ninja_version.rst"),
160-
pattern, replacement, verbose=False)
77+
_update_file(ROOT_DIR / "docs/update_ninja_version.rst", pattern, replacement, verbose=False)
16178

16279

16380
def update_tests(version):
@@ -170,8 +87,7 @@ def update_tests(version):
17087

17188
pattern = re.compile(r'expected_version = "\d+.\d+.\d+(\.[\w\-]+)*"')
17289
replacement = f'expected_version = "{version}"'
173-
_update_file(os.path.join(
174-
ROOT_DIR, "tests/test_ninja.py"), pattern, replacement)
90+
_update_file(ROOT_DIR / "tests/test_ninja.py", pattern, replacement)
17591

17692

17793
def main():
@@ -189,34 +105,27 @@ def main():
189105
default="Kitware/ninja",
190106
help="Ninja upstream repository",
191107
)
192-
parser.add_argument(
193-
"--collect-only",
194-
action="store_true",
195-
help="If specified, only display the archive URLs and associated hashsums",
196-
)
197108
parser.add_argument(
198109
"--quiet",
199110
action="store_true",
200111
help="Hide the output",
201112
)
202113
args = parser.parse_args()
203-
if args.collect_only:
204-
get_ninja_archive_urls_and_sha256s(args.upstream_repository, args.ninja_version, verbose=True)
205-
else:
206-
update_cmake_urls_script(args.upstream_repository, args.ninja_version)
207-
update_docs(args.upstream_repository, args.ninja_version)
208-
update_tests(args.ninja_version)
209-
210-
if not args.quiet:
211-
msg = """\
212-
Complete! Now run:
213-
214-
git switch -c update-to-ninja-{release}
215-
git add -u NinjaUrls.cmake docs/index.rst README.rst tests/test_ninja.py docs/update_ninja_version.rst
216-
git commit -m "Update to Ninja {release}"
217-
gh pr create --fill --body "Created by update_ninja_version.py"
218-
"""
219-
print(textwrap.dedent(msg.format(release=args.ninja_version)))
114+
115+
update_submodule(args.upstream_repository, args.ninja_version)
116+
update_docs(args.upstream_repository, args.ninja_version)
117+
update_tests(args.ninja_version)
118+
119+
if not args.quiet:
120+
msg = """\
121+
Complete! Now run:
122+
123+
git switch -c update-to-ninja-{release}
124+
git add -u ninja-upstream docs/index.rst README.rst tests/test_ninja.py docs/update_ninja_version.rst
125+
git commit -m "Update to Ninja {release}"
126+
gh pr create --fill --body "Created by update_ninja_version.py"
127+
"""
128+
print(textwrap.dedent(msg.format(release=args.ninja_version)))
220129

221130

222131
if __name__ == "__main__":

0 commit comments

Comments
 (0)