machineconfig 2.8__py3-none-any.whl → 2.9__py3-none-any.whl

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.

Potentially problematic release.


This version of machineconfig might be problematic. Click here for more details.

Files changed (26) hide show
  1. machineconfig/jobs/python/python_ve_symlink.py +1 -1
  2. machineconfig/scripts/python/__pycache__/devops.cpython-313.pyc +0 -0
  3. machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-313.pyc +0 -0
  4. machineconfig/scripts/python/__pycache__/fire_agents.cpython-313.pyc +0 -0
  5. machineconfig/scripts/python/devops.py +18 -64
  6. machineconfig/scripts/python/devops_add_identity.py +6 -2
  7. machineconfig/scripts/python/devops_add_ssh_key.py +5 -2
  8. machineconfig/scripts/python/devops_backup_retrieve.py +3 -15
  9. machineconfig/scripts/python/devops_devapps_install.py +8 -6
  10. machineconfig/scripts/python/devops_update_repos.py +125 -226
  11. machineconfig/scripts/python/fire_agents.py +108 -151
  12. machineconfig/scripts/python/fire_agents_help_launch.py +97 -0
  13. machineconfig/scripts/python/fire_agents_help_search.py +83 -0
  14. machineconfig/scripts/python/helpers/cloud_helpers.py +2 -5
  15. machineconfig/scripts/python/repos.py +1 -1
  16. machineconfig/scripts/python/repos_helper_update.py +288 -0
  17. machineconfig/utils/installer_utils/installer_class.py +3 -3
  18. machineconfig/utils/notifications.py +24 -4
  19. machineconfig/utils/path.py +2 -1
  20. machineconfig/utils/procs.py +7 -7
  21. machineconfig/utils/source_of_truth.py +2 -0
  22. {machineconfig-2.8.dist-info → machineconfig-2.9.dist-info}/METADATA +7 -10
  23. {machineconfig-2.8.dist-info → machineconfig-2.9.dist-info}/RECORD +26 -22
  24. {machineconfig-2.8.dist-info → machineconfig-2.9.dist-info}/WHEEL +0 -0
  25. {machineconfig-2.8.dist-info → machineconfig-2.9.dist-info}/entry_points.txt +0 -0
  26. {machineconfig-2.8.dist-info → machineconfig-2.9.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,288 @@
1
+ from pathlib import Path
2
+ from typing import TypedDict
3
+ import subprocess
4
+ import git
5
+
6
+
7
+
8
+ class RepositoryUpdateResult(TypedDict):
9
+ """Result of updating a single repository."""
10
+ repo_path: str
11
+ status: str # "success", "error", "skipped", "auth_failed"
12
+ had_uncommitted_changes: bool
13
+ uncommitted_files: list[str]
14
+ commit_before: str
15
+ commit_after: str
16
+ commits_changed: bool
17
+ pyproject_changed: bool
18
+ uv_lock_changed: bool
19
+ dependencies_changed: bool
20
+ uv_sync_ran: bool
21
+ uv_sync_success: bool
22
+ remotes_processed: list[str]
23
+ remotes_skipped: list[str]
24
+ error_message: str | None
25
+ is_machineconfig_repo: bool
26
+ permissions_updated: bool
27
+
28
+
29
+ def set_permissions_recursive(path: Path, executable: bool = True) -> None:
30
+ """Set permissions recursively for a directory."""
31
+ if not path.exists():
32
+ return
33
+ if path.is_file():
34
+ if executable:
35
+ path.chmod(0o755)
36
+ else:
37
+ path.chmod(0o644)
38
+ elif path.is_dir():
39
+ path.chmod(0o755)
40
+ for item in path.rglob("*"):
41
+ set_permissions_recursive(item, executable)
42
+
43
+
44
+ def run_uv_sync(repo_path: Path) -> bool:
45
+ """Run uv sync in the given repository path. Returns True if successful."""
46
+ try:
47
+ print(f"🔄 Running uv sync in {repo_path}")
48
+ # Run uv sync with output directly to terminal (no capture)
49
+ subprocess.run(["uv", "sync"], cwd=repo_path, check=True)
50
+ print("✅ uv sync completed successfully")
51
+ return True
52
+ except subprocess.CalledProcessError as e:
53
+ print(f"❌ uv sync failed with return code {e.returncode}")
54
+ return False
55
+ except FileNotFoundError:
56
+ print("⚠️ uv command not found. Please install uv first.")
57
+ return False
58
+
59
+
60
+ def get_file_hash(file_path: Path) -> str | None:
61
+ """Get SHA256 hash of a file, return None if file doesn't exist."""
62
+ if not file_path.exists():
63
+ return None
64
+ import hashlib
65
+ return hashlib.sha256(file_path.read_bytes()).hexdigest()
66
+
67
+
68
+ def update_repository(repo: git.Repo, auto_sync: bool, allow_password_prompt: bool) -> RepositoryUpdateResult:
69
+ """Update a single repository and return detailed information about what happened."""
70
+ repo_path = Path(repo.working_dir)
71
+ print(f"🔄 {'Updating ' + str(repo_path):.^80}")
72
+
73
+ # Initialize result dict
74
+ result: RepositoryUpdateResult = {
75
+ "repo_path": str(repo_path),
76
+ "status": "success",
77
+ "had_uncommitted_changes": False,
78
+ "uncommitted_files": [],
79
+ "commit_before": "",
80
+ "commit_after": "",
81
+ "commits_changed": False,
82
+ "pyproject_changed": False,
83
+ "uv_lock_changed": False,
84
+ "dependencies_changed": False,
85
+ "uv_sync_ran": False,
86
+ "uv_sync_success": False,
87
+ "remotes_processed": [],
88
+ "remotes_skipped": [],
89
+ "error_message": None,
90
+ "is_machineconfig_repo": "machineconfig" in str(repo_path),
91
+ "permissions_updated": False,
92
+ }
93
+
94
+ # Check git status first
95
+ print("📊 Checking git status...")
96
+ if repo.is_dirty():
97
+ # Get the list of modified files
98
+ changed_files_raw = [item.a_path for item in repo.index.diff(None)]
99
+ changed_files_raw.extend([item.a_path for item in repo.index.diff("HEAD")])
100
+ # Filter out None values and remove duplicates
101
+ changed_files = list(set(file for file in changed_files_raw if file is not None))
102
+
103
+ result["had_uncommitted_changes"] = True
104
+ result["uncommitted_files"] = changed_files
105
+ print(f"⚠️ Repository has uncommitted changes: {', '.join(changed_files)}")
106
+
107
+ # Check if the only change is uv.lock
108
+ if len(changed_files) == 1 and changed_files[0] == "uv.lock":
109
+ print("🔒 Only uv.lock has changes, resetting it...")
110
+ try:
111
+ # Reset uv.lock file
112
+ subprocess.run(["git", "checkout", "HEAD", "--", "uv.lock"], cwd=repo_path, check=True)
113
+ print("✅ uv.lock has been reset")
114
+ except subprocess.CalledProcessError as e:
115
+ result["status"] = "error"
116
+ result["error_message"] = f"Failed to reset uv.lock: {e}"
117
+ print(f"❌ Failed to reset uv.lock: {e}")
118
+ return result
119
+ else:
120
+ # Multiple files or files other than uv.lock have changes
121
+ result["status"] = "error"
122
+ result["error_message"] = f"Cannot update repository - there are pending changes in: {', '.join(changed_files)}. Please commit or stash your changes first."
123
+ raise RuntimeError(result["error_message"])
124
+ else:
125
+ print("✅ Repository is clean")
126
+
127
+ # Check if this repo has pyproject.toml or uv.lock
128
+ pyproject_path = repo_path / "pyproject.toml"
129
+ uv_lock_path = repo_path / "uv.lock"
130
+
131
+ # Get hashes before pull
132
+ pyproject_hash_before = get_file_hash(pyproject_path)
133
+ uv_lock_hash_before = get_file_hash(uv_lock_path)
134
+
135
+ # Get current commit hash before pull
136
+ result["commit_before"] = repo.head.commit.hexsha
137
+
138
+ try:
139
+ # Use subprocess for git pull to get better output control
140
+
141
+ # Get list of remotes
142
+ remotes = list(repo.remotes)
143
+ if not remotes:
144
+ print("⚠️ No remotes configured for this repository")
145
+ result["status"] = "skipped"
146
+ result["error_message"] = "No remotes configured for this repository"
147
+ return result
148
+
149
+ for remote in remotes:
150
+ try:
151
+ print(f"📥 Fetching from {remote.name}...")
152
+
153
+ # Set up environment for git commands
154
+ env = None
155
+ if not allow_password_prompt:
156
+ # Disable interactive prompts
157
+ import os
158
+
159
+ env = os.environ.copy()
160
+ env["GIT_TERMINAL_PROMPT"] = "0"
161
+ env["GIT_ASKPASS"] = "echo" # Returns empty string for any credential request
162
+
163
+ # First fetch to see what's available
164
+ fetch_result = subprocess.run(
165
+ ["git", "fetch", remote.name, "--verbose"],
166
+ cwd=repo_path,
167
+ capture_output=True,
168
+ text=True,
169
+ env=env,
170
+ timeout=30, # Add timeout to prevent hanging
171
+ )
172
+
173
+ # Check if fetch failed due to authentication
174
+ if fetch_result.returncode != 0 and not allow_password_prompt:
175
+ auth_error_indicators = [
176
+ "Authentication failed",
177
+ "Password for",
178
+ "Username for",
179
+ "could not read Username",
180
+ "could not read Password",
181
+ "fatal: Authentication failed",
182
+ "fatal: could not read Username",
183
+ "fatal: could not read Password",
184
+ ]
185
+
186
+ error_output = (fetch_result.stderr or "") + (fetch_result.stdout or "")
187
+ if any(indicator in error_output for indicator in auth_error_indicators):
188
+ print(f"⚠️ Skipping {remote.name} - authentication required but password prompts are disabled")
189
+ continue
190
+
191
+ if fetch_result.stdout:
192
+ print(f"📡 Fetch output: {fetch_result.stdout.strip()}")
193
+ if fetch_result.stderr:
194
+ print(f"📡 Fetch info: {fetch_result.stderr.strip()}")
195
+
196
+ # Now pull with verbose output
197
+ print(f"📥 Pulling from {remote.name}/{repo.active_branch.name}...")
198
+ pull_result = subprocess.run(["git", "pull", remote.name, repo.active_branch.name, "--verbose"], cwd=repo_path, capture_output=True, text=True, env=env, timeout=30)
199
+
200
+ # Check if pull failed due to authentication
201
+ if pull_result.returncode != 0 and not allow_password_prompt:
202
+ auth_error_indicators = [
203
+ "Authentication failed",
204
+ "Password for",
205
+ "Username for",
206
+ "could not read Username",
207
+ "could not read Password",
208
+ "fatal: Authentication failed",
209
+ "fatal: could not read Username",
210
+ "fatal: could not read Password",
211
+ ]
212
+
213
+ error_output = (pull_result.stderr or "") + (pull_result.stdout or "")
214
+ if any(indicator in error_output for indicator in auth_error_indicators):
215
+ print(f"⚠️ Skipping pull from {remote.name} - authentication required but password prompts are disabled")
216
+ continue
217
+
218
+ if pull_result.stdout:
219
+ print(f"📦 Pull output: {pull_result.stdout.strip()}")
220
+ if pull_result.stderr:
221
+ print(f"📦 Pull info: {pull_result.stderr.strip()}")
222
+
223
+ # Check if pull was successful
224
+ if pull_result.returncode == 0:
225
+ result["remotes_processed"].append(remote.name)
226
+ # Check if commits changed
227
+ result["commit_after"] = repo.head.commit.hexsha
228
+ if result["commit_before"] != result["commit_after"]:
229
+ result["commits_changed"] = True
230
+ print(f"✅ Repository updated: {result['commit_before'][:8]} → {result['commit_after'][:8]}")
231
+ else:
232
+ print("✅ Already up to date")
233
+ else:
234
+ result["remotes_skipped"].append(remote.name)
235
+ print(f"❌ Pull failed with return code {pull_result.returncode}")
236
+
237
+ except Exception as e:
238
+ result["remotes_skipped"].append(remote.name)
239
+ print(f"⚠️ Failed to pull from {remote.name}: {e}")
240
+ continue
241
+
242
+ # Check if pyproject.toml or uv.lock changed after pull
243
+ pyproject_hash_after = get_file_hash(pyproject_path)
244
+ uv_lock_hash_after = get_file_hash(uv_lock_path)
245
+
246
+ if pyproject_hash_before != pyproject_hash_after:
247
+ print("📋 pyproject.toml has changed")
248
+ result["pyproject_changed"] = True
249
+ result["dependencies_changed"] = True
250
+
251
+ if uv_lock_hash_before != uv_lock_hash_after:
252
+ print("🔒 uv.lock has changed")
253
+ result["uv_lock_changed"] = True
254
+ result["dependencies_changed"] = True
255
+
256
+ # Special handling for machineconfig repository
257
+ if result["is_machineconfig_repo"]:
258
+ print("🛠 Special handling for machineconfig repository...")
259
+ scripts_path = Path.home() / "scripts"
260
+ if scripts_path.exists():
261
+ set_permissions_recursive(scripts_path)
262
+ result["permissions_updated"] = True
263
+ print(f"✅ Set permissions for {scripts_path}")
264
+
265
+ linux_jobs_path = repo_path / "src" / "machineconfig" / "jobs" / "linux"
266
+ if linux_jobs_path.exists():
267
+ set_permissions_recursive(linux_jobs_path)
268
+ result["permissions_updated"] = True
269
+ print(f"✅ Set permissions for {linux_jobs_path}")
270
+
271
+ lf_exe_path = repo_path / "src" / "machineconfig" / "settings" / "lf" / "linux" / "exe"
272
+ if lf_exe_path.exists():
273
+ set_permissions_recursive(lf_exe_path)
274
+ result["permissions_updated"] = True
275
+ print(f"✅ Set permissions for {lf_exe_path}")
276
+
277
+ # Run uv sync if dependencies changed and auto_sync is enabled
278
+ if result["dependencies_changed"] and auto_sync:
279
+ result["uv_sync_ran"] = True
280
+ result["uv_sync_success"] = run_uv_sync(repo_path)
281
+
282
+ return result
283
+
284
+ except Exception as e:
285
+ result["status"] = "error"
286
+ result["error_message"] = str(e)
287
+ print(f"❌ Error updating repository {repo_path}: {e}")
288
+ return result
@@ -94,14 +94,14 @@ class Installer:
94
94
 
95
95
  if old_version_cli == new_version_cli:
96
96
  print(f"ℹ️ Same version detected: {old_version_cli}")
97
- return f"""echo "📦️ 😑 {self.exe_name}, same version: {old_version_cli}" """
97
+ return f"""📦️ 😑 {self.exe_name}, same version: {old_version_cli}"""
98
98
  else:
99
99
  print(f"🚀 Update successful: {old_version_cli} ➡️ {new_version_cli}")
100
- return f"""echo "📦️ 🤩 {self.exe_name} updated from {old_version_cli} ➡️ TO ➡️ {new_version_cli}" """
100
+ return f"""📦️ 🤩 {self.exe_name} updated from {old_version_cli} ➡️ TO ➡️ {new_version_cli}"""
101
101
 
102
102
  except Exception as ex:
103
103
  print(f"❌ ERROR: Installation failed for {self.exe_name}: {ex}")
104
- return f"""echo "📦️ ❌ Failed to install `{self.name}` with error: {ex}" """
104
+ return f"""📦️ ❌ Failed to install `{self.name}` with error: {ex}"""
105
105
 
106
106
  def install(self, version: Optional[str]):
107
107
  print(f"\n{'=' * 80}\n🔧 INSTALLATION PROCESS: {self.exe_name} 🔧\n{'=' * 80}")
@@ -14,7 +14,8 @@ import imaplib
14
14
  from email.mime.text import MIMEText
15
15
  from email.mime.multipart import MIMEMultipart
16
16
  from typing import Optional, Any, Union
17
- from markdown import markdown
17
+ from rich.console import Console
18
+ from rich.markdown import Markdown
18
19
 
19
20
 
20
21
  def download_to_memory(path: Path, allow_redirects: bool = True, timeout: Optional[float] = None, params: Any = None) -> "Any":
@@ -30,8 +31,27 @@ def get_github_markdown_css() -> str:
30
31
  return download_to_memory(Path(pp)).text
31
32
 
32
33
 
33
- def md2html(body: str):
34
- gh_style = Path(__file__).parent.joinpath("gh_style.css").read_text()
34
+ def md2html(body: str) -> str:
35
+ """Convert markdown to HTML using Rich library."""
36
+ # Use Rich's HTML export functionality to convert markdown to HTML
37
+ console = Console(record=True, width=120)
38
+ markdown_obj = Markdown(body)
39
+ console.print(markdown_obj)
40
+ html_output = console.export_html(inline_styles=True)
41
+
42
+ # Try to load GitHub CSS style, fallback to basic style if not found
43
+ gh_style_path = Path(__file__).parent.joinpath("gh_style.css")
44
+ if gh_style_path.exists():
45
+ gh_style = gh_style_path.read_text()
46
+ else:
47
+ # Fallback basic styling
48
+ gh_style = """
49
+ body { font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif; }
50
+ h1, h2, h3, h4, h5, h6 { color: #0366d6; }
51
+ code { background-color: #f6f8fa; padding: 2px 4px; border-radius: 3px; }
52
+ pre { background-color: #f6f8fa; padding: 16px; border-radius: 6px; overflow: auto; }
53
+ """
54
+
35
55
  return f"""
36
56
  <!DOCTYPE html>
37
57
  <html>
@@ -51,7 +71,7 @@ def md2html(body: str):
51
71
  </style>
52
72
  <body>
53
73
  <div class="markdown-body">
54
- {markdown(body)}
74
+ {html_output}
55
75
  </div>
56
76
  </body>
57
77
  </html>"""
@@ -1,5 +1,6 @@
1
1
  from machineconfig.utils.path_reduced import PathExtended as PathExtended
2
2
  from machineconfig.utils.options import choose_one_option
3
+ from machineconfig.utils.source_of_truth import EXCLUDE_DIRS
3
4
  from rich.console import Console
4
5
  from rich.panel import Panel
5
6
  import platform
@@ -54,7 +55,7 @@ def find_scripts(root: Path, name_substring: str, suffixes: set[str]) -> tuple[l
54
55
  partial_path_matches = []
55
56
  for entry in root.iterdir():
56
57
  if entry.is_dir():
57
- if entry.name in {".links", ".venv", ".git", ".idea", ".vscode", "node_modules", "__pycache__", ".mypy_cache"}:
58
+ if entry.name in set(EXCLUDE_DIRS):
58
59
  # prune this entire subtree
59
60
  continue
60
61
  tmp1, tmp2 = find_scripts(entry, name_substring, suffixes)
@@ -2,12 +2,12 @@
2
2
 
3
3
  import psutil
4
4
  from rich.progress import Progress, SpinnerColumn, TextColumn
5
- from pytz import timezone
5
+ from zoneinfo import ZoneInfo
6
6
  from machineconfig.utils.options import display_options
7
7
  from typing import Optional, Any
8
8
  from rich.console import Console
9
9
  from rich.panel import Panel
10
- from datetime import datetime
10
+ from datetime import datetime, timezone
11
11
  from machineconfig.utils.utils2 import pprint
12
12
 
13
13
  console = Console()
@@ -72,8 +72,8 @@ class ProcessManager:
72
72
  try:
73
73
  mem_usage_mb = proc.memory_info().rss / (1024 * 1024)
74
74
  # Convert create_time to local timezone
75
- create_time_utc = datetime.fromtimestamp(proc.create_time(), tz=timezone("UTC"))
76
- create_time_local = create_time_utc.astimezone(timezone("Australia/Adelaide"))
75
+ create_time_utc = datetime.fromtimestamp(proc.create_time(), tz=timezone.utc)
76
+ create_time_local = create_time_utc.astimezone(ZoneInfo("Australia/Adelaide"))
77
77
 
78
78
  process_info.append(
79
79
  {
@@ -222,13 +222,13 @@ def get_age(create_time: Any) -> str:
222
222
  try:
223
223
  if isinstance(create_time, (int, float)):
224
224
  # Handle timestampz
225
- create_time_utc = datetime.fromtimestamp(create_time, tz=timezone("UTC"))
226
- create_time_local = create_time_utc.astimezone(timezone("Australia/Adelaide"))
225
+ create_time_utc = datetime.fromtimestamp(create_time, tz=timezone.utc)
226
+ create_time_local = create_time_utc.astimezone(ZoneInfo("Australia/Adelaide"))
227
227
  else:
228
228
  # Already a datetime object
229
229
  create_time_local = create_time
230
230
 
231
- now_local = datetime.now(tz=timezone("Australia/Adelaide"))
231
+ now_local = datetime.now(tz=ZoneInfo("Australia/Adelaide"))
232
232
  age = now_local - create_time_local
233
233
  return str(age)
234
234
  except Exception as e:
@@ -5,6 +5,8 @@ Utils
5
5
  import machineconfig
6
6
  from pathlib import Path
7
7
 
8
+ EXCLUDE_DIRS = [".links", ".ai", ".scripts", ".venv", ".git", ".idea", ".vscode", "node_modules", "__pycache__", ".mypy_cache"]
9
+
8
10
  LIBRARY_ROOT = Path(machineconfig.__file__).resolve().parent
9
11
  REPO_ROOT = LIBRARY_ROOT.parent.parent
10
12
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: machineconfig
3
- Version: 2.8
3
+ Version: 2.9
4
4
  Summary: Dotfiles management package
5
5
  Author-email: Alex Al-Saffar <programmer@usa.com>
6
6
  License: Apache 2.0
@@ -13,21 +13,18 @@ Requires-Python: >=3.13
13
13
  Description-Content-Type: text/markdown
14
14
  Requires-Dist: cryptography>=44.0.2
15
15
  Requires-Dist: fire>=0.7.0
16
- Requires-Dist: gitpython>=3.1.44
17
16
  Requires-Dist: joblib>=1.5.2
18
- Requires-Dist: markdown>=3.9
19
17
  Requires-Dist: paramiko>=3.5.1
20
- Requires-Dist: psutil>=7.0.0
21
- Requires-Dist: pydantic>=2.11.3
22
- Requires-Dist: pyfzf>=0.3.1
23
- Requires-Dist: pyjson5>=1.6.9
24
- Requires-Dist: pytz>=2025.2
25
- Requires-Dist: pyyaml>=6.0.2
26
18
  Requires-Dist: randomname>=0.2.1
27
- Requires-Dist: rclone-python>=0.1.23
28
19
  Requires-Dist: requests>=2.32.5
29
20
  Requires-Dist: rich>=14.0.0
30
21
  Requires-Dist: tenacity>=9.1.2
22
+ Requires-Dist: psutil>=7.0.0
23
+ Requires-Dist: gitpython>=3.1.44
24
+ Requires-Dist: pyfzf>=0.3.1
25
+ Requires-Dist: rclone-python>=0.1.23
26
+ Requires-Dist: pyjson5>=1.6.9
27
+ Requires-Dist: pyyaml>=6.0.2
31
28
  Requires-Dist: toml>=0.10.2
32
29
  Requires-Dist: tomli>=2.2.1
33
30
  Provides-Extra: windows
@@ -48,7 +48,7 @@ machineconfig/jobs/python/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJW
48
48
  machineconfig/jobs/python/check_installations.py,sha256=o0mrZ-ivdED_7Od1tdtwJ4XSQRfiY6d_HciXLh1PXtY,11126
49
49
  machineconfig/jobs/python/create_bootable_media.py,sha256=KKtcPk0rFLQc4eNVP6nbeYX-P7Gpqi0HvfIcUM6rVVs,827
50
50
  machineconfig/jobs/python/python_cargo_build_share.py,sha256=RDe1QiTH3vLQ1wjN0kE5NxMIqwB-_WHz6O3svyuH_VE,2133
51
- machineconfig/jobs/python/python_ve_symlink.py,sha256=quma-fmKIeNbScaQ3HdZV50QCcGt4MF6HjBfsHtxdv4,852
51
+ machineconfig/jobs/python/python_ve_symlink.py,sha256=ico4Xq_v7eKB2jGtL0puJI-KgAt3_NVIF4UCU3Z_7RM,845
52
52
  machineconfig/jobs/python/tasks.py,sha256=hrBDQOnBmcXtauTkicVgC8J2AOGcfdFfyx0K8eI6Coc,150
53
53
  machineconfig/jobs/python/vscode/api.py,sha256=BYF3XeNXYCpM4ApDCz2ZM1AInY4WgBqrpX9l_MWYqfM,1670
54
54
  machineconfig/jobs/python/vscode/link_ve.py,sha256=1tXXgfWcl18K6avdhm2V7zng18opR9pfI0PSLxMFbiQ,1439
@@ -165,14 +165,16 @@ machineconfig/scripts/python/cloud_mount.py,sha256=QdokpaQ31S5oVBsZTApVNXbquWfJL
165
165
  machineconfig/scripts/python/cloud_repo_sync.py,sha256=-aGiNw-K706vcuVwsuBXUL2FMHpa6OnHiKIIaydAt38,9940
166
166
  machineconfig/scripts/python/cloud_sync.py,sha256=UVxFG2mRARU0CEU51RvdjyR4vxxF8bemzmDgWvZ9SRs,3858
167
167
  machineconfig/scripts/python/croshell.py,sha256=7b7I5NSXQvQoiyWH7zKNIi2mO1tZ8yi8XkWn38XkreE,9509
168
- machineconfig/scripts/python/devops.py,sha256=5l2d2WlQSZ811W6Gtw6xwmIypt-NLHcABJbRiBf7Fmg,7887
169
- machineconfig/scripts/python/devops_add_identity.py,sha256=gYcRzUZGr-truU2l5iPLEiWSZpKLzz5a6v5VPrEMVwg,3869
170
- machineconfig/scripts/python/devops_add_ssh_key.py,sha256=D66vyl4NnvwL306yJXSFI4ht0sz-m9yczuBf82VCodo,6760
171
- machineconfig/scripts/python/devops_backup_retrieve.py,sha256=noN0pgZkj7wdQSZpyCOKYVV_npcKn1CkXtqt1l2QO4w,6201
172
- machineconfig/scripts/python/devops_devapps_install.py,sha256=6G_drNiChsFkX4qj_K_DPn666QxqYlkp9ENQAIs5HUw,8540
173
- machineconfig/scripts/python/devops_update_repos.py,sha256=bTvKYvT6i6TTmjpfM19NyPb5_Y9vqESYNzjYEzT0N4k,12627
168
+ machineconfig/scripts/python/devops.py,sha256=X_Q7-EqIoBEVieITICyZHVYHPE9Q8X84-HOxl2dU4pk,6181
169
+ machineconfig/scripts/python/devops_add_identity.py,sha256=mRoH2_SD_i4xzhBSuXk97W3fv7R9emZFDUX2lunxXrI,4066
170
+ machineconfig/scripts/python/devops_add_ssh_key.py,sha256=zdVlHtD6vlpXMLuwIqN5nHcm023ty2qVArWe7zPxgCo,6949
171
+ machineconfig/scripts/python/devops_backup_retrieve.py,sha256=I7lghN_HJT1mPaZ7zcD1jIJnTjNOvUC7nQZAoySPp7o,5563
172
+ machineconfig/scripts/python/devops_devapps_install.py,sha256=xQaOHlr6ziHxrx7e5Ri7WQ-FjIW0hjzDhlPJC-3qwks,8596
173
+ machineconfig/scripts/python/devops_update_repos.py,sha256=dIvHfq9zRkZhvFjYXOamJEAuF-AWXwtSnwGLOf2SE7E,8350
174
174
  machineconfig/scripts/python/dotfile.py,sha256=miL8mQH2AqPdnHSz0Cxa7qQavaOmzTD9DAF66H2PRzA,2259
175
- machineconfig/scripts/python/fire_agents.py,sha256=WcdvWuqg0GiAoW3JWnVZSl3009QCPQ6FmEPzEmZz_vE,9354
175
+ machineconfig/scripts/python/fire_agents.py,sha256=RFUZ-bULx93a3MkjSl-2rGlx_bguQUcGqoTkefuUN_I,8739
176
+ machineconfig/scripts/python/fire_agents_help_launch.py,sha256=41GagLs0QJCdoS-5aVcm4EpApRKzAXdc_SFFUTdSbIQ,3746
177
+ machineconfig/scripts/python/fire_agents_help_search.py,sha256=EmvCh9HD45sePgrE1skvd3CZsOVh13AC7S0PNeMP__0,2992
176
178
  machineconfig/scripts/python/fire_jobs.py,sha256=FvfJ-LrTUTVJRVT7i1LeP2YEUYH21RkYwKlVoEJxZNs,16616
177
179
  machineconfig/scripts/python/fire_jobs_args_helper.py,sha256=TfCKSExGZhYrZ6JmXIHsd0wpNSWcKeLeRh9gFR3FG-M,4330
178
180
  machineconfig/scripts/python/fire_jobs_layout_helper.py,sha256=_cx6ZnWezes-s13HXyKiI16vj9gF-Mpo_OF4StDQfFs,3222
@@ -185,8 +187,9 @@ machineconfig/scripts/python/mount_nw_drive.py,sha256=_7Rq-OGdJ8eYivESqGqdtWfSER
185
187
  machineconfig/scripts/python/mount_ssh.py,sha256=uALax_ZVKihspQF6TuUtvtoAo-VRHCkdKQ7N9GRcry8,2234
186
188
  machineconfig/scripts/python/onetimeshare.py,sha256=bmGsNnskym5OWfIhpOfZG5jq3m89FS0a6dF5Sb8LaZM,2539
187
189
  machineconfig/scripts/python/pomodoro.py,sha256=SPkfeoZGv8rylGiOyzQ7UK3aXZ3G2FIOuGkSuBUggOI,2019
188
- machineconfig/scripts/python/repos.py,sha256=K6Q4E3YsV3BdXIJXgiy2bhv9mzBAlvERBhliPM4mN3Q,7229
190
+ machineconfig/scripts/python/repos.py,sha256=nV5iJV7BLwBKiS_aqnrh63cfp-3k7nZyfUGtspwjKsM,7229
189
191
  machineconfig/scripts/python/repos_helper_record.py,sha256=rtnjcr2ZCzt4j7oSPws25fPiCzshOEU_jH1ORW4QWx0,11372
192
+ machineconfig/scripts/python/repos_helper_update.py,sha256=yEXG1eFbeZPCDOTKA3_X9TpHa-WzbZcUFTlXAlT-itQ,12160
190
193
  machineconfig/scripts/python/scheduler.py,sha256=7IBjMMOHMkklcWzYwz93EH9XzbJ5uPqU03bJ_lYbRNo,3083
191
194
  machineconfig/scripts/python/snapshot.py,sha256=aDvKeoniZaeTSNv9zWBUajaj2yagAxVdfuvO1_tgq5Y,1026
192
195
  machineconfig/scripts/python/start_slidev.py,sha256=MPCN0JgRzOAXywj6n9s0iZYcLFAscP-eOPQvkUyElRA,4525
@@ -197,9 +200,10 @@ machineconfig/scripts/python/wifi_conn.py,sha256=2FJ4srVthGHsy3KSXpvndAyVkNO8n_X
197
200
  machineconfig/scripts/python/wsl_windows_transfer.py,sha256=RfSf5SJejnqrg36YfXSwu52ceEW77uNP4WC6QQUyRTA,3650
198
201
  machineconfig/scripts/python/__pycache__/__init__.cpython-313.pyc,sha256=IppPGJ6Wk5Ma5oPWfJpN5QDW6-NvCk29la5JGbgAJ6E,171
199
202
  machineconfig/scripts/python/__pycache__/cloud_repo_sync.cpython-313.pyc,sha256=sWCevZgeQxIHoQ5Ea7a0OpjgJpkcKMoZylwCyizXYqA,10555
200
- machineconfig/scripts/python/__pycache__/devops.cpython-313.pyc,sha256=8j-fZCwpUVjwTRYgcNfTjjUyDg__ECUPlhtk79Vbtas,10817
203
+ machineconfig/scripts/python/__pycache__/devops.cpython-313.pyc,sha256=Rs6A-GpFrTXuXAn0tO3cGvilciJMHk0ujt_JPlsxaJ4,8216
201
204
  machineconfig/scripts/python/__pycache__/devops_devapps_install.cpython-313.pyc,sha256=BrMh1Rzca_iY0EvlPsSXBqpwOZw-De6I3y8blXJZCuc,8616
202
- machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-313.pyc,sha256=8S4qRoRpahRr8HEZ4mfxEVLWbWbVhcdmAMNeL8U7Sp4,13923
205
+ machineconfig/scripts/python/__pycache__/devops_update_repos.cpython-313.pyc,sha256=6gTDTRboQbrSfF-8gR7SSJZSqygd6yNf_08xnxZYLno,23284
206
+ machineconfig/scripts/python/__pycache__/fire_agents.cpython-313.pyc,sha256=61OZTwltoquxWzQPwHue4SehHuiaDExcl57aN07Cpww,15829
203
207
  machineconfig/scripts/python/__pycache__/get_zellij_cmd.cpython-313.pyc,sha256=jx8_Gyx1kkqCwIe8W51h9hO89yuzTdd4Vh5oPRBOLio,826
204
208
  machineconfig/scripts/python/__pycache__/repos.cpython-313.pyc,sha256=CoqJX-Oc-7suZ03dIkNqWscKXsuiswHHoGPM_VaZzS8,9642
205
209
  machineconfig/scripts/python/__pycache__/repos_helper_record.cpython-313.pyc,sha256=VWsAX_sFJxVD0MUiZ1d9Bj9p4kw5gquukGLoJlID-lQ,13573
@@ -218,7 +222,7 @@ machineconfig/scripts/python/archive/im2text.py,sha256=WLyic89vxi_pqQMzo-MOrGf39
218
222
  machineconfig/scripts/python/archive/tmate_conn.py,sha256=BiZQmYabl4K4-mbOpcb_R1JzYfEwxuAnk5FOciqGHFo,1231
219
223
  machineconfig/scripts/python/archive/tmate_start.py,sha256=Hp7xv32u-fRuCG_f-Cy6qg0VemoaPOP-Pxs_gsFYcyg,1518
220
224
  machineconfig/scripts/python/helpers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
221
- machineconfig/scripts/python/helpers/cloud_helpers.py,sha256=R8xFPcgsdRHn4ta9QjQUjch3P5Bwnv8oiY-UpFE982U,4966
225
+ machineconfig/scripts/python/helpers/cloud_helpers.py,sha256=ogjMFla4IAM50xkRCJU79sqylY02x31e9ulqYoRF8BY,4874
222
226
  machineconfig/scripts/python/helpers/helpers2.py,sha256=TU1sA0GKNXHXT1_0y8piBLT_BeXfk0uBmkmUeyVYj58,7295
223
227
  machineconfig/scripts/python/helpers/helpers4.py,sha256=SFYfxRleEq3gIbffIxFM8d1Ra5zNheUuTIOi2iBsqlE,7708
224
228
  machineconfig/scripts/python/helpers/helpers5.py,sha256=dPBvA9Tcyx9TMgM6On49A1CueGMhBdRzikDnlJGf3J0,1123
@@ -390,13 +394,13 @@ machineconfig/utils/code.py,sha256=y2CTzD9elNOqMfiAJgxyTNhYG28IaYtKOv5zjTiRchE,4
390
394
  machineconfig/utils/installer.py,sha256=725N-0gmMbrWWh6_9sn-2w9aXrfjIPrnuu9o13T4N4o,10941
391
395
  machineconfig/utils/io_save.py,sha256=iC1YTH0MOlBS8bWUB8Xhdl4CG_bEKQ3OVwMohdCOazI,3145
392
396
  machineconfig/utils/links.py,sha256=5rDQ6Id-vTtJRFwOWX8xZDXIOR5lY0DgLy0HpxIKLhk,10247
393
- machineconfig/utils/notifications.py,sha256=7OQmcOMhJIOQ2Rhgm9HDeyhXtjUkC4Ldl1Rrgnv311g,8423
397
+ machineconfig/utils/notifications.py,sha256=q1kZM1y4ZmNhAHlEWZlzLE2HS3nnevrSUpunxd8rAT4,9307
394
398
  machineconfig/utils/options.py,sha256=F8w5AEvm8yxgipYpLgeHlXJtvoXigZvDJjSqA5TU9J0,8554
395
- machineconfig/utils/path.py,sha256=4PNyyYsjPdJGDx1FbhPT4Sv6uR6PHAk9tMZiGQCGkIc,8071
399
+ machineconfig/utils/path.py,sha256=k0iyDaYsO-4yWCzjZ88-SxXDZLZPTGYX2WeSU8Pn-6w,8056
396
400
  machineconfig/utils/path_reduced.py,sha256=hccGUTSMtggU-LpLNS7W_c1s-CqhjHMbTQ59-1EqgmY,52473
397
- machineconfig/utils/procs.py,sha256=Ysbo61YrJ0N1kAsF52-WAdS5fplAABNDd0ZgCpTRzK8,11476
401
+ machineconfig/utils/procs.py,sha256=aw2UyFvoJw69zDzfcxG46z-4O8MA5WsXvRpvFTqht-4,11484
398
402
  machineconfig/utils/scheduling.py,sha256=8xjeoR_D5QHT0d7299Mgsj6JUbvkE_PX_pWq3myi658,11184
399
- machineconfig/utils/source_of_truth.py,sha256=n2zSG3HQO7YIdZi31dz_isxWMNQcO9LpJ_RCCSKcTHA,725
403
+ machineconfig/utils/source_of_truth.py,sha256=GnjcVkKm11RyZFHGnPbne5YDEBYoZ5yryBNkpfGC7O4,854
400
404
  machineconfig/utils/ssh.py,sha256=YBL2avhPUC43L1wxi2Doh2-cK-I7j81eUWEmfzAj9Jc,21196
401
405
  machineconfig/utils/terminal.py,sha256=k3xoMwJPGvmaeL9CxEIwrcQjRNN6EnJItoIIxXrUY8c,12258
402
406
  machineconfig/utils/upgrade_packages.py,sha256=H96zVJEWXJW07nh5vhjuSCrPtXGqoUb7xeJsFYYdmCI,3330
@@ -409,11 +413,11 @@ machineconfig/utils/cloud/onedrive/setup_oauth.py,sha256=ZTVkqgrwbV_EoPvyT8dyOTU
409
413
  machineconfig/utils/cloud/onedrive/transaction.py,sha256=m-aNcnWj_gfZVvJOSpkdIqjZxU_3nXx2CA-qKbQgP3I,26232
410
414
  machineconfig/utils/installer_utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
411
415
  machineconfig/utils/installer_utils/installer_abc.py,sha256=jR5XvrCjisIzoxk2VL0VhoVv-PkKdstDHGLcYky5Mqs,5319
412
- machineconfig/utils/installer_utils/installer_class.py,sha256=l0UM-u6ZfWx-uLvAk_mmojbppj4sxDrHX3wmVwQv12w,20366
416
+ machineconfig/utils/installer_utils/installer_class.py,sha256=3jknokPmaN4LuBR5n6LrewIYo4-PrTuhYnFJIuhjjuY,20342
413
417
  machineconfig/utils/schemas/layouts/layout_types.py,sha256=SPgoc0ncazKlXtQUhi7u1mMP2JvDt5jSG9YQmBr7-zc,616
414
418
  machineconfig/utils/schemas/repos/repos_types.py,sha256=beWlwPRNDBABmlzxHBYkAsMXS1MgFFdDZf4G2ge8J-I,408
415
- machineconfig-2.8.dist-info/METADATA,sha256=B7vcd_JlfLHIcqV3pv_-xqhDYVKyYpRdt4ikTWC0mA0,7137
416
- machineconfig-2.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
417
- machineconfig-2.8.dist-info/entry_points.txt,sha256=71EzS7_2LTIigVxC1YXNxHXhC9mu5Me2Feyq2KocXBI,977
418
- machineconfig-2.8.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
419
- machineconfig-2.8.dist-info/RECORD,,
419
+ machineconfig-2.9.dist-info/METADATA,sha256=7SpBqWO0al_Ce8zqCT2AyKdpFzT5bJ_7QvD_nMoK0qQ,7048
420
+ machineconfig-2.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
421
+ machineconfig-2.9.dist-info/entry_points.txt,sha256=71EzS7_2LTIigVxC1YXNxHXhC9mu5Me2Feyq2KocXBI,977
422
+ machineconfig-2.9.dist-info/top_level.txt,sha256=porRtB8qms8fOIUJgK-tO83_FeH6Bpe12oUVC670teA,14
423
+ machineconfig-2.9.dist-info/RECORD,,