clonebox 0.1.3__py3-none-any.whl → 0.1.5__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.
- clonebox/__main__.py +7 -0
- clonebox/cli.py +344 -273
- clonebox/cloner.py +142 -119
- clonebox/detector.py +186 -108
- {clonebox-0.1.3.dist-info → clonebox-0.1.5.dist-info}/METADATA +31 -2
- clonebox-0.1.5.dist-info/RECORD +11 -0
- clonebox-0.1.3.dist-info/RECORD +0 -10
- {clonebox-0.1.3.dist-info → clonebox-0.1.5.dist-info}/WHEEL +0 -0
- {clonebox-0.1.3.dist-info → clonebox-0.1.5.dist-info}/entry_points.txt +0 -0
- {clonebox-0.1.3.dist-info → clonebox-0.1.5.dist-info}/licenses/LICENSE +0 -0
- {clonebox-0.1.3.dist-info → clonebox-0.1.5.dist-info}/top_level.txt +0 -0
clonebox/detector.py
CHANGED
|
@@ -4,11 +4,10 @@ SystemDetector - Detects running services, applications and important paths.
|
|
|
4
4
|
"""
|
|
5
5
|
|
|
6
6
|
import os
|
|
7
|
-
import subprocess
|
|
8
7
|
import pwd
|
|
9
|
-
|
|
8
|
+
import subprocess
|
|
10
9
|
from dataclasses import dataclass, field
|
|
11
|
-
from
|
|
10
|
+
from pathlib import Path
|
|
12
11
|
|
|
13
12
|
import psutil
|
|
14
13
|
|
|
@@ -16,6 +15,7 @@ import psutil
|
|
|
16
15
|
@dataclass
|
|
17
16
|
class DetectedService:
|
|
18
17
|
"""A detected systemd service."""
|
|
18
|
+
|
|
19
19
|
name: str
|
|
20
20
|
status: str # running, stopped, failed
|
|
21
21
|
description: str = ""
|
|
@@ -25,6 +25,7 @@ class DetectedService:
|
|
|
25
25
|
@dataclass
|
|
26
26
|
class DetectedApplication:
|
|
27
27
|
"""A detected running application."""
|
|
28
|
+
|
|
28
29
|
name: str
|
|
29
30
|
pid: int
|
|
30
31
|
cmdline: str
|
|
@@ -36,6 +37,7 @@ class DetectedApplication:
|
|
|
36
37
|
@dataclass
|
|
37
38
|
class DetectedPath:
|
|
38
39
|
"""A detected important path."""
|
|
40
|
+
|
|
39
41
|
path: str
|
|
40
42
|
type: str # config, data, project, home
|
|
41
43
|
size_mb: float = 0.0
|
|
@@ -45,14 +47,15 @@ class DetectedPath:
|
|
|
45
47
|
@dataclass
|
|
46
48
|
class SystemSnapshot:
|
|
47
49
|
"""Complete snapshot of detected system state."""
|
|
50
|
+
|
|
48
51
|
services: list = field(default_factory=list)
|
|
49
52
|
applications: list = field(default_factory=list)
|
|
50
53
|
paths: list = field(default_factory=list)
|
|
51
|
-
|
|
54
|
+
|
|
52
55
|
@property
|
|
53
56
|
def running_services(self) -> list:
|
|
54
57
|
return [s for s in self.services if s.status == "running"]
|
|
55
|
-
|
|
58
|
+
|
|
56
59
|
@property
|
|
57
60
|
def running_apps(self) -> list:
|
|
58
61
|
return self.applications
|
|
@@ -60,43 +63,93 @@ class SystemSnapshot:
|
|
|
60
63
|
|
|
61
64
|
class SystemDetector:
|
|
62
65
|
"""Detects running services, applications and important paths on the system."""
|
|
63
|
-
|
|
66
|
+
|
|
64
67
|
# Common development/server services to look for
|
|
65
68
|
INTERESTING_SERVICES = [
|
|
66
|
-
"docker",
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
"
|
|
70
|
-
"
|
|
71
|
-
"
|
|
72
|
-
"
|
|
73
|
-
"
|
|
74
|
-
"
|
|
75
|
-
"
|
|
76
|
-
"
|
|
69
|
+
"docker",
|
|
70
|
+
"containerd",
|
|
71
|
+
"podman",
|
|
72
|
+
"nginx",
|
|
73
|
+
"apache2",
|
|
74
|
+
"httpd",
|
|
75
|
+
"caddy",
|
|
76
|
+
"postgresql",
|
|
77
|
+
"mysql",
|
|
78
|
+
"mariadb",
|
|
79
|
+
"mongodb",
|
|
80
|
+
"redis",
|
|
81
|
+
"memcached",
|
|
82
|
+
"elasticsearch",
|
|
83
|
+
"kibana",
|
|
84
|
+
"grafana",
|
|
85
|
+
"prometheus",
|
|
86
|
+
"jenkins",
|
|
87
|
+
"gitlab-runner",
|
|
88
|
+
"sshd",
|
|
89
|
+
"rsync",
|
|
90
|
+
"rabbitmq-server",
|
|
91
|
+
"kafka",
|
|
92
|
+
"nodejs",
|
|
93
|
+
"pm2",
|
|
94
|
+
"supervisor",
|
|
95
|
+
"systemd-resolved",
|
|
96
|
+
"cups",
|
|
97
|
+
"bluetooth",
|
|
98
|
+
"NetworkManager",
|
|
99
|
+
"libvirtd",
|
|
100
|
+
"virtlogd",
|
|
77
101
|
]
|
|
78
|
-
|
|
102
|
+
|
|
79
103
|
# Interesting process names
|
|
80
104
|
INTERESTING_PROCESSES = [
|
|
81
|
-
"python",
|
|
82
|
-
"
|
|
83
|
-
"
|
|
84
|
-
"
|
|
85
|
-
"
|
|
86
|
-
"
|
|
87
|
-
"
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
-
"
|
|
91
|
-
"
|
|
92
|
-
"
|
|
93
|
-
"
|
|
105
|
+
"python",
|
|
106
|
+
"python3",
|
|
107
|
+
"node",
|
|
108
|
+
"npm",
|
|
109
|
+
"yarn",
|
|
110
|
+
"pnpm",
|
|
111
|
+
"java",
|
|
112
|
+
"gradle",
|
|
113
|
+
"mvn",
|
|
114
|
+
"go",
|
|
115
|
+
"cargo",
|
|
116
|
+
"rustc",
|
|
117
|
+
"docker",
|
|
118
|
+
"docker-compose",
|
|
119
|
+
"podman",
|
|
120
|
+
"nginx",
|
|
121
|
+
"apache",
|
|
122
|
+
"httpd",
|
|
123
|
+
"postgres",
|
|
124
|
+
"mysql",
|
|
125
|
+
"mongod",
|
|
126
|
+
"redis-server",
|
|
127
|
+
"code",
|
|
128
|
+
"code-server",
|
|
129
|
+
"cursor",
|
|
130
|
+
"vim",
|
|
131
|
+
"nvim",
|
|
132
|
+
"emacs",
|
|
133
|
+
"firefox",
|
|
134
|
+
"chrome",
|
|
135
|
+
"chromium",
|
|
136
|
+
"jupyter",
|
|
137
|
+
"jupyter-lab",
|
|
138
|
+
"gunicorn",
|
|
139
|
+
"uvicorn",
|
|
140
|
+
"flask",
|
|
141
|
+
"django",
|
|
142
|
+
"webpack",
|
|
143
|
+
"vite",
|
|
144
|
+
"esbuild",
|
|
145
|
+
"tmux",
|
|
146
|
+
"screen",
|
|
94
147
|
]
|
|
95
|
-
|
|
148
|
+
|
|
96
149
|
def __init__(self):
|
|
97
150
|
self.user = pwd.getpwuid(os.getuid()).pw_name
|
|
98
151
|
self.home = Path.home()
|
|
99
|
-
|
|
152
|
+
|
|
100
153
|
def detect_all(self) -> SystemSnapshot:
|
|
101
154
|
"""Detect all services, applications and paths."""
|
|
102
155
|
return SystemSnapshot(
|
|
@@ -104,95 +157,104 @@ class SystemDetector:
|
|
|
104
157
|
applications=self.detect_applications(),
|
|
105
158
|
paths=self.detect_paths(),
|
|
106
159
|
)
|
|
107
|
-
|
|
160
|
+
|
|
108
161
|
def detect_services(self) -> list:
|
|
109
162
|
"""Detect systemd services."""
|
|
110
163
|
services = []
|
|
111
|
-
|
|
164
|
+
|
|
112
165
|
try:
|
|
113
166
|
# Get all services
|
|
114
167
|
result = subprocess.run(
|
|
115
168
|
["systemctl", "list-units", "--type=service", "--all", "--no-pager", "--plain"],
|
|
116
|
-
capture_output=True,
|
|
169
|
+
capture_output=True,
|
|
170
|
+
text=True,
|
|
171
|
+
timeout=10,
|
|
117
172
|
)
|
|
118
|
-
|
|
173
|
+
|
|
119
174
|
for line in result.stdout.strip().split("\n")[1:]: # Skip header
|
|
120
175
|
parts = line.split()
|
|
121
176
|
if len(parts) >= 4:
|
|
122
177
|
name = parts[0].replace(".service", "")
|
|
123
|
-
|
|
178
|
+
|
|
124
179
|
# Filter to interesting services
|
|
125
|
-
if any(
|
|
180
|
+
if any(
|
|
181
|
+
interesting in name.lower() for interesting in self.INTERESTING_SERVICES
|
|
182
|
+
):
|
|
126
183
|
status = "running" if parts[3] == "running" else parts[3]
|
|
127
|
-
|
|
184
|
+
|
|
128
185
|
# Get description
|
|
129
186
|
desc = " ".join(parts[4:]) if len(parts) > 4 else ""
|
|
130
|
-
|
|
187
|
+
|
|
131
188
|
# Check if enabled
|
|
132
189
|
enabled = False
|
|
133
190
|
try:
|
|
134
191
|
en_result = subprocess.run(
|
|
135
192
|
["systemctl", "is-enabled", name],
|
|
136
|
-
capture_output=True,
|
|
193
|
+
capture_output=True,
|
|
194
|
+
text=True,
|
|
195
|
+
timeout=5,
|
|
137
196
|
)
|
|
138
197
|
enabled = en_result.stdout.strip() == "enabled"
|
|
139
198
|
except:
|
|
140
199
|
pass
|
|
141
|
-
|
|
142
|
-
services.append(
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
))
|
|
200
|
+
|
|
201
|
+
services.append(
|
|
202
|
+
DetectedService(
|
|
203
|
+
name=name, status=status, description=desc, enabled=enabled
|
|
204
|
+
)
|
|
205
|
+
)
|
|
148
206
|
except Exception:
|
|
149
207
|
pass
|
|
150
|
-
|
|
208
|
+
|
|
151
209
|
return services
|
|
152
|
-
|
|
210
|
+
|
|
153
211
|
def detect_applications(self) -> list:
|
|
154
212
|
"""Detect running applications/processes."""
|
|
155
213
|
applications = []
|
|
156
214
|
seen_names = set()
|
|
157
|
-
|
|
158
|
-
for proc in psutil.process_iter([
|
|
215
|
+
|
|
216
|
+
for proc in psutil.process_iter(["pid", "name", "cmdline", "exe", "cwd", "memory_info"]):
|
|
159
217
|
try:
|
|
160
218
|
info = proc.info
|
|
161
|
-
name = info[
|
|
162
|
-
|
|
219
|
+
name = info["name"] or ""
|
|
220
|
+
|
|
163
221
|
# Filter to interesting processes
|
|
164
|
-
if not any(
|
|
222
|
+
if not any(
|
|
223
|
+
interesting in name.lower() for interesting in self.INTERESTING_PROCESSES
|
|
224
|
+
):
|
|
165
225
|
continue
|
|
166
|
-
|
|
226
|
+
|
|
167
227
|
# Skip duplicates by name (keep first)
|
|
168
228
|
if name in seen_names:
|
|
169
229
|
continue
|
|
170
230
|
seen_names.add(name)
|
|
171
|
-
|
|
172
|
-
cmdline = " ".join(info[
|
|
173
|
-
exe = info[
|
|
174
|
-
cwd = info[
|
|
175
|
-
mem = (info[
|
|
176
|
-
|
|
177
|
-
applications.append(
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
231
|
+
|
|
232
|
+
cmdline = " ".join(info["cmdline"] or [])[:200]
|
|
233
|
+
exe = info["exe"] or ""
|
|
234
|
+
cwd = info["cwd"] or ""
|
|
235
|
+
mem = (info["memory_info"].rss / 1024 / 1024) if info["memory_info"] else 0
|
|
236
|
+
|
|
237
|
+
applications.append(
|
|
238
|
+
DetectedApplication(
|
|
239
|
+
name=name,
|
|
240
|
+
pid=info["pid"],
|
|
241
|
+
cmdline=cmdline,
|
|
242
|
+
exe=exe,
|
|
243
|
+
working_dir=cwd,
|
|
244
|
+
memory_mb=round(mem, 1),
|
|
245
|
+
)
|
|
246
|
+
)
|
|
185
247
|
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
|
|
186
248
|
continue
|
|
187
|
-
|
|
249
|
+
|
|
188
250
|
# Sort by memory usage
|
|
189
251
|
applications.sort(key=lambda x: x.memory_mb, reverse=True)
|
|
190
252
|
return applications
|
|
191
|
-
|
|
253
|
+
|
|
192
254
|
def detect_paths(self) -> list:
|
|
193
255
|
"""Detect important paths (projects, configs, data)."""
|
|
194
256
|
paths = []
|
|
195
|
-
|
|
257
|
+
|
|
196
258
|
# User home subdirectories
|
|
197
259
|
important_home_dirs = [
|
|
198
260
|
("projects", "project"),
|
|
@@ -217,18 +279,20 @@ class SystemDetector:
|
|
|
217
279
|
("Documents", "data"),
|
|
218
280
|
("Downloads", "data"),
|
|
219
281
|
]
|
|
220
|
-
|
|
282
|
+
|
|
221
283
|
for dirname, path_type in important_home_dirs:
|
|
222
284
|
full_path = self.home / dirname
|
|
223
285
|
if full_path.exists() and full_path.is_dir():
|
|
224
286
|
size = self._get_dir_size(full_path, max_depth=1)
|
|
225
|
-
paths.append(
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
287
|
+
paths.append(
|
|
288
|
+
DetectedPath(
|
|
289
|
+
path=str(full_path),
|
|
290
|
+
type=path_type,
|
|
291
|
+
size_mb=round(size / 1024 / 1024, 1),
|
|
292
|
+
description=f"User {dirname}",
|
|
293
|
+
)
|
|
294
|
+
)
|
|
295
|
+
|
|
232
296
|
# System paths that might be interesting
|
|
233
297
|
system_paths = [
|
|
234
298
|
("/var/www", "data", "Web server root"),
|
|
@@ -239,21 +303,35 @@ class SystemDetector:
|
|
|
239
303
|
("/etc/nginx", "config", "Nginx config"),
|
|
240
304
|
("/etc/apache2", "config", "Apache config"),
|
|
241
305
|
]
|
|
242
|
-
|
|
306
|
+
|
|
243
307
|
for path, path_type, desc in system_paths:
|
|
244
308
|
p = Path(path)
|
|
245
309
|
if p.exists():
|
|
246
310
|
size = self._get_dir_size(p, max_depth=1)
|
|
247
|
-
paths.append(
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
311
|
+
paths.append(
|
|
312
|
+
DetectedPath(
|
|
313
|
+
path=path,
|
|
314
|
+
type=path_type,
|
|
315
|
+
size_mb=round(size / 1024 / 1024, 1),
|
|
316
|
+
description=desc,
|
|
317
|
+
)
|
|
318
|
+
)
|
|
319
|
+
|
|
254
320
|
# Detect project directories (with .git, package.json, etc.)
|
|
255
|
-
project_markers = [
|
|
256
|
-
|
|
321
|
+
project_markers = [
|
|
322
|
+
".git",
|
|
323
|
+
"package.json",
|
|
324
|
+
"Cargo.toml",
|
|
325
|
+
"go.mod",
|
|
326
|
+
"pyproject.toml",
|
|
327
|
+
"setup.py",
|
|
328
|
+
]
|
|
329
|
+
for search_dir in [
|
|
330
|
+
self.home / "projects",
|
|
331
|
+
self.home / "code",
|
|
332
|
+
self.home / "github",
|
|
333
|
+
self.home,
|
|
334
|
+
]:
|
|
257
335
|
if search_dir.exists():
|
|
258
336
|
for item in search_dir.iterdir():
|
|
259
337
|
if item.is_dir() and not item.name.startswith("."):
|
|
@@ -261,18 +339,20 @@ class SystemDetector:
|
|
|
261
339
|
if (item / marker).exists():
|
|
262
340
|
size = self._get_dir_size(item, max_depth=2)
|
|
263
341
|
if str(item) not in [p.path for p in paths]:
|
|
264
|
-
paths.append(
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
342
|
+
paths.append(
|
|
343
|
+
DetectedPath(
|
|
344
|
+
path=str(item),
|
|
345
|
+
type="project",
|
|
346
|
+
size_mb=round(size / 1024 / 1024, 1),
|
|
347
|
+
description=f"Project ({marker})",
|
|
348
|
+
)
|
|
349
|
+
)
|
|
270
350
|
break
|
|
271
|
-
|
|
351
|
+
|
|
272
352
|
# Sort by type then path
|
|
273
353
|
paths.sort(key=lambda x: (x.type, x.path))
|
|
274
354
|
return paths
|
|
275
|
-
|
|
355
|
+
|
|
276
356
|
def _get_dir_size(self, path: Path, max_depth: int = 2) -> int:
|
|
277
357
|
"""Get approximate directory size in bytes."""
|
|
278
358
|
total = 0
|
|
@@ -290,28 +370,26 @@ class SystemDetector:
|
|
|
290
370
|
except (PermissionError, FileNotFoundError, OSError):
|
|
291
371
|
pass
|
|
292
372
|
return total
|
|
293
|
-
|
|
373
|
+
|
|
294
374
|
def detect_docker_containers(self) -> list:
|
|
295
375
|
"""Detect running Docker containers."""
|
|
296
376
|
containers = []
|
|
297
377
|
try:
|
|
298
378
|
result = subprocess.run(
|
|
299
379
|
["docker", "ps", "--format", "{{.Names}}\t{{.Image}}\t{{.Status}}"],
|
|
300
|
-
capture_output=True,
|
|
380
|
+
capture_output=True,
|
|
381
|
+
text=True,
|
|
382
|
+
timeout=10,
|
|
301
383
|
)
|
|
302
384
|
for line in result.stdout.strip().split("\n"):
|
|
303
385
|
if line:
|
|
304
386
|
parts = line.split("\t")
|
|
305
387
|
if len(parts) >= 3:
|
|
306
|
-
containers.append({
|
|
307
|
-
"name": parts[0],
|
|
308
|
-
"image": parts[1],
|
|
309
|
-
"status": parts[2]
|
|
310
|
-
})
|
|
388
|
+
containers.append({"name": parts[0], "image": parts[1], "status": parts[2]})
|
|
311
389
|
except:
|
|
312
390
|
pass
|
|
313
391
|
return containers
|
|
314
|
-
|
|
392
|
+
|
|
315
393
|
def get_system_info(self) -> dict:
|
|
316
394
|
"""Get basic system information."""
|
|
317
395
|
return {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: clonebox
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.5
|
|
4
4
|
Summary: Clone your workstation environment to an isolated VM with selective apps, paths and services
|
|
5
5
|
Author: CloneBox Team
|
|
6
6
|
License: Apache-2.0
|
|
@@ -291,6 +291,29 @@ clonebox detect --yaml --dedupe
|
|
|
291
291
|
clonebox detect --yaml --dedupe -o my-config.yaml
|
|
292
292
|
```
|
|
293
293
|
|
|
294
|
+
### User Session & Networking
|
|
295
|
+
|
|
296
|
+
CloneBox supports creating VMs in user session (no root required) with automatic network fallback:
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
# Create VM in user session (uses ~/.local/share/libvirt/images)
|
|
300
|
+
clonebox clone . --user
|
|
301
|
+
|
|
302
|
+
# Explicitly use user-mode networking (slirp) - works without libvirt network
|
|
303
|
+
clonebox clone . --user --network user
|
|
304
|
+
|
|
305
|
+
# Force libvirt default network (may fail in user session)
|
|
306
|
+
clonebox clone . --network default
|
|
307
|
+
|
|
308
|
+
# Auto mode (default): tries libvirt network, falls back to user-mode if unavailable
|
|
309
|
+
clonebox clone . --network auto
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
**Network modes:**
|
|
313
|
+
- `auto` (default): Uses libvirt default network if available, otherwise falls back to user-mode (slirp)
|
|
314
|
+
- `default`: Forces use of libvirt default network
|
|
315
|
+
- `user`: Uses user-mode networking (slirp) - no bridge setup required
|
|
316
|
+
|
|
294
317
|
## Commands Reference
|
|
295
318
|
|
|
296
319
|
| Command | Description |
|
|
@@ -299,6 +322,9 @@ clonebox detect --yaml --dedupe -o my-config.yaml
|
|
|
299
322
|
| `clonebox clone <path>` | Generate `.clonebox.yaml` from path + running processes |
|
|
300
323
|
| `clonebox clone . --run` | Clone and immediately start VM |
|
|
301
324
|
| `clonebox clone . --edit` | Clone, edit config, then create |
|
|
325
|
+
| `clonebox clone . --user` | Clone in user session (no root) |
|
|
326
|
+
| `clonebox clone . --network user` | Use user-mode networking (slirp) |
|
|
327
|
+
| `clonebox clone . --network auto` | Auto-detect network mode (default) |
|
|
302
328
|
| `clonebox start .` | Start VM from `.clonebox.yaml` in current dir |
|
|
303
329
|
| `clonebox start <name>` | Start existing VM by name |
|
|
304
330
|
| `clonebox stop <name>` | Stop a VM (graceful shutdown) |
|
|
@@ -324,7 +350,10 @@ clonebox detect --yaml --dedupe -o my-config.yaml
|
|
|
324
350
|
If you encounter "Network not found" or "network 'default' is not active" errors:
|
|
325
351
|
|
|
326
352
|
```bash
|
|
327
|
-
#
|
|
353
|
+
# Option 1: Use user-mode networking (no setup required)
|
|
354
|
+
clonebox clone . --user --network user
|
|
355
|
+
|
|
356
|
+
# Option 2: Run the network fix script
|
|
328
357
|
./fix-network.sh
|
|
329
358
|
|
|
330
359
|
# Or manually fix:
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
clonebox/__init__.py,sha256=IOk7G0DiSQ33EGbFC0xbnnFB9aou_6yuyFxvycQEvA0,407
|
|
2
|
+
clonebox/__main__.py,sha256=Fcoyzwwyz5-eC_sBlQk5a5RbKx8uodQz5sKJ190U0NU,135
|
|
3
|
+
clonebox/cli.py,sha256=TROvvv2BtUqKp5osXVUBvmPAdYTeTf0M-e69YaYQp78,32700
|
|
4
|
+
clonebox/cloner.py,sha256=Uoh9mCUX-3p2tFL_3qlf2R2232JCXO5YhWrgKTpEr0s,19369
|
|
5
|
+
clonebox/detector.py,sha256=jkzENmi4720n5e04k6gM7MNvXbQdYX-z1_O3Id0WK9w,12505
|
|
6
|
+
clonebox-0.1.5.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
7
|
+
clonebox-0.1.5.dist-info/METADATA,sha256=WWS_bye_xkDuWeJSfOMk7BDaDcL1rfE4RtZiKNlO1nA,13126
|
|
8
|
+
clonebox-0.1.5.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
9
|
+
clonebox-0.1.5.dist-info/entry_points.txt,sha256=FES95Vi3btfViLEEoHdb8nikNxTqzaooi9ehZw9ZfWI,47
|
|
10
|
+
clonebox-0.1.5.dist-info/top_level.txt,sha256=LdMo2cvCrEcRGH2M8JgQNVsCoszLV0xug6kx1JnaRjo,9
|
|
11
|
+
clonebox-0.1.5.dist-info/RECORD,,
|
clonebox-0.1.3.dist-info/RECORD
DELETED
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
clonebox/__init__.py,sha256=IOk7G0DiSQ33EGbFC0xbnnFB9aou_6yuyFxvycQEvA0,407
|
|
2
|
-
clonebox/cli.py,sha256=tg_tinIH3D6Q1xAjhXu7P4msl2XcxLo8XUHMDxkOFis,31996
|
|
3
|
-
clonebox/cloner.py,sha256=bB37BFYY7_xlfOSdk05zrUsrw7ewItRBMb7EJkYFA_0,19671
|
|
4
|
-
clonebox/detector.py,sha256=Umg4CRJU61yV3a1AvR_0tOfjBMCCIbiQdDAAhlrOL5k,11916
|
|
5
|
-
clonebox-0.1.3.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
|
6
|
-
clonebox-0.1.3.dist-info/METADATA,sha256=W6d_Km3nbulNWpl5Z6KctOHciT1o14o4OnAELJMAfbc,11996
|
|
7
|
-
clonebox-0.1.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
8
|
-
clonebox-0.1.3.dist-info/entry_points.txt,sha256=FES95Vi3btfViLEEoHdb8nikNxTqzaooi9ehZw9ZfWI,47
|
|
9
|
-
clonebox-0.1.3.dist-info/top_level.txt,sha256=LdMo2cvCrEcRGH2M8JgQNVsCoszLV0xug6kx1JnaRjo,9
|
|
10
|
-
clonebox-0.1.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|