envrcctl 0.2.4__tar.gz → 0.2.6__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 (52) hide show
  1. {envrcctl-0.2.4 → envrcctl-0.2.6}/PKG-INFO +1 -1
  2. {envrcctl-0.2.4 → envrcctl-0.2.6}/pyproject.toml +1 -1
  3. {envrcctl-0.2.4 → envrcctl-0.2.6}/scripts/release_artifacts.py +103 -1
  4. {envrcctl-0.2.4 → envrcctl-0.2.6}/.gitignore +0 -0
  5. {envrcctl-0.2.4 → envrcctl-0.2.6}/LICENSE +0 -0
  6. {envrcctl-0.2.4 → envrcctl-0.2.6}/README.md +0 -0
  7. {envrcctl-0.2.4 → envrcctl-0.2.6}/completions/envrcctl.bash +0 -0
  8. {envrcctl-0.2.4 → envrcctl-0.2.6}/completions/envrcctl.fish +0 -0
  9. {envrcctl-0.2.4 → envrcctl-0.2.6}/completions/envrcctl.zsh +0 -0
  10. {envrcctl-0.2.4 → envrcctl-0.2.6}/scripts/build_macos_auth_helper.sh +0 -0
  11. {envrcctl-0.2.4 → envrcctl-0.2.6}/scripts/generate_completions.py +0 -0
  12. {envrcctl-0.2.4 → envrcctl-0.2.6}/scripts/macos/envrcctl-macos-auth.swift +0 -0
  13. {envrcctl-0.2.4 → envrcctl-0.2.6}/scripts/package_for_ship.sh +0 -0
  14. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/__init__.py +0 -0
  15. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/audit.py +0 -0
  16. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/auth.py +0 -0
  17. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/cli.py +0 -0
  18. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/command_runner.py +0 -0
  19. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/envrc.py +0 -0
  20. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/envrcctl-macos-auth.bak +0 -0
  21. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/errors.py +0 -0
  22. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/keychain.py +0 -0
  23. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/main.py +0 -0
  24. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/managed_block.py +0 -0
  25. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/secrets.py +0 -0
  26. {envrcctl-0.2.4 → envrcctl-0.2.6}/src/envrcctl/secretservice.py +0 -0
  27. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/__init__.py +0 -0
  28. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/conftest.py +0 -0
  29. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/helpers/__init__.py +0 -0
  30. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/helpers/cli_support.py +0 -0
  31. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_audit.py +0 -0
  32. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_audit_cli.py +0 -0
  33. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_auth.py +0 -0
  34. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli.py +0 -0
  35. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_doctor.py +0 -0
  36. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_errors.py +0 -0
  37. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_eval.py +0 -0
  38. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_exec.py +0 -0
  39. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_helpers.py +0 -0
  40. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_inject.py +0 -0
  41. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_migrate.py +0 -0
  42. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_secret_get.py +0 -0
  43. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_secret_list.py +0 -0
  44. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_cli_secret_set_unset.py +0 -0
  45. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_command_runner.py +0 -0
  46. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_envrc.py +0 -0
  47. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_keychain.py +0 -0
  48. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_main.py +0 -0
  49. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_managed_block.py +0 -0
  50. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_secrets.py +0 -0
  51. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_secretservice.py +0 -0
  52. {envrcctl-0.2.4 → envrcctl-0.2.6}/tests/test_smoke.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: envrcctl
3
- Version: 0.2.4
3
+ Version: 0.2.6
4
4
  Summary: Manage .envrc with managed blocks and OS-backed secrets.
5
5
  Project-URL: Homepage, https://github.com/rioriost/envrcctl
6
6
  Project-URL: Issues, https://github.com/rioriost/envrcctl/issues
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "envrcctl"
3
- version = "0.2.4"
3
+ version = "0.2.6"
4
4
  description = "Manage .envrc with managed blocks and OS-backed secrets."
5
5
  readme = { file = "README.md", content-type = "text/markdown" }
6
6
  license = "MIT"
@@ -3,6 +3,7 @@ from __future__ import annotations
3
3
 
4
4
  import argparse
5
5
  import hashlib
6
+ import re
6
7
  import shutil
7
8
  import subprocess
8
9
  import sys
@@ -40,6 +41,87 @@ def project_version(pyproject_path: Path) -> str:
40
41
  raise RuntimeError(f"Could not find project version in {pyproject_path}")
41
42
 
42
43
 
