code-aide 1.1.0__tar.gz → 1.2.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 (36) hide show
  1. {code_aide-1.1.0 → code_aide-1.2.0}/PKG-INFO +1 -1
  2. code_aide-1.2.0/TODO.md +70 -0
  3. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/__init__.py +1 -1
  4. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/commands_actions.py +2 -2
  5. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/detection.py +3 -0
  6. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/entry.py +1 -1
  7. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/install.py +7 -2
  8. {code_aide-1.1.0 → code_aide-1.2.0}/tests/test_commands_actions.py +3 -3
  9. {code_aide-1.1.0 → code_aide-1.2.0}/tests/test_install.py +54 -0
  10. code_aide-1.1.0/TODO.md +0 -39
  11. {code_aide-1.1.0 → code_aide-1.2.0}/.github/workflows/ci.yml +0 -0
  12. {code_aide-1.1.0 → code_aide-1.2.0}/.github/workflows/publish.yml +0 -0
  13. {code_aide-1.1.0 → code_aide-1.2.0}/.gitignore +0 -0
  14. {code_aide-1.1.0 → code_aide-1.2.0}/AGENTS.md +0 -0
  15. {code_aide-1.1.0 → code_aide-1.2.0}/CLAUDE.md +0 -0
  16. {code_aide-1.1.0 → code_aide-1.2.0}/LICENSE +0 -0
  17. {code_aide-1.1.0 → code_aide-1.2.0}/README.md +0 -0
  18. {code_aide-1.1.0 → code_aide-1.2.0}/pyproject.toml +0 -0
  19. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/__main__.py +0 -0
  20. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/commands_tools.py +0 -0
  21. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/config.py +0 -0
  22. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/console.py +0 -0
  23. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/constants.py +0 -0
  24. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/data/tools.json +0 -0
  25. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/operations.py +0 -0
  26. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/prereqs.py +0 -0
  27. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/status.py +0 -0
  28. {code_aide-1.1.0 → code_aide-1.2.0}/src/code_aide/versions.py +0 -0
  29. {code_aide-1.1.0 → code_aide-1.2.0}/tests/test_commands_tools.py +0 -0
  30. {code_aide-1.1.0 → code_aide-1.2.0}/tests/test_config.py +0 -0
  31. {code_aide-1.1.0 → code_aide-1.2.0}/tests/test_console.py +0 -0
  32. {code_aide-1.1.0 → code_aide-1.2.0}/tests/test_constants.py +0 -0
  33. {code_aide-1.1.0 → code_aide-1.2.0}/tests/test_detection.py +0 -0
  34. {code_aide-1.1.0 → code_aide-1.2.0}/tests/test_operations.py +0 -0
  35. {code_aide-1.1.0 → code_aide-1.2.0}/tests/test_status.py +0 -0
  36. {code_aide-1.1.0 → code_aide-1.2.0}/tests/test_versions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: code-aide
3
- Version: 1.1.0
3
+ Version: 1.2.0
4
4
  Summary: Manage AI coding CLI tools (Claude, Copilot, Cursor, Gemini, Amp, Codex)
5
5
  Project-URL: Homepage, https://github.com/dajobe/code-aide
6
6
  Project-URL: Repository, https://github.com/dajobe/code-aide
