codefetch-cli 1.2.4__tar.gz → 1.2.6__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codefetch-cli
3
- Version: 1.2.4
3
+ Version: 1.2.6
4
4
  Summary: Quickly fetch code files from GitHub repositories with simple commands
5
5
  Home-page: https://github.com/InzamamulQureshi/Codefetch
6
6
  Author: Inzamamul Qureshi
@@ -35,6 +35,8 @@ CodeFetch is a lightweight command-line utility and Python library designed to q
35
35
  - **Automatic Path & Case Resolution**: Automatically resolves case mismatches and finds files nested inside subdirectories.
36
36
  - **Repository Discovery**: List all public repositories for any GitHub user with `--repos`.
37
37
  - **Tree Exploration**: List all supported code files within a repository with `--list`.
38
+ - **Self-Updating**: Keep CodeFetch updated to the latest PyPI release with `codefetch --update`.
39
+ - **Clean Uninstall**: Easily remove CodeFetch and its configuration with `codefetch --uninstall`.
38
40
  - **Python Library Support**: Import and use programmatically with `import codefetch as cf`.
39
41
  - **Optional Persistent Defaults**: Save a default repository or user with `--set-default` if you frequently work with the same repository.
40
42
  - **Zero Runtime Dependencies**: Built using only the Python standard library with zero third-party dependencies.
@@ -129,6 +131,16 @@ codefetch --config
129
131
  codefetch --reset-config
130
132
  ```
131
133
 
134
+ ### 5. Package Management
135
+
136
+ ```bash
137
+ # Update CodeFetch to the latest version published on PyPI
138
+ codefetch --update
139
+
140
+ # Uninstall CodeFetch and remove local configuration
141
+ codefetch --uninstall
142
+ ```
143
+
132
144
  ---
133
145
 
134
146
  ## Python API Usage
@@ -163,11 +175,13 @@ print(f"Found {len(files)} files")
163
175
  | `-R`, `--repos` | List public repositories for a user | `codefetch -R -u username` |
164
176
  | `-r`, `--repo` | Specify repository name or URL | `codefetch -r repo main.py` |
165
177
  | `-u`, `--user` | Specify GitHub username or organization | `codefetch -u username -r repo main.py` |
166
- | `-b`, `--branch` | Branch name (default: `main`) | `codefetch -b master owner/repo Makefile` |
178
+ | `-b`, `--branch` | Branch name (default: repo default branch) | `codefetch -b master owner/repo Makefile` |
167
179
  | `--set-default` | Set persistent default repository | `codefetch --set-default owner/repo` |
168
180
  | `--set-default-user` | Set persistent default user | `codefetch --set-default-user username` |
169
181
  | `--config` | Display active configuration | `codefetch --config` |
170
182
  | `--reset-config` | Reset configuration back to defaults | `codefetch --reset-config` |
183
+ | `-U`, `--update` | Update CodeFetch to latest PyPI release | `codefetch --update` |
184
+ | `--uninstall` | Uninstall CodeFetch from your system | `codefetch --uninstall` |
171
185
  | `-v`, `--version` | Display version information | `codefetch --version` |
172
186
  | `-h`, `--help` | Display help and usage message | `codefetch --help` |
173
187
 
@@ -13,6 +13,8 @@ CodeFetch is a lightweight command-line utility and Python library designed to q
13
13
  - **Automatic Path & Case Resolution**: Automatically resolves case mismatches and finds files nested inside subdirectories.
14
14
  - **Repository Discovery**: List all public repositories for any GitHub user with `--repos`.
15
15
  - **Tree Exploration**: List all supported code files within a repository with `--list`.
16
+ - **Self-Updating**: Keep CodeFetch updated to the latest PyPI release with `codefetch --update`.
17
+ - **Clean Uninstall**: Easily remove CodeFetch and its configuration with `codefetch --uninstall`.
16
18
  - **Python Library Support**: Import and use programmatically with `import codefetch as cf`.
17
19
  - **Optional Persistent Defaults**: Save a default repository or user with `--set-default` if you frequently work with the same repository.
18
20
  - **Zero Runtime Dependencies**: Built using only the Python standard library with zero third-party dependencies.
@@ -107,6 +109,16 @@ codefetch --config
107
109
  codefetch --reset-config
108
110
  ```
109
111
 
112
+ ### 5. Package Management
113
+
114
+ ```bash
115
+ # Update CodeFetch to the latest version published on PyPI
116
+ codefetch --update
117
+
118
+ # Uninstall CodeFetch and remove local configuration
119
+ codefetch --uninstall
120
+ ```
121
+
110
122
  ---
111
123
 
112
124
  ## Python API Usage
@@ -141,11 +153,13 @@ print(f"Found {len(files)} files")
141
153
  | `-R`, `--repos` | List public repositories for a user | `codefetch -R -u username` |
142
154
  | `-r`, `--repo` | Specify repository name or URL | `codefetch -r repo main.py` |
143
155
  | `-u`, `--user` | Specify GitHub username or organization | `codefetch -u username -r repo main.py` |
144
- | `-b`, `--branch` | Branch name (default: `main`) | `codefetch -b master owner/repo Makefile` |
156
+ | `-b`, `--branch` | Branch name (default: repo default branch) | `codefetch -b master owner/repo Makefile` |
145
157
  | `--set-default` | Set persistent default repository | `codefetch --set-default owner/repo` |
146
158
  | `--set-default-user` | Set persistent default user | `codefetch --set-default-user username` |
147
159
  | `--config` | Display active configuration | `codefetch --config` |
148
160
  | `--reset-config` | Reset configuration back to defaults | `codefetch --reset-config` |
161
+ | `-U`, `--update` | Update CodeFetch to latest PyPI release | `codefetch --update` |
162
+ | `--uninstall` | Uninstall CodeFetch from your system | `codefetch --uninstall` |
149
163
  | `-v`, `--version` | Display version information | `codefetch --version` |
150
164
  | `-h`, `--help` | Display help and usage message | `codefetch --help` |
151
165
 
@@ -16,7 +16,7 @@ Usage in Python:
16
16
  files = cf.list("torvalds/linux")
17
17
  """
18
18
 
19
- __version__ = "1.2.4"
19
+ __version__ = "1.2.6"
20
20
 
21
21
 
22
22
  def get(target, filename=None, branch=None):
@@ -7,6 +7,7 @@ import argparse
7
7
  import json
8
8
  import os
9
9
  import re
10
+ import subprocess
10
11
  import sys
11
12
  import urllib.error
12
13
  import urllib.request
@@ -14,11 +15,10 @@ from pathlib import Path
14
15
 
15
16
  DEFAULT_OWNER = None
16
17
  DEFAULT_REPO = None
17
- DEFAULT_BRANCH = None
18
18
 
19
19
  CONFIG_FILE = Path.home() / ".codefetch.json"
20
20
 
21
- __version__ = "1.2.4"
21
+ __version__ = "1.2.6"
22
22
 
23
23
  # Supported code, data, and config extensions
24
24
  CODE_EXTENSIONS = {
@@ -62,6 +62,8 @@ USAGE:
62
62
  codefetch -s <owner>/<repo> <filename> Preview file in terminal without saving
63
63
  codefetch -l <owner>/<repo> List all code files in a repository
64
64
  codefetch -R <username> List public repositories for a user
65
+ codefetch --update Update CodeFetch to the latest version
66
+ codefetch --uninstall Uninstall CodeFetch from your system
65
67
 
66
68
  POPULAR EXAMPLES:
67
69
  # Download from any repository:
@@ -79,6 +81,10 @@ POPULAR EXAMPLES:
79
81
  codefetch -l torvalds/linux # list files in a repo
80
82
  codefetch -R torvalds # list repos belonging to user
81
83
 
84
+ # Package management:
85
+ codefetch --update # update to latest PyPI release
86
+ codefetch --uninstall # uninstall CodeFetch package
87
+
82
88
  SETTING A DEFAULT REPOSITORY (OPTIONAL):
83
89
  If you frequently work with the same repo, you can set it as default:
84
90
  codefetch --set-default owner/repo # sets default repo
@@ -98,6 +104,9 @@ FLAGS & OPTIONS:
98
104
  --set-default-user <user> Save default user/organization
99
105
  --config Show current saved configuration
100
106
  --reset-config Reset configuration back to defaults
107
+ -U, --update Update CodeFetch to the latest version from PyPI
108
+ --uninstall Uninstall CodeFetch from your system
109
+ -y, --yes Confirm uninstall without prompting
101
110
  -v, --version Show version number
102
111
  -h, --help Show this help message
103
112
  """
@@ -122,7 +131,7 @@ def load_config():
122
131
 
123
132
 
124
133
  def save_config(owner=None, repo=None):
125
- """Save user configuration to ~/.codefetch.json (no branch saved in config)."""
134
+ """Save user configuration to ~/.codefetch.json."""
126
135
  cfg = load_config()
127
136
  if owner is not None:
128
137
  cfg["owner"] = owner
@@ -478,7 +487,6 @@ def fetch_file(filename, owner=None, repo=None, branch=None,
478
487
 
479
488
  # Case A: Branch parameter was explicitly entered by the user
480
489
  if branch:
481
- # First, check if the specified branch exists
482
490
  branch_exists = check_branch_exists(owner, repo, branch)
483
491
 
484
492
  if not branch_exists:
@@ -490,7 +498,6 @@ def fetch_file(filename, owner=None, repo=None, branch=None,
490
498
  print(f"Available branches in {owner}/{repo}: {', '.join(shown)}{extra}")
491
499
  print(f"Trying default branch '{default_branch}'...")
492
500
 
493
- # Fall back to default branch
494
501
  actual_branch = default_branch
495
502
  try:
496
503
  content = fetch_raw_single(owner, repo, default_branch, clean_filename)
@@ -501,7 +508,6 @@ def fetch_file(filename, owner=None, repo=None, branch=None,
501
508
  pass
502
509
 
503
510
  if content is None:
504
- # Try tree on default branch
505
511
  try:
506
512
  tree_data = get_repo_tree(owner, repo, default_branch)
507
513
  matched = resolve_file_in_tree(tree_data, clean_filename)
@@ -519,7 +525,6 @@ def fetch_file(filename, owner=None, repo=None, branch=None,
519
525
  return
520
526
 
521
527
  else:
522
- # The specified branch exists! First try direct fetch from it
523
528
  actual_branch = branch
524
529
  try:
525
530
  content = fetch_raw_single(owner, repo, branch, clean_filename)
@@ -530,7 +535,6 @@ def fetch_file(filename, owner=None, repo=None, branch=None,
530
535
  pass
531
536
 
532
537
  if content is None:
533
- # Direct raw 404ed, search tree of the specified branch
534
538
  try:
535
539
  tree_data = get_repo_tree(owner, repo, branch)
536
540
  matched = resolve_file_in_tree(tree_data, clean_filename)
@@ -542,7 +546,6 @@ def fetch_file(filename, owner=None, repo=None, branch=None,
542
546
  except Exception:
543
547
  pass
544
548
 
545
- # If file not in specified branch, check default branch as well
546
549
  if content is None and branch.lower() != default_branch.lower():
547
550
  print(f"Notice: File '{clean_filename}' not found on branch '{branch}'.")
548
551
  available_branches = get_repo_branches(owner, repo)
@@ -593,7 +596,6 @@ def fetch_file(filename, owner=None, repo=None, branch=None,
593
596
  return
594
597
 
595
598
  if content is None:
596
- # Tree search on default branch
597
599
  try:
598
600
  tree_data = get_repo_tree(owner, repo, default_branch)
599
601
  matched = resolve_file_in_tree(tree_data, clean_filename)
@@ -603,7 +605,6 @@ def fetch_file(filename, owner=None, repo=None, branch=None,
603
605
  if resolved_path != clean_filename:
604
606
  print(f"(Resolved '{clean_filename}' -> '{resolved_path}')")
605
607
  else:
606
- # Check other public repositories for the same user
607
608
  other_repo, other_match = find_file_in_other_repos(owner, repo, clean_filename)
608
609
  if other_repo:
609
610
  print(f"File not found: '{clean_filename}' in {owner}/{repo} ({default_branch}).")
@@ -639,6 +640,91 @@ def fetch_file(filename, owner=None, repo=None, branch=None,
639
640
  print(f"Error saving file '{out_name}': {e}")
640
641
 
641
642
 
643
+ def parse_version_tuple(v_str):
644
+ """Parse version string like '1.2.6' into a comparable tuple of integers."""
645
+ try:
646
+ return tuple(int(x) for x in re.findall(r"\d+", v_str))
647
+ except Exception:
648
+ return (0,)
649
+
650
+
651
+ def update_codefetch():
652
+ """Update codefetch-cli to the latest version from PyPI."""
653
+ print("Checking for updates from PyPI...")
654
+ package_name = "codefetch-cli"
655
+ latest_version = None
656
+
657
+ try:
658
+ url = f"https://pypi.org/pypi/{package_name}/json"
659
+ req = urllib.request.Request(url, headers={"User-Agent": "codefetch"})
660
+ with urllib.request.urlopen(req, timeout=10) as resp:
661
+ data = json.loads(resp.read().decode("utf-8"))
662
+ latest_version = data.get("info", {}).get("version")
663
+ except Exception as e:
664
+ print(f"Note: Could not check PyPI metadata ({e}).")
665
+
666
+ if latest_version:
667
+ curr_tuple = parse_version_tuple(__version__)
668
+ latest_tuple = parse_version_tuple(latest_version)
669
+
670
+ if latest_tuple <= curr_tuple:
671
+ print(f"CodeFetch is already up to date (version {__version__}).")
672
+ return
673
+
674
+ print(f"Update available: v{latest_version} (current: v{__version__})")
675
+ print(f"Updating {package_name}...")
676
+ else:
677
+ print(f"Updating {package_name} to latest version...")
678
+
679
+ cmd = [sys.executable, "-m", "pip", "install", "--upgrade", package_name]
680
+ try:
681
+ result = subprocess.run(cmd)
682
+ if result.returncode == 0:
683
+ target_v = f"v{latest_version}" if latest_version else "the latest version"
684
+ print(f"\nSuccessfully updated CodeFetch to {target_v}!")
685
+ else:
686
+ print(f"\nUpdate failed (exit code {result.returncode}).")
687
+ print(f"You can manually update with: pip install --upgrade {package_name}")
688
+ except Exception as e:
689
+ print(f"\nError running update: {e}")
690
+ print(f"You can manually update with: pip install --upgrade {package_name}")
691
+
692
+
693
+ def uninstall_codefetch(yes=False):
694
+ """Uninstall codefetch-cli package from system."""
695
+ if not yes:
696
+ try:
697
+ choice = input("Are you sure you want to uninstall CodeFetch? [y/N]: ").strip().lower()
698
+ except (EOFError, KeyboardInterrupt):
699
+ print("\nCancelled.")
700
+ return
701
+
702
+ if choice not in ("y", "yes"):
703
+ print("Uninstall cancelled.")
704
+ return
705
+
706
+ # Clean up ~/.codefetch.json configuration file if present
707
+ if CONFIG_FILE.exists():
708
+ try:
709
+ CONFIG_FILE.unlink()
710
+ print(f"Removed configuration file: {CONFIG_FILE}")
711
+ except Exception:
712
+ pass
713
+
714
+ print("Uninstalling codefetch-cli...")
715
+ cmd = [sys.executable, "-m", "pip", "uninstall", "-y", "codefetch-cli"]
716
+ try:
717
+ result = subprocess.run(cmd)
718
+ if result.returncode == 0:
719
+ print("\nSuccessfully uninstalled CodeFetch.")
720
+ else:
721
+ print(f"\nUninstall failed (exit code {result.returncode}).")
722
+ print("You can manually uninstall with: pip uninstall codefetch-cli")
723
+ except Exception as e:
724
+ print(f"\nError during uninstall: {e}")
725
+ print("You can manually uninstall with: pip uninstall codefetch-cli")
726
+
727
+
642
728
  class CodefetchParser(argparse.ArgumentParser):
643
729
  """Custom parser providing clean, intuitive help formatting."""
644
730
 
@@ -669,6 +755,9 @@ def build_parser():
669
755
  parser.add_argument("--set-default-user", type=str, help="Save default GitHub user")
670
756
  parser.add_argument("--config", action="store_true", help="Display active configuration")
671
757
  parser.add_argument("--reset-config", action="store_true", help="Reset configuration back to defaults")
758
+ parser.add_argument("-U", "--update", action="store_true", help="Update CodeFetch to the latest version from PyPI")
759
+ parser.add_argument("--uninstall", action="store_true", help="Uninstall CodeFetch from your system")
760
+ parser.add_argument("-y", "--yes", action="store_true", help="Confirm uninstall without prompting")
672
761
  parser.add_argument("-v", "--version", action="version", version=f"%(prog)s {__version__}")
673
762
  parser.add_argument("-h", "--help", action="help", help="Show help message")
674
763
 
@@ -738,6 +827,16 @@ def main():
738
827
  parser = build_parser()
739
828
  args = parser.parse_args()
740
829
 
830
+ # Handle --update
831
+ if args.update:
832
+ update_codefetch()
833
+ return
834
+
835
+ # Handle --uninstall
836
+ if args.uninstall:
837
+ uninstall_codefetch(yes=args.yes)
838
+ return
839
+
741
840
  config = load_config()
742
841
  default_owner = config.get("owner", DEFAULT_OWNER)
743
842
  default_repo = config.get("repo", DEFAULT_REPO)
@@ -776,7 +875,6 @@ def main():
776
875
  print("CodeFetch Configuration:")
777
876
  print(f" Default User: {default_owner or 'None (not set)'}")
778
877
  print(f" Default Repository: {default_repo or 'None (not set)'}")
779
- print(" Default Branch: None (auto-detect repository default)")
780
878
  print(f" Config File: {CONFIG_FILE}")
781
879
  return
782
880
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: codefetch-cli
3
- Version: 1.2.4
3
+ Version: 1.2.6
4
4
  Summary: Quickly fetch code files from GitHub repositories with simple commands
5
5
  Home-page: https://github.com/InzamamulQureshi/Codefetch
6
6
  Author: Inzamamul Qureshi
@@ -35,6 +35,8 @@ CodeFetch is a lightweight command-line utility and Python library designed to q
35
35
  - **Automatic Path & Case Resolution**: Automatically resolves case mismatches and finds files nested inside subdirectories.
36
36
  - **Repository Discovery**: List all public repositories for any GitHub user with `--repos`.
37
37
  - **Tree Exploration**: List all supported code files within a repository with `--list`.
38
+ - **Self-Updating**: Keep CodeFetch updated to the latest PyPI release with `codefetch --update`.
39
+ - **Clean Uninstall**: Easily remove CodeFetch and its configuration with `codefetch --uninstall`.
38
40
  - **Python Library Support**: Import and use programmatically with `import codefetch as cf`.
39
41
  - **Optional Persistent Defaults**: Save a default repository or user with `--set-default` if you frequently work with the same repository.
40
42
  - **Zero Runtime Dependencies**: Built using only the Python standard library with zero third-party dependencies.
@@ -129,6 +131,16 @@ codefetch --config
129
131
  codefetch --reset-config
130
132
  ```
131
133
 
134
+ ### 5. Package Management
135
+
136
+ ```bash
137
+ # Update CodeFetch to the latest version published on PyPI
138
+ codefetch --update
139
+
140
+ # Uninstall CodeFetch and remove local configuration
141
+ codefetch --uninstall
142
+ ```
143
+
132
144
  ---
133
145
 
134
146
  ## Python API Usage
@@ -163,11 +175,13 @@ print(f"Found {len(files)} files")
163
175
  | `-R`, `--repos` | List public repositories for a user | `codefetch -R -u username` |
164
176
  | `-r`, `--repo` | Specify repository name or URL | `codefetch -r repo main.py` |
165
177
  | `-u`, `--user` | Specify GitHub username or organization | `codefetch -u username -r repo main.py` |
166
- | `-b`, `--branch` | Branch name (default: `main`) | `codefetch -b master owner/repo Makefile` |
178
+ | `-b`, `--branch` | Branch name (default: repo default branch) | `codefetch -b master owner/repo Makefile` |
167
179
  | `--set-default` | Set persistent default repository | `codefetch --set-default owner/repo` |
168
180
  | `--set-default-user` | Set persistent default user | `codefetch --set-default-user username` |
169
181
  | `--config` | Display active configuration | `codefetch --config` |
170
182
  | `--reset-config` | Reset configuration back to defaults | `codefetch --reset-config` |
183
+ | `-U`, `--update` | Update CodeFetch to latest PyPI release | `codefetch --update` |
184
+ | `--uninstall` | Uninstall CodeFetch from your system | `codefetch --uninstall` |
171
185
  | `-v`, `--version` | Display version information | `codefetch --version` |
172
186
  | `-h`, `--help` | Display help and usage message | `codefetch --help` |
173
187
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "codefetch-cli"
7
- version = "1.2.4"
7
+ version = "1.2.6"
8
8
  description = "Quickly fetch code files from GitHub repositories with simple commands"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -7,7 +7,7 @@ long_description = readme_path.read_text(encoding="utf-8") if readme_path.exists
7
7
 
8
8
  setup(
9
9
  name="codefetch-cli",
10
- version="1.2.4",
10
+ version="1.2.6",
11
11
  description="Quickly fetch code files from GitHub repositories with simple commands",
12
12
  long_description=long_description,
13
13
  long_description_content_type="text/markdown",
File without changes
File without changes