envrcctl 0.2.5__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.5 → envrcctl-0.2.6}/PKG-INFO +1 -1
  2. {envrcctl-0.2.5 → envrcctl-0.2.6}/pyproject.toml +1 -1
  3. {envrcctl-0.2.5 → envrcctl-0.2.6}/scripts/release_artifacts.py +101 -5
  4. {envrcctl-0.2.5 → envrcctl-0.2.6}/.gitignore +0 -0
  5. {envrcctl-0.2.5 → envrcctl-0.2.6}/LICENSE +0 -0
  6. {envrcctl-0.2.5 → envrcctl-0.2.6}/README.md +0 -0
  7. {envrcctl-0.2.5 → envrcctl-0.2.6}/completions/envrcctl.bash +0 -0
  8. {envrcctl-0.2.5 → envrcctl-0.2.6}/completions/envrcctl.fish +0 -0
  9. {envrcctl-0.2.5 → envrcctl-0.2.6}/completions/envrcctl.zsh +0 -0
  10. {envrcctl-0.2.5 → envrcctl-0.2.6}/scripts/build_macos_auth_helper.sh +0 -0
  11. {envrcctl-0.2.5 → envrcctl-0.2.6}/scripts/generate_completions.py +0 -0
  12. {envrcctl-0.2.5 → envrcctl-0.2.6}/scripts/macos/envrcctl-macos-auth.swift +0 -0
  13. {envrcctl-0.2.5 → envrcctl-0.2.6}/scripts/package_for_ship.sh +0 -0
  14. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/__init__.py +0 -0
  15. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/audit.py +0 -0
  16. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/auth.py +0 -0
  17. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/cli.py +0 -0
  18. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/command_runner.py +0 -0
  19. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/envrc.py +0 -0
  20. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/envrcctl-macos-auth.bak +0 -0
  21. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/errors.py +0 -0
  22. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/keychain.py +0 -0
  23. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/main.py +0 -0
  24. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/managed_block.py +0 -0
  25. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/secrets.py +0 -0
  26. {envrcctl-0.2.5 → envrcctl-0.2.6}/src/envrcctl/secretservice.py +0 -0
  27. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/__init__.py +0 -0
  28. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/conftest.py +0 -0
  29. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/helpers/__init__.py +0 -0
  30. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/helpers/cli_support.py +0 -0
  31. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_audit.py +0 -0
  32. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_audit_cli.py +0 -0
  33. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_auth.py +0 -0
  34. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_cli.py +0 -0
  35. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_cli_doctor.py +0 -0
  36. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_cli_errors.py +0 -0
  37. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_cli_eval.py +0 -0
  38. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_cli_exec.py +0 -0
  39. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_cli_helpers.py +0 -0
  40. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_cli_inject.py +0 -0
  41. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_cli_migrate.py +0 -0
  42. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_cli_secret_get.py +0 -0
  43. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_cli_secret_list.py +0 -0
  44. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_cli_secret_set_unset.py +0 -0
  45. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_command_runner.py +0 -0
  46. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_envrc.py +0 -0
  47. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_keychain.py +0 -0
  48. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_main.py +0 -0
  49. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_managed_block.py +0 -0
  50. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_secrets.py +0 -0
  51. {envrcctl-0.2.5 → envrcctl-0.2.6}/tests/test_secretservice.py +0 -0
  52. {envrcctl-0.2.5 → 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.5
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.5"
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,10 +254,7 @@ def formula_content(
157
254
 
158
255
  depends_on "python@3.12"
159
256
 
160
- resource "typer" do
161
- url "https://files.pythonhosted.org/packages/source/t/typer/typer-0.24.1.tar.gz"
162
- sha256 "8bf4e81499611d3161106e998fe4d624a83abf8bfda3b99898b4498d0c2f0976"
163
- end
257
+ {resources_section}
164
258
 
165
259
  on_macos do
166
260
  on_arm do
@@ -173,7 +267,7 @@ def formula_content(
173
267
 
174
268
  def install
175
269
  venv = virtualenv_create(libexec, "python3.12")
176
- venv.pip_install resource("typer")
270
+ {install_resources}
177
271
  venv.pip_install buildpath
178
272
 
179
273
  bin.install_symlink libexec/"bin/envrcctl"
@@ -261,6 +355,7 @@ def main() -> int:
261
355
 
262
356
  source_sha256 = sha256_file(sdist_path)
263
357
  helper_sha256 = sha256_file(helper_archive)
358
+ dependency_resources = dependency_resource_specs(repo_root)
264
359
 
265
360
  formula_path = write_formula(
266
361
  repo_root,
@@ -270,6 +365,7 @@ def main() -> int:
270
365
  helper_sha256=helper_sha256,
271
366
  homepage=args.homepage,
272
367
  license_name=args.license_name,
368
+ dependency_resources=dependency_resources,
273
369
  ),
274
370
  args.formula_dir,
275
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