pygitgo 1.6.0__tar.gz → 1.6.2__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.
Files changed (44) hide show
  1. {pygitgo-1.6.0/src/pygitgo.egg-info → pygitgo-1.6.2}/PKG-INFO +51 -32
  2. {pygitgo-1.6.0 → pygitgo-1.6.2}/README.md +49 -31
  3. {pygitgo-1.6.0 → pygitgo-1.6.2}/pyproject.toml +6 -1
  4. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/commands/git_operations.py +5 -4
  5. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/commands/jump.py +12 -11
  6. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/commands/pull.py +8 -6
  7. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/commands/state.py +10 -12
  8. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/commands/undo.py +13 -18
  9. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/main.py +18 -15
  10. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/utils/setup.py +2 -1
  11. {pygitgo-1.6.0 → pygitgo-1.6.2/src/pygitgo.egg-info}/PKG-INFO +51 -32
  12. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo.egg-info/requires.txt +1 -0
  13. {pygitgo-1.6.0 → pygitgo-1.6.2}/tests/test_config.py +1 -1
  14. {pygitgo-1.6.0 → pygitgo-1.6.2}/tests/test_git_operations.py +4 -6
  15. {pygitgo-1.6.0 → pygitgo-1.6.2}/tests/test_jump.py +0 -2
  16. {pygitgo-1.6.0 → pygitgo-1.6.2}/tests/test_pull.py +7 -15
  17. {pygitgo-1.6.0 → pygitgo-1.6.2}/tests/test_setup.py +1 -1
  18. {pygitgo-1.6.0 → pygitgo-1.6.2}/tests/test_state.py +9 -20
  19. {pygitgo-1.6.0 → pygitgo-1.6.2}/tests/test_undo.py +10 -19
  20. {pygitgo-1.6.0 → pygitgo-1.6.2}/LICENSE +0 -0
  21. {pygitgo-1.6.0 → pygitgo-1.6.2}/setup.cfg +0 -0
  22. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/__init__.py +0 -0
  23. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/auth/__init__.py +0 -0
  24. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/auth/account.py +0 -0
  25. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/auth/manager.py +0 -0
  26. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/auth/ssh_utils.py +0 -0
  27. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/commands/__init__.py +0 -0
  28. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/commands/staging.py +0 -0
  29. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/exceptions.py +0 -0
  30. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/utils/__init__.py +0 -0
  31. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/utils/colors.py +0 -0
  32. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/utils/config.py +0 -0
  33. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/utils/executor.py +0 -0
  34. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/utils/platform_utils.py +0 -0
  35. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo/utils/update_checker.py +0 -0
  36. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo.egg-info/SOURCES.txt +0 -0
  37. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo.egg-info/dependency_links.txt +0 -0
  38. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo.egg-info/entry_points.txt +0 -0
  39. {pygitgo-1.6.0 → pygitgo-1.6.2}/src/pygitgo.egg-info/top_level.txt +0 -0
  40. {pygitgo-1.6.0 → pygitgo-1.6.2}/tests/test_main.py +0 -0
  41. {pygitgo-1.6.0 → pygitgo-1.6.2}/tests/test_platform.py +0 -0
  42. {pygitgo-1.6.0 → pygitgo-1.6.2}/tests/test_staging.py +0 -0
  43. {pygitgo-1.6.0 → pygitgo-1.6.2}/tests/test_update_checker.py +0 -0
  44. {pygitgo-1.6.0 → pygitgo-1.6.2}/tests/test_url_validator.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pygitgo
3
- Version: 1.6.0
3
+ Version: 1.6.2
4
4
  Summary: GitGo CLI - Your Fast Git Companion. Simplifies git push, link, stash, and user management.
5
5
  Author: Huerte
6
6
  License: GPL-3.0-or-later
@@ -20,11 +20,12 @@ Requires-Dist: pick>=2.0
20
20
  Provides-Extra: dev
21
21
  Requires-Dist: pytest>=7.0; extra == "dev"
22
22
  Requires-Dist: pytest-mock>=3.10; extra == "dev"
23
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
23
24
  Dynamic: license-file
24
25
 
25
26
  <div align="center">
26
27
 
27
- # GitGo
28
+ ![GitGo Banner](assets/banner.png)
28
29
 
