@codebend3r/che 1.0.0

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.
Files changed (45) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +424 -0
  3. package/bin/che.py +869 -0
  4. package/bin/commands.py +872 -0
  5. package/bin/drives/eject-all-drives.py +203 -0
  6. package/bin/drives/mount-all-drives.py +140 -0
  7. package/bin/drives/ping-nas.py +242 -0
  8. package/bin/files/compress-folders.py +188 -0
  9. package/bin/files/delete-by-ext.py +108 -0
  10. package/bin/files/delete-empty-folders.py +136 -0
  11. package/bin/files/delete-smb-files.py +105 -0
  12. package/bin/files/files-under-size.py +132 -0
  13. package/bin/files/find-largest-files.py +102 -0
  14. package/bin/files/make-alpha-dir.py +63 -0
  15. package/bin/git/all-actions.py +545 -0
  16. package/bin/git/checkout-my-branches.py +147 -0
  17. package/bin/git/clean-stale-branches.py +161 -0
  18. package/bin/git/prune-worktrees.py +143 -0
  19. package/bin/git/sync-all-branches.py +368 -0
  20. package/bin/git/update-local-branches.py +195 -0
  21. package/bin/install.py +1515 -0
  22. package/bin/shellgen.py +782 -0
  23. package/bin/system/btop-launch.py +114 -0
  24. package/bin/system/update-brew.py +146 -0
  25. package/bin/tui.py +648 -0
  26. package/bin/utils.py +836 -0
  27. package/bin/video/delete-duplicate-videos.py +313 -0
  28. package/bin/video/detect-green-magenta-videos.py +268 -0
  29. package/bin/video/find-movie-by-year.py +84 -0
  30. package/bin/video/find-video-mkv-issues.py +242 -0
  31. package/bin/video/fix-codecs.py +209 -0
  32. package/bin/video/largest-tv-shows.py +175 -0
  33. package/bin/video/remove-metadata.py +126 -0
  34. package/bin/video/rename-video-file.py +329 -0
  35. package/bin/video/scan-videos-audio-language.py +110 -0
  36. package/bin/video/show-codecs.py +111 -0
  37. package/bin/video/validate-video-files.py +114 -0
  38. package/bin/video/video-list.py +120 -0
  39. package/package.json +54 -0
  40. package/shell/che.bash +382 -0
  41. package/shell/che.fish +282 -0
  42. package/shell/che.zsh +389 -0
  43. package/shell/completions/_che +146 -0
  44. package/shell/completions/che.bash +107 -0
  45. package/shell/completions/che.fish +371 -0
@@ -0,0 +1,195 @@
1
+ #!/usr/bin/env python3
2
+ """⬇️ For each local branch with an upstream, rebase onto origin.
3
+
4
+ Conflicts are aborted and reported; the script keeps going.
5
+
6
+ Usage:
7
+ update-local-branches.py [--limit=N] [--dry-run]
8
+
9
+ Options:
10
+ --limit=N Only update the N most recently committed branches
11
+ --dry-run List branches that would be updated, change nothing
12
+ --help Show help
13
+ """
14
+
15
+ from __future__ import annotations
16
+
17
+ import re
18
+ import sys
19
+ from pathlib import Path
20
+
21
+ sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
22
+
23
+ from utils import (
24
+ add_bool_flag,
25
+ build_parser,
26
+ info,
27
+ log,
28
+ note,
29
+ require_binary,
30
+ run,
31
+ run_cli,
32
+ run_lines,
33
+ run_output,
34
+ success,
35
+ warning,
36
+ worktree_branch_map,
37
+ worktree_is_clean,
38
+ )
39
+
40
+ __version__ = "3.1.0"
41
+
42
+
43
+ def branches_with_upstream() -> list[str]:
44
+ """Local branches that have an upstream, most recently committed first.
45
+
46
+ The separator is \\x01, not the shell version's ``|``. A branch name may
47
+ legally contain a pipe (``git check-ref-format`` allows it), and splitting
48
+ on ``|`` then treating the whole remainder as the upstream reports such a
49
+ branch as *having* an upstream when it does not - after which
50
+ ``git pull --rebase`` fails on it and the run exits non-zero. Control
51
+ characters are illegal in ref names, so \\x01 cannot collide.
52
+ """
53
+ found = []
54
+ for line in run_lines(
55
+ [
56
+ "git",
57
+ "for-each-ref",
58
+ "--sort=-committerdate",
59
+ "--format=%(refname:short)%01%(upstream)",
60
+ "refs/heads/",
61
+ ]
62
+ ):
63
+ branch, _, upstream = line.partition("\x01")
64
+ if branch and upstream:
65
+ found.append(branch)
66
+ return found
67
+
68
+
69
+ def main(argv: list[str] | None = None) -> int:
70
+ parser = build_parser(
71
+ prog="update-local-branches",
72
+ description="⬇️ Rebase every local branch that has an upstream onto origin.",
73
+ )
74
+ # Kept as a string, not `type=int`: argparse's own int conversion would
75
+ # own the failure and exit before the shell version's message could print.
76
+ parser.add_argument(
77
+ "--limit",
78
+ default="0",
79
+ metavar="N",
80
+ help="Only update the N most recently committed branches",
81
+ )
82
+ add_bool_flag(
83
+ parser,
84
+ "--dry-run",
85
+ help="List branches that would be updated, change nothing",
86
+ )
87
+ args = parser.parse_args(argv)
88
+
89
+ if not re.fullmatch(r"[0-9]+", args.limit):
90
+ warning(f"❌ --limit must be a non-negative integer (got: {args.limit})")
91
+ return 1
92
+ limit = int(args.limit)
93
+
94
+ require_binary("git")
95
+
96
+ header_suffix = " 🌵 (dry run)" if args.dry_run else ""
97
+ note("═══════════════════════════════════════════")
98
+ note(f"⬇️ update-local-branches{header_suffix}")
99
+ note("═══════════════════════════════════════════")
100
+
101
+ original_branch = run_output(
102
+ ["git", "symbolic-ref", "--quiet", "--short", "HEAD"], check=False
103
+ ).strip()
104
+ if not original_branch:
105
+ warning("❌ Detached HEAD — check out a branch first.")
106
+ return 1
107
+
108
+ if not args.dry_run and run_output(["git", "status", "--porcelain"]):
109
+ warning("❌ Working tree is dirty. Commit or stash before running. 🧺")
110
+ return 1
111
+
112
+ info("📡 Fetching remotes...")
113
+ run(["git", "fetch", "--all", "--quiet"])
114
+
115
+ branches = branches_with_upstream()
116
+ if limit > 0:
117
+ branches = branches[:limit]
118
+
119
+ if not branches:
120
+ info("ℹ️ No local branches with upstreams.") # noqa: RUF001
121
+ return 0
122
+
123
+ if args.dry_run:
124
+ info(f"🌵 Would update {len(branches)} branch(es):")
125
+ for branch in branches:
126
+ info(f" • 🌿 {branch}")
127
+ return 0
128
+
129
+ succeeded: list[str] = []
130
+ failed: list[str] = []
131
+
132
+ # One `git worktree list` for the whole run, not one per branch as the
133
+ # shell's per-branch `worktree_for_branch` did.
134
+ pinned_by_branch = worktree_branch_map()
135
+ here = Path.cwd().resolve()
136
+
137
+ for branch in branches:
138
+ # A branch checked out in another worktree cannot be checked out here —
139
+ # git refuses with "already used by worktree". That's a mechanical
140
+ # limit, not a conflict, so update it in place rather than counting it
141
+ # as a failure.
142
+ pinned = pinned_by_branch.get(branch, "")
143
+
144
+ if pinned and Path(pinned).resolve() != here:
145
+ if not worktree_is_clean(pinned):
146
+ warning(f" ⏭️ {branch} — worktree is dirty ({pinned}), skipping")
147
+ failed.append(branch)
148
+ continue
149
+
150
+ log(f"⬇️ Rebasing {branch} in its worktree ({pinned})")
151
+ rebase = run(["git", "-C", pinned, "pull", "--rebase", "--quiet"], check=False)
152
+ if rebase.returncode == 0:
153
+ success(f" ✅ {branch} up to date (in {pinned})")
154
+ succeeded.append(branch)
155
+ else:
156
+ warning(" ❌ rebase failed — aborting and moving on")
157
+ run(["git", "-C", pinned, "rebase", "--abort"], check=False, capture=True)
158
+ failed.append(branch)
159
+ continue
160
+
161
+ info(f"📂 Switching to 🌿 {branch}")
162
+ checkout = run(["git", "checkout", "--quiet", branch], check=False, capture=True)
163
+ if checkout.returncode != 0:
164
+ warning(" ✗ checkout failed, skipping")
165
+ failed.append(branch)
166
+ continue
167
+
168
+ log(f"⬇️ Rebasing {branch} onto upstream")
169
+ pull = run(["git", "pull", "--rebase", "--quiet"], check=False)
170
+ if pull.returncode == 0:
171
+ success(f" ✅ {branch} up to date")
172
+ succeeded.append(branch)
173
+ else:
174
+ warning(" ❌ rebase failed — aborting and moving on")
175
+ run(["git", "rebase", "--abort"], check=False, capture=True)
176
+ failed.append(branch)
177
+
178
+ info(f"🔁 Returning to 🌿 {original_branch}")
179
+ run(["git", "checkout", "--quiet", original_branch])
180
+
181
+ print()
182
+ success("═══ summary ═══")
183
+ success(f"✅ Updated: {len(succeeded)}")
184
+ if failed:
185
+ warning(f"❌ Failed: {len(failed)}")
186
+ for branch in failed:
187
+ warning(f" • 💥 {branch}")
188
+ return 1
189
+
190
+ success("🎉 All clean!")
191
+ return 0
192
+
193
+
194
+ if __name__ == "__main__":
195
+ run_cli(main)