pluck-cli 0.1.0__tar.gz → 0.2.1__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.
- {pluck_cli-0.1.0/src/pluck_cli.egg-info → pluck_cli-0.2.1}/PKG-INFO +15 -7
- {pluck_cli-0.1.0 → pluck_cli-0.2.1}/README.md +13 -5
- {pluck_cli-0.1.0 → pluck_cli-0.2.1}/pyproject.toml +2 -2
- {pluck_cli-0.1.0 → pluck_cli-0.2.1}/src/gh_install.py +30 -20
- {pluck_cli-0.1.0 → pluck_cli-0.2.1/src/pluck_cli.egg-info}/PKG-INFO +15 -7
- {pluck_cli-0.1.0 → pluck_cli-0.2.1}/tests/test_gh_install.py +10 -10
- {pluck_cli-0.1.0 → pluck_cli-0.2.1}/LICENSE +0 -0
- {pluck_cli-0.1.0 → pluck_cli-0.2.1}/setup.cfg +0 -0
- {pluck_cli-0.1.0 → pluck_cli-0.2.1}/src/pluck_cli.egg-info/SOURCES.txt +0 -0
- {pluck_cli-0.1.0 → pluck_cli-0.2.1}/src/pluck_cli.egg-info/dependency_links.txt +0 -0
- {pluck_cli-0.1.0 → pluck_cli-0.2.1}/src/pluck_cli.egg-info/entry_points.txt +0 -0
- {pluck_cli-0.1.0 → pluck_cli-0.2.1}/src/pluck_cli.egg-info/top_level.txt +0 -0
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pluck-cli
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Pluck any git repo from any forge — auto-detect, auto-install, done!
|
|
5
5
|
Author: pluck contributors
|
|
6
|
-
License
|
|
6
|
+
License: MIT
|
|
7
7
|
Keywords: git,forge,installer,cli,github,gitlab,codeberg
|
|
8
8
|
Classifier: Development Status :: 3 - Alpha
|
|
9
9
|
Classifier: Environment :: Console
|
|
@@ -36,7 +36,9 @@ Dynamic: license-file
|
|
|
36
36
|
<img src="https://img.shields.io/badge/Dependencies-Zero-brightgreen" alt="Zero dependencies">
|
|
37
37
|
<img src="https://img.shields.io/badge/Tests-111%20passing-brightgreen" alt="111 passing tests">
|
|
38
38
|
<img src="https://img.shields.io/badge/Forges-11%20supported-blue" alt="11 forges supported">
|
|
39
|
+
<img src="https://img.shields.io/badge/PyPI-pluck--cli-blue?logo=pypi" alt="PyPI: pluck-cli">
|
|
39
40
|
<img src="https://img.shields.io/badge/Code%20style-ruff-EF5552" alt="Code style: ruff">
|
|
41
|
+
<img src="https://gitlab.com/mabodu/pluck/badges/main/pipeline.svg" alt="GitLab CI">
|
|
40
42
|
</p>
|
|
41
43
|
|
|
42
44
|
---
|
|
@@ -138,6 +140,10 @@ pluck install https://bitbucket.org/owner/repo
|
|
|
138
140
|
|
|
139
141
|
## 🌐 Supported Forges
|
|
140
142
|
|
|
143
|
+
<p align="center">
|
|
144
|
+
<img src="assets/images/pluck_front_baubles.png" alt="All the forges" width="500"/>
|
|
145
|
+
</p>
|
|
146
|
+
|
|
141
147
|
| Forge | Host | Built-in | Notes |
|
|
142
148
|
|-------|------|----------|-------|
|
|
143
149
|
| **GitHub** | `github.com` | ✅ | Full support including gists |
|
|
@@ -169,7 +175,7 @@ Any git hosting platform that follows the standard `host/owner/repo` URL pattern
|
|
|
169
175
|
| `stats` | Show statistics | `pluck stats` |
|
|
170
176
|
| `doctor` | Check tool availability | `pluck doctor` |
|
|
171
177
|
| `config [key] [val]` | View/set config | `pluck config install_dir ~/Apps` |
|
|
172
|
-
| `search <query
|
|
178
|
+
| `search <query> [--forge <name>]` | Search repos (github\|gitlab\|codeberg\|bitbucket) | `pluck search python installer --forge gitlab` |
|
|
173
179
|
| `export <file>` | Export registry | `pluck export ~/backup.json` |
|
|
174
180
|
| `import <file>` | Import registry | `pluck import ~/backup.json` |
|
|
175
181
|
| `completion <shell>` | Generate shell completion | `pluck completion bash` |
|
|
@@ -191,6 +197,7 @@ Any git hosting platform that follows the standard `host/owner/repo` URL pattern
|
|
|
191
197
|
| `--no-color` | Disable colored output |
|
|
192
198
|
| `--timeout <secs>` | Timeout for git clone in seconds |
|
|
193
199
|
| `--retries <n>` | Number of retries for failed git clone |
|
|
200
|
+
| `--verbose` | Show detailed git clone output |
|
|
194
201
|
|
|
195
202
|
## 📥 Installation
|
|
196
203
|
|
|
@@ -208,15 +215,12 @@ pip install -e .
|
|
|
208
215
|
./src/gh_install.py install https://gitlab.com/user/project
|
|
209
216
|
```
|
|
210
217
|
|
|
211
|
-
### Via pip
|
|
218
|
+
### Via pip
|
|
212
219
|
|
|
213
220
|
```bash
|
|
214
|
-
# Once published to PyPI:
|
|
215
221
|
pip install pluck-cli
|
|
216
222
|
```
|
|
217
223
|
|
|
218
|
-
> **Note**: `pluck-cli` is not yet published to PyPI. Install from source above, or use the Docker image.
|
|
219
|
-
|
|
220
224
|
### Via Docker
|
|
221
225
|
|
|
222
226
|
```bash
|
|
@@ -261,6 +265,10 @@ Available environment variables:
|
|
|
261
265
|
|
|
262
266
|
## 🖱️ Browser Integration
|
|
263
267
|
|
|
268
|
+
<p align="center">
|
|
269
|
+
<img src="assets/images/pluck_stalking2.png" alt="pluck stalking repos in your browser" width="500"/>
|
|
270
|
+
</p>
|
|
271
|
+
|
|
264
272
|
Pluck includes a **right-click context menu** integration. Install a repo from any
|
|
265
273
|
forge without leaving your browser.
|
|
266
274
|
|
|
@@ -11,7 +11,9 @@
|
|
|
11
11
|
<img src="https://img.shields.io/badge/Dependencies-Zero-brightgreen" alt="Zero dependencies">
|
|
12
12
|
<img src="https://img.shields.io/badge/Tests-111%20passing-brightgreen" alt="111 passing tests">
|
|
13
13
|
<img src="https://img.shields.io/badge/Forges-11%20supported-blue" alt="11 forges supported">
|
|
14
|
+
<img src="https://img.shields.io/badge/PyPI-pluck--cli-blue?logo=pypi" alt="PyPI: pluck-cli">
|
|
14
15
|
<img src="https://img.shields.io/badge/Code%20style-ruff-EF5552" alt="Code style: ruff">
|
|
16
|
+
<img src="https://gitlab.com/mabodu/pluck/badges/main/pipeline.svg" alt="GitLab CI">
|
|
15
17
|
</p>
|
|
16
18
|
|
|
17
19
|
---
|
|
@@ -113,6 +115,10 @@ pluck install https://bitbucket.org/owner/repo
|
|
|
113
115
|
|
|
114
116
|
## 🌐 Supported Forges
|
|
115
117
|
|
|
118
|
+
<p align="center">
|
|
119
|
+
<img src="assets/images/pluck_front_baubles.png" alt="All the forges" width="500"/>
|
|
120
|
+
</p>
|
|
121
|
+
|
|
116
122
|
| Forge | Host | Built-in | Notes |
|
|
117
123
|
|-------|------|----------|-------|
|
|
118
124
|
| **GitHub** | `github.com` | ✅ | Full support including gists |
|
|
@@ -144,7 +150,7 @@ Any git hosting platform that follows the standard `host/owner/repo` URL pattern
|
|
|
144
150
|
| `stats` | Show statistics | `pluck stats` |
|
|
145
151
|
| `doctor` | Check tool availability | `pluck doctor` |
|
|
146
152
|
| `config [key] [val]` | View/set config | `pluck config install_dir ~/Apps` |
|
|
147
|
-
| `search <query
|
|
153
|
+
| `search <query> [--forge <name>]` | Search repos (github\|gitlab\|codeberg\|bitbucket) | `pluck search python installer --forge gitlab` |
|
|
148
154
|
| `export <file>` | Export registry | `pluck export ~/backup.json` |
|
|
149
155
|
| `import <file>` | Import registry | `pluck import ~/backup.json` |
|
|
150
156
|
| `completion <shell>` | Generate shell completion | `pluck completion bash` |
|
|
@@ -166,6 +172,7 @@ Any git hosting platform that follows the standard `host/owner/repo` URL pattern
|
|
|
166
172
|
| `--no-color` | Disable colored output |
|
|
167
173
|
| `--timeout <secs>` | Timeout for git clone in seconds |
|
|
168
174
|
| `--retries <n>` | Number of retries for failed git clone |
|
|
175
|
+
| `--verbose` | Show detailed git clone output |
|
|
169
176
|
|
|
170
177
|
## 📥 Installation
|
|
171
178
|
|
|
@@ -183,15 +190,12 @@ pip install -e .
|
|
|
183
190
|
./src/gh_install.py install https://gitlab.com/user/project
|
|
184
191
|
```
|
|
185
192
|
|
|
186
|
-
### Via pip
|
|
193
|
+
### Via pip
|
|
187
194
|
|
|
188
195
|
```bash
|
|
189
|
-
# Once published to PyPI:
|
|
190
196
|
pip install pluck-cli
|
|
191
197
|
```
|
|
192
198
|
|
|
193
|
-
> **Note**: `pluck-cli` is not yet published to PyPI. Install from source above, or use the Docker image.
|
|
194
|
-
|
|
195
199
|
### Via Docker
|
|
196
200
|
|
|
197
201
|
```bash
|
|
@@ -236,6 +240,10 @@ Available environment variables:
|
|
|
236
240
|
|
|
237
241
|
## 🖱️ Browser Integration
|
|
238
242
|
|
|
243
|
+
<p align="center">
|
|
244
|
+
<img src="assets/images/pluck_stalking2.png" alt="pluck stalking repos in your browser" width="500"/>
|
|
245
|
+
</p>
|
|
246
|
+
|
|
239
247
|
Pluck includes a **right-click context menu** integration. Install a repo from any
|
|
240
248
|
forge without leaving your browser.
|
|
241
249
|
|
|
@@ -4,10 +4,10 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pluck-cli"
|
|
7
|
-
version = "0.1
|
|
7
|
+
version = "0.2.1"
|
|
8
8
|
description = "Pluck any git repo from any forge — auto-detect, auto-install, done!"
|
|
9
9
|
readme = "README.md"
|
|
10
|
-
license = "MIT"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
11
|
requires-python = ">=3.6"
|
|
12
12
|
authors = [
|
|
13
13
|
{name = "pluck contributors"}
|
|
@@ -18,7 +18,7 @@ import urllib.request
|
|
|
18
18
|
from datetime import datetime
|
|
19
19
|
from pathlib import Path
|
|
20
20
|
|
|
21
|
-
__version__ = "0.1
|
|
21
|
+
__version__ = "0.2.1"
|
|
22
22
|
|
|
23
23
|
# Configuration
|
|
24
24
|
DEFAULT_INSTALL_DIR_MACOS = Path.home() / "Applications"
|
|
@@ -88,7 +88,7 @@ def print_usage():
|
|
|
88
88
|
("stats", "Show installation statistics"),
|
|
89
89
|
("doctor", "Check tool availability"),
|
|
90
90
|
("config [key] [value]", "View/set config"),
|
|
91
|
-
("search <query> [--forge <name>]", "Search repos (github|gitlab|codeberg)"),
|
|
91
|
+
("search <query> [--forge <name>]", "Search repos (github|gitlab|codeberg|bitbucket)"),
|
|
92
92
|
("export <file>", "Export registry"),
|
|
93
93
|
("import <file>", "Import registry"),
|
|
94
94
|
("completion <shell>", "Generate shell completion"),
|
|
@@ -107,6 +107,7 @@ def print_usage():
|
|
|
107
107
|
("--no-color", "Disable colored output"),
|
|
108
108
|
("--timeout <secs>", "Timeout for git clone in seconds"),
|
|
109
109
|
("--retries <n>", "Number of retries for failed git clone"),
|
|
110
|
+
("--verbose", "Show detailed git clone output"),
|
|
110
111
|
]
|
|
111
112
|
|
|
112
113
|
print("Usage:")
|
|
@@ -632,6 +633,7 @@ def download_and_install(
|
|
|
632
633
|
shallow=False,
|
|
633
634
|
ref=None,
|
|
634
635
|
method_override=None,
|
|
636
|
+
verbose=False,
|
|
635
637
|
timeout=None,
|
|
636
638
|
retries=0,
|
|
637
639
|
):
|
|
@@ -689,7 +691,9 @@ def download_and_install(
|
|
|
689
691
|
print(" Downloading...")
|
|
690
692
|
|
|
691
693
|
try:
|
|
692
|
-
subprocess.run(clone_cmd, check=True, timeout=timeout
|
|
694
|
+
subprocess.run(clone_cmd, check=True, timeout=timeout,
|
|
695
|
+
stdout=None if verbose else subprocess.DEVNULL,
|
|
696
|
+
stderr=None if verbose else subprocess.DEVNULL)
|
|
693
697
|
break
|
|
694
698
|
except subprocess.TimeoutExpired:
|
|
695
699
|
print_error(f"Clone timed out after {timeout}s")
|
|
@@ -1037,31 +1041,31 @@ def search_codeberg(query, limit=10):
|
|
|
1037
1041
|
repo.get("html_url", ""),
|
|
1038
1042
|
)
|
|
1039
1043
|
|
|
1040
|
-
|
|
1044
|
+
|
|
1045
|
+
def search_bitbucket(query, limit=10):
|
|
1046
|
+
"""Search repositories using the Bitbucket Cloud API."""
|
|
1047
|
+
print(f" Searching Bitbucket for '{query}'...")
|
|
1048
|
+
url = f"https://api.bitbucket.org/2.0/repositories?q=name~\"{urllib.parse.quote(query)}\"&sort=-updated_on"
|
|
1041
1049
|
try:
|
|
1042
|
-
req = urllib.request.Request(url, headers={"Accept": "application/
|
|
1050
|
+
req = urllib.request.Request(url, headers={"Accept": "application/json"})
|
|
1043
1051
|
with urllib.request.urlopen(req, timeout=10) as resp:
|
|
1044
1052
|
data = json.loads(resp.read().decode())
|
|
1045
1053
|
except Exception as e:
|
|
1046
1054
|
print_error(f"Search failed: {e}")
|
|
1047
1055
|
return
|
|
1048
1056
|
|
|
1049
|
-
items = data.get("
|
|
1057
|
+
items = data.get("values", [])
|
|
1050
1058
|
if not items:
|
|
1051
1059
|
print_warning("No results found")
|
|
1052
1060
|
return
|
|
1053
1061
|
|
|
1054
|
-
print_header(f"
|
|
1062
|
+
print_header(f"Bitbucket Results — '{query}' ({len(items)} found)")
|
|
1055
1063
|
for i, repo in enumerate(items, 1):
|
|
1056
|
-
|
|
1057
|
-
stars = repo["stargazers_count"]
|
|
1064
|
+
full_name = repo.get("full_name", "unknown")
|
|
1058
1065
|
desc = repo.get("description") or "No description"
|
|
1059
1066
|
lang = repo.get("language") or "Unknown"
|
|
1060
|
-
|
|
1061
|
-
|
|
1062
|
-
print(f" {Colors.CYAN}★{Colors.END} {stars:,} | Language: {lang}")
|
|
1063
|
-
print(f" URL: {repo['html_url']}")
|
|
1064
|
-
print()
|
|
1067
|
+
url = repo.get("links", {}).get("html", {}).get("href", "")
|
|
1068
|
+
_search_print_result(i, full_name, desc, 0, lang, url, star_char="\u2022")
|
|
1065
1069
|
|
|
1066
1070
|
|
|
1067
1071
|
def export_registry(filepath):
|
|
@@ -1122,7 +1126,7 @@ def register_app(repo_name, repo_url, install_path, install_method, skip_hook=Fa
|
|
|
1122
1126
|
|
|
1123
1127
|
def _run_post_install_hook(repo_name, install_path, method):
|
|
1124
1128
|
"""Run user-defined post-install hook if configured."""
|
|
1125
|
-
hook_dir = CONFIG_FILE.parent / "
|
|
1129
|
+
hook_dir = CONFIG_FILE.parent / "hooks"
|
|
1126
1130
|
hook_file = hook_dir / "post-install.sh"
|
|
1127
1131
|
|
|
1128
1132
|
if hook_file.exists():
|
|
@@ -1296,6 +1300,7 @@ def _parse_args(args):
|
|
|
1296
1300
|
method = None
|
|
1297
1301
|
json_output = False
|
|
1298
1302
|
no_color = False
|
|
1303
|
+
verbose = False
|
|
1299
1304
|
timeout = None
|
|
1300
1305
|
retries = 0
|
|
1301
1306
|
urls = []
|
|
@@ -1326,6 +1331,9 @@ def _parse_args(args):
|
|
|
1326
1331
|
elif args[i] == "--json":
|
|
1327
1332
|
json_output = True
|
|
1328
1333
|
i += 1
|
|
1334
|
+
elif args[i] == "--verbose":
|
|
1335
|
+
verbose = True
|
|
1336
|
+
i += 1
|
|
1329
1337
|
elif args[i] == "--no-color":
|
|
1330
1338
|
no_color = True
|
|
1331
1339
|
i += 1
|
|
@@ -1350,7 +1358,7 @@ def _parse_args(args):
|
|
|
1350
1358
|
if no_color:
|
|
1351
1359
|
_enable_colors(False)
|
|
1352
1360
|
|
|
1353
|
-
return install_dir, dry_run, force, shallow, ref, method, json_output, timeout, retries, urls
|
|
1361
|
+
return install_dir, dry_run, force, shallow, ref, method, json_output, verbose, no_color, timeout, retries, urls
|
|
1354
1362
|
|
|
1355
1363
|
|
|
1356
1364
|
def verify_apps(json_output=False):
|
|
@@ -1525,7 +1533,7 @@ def main():
|
|
|
1525
1533
|
command = sys.argv[1]
|
|
1526
1534
|
|
|
1527
1535
|
if command == "install":
|
|
1528
|
-
install_dir, dry_run, force, shallow, ref, method, json_output, timeout, retries, urls = (
|
|
1536
|
+
install_dir, dry_run, force, shallow, ref, method, json_output, verbose, no_color, timeout, retries, urls = (
|
|
1529
1537
|
_parse_args(sys.argv[2:])
|
|
1530
1538
|
)
|
|
1531
1539
|
|
|
@@ -1549,12 +1557,13 @@ def main():
|
|
|
1549
1557
|
shallow=shallow,
|
|
1550
1558
|
ref=ref,
|
|
1551
1559
|
method_override=method,
|
|
1560
|
+
verbose=verbose,
|
|
1552
1561
|
timeout=timeout,
|
|
1553
1562
|
retries=retries,
|
|
1554
1563
|
)
|
|
1555
1564
|
|
|
1556
1565
|
elif command == "update":
|
|
1557
|
-
install_dir, dry_run, force, shallow, ref, method, json_output, timeout, retries, rest = (
|
|
1566
|
+
install_dir, dry_run, force, shallow, ref, method, json_output, verbose, no_color, timeout, retries, rest = (
|
|
1558
1567
|
_parse_args(sys.argv[2:])
|
|
1559
1568
|
)
|
|
1560
1569
|
if not rest:
|
|
@@ -1588,7 +1597,7 @@ def main():
|
|
|
1588
1597
|
list_installed(json_output=json_output)
|
|
1589
1598
|
|
|
1590
1599
|
elif command in ("uninstall", "remove"):
|
|
1591
|
-
install_dir, dry_run, force, shallow, ref, method, json_output, timeout, retries, rest = (
|
|
1600
|
+
install_dir, dry_run, force, shallow, ref, method, json_output, verbose, no_color, timeout, retries, rest = (
|
|
1592
1601
|
_parse_args(sys.argv[2:])
|
|
1593
1602
|
)
|
|
1594
1603
|
if not rest:
|
|
@@ -1603,7 +1612,7 @@ def main():
|
|
|
1603
1612
|
verify_apps(json_output=json_output)
|
|
1604
1613
|
|
|
1605
1614
|
elif command == "clean":
|
|
1606
|
-
install_dir, dry_run, force, shallow, ref, method, json_output, timeout, retries, rest = (
|
|
1615
|
+
install_dir, dry_run, force, shallow, ref, method, json_output, verbose, no_color, timeout, retries, rest = (
|
|
1607
1616
|
_parse_args(sys.argv[2:])
|
|
1608
1617
|
)
|
|
1609
1618
|
clean_registry(dry_run=dry_run, force=force, json_output=json_output)
|
|
@@ -1642,6 +1651,7 @@ def main():
|
|
|
1642
1651
|
"github": search_github,
|
|
1643
1652
|
"gitlab": search_gitlab,
|
|
1644
1653
|
"codeberg": search_codeberg,
|
|
1654
|
+
"bitbucket": search_bitbucket,
|
|
1645
1655
|
}
|
|
1646
1656
|
searcher = forge_searchers.get(forge)
|
|
1647
1657
|
if searcher:
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: pluck-cli
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Pluck any git repo from any forge — auto-detect, auto-install, done!
|
|
5
5
|
Author: pluck contributors
|
|
6
|
-
License
|
|
6
|
+
License: MIT
|
|
7
7
|
Keywords: git,forge,installer,cli,github,gitlab,codeberg
|
|
8
8
|
Classifier: Development Status :: 3 - Alpha
|
|
9
9
|
Classifier: Environment :: Console
|
|
@@ -36,7 +36,9 @@ Dynamic: license-file
|
|
|
36
36
|
<img src="https://img.shields.io/badge/Dependencies-Zero-brightgreen" alt="Zero dependencies">
|
|
37
37
|
<img src="https://img.shields.io/badge/Tests-111%20passing-brightgreen" alt="111 passing tests">
|
|
38
38
|
<img src="https://img.shields.io/badge/Forges-11%20supported-blue" alt="11 forges supported">
|
|
39
|
+
<img src="https://img.shields.io/badge/PyPI-pluck--cli-blue?logo=pypi" alt="PyPI: pluck-cli">
|
|
39
40
|
<img src="https://img.shields.io/badge/Code%20style-ruff-EF5552" alt="Code style: ruff">
|
|
41
|
+
<img src="https://gitlab.com/mabodu/pluck/badges/main/pipeline.svg" alt="GitLab CI">
|
|
40
42
|
</p>
|
|
41
43
|
|
|
42
44
|
---
|
|
@@ -138,6 +140,10 @@ pluck install https://bitbucket.org/owner/repo
|
|
|
138
140
|
|
|
139
141
|
## 🌐 Supported Forges
|
|
140
142
|
|
|
143
|
+
<p align="center">
|
|
144
|
+
<img src="assets/images/pluck_front_baubles.png" alt="All the forges" width="500"/>
|
|
145
|
+
</p>
|
|
146
|
+
|
|
141
147
|
| Forge | Host | Built-in | Notes |
|
|
142
148
|
|-------|------|----------|-------|
|
|
143
149
|
| **GitHub** | `github.com` | ✅ | Full support including gists |
|
|
@@ -169,7 +175,7 @@ Any git hosting platform that follows the standard `host/owner/repo` URL pattern
|
|
|
169
175
|
| `stats` | Show statistics | `pluck stats` |
|
|
170
176
|
| `doctor` | Check tool availability | `pluck doctor` |
|
|
171
177
|
| `config [key] [val]` | View/set config | `pluck config install_dir ~/Apps` |
|
|
172
|
-
| `search <query
|
|
178
|
+
| `search <query> [--forge <name>]` | Search repos (github\|gitlab\|codeberg\|bitbucket) | `pluck search python installer --forge gitlab` |
|
|
173
179
|
| `export <file>` | Export registry | `pluck export ~/backup.json` |
|
|
174
180
|
| `import <file>` | Import registry | `pluck import ~/backup.json` |
|
|
175
181
|
| `completion <shell>` | Generate shell completion | `pluck completion bash` |
|
|
@@ -191,6 +197,7 @@ Any git hosting platform that follows the standard `host/owner/repo` URL pattern
|
|
|
191
197
|
| `--no-color` | Disable colored output |
|
|
192
198
|
| `--timeout <secs>` | Timeout for git clone in seconds |
|
|
193
199
|
| `--retries <n>` | Number of retries for failed git clone |
|
|
200
|
+
| `--verbose` | Show detailed git clone output |
|
|
194
201
|
|
|
195
202
|
## 📥 Installation
|
|
196
203
|
|
|
@@ -208,15 +215,12 @@ pip install -e .
|
|
|
208
215
|
./src/gh_install.py install https://gitlab.com/user/project
|
|
209
216
|
```
|
|
210
217
|
|
|
211
|
-
### Via pip
|
|
218
|
+
### Via pip
|
|
212
219
|
|
|
213
220
|
```bash
|
|
214
|
-
# Once published to PyPI:
|
|
215
221
|
pip install pluck-cli
|
|
216
222
|
```
|
|
217
223
|
|
|
218
|
-
> **Note**: `pluck-cli` is not yet published to PyPI. Install from source above, or use the Docker image.
|
|
219
|
-
|
|
220
224
|
### Via Docker
|
|
221
225
|
|
|
222
226
|
```bash
|
|
@@ -261,6 +265,10 @@ Available environment variables:
|
|
|
261
265
|
|
|
262
266
|
## 🖱️ Browser Integration
|
|
263
267
|
|
|
268
|
+
<p align="center">
|
|
269
|
+
<img src="assets/images/pluck_stalking2.png" alt="pluck stalking repos in your browser" width="500"/>
|
|
270
|
+
</p>
|
|
271
|
+
|
|
264
272
|
Pluck includes a **right-click context menu** integration. Install a repo from any
|
|
265
273
|
forge without leaving your browser.
|
|
266
274
|
|
|
@@ -433,7 +433,7 @@ class TestParseArgs:
|
|
|
433
433
|
def test_urls_only(self):
|
|
434
434
|
(
|
|
435
435
|
install_dir, dry_run, force, shallow, ref,
|
|
436
|
-
method, json_output, timeout, retries, urls,
|
|
436
|
+
method, json_output, verbose, no_color, timeout, retries, urls,
|
|
437
437
|
) = _parse_args(["https://github.com/a/b"])
|
|
438
438
|
assert install_dir is None
|
|
439
439
|
assert dry_run is False
|
|
@@ -446,7 +446,7 @@ class TestParseArgs:
|
|
|
446
446
|
def test_dir_flag(self):
|
|
447
447
|
(
|
|
448
448
|
install_dir, dry_run, force, shallow, ref,
|
|
449
|
-
method, json_output, timeout, retries, urls,
|
|
449
|
+
method, json_output, verbose, no_color, timeout, retries, urls,
|
|
450
450
|
) = _parse_args(["--dir", "/tmp/test", "https://github.com/a/b"])
|
|
451
451
|
assert install_dir == Path("/tmp/test")
|
|
452
452
|
assert urls == ["https://github.com/a/b"]
|
|
@@ -454,49 +454,49 @@ class TestParseArgs:
|
|
|
454
454
|
def test_dry_run_flag(self):
|
|
455
455
|
(
|
|
456
456
|
install_dir, dry_run, force, shallow, ref,
|
|
457
|
-
method, json_output, timeout, retries, urls,
|
|
457
|
+
method, json_output, verbose, no_color, timeout, retries, urls,
|
|
458
458
|
) = _parse_args(["--dry-run", "https://github.com/a/b"])
|
|
459
459
|
assert dry_run is True
|
|
460
460
|
|
|
461
461
|
def test_force_flag(self):
|
|
462
462
|
(
|
|
463
463
|
install_dir, dry_run, force, shallow, ref,
|
|
464
|
-
method, json_output, timeout, retries, urls,
|
|
464
|
+
method, json_output, verbose, no_color, timeout, retries, urls,
|
|
465
465
|
) = _parse_args(["--force", "https://github.com/a/b"])
|
|
466
466
|
assert force is True
|
|
467
467
|
|
|
468
468
|
def test_yes_flag(self):
|
|
469
469
|
(
|
|
470
470
|
install_dir, dry_run, force, shallow, ref,
|
|
471
|
-
method, json_output, timeout, retries, urls,
|
|
471
|
+
method, json_output, verbose, no_color, timeout, retries, urls,
|
|
472
472
|
) = _parse_args(["--yes", "https://github.com/a/b"])
|
|
473
473
|
assert force is True
|
|
474
474
|
|
|
475
475
|
def test_shallow_flag(self):
|
|
476
476
|
(
|
|
477
477
|
install_dir, dry_run, force, shallow, ref,
|
|
478
|
-
method, json_output, timeout, retries, urls,
|
|
478
|
+
method, json_output, verbose, no_color, timeout, retries, urls,
|
|
479
479
|
) = _parse_args(["--shallow", "https://github.com/a/b"])
|
|
480
480
|
assert shallow is True
|
|
481
481
|
|
|
482
482
|
def test_ref_flag(self):
|
|
483
483
|
(
|
|
484
484
|
install_dir, dry_run, force, shallow, ref,
|
|
485
|
-
method, json_output, timeout, retries, urls,
|
|
485
|
+
method, json_output, verbose, no_color, timeout, retries, urls,
|
|
486
486
|
) = _parse_args(["--ref", "v2.0", "https://github.com/a/b"])
|
|
487
487
|
assert ref == "v2.0"
|
|
488
488
|
|
|
489
489
|
def test_method_flag(self):
|
|
490
490
|
(
|
|
491
491
|
install_dir, dry_run, force, shallow, ref,
|
|
492
|
-
method, json_output, timeout, retries, urls,
|
|
492
|
+
method, json_output, verbose, no_color, timeout, retries, urls,
|
|
493
493
|
) = _parse_args(["--method", "python", "https://github.com/a/b"])
|
|
494
494
|
assert method == "python"
|
|
495
495
|
|
|
496
496
|
def test_combined_flags(self):
|
|
497
497
|
(
|
|
498
498
|
install_dir, dry_run, force, shallow, ref,
|
|
499
|
-
method, json_output, timeout, retries, urls,
|
|
499
|
+
method, json_output, verbose, no_color, timeout, retries, urls,
|
|
500
500
|
) = _parse_args([
|
|
501
501
|
"--dir", "/custom", "--dry-run", "--shallow",
|
|
502
502
|
"--ref", "main", "--method", "python",
|
|
@@ -511,7 +511,7 @@ class TestParseArgs:
|
|
|
511
511
|
def test_flags_between_urls(self):
|
|
512
512
|
(
|
|
513
513
|
install_dir, dry_run, force, shallow, ref,
|
|
514
|
-
method, json_output, timeout, retries, urls,
|
|
514
|
+
method, json_output, verbose, no_color, timeout, retries, urls,
|
|
515
515
|
) = _parse_args([
|
|
516
516
|
"https://github.com/a/b", "--dir", "/opt", "https://github.com/c/d",
|
|
517
517
|
])
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|