29
30
  [![Tests](https://github.com/Huerte/GitGo/actions/workflows/tests.yml/badge.svg)](https://github.com/Huerte/GitGo/actions)
30
31
  [![PyPI version](https://img.shields.io/pypi/v/pygitgo?color=blue&label=PyPI)](https://pypi.org/project/pygitgo)
@@ -38,6 +39,14 @@ Dynamic: license-file
38
39
 
39
40
  <a href="https://github.com/Huerte/GitGo/issues">Report Bug</a> · <a href="https://github.com/Huerte/GitGo/issues">Request Feature</a>
40
41
 
42
+ <br />
43
+
44
+ If GitGo saves you time, consider buying me a coffee. It helps keep the project going.
45
+
46
+ <a href="https://ko-fi.com/huerte">
47
+ <img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="Support on Ko-fi" />
48
+ </a>
49
+
41
50
  </div>
42
51
 
43
52
  ---
@@ -63,7 +72,10 @@ gitgo link https://github.com/username/repo.git "init"
63
72
  - [Command Reference](#command-reference)
64
73
  - [How It Works](#how-it-works)
65
74
  - [Contributing](#contributing)
75
+ - [Credits](#credits)
66
76
  - [License](#license)
77
+ - [Changelog](CHANGELOG.md)
78
+ - [Contributing Guide](CONTRIBUTING.md)
67
79
 
68
80
  ---
69
81
 
@@ -75,17 +87,18 @@ gitgo link https://github.com/username/repo.git "init"
75
87
 
76
88
  ## Features
77
89
 
78
- GitGo provides a CLI environment designed for faster and simpler Git workflows. Built to be intuitive, fast, and frictionless.
90
+ GitGo provides a CLI environment designed for faster and simpler Git workflows.
91
+ No chained commands, no cryptic flags — just short commands you can actually remember.
79
92
 
80
- - **Simplified Git Operations:** Replaces chained commands with single intuitive commands for linking, pushing, and stashing.
81
- - **Easy Undo Operations:** Safely undo commits, un-queue files, or wipe local changes without any complex Git jargon.
82
- - **Smart Branch Hopping:** Safely traverse branches with `jump`. Auto-stashes messy code and prevents merge conflict disasters with a Try-And-Revert safety engine.
93
+ - **Simplified Git Operations:** Replaces chained commands with single commands for linking, pushing, and stashing.
94
+ - **Undo Operations:** Safely undo commits, un-queue files, or wipe local changes without any complex Git jargon.
95
+ - **Safe Branch Switching:** Safely traverse branches with `jump`. Auto-stashes messy code and prevents merge conflict disasters with a Try-And-Revert safety engine.
83
96
  - **State Management:** A human-readable interface over `git stash`. States are named and listed by index so you never have to remember cryptic stash references.
84
97
  - **Custom Defaults:** Save your preferred branch name and commit message locally so you never have to type them again.
85
98
  - **Auto-Update Checker:** Silently checks for newer versions in the background and notifies you, without slowing down your commands.
86
99
  - **SSH Auto-Setup:** Generates an SSH key, adds it to `ssh-agent`, and opens your GitHub settings automatically.
87
100
  - **HTTPS to SSH Conversion:** Silently converts the remote to SSH before pushing if your SSH is configured.
88
- - **Termux Compatibility:** Works natively on Android natively handling common issues like dubious ownership errors.
101
+ - **Termux Compatibility:** Works on Android via Termux, handling common issues like dubious ownership errors out of the box.
89
102
 
90
103
  ---
91
104
 
@@ -94,16 +107,38 @@ GitGo provides a CLI environment designed for faster and simpler Git workflows.
94
107
  ### Prerequisites
95
108
 
96
109
  - **Python 3.8+**
97
- - **Git 2.x+** [git-scm.com](https://git-scm.com)
98
- - **OpenSSH** required for `gitgo user login` (pre-installed on most systems)
110
+ - **Git 2.x+**: [git-scm.com](https://git-scm.com)
111
+ - **OpenSSH**: required for `gitgo user login` (pre-installed on most systems)
99
112
  - A **GitHub account**
100
113
 
101
114
  ### Install from PyPI
102
115
 
116
+ For Windows users or environments without global pip restrictions, you can install GitGo directly via pip:
117
+
103
118
  ```bash
104
119
  pip install pygitgo
105
120
  ```
106
121
 
122
+ *(Alternatively, you can use `pipx install pygitgo` if you prefer isolated environments).*
123
+
124
+ ### Install via pipx (Cross-Platform)
125
+
126
+ If you already have `pipx` installed, you can use it to safely install GitGo on any operating system:
127
+
128
+ ```bash
129
+ pipx install pygitgo
130
+ ```
131
+
132
+ ### Quick Install (Linux & macOS)
133
+
134
+ The easiest way to install GitGo on Unix systems without worrying about Python environments or PEP 668 restrictions is using our install script:
135
+
136
+ ```bash
137
+ curl -sSL https://raw.githubusercontent.com/Huerte/GitGo/main/install.sh | bash
138
+ ```
139
+
140
+ This will automatically create an isolated environment and place `gitgo` in your `~/.local/bin` folder.
141
+
107
142
  Verify the installation:
108
143
 
109
144
  ```bash
@@ -142,13 +177,13 @@ gitgo link https://github.com/username/repo.git "Initial commit"
142
177
  gitgo push main "Fix auth bug"
143
178
 
144
179
  # Create a new branch and push
145
- gitgo push -n feature/login "Add login flow"
180
+ gitgo push -n feat/login "Add login flow"
146
181
  ```
147
182
 
148
183
  ### 4. Safely Switch Branches
149
184
  Jump to a different branch without worrying about your uncommitted changes. GitGo will safely stash them, hop to the new branch, sync with `main`, and carefully unpack them.
150
185
  ```bash
151
- gitgo jump feature/new-login
186
+ gitgo jump feat/new-login
152
187
  ```
153
188
 
154
189
  ### 5. Safely Undo Mistakes
@@ -225,7 +260,7 @@ gitgo jump <branch>
225
260
 
226
261
  ### `gitgo undo`
227
262
 
228
- Safely undo recent actions and mistakes using simple, human-readable commands.
263
+ Safely undo recent actions and mistakes using plain commands that say exactly what they do.
229
264
 
230
265
  ```bash
231
266
  gitgo undo commit # Undo your last commit without losing files
@@ -235,7 +270,7 @@ gitgo undo changes # Permanently wipe all new files and local edits
235
270
 
236
271
  ### `gitgo state`
237
272
 
238
- A human-readable interface over `git stash`.
273
+ A named interface over `git stash`.
239
274
 
240
275
  ```bash
241
276
  gitgo state list # show all saved states
@@ -291,13 +326,9 @@ gitgo -r # verify GitGo is ready
291
326
 
292
327
  ## Contributing
293
328
 
294
- Contributions are welcome and appreciated!
295
-
296
- 1. Fork the Project
297
- 2. Create a Feature Branch (`git checkout -b feature/your-feature`)
298
- 3. Commit Changes
299
- 4. Push to the Branch (`git push origin feature/your-feature`)
300
- 5. Open a Pull Request
329
+ Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide,
330
+ including project structure, test instructions, commit conventions, and a
331
+ [Good First Issues](CONTRIBUTING.md#good-first-issues) table if you are not sure where to start.
301
332
 
302
333
  ---
303
334
 
@@ -314,18 +345,6 @@ Contributions are welcome and appreciated!
314
345
 
315
346
  ---
316
347
 
317
- ## Support
318
-
319
- If GitGo saves you time, consider buying me a coffee. It helps keep the project going.
320
-
321
- <div align="center">
322
- <a href="https://ko-fi.com/huerte">
323
- <img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="Support on Ko-fi" />
324
- </a>
325
- </div>
326
-
327
- ---
328
-
329
348
  ## License
330
349
 
331
350
  Distributed under the **GPLv3** License. See [`LICENSE`](LICENSE) for details.
@@ -1,6 +1,6 @@
1
1
  <div align="center">
2
2
 
3
- # GitGo
3
+ ![GitGo Banner](assets/banner.png)
4
4
 
5
5
  [![Tests](https://github.com/Huerte/GitGo/actions/workflows/tests.yml/badge.svg)](https://github.com/Huerte/GitGo/actions)
6
6
  [![PyPI version](https://img.shields.io/pypi/v/pygitgo?color=blue&label=PyPI)](https://pypi.org/project/pygitgo)
@@ -14,6 +14,14 @@
14
14
 
15
15
  <a href="https://github.com/Huerte/GitGo/issues">Report Bug</a> · <a href="https://github.com/Huerte/GitGo/issues">Request Feature</a>
16
16
 
17
+ <br />
18
+
19
+ If GitGo saves you time, consider buying me a coffee. It helps keep the project going.
20
+
21
+ <a href="https://ko-fi.com/huerte">
22
+ <img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="Support on Ko-fi" />
23
+ </a>
24
+
17
25
  </div>
18
26
 
19
27
  ---
@@ -39,7 +47,10 @@ gitgo link https://github.com/username/repo.git "init"
39
47
  - [Command Reference](#command-reference)
40
48
  - [How It Works](#how-it-works)
41
49
  - [Contributing](#contributing)
50
+ - [Credits](#credits)
42
51
  - [License](#license)
52
+ - [Changelog](CHANGELOG.md)
53
+ - [Contributing Guide](CONTRIBUTING.md)
43
54
 
44
55
  ---
45
56
 
@@ -51,17 +62,18 @@ gitgo link https://github.com/username/repo.git "init"
51
62
 
52
63
  ## Features
53
64
 
54
- GitGo provides a CLI environment designed for faster and simpler Git workflows. Built to be intuitive, fast, and frictionless.
65
+ GitGo provides a CLI environment designed for faster and simpler Git workflows.
66
+ No chained commands, no cryptic flags — just short commands you can actually remember.
55
67
 
56
- - **Simplified Git Operations:** Replaces chained commands with single intuitive commands for linking, pushing, and stashing.
57
- - **Easy Undo Operations:** Safely undo commits, un-queue files, or wipe local changes without any complex Git jargon.
58
- - **Smart Branch Hopping:** Safely traverse branches with `jump`. Auto-stashes messy code and prevents merge conflict disasters with a Try-And-Revert safety engine.
68
+ - **Simplified Git Operations:** Replaces chained commands with single commands for linking, pushing, and stashing.
69
+ - **Undo Operations:** Safely undo commits, un-queue files, or wipe local changes without any complex Git jargon.
70
+ - **Safe Branch Switching:** Safely traverse branches with `jump`. Auto-stashes messy code and prevents merge conflict disasters with a Try-And-Revert safety engine.
59
71
  - **State Management:** A human-readable interface over `git stash`. States are named and listed by index so you never have to remember cryptic stash references.
60
72
  - **Custom Defaults:** Save your preferred branch name and commit message locally so you never have to type them again.
61
73
  - **Auto-Update Checker:** Silently checks for newer versions in the background and notifies you, without slowing down your commands.
62
74
  - **SSH Auto-Setup:** Generates an SSH key, adds it to `ssh-agent`, and opens your GitHub settings automatically.
63
75
  - **HTTPS to SSH Conversion:** Silently converts the remote to SSH before pushing if your SSH is configured.
64
- - **Termux Compatibility:** Works natively on Android natively handling common issues like dubious ownership errors.
76
+ - **Termux Compatibility:** Works on Android via Termux, handling common issues like dubious ownership errors out of the box.
65
77
 
66
78
  ---
67
79
 
@@ -70,16 +82,38 @@ GitGo provides a CLI environment designed for faster and simpler Git workflows.
70
82
  ### Prerequisites
71
83
 
72
84
  - **Python 3.8+**
73
- - **Git 2.x+** [git-scm.com](https://git-scm.com)
74
- - **OpenSSH** required for `gitgo user login` (pre-installed on most systems)
85
+ - **Git 2.x+**: [git-scm.com](https://git-scm.com)
86
+ - **OpenSSH**: required for `gitgo user login` (pre-installed on most systems)
75
87
  - A **GitHub account**
76
88
 
77
89
  ### Install from PyPI
78
90
 
91
+ For Windows users or environments without global pip restrictions, you can install GitGo directly via pip:
92
+
79
93
  ```bash
80
94
  pip install pygitgo
81
95
  ```
82
96
 
97
+ *(Alternatively, you can use `pipx install pygitgo` if you prefer isolated environments).*
98
+
99
+ ### Install via pipx (Cross-Platform)
100
+
101
+ If you already have `pipx` installed, you can use it to safely install GitGo on any operating system:
102
+
103
+ ```bash
104
+ pipx install pygitgo
105
+ ```
106
+
107
+ ### Quick Install (Linux & macOS)
108
+
109
+ The easiest way to install GitGo on Unix systems without worrying about Python environments or PEP 668 restrictions is using our install script:
110
+
111
+ ```bash
112
+ curl -sSL https://raw.githubusercontent.com/Huerte/GitGo/main/install.sh | bash
113
+ ```
114
+
115
+ This will automatically create an isolated environment and place `gitgo` in your `~/.local/bin` folder.
116
+
83
117
  Verify the installation:
84
118
 
85
119
  ```bash
@@ -118,13 +152,13 @@ gitgo link https://github.com/username/repo.git "Initial commit"
118
152
  gitgo push main "Fix auth bug"
119
153
 
120
154
  # Create a new branch and push
121
- gitgo push -n feature/login "Add login flow"
155
+ gitgo push -n feat/login "Add login flow"
122
156
  ```
123
157
 
124
158
  ### 4. Safely Switch Branches
125
159
  Jump to a different branch without worrying about your uncommitted changes. GitGo will safely stash them, hop to the new branch, sync with `main`, and carefully unpack them.
126
160
  ```bash
127
- gitgo jump feature/new-login
161
+ gitgo jump feat/new-login
128
162
  ```
129
163
 
130
164
  ### 5. Safely Undo Mistakes
@@ -201,7 +235,7 @@ gitgo jump <branch>
201
235
 
202
236
  ### `gitgo undo`
203
237
 
204
- Safely undo recent actions and mistakes using simple, human-readable commands.
238
+ Safely undo recent actions and mistakes using plain commands that say exactly what they do.
205
239
 
206
240
  ```bash
207
241
  gitgo undo commit # Undo your last commit without losing files
@@ -211,7 +245,7 @@ gitgo undo changes # Permanently wipe all new files and local edits
211
245
 
212
246
  ### `gitgo state`
213
247
 
214
- A human-readable interface over `git stash`.
248
+ A named interface over `git stash`.
215
249
 
216
250
  ```bash
217
251
  gitgo state list # show all saved states
@@ -267,13 +301,9 @@ gitgo -r # verify GitGo is ready
267
301
 
268
302
  ## Contributing
269
303
 
270
- Contributions are welcome and appreciated!
271
-
272
- 1. Fork the Project
273
- 2. Create a Feature Branch (`git checkout -b feature/your-feature`)
274
- 3. Commit Changes
275
- 4. Push to the Branch (`git push origin feature/your-feature`)
276
- 5. Open a Pull Request
304
+ Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide,
305
+ including project structure, test instructions, commit conventions, and a
306
+ [Good First Issues](CONTRIBUTING.md#good-first-issues) table if you are not sure where to start.
277
307
 
278
308
  ---
279
309
 
@@ -290,18 +320,6 @@ Contributions are welcome and appreciated!
290
320
 
291
321
  ---
292
322
 
293
- ## Support
294
-
295
- If GitGo saves you time, consider buying me a coffee. It helps keep the project going.
296
-
297
- <div align="center">
298
- <a href="https://ko-fi.com/huerte">
299
- <img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="Support on Ko-fi" />
300
- </a>
301
- </div>
302
-
303
- ---
304
-
305
323
  ## License
306
324
 
307
325
  Distributed under the **GPLv3** License. See [`LICENSE`](LICENSE) for details.
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "pygitgo"
7
- version = "1.6.0"
7
+ version = "1.6.2"
8
8
  description = "GitGo CLI - Your Fast Git Companion. Simplifies git push, link, stash, and user management."
9
9
  readme = "README.md"
10
10
  license = {text = "GPL-3.0-or-later"}
@@ -29,6 +29,7 @@ dependencies = [
29
29
  dev = [
30
30
  "pytest>=7.0",
31
31
  "pytest-mock>=3.10",
32
+ "pytest-cov>=4.0"
32
33
  ]
33
34
 
34
35
  [project.urls]
@@ -40,3 +41,7 @@ gitgo = "pygitgo.main:main"
40
41
 
41
42
  [tool.setuptools.packages.find]
42
43
  where = ["src"]
44
+
45
+ [tool.pytest.ini_options]
46
+ testpaths = ["tests"]
47
+ addopts = "--cov=pygitgo --cov-report=term-missing"
@@ -2,6 +2,7 @@ from pygitgo.auth.ssh_utils import convert_https_to_ssh, is_ssh_url, check_conne
2
2
  from pygitgo.utils.colors import info, success, warning, error
3
3
  from pygitgo.utils.executor import run_command
4
4
  from pygitgo.utils.config import get_config
5
+ from pygitgo.exceptions import GitGoError
5
6
  from argparse import Namespace
6
7
  import subprocess
7
8
  import sys
@@ -11,7 +12,7 @@ import os
11
12
  def get_status_content():
12
13
  status = run_command(["git", "status", "--porcelain"], allow_fail=True)
13
14
  if isinstance(status, subprocess.CalledProcessError) or not status.strip():
14
- sys.exit(1)
15
+ raise GitGoError("\nWorking tree is clean. Nothing to commit.\n")
15
16
  return status
16
17
 
17
18
  def get_current_branch():
@@ -41,7 +42,7 @@ def git_new_branch(branch):
41
42
  from pygitgo.commands.jump import jump_operation
42
43
  jump_operation(Namespace(branch=branch))
43
44
  else:
44
- sys.exit(1)
45
+ raise GitGoError(f"\nOperation canceled. Branch '{branch}' already exists.\n")
45
46
  else:
46
47
  success(f"\nBranch '{branch}' created.\n")
47
48
 
@@ -161,7 +162,7 @@ def git_push(branch):
161
162
  if "rebase in progress" in str(e):
162
163
  handle_rebase()
163
164
  else:
164
- sys.exit(1)
165
+ raise GitGoError()
165
166
 
166
167
 
167
168
  def handle_rebase():
@@ -175,6 +176,6 @@ def handle_rebase():
175
176
  info(" git add <files>")
176
177
  info(" git rebase --continue")
177
178
  warning("When finished, run 'gitgo push <branch> <message>' again.\n")
178
- sys.exit(1)
179
+ raise GitGoError()
179
180
 
180
181
  return True
@@ -1,3 +1,4 @@
1
+ from pygitgo.exceptions import GitGoError
1
2
  from pygitgo.commands.git_operations import (
2
3
  is_branch_exist, get_current_branch, git_new_branch, get_main_branch
3
4
  )
@@ -30,12 +31,11 @@ def jump_operation(args):
30
31
 
31
32
  if original_branch == target_branch:
32
33
  warning(f"\nYou are already on branch '{target_branch}'.\n")
33
- sys.exit(0)
34
+ return
34
35
 
35
36
  has_changes = run_command(['git', 'status', '--porcelain'], allow_fail=True, loading_msg="Checking for uncommitted changes...")
36
37
  if isinstance(has_changes, subprocess.CalledProcessError):
37
- warning("\nUnable to check for uncommitted changes. Please ensure you're in a valid git repository.")
38
- sys.exit(1)
38
+ raise GitGoError("\nUnable to check for uncommitted changes. Please ensure you're in a valid git repository.\n")
39
39
 
40
40
  stashed_code = False
41
41
  if has_changes.strip():
@@ -43,12 +43,12 @@ def jump_operation(args):
43
43
  user_input = input("Do you want to move these changes to your new branch? (y/n): ").strip().lower()
44
44
  if user_input != 'y':
45
45
  warning("\nYou cannot switch branches with unsaved changes. Jump canceled.\n")
46
- sys.exit(0)
46
+ return
47
47
  else:
48
48
  stash_result = run_command(["git", "stash", "push", "-u", "-m", "GitGo Jump Auto-Stash"], allow_fail=True, loading_msg="Saving your changes before jumping...")
49
49
  if isinstance(stash_result, subprocess.CalledProcessError):
50
50
  warning("\nFailed to save your changes. Please resolve any issues and try again.")
51
- sys.exit(1)
51
+ raise GitGoError()
52
52
  info("\nYour changes have been saved. Jumping to the new branch...")
53
53
  stashed_code = True
54
54
 
@@ -61,7 +61,7 @@ def jump_operation(args):
61
61
  info("Exiting without jumping...\n")
62
62
  if stashed_code:
63
63
  run_command(["git", "stash", "pop"], loading_msg="Putting your unsaved changes back...")
64
- sys.exit(0)
64
+ return
65
65
 
66
66
  git_new_branch(target_branch)
67
67
  created_branch = target_branch
@@ -76,7 +76,7 @@ def jump_operation(args):
76
76
  user_input = input("Do you want to stay on the new branch without the latest updates? (y/n): ").strip().lower()
77
77
  if user_input != 'y':
78
78
  undo_jump_operation(original_branch, stashed_code, created_branch)
79
- sys.exit(1)
79
+ raise GitGoError()
80
80
  else:
81
81
  success(f"\nOkay! You are on the new branch, but without the latest updates from '{main_branch}'.")
82
82
 
@@ -91,17 +91,18 @@ def jump_operation(args):
91
91
 
92
92
  if conflict_choice != 'y':
93
93
  undo_jump_operation(original_branch, stashed_code, created_branch)
94
- sys.exit(0)
94
+ return
95
95
  else:
96
96
  success("\nOkay! You are on the new branch with your code.")
97
97
  warning("Please open your code editor RIGHT NOW to fix the conflicts!")
98
98
  info("Your stash backup is still saved. Run 'gitgo state list' to see it.\n")
99
- sys.exit(0)
99
+ return
100
100
  else:
101
101
  run_command(["git", "stash", "drop"], allow_fail=True, loading_msg="Cleaning up the temporary stash...")
102
102
  success(f"\nSuccess! You are now on '{target_branch}'.")
103
103
  success("Your unsaved code was moved here safely!\n")
104
- sys.exit(0)
104
+ return
105
105
  else:
106
106
  success(f"\nSuccess! You are now on '{target_branch}'.\n")
107
- sys.exit(0)
107
+ return
108
+
@@ -1,3 +1,4 @@
1
+ from pygitgo.exceptions import GitGoError
1
2
  from pygitgo.utils.colors import success, warning, error, info
2
3
  from pygitgo.utils.executor import run_command
3
4
  from pygitgo.exceptions import GitCommandError
@@ -17,7 +18,7 @@ def pull_operation(args):
17
18
  if isinstance(remote_refs, subprocess.CalledProcessError) or not remote_refs.strip():
18
19
  error(f"\nFailed! The branch '{branch}' does not exist on the remote server.")
19
20
  warning("You might need to push your local branch first.\n")
20
- sys.exit(1)
21
+ raise GitGoError()
21
22
 
22
23
  run_command(
23
24
  ["git", "pull", "--rebase", "--autostash", "origin", branch],
@@ -35,9 +36,10 @@ def pull_operation(args):
35
36
  info("2. Fix the red conflict lines in your files.")
36
37
  info("3. Save the files.")
37
38
  info("4. Run this command to finish: git rebase --continue\n")
38
- sys.exit(1)
39
+ raise GitGoError()
39
40
  else:
40
- error("\nFailed to pull updates from the server!")
41
- error("Please check your internet connection and try again.")
42
- error(f"Details: {e}\n")
43
- sys.exit(1)
41
+ raise GitGoError(
42
+ "\nFailed to pull updates from the server!"
43
+ "Please check your internet connection and try again."
44
+ f"Details: {e}\n"
45
+ )
@@ -1,3 +1,4 @@
1
+ from pygitgo.exceptions import GitGoError
1
2
  from pygitgo.utils.colors import info, highlight, error, warning, success
2
3
  from pygitgo.utils.executor import run_command
3
4
  import sys
@@ -19,7 +20,7 @@ def all_save_state():
19
20
 
20
21
  if not output:
21
22
  info("\nNo saved states found.\n")
22
- sys.exit(0)
23
+ return
23
24
 
24
25
  save_states = []
25
26
 
@@ -88,7 +89,7 @@ def ask_state_id(save_states):
88
89
  state_id = input(">> ").strip().lower()
89
90
  if state_id == 'q':
90
91
  warning("\nLoad operation cancelled by user.\n")
91
- sys.exit(0)
92
+ return
92
93
  proceed = validate_state_id(state_id, save_states)
93
94
 
94
95
  return state_id
@@ -106,10 +107,9 @@ def load_state(state_id=None):
106
107
  if state_id.isdigit():
107
108
  proceed = validate_state_id(state_id, save_states)
108
109
  if not proceed:
109
- sys.exit(1)
110
+ raise GitGoError()
110
111
  else:
111
- error(f"\nInvalid argument '{state_id}' for load operation. Expected a state ID.\n")
112
- sys.exit(1)
112
+ raise GitGoError(f"\nInvalid argument '{state_id}' for load operation. Expected a state ID.\n")
113
113
 
114
114
  if not proceed:
115
115
  state_id = ask_state_id(save_states)
@@ -141,18 +141,17 @@ def delete_state(identifier=None):
141
141
  if confirm.lower() == 'y':
142
142
  run_command(["git", "stash", "clear"])
143
143
  success("\nAll saved states deleted successfully.\n")
144
- sys.exit(0)
144
+ return
145
145
  else:
146
146
  warning("\nDelete operation cancelled by user.\n")
147
- sys.exit(0)
147
+ return
148
148
 
149
149
  elif not identifier.isdigit():
150
- error("\nInvalid input. Please enter a valid state ID.\n")
151
- sys.exit(1)
150
+ raise GitGoError("\nInvalid input. Please enter a valid state ID.\n")
152
151
 
153
152
  state_id = identifier
154
153
  if not validate_state_id(state_id, all_save_state()):
155
- sys.exit(1)
154
+ raise GitGoError()
156
155
 
157
156
  run_command(["git", "stash", "drop", str(int(state_id) - 1)])
158
157
  success(f"\nState with ID '{state_id}' deleted successfully.\n")
@@ -173,5 +172,4 @@ def state_operations(args):
173
172
  elif action == "delete":
174
173
  delete_state(identifier)
175
174
  else:
176
- error(f"\nUnknown state operation: {action}\n")
177
- sys.exit(1)
175
+ raise GitGoError(f"\nUnknown state operation: {action}\n")
@@ -1,3 +1,4 @@
1
+ from pygitgo.exceptions import GitGoError
1
2
  from pygitgo.utils.colors import success, warning, error, info
2
3
  from pygitgo.exceptions import GitCommandError
3
4
  from pygitgo.utils.executor import run_command
@@ -9,18 +10,15 @@ def undo_commit():
9
10
  run_command(["git", "reset", "--soft", "HEAD~"])
10
11
  success("\nSuccess! Your last commit is undone. Your files are safe.\n")
11
12
  except GitCommandError as e:
12
- error("\nFailed! You might not have any previous commits to undo yet.")
13
- error(f"Details: {e}\n")
14
- sys.exit(1)
13
+ raise GitGoError(
14
+ "\nFailed! You might not have any previous commits to undo yet."
15
+ f"Details: {e}\n"
16
+ )
15
17
 
16
18
 
17
19
  def undo_add():
18
- try:
19
- run_command(["git", "reset", "HEAD"])
20
- success("\nSuccess! Files are no longer ready to commit.\n")
21
- except GitCommandError as e:
22
- error(f"\n{e}\n")
23
- sys.exit(1)
20
+ run_command(["git", "reset", "HEAD"])
21
+ success("\nSuccess! Files are no longer ready to commit.\n")
24
22
 
25
23
 
26
24
  def undo_changes():
@@ -29,14 +27,11 @@ def undo_changes():
29
27
  if confirm.lower() != "y":
30
28
  info("\nCanceled. Your files are safe.\n")
31
29
  return
32
- try:
33
- run_command(["git", "reset", "--hard", "HEAD"], loading_msg="Throwing away edits...")
34
- run_command(["git", "clean", "-fd"], loading_msg="Removing new files...")
30
+
31
+ run_command(["git", "reset", "--hard", "HEAD"], loading_msg="Throwing away edits...")
32
+ run_command(["git", "clean", "-fd"], loading_msg="Removing new files...")
35
33
 
36
- success("\nSuccess! All changes are completely gone. You have a clean start.\n")
37
- except GitCommandError as e:
38
- error(f"\n{e}\n")
39
- sys.exit(1)
34
+ success("\nSuccess! All changes are completely gone. You have a clean start.\n")
40
35
 
41
36
 
42
37
  def undo_operations(args):
@@ -49,5 +44,5 @@ def undo_operations(args):
49
44
  elif action == "changes":
50
45
  undo_changes()
51
46
  else:
52
- error(f"\nUnknown undo operation: {action}\n")
53
- sys.exit(1)
47
+ raise GitGoError(f"\nUnknown undo operation: {action}\n")
48
+
@@ -38,10 +38,11 @@ def link_operation(args):
38
38
  repo_url = args.url
39
39
 
40
40
  if not validate_repo_url(repo_url):
41
- error("\nInvalid repository URL!")
42
- warning("Expected format: https://github.com/username/repo.git")
43
- warning(" or: git@github.com:username/repo.git\n")
44
- sys.exit(1)
41
+ raise GitGoError(
42
+ "\nInvalid repository URL!\n"
43
+ "Expected format: https://github.com/username/repo.git"
44
+ " or: git@github.com:username/repo.git\n"
45
+ )
45
46
 
46
47
  commit_message = args.message
47
48
 
@@ -106,8 +107,7 @@ def push_operation(args):
106
107
 
107
108
  if args.new:
108
109
  if not branch:
109
- error("\nBranch name required when using --new flag!\n")
110
- sys.exit(1)
110
+ raise GitGoError("\nBranch name required when using --new flag!\n")
111
111
  git_new_branch(branch)
112
112
  else:
113
113
  if branch and not message and not is_branch_exist(branch):
@@ -121,8 +121,7 @@ def push_operation(args):
121
121
  warning(f"You are currently on branch '{current_branch}', not '{branch}'.")
122
122
  user_choice = input(f"Do you want to switch to branch '{branch}'? (y/n): ").lower()
123
123
  if user_choice != 'y':
124
- error("\nPush aborted to prevent committing to the wrong branch.\n")
125
- sys.exit(1)
124
+ raise GitGoError("\nPush aborted to prevent committing to the wrong branch.\n")
126
125
  jump_operation(Namespace(branch=branch))
127
126
 
128
127
  elif not branch:
@@ -200,15 +199,14 @@ def user_management(args):
200
199
 
201
200
  if not action:
202
201
  display_current_user()
203
- sys.exit(0)
202
+ return
204
203
 
205
204
  if action == 'login':
206
205
  login()
207
206
  elif action == 'logout':
208
207
  logout()
209
208
  else:
210
- error(f"\nInvalid user operation '{action}'!\n")
211
- sys.exit(1)
209
+ raise GitGoError(f"\nInvalid user operation '{action}'!\n")
212
210
 
213
211
 
214
212
  def get_version():
@@ -226,7 +224,7 @@ def main():
226
224
  epilog="Use 'gitgo <command> -h' for help on a specific command."
227
225
  )
228
226
 
229
- parser.add_argument("-v", "-V", "--version", action="version", version=f"GitGo {get_version()}\nSupport GitGo: https://ko-fi.com/huerte")
227
+ parser.add_argument("-v", "-V", "--version", action="store_true", help="show program's version number and exit")
230
228
  parser.add_argument("-r", "--ready", action="store_true", help="Check tool readiness")
231
229
 
232
230
  subparsers = parser.add_subparsers(title="Commands", dest="command")
@@ -329,13 +327,18 @@ def main():
329
327
 
330
328
  args = parser.parse_args()
331
329
 
330
+ if getattr(args, 'version', False):
331
+ print(f"GitGo {get_version()}")
332
+ print(f"Support GitGo: https://ko-fi.com/huerte")
333
+ return
334
+
332
335
  if args.ready:
333
336
  info("\nALL UNITS ONLINE. GitGo STANDING BY. AWAITING COMMANDS...\n")
334
- sys.exit(0)
337
+ return
335
338
 
336
339
  if not args.command:
337
340
  parser.print_help()
338
- sys.exit(0)
341
+ return
339
342
 
340
343
  ensure_first_run_setup()
341
344
  check_for_updates_background(get_version())
@@ -358,7 +361,7 @@ def main():
358
361
  elif args.command == "pull":
359
362
  pull_operation(args)
360
363
  except GitGoError as e:
361
- error(f"\n{e}\n")
364
+ error(f"{e}")
362
365
  sys.exit(1)
363
366
 
364
367
  if __name__ == "__main__":
@@ -1,3 +1,4 @@
1
+ from pygitgo.exceptions import GitGoError
1
2
  from pygitgo.auth.ssh_utils import ensure_github_known_host
2
3
  from pygitgo.utils.config import get_config, set_config
3
4
  from pygitgo.utils.colors import error, info
@@ -11,7 +12,7 @@ def check_git_installed():
11
12
  error("\nGit is not installed or not found on your PATH!")
12
13
  info("Install Git from: https://git-scm.com/downloads")
13
14
  info("After installing, restart your terminal and try again.\n")
14
- sys.exit(1)
15
+ raise GitGoError()
15
16
 
16
17
 
17
18
  def ensure_first_run_setup():
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pygitgo
3
- Version: 1.6.0
3
+ Version: 1.6.2
4
4
  Summary: GitGo CLI - Your Fast Git Companion. Simplifies git push, link, stash, and user management.
5
5
  Author: Huerte
6
6
  License: GPL-3.0-or-later
@@ -20,11 +20,12 @@ Requires-Dist: pick>=2.0
20
20
  Provides-Extra: dev
21
21
  Requires-Dist: pytest>=7.0; extra == "dev"
22
22
  Requires-Dist: pytest-mock>=3.10; extra == "dev"
23
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
23
24
  Dynamic: license-file
24
25
 
25
26
  <div align="center">
26
27
 
27
- # GitGo
28
+ ![GitGo Banner](assets/banner.png)
28
29
 
29
30
  [![Tests](https://github.com/Huerte/GitGo/actions/workflows/tests.yml/badge.svg)](https://github.com/Huerte/GitGo/actions)
30
31
  [![PyPI version](https://img.shields.io/pypi/v/pygitgo?color=blue&label=PyPI)](https://pypi.org/project/pygitgo)
@@ -38,6 +39,14 @@ Dynamic: license-file
38
39
 
39
40
  <a href="https://github.com/Huerte/GitGo/issues">Report Bug</a> · <a href="https://github.com/Huerte/GitGo/issues">Request Feature</a>
40
41
 
42
+ <br />
43
+
44
+ If GitGo saves you time, consider buying me a coffee. It helps keep the project going.
45
+
46
+ <a href="https://ko-fi.com/huerte">
47
+ <img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="Support on Ko-fi" />
48
+ </a>
49
+
41
50
  </div>
42
51
 
43
52
  ---
@@ -63,7 +72,10 @@ gitgo link https://github.com/username/repo.git "init"
63
72
  - [Command Reference](#command-reference)
64
73
  - [How It Works](#how-it-works)
65
74
  - [Contributing](#contributing)
75
+ - [Credits](#credits)
66
76
  - [License](#license)
77
+ - [Changelog](CHANGELOG.md)
78
+ - [Contributing Guide](CONTRIBUTING.md)
67
79
 
68
80
  ---
69
81
 
@@ -75,17 +87,18 @@ gitgo link https://github.com/username/repo.git "init"
75
87
 
76
88
  ## Features
77
89
 
78
- GitGo provides a CLI environment designed for faster and simpler Git workflows. Built to be intuitive, fast, and frictionless.
90
+ GitGo provides a CLI environment designed for faster and simpler Git workflows.
91
+ No chained commands, no cryptic flags — just short commands you can actually remember.
79
92
 
80
- - **Simplified Git Operations:** Replaces chained commands with single intuitive commands for linking, pushing, and stashing.
81
- - **Easy Undo Operations:** Safely undo commits, un-queue files, or wipe local changes without any complex Git jargon.
82
- - **Smart Branch Hopping:** Safely traverse branches with `jump`. Auto-stashes messy code and prevents merge conflict disasters with a Try-And-Revert safety engine.
93
+ - **Simplified Git Operations:** Replaces chained commands with single commands for linking, pushing, and stashing.
94
+ - **Undo Operations:** Safely undo commits, un-queue files, or wipe local changes without any complex Git jargon.
95
+ - **Safe Branch Switching:** Safely traverse branches with `jump`. Auto-stashes messy code and prevents merge conflict disasters with a Try-And-Revert safety engine.
83
96
  - **State Management:** A human-readable interface over `git stash`. States are named and listed by index so you never have to remember cryptic stash references.
84
97
  - **Custom Defaults:** Save your preferred branch name and commit message locally so you never have to type them again.
85
98
  - **Auto-Update Checker:** Silently checks for newer versions in the background and notifies you, without slowing down your commands.
86
99
  - **SSH Auto-Setup:** Generates an SSH key, adds it to `ssh-agent`, and opens your GitHub settings automatically.
87
100
  - **HTTPS to SSH Conversion:** Silently converts the remote to SSH before pushing if your SSH is configured.
88
- - **Termux Compatibility:** Works natively on Android natively handling common issues like dubious ownership errors.
101
+ - **Termux Compatibility:** Works on Android via Termux, handling common issues like dubious ownership errors out of the box.
89
102
 
90
103
  ---
91
104
 
@@ -94,16 +107,38 @@ GitGo provides a CLI environment designed for faster and simpler Git workflows.
94
107
  ### Prerequisites
95
108
 
96
109
  - **Python 3.8+**
97
- - **Git 2.x+** [git-scm.com](https://git-scm.com)
98
- - **OpenSSH** required for `gitgo user login` (pre-installed on most systems)
110
+ - **Git 2.x+**: [git-scm.com](https://git-scm.com)
111
+ - **OpenSSH**: required for `gitgo user login` (pre-installed on most systems)
99
112
  - A **GitHub account**
100
113
 
101
114
  ### Install from PyPI
102
115
 
116
+ For Windows users or environments without global pip restrictions, you can install GitGo directly via pip:
117
+
103
118
  ```bash
104
119
  pip install pygitgo
105
120
  ```
106
121
 
122
+ *(Alternatively, you can use `pipx install pygitgo` if you prefer isolated environments).*
123
+
124
+ ### Install via pipx (Cross-Platform)
125
+
126
+ If you already have `pipx` installed, you can use it to safely install GitGo on any operating system:
127
+
128
+ ```bash
129
+ pipx install pygitgo
130
+ ```
131
+
132
+ ### Quick Install (Linux & macOS)
133
+
134
+ The easiest way to install GitGo on Unix systems without worrying about Python environments or PEP 668 restrictions is using our install script:
135
+
136
+ ```bash
137
+ curl -sSL https://raw.githubusercontent.com/Huerte/GitGo/main/install.sh | bash
138
+ ```
139
+
140
+ This will automatically create an isolated environment and place `gitgo` in your `~/.local/bin` folder.
141
+
107
142
  Verify the installation:
108
143
 
109
144
  ```bash
@@ -142,13 +177,13 @@ gitgo link https://github.com/username/repo.git "Initial commit"
142
177
  gitgo push main "Fix auth bug"
143
178
 
144
179
  # Create a new branch and push
145
- gitgo push -n feature/login "Add login flow"
180
+ gitgo push -n feat/login "Add login flow"
146
181
  ```
147
182
 
148
183
  ### 4. Safely Switch Branches
149
184
  Jump to a different branch without worrying about your uncommitted changes. GitGo will safely stash them, hop to the new branch, sync with `main`, and carefully unpack them.
150
185
  ```bash
151
- gitgo jump feature/new-login
186
+ gitgo jump feat/new-login
152
187
  ```
153
188
 
154
189
  ### 5. Safely Undo Mistakes
@@ -225,7 +260,7 @@ gitgo jump <branch>
225
260
 
226
261
  ### `gitgo undo`
227
262
 
228
- Safely undo recent actions and mistakes using simple, human-readable commands.
263
+ Safely undo recent actions and mistakes using plain commands that say exactly what they do.
229
264
 
230
265
  ```bash
231
266
  gitgo undo commit # Undo your last commit without losing files
@@ -235,7 +270,7 @@ gitgo undo changes # Permanently wipe all new files and local edits
235
270
 
236
271
  ### `gitgo state`
237
272
 
238
- A human-readable interface over `git stash`.
273
+ A named interface over `git stash`.
239
274
 
240
275
  ```bash
241
276
  gitgo state list # show all saved states
@@ -291,13 +326,9 @@ gitgo -r # verify GitGo is ready
291
326
 
292
327
  ## Contributing
293
328
 
294
- Contributions are welcome and appreciated!
295
-
296
- 1. Fork the Project
297
- 2. Create a Feature Branch (`git checkout -b feature/your-feature`)
298
- 3. Commit Changes
299
- 4. Push to the Branch (`git push origin feature/your-feature`)
300
- 5. Open a Pull Request
329
+ Contributions are welcome. Read [CONTRIBUTING.md](CONTRIBUTING.md) for the full guide,
330
+ including project structure, test instructions, commit conventions, and a
331
+ [Good First Issues](CONTRIBUTING.md#good-first-issues) table if you are not sure where to start.
301
332
 
302
333
  ---
303
334
 
@@ -314,18 +345,6 @@ Contributions are welcome and appreciated!
314
345
 
315
346
  ---
316
347
 
317
- ## Support
318
-
319
- If GitGo saves you time, consider buying me a coffee. It helps keep the project going.
320
-
321
- <div align="center">
322
- <a href="https://ko-fi.com/huerte">
323
- <img src="https://ko-fi.com/img/githubbutton_sm.svg" alt="Support on Ko-fi" />
324
- </a>
325
- </div>
326
-
327
- ---
328
-
329
348
  ## License
330
349
 
331
350
  Distributed under the **GPLv3** License. See [`LICENSE`](LICENSE) for details.
@@ -4,3 +4,4 @@ pick>=2.0
4
4
  [dev]
5
5
  pytest>=7.0
6
6
  pytest-mock>=3.10
7
+ pytest-cov>=4.0
@@ -56,7 +56,7 @@ def test_config_operation_not_valid_keys(mocker):
56
56
  value = "true"
57
57
  args = Namespace(key=key, action="set", value=value)
58
58
 
59
- assert capture_system_exit_code(lambda: config_operation(args)) is None
59
+ assert capture_system_exit_code(lambda: config_operation(args)) == 0
60
60
 
61
61
  fake_error.assert_called_with(f"\nInvalid configuration key: '{key}'")
62
62
  fake_warning.assert_called_with(f"Valid keys are: {', '.join(VALID_KEYS)}\n")
@@ -44,10 +44,9 @@ def test_git_branch_exists_jump_no(mocker):
44
44
 
45
45
  branch_name = "existing-branch"
46
46
 
47
- with pytest.raises(SystemExit) as exc_info:
47
+ from pygitgo.exceptions import GitGoError
48
+ with pytest.raises(GitGoError):
48
49
  git_new_branch(branch_name)
49
-
50
- assert exc_info.value.code == 1
51
50
  fake_error.assert_called_once_with(f"Failed to create branch '{branch_name}'! It may already exist.")
52
51
  fake_jump.assert_not_called()
53
52
 
@@ -199,10 +198,9 @@ def test_handle_rebase_conflict(mocker):
199
198
  return_value='rebase'
200
199
  )
201
200
 
202
- with pytest.raises(SystemExit) as exc_info:
201
+ from pygitgo.exceptions import GitGoError
202
+ with pytest.raises(GitGoError):
203
203
  handle_rebase()
204
-
205
- assert exc_info.value.code == 1
206
204
 
207
205
  fake_run.assert_called_with(
208
206
  ["git", "status"], allow_fail=True
@@ -57,8 +57,6 @@ def test_jump_operation_not_valid_repo(mocker):
57
57
 
58
58
  assert capture_system_exit_code(lambda: jump_operation(make_args('main'))) == 1
59
59
 
60
- fake_warning.assert_called_with("\nUnable to check for uncommitted changes. Please ensure you're in a valid git repository.")
61
-
62
60
  fake_run.assert_any_call(['git', 'status', '--porcelain'], allow_fail=True, loading_msg="Checking for uncommitted changes...")
63
61
 
64
62
  def test_jump_operation_has_changes_exit(mocker):
@@ -1,7 +1,7 @@
1
1
  import pytest
2
2
  from unittest.mock import patch, MagicMock
3
3
  from pygitgo.commands.pull import pull_operation
4
- from pygitgo.exceptions import GitCommandError
4
+ from pygitgo.exceptions import GitCommandError, GitGoError
5
5
  from argparse import Namespace
6
6
  import subprocess
7
7
 
@@ -44,22 +44,16 @@ def test_pull_operation_success_with_branch(mock_success, mock_run_command):
44
44
  )
45
45
  mock_success.assert_called_once()
46
46
 
47
- @patch("pygitgo.commands.pull.sys.exit")
48
- @patch("pygitgo.commands.pull.error")
49
47
  @patch("pygitgo.commands.pull.run_command")
50
- def test_pull_operation_branch_not_found(mock_run_command, mock_error, mock_exit):
48
+ def test_pull_operation_branch_not_found(mock_run_command):
51
49
  mock_run_command.return_value = subprocess.CalledProcessError(128, ["git", "ls-remote"])
52
50
 
53
51
  args = Namespace(branch="does-not-exist")
54
- pull_operation(args)
55
-
56
- mock_exit.assert_called_once_with(1)
57
- mock_error.assert_called()
52
+ with pytest.raises(GitGoError):
53
+ pull_operation(args)
58
54
 
59
- @patch("pygitgo.commands.pull.sys.exit")
60
- @patch("pygitgo.commands.pull.error")
61
55
  @patch("pygitgo.commands.pull.run_command")
62
- def test_pull_operation_merge_conflict(mock_run_command, mock_error, mock_exit):
56
+ def test_pull_operation_merge_conflict(mock_run_command):
63
57
  conflict_err = GitCommandError(["git", "pull"], stderr="merge conflict in file.py")
64
58
 
65
59
  def side_effect_fn(*args, **kwargs):
@@ -71,7 +65,5 @@ def test_pull_operation_merge_conflict(mock_run_command, mock_error, mock_exit):
71
65
  mock_run_command.side_effect = side_effect_fn
72
66
 
73
67
  args = Namespace(branch="main")
74
- pull_operation(args)
75
-
76
- mock_exit.assert_called_once_with(1)
77
- mock_error.assert_any_call("\nMERGE CONFLICT DETECTED!")
68
+ with pytest.raises(GitGoError):
69
+ pull_operation(args)
@@ -18,7 +18,7 @@ def test_check_git_installed_exist(mocker):
18
18
  fake_error = mocker.patch("pygitgo.utils.setup.error")
19
19
  fake_info = mocker.patch("pygitgo.utils.setup.info")
20
20
 
21
- assert capture_system_exit_code(lambda: check_git_installed()) == None
21
+ assert capture_system_exit_code(lambda: check_git_installed()) == 0
22
22
 
23
23
  fake_error.assert_not_called()
24
24
  fake_info.assert_not_called()
@@ -49,10 +49,8 @@ def test_all_save_state_no_output(mocker):
49
49
  fake_run = mocker.patch("pygitgo.commands.state.run_command", return_value="")
50
50
  fake_info = mocker.patch("pygitgo.commands.state.info")
51
51
 
52
- with pytest.raises(SystemExit) as exc_info:
53
- all_save_state()
52
+ all_save_state()
54
53
 
55
- assert exc_info.value.code == 0
56
54
  fake_info.assert_called_once_with("\nNo saved states found.\n")
57
55
  fake_run.assert_called_once_with([
58
56
  "git", "stash", "list",
@@ -124,22 +122,19 @@ def test_load_state_invalid_id(mocker):
124
122
  mocker.patch("pygitgo.commands.state.all_save_state", return_value=save_states)
125
123
  mocker.patch("pygitgo.commands.state.validate_state_id", return_value=False)
126
124
 
127
- with pytest.raises(SystemExit) as exc_info:
125
+ from pygitgo.exceptions import GitGoError
126
+ with pytest.raises(GitGoError):
128
127
  load_state("100")
129
128
 
130
- assert exc_info.value.code == 1
131
-
132
129
  def test_load_state_invalid_argument(mocker):
133
130
  save_states = [{"id": 1, "ref": "stash@{0}", "date": "date", "message": "msg"}]
134
131
  mocker.patch("pygitgo.commands.state.all_save_state", return_value=save_states)
135
132
  fake_error = mocker.patch("pygitgo.commands.state.error")
136
133
 
137
- with pytest.raises(SystemExit) as exc_info:
134
+ from pygitgo.exceptions import GitGoError
135
+ with pytest.raises(GitGoError):
138
136
  load_state("invalid_arg")
139
137
 
140
- assert exc_info.value.code == 1
141
- fake_error.assert_called_once_with("\nInvalid argument 'invalid_arg' for load operation. Expected a state ID.\n")
142
-
143
138
  def test_load_state_no_args(mocker):
144
139
  save_states = [{"id": 1, "ref": "stash@{0}", "date": "date", "message": "msg"},
145
140
  {"id": 2, "ref": "stash@{1}", "date": "date2", "message": "msg2"}]
@@ -178,10 +173,8 @@ def test_delete_state_all_confirm(mocker):
178
173
  fake_run = mocker.patch("pygitgo.commands.state.run_command")
179
174
  fake_success = mocker.patch("pygitgo.commands.state.success")
180
175
 
181
- with pytest.raises(SystemExit) as exc_info:
182
- delete_state("-a")
176
+ delete_state("-a")
183
177
 
184
- assert exc_info.value.code == 0
185
178
  fake_run.assert_called_once_with(["git", "stash", "clear"])
186
179
  fake_success.assert_called_once_with("\nAll saved states deleted successfully.\n")
187
180
 
@@ -189,21 +182,17 @@ def test_delete_state_all_cancel(mocker):
189
182
  mocker.patch("builtins.input", return_value="n")
190
183
  fake_warning = mocker.patch("pygitgo.commands.state.warning")
191
184
 
192
- with pytest.raises(SystemExit) as exc_info:
193
- delete_state("-a")
185
+ delete_state("-a")
194
186
 
195
- assert exc_info.value.code == 0
196
187
  fake_warning.assert_called_once_with("\nDelete operation cancelled by user.\n")
197
188
 
198
189
  def test_delete_state_invalid_id(mocker):
199
190
  fake_error = mocker.patch("pygitgo.commands.state.error")
200
191
 
201
- with pytest.raises(SystemExit) as exc_info:
192
+ from pygitgo.exceptions import GitGoError
193
+ with pytest.raises(GitGoError):
202
194
  delete_state("abc")
203
195
 
204
- assert exc_info.value.code == 1
205
- fake_error.assert_called_once_with("\nInvalid input. Please enter a valid state ID.\n")
206
-
207
196
  def test_delete_state_specific_id(mocker):
208
197
  mocker.patch("pygitgo.commands.state.validate_state_id", return_value=True)
209
198
  mocker.patch("pygitgo.commands.state.all_save_state", return_value=[])
@@ -1,7 +1,7 @@
1
1
  import pytest
2
2
  from unittest.mock import patch, MagicMock
3
3
  from pygitgo.commands.undo import undo_commit, undo_add, undo_changes, undo_operations
4
- from pygitgo.exceptions import GitCommandError
4
+ from pygitgo.exceptions import GitGoError, GitCommandError
5
5
  from argparse import Namespace
6
6
 
7
7
  @patch("pygitgo.commands.undo.run_command")
@@ -12,15 +12,12 @@ def test_undo_commit_success(mock_success, mock_run_command):
12
12
  mock_success.assert_called_once()
13
13
 
14
14
 
15
- @patch("pygitgo.commands.undo.sys.exit")
16
- @patch("pygitgo.commands.undo.error")
17
15
  @patch("pygitgo.commands.undo.run_command")
18
- def test_undo_commit_failure(mock_run_command, mock_error, mock_exit):
16
+ def test_undo_commit_failure(mock_run_command):
19
17
  mock_run_command.side_effect = GitCommandError(["git", "reset", "--soft", "HEAD~"])
20
- undo_commit()
18
+ with pytest.raises(GitGoError):
19
+ undo_commit()
21
20
  mock_run_command.assert_called_once()
22
- assert mock_error.call_count == 2
23
- mock_exit.assert_called_once_with(1)
24
21
 
25
22
 
26
23
  @patch("pygitgo.commands.undo.run_command")
@@ -31,15 +28,12 @@ def test_undo_add_success(mock_success, mock_run_command):
31
28
  mock_success.assert_called_once()
32
29
 
33
30
 
34
- @patch("pygitgo.commands.undo.sys.exit")
35
- @patch("pygitgo.commands.undo.error")
36
31
  @patch("pygitgo.commands.undo.run_command")
37
- def test_undo_add_failure(mock_run_command, mock_error, mock_exit):
32
+ def test_undo_add_failure(mock_run_command):
38
33
  mock_run_command.side_effect = GitCommandError(["git", "reset", "HEAD"])
39
- undo_add()
34
+ with pytest.raises(GitCommandError):
35
+ undo_add()
40
36
  mock_run_command.assert_called_once()
41
- mock_error.assert_called_once()
42
- mock_exit.assert_called_once_with(1)
43
37
 
44
38
 
45
39
  @patch("pygitgo.commands.undo.run_command")
@@ -85,10 +79,7 @@ def test_undo_operations_changes(mock_undo_changes):
85
79
  mock_undo_changes.assert_called_once()
86
80
 
87
81
 
88
- @patch("pygitgo.commands.undo.sys.exit")
89
- @patch("pygitgo.commands.undo.error")
90
- def test_undo_operations_invalid(mock_error, mock_exit):
82
+ def test_undo_operations_invalid():
91
83
  args = Namespace(action="invalid")
92
- undo_operations(args)
93
- mock_error.assert_called_once()
94
- mock_exit.assert_called_once_with(1)
84
+ with pytest.raises(GitGoError):
85
+ undo_operations(args)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes