Skip to content
Bitcoin Roots

v31.1-roots.1 · Commit 17: [PATCH 17/17] fix(release): preserve notice bytes and integrate nightly fixes

ci/test/test_prepare_release.py

Before: ci/test/test_prepare_release.py · After: ci/test/test_prepare_release.py

File metadata
index eefc00275c41480c3e1b45768881746ec3d59b15..477dff6f9a648b9dc018d0c18889fb7e0bd9c9f4 100755

Download original patch · Release notes

Diff rows 1–53 of 53. Line numbers refer to the original before/after files.

+ Added− RemovedUnmarked lines are context.

Scroll the code area horizontally to read long lines. The two line-number columns refer to before and after.

ci/test/test_prepare_release.py CHANGED
@@ -107,6 +107,53 @@ class PrepareReleaseTest(unittest.TestCase):
107
107
  subprocess.run(["python3", ARCHIVE_TOOL, "validate", archive, root.name,
108
108
  "--copying", ROOT / "COPYING"], check=True)
109
109
 
110
+ def test_autocrlf_checkout_preserves_canonical_copying_through_packaging(self):
111
+ with tempfile.TemporaryDirectory() as temporary_dir:
112
+ work = Path(temporary_dir)
113
+ checkout = work / "checkout"
114
+ checkout.mkdir()
115
+ subprocess.run(["git", "init", "--quiet", checkout], check=True)
116
+ environment = {**os.environ, "GIT_CONFIG_NOSYSTEM": "1", "GIT_CONFIG_GLOBAL": os.devnull}
117
+ def git(*args):
118
+ return subprocess.run(["git", "-c", "core.autocrlf=true", *args], cwd=checkout,
119
+ env=environment, capture_output=True, check=True)
120
+
121
+ canonical = subprocess.run(["git", "show", "HEAD:COPYING"], cwd=ROOT,
122
+ capture_output=True, check=True).stdout
123
+ (checkout / "COPYING").write_bytes(canonical)
124
+ (checkout / ".gitattributes").write_bytes((ROOT / ".gitattributes").read_bytes())
125
+ tool = checkout / "ci/release/archive.py"
126
+ tool.parent.mkdir(parents=True)
127
+ shutil.copyfile(ARCHIVE_TOOL, tool)
128
+ git("add", "COPYING", ".gitattributes", "ci/release/archive.py")
129
+ git("-c", "user.name=Release fixture", "-c", "user.email=fixture@example.invalid",
130
+ "commit", "--quiet", "-m", "Release checkout fixture")
131
+ (checkout / "COPYING").unlink()
132
+ git("checkout", "HEAD", "--", "COPYING")
133
+ self.assertEqual((checkout / "COPYING").read_bytes(), canonical)
134
+
135
+ root = work / "bitcoin-roots-31.1-roots.1"
136
+ root.mkdir()
137
+ subprocess.run(["python3", tool, "stage-copying", root], check=True)
138
+ self.assertEqual((root / "COPYING").read_bytes(), canonical)
139
+ archive = work / "bitcoin-roots-windows-x86_64.zip"
140
+ with zipfile.ZipFile(archive, mode="w") as package:
141
+ package.write(root / "COPYING", f"{root.name}/COPYING")
142
+ package.writestr(f"{root.name}/bin/bitcoind.exe", b"binary fixture")
143
+ canonical_file = work / "canonical-COPYING"
144
+ canonical_file.write_bytes(canonical)
145
+ subprocess.run(["python3", ARCHIVE_TOOL, "validate", archive, root.name,
146
+ "--copying", canonical_file], check=True)
147
+
148
+ # Keep byte-exact integrity: a CRLF copy must still be rejected.
149
+ with zipfile.ZipFile(archive, mode="w") as package:
150
+ package.writestr(f"{root.name}/COPYING", canonical.replace(b"\n", b"\r\n"))
151
+ package.writestr(f"{root.name}/bin/bitcoind.exe", b"binary fixture")
152
+ result = subprocess.run(["python3", ARCHIVE_TOOL, "validate", archive, root.name,
153
+ "--copying", canonical_file], capture_output=True, text=True)
154
+ self.assertNotEqual(result.returncode, 0)
155
+ self.assertIn("COPYING differs from canonical notice", result.stderr)
156
+
110
157
  def test_actual_unix_workflow_stages_copying_without_dependency_index_and_prepares(self):
111
158
  lines = (ROOT / ".github/workflows/release.yml").read_text().splitlines()
112
159
  def packaging_block(name):