44
+ def project_dependencies(pyproject_path: Path) -> list[str]:
45
+ text = pyproject_path.read_text(encoding="utf-8")
46
+ match = re.search(r"(?ms)^\[project\]\n.*?^dependencies\s*=\s*\[(.*?)\]", text)
47
+ if not match:
48
+ return []
49
+
50
+ dependencies: list[str] = []
51
+ for raw_line in match.group(1).splitlines():
52
+ stripped = raw_line.strip().rstrip(",")
53
+ if not stripped:
54
+ continue
55
+ if stripped.startswith('"') and stripped.endswith('"'):
56
+ dependencies.append(stripped[1:-1])
57
+ elif stripped.startswith("'") and stripped.endswith("'"):
58
+ dependencies.append(stripped[1:-1])
59
+ return dependencies
60
+
61
+
62
+ def normalize_package_name(name: str) -> str:
63
+ return re.sub(r"[-_.]+", "-", name).lower()
64
+
65
+
66
+ def dependency_name(requirement: str) -> str:
67
+ base = re.split(r"[<>=!~;\[\]\s]", requirement, maxsplit=1)[0]
68
+ if not base:
69
+ raise RuntimeError(f"Could not parse dependency requirement: {requirement}")
70
+ return normalize_package_name(base)
71
+
72
+
73
+ def uv_lock_package_block(lock_text: str, package_name: str) -> str:
74
+ normalized = normalize_package_name(package_name)
75
+ current: list[str] = []
76
+ in_package = False
77
+
78
+ for line in lock_text.splitlines():
79
+ if line == "[[package]]":
80
+ if in_package:
81
+ block = "\n".join(current)
82
+ name_match = re.search(r'^name = "([^"]+)"$', block, re.MULTILINE)
83
+ if name_match and normalize_package_name(name_match.group(1)) == normalized:
84
+ return block
85
+ current = [line]
86
+ in_package = True
87
+ continue
88
+
89
+ if in_package:
90
+ current.append(line)
91
+
92
+ if in_package:
93
+ block = "\n".join(current)
94
+ name_match = re.search(r'^name = "([^"]+)"$', block, re.MULTILINE)
95
+ if name_match and normalize_package_name(name_match.group(1)) == normalized:
96
+ return block
97
+
98
+ raise RuntimeError(f"Package {package_name!r} not found in uv.lock")
99
+
100
+
101
+ def extract_sdist_url_and_sha(block: str, package_name: str) -> tuple[str, str]:
102
+ sdist_match = re.search(
103
+ r'sdist = \{ url = "([^"]+\.tar\.gz)", hash = "sha256:([0-9a-f]+)"',
104
+ block,
105
+ )
106
+ if sdist_match:
107
+ return sdist_match.group(1), sdist_match.group(2)
108
+
109
+ raise RuntimeError(f"Could not find sdist URL and sha256 for {package_name!r} in uv.lock")
110
+
111
+
112
+ def dependency_resource_specs(repo_root: Path) -> list[tuple[str, str, str]]:
113
+ lock_text = (repo_root / "uv.lock").read_text(encoding="utf-8")
114
+ specs: list[tuple[str, str, str]] = []
115
+
116
+ for requirement in project_dependencies(repo_root / "pyproject.toml"):
117
+ package_name = dependency_name(requirement)
118
+ block = uv_lock_package_block(lock_text, package_name)
119
+ url, sha256 = extract_sdist_url_and_sha(block, package_name)
120
+ specs.append((package_name, url, sha256))
121
+
122
+ return specs
123
+
124
+
43
125
  def require_command(name: str) -> None:
44
126
  if shutil.which(name) is None:
45
127
  raise RuntimeError(f"Required command not found in PATH: {name}")
@@ -141,11 +223,26 @@ def formula_content(
141
223
  helper_sha256: str,
142
224
  homepage: str,
143
225
  license_name: str,
226
+ dependency_resources: list[tuple[str, str, str]],
144
227
  ) -> str:
145
228
  release_base = f"{homepage}/releases/download/{version}"
146
229
  source_url = f"{release_base}/envrcctl-{version}.tar.gz"
147
230
  helper_url = f"{release_base}/envrcctl-macos-auth-{version}-arm64.tar.gz"
148
231
 
232
+ resource_blocks = []
233
+ install_lines = []
234
+ for package_name, package_url, package_sha256 in dependency_resources:
235
+ resource_blocks.append(
236
+ f""" resource "{package_name}" do
237
+ url "{package_url}"
238
+ sha256 "{package_sha256}"
239
+ end"""
240
+ )
241
+ install_lines.append(f' venv.pip_install resource("{package_name}")')
242
+
243
+ resources_section = "\n\n".join(resource_blocks)
244
+ install_resources = "\n".join(install_lines)
245
+
149
246
  return f"""class Envrcctl < Formula
150
247
  include Language::Python::Virtualenv
151
248
 
@@ -157,6 +254,8 @@ def formula_content(
157
254
 
158
255
  depends_on "python@3.12"
159
256
 
257
+ {resources_section}
258
+
160
259
  on_macos do
161
260
  on_arm do
162
261
  resource "envrcctl-macos-auth-arm64" do
@@ -168,6 +267,7 @@ def formula_content(
168
267
 
169
268
  def install
170
269
  venv = virtualenv_create(libexec, "python3.12")
270
+ {install_resources}
171
271
  venv.pip_install buildpath
172
272
 
173
273
  bin.install_symlink libexec/"bin/envrcctl"
@@ -185,7 +285,7 @@ def formula_content(
185
285
 
186
286
  test do
187
287
  assert_predicate bin/"envrcctl", :exist?
188
- assert_match version.to_s, shell_output("#{bin}/envrcctl --version")
288
+ assert_match version.to_s, shell_output("#{{bin}}/envrcctl --version")
189
289
  if OS.mac? && Hardware::CPU.arm?
190
290
  assert_predicate bin/"envrcctl-macos-auth", :exist?
191
291
  end
@@ -255,6 +355,7 @@ def main() -> int:
255
355
 
256
356
  source_sha256 = sha256_file(sdist_path)
257
357
  helper_sha256 = sha256_file(helper_archive)
358
+ dependency_resources = dependency_resource_specs(repo_root)
258
359
 
259
360
  formula_path = write_formula(
260
361
  repo_root,
@@ -264,6 +365,7 @@ def main() -> int:
264
365
  helper_sha256=helper_sha256,
265
366
  homepage=args.homepage,
266
367
  license_name=args.license_name,
368
+ dependency_resources=dependency_resources,
267
369
  ),
268
370
  args.formula_dir,
269
371
  )
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