@@ -0,0 +1,70 @@
1
+ # TODO
2
+
3
+ Keep the project focused on managing AI coding CLI tools (install, upgrade,
4
+ remove, status, and version metadata).
5
+
6
+ ## Bugs
7
+
8
+ - [x] Standardize `--dryrun` flag: `update-versions` uses `--dry-run` but
9
+ `install` uses `--dryrun`. Change `update-versions` to `--dryrun`.
10
+ - [x] Add missing `success()` message for direct-download installs in non-dryrun
11
+ mode (`install.py`, `install_tool()`).
12
+ - [x] Replace PID-based temp directory naming with `tempfile.mkdtemp()` in
13
+ `install.py` `install_direct_download()`.
14
+ - [x] Guard `package.split("/", 1)` in `detection.py`
15
+ `get_system_package_info()` against missing `/` in subprocess output.
16
+
17
+ ## Reliability and Correctness
18
+
19
+ - [ ] Handle missing `node` cleanly during prerequisite checks
20
+ (`FileNotFoundError` path in Node version probing).
21
+ - [ ] Read tool version output from both stdout and stderr so status does not
22
+ miss installed versions.
23
+ - [ ] Make version cache writes atomic (write temp file + rename) to avoid
24
+ partial/corrupted `versions.json`. Apply to `save_bundled_versions()` too.
25
+ - [ ] Warn when `versions.json` cache contains invalid JSON instead of silently
26
+ returning empty data.
27
+ - [ ] Use `os.pathsep` instead of hardcoded `":"` in `prereqs.py`
28
+ `check_path_directories()`.
29
+
30
+ ## Security and Integrity
31
+
32
+ - [ ] Add integrity verification for direct-download tarballs (not only install
33
+ script SHA256).
34
+ - [ ] Extend tool metadata to support tarball checksum/signature fields where
35
+ applicable.
36
+
37
+ ## CLI and Automation UX
38
+
39
+ - [ ] Add `--json` output mode for `list`, `status`, and `update-versions`.
40
+ - [ ] Add a focused `doctor` command for environment checks (PATH,
41
+ prerequisites, command health).
42
+ - [ ] Consider `install --force` for reinstall/repair flows.
43
+ - [ ] Add cleanup support for stale direct-download versions no longer in use.
44
+ - [ ] Expand `upgrade` help text to mention the default "only out-of-date tools"
45
+ behavior.
46
+
47
+ ## Documentation
48
+
49
+ - [ ] Document that running `code-aide` with no subcommand defaults to `status`.
50
+ - [ ] Add `install --dryrun` to the README usage examples.
51
+ - [ ] Document environment variables and config file paths
52
+ (`~/.config/code-aide/versions.json`).
53
+
54
+ ## Platform and Package Detection
55
+
56
+ - [ ] Broaden system package metadata detection beyond Gentoo-specific tooling
57
+ where practical.
58
+
59
+ ## Maintainability and Tests
60
+
61
+ - [ ] Split larger modules into smaller focused files where practical
62
+ (`commands_actions.py`, `versions.py`, `install.py`).
63
+ - [ ] Add tests for major untested functions:
64
+ - `upgrade_tool()` (completely untested)
65
+ - `cmd_remove()` (completely untested)
66
+ - `fetch_url()` (completely untested)
67
+ - `check_prerequisites()` / `install_nodejs_npm()` (completely untested)
68
+ - `save_bundled_versions()` (untested)
69
+ - `get_system_package_info()` (completely untested)
70
+ - [ ] Add tests for prerequisite edge cases and cache write behavior.
@@ -1,3 +1,3 @@
1
1
  """code-aide - Manage AI coding CLI tools."""
2
2
 
3
- __version__ = "1.1.0"
3
+ __version__ = "1.2.0"
@@ -302,7 +302,7 @@ def cmd_update_versions(args: argparse.Namespace) -> None:
302
302
 
303
303
  updates = [result for result in results if result["update"]]
304
304
  if not updates:
305
- if version_info_changed and not args.dry_run:
305
+ if version_info_changed and not args.dryrun:
306
306
  dest = _save(config["tools"])
307
307
  print(f"Updated latest version info in {dest}.")
308
308
  if version_info_changed:
@@ -323,7 +323,7 @@ def cmd_update_versions(args: argparse.Namespace) -> None:
323
323
  for result in updates:
324
324
  print(f" {result['tool']}: SHA256 changed")
325
325
 
326
- if args.dry_run:
326
+ if args.dryrun:
327
327
  print("\nDry run mode - no changes written.")
328
328
  return
329
329
 
@@ -105,6 +105,9 @@ def get_system_package_info(binary_path: str) -> Dict[str, Optional[str]]:
105
105
  except Exception:
106
106
  pass
107
107
 
108
+ if "/" not in package:
109
+ return result
110
+
108
111
  category, package_name = package.split("/", 1)
109
112
  ebuild_dirs = globmod.glob(f"/var/db/repos/*/{category}/{package_name}/")
110
113
  ebuilds = []
@@ -84,7 +84,7 @@ def main() -> None:
84
84
  )
85
85
  update_versions_parser.add_argument(
86
86
  "-n",
87
- "--dry-run",
87
+ "--dryrun",
88
88
  action="store_true",
89
89
  help="Show changes only, do not write updates",
90
90
  )
@@ -7,6 +7,7 @@ import platform
7
7
  import shutil
8
8
  import subprocess
9
9
  import tarfile
10
+ import tempfile
10
11
  from typing import Any, Dict, Optional
11
12
 
12
13
  from code_aide.constants import TOOLS
@@ -162,8 +163,11 @@ def install_direct_download(
162
163
  tarball_data, _ = fetch_url(download_url, timeout=120)
163
164
  success(f"Downloaded {len(tarball_data)} bytes")
164
165
 
165
- temp_dir = install_dir + f".tmp-{os.getpid()}"
166
- os.makedirs(temp_dir, exist_ok=True)
166
+ install_parent = os.path.dirname(install_dir) or "."
167
+ os.makedirs(install_parent, exist_ok=True)
168
+ temp_dir = tempfile.mkdtemp(
169
+ prefix=os.path.basename(install_dir) + ".tmp-", dir=install_parent
170
+ )
167
171
 
168
172
  try:
169
173
  with tarfile.open(fileobj=io.BytesIO(tarball_data), mode="r:gz") as tf:
@@ -275,6 +279,7 @@ def install_tool(tool_name: str, dryrun: bool = False) -> bool:
275
279
  if dryrun:
276
280
  success(f"{tool_config['name']} verification passed")
277
281
  else:
282
+ success(f"{tool_config['name']} installed successfully")
278
283
  info(tool_config["next_steps"])
279
284
  if "docs_url" in tool_config:
280
285
  info(f"Documentation: {tool_config['docs_url']}")
@@ -59,7 +59,7 @@ class TestCmdUpdateVersions(unittest.TestCase):
59
59
  (),
60
60
  {
61
61
  "tools": ["missing"],
62
- "dry_run": False,
62
+ "dryrun": False,
63
63
  "yes": False,
64
64
  "verbose": False,
65
65
  "bundled": False,
@@ -81,7 +81,7 @@ class TestCmdUpdateVersions(unittest.TestCase):
81
81
  (),
82
82
  {
83
83
  "tools": [],
84
- "dry_run": True,
84
+ "dryrun": True,
85
85
  "yes": False,
86
86
  "verbose": False,
87
87
  "bundled": False,
@@ -131,7 +131,7 @@ class TestCmdUpdateVersions(unittest.TestCase):
131
131
  (),
132
132
  {
133
133
  "tools": [],
134
- "dry_run": False,
134
+ "dryrun": False,
135
135
  "yes": True,
136
136
  "verbose": False,
137
137
  "bundled": True,
@@ -122,3 +122,57 @@ class TestInstallDirectDownloadDryrun(unittest.TestCase):
122
122
 
123
123
  result = cli_install.install_direct_download("test", tool_config, dryrun=True)
124
124
  self.assertFalse(result)
125
+
126
+
127
+ class TestInstallDirectDownload(unittest.TestCase):
128
+ """Tests for install_direct_download in non-dryrun mode."""
129
+
130
+ @mock.patch.object(cli_install, "detect_os_arch", return_value=("linux", "x64"))
131
+ @mock.patch.object(cli_install, "fetch_url")
132
+ def test_creates_missing_install_parent_directory(self, mock_fetch, mock_os_arch):
133
+ script_content = b"echo install"
134
+ expected_sha256 = cli_install.hashlib.sha256(script_content).hexdigest()
135
+
136
+ tarball_data = io.BytesIO()
137
+ with tarfile.open(fileobj=tarball_data, mode="w:gz") as tf:
138
+ payload = b"#!/bin/sh\necho ok\n"
139
+ info = tarfile.TarInfo("package/test-bin")
140
+ info.mode = 0o755
141
+ info.size = len(payload)
142
+ tf.addfile(info, io.BytesIO(payload))
143
+ tarball_bytes = tarball_data.getvalue()
144
+
145
+ def _fake_fetch(url, timeout=30):
146
+ if url.endswith("/install"):
147
+ return script_content, None
148
+ return tarball_bytes, None
149
+
150
+ mock_fetch.side_effect = _fake_fetch
151
+
152
+ tool_config = {
153
+ "name": "Test Tool",
154
+ "install_url": "https://example.com/install",
155
+ "install_sha256": expected_sha256,
156
+ "download_url_template": "https://example.com/{version}/{os}/{arch}/pkg.tar.gz",
157
+ "install_dir": "/tmp/test-{version}",
158
+ "bin_dir": "/tmp/test-bin",
159
+ "symlinks": {"test": "test-bin"},
160
+ "latest_version": "1.0.0",
161
+ }
162
+
163
+ with tempfile.TemporaryDirectory() as td:
164
+ install_dir = os.path.join(td, "missing", "versions", "1.0.0")
165
+ bin_dir = os.path.join(td, "bin")
166
+
167
+ result = cli_install.install_direct_download(
168
+ "test",
169
+ tool_config,
170
+ dryrun=False,
171
+ install_dir_override=install_dir,
172
+ bin_dir_override=bin_dir,
173
+ )
174
+
175
+ self.assertTrue(result)
176
+ self.assertTrue(os.path.isdir(os.path.dirname(install_dir)))
177
+ self.assertTrue(os.path.exists(os.path.join(install_dir, "test-bin")))
178
+ self.assertTrue(os.path.islink(os.path.join(bin_dir, "test")))
code_aide-1.1.0/TODO.md DELETED
@@ -1,39 +0,0 @@
1
- # TODO
2
-
3
- Keep the project focused on managing AI coding CLI tools (install, upgrade,
4
- remove, status, and version metadata).
5
-
6
- ## Reliability and Correctness
7
-
8
- - [ ] Handle missing `node` cleanly during prerequisite checks
9
- (`FileNotFoundError` path in Node version probing).
10
- - [ ] Read tool version output from both stdout and stderr so status does not
11
- miss installed versions.
12
- - [ ] Make version cache writes atomic (write temp file + rename) to avoid
13
- partial/corrupted `versions.json`.
14
-
15
- ## Security and Integrity
16
-
17
- - [ ] Add integrity verification for direct-download tarballs (not only install
18
- script SHA256).
19
- - [ ] Extend tool metadata to support tarball checksum/signature fields where
20
- applicable.
21
-
22
- ## CLI and Automation UX
23
-
24
- - [ ] Add `--json` output mode for `list`, `status`, and `update-versions`.
25
- - [ ] Add a focused `doctor` command for environment checks (PATH,
26
- prerequisites, command health).
27
- - [ ] Consider `install --force` for reinstall/repair flows.
28
- - [ ] Add cleanup support for stale direct-download versions no longer in use.
29
-
30
- ## Platform and Package Detection
31
-
32
- - [ ] Broaden system package metadata detection beyond Gentoo-specific tooling
33
- where practical.
34
-
35
- ## Maintainability and Tests
36
-
37
- - [ ] Split larger modules into smaller focused files where practical
38
- (`commands_actions.py`, `versions.py`, `install.py`).
39
- - [ ] Add tests for prerequisite edge cases and cache write behavior.
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes