sentry-devenv 1.16.0__tar.gz → 1.17.0__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.
Files changed (82) hide show
  1. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/PKG-INFO +3 -3
  2. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/README.md +1 -1
  3. sentry_devenv-1.17.0/devenv/lib/docker.py +160 -0
  4. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/pyproject.toml +1 -1
  5. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/sentry_devenv.egg-info/PKG-INFO +3 -3
  6. sentry_devenv-1.16.0/devenv/lib/docker.py +0 -105
  7. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/ci/integration/repo/devenv/sync.py +0 -0
  8. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/__init__.py +0 -0
  9. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/__main__.py +0 -0
  10. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/bootstrap.py +0 -0
  11. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/checks/__init__.py +0 -0
  12. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/checks/credsStore.py +0 -0
  13. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/checks/test.py +0 -0
  14. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/colima.py +0 -0
  15. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/constants.py +0 -0
  16. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/doctor.py +0 -0
  17. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/fetch.py +0 -0
  18. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/__init__.py +0 -0
  19. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/archive.py +0 -0
  20. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/brew.py +0 -0
  21. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/colima.py +0 -0
  22. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/config.py +0 -0
  23. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/context.py +0 -0
  24. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/direnv.py +0 -0
  25. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/fs.py +0 -0
  26. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/gcloud.py +0 -0
  27. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/github.py +0 -0
  28. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/limactl.py +0 -0
  29. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/modules.py +0 -0
  30. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/node.py +0 -0
  31. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/proc.py +0 -0
  32. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/repository.py +0 -0
  33. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/rosetta.py +0 -0
  34. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/tenv.py +0 -0
  35. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib/venv.py +0 -0
  36. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib_check/__init__.py +0 -0
  37. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib_check/brew.py +0 -0
  38. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/lib_check/types.py +0 -0
  39. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/main.py +0 -0
  40. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/pin_gha.py +0 -0
  41. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/py.typed +0 -0
  42. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/pythons.py +0 -0
  43. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/sync.py +0 -0
  44. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/devenv/update.py +0 -0
  45. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/sentry_devenv.egg-info/SOURCES.txt +0 -0
  46. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/sentry_devenv.egg-info/dependency_links.txt +0 -0
  47. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/sentry_devenv.egg-info/entry_points.txt +0 -0
  48. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/sentry_devenv.egg-info/requires.txt +0 -0
  49. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/sentry_devenv.egg-info/top_level.txt +0 -0
  50. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/setup.cfg +0 -0
  51. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/__init__.py +0 -0
  52. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/checks/__init__.py +0 -0
  53. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/checks/test_credStore.py +0 -0
  54. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/conftest.py +0 -0
  55. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/__init__.py +0 -0
  56. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/devenv/checks/bad_check.py +0 -0
  57. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/devenv/checks/bad_fix.py +0 -0
  58. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/devenv/checks/broken_check.py +0 -0
  59. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/devenv/checks/broken_fix.py +0 -0
  60. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/devenv/checks/failing_check.py +0 -0
  61. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/devenv/checks/failing_check_with_msg.py +0 -0
  62. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/devenv/checks/no_check.py +0 -0
  63. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/devenv/checks/no_name.py +0 -0
  64. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/devenv/checks/no_tags.py +0 -0
  65. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/devenv/checks/passing_check.py +0 -0
  66. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/test_attempt_fix.py +0 -0
  67. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/test_filter_failing_checks.py +0 -0
  68. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/test_load_checks.py +0 -0
  69. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/test_prompt_for_fix.py +0 -0
  70. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/doctor/test_run_checks.py +0 -0
  71. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/lib/test_archive.py +0 -0
  72. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/lib/test_brew.py +0 -0
  73. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/lib/test_direnv.py +0 -0
  74. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/lib/test_fs.py +0 -0
  75. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/lib/test_github.py +0 -0
  76. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/lib/test_proc.py +0 -0
  77. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/lib/test_repository.py +0 -0
  78. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/lib/test_venv.py +0 -0
  79. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/test_main.py +0 -0
  80. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/test_pythons.py +0 -0
  81. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/test_sync.py +0 -0
  82. {sentry_devenv-1.16.0 → sentry_devenv-1.17.0}/tests/utils.py +0 -0
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: sentry_devenv
3
- Version: 1.16.0
3
+ Version: 1.17.0
4
4
  Summary: Utilities for setting up a Sentry development environment
5
5
  Author-email: Joshua Li <joshua.li@sentry.io>, Ian Woodard <ian.woodard@sentry.io>, Buck Evan <buck.evan@sentry.io>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -16,7 +16,7 @@ Requires-Dist: sentry-sdk
16
16
  managing dev environments since '24
17
17
 
18
18
  `devenv` is an extensible execution framework and library for authoring
19
- a simple set of high level commands - bootstrap, sync, doctor, nuke - that
19
+ a simple set of high level commands - bootstrap, fetch, sync, doctor - that
20
20
  manage a repository's dev environment.
21
21
 
22
22
  ## prerequisites
@@ -3,7 +3,7 @@
3
3
  managing dev environments since '24
4
4
 
5
5
  `devenv` is an extensible execution framework and library for authoring
6
- a simple set of high level commands - bootstrap, sync, doctor, nuke - that
6
+ a simple set of high level commands - bootstrap, fetch, sync, doctor - that
7
7
  manage a repository's dev environment.
8
8
 
9
9
  ## prerequisites
@@ -0,0 +1,160 @@
1
+ from __future__ import annotations
2
+
3
+ import os
4
+ import shutil
5
+ import socket
6
+ import subprocess
7
+ import tempfile
8
+ from threading import Thread
9
+
10
+ from devenv.constants import home
11
+ from devenv.constants import root
12
+ from devenv.constants import SYSTEM_MACHINE
13
+ from devenv.lib import archive
14
+ from devenv.lib import proc
15
+
16
+
17
+ def _accept_and_close(sock: socket.socket) -> None:
18
+ sock.listen()
19
+ conn, addr = sock.accept()
20
+ conn.close()
21
+
22
+
23
+ def check_docker_to_host_connectivity(timeout: int = 3) -> bool:
24
+ sock = socket.socket()
25
+ sock.bind(("127.0.0.1", 0))
26
+ port = sock.getsockname()[1]
27
+
28
+ listener = Thread(target=_accept_and_close, args=(sock,))
29
+ listener.start()
30
+
31
+ rc = subprocess.call(
32
+ (
33
+ "docker",
34
+ "run",
35
+ "--rm",
36
+ "--add-host=host.docker.internal:host-gateway",
37
+ "busybox:1.36.1-musl",
38
+ "/bin/sh",
39
+ "-c",
40
+ f"/bin/echo hi | /bin/nc -w {timeout} host.docker.internal {port}",
41
+ )
42
+ )
43
+
44
+ if rc != 0:
45
+ # easiest way to terminate the socket server
46
+ # (so the thread doesn't indefinitely hang)
47
+ with socket.socket() as s:
48
+ s.connect(("127.0.0.1", port))
49
+ s.send(b"die")
50
+
51
+ listener.join()
52
+ return False
53
+
54
+ listener.join()
55
+ return True
56
+
57
+
58
+ def uninstall(binroot: str) -> None:
59
+ for fp in (
60
+ f"{binroot}/docker",
61
+ f"{home}/.docker/cli-plugins/docker-buildx",
62
+ ):
63
+ try:
64
+ os.remove(fp)
65
+ except FileNotFoundError:
66
+ # it's better to do this than to guard with
67
+ # os.path.exists(fp) because if it's an invalid or circular
68
+ # symlink the result'll be False!
69
+ pass
70
+
71
+
72
+ def _install(url: str, sha256: str, into: str) -> None:
73
+ os.makedirs(into, exist_ok=True)
74
+ with tempfile.TemporaryDirectory(dir=into) as tmpd:
75
+ archive_file = archive.download(url, sha256, dest=f"{tmpd}/download")
76
+ archive.unpack_strip_n(archive_file, tmpd, n=1)
77
+
78
+ # the archive was atomically placed into tmpd so
79
+ # these are on the same fs and can be atomically moved too
80
+ os.replace(f"{tmpd}/docker", f"{into}/docker")
81
+
82
+
83
+ def _install_buildx(url: str, sha256: str, into: str) -> None:
84
+ archive.download(url, sha256, dest=f"{into}/docker-buildx")
85
+ os.chmod(f"{into}/docker-buildx", 0o775)
86
+
87
+
88
+ def _check_buildx(binroot: str, expected_version: str) -> bool:
89
+ try:
90
+ stdout = proc.run(
91
+ (f"{binroot}/docker", "buildx", "version"), stdout=True
92
+ )
93
+ except RuntimeError as e:
94
+ print(f"failed getting buildx version:\n\n{e}")
95
+ return False
96
+
97
+ # github.com/docker/buildx v0.22.0 Homebrew
98
+ installed_version = stdout.strip().split()[1]
99
+
100
+ if installed_version == expected_version:
101
+ return True
102
+
103
+ print(
104
+ f"installed docker-buildx {installed_version} is outdated! expected: {expected_version}"
105
+ )
106
+ return False
107
+
108
+
109
+ def install_global() -> None:
110
+ version = "27.3.1"
111
+ cfg = {
112
+ "darwin_x86_64": f"https://download.docker.com/mac/static/stable/x86_64/docker-{version}.tgz",
113
+ "darwin_x86_64_sha256": "1b621d4c9a57ff361811cf29754aafb0c28bc113c70011927af8d73c2c162186",
114
+ "darwin_arm64": f"https://download.docker.com/mac/static/stable/aarch64/docker-{version}.tgz",
115
+ "darwin_arm64_sha256": "9dae125282116146b06eb777c2125ddda6c0468c0b9ad6c72a82edbc6783a77b",
116
+ "linux_x86_64": f"https://download.docker.com/linux/static/stable/x86_64/docker-{version}.tgz",
117
+ "linux_x86_64_sha256": "9b4f6fe406e50f9085ee474c451e2bb5adb119a03591f467922d3b4e2ddf31d3",
118
+ }
119
+
120
+ version_buildx = "v0.22.0"
121
+ cfg_buildx = {
122
+ "darwin_x86_64": f"https://github.com/docker/buildx/releases/download/{version_buildx}/buildx-{version_buildx}.darwin-amd64",
123
+ "darwin_x86_64_sha256": "5221ad6b8acd2283f8fbbeebc79ae4b657e83519ca1c1e4cfbb9405230b3d933",
124
+ "darwin_arm64": f"https://github.com/docker/buildx/releases/download/{version_buildx}/buildx-{version_buildx}.darwin-arm64",
125
+ "darwin_arm64_sha256": "5898c338abb1f673107bc087997dc3cb63b4ea66d304ce4223472f57bd8d616e",
126
+ "linux_x86_64": f"https://github.com/docker/buildx/releases/download/{version_buildx}/buildx-{version_buildx}.linux-amd64",
127
+ "linux_x86_64_sha256": "805195386fba0cea5a1487cf0d47da82a145ea0a792bd3fb477583e2dbcdcc2f",
128
+ }
129
+
130
+ binroot = f"{root}/bin"
131
+
132
+ if shutil.which("docker", path=binroot) == f"{binroot}/docker":
133
+ stdout = proc.run((f"{binroot}/docker", "--version"), stdout=True)
134
+ installed_version = stdout.strip().split()[2][:-1]
135
+ if version != installed_version:
136
+ print(f"installed docker {installed_version} is outdated!")
137
+ print(f"installing docker (cli, not desktop) {version}...")
138
+ uninstall(binroot)
139
+ _install(
140
+ cfg[SYSTEM_MACHINE], cfg[f"{SYSTEM_MACHINE}_sha256"], binroot
141
+ )
142
+ else:
143
+ _install(cfg[SYSTEM_MACHINE], cfg[f"{SYSTEM_MACHINE}_sha256"], binroot)
144
+
145
+ stdout = proc.run((f"{binroot}/docker", "--version"), stdout=True)
146
+ if f"Docker version {version}" not in stdout:
147
+ raise SystemExit(f"Failed to install docker {version}!\n\n{stdout}")
148
+
149
+ if not _check_buildx(binroot, version_buildx):
150
+ print(f"installing docker buildx {version_buildx}...")
151
+ _install_buildx(
152
+ cfg_buildx[SYSTEM_MACHINE],
153
+ cfg_buildx[f"{SYSTEM_MACHINE}_sha256"],
154
+ f"{home}/.docker/cli-plugins",
155
+ )
156
+
157
+ if not _check_buildx(binroot, version_buildx):
158
+ raise SystemExit(
159
+ f"Failed to install docker buildx {version_buildx}!"
160
+ )
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "sentry_devenv"
7
- version = "1.16.0"
7
+ version = "1.17.0"
8
8
  authors = [
9
9
  { name="Joshua Li", email="joshua.li@sentry.io" },
10
10
  { name="Ian Woodard", email="ian.woodard@sentry.io" },
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.2
1
+ Metadata-Version: 2.4
2
2
  Name: sentry_devenv
3
- Version: 1.16.0
3
+ Version: 1.17.0
4
4
  Summary: Utilities for setting up a Sentry development environment
5
5
  Author-email: Joshua Li <joshua.li@sentry.io>, Ian Woodard <ian.woodard@sentry.io>, Buck Evan <buck.evan@sentry.io>
6
6
  Classifier: Programming Language :: Python :: 3
@@ -16,7 +16,7 @@ Requires-Dist: sentry-sdk
16
16
  managing dev environments since '24
17
17
 
18
18
  `devenv` is an extensible execution framework and library for authoring
19
- a simple set of high level commands - bootstrap, sync, doctor, nuke - that
19
+ a simple set of high level commands - bootstrap, fetch, sync, doctor - that
20
20
  manage a repository's dev environment.
21
21
 
22
22
  ## prerequisites
@@ -1,105 +0,0 @@
1
- from __future__ import annotations
2
-
3
- import os
4
- import shutil
5
- import socket
6
- import subprocess
7
- import tempfile
8
- from threading import Thread
9
-
10
- from devenv.constants import root
11
- from devenv.constants import SYSTEM_MACHINE
12
- from devenv.lib import archive
13
- from devenv.lib import proc
14
-
15
-
16
- def _accept_and_close(sock: socket.socket) -> None:
17
- sock.listen()
18
- conn, addr = sock.accept()
19
- conn.close()
20
-
21
-
22
- def check_docker_to_host_connectivity(timeout: int = 3) -> bool:
23
- sock = socket.socket()
24
- sock.bind(("127.0.0.1", 0))
25
- port = sock.getsockname()[1]
26
-
27
- listener = Thread(target=_accept_and_close, args=(sock,))
28
- listener.start()
29
-
30
- rc = subprocess.call(
31
- (
32
- "docker",
33
- "run",
34
- "--rm",
35
- "--add-host=host.docker.internal:host-gateway",
36
- "busybox:1.36.1-musl",
37
- "/bin/sh",
38
- "-c",
39
- f"/bin/echo hi | /bin/nc -w {timeout} host.docker.internal {port}",
40
- )
41
- )
42
-
43
- if rc != 0:
44
- # easiest way to terminate the socket server
45
- # (so the thread doesn't indefinitely hang)
46
- with socket.socket() as s:
47
- s.connect(("127.0.0.1", port))
48
- s.send(b"die")
49
-
50
- listener.join()
51
- return False
52
-
53
- listener.join()
54
- return True
55
-
56
-
57
- def uninstall(binroot: str) -> None:
58
- for fp in (f"{binroot}/docker",):
59
- try:
60
- os.remove(fp)
61
- except FileNotFoundError:
62
- # it's better to do this than to guard with
63
- # os.path.exists(fp) because if it's an invalid or circular
64
- # symlink the result'll be False!
65
- pass
66
-
67
-
68
- def _install(url: str, sha256: str, into: str) -> None:
69
- os.makedirs(into, exist_ok=True)
70
- with tempfile.TemporaryDirectory(dir=into) as tmpd:
71
- archive_file = archive.download(url, sha256, dest=f"{tmpd}/download")
72
- archive.unpack_strip_n(archive_file, tmpd, n=1)
73
-
74
- # the archive was atomically placed into tmpd so
75
- # these are on the same fs and can be atomically moved too
76
- os.replace(f"{tmpd}/docker", f"{into}/docker")
77
-
78
-
79
- def install_global() -> None:
80
- version = "27.3.1"
81
- cfg = {
82
- "darwin_x86_64": "https://download.docker.com/mac/static/stable/x86_64/docker-27.3.1.tgz",
83
- "darwin_x86_64_sha256": "1b621d4c9a57ff361811cf29754aafb0c28bc113c70011927af8d73c2c162186",
84
- "darwin_arm64": "https://download.docker.com/mac/static/stable/aarch64/docker-27.3.1.tgz",
85
- "darwin_arm64_sha256": "9dae125282116146b06eb777c2125ddda6c0468c0b9ad6c72a82edbc6783a77b",
86
- "linux_x86_64": "https://download.docker.com/linux/static/stable/x86_64/docker-27.3.1.tgz",
87
- "linux_x86_64_sha256": "9b4f6fe406e50f9085ee474c451e2bb5adb119a03591f467922d3b4e2ddf31d3",
88
- }
89
-
90
- binroot = f"{root}/bin"
91
-
92
- if shutil.which("docker", path=binroot) == f"{binroot}/docker":
93
- stdout = proc.run((f"{binroot}/docker", "--version"), stdout=True)
94
- installed_version = stdout.strip().split()[2][:-1]
95
- if version == installed_version:
96
- return
97
- print(f"installed docker {installed_version} is outdated!")
98
-
99
- print(f"installing docker (cli, not desktop) {version}...")
100
- uninstall(binroot)
101
- _install(cfg[SYSTEM_MACHINE], cfg[f"{SYSTEM_MACHINE}_sha256"], binroot)
102
-
103
- stdout = proc.run((f"{binroot}/docker", "--version"), stdout=True)
104
- if f"Docker version {version}" not in stdout:
105
- raise SystemExit(f"Failed to install docker {version}! Found: {stdout}")
File without changes