clonebox 1.1.17__py3-none-any.whl → 1.1.18__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 clonebox might be problematic. Click here for more details.
- clonebox/cli.py +12 -0
- clonebox/cloner.py +36 -13
- clonebox/validator.py +163 -28
- {clonebox-1.1.17.dist-info → clonebox-1.1.18.dist-info}/METADATA +1 -1
- {clonebox-1.1.17.dist-info → clonebox-1.1.18.dist-info}/RECORD +9 -9
- {clonebox-1.1.17.dist-info → clonebox-1.1.18.dist-info}/WHEEL +0 -0
- {clonebox-1.1.17.dist-info → clonebox-1.1.18.dist-info}/entry_points.txt +0 -0
- {clonebox-1.1.17.dist-info → clonebox-1.1.18.dist-info}/licenses/LICENSE +0 -0
- {clonebox-1.1.17.dist-info → clonebox-1.1.18.dist-info}/top_level.txt +0 -0
clonebox/cli.py
CHANGED
|
@@ -2498,6 +2498,18 @@ def monitor_cloud_init_status(vm_name: str, user_session: bool = False, timeout:
|
|
|
2498
2498
|
"grep -E '\\[[0-9]/[0-9]\\]|→' /var/log/cloud-init-output.log 2>/dev/null | tail -n 5"
|
|
2499
2499
|
)
|
|
2500
2500
|
|
|
2501
|
+
# Check disk space in real-time
|
|
2502
|
+
disk_info = _exec_in_vm_qga(
|
|
2503
|
+
vm_name,
|
|
2504
|
+
conn_uri,
|
|
2505
|
+
"df / --output=pcent | tail -n 1 | tr -dc '0-9'"
|
|
2506
|
+
)
|
|
2507
|
+
if disk_info and disk_info.isdigit():
|
|
2508
|
+
usage = int(disk_info)
|
|
2509
|
+
if usage > 90:
|
|
2510
|
+
console.print(f"[bold red]⚠️ WARNING: VM Disk is nearly full ({usage}%)![/]")
|
|
2511
|
+
console.print("[red] Installation may fail. Consider increasing --disk-size-gb.[/]")
|
|
2512
|
+
|
|
2501
2513
|
if raw_info:
|
|
2502
2514
|
lines = [l.strip() for l in raw_info.strip().split('\n') if l.strip()]
|
|
2503
2515
|
for line in lines:
|
clonebox/cloner.py
CHANGED
|
@@ -1124,7 +1124,7 @@ fi
|
|
|
1124
1124
|
mount_checks.append(f'check_mount "{guest_path}" "mount{idx}"')
|
|
1125
1125
|
|
|
1126
1126
|
# Add copied paths checks
|
|
1127
|
-
copy_paths = config.copy_paths or config
|
|
1127
|
+
copy_paths = config.copy_paths or getattr(config, "app_data_paths", {})
|
|
1128
1128
|
if copy_paths:
|
|
1129
1129
|
for idx, (host_path, guest_path) in enumerate(copy_paths.items()):
|
|
1130
1130
|
mount_checks.append(f'check_copy_path "{guest_path}"')
|
|
@@ -1161,6 +1161,27 @@ log() {{
|
|
|
1161
1161
|
echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" | tee -a "$REPORT_FILE"
|
|
1162
1162
|
}}
|
|
1163
1163
|
|
|
1164
|
+
check_disk_space() {{
|
|
1165
|
+
local usage
|
|
1166
|
+
usage=$(df / --output=pcent | tail -n 1 | tr -dc '0-9')
|
|
1167
|
+
local avail
|
|
1168
|
+
avail=$(df -h / --output=avail | tail -n 1 | tr -d ' ')
|
|
1169
|
+
|
|
1170
|
+
if [ "$usage" -gt 95 ]; then
|
|
1171
|
+
log "[FAIL] Disk space nearly full: ${{usage}}% used ($avail available)"
|
|
1172
|
+
((FAILED++))
|
|
1173
|
+
return 1
|
|
1174
|
+
elif [ "$usage" -gt 85 ]; then
|
|
1175
|
+
log "[WARN] Disk usage high: ${{usage}}% used ($avail available)"
|
|
1176
|
+
((WARNINGS++))
|
|
1177
|
+
return 0
|
|
1178
|
+
else
|
|
1179
|
+
log "[PASS] Disk space OK: ${{usage}}% used ($avail available)"
|
|
1180
|
+
((PASSED++))
|
|
1181
|
+
return 0
|
|
1182
|
+
fi
|
|
1183
|
+
}}
|
|
1184
|
+
|
|
1164
1185
|
check_apt_package() {{
|
|
1165
1186
|
local pkg="$1"
|
|
1166
1187
|
if dpkg -l "$pkg" 2>/dev/null | grep -q "^ii"; then
|
|
@@ -1283,6 +1304,11 @@ log "VM Name: {config.name}"
|
|
|
1283
1304
|
log "Date: $(date)"
|
|
1284
1305
|
log "=========================================="
|
|
1285
1306
|
|
|
1307
|
+
log ""
|
|
1308
|
+
log "--- System Health ---"
|
|
1309
|
+
check_disk_space
|
|
1310
|
+
check_gui
|
|
1311
|
+
|
|
1286
1312
|
log ""
|
|
1287
1313
|
log "--- APT Packages ---"
|
|
1288
1314
|
{apt_checks_str}
|
|
@@ -1507,7 +1533,8 @@ fi
|
|
|
1507
1533
|
for i, pkg in enumerate(all_packages, 1):
|
|
1508
1534
|
runcmd_lines.append(f" - echo ' → [{i}/{len(all_packages)}] Installing {pkg}...'")
|
|
1509
1535
|
runcmd_lines.append(f" - apt-get install -y {pkg} || echo ' ⚠️ Failed to install {pkg}'")
|
|
1510
|
-
runcmd_lines.append(" -
|
|
1536
|
+
runcmd_lines.append(" - apt-get clean")
|
|
1537
|
+
runcmd_lines.append(" - echo ' ✓ APT packages installed and cache cleaned'")
|
|
1511
1538
|
runcmd_lines.append(" - echo ''")
|
|
1512
1539
|
else:
|
|
1513
1540
|
runcmd_lines.append(" - echo '[1/9] 📦 No APT packages to install'")
|
|
@@ -2454,25 +2481,21 @@ if __name__ == "__main__":
|
|
|
2454
2481
|
# Note: The bash monitor is already installed above, no need to install Python monitor
|
|
2455
2482
|
|
|
2456
2483
|
# Create logs disk for host access
|
|
2457
|
-
#
|
|
2458
|
-
|
|
2459
|
-
logs_disk_path = str(Path.home() / ".local/share/libvirt/images/clonebox-logs.qcow2")
|
|
2460
|
-
else:
|
|
2461
|
-
logs_disk_path = "/var/lib/libvirt/images/clonebox-logs.qcow2"
|
|
2484
|
+
# Inside the VM, we use a fixed path for the image file
|
|
2485
|
+
vm_logs_img_path = "/var/lib/clonebox/logs.img"
|
|
2462
2486
|
|
|
2463
2487
|
runcmd_lines.extend(
|
|
2464
2488
|
[
|
|
2465
|
-
" - mkdir -p /mnt/logs",
|
|
2466
|
-
f" - truncate -s 1G {
|
|
2467
|
-
f" - mkfs.ext4 -F {
|
|
2468
|
-
f" - echo '{
|
|
2489
|
+
" - mkdir -p /var/lib/clonebox /mnt/logs",
|
|
2490
|
+
f" - truncate -s 1G {vm_logs_img_path}",
|
|
2491
|
+
f" - mkfs.ext4 -F {vm_logs_img_path}",
|
|
2492
|
+
f" - echo '{vm_logs_img_path} /mnt/logs ext4 loop,defaults 0 0' >> /etc/fstab",
|
|
2469
2493
|
" - mount -a",
|
|
2470
2494
|
" - mkdir -p /mnt/logs/var/log",
|
|
2471
2495
|
" - mkdir -p /mnt/logs/tmp",
|
|
2472
2496
|
" - cp -r /var/log/clonebox*.log /mnt/logs/var/log/ 2>/dev/null || true",
|
|
2473
2497
|
" - cp -r /tmp/*-error.log /mnt/logs/tmp/ 2>/dev/null || true",
|
|
2474
|
-
f" - echo 'Logs disk mounted at /mnt/logs -
|
|
2475
|
-
f" - \"echo 'To view logs on host: sudo mount -o loop {logs_disk_path} /mnt/clonebox-logs'\"",
|
|
2498
|
+
f" - echo 'Logs disk mounted at /mnt/logs - backing file: {vm_logs_img_path}'",
|
|
2476
2499
|
]
|
|
2477
2500
|
)
|
|
2478
2501
|
|
clonebox/validator.py
CHANGED
|
@@ -76,39 +76,38 @@ class VMValidator:
|
|
|
76
76
|
|
|
77
77
|
pid = response["return"]["pid"]
|
|
78
78
|
|
|
79
|
-
|
|
80
|
-
time.
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
timeout=5,
|
|
95
|
-
)
|
|
79
|
+
deadline = time.time() + timeout
|
|
80
|
+
while time.time() < deadline:
|
|
81
|
+
status_result = subprocess.run(
|
|
82
|
+
[
|
|
83
|
+
"virsh",
|
|
84
|
+
"--connect",
|
|
85
|
+
self.conn_uri,
|
|
86
|
+
"qemu-agent-command",
|
|
87
|
+
self.vm_name,
|
|
88
|
+
f'{{"execute":"guest-exec-status","arguments":{{"pid":{pid}}}}}',
|
|
89
|
+
],
|
|
90
|
+
capture_output=True,
|
|
91
|
+
text=True,
|
|
92
|
+
timeout=5,
|
|
93
|
+
)
|
|
96
94
|
|
|
97
|
-
|
|
98
|
-
|
|
95
|
+
if status_result.returncode != 0:
|
|
96
|
+
return None
|
|
99
97
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
98
|
+
status_resp = json.loads(status_result.stdout)
|
|
99
|
+
if "return" not in status_resp:
|
|
100
|
+
return None
|
|
103
101
|
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
ret = status_resp["return"]
|
|
103
|
+
if ret.get("exited", False):
|
|
104
|
+
if "out-data" in ret:
|
|
105
|
+
return base64.b64decode(ret["out-data"]).decode().strip()
|
|
106
|
+
return ""
|
|
107
107
|
|
|
108
|
-
|
|
109
|
-
return base64.b64decode(ret["out-data"]).decode().strip()
|
|
108
|
+
time.sleep(0.2)
|
|
110
109
|
|
|
111
|
-
return
|
|
110
|
+
return None
|
|
112
111
|
|
|
113
112
|
except Exception:
|
|
114
113
|
return None
|
|
@@ -397,6 +396,8 @@ class VMValidator:
|
|
|
397
396
|
svc_table.add_column("PID", justify="right", style="dim")
|
|
398
397
|
svc_table.add_column("Note", style="dim")
|
|
399
398
|
|
|
399
|
+
setup_in_progress = self._setup_in_progress() is True
|
|
400
|
+
|
|
400
401
|
for service in services:
|
|
401
402
|
if service in self.VM_EXCLUDED_SERVICES:
|
|
402
403
|
svc_table.add_row(service, "[dim]—[/]", "[dim]—[/]", "[dim]—[/]", "host-only")
|
|
@@ -413,6 +414,7 @@ class VMValidator:
|
|
|
413
414
|
continue
|
|
414
415
|
|
|
415
416
|
self.results["services"]["total"] += 1
|
|
417
|
+
setup_in_progress = self._setup_in_progress() is True
|
|
416
418
|
|
|
417
419
|
enabled_cmd = f"systemctl is-enabled {service} 2>/dev/null"
|
|
418
420
|
enabled_status = self._exec_in_vm(enabled_cmd)
|
|
@@ -970,6 +972,138 @@ class VMValidator:
|
|
|
970
972
|
except Exception:
|
|
971
973
|
return False
|
|
972
974
|
|
|
975
|
+
def validate_disk_space(self) -> Dict:
|
|
976
|
+
"""Validate disk space on root filesystem."""
|
|
977
|
+
self.console.print("\n[bold]💾 Validating Disk Space...[/]")
|
|
978
|
+
|
|
979
|
+
df_output = self._exec_in_vm("df -h / --output=pcent,avail,size | tail -n 1", timeout=20)
|
|
980
|
+
if not df_output:
|
|
981
|
+
self.console.print("[red]❌ Could not check disk space[/]")
|
|
982
|
+
return {"status": "error"}
|
|
983
|
+
|
|
984
|
+
try:
|
|
985
|
+
# Format: pcent avail size
|
|
986
|
+
# Example: 98% 100M 30G
|
|
987
|
+
parts = df_output.split()
|
|
988
|
+
usage_pct = int(parts[0].replace('%', ''))
|
|
989
|
+
avail = parts[1]
|
|
990
|
+
total = parts[2]
|
|
991
|
+
|
|
992
|
+
self.results["disk"] = {
|
|
993
|
+
"usage_pct": usage_pct,
|
|
994
|
+
"avail": avail,
|
|
995
|
+
"total": total
|
|
996
|
+
}
|
|
997
|
+
|
|
998
|
+
if usage_pct > 95:
|
|
999
|
+
self.console.print(f"[red]❌ Disk nearly full: {usage_pct}% used ({avail} available of {total})[/]")
|
|
1000
|
+
status = "fail"
|
|
1001
|
+
elif usage_pct > 80:
|
|
1002
|
+
self.console.print(f"[yellow]⚠️ Disk usage high: {usage_pct}% used ({avail} available of {total})[/]")
|
|
1003
|
+
status = "warning"
|
|
1004
|
+
else:
|
|
1005
|
+
self.console.print(f"[green]✅ Disk space OK: {usage_pct}% used ({avail} available of {total})[/]")
|
|
1006
|
+
status = "pass"
|
|
1007
|
+
|
|
1008
|
+
if usage_pct > 80:
|
|
1009
|
+
self._print_disk_usage_breakdown()
|
|
1010
|
+
|
|
1011
|
+
return self.results["disk"]
|
|
1012
|
+
except Exception as e:
|
|
1013
|
+
self.console.print(f"[red]❌ Error parsing df output: {e}[/]")
|
|
1014
|
+
return {"status": "error"}
|
|
1015
|
+
|
|
1016
|
+
def _print_disk_usage_breakdown(self) -> None:
|
|
1017
|
+
def _parse_du_lines(out: Optional[str]) -> List[Tuple[str, str]]:
|
|
1018
|
+
if not out:
|
|
1019
|
+
return []
|
|
1020
|
+
rows: List[Tuple[str, str]] = []
|
|
1021
|
+
for line in out.splitlines():
|
|
1022
|
+
line = line.strip()
|
|
1023
|
+
if not line:
|
|
1024
|
+
continue
|
|
1025
|
+
parts = line.split(maxsplit=1)
|
|
1026
|
+
if len(parts) != 2:
|
|
1027
|
+
continue
|
|
1028
|
+
size, path = parts
|
|
1029
|
+
rows.append((path, size))
|
|
1030
|
+
return rows
|
|
1031
|
+
|
|
1032
|
+
def _dir_size(path: str, timeout: int = 30) -> Optional[str]:
|
|
1033
|
+
out = self._exec_in_vm(f"du -x -s -h {path} 2>/dev/null | head -n 1 | cut -f1", timeout=timeout)
|
|
1034
|
+
return out.strip() if out else None
|
|
1035
|
+
|
|
1036
|
+
self.console.print("\n[bold]📁 Disk usage breakdown (largest directories)[/]")
|
|
1037
|
+
|
|
1038
|
+
top_level = self._exec_in_vm(
|
|
1039
|
+
"du -x -h --max-depth=1 / 2>/dev/null | sort -hr | head -n 15",
|
|
1040
|
+
timeout=60,
|
|
1041
|
+
)
|
|
1042
|
+
top_rows = _parse_du_lines(top_level)
|
|
1043
|
+
|
|
1044
|
+
if top_rows:
|
|
1045
|
+
table = Table(title="Disk Usage: / (Top 15)", border_style="cyan")
|
|
1046
|
+
table.add_column("Path", style="bold")
|
|
1047
|
+
table.add_column("Size", justify="right")
|
|
1048
|
+
for path, size in top_rows:
|
|
1049
|
+
table.add_row(path, size)
|
|
1050
|
+
self.console.print(table)
|
|
1051
|
+
else:
|
|
1052
|
+
self.console.print("[dim]Could not compute top-level directory sizes (du may be busy)[/]")
|
|
1053
|
+
|
|
1054
|
+
var_sz = _dir_size("/var")
|
|
1055
|
+
home_sz = _dir_size("/home")
|
|
1056
|
+
if var_sz or home_sz:
|
|
1057
|
+
sum_table = Table(title="Disk Usage: Key Directories", border_style="cyan")
|
|
1058
|
+
sum_table.add_column("Path", style="bold")
|
|
1059
|
+
sum_table.add_column("Size", justify="right")
|
|
1060
|
+
for p in ["/var", "/var/lib", "/var/log", "/var/cache", "/var/lib/snapd", "/home", "/home/ubuntu", "/tmp"]:
|
|
1061
|
+
sz = _dir_size(p, timeout=30)
|
|
1062
|
+
if sz:
|
|
1063
|
+
sum_table.add_row(p, sz)
|
|
1064
|
+
self.console.print(sum_table)
|
|
1065
|
+
|
|
1066
|
+
var_breakdown = self._exec_in_vm(
|
|
1067
|
+
"du -x -h --max-depth=1 /var 2>/dev/null | sort -hr | head -n 12",
|
|
1068
|
+
timeout=60,
|
|
1069
|
+
)
|
|
1070
|
+
var_rows = _parse_du_lines(var_breakdown)
|
|
1071
|
+
if var_rows:
|
|
1072
|
+
vtable = Table(title="Disk Usage: /var (Top 12)", border_style="cyan")
|
|
1073
|
+
vtable.add_column("Path", style="bold")
|
|
1074
|
+
vtable.add_column("Size", justify="right")
|
|
1075
|
+
for path, size in var_rows:
|
|
1076
|
+
vtable.add_row(path, size)
|
|
1077
|
+
self.console.print(vtable)
|
|
1078
|
+
|
|
1079
|
+
home_breakdown = self._exec_in_vm(
|
|
1080
|
+
"du -x -h --max-depth=2 /home/ubuntu 2>/dev/null | sort -hr | head -n 12",
|
|
1081
|
+
timeout=60,
|
|
1082
|
+
)
|
|
1083
|
+
home_rows = _parse_du_lines(home_breakdown)
|
|
1084
|
+
if home_rows:
|
|
1085
|
+
htable = Table(title="Disk Usage: /home/ubuntu (Top 12)", border_style="cyan")
|
|
1086
|
+
htable.add_column("Path", style="bold")
|
|
1087
|
+
htable.add_column("Size", justify="right")
|
|
1088
|
+
for path, size in home_rows:
|
|
1089
|
+
htable.add_row(path, size)
|
|
1090
|
+
self.console.print(htable)
|
|
1091
|
+
|
|
1092
|
+
copy_paths = self.config.get("copy_paths", None)
|
|
1093
|
+
if not isinstance(copy_paths, dict) or not copy_paths:
|
|
1094
|
+
copy_paths = self.config.get("app_data_paths", {})
|
|
1095
|
+
if copy_paths:
|
|
1096
|
+
ctable = Table(title="Disk Usage: Configured Imported Paths", border_style="cyan")
|
|
1097
|
+
ctable.add_column("Guest Path", style="bold")
|
|
1098
|
+
ctable.add_column("Size", justify="right")
|
|
1099
|
+
for _, guest_path in copy_paths.items():
|
|
1100
|
+
sz = _dir_size(guest_path, timeout=30)
|
|
1101
|
+
if sz:
|
|
1102
|
+
ctable.add_row(str(guest_path), sz)
|
|
1103
|
+
else:
|
|
1104
|
+
ctable.add_row(str(guest_path), "—")
|
|
1105
|
+
self.console.print(ctable)
|
|
1106
|
+
|
|
973
1107
|
def validate_all(self) -> Dict:
|
|
974
1108
|
"""Run all validations and return comprehensive results."""
|
|
975
1109
|
self.console.print("[bold cyan]🔍 Running Full Validation...[/]")
|
|
@@ -1026,6 +1160,7 @@ class VMValidator:
|
|
|
1026
1160
|
)
|
|
1027
1161
|
|
|
1028
1162
|
# Run all validations
|
|
1163
|
+
self.validate_disk_space()
|
|
1029
1164
|
self.validate_mounts()
|
|
1030
1165
|
self.validate_packages()
|
|
1031
1166
|
self.validate_snap_packages()
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
clonebox/__init__.py,sha256=CyfHVVq6KqBr4CNERBpXk_O6Q5B35q03YpdQbokVvvI,408
|
|
2
2
|
clonebox/__main__.py,sha256=Fcoyzwwyz5-eC_sBlQk5a5RbKx8uodQz5sKJ190U0NU,135
|
|
3
3
|
clonebox/audit.py,sha256=1W9vaIjB0A--_p7CgE3cIP5RNckJG1RxJrL-tOb-QmU,14298
|
|
4
|
-
clonebox/cli.py,sha256=
|
|
5
|
-
clonebox/cloner.py,sha256=
|
|
4
|
+
clonebox/cli.py,sha256=x0VQ9WI1KZrNQGAh7FDf_036jDypdT5Q7vuTlr-dgi0,179087
|
|
5
|
+
clonebox/cloner.py,sha256=WEMNjhHVdXwiA2zCq14fr5eVD6vhLuX4vnJ47p3SiNI,107839
|
|
6
6
|
clonebox/container.py,sha256=tiYK1ZB-DhdD6A2FuMA0h_sRNkUI7KfYcJ0tFOcdyeM,6105
|
|
7
7
|
clonebox/dashboard.py,sha256=dMY6odvPq3j6FronhRRsX7aY3qdCwznB-aCWKEmHDNw,5768
|
|
8
8
|
clonebox/detector.py,sha256=vS65cvFNPmUBCX1Y_TMTnSRljw6r1Ae9dlVtACs5XFc,23075
|
|
@@ -20,7 +20,7 @@ clonebox/resource_monitor.py,sha256=lDR9KyPbVtImeeOkOBPPVP-5yCgoL5hsVFPZ_UqsY0w,
|
|
|
20
20
|
clonebox/resources.py,sha256=IkuM4OdSDV4qhyc0eIynwbAHBTv0aVSxxW-gghsnCAs,6815
|
|
21
21
|
clonebox/rollback.py,sha256=hpwO-8Ehe1pW0wHuZvJkC_qxZ6yEo9otCJRhGIUArCo,5711
|
|
22
22
|
clonebox/secrets.py,sha256=l1jwJcEPB1qMoGNLPjyrkKKr1khh9VmftFJI9BWhgK0,10628
|
|
23
|
-
clonebox/validator.py,sha256=
|
|
23
|
+
clonebox/validator.py,sha256=PWPgkR9cjewTh6-uW_2YyjxuEj2wI9O7h7hk7NK8nAI,51181
|
|
24
24
|
clonebox/backends/libvirt_backend.py,sha256=sIHFIvFO1hIOXEFR_foSkOGBgIzaJVQs-njOU8GdafA,7170
|
|
25
25
|
clonebox/backends/qemu_disk.py,sha256=YsGjYX5sbEf35Y4yjTpNkZat73a4RGBxY-KTVzJhqIs,1687
|
|
26
26
|
clonebox/backends/subprocess_runner.py,sha256=c-IyaMxM1cmUu64h654oAvulm83K5Mu-VQxXJ_0BOds,1506
|
|
@@ -40,9 +40,9 @@ clonebox/snapshots/manager.py,sha256=hGzM8V6ZJPXjTqj47c4Kr8idlE-c1Q3gPUvuw1HvS1A
|
|
|
40
40
|
clonebox/snapshots/models.py,sha256=sRnn3OZE8JG9FZJlRuA3ihO-JXoPCQ3nD3SQytflAao,6206
|
|
41
41
|
clonebox/templates/profiles/ml-dev.yaml,sha256=w07MToGh31xtxpjbeXTBk9BkpAN8A3gv8HeA3ESKG9M,461
|
|
42
42
|
clonebox/templates/profiles/web-stack.yaml,sha256=EBnnGMzML5vAjXmIUbCpbTCwmRaNJiuWd3EcL43DOK8,485
|
|
43
|
-
clonebox-1.1.
|
|
44
|
-
clonebox-1.1.
|
|
45
|
-
clonebox-1.1.
|
|
46
|
-
clonebox-1.1.
|
|
47
|
-
clonebox-1.1.
|
|
48
|
-
clonebox-1.1.
|
|
43
|
+
clonebox-1.1.18.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
44
|
+
clonebox-1.1.18.dist-info/METADATA,sha256=n1VJE8-Mk-zf9QgHBbvt1Z5fbJMdpD1vjZVVjEBeaxE,49052
|
|
45
|
+
clonebox-1.1.18.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
46
|
+
clonebox-1.1.18.dist-info/entry_points.txt,sha256=FES95Vi3btfViLEEoHdb8nikNxTqzaooi9ehZw9ZfWI,47
|
|
47
|
+
clonebox-1.1.18.dist-info/top_level.txt,sha256=LdMo2cvCrEcRGH2M8JgQNVsCoszLV0xug6kx1JnaRjo,9
|
|
48
|
+
clonebox-1.1.18.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|