lean-runtime 2.0.2__tar.gz → 2.0.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/CHANGELOG.md +7 -0
- {lean_runtime-2.0.2/lean_runtime.egg-info → lean_runtime-2.0.3}/PKG-INFO +1 -1
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/bundles.py +54 -8
- {lean_runtime-2.0.2 → lean_runtime-2.0.3/lean_runtime.egg-info}/PKG-INFO +1 -1
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/pyproject.toml +1 -1
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_bundles.py +53 -1
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/LICENSE +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/MANIFEST.in +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/README.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/compatibility/README.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/compatibility/mathlib-4.32.2.json +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/compatibility/mathlib-4.32.2.toml +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/architecture.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/captures.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/case-study-v1.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/cli.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/development.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/environments.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/getting-started.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/index.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/local-projects.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/portable-copies.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/python-api.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/ready-programs.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/standalone-files.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/trust-and-limitations.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/docs/v1-precision.md +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/examples/mathlib.toml +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/__init__.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/__main__.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/_git.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/_paths.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/backends.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/cli.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/comparison.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/decisions.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/diagnostics.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/environments.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/errors.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/events.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/facade.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/frontmatter.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/health.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/lake.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/lockfiles.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/locking.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/matrix.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/models.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/oci.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/policies.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/profiling.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/programs.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/projects.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/publisher_verification.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/py.typed +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/references.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/resolver.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/run_cli.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/runtime.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/schema_resources.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/serialization.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/specs.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/store.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/timings.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/toolchains.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/verification.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime/wire.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime.egg-info/SOURCES.txt +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime.egg-info/dependency_links.txt +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime.egg-info/entry_points.txt +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime.egg-info/requires.txt +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/lean_runtime.egg-info/top_level.txt +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/mkdocs.yml +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/schemas/cleanup-v1.schema.json +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/schemas/comparison-v1.schema.json +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/schemas/execution-v1.schema.json +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/schemas/inspect-v1.schema.json +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/schemas/matrix-v1.schema.json +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/schemas/profile-v1.schema.json +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/schemas/verify-v1.schema.json +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/scripts/run_compatibility.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/scripts/run_v1_case_study.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/scripts/smoke_wheel.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/setup.cfg +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/conftest.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_backend.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_cli.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_diagnostics.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_environment_integration.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_events_health.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_facade.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_frontmatter.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_git.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_interactive.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_lockfiles.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_multifile.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_paths.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_prebuilt_policy.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_programs.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_projects.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_references.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_run_cli.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_runtime.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_schema_resources.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_schemas.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_signatures.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_specs.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_store.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_toolchains.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_v1_precision.py +0 -0
- {lean_runtime-2.0.2 → lean_runtime-2.0.3}/tests/test_verification_inventory.py +0 -0
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2.0.3
|
|
4
|
+
|
|
5
|
+
- Accept portable-copy symlinks whose normalized targets remain inside the
|
|
6
|
+
extracted copy, including common links such as `docs/README.md -> ../README.md`.
|
|
7
|
+
- Continue rejecting absolute or escaping symlink targets, duplicate archive
|
|
8
|
+
members, and later archive writes that traverse an extracted symlink.
|
|
9
|
+
|
|
3
10
|
## 2.0.2
|
|
4
11
|
|
|
5
12
|
- Remove staged environments safely when Git-for-Windows leaves source pack
|
|
@@ -203,11 +203,54 @@ def _require_media_type(descriptor: dict[str, Any], expected: str, label: str) -
|
|
|
203
203
|
|
|
204
204
|
def _safe_name(name: str) -> PurePosixPath:
|
|
205
205
|
path = PurePosixPath(name)
|
|
206
|
-
if
|
|
206
|
+
if (
|
|
207
|
+
not name
|
|
208
|
+
or path == PurePosixPath(".")
|
|
209
|
+
or path.is_absolute()
|
|
210
|
+
or ".." in path.parts
|
|
211
|
+
or "\\" in name
|
|
212
|
+
or "\x00" in name
|
|
213
|
+
):
|
|
207
214
|
raise EnvironmentError(f"unsafe bundle member path: {name!r}")
|
|
208
215
|
return path
|
|
209
216
|
|
|
210
217
|
|
|
218
|
+
def _internal_link_target(member: PurePosixPath, linkname: str) -> PurePosixPath:
|
|
219
|
+
link = PurePosixPath(linkname)
|
|
220
|
+
if not linkname or link.is_absolute() or "\\" in linkname or "\x00" in linkname:
|
|
221
|
+
raise EnvironmentError(f"unsafe bundle symlink: {member.as_posix()!r}")
|
|
222
|
+
parts: list[str] = []
|
|
223
|
+
for part in member.parent.joinpath(link).parts:
|
|
224
|
+
if part in {"", "."}:
|
|
225
|
+
continue
|
|
226
|
+
if part == "..":
|
|
227
|
+
if not parts:
|
|
228
|
+
raise EnvironmentError(f"unsafe bundle symlink: {member.as_posix()!r}")
|
|
229
|
+
parts.pop()
|
|
230
|
+
else:
|
|
231
|
+
parts.append(part)
|
|
232
|
+
return PurePosixPath(*parts) if parts else PurePosixPath(".")
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def _ensure_directories(destination: Path, relative: PurePosixPath) -> None:
|
|
236
|
+
current = destination
|
|
237
|
+
for part in relative.parts:
|
|
238
|
+
if part == ".":
|
|
239
|
+
continue
|
|
240
|
+
current = current / part
|
|
241
|
+
if current.is_symlink():
|
|
242
|
+
raise EnvironmentError(
|
|
243
|
+
f"bundle member traverses an extracted symlink: {relative.as_posix()!r}"
|
|
244
|
+
)
|
|
245
|
+
if current.exists():
|
|
246
|
+
if not current.is_dir():
|
|
247
|
+
raise EnvironmentError(
|
|
248
|
+
f"bundle member parent is not a directory: {relative.as_posix()!r}"
|
|
249
|
+
)
|
|
250
|
+
else:
|
|
251
|
+
current.mkdir()
|
|
252
|
+
|
|
253
|
+
|
|
211
254
|
def _packages_directory(lock: EnvironmentLock) -> PurePosixPath:
|
|
212
255
|
value = lock.manifest.get("packagesDir", ".lake/packages")
|
|
213
256
|
if not isinstance(value, str):
|
|
@@ -221,6 +264,8 @@ def _packages_directory(lock: EnvironmentLock) -> PurePosixPath:
|
|
|
221
264
|
def _extract_layer(data: bytes | Path, destination: Path) -> None:
|
|
222
265
|
total = 0
|
|
223
266
|
count = 0
|
|
267
|
+
if destination.is_symlink():
|
|
268
|
+
raise EnvironmentError("bundle extraction destination must not be a symlink")
|
|
224
269
|
destination.mkdir(parents=True, exist_ok=True)
|
|
225
270
|
try:
|
|
226
271
|
if isinstance(data, Path):
|
|
@@ -240,10 +285,12 @@ def _extract_layer(data: bytes | Path, destination: Path) -> None:
|
|
|
240
285
|
relative = _safe_name(member.name)
|
|
241
286
|
target = destination.joinpath(*relative.parts)
|
|
242
287
|
if member.isdir():
|
|
243
|
-
|
|
288
|
+
_ensure_directories(destination, relative)
|
|
244
289
|
target.chmod(member.mode & 0o777)
|
|
245
290
|
elif member.isfile():
|
|
246
|
-
|
|
291
|
+
_ensure_directories(destination, relative.parent)
|
|
292
|
+
if target.exists() or target.is_symlink():
|
|
293
|
+
raise EnvironmentError(f"duplicate bundle member: {member.name!r}")
|
|
247
294
|
source = archive.extractfile(member)
|
|
248
295
|
if source is None:
|
|
249
296
|
raise EnvironmentError(f"bundle member has no content: {member.name}")
|
|
@@ -251,11 +298,10 @@ def _extract_layer(data: bytes | Path, destination: Path) -> None:
|
|
|
251
298
|
shutil.copyfileobj(source, handle)
|
|
252
299
|
target.chmod(member.mode & 0o777)
|
|
253
300
|
elif member.issym():
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
if
|
|
257
|
-
raise EnvironmentError(f"
|
|
258
|
-
target.parent.mkdir(parents=True, exist_ok=True)
|
|
301
|
+
_internal_link_target(relative, member.linkname)
|
|
302
|
+
_ensure_directories(destination, relative.parent)
|
|
303
|
+
if target.exists() or target.is_symlink():
|
|
304
|
+
raise EnvironmentError(f"duplicate bundle member: {member.name!r}")
|
|
259
305
|
target.symlink_to(member.linkname)
|
|
260
306
|
else:
|
|
261
307
|
raise EnvironmentError(f"unsupported bundle member: {member.name!r}")
|
|
@@ -2,6 +2,7 @@ from __future__ import annotations
|
|
|
2
2
|
|
|
3
3
|
import hashlib
|
|
4
4
|
import http.server
|
|
5
|
+
import io
|
|
5
6
|
import json
|
|
6
7
|
import os
|
|
7
8
|
import shutil
|
|
@@ -15,7 +16,7 @@ from pathlib import Path
|
|
|
15
16
|
import pytest
|
|
16
17
|
|
|
17
18
|
from lean_runtime import EnvironmentError, EnvironmentLock, LockedPackage, Runtime
|
|
18
|
-
from lean_runtime.bundles import _oci_archive
|
|
19
|
+
from lean_runtime.bundles import _extract_layer, _oci_archive
|
|
19
20
|
from lean_runtime.environments import ENVIRONMENT_SCHEMA
|
|
20
21
|
from lean_runtime.oci import OCIEnvironmentPublisher, OCIRepository
|
|
21
22
|
from lean_runtime.store import environment_identity, platform_record, source_snapshot_digest
|
|
@@ -119,6 +120,57 @@ def _archive_entries(path: Path) -> dict[str, bytes]:
|
|
|
119
120
|
return result
|
|
120
121
|
|
|
121
122
|
|
|
123
|
+
def _layer(*members: tuple[str, str, bytes | str]) -> bytes:
|
|
124
|
+
output = io.BytesIO()
|
|
125
|
+
with tarfile.open(fileobj=output, mode="w:gz", format=tarfile.PAX_FORMAT) as archive:
|
|
126
|
+
for kind, name, value in members:
|
|
127
|
+
info = tarfile.TarInfo(name)
|
|
128
|
+
info.mode = 0o644
|
|
129
|
+
if kind == "file":
|
|
130
|
+
assert isinstance(value, bytes)
|
|
131
|
+
info.size = len(value)
|
|
132
|
+
archive.addfile(info, io.BytesIO(value))
|
|
133
|
+
else:
|
|
134
|
+
assert kind == "symlink" and isinstance(value, str)
|
|
135
|
+
info.type = tarfile.SYMTYPE
|
|
136
|
+
info.linkname = value
|
|
137
|
+
archive.addfile(info)
|
|
138
|
+
return output.getvalue()
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
@pytest.mark.skipif(os.name == "nt", reason="Windows runners may not permit symlink creation")
|
|
142
|
+
def test_layer_extract_accepts_internal_parent_symlink(tmp_path: Path) -> None:
|
|
143
|
+
layer = _layer(
|
|
144
|
+
("file", "README.md", b"Batteries\n"),
|
|
145
|
+
("symlink", "docs/README.md", "../README.md"),
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
_extract_layer(layer, tmp_path / "output")
|
|
149
|
+
|
|
150
|
+
link = tmp_path / "output" / "docs" / "README.md"
|
|
151
|
+
assert link.is_symlink()
|
|
152
|
+
assert link.read_text() == "Batteries\n"
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
@pytest.mark.skipif(os.name == "nt", reason="Windows runners may not permit symlink creation")
|
|
156
|
+
def test_layer_extract_rejects_symlink_outside_destination(tmp_path: Path) -> None:
|
|
157
|
+
layer = _layer(("symlink", "docs/README.md", "../../outside"))
|
|
158
|
+
|
|
159
|
+
with pytest.raises(EnvironmentError, match="unsafe bundle symlink"):
|
|
160
|
+
_extract_layer(layer, tmp_path / "output")
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
@pytest.mark.skipif(os.name == "nt", reason="Windows runners may not permit symlink creation")
|
|
164
|
+
def test_layer_extract_rejects_later_write_through_symlink(tmp_path: Path) -> None:
|
|
165
|
+
layer = _layer(
|
|
166
|
+
("symlink", "redirect", "inside"),
|
|
167
|
+
("file", "redirect/payload", b"must not be written"),
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
with pytest.raises(EnvironmentError, match="traverses an extracted symlink"):
|
|
171
|
+
_extract_layer(layer, tmp_path / "output")
|
|
172
|
+
|
|
173
|
+
|
|
122
174
|
def test_bundle_export_is_deterministic_and_imports_into_fresh_store(tmp_path: Path) -> None:
|
|
123
175
|
producer, environment_id, lock = _published_runtime(tmp_path / "producer")
|
|
124
176
|
first = tmp_path / "first.oci.tar.gz"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|