pygitgo 1.2.0__tar.gz → 1.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.
- {pygitgo-1.2.0/src/pygitgo.egg-info → pygitgo-1.2.1}/PKG-INFO +1 -1
- {pygitgo-1.2.0 → pygitgo-1.2.1}/pyproject.toml +1 -1
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/auth/ssh_utils.py +5 -1
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/commands/git_operations.py +28 -4
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/commands/jump.py +1 -2
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/commands/state.py +14 -11
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/main.py +18 -6
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/utils/config.py +3 -1
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/utils/executor.py +13 -7
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/utils/setup.py +1 -1
- {pygitgo-1.2.0 → pygitgo-1.2.1/src/pygitgo.egg-info}/PKG-INFO +1 -1
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo.egg-info/SOURCES.txt +2 -0
- pygitgo-1.2.1/tests/test_config.py +99 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/tests/test_git_operations.py +31 -1
- {pygitgo-1.2.0 → pygitgo-1.2.1}/tests/test_jump.py +13 -18
- {pygitgo-1.2.0 → pygitgo-1.2.1}/tests/test_main.py +2 -1
- pygitgo-1.2.1/tests/test_setup.py +55 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/tests/test_state.py +8 -9
- {pygitgo-1.2.0 → pygitgo-1.2.1}/LICENSE +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/README.md +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/setup.cfg +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/__init__.py +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/auth/__init__.py +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/auth/account.py +1 -1
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/auth/manager.py +1 -1
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/commands/__init__.py +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/exceptions.py +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/utils/__init__.py +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/utils/colors.py +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo/utils/platform_utils.py +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo.egg-info/dependency_links.txt +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo.egg-info/entry_points.txt +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo.egg-info/requires.txt +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/src/pygitgo.egg-info/top_level.txt +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/tests/test_platform.py +0 -0
- {pygitgo-1.2.0 → pygitgo-1.2.1}/tests/test_url_validator.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "pygitgo"
|
|
7
|
-
version = "1.2.
|
|
7
|
+
version = "1.2.1"
|
|
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"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from pygitgo.utils.executor import run_command
|
|
2
1
|
from pygitgo.utils.colors import info, success, warning, error
|
|
2
|
+
from pygitgo.utils.executor import run_command
|
|
3
3
|
from pygitgo.utils import platform_utils
|
|
4
4
|
from pathlib import Path
|
|
5
5
|
import subprocess
|
|
@@ -35,11 +35,15 @@ def ensure_github_known_host():
|
|
|
35
35
|
def check_connection():
|
|
36
36
|
ensure_github_known_host()
|
|
37
37
|
result = run_command(["ssh", "-T", "git@github.com"], allow_fail=True, return_complete=True)
|
|
38
|
+
if not hasattr(result, "stderr") or not result.stderr:
|
|
39
|
+
return False
|
|
38
40
|
return "successfully authenticated" in result.stderr
|
|
39
41
|
|
|
40
42
|
def get_github_username():
|
|
41
43
|
|
|
42
44
|
result = run_command(["ssh", "-T", "git@github.com"], allow_fail=True, return_complete=True)
|
|
45
|
+
if not hasattr(result, "stderr") or not result.stderr:
|
|
46
|
+
return None
|
|
43
47
|
output = result.stderr
|
|
44
48
|
|
|
45
49
|
if "Hi " in output and "!" in output:
|
|
@@ -2,11 +2,18 @@ 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 argparse import Namespace
|
|
5
6
|
import subprocess
|
|
6
7
|
import sys
|
|
7
8
|
import os
|
|
8
9
|
|
|
9
10
|
|
|
11
|
+
def get_status_content():
|
|
12
|
+
status = run_command(["git", "status", "--porcelain"], allow_fail=True)
|
|
13
|
+
if isinstance(status, subprocess.CalledProcessError) or not status.strip():
|
|
14
|
+
sys.exit(1)
|
|
15
|
+
return status
|
|
16
|
+
|
|
10
17
|
def get_current_branch():
|
|
11
18
|
branch = run_command(["git", "branch", "--show-current"]).strip()
|
|
12
19
|
if not branch:
|
|
@@ -26,8 +33,17 @@ def is_branch_exist(branch):
|
|
|
26
33
|
|
|
27
34
|
|
|
28
35
|
def git_new_branch(branch):
|
|
29
|
-
run_command(["git", "checkout", "-b", branch], loading_msg=f"Creating branch '{branch}'...")
|
|
30
|
-
|
|
36
|
+
result = run_command(["git", "checkout", "-b", branch], loading_msg=f"Creating branch '{branch}'...")
|
|
37
|
+
if isinstance(result, subprocess.CalledProcessError):
|
|
38
|
+
error(f"Failed to create branch '{branch}'! It may already exist.")
|
|
39
|
+
choice = input("\nWould you like to jump to the existing branch instead? (y/n): ").strip().lower()
|
|
40
|
+
if choice == "y":
|
|
41
|
+
from pygitgo.commands.jump import jump_operation
|
|
42
|
+
jump_operation(Namespace(branch=branch))
|
|
43
|
+
else:
|
|
44
|
+
sys.exit(1)
|
|
45
|
+
else:
|
|
46
|
+
success(f"\nBranch '{branch}' created.\n")
|
|
31
47
|
|
|
32
48
|
return branch
|
|
33
49
|
|
|
@@ -136,8 +152,16 @@ def git_push(branch):
|
|
|
136
152
|
if ssh_url:
|
|
137
153
|
run_command(["git", "remote", "set-url", "origin", ssh_url], loading_msg="Converting remote from HTTPS to SSH for secure push...")
|
|
138
154
|
success(f"Remote updated to: {ssh_url}")
|
|
139
|
-
|
|
140
|
-
|
|
155
|
+
|
|
156
|
+
try:
|
|
157
|
+
run_command(["git", "push", "-u", "origin", branch], loading_msg=f"Pushing to remote branch '{branch}'...")
|
|
158
|
+
except (subprocess.CalledProcessError, OSError) as e:
|
|
159
|
+
error("Failed to push to remote repository!")
|
|
160
|
+
warning("Please check your network connection, remote URL, and authentication.")
|
|
161
|
+
if "rebase in progress" in str(e):
|
|
162
|
+
handle_rebase()
|
|
163
|
+
else:
|
|
164
|
+
sys.exit(1)
|
|
141
165
|
|
|
142
166
|
|
|
143
167
|
def handle_rebase():
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
from pygitgo.commands.git_operations import (
|
|
2
2
|
is_branch_exist, get_current_branch, git_new_branch, get_main_branch
|
|
3
3
|
)
|
|
4
|
-
from pygitgo.utils.executor import run_command
|
|
5
|
-
from pygitgo.commands.state import *
|
|
6
4
|
from pygitgo.utils.colors import warning, info, success, error
|
|
5
|
+
from pygitgo.utils.executor import run_command
|
|
7
6
|
import subprocess
|
|
8
7
|
import sys
|
|
9
8
|
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from pygitgo.utils.executor import run_command
|
|
2
1
|
from pygitgo.utils.colors import info, highlight, error, warning, success
|
|
2
|
+
from pygitgo.utils.executor import run_command
|
|
3
3
|
import sys
|
|
4
4
|
|
|
5
5
|
|
|
@@ -59,20 +59,19 @@ def display_save_states():
|
|
|
59
59
|
|
|
60
60
|
|
|
61
61
|
def is_number(value):
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
return
|
|
65
|
-
|
|
66
|
-
return False
|
|
62
|
+
val = str(value).strip()
|
|
63
|
+
if val.startswith('-'):
|
|
64
|
+
return val[1:].isdigit()
|
|
65
|
+
return val.isdigit()
|
|
67
66
|
|
|
68
67
|
def validate_state_id(state_id, save_states):
|
|
69
68
|
if not is_number(state_id):
|
|
70
69
|
error("\nInvalid input. Please enter a valid state ID.\n")
|
|
71
70
|
return False
|
|
72
|
-
elif (int(
|
|
71
|
+
elif (int(state_id) - 1) < 0:
|
|
73
72
|
error("\nState ID cannot be '0' or negative. Please enter a valid state ID.\n")
|
|
74
73
|
return False
|
|
75
|
-
elif (int(
|
|
74
|
+
elif (int(state_id) - 1) >= len(save_states):
|
|
76
75
|
error("\nState ID out of range. Please enter a valid state ID.\n")
|
|
77
76
|
return False
|
|
78
77
|
return True
|
|
@@ -124,9 +123,13 @@ def save_state(state_name=None):
|
|
|
124
123
|
if not state_name:
|
|
125
124
|
state_name = "Auto-Save"
|
|
126
125
|
|
|
127
|
-
run_command(["git", "stash", "push", "-m", state_name])
|
|
128
|
-
|
|
129
|
-
|
|
126
|
+
output = run_command(["git", "stash", "push", "-m", state_name], allow_fail=True)
|
|
127
|
+
if isinstance(output, Exception):
|
|
128
|
+
error(f"\nFailed to save state '{state_name}'.\n")
|
|
129
|
+
elif "No local changes to save" in output:
|
|
130
|
+
warning("\nNo local changes to save.\n")
|
|
131
|
+
else:
|
|
132
|
+
success(f"\nState '{state_name}' saved successfully.\n")
|
|
130
133
|
|
|
131
134
|
|
|
132
135
|
def delete_state(identifier=None):
|
|
@@ -1,18 +1,17 @@
|
|
|
1
|
-
from pygitgo.auth.ssh_utils import ensure_github_known_host
|
|
2
1
|
from pygitgo.commands.git_operations import (
|
|
3
2
|
git_new_branch, git_commit, git_init, add_remote_origin,
|
|
4
|
-
confirm_remote_link,
|
|
5
|
-
git_push, handle_rebase, get_current_branch, is_branch_exist
|
|
3
|
+
confirm_remote_link, git_push, get_current_branch, is_branch_exist
|
|
6
4
|
)
|
|
7
|
-
from pygitgo.utils.colors import info, success, warning, error
|
|
5
|
+
from pygitgo.utils.colors import info, success, warning, error
|
|
8
6
|
from pygitgo.utils.config import get_config, config_operation
|
|
7
|
+
from pygitgo.exceptions import GitCommandError, GitGoError
|
|
9
8
|
from pygitgo.utils.setup import ensure_first_run_setup
|
|
10
9
|
from pygitgo.commands.state import state_operations
|
|
11
10
|
from pygitgo.commands.jump import jump_operation
|
|
12
11
|
from pygitgo.utils.executor import run_command
|
|
13
12
|
from pygitgo.auth.manager import login, logout
|
|
14
13
|
from pygitgo.auth.account import get_user
|
|
15
|
-
from
|
|
14
|
+
from argparse import Namespace
|
|
16
15
|
import subprocess
|
|
17
16
|
import argparse
|
|
18
17
|
import sys
|
|
@@ -109,11 +108,24 @@ def push_operation(args):
|
|
|
109
108
|
if branch and not message and not is_branch_exist(branch):
|
|
110
109
|
message = branch
|
|
111
110
|
branch = get_current_branch()
|
|
111
|
+
info(f"No branch name provided. Using current branch: '{branch}'\n")
|
|
112
|
+
|
|
113
|
+
elif branch and is_branch_exist(branch):
|
|
114
|
+
current_branch = get_current_branch()
|
|
115
|
+
if current_branch != branch:
|
|
116
|
+
warning(f"You are currently on branch '{current_branch}', not '{branch}'.")
|
|
117
|
+
user_choice = input(f"Do you want to switch to branch '{branch}'? (y/n): ").lower()
|
|
118
|
+
if user_choice != 'y':
|
|
119
|
+
error("\nPush aborted to prevent committing to the wrong branch.\n")
|
|
120
|
+
sys.exit(1)
|
|
121
|
+
jump_operation(Namespace(branch=branch))
|
|
122
|
+
|
|
112
123
|
elif not branch:
|
|
113
124
|
branch = get_current_branch()
|
|
114
125
|
|
|
115
126
|
if not message:
|
|
116
127
|
message = get_config("default-message", "New Project Update")
|
|
128
|
+
info(f"No commit message provided. Using default: '{message}'\n")
|
|
117
129
|
|
|
118
130
|
commit_made = git_commit(message)
|
|
119
131
|
|
|
@@ -129,7 +141,7 @@ def push_operation(args):
|
|
|
129
141
|
info("\nWorking tree is clean and everything is up to date.")
|
|
130
142
|
warning("Make some changes first before using GitGo to commit and push.")
|
|
131
143
|
return
|
|
132
|
-
except:
|
|
144
|
+
except (GitCommandError, Exception):
|
|
133
145
|
warning("\nNo changes to commit. Cannot verify remote status.")
|
|
134
146
|
warning("Make some changes first or check your git remote configuration.")
|
|
135
147
|
return
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import subprocess
|
|
2
|
-
import sys
|
|
3
|
-
import os
|
|
4
1
|
from pygitgo.utils.colors import error, info, success, warning
|
|
5
2
|
from pygitgo.exceptions import GitCommandError
|
|
3
|
+
from yaspin import yaspin
|
|
4
|
+
import subprocess
|
|
5
|
+
import os
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
def run_command(command, allow_fail=False, return_complete=False, loading_msg=None):
|
|
@@ -15,7 +15,6 @@ def run_command(command, allow_fail=False, return_complete=False, loading_msg=No
|
|
|
15
15
|
:param loading_msg: if provided, show a yaspin spinner with this message
|
|
16
16
|
:raises GitCommandError: when the command fails and allow_fail is False
|
|
17
17
|
"""
|
|
18
|
-
from yaspin import yaspin
|
|
19
18
|
|
|
20
19
|
spinner = yaspin(text=loading_msg, color="cyan") if loading_msg else None
|
|
21
20
|
|
|
@@ -34,11 +33,18 @@ def run_command(command, allow_fail=False, return_complete=False, loading_msg=No
|
|
|
34
33
|
spinner.ok("✔")
|
|
35
34
|
|
|
36
35
|
return result if return_complete else result.stdout.strip()
|
|
37
|
-
except subprocess.CalledProcessError as e:
|
|
36
|
+
except (subprocess.CalledProcessError, OSError) as e:
|
|
38
37
|
if spinner:
|
|
39
38
|
spinner.fail("✖")
|
|
40
39
|
|
|
41
|
-
stderr =
|
|
40
|
+
stderr = ""
|
|
41
|
+
returncode = 1
|
|
42
|
+
|
|
43
|
+
if isinstance(e, subprocess.CalledProcessError):
|
|
44
|
+
stderr = e.stderr.strip() if e.stderr else ""
|
|
45
|
+
returncode = e.returncode
|
|
46
|
+
else:
|
|
47
|
+
stderr = f"Command not found or execution failed: {str(e)}"
|
|
42
48
|
|
|
43
49
|
if "detected dubious ownership" in stderr:
|
|
44
50
|
error(f"\nSECURITY ALERT: {stderr}")
|
|
@@ -68,4 +74,4 @@ def run_command(command, allow_fail=False, return_complete=False, loading_msg=No
|
|
|
68
74
|
if allow_fail:
|
|
69
75
|
return e
|
|
70
76
|
|
|
71
|
-
raise GitCommandError(command, stderr=stderr, returncode=
|
|
77
|
+
raise GitCommandError(command, stderr=stderr, returncode=returncode)
|
|
@@ -19,7 +19,7 @@ def ensure_first_run_setup():
|
|
|
19
19
|
|
|
20
20
|
is_initialized = get_config("initialized", fallback_value="false")
|
|
21
21
|
|
|
22
|
-
if
|
|
22
|
+
if is_initialized == "false":
|
|
23
23
|
info("\nInitializing GitGo network settings for the first time... please wait.")
|
|
24
24
|
ensure_github_known_host()
|
|
25
25
|
|
|
@@ -24,9 +24,11 @@ src/pygitgo/utils/config.py
|
|
|
24
24
|
src/pygitgo/utils/executor.py
|
|
25
25
|
src/pygitgo/utils/platform_utils.py
|
|
26
26
|
src/pygitgo/utils/setup.py
|
|
27
|
+
tests/test_config.py
|
|
27
28
|
tests/test_git_operations.py
|
|
28
29
|
tests/test_jump.py
|
|
29
30
|
tests/test_main.py
|
|
30
31
|
tests/test_platform.py
|
|
32
|
+
tests/test_setup.py
|
|
31
33
|
tests/test_state.py
|
|
32
34
|
tests/test_url_validator.py
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
from pygitgo.utils.config import get_config, set_config, config_operation
|
|
2
|
+
from conftest import capture_system_exit_code
|
|
3
|
+
from argparse import Namespace
|
|
4
|
+
import subprocess
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def test_get_config_fallback(mocker):
|
|
8
|
+
fake_run = mocker.patch('pygitgo.utils.config.run_command', return_value="")
|
|
9
|
+
|
|
10
|
+
fallback_value = "false"
|
|
11
|
+
|
|
12
|
+
result = get_config("default-key", fallback_value)
|
|
13
|
+
assert result == fallback_value
|
|
14
|
+
|
|
15
|
+
def test_get_config_ok(mocker):
|
|
16
|
+
fake_run = mocker.patch('pygitgo.utils.config.run_command', return_value="true")
|
|
17
|
+
|
|
18
|
+
fallback_value = "false"
|
|
19
|
+
|
|
20
|
+
result = get_config("default-key", fallback_value)
|
|
21
|
+
assert result != fallback_value
|
|
22
|
+
|
|
23
|
+
def test_set_config_fallback(mocker):
|
|
24
|
+
fake_run = mocker.patch('pygitgo.utils.config.run_command', return_value=subprocess.CalledProcessError(1, 'git'))
|
|
25
|
+
fake_error = mocker.patch('pygitgo.utils.config.error')
|
|
26
|
+
|
|
27
|
+
key = 'default-key'
|
|
28
|
+
|
|
29
|
+
result = set_config(key, 'true')
|
|
30
|
+
assert result == False
|
|
31
|
+
|
|
32
|
+
fake_error.assert_called_with(f"\nFailed to save configuration for '{key}'.")
|
|
33
|
+
|
|
34
|
+
def test_set_config_ok(mocker):
|
|
35
|
+
fake_run = mocker.patch('pygitgo.utils.config.run_command', return_value='ok')
|
|
36
|
+
fake_error = mocker.patch('pygitgo.utils.config.error')
|
|
37
|
+
fake_success = mocker.patch('pygitgo.utils.config.success')
|
|
38
|
+
|
|
39
|
+
key = 'default-key'
|
|
40
|
+
value = 'true'
|
|
41
|
+
|
|
42
|
+
result = set_config(key, value)
|
|
43
|
+
assert result == True
|
|
44
|
+
|
|
45
|
+
fake_error.assert_not_called()
|
|
46
|
+
fake_success.assert_called_with(f"\nConfiguration saved: {key} = '{value}'")
|
|
47
|
+
|
|
48
|
+
def test_config_operation_not_valid_keys(mocker):
|
|
49
|
+
fake_error = mocker.patch('pygitgo.utils.config.error')
|
|
50
|
+
fake_warning = mocker.patch('pygitgo.utils.config.warning')
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
VALID_KEYS = ["default-branch", "default-message"]
|
|
54
|
+
|
|
55
|
+
key = "not-valid"
|
|
56
|
+
value = "true"
|
|
57
|
+
args = Namespace(key=key, action="set", value=value)
|
|
58
|
+
|
|
59
|
+
assert capture_system_exit_code(lambda: config_operation(args)) is None
|
|
60
|
+
|
|
61
|
+
fake_error.assert_called_with(f"\nInvalid configuration key: '{key}'")
|
|
62
|
+
fake_warning.assert_called_with(f"Valid keys are: {', '.join(VALID_KEYS)}\n")
|
|
63
|
+
|
|
64
|
+
def test_get_config_strip(mocker):
|
|
65
|
+
fake_run = mocker.patch('pygitgo.utils.config.run_command', return_value=" true \n")
|
|
66
|
+
result = get_config("default-key", "false")
|
|
67
|
+
assert result == "true"
|
|
68
|
+
|
|
69
|
+
def test_get_config_error_handling(mocker):
|
|
70
|
+
fake_run = mocker.patch('pygitgo.utils.config.run_command', return_value=subprocess.CalledProcessError(1, 'git'))
|
|
71
|
+
result = get_config("default-key", "fallback")
|
|
72
|
+
assert result == "fallback"
|
|
73
|
+
|
|
74
|
+
def test_config_operation_set_no_value(mocker):
|
|
75
|
+
fake_error = mocker.patch('pygitgo.utils.config.error')
|
|
76
|
+
args = Namespace(key="default-branch", action="set") # value is missing
|
|
77
|
+
config_operation(args)
|
|
78
|
+
fake_error.assert_called_with("\nYou must provide a value to set!\n")
|
|
79
|
+
|
|
80
|
+
def test_config_operation_set_ok(mocker):
|
|
81
|
+
fake_set = mocker.patch('pygitgo.utils.config.set_config')
|
|
82
|
+
args = Namespace(key="default-branch", action="set", value="main")
|
|
83
|
+
config_operation(args)
|
|
84
|
+
fake_set.assert_called_with("default-branch", "main")
|
|
85
|
+
|
|
86
|
+
def test_config_operation_get_ok(mocker):
|
|
87
|
+
mocker.patch('pygitgo.utils.config.get_config', return_value="main")
|
|
88
|
+
fake_info = mocker.patch('pygitgo.utils.config.info')
|
|
89
|
+
args = Namespace(key="default-branch", action="get")
|
|
90
|
+
config_operation(args)
|
|
91
|
+
fake_info.assert_called_with("\ndefault-branch is currently set to: 'main'\n")
|
|
92
|
+
|
|
93
|
+
def test_config_operation_get_none(mocker):
|
|
94
|
+
mocker.patch('pygitgo.utils.config.get_config', return_value=None)
|
|
95
|
+
fake_warning = mocker.patch('pygitgo.utils.config.warning')
|
|
96
|
+
args = Namespace(key="default-branch", action="get")
|
|
97
|
+
config_operation(args)
|
|
98
|
+
fake_warning.assert_called_with("\ndefault-branch is not currently set.\n")
|
|
99
|
+
|
|
@@ -7,7 +7,7 @@ from pygitgo.commands.git_operations import (
|
|
|
7
7
|
from unittest.mock import call
|
|
8
8
|
import subprocess
|
|
9
9
|
import pytest
|
|
10
|
-
|
|
10
|
+
|
|
11
11
|
|
|
12
12
|
def test_git_branch_logic(mocker):
|
|
13
13
|
fake_run = mocker.patch("pygitgo.commands.git_operations.run_command")
|
|
@@ -21,6 +21,36 @@ def test_git_branch_logic(mocker):
|
|
|
21
21
|
loading_msg="Creating branch 'hello-world'..."
|
|
22
22
|
)
|
|
23
23
|
|
|
24
|
+
def test_git_branch_exists_jump_yes(mocker):
|
|
25
|
+
fake_run = mocker.patch("pygitgo.commands.git_operations.run_command", return_value=subprocess.CalledProcessError(1, 'git'))
|
|
26
|
+
mocker.patch("builtins.input", return_value="y")
|
|
27
|
+
fake_jump = mocker.patch("pygitgo.commands.jump.jump_operation")
|
|
28
|
+
fake_error = mocker.patch("pygitgo.commands.git_operations.error")
|
|
29
|
+
|
|
30
|
+
branch_name = "existing-branch"
|
|
31
|
+
result = git_new_branch(branch_name)
|
|
32
|
+
|
|
33
|
+
assert result == "existing-branch"
|
|
34
|
+
fake_error.assert_called_once_with(f"Failed to create branch '{branch_name}'! It may already exist.")
|
|
35
|
+
|
|
36
|
+
args = fake_jump.call_args[0][0]
|
|
37
|
+
assert args.branch == branch_name
|
|
38
|
+
|
|
39
|
+
def test_git_branch_exists_jump_no(mocker):
|
|
40
|
+
fake_run = mocker.patch("pygitgo.commands.git_operations.run_command", return_value=subprocess.CalledProcessError(1, 'git'))
|
|
41
|
+
mocker.patch("builtins.input", return_value="n")
|
|
42
|
+
fake_jump = mocker.patch("pygitgo.commands.jump.jump_operation")
|
|
43
|
+
fake_error = mocker.patch("pygitgo.commands.git_operations.error")
|
|
44
|
+
|
|
45
|
+
branch_name = "existing-branch"
|
|
46
|
+
|
|
47
|
+
with pytest.raises(SystemExit) as exc_info:
|
|
48
|
+
git_new_branch(branch_name)
|
|
49
|
+
|
|
50
|
+
assert exc_info.value.code == 1
|
|
51
|
+
fake_error.assert_called_once_with(f"Failed to create branch '{branch_name}'! It may already exist.")
|
|
52
|
+
fake_jump.assert_not_called()
|
|
53
|
+
|
|
24
54
|
def test_git_commit(mocker):
|
|
25
55
|
fake_run = mocker.patch("pygitgo.commands.git_operations.run_command")\
|
|
26
56
|
|
|
@@ -1,18 +1,13 @@
|
|
|
1
1
|
from pygitgo.commands.jump import undo_jump_operation, jump_operation
|
|
2
|
+
from conftest import capture_system_exit_code
|
|
2
3
|
from argparse import Namespace
|
|
3
4
|
import subprocess
|
|
4
5
|
import pytest
|
|
5
6
|
|
|
7
|
+
|
|
6
8
|
def make_args(branch):
|
|
7
|
-
"""Helper to create an argparse-like Namespace for jump_operation."""
|
|
8
9
|
return Namespace(branch=branch)
|
|
9
10
|
|
|
10
|
-
def check_pytest_system_exit(function):
|
|
11
|
-
with pytest.raises(SystemExit) as exc_info:
|
|
12
|
-
function()
|
|
13
|
-
|
|
14
|
-
return exc_info.value.code
|
|
15
|
-
|
|
16
11
|
def test_undo_jump_operation_no_stash(mocker):
|
|
17
12
|
fake_run = mocker.patch('pygitgo.commands.jump.run_command', return_value="")
|
|
18
13
|
|
|
@@ -47,7 +42,7 @@ def test_jump_operation_same_branch(mocker):
|
|
|
47
42
|
)
|
|
48
43
|
fake_warning = mocker.patch('pygitgo.commands.jump.warning')
|
|
49
44
|
|
|
50
|
-
assert
|
|
45
|
+
assert capture_system_exit_code(lambda: jump_operation(make_args(main_branch))) == 0
|
|
51
46
|
|
|
52
47
|
fake_warning.assert_called_with(f"\nYou are already on branch '{main_branch}'.\n")
|
|
53
48
|
|
|
@@ -60,7 +55,7 @@ def test_jump_operation_not_valid_repo(mocker):
|
|
|
60
55
|
return_value=subprocess.CalledProcessError(1, 'git')
|
|
61
56
|
)
|
|
62
57
|
|
|
63
|
-
assert
|
|
58
|
+
assert capture_system_exit_code(lambda: jump_operation(make_args('main'))) == 1
|
|
64
59
|
|
|
65
60
|
fake_warning.assert_called_with("\nUnable to check for uncommitted changes. Please ensure you're in a valid git repository.")
|
|
66
61
|
|
|
@@ -77,7 +72,7 @@ def test_jump_operation_has_changes_exit(mocker):
|
|
|
77
72
|
side_effect=['some-changes']
|
|
78
73
|
)
|
|
79
74
|
|
|
80
|
-
assert
|
|
75
|
+
assert capture_system_exit_code(lambda: jump_operation(make_args('main'))) == 0
|
|
81
76
|
|
|
82
77
|
fake_warning.assert_any_call("\nYou cannot switch branches with unsaved changes. Jump canceled.\n")
|
|
83
78
|
fake_run.assert_any_call(['git', 'status', '--porcelain'], allow_fail=True, loading_msg="Checking for uncommitted changes...")
|
|
@@ -94,7 +89,7 @@ def test_jump_operation_save_changes_error(mocker):
|
|
|
94
89
|
)
|
|
95
90
|
)
|
|
96
91
|
|
|
97
|
-
assert
|
|
92
|
+
assert capture_system_exit_code(lambda: jump_operation(make_args('main'))) == 1
|
|
98
93
|
|
|
99
94
|
fake_warning.assert_called_with("\nFailed to save your changes. Please resolve any issues and try again.")
|
|
100
95
|
fake_run.assert_any_call(['git', 'status', '--porcelain'], allow_fail=True, loading_msg="Checking for uncommitted changes...")
|
|
@@ -115,7 +110,7 @@ def test_jump_operation_no_changes(mocker):
|
|
|
115
110
|
|
|
116
111
|
target_branch = 'feature'
|
|
117
112
|
|
|
118
|
-
assert
|
|
113
|
+
assert capture_system_exit_code(lambda: jump_operation(make_args(target_branch))) == 0
|
|
119
114
|
|
|
120
115
|
fake_success.assert_called_with(f"\nSuccess! You are now on '{target_branch}'.\n")
|
|
121
116
|
fake_run.assert_any_call(['git', 'status', '--porcelain'], allow_fail=True, loading_msg="Checking for uncommitted changes...")
|
|
@@ -143,7 +138,7 @@ def test_jump_operation_branch_not_exist_cancel_operation(mocker):
|
|
|
143
138
|
|
|
144
139
|
target_branch = 'feature'
|
|
145
140
|
|
|
146
|
-
assert
|
|
141
|
+
assert capture_system_exit_code(lambda: jump_operation(make_args(target_branch))) == 0
|
|
147
142
|
|
|
148
143
|
fake_info.assert_any_call('\nYour changes have been saved. Jumping to the new branch...')
|
|
149
144
|
fake_info.assert_any_call("Exiting without jumping...\n")
|
|
@@ -175,7 +170,7 @@ def test_jump_operation_branch_not_exist_create_branch(mocker):
|
|
|
175
170
|
|
|
176
171
|
target_branch = 'feature'
|
|
177
172
|
|
|
178
|
-
assert
|
|
173
|
+
assert capture_system_exit_code(lambda: jump_operation(make_args(target_branch))) == 0
|
|
179
174
|
|
|
180
175
|
fake_info.assert_called_with('\nYour changes have been saved. Jumping to the new branch...')
|
|
181
176
|
fake_success.assert_any_call(f"\nSuccess! You are now on '{target_branch}'.")
|
|
@@ -204,7 +199,7 @@ def test_jump_operation_sync_fail_cancel(mocker):
|
|
|
204
199
|
)
|
|
205
200
|
)
|
|
206
201
|
|
|
207
|
-
assert
|
|
202
|
+
assert capture_system_exit_code(lambda: jump_operation(make_args('feature'))) == 1
|
|
208
203
|
|
|
209
204
|
fake_warning.assert_any_call("\nFailed to pull updates from 'main'. Make sure you have internet or the remote branch exists.")
|
|
210
205
|
|
|
@@ -225,7 +220,7 @@ def test_jump_operation_sync_fail_stay(mocker):
|
|
|
225
220
|
)
|
|
226
221
|
)
|
|
227
222
|
|
|
228
|
-
assert
|
|
223
|
+
assert capture_system_exit_code(lambda: jump_operation(make_args('feature'))) == 0
|
|
229
224
|
|
|
230
225
|
fake_success.assert_any_call("\nOkay! You are on the new branch, but without the latest updates from 'main'.")
|
|
231
226
|
|
|
@@ -247,7 +242,7 @@ def test_jump_operation_merge_conflict_cancel(mocker):
|
|
|
247
242
|
)
|
|
248
243
|
)
|
|
249
244
|
|
|
250
|
-
assert
|
|
245
|
+
assert capture_system_exit_code(lambda: jump_operation(make_args('feature'))) == 0
|
|
251
246
|
|
|
252
247
|
fake_error.assert_any_call("\nSTOP! There is a 'Merge Conflict'.")
|
|
253
248
|
|
|
@@ -270,7 +265,7 @@ def test_jump_operation_merge_conflict_stay(mocker):
|
|
|
270
265
|
)
|
|
271
266
|
)
|
|
272
267
|
|
|
273
|
-
assert
|
|
268
|
+
assert capture_system_exit_code(lambda: jump_operation(make_args('feature'))) == 0
|
|
274
269
|
|
|
275
270
|
fake_success.assert_any_call("\nOkay! You are on the new branch with your code.")
|
|
276
271
|
fake_warning.assert_any_call("Please open your code editor RIGHT NOW to fix the conflicts!")
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from pygitgo.utils.setup import check_git_installed, ensure_first_run_setup
|
|
2
|
+
from conftest import capture_system_exit_code
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def test_check_git_installed_no_exist(mocker):
|
|
6
|
+
mocker.patch("shutil.which", return_value=None)
|
|
7
|
+
fake_error = mocker.patch("pygitgo.utils.setup.error")
|
|
8
|
+
fake_info = mocker.patch("pygitgo.utils.setup.info")
|
|
9
|
+
|
|
10
|
+
assert capture_system_exit_code(lambda: check_git_installed()) == 1
|
|
11
|
+
|
|
12
|
+
fake_error.assert_called_with("\nGit is not installed or not found on your PATH!")
|
|
13
|
+
fake_info.assert_any_call("Install Git from: https://git-scm.com/downloads")
|
|
14
|
+
fake_info.assert_any_call("After installing, restart your terminal and try again.\n")
|
|
15
|
+
|
|
16
|
+
def test_check_git_installed_exist(mocker):
|
|
17
|
+
mocker.patch("shutil.which", return_value="ok")
|
|
18
|
+
fake_error = mocker.patch("pygitgo.utils.setup.error")
|
|
19
|
+
fake_info = mocker.patch("pygitgo.utils.setup.info")
|
|
20
|
+
|
|
21
|
+
assert capture_system_exit_code(lambda: check_git_installed()) == None
|
|
22
|
+
|
|
23
|
+
fake_error.assert_not_called()
|
|
24
|
+
fake_info.assert_not_called()
|
|
25
|
+
|
|
26
|
+
def test_ensure_first_run_setup_already_initialized(mocker):
|
|
27
|
+
mocker.patch('pygitgo.utils.setup.check_git_installed', return_value=None)
|
|
28
|
+
fake_get_config = mocker.patch('pygitgo.utils.setup.get_config', return_value="ok")
|
|
29
|
+
fake_github_function = mocker.patch('pygitgo.utils.setup.ensure_github_known_host', return_value=None)
|
|
30
|
+
fake_set_config = mocker.patch('pygitgo.utils.setup.set_config', return_value=True)
|
|
31
|
+
fake_info = mocker.patch("pygitgo.utils.setup.info")
|
|
32
|
+
|
|
33
|
+
ensure_first_run_setup()
|
|
34
|
+
|
|
35
|
+
fake_info.assert_not_called()
|
|
36
|
+
fake_github_function.assert_not_called()
|
|
37
|
+
fake_set_config.assert_not_called()
|
|
38
|
+
|
|
39
|
+
fake_get_config.assert_called_with("initialized", fallback_value="false")
|
|
40
|
+
|
|
41
|
+
def test_ensure_first_run_setup_not_initialized(mocker):
|
|
42
|
+
mocker.patch('pygitgo.utils.setup.check_git_installed', return_value=None)
|
|
43
|
+
fake_get_config = mocker.patch('pygitgo.utils.setup.get_config', return_value="false")
|
|
44
|
+
fake_github_function = mocker.patch('pygitgo.utils.setup.ensure_github_known_host', return_value=None)
|
|
45
|
+
fake_set_config = mocker.patch('pygitgo.utils.setup.set_config', return_value=True)
|
|
46
|
+
fake_info = mocker.patch("pygitgo.utils.setup.info")
|
|
47
|
+
|
|
48
|
+
ensure_first_run_setup()
|
|
49
|
+
|
|
50
|
+
fake_info.assert_called_with("\nInitializing GitGo network settings for the first time... please wait.")
|
|
51
|
+
fake_github_function.assert_called_once()
|
|
52
|
+
fake_set_config.assert_called_with("initialized", "true")
|
|
53
|
+
|
|
54
|
+
fake_get_config.assert_called_with("initialized", fallback_value="false")
|
|
55
|
+
|
|
@@ -3,12 +3,11 @@ from pygitgo.commands.state import (
|
|
|
3
3
|
all_save_state
|
|
4
4
|
)
|
|
5
5
|
from unittest.mock import call
|
|
6
|
-
import subprocess
|
|
7
6
|
import pytest
|
|
8
|
-
|
|
7
|
+
|
|
9
8
|
|
|
10
9
|
@pytest.mark.parametrize('state_id',[
|
|
11
|
-
'1', '3', '11', '00002'
|
|
10
|
+
'1', '3', '11', '00002'
|
|
12
11
|
])
|
|
13
12
|
def test_validate_state_id(state_id, mocker):
|
|
14
13
|
fake_error = mocker.patch('pygitgo.commands.state.error')
|
|
@@ -20,7 +19,7 @@ def test_validate_state_id(state_id, mocker):
|
|
|
20
19
|
fake_error.assert_not_called()
|
|
21
20
|
|
|
22
21
|
@pytest.mark.parametrize('state_id',[
|
|
23
|
-
'-1', '-3', '-11', '-00002'
|
|
22
|
+
'-1', '-3', '-11', '-00002'
|
|
24
23
|
])
|
|
25
24
|
def test_validate_state_id_negative(state_id, mocker):
|
|
26
25
|
|
|
@@ -33,7 +32,7 @@ def test_validate_state_id_negative(state_id, mocker):
|
|
|
33
32
|
fake_error.assert_called_with("\nState ID cannot be '0' or negative. Please enter a valid state ID.\n")
|
|
34
33
|
|
|
35
34
|
@pytest.mark.parametrize('state_id',[
|
|
36
|
-
'4', '10', '15', '0000020'
|
|
35
|
+
'4', '10', '15', '0000020'
|
|
37
36
|
])
|
|
38
37
|
def test_validate_state_id_out_scope(state_id, mocker):
|
|
39
38
|
|
|
@@ -156,21 +155,21 @@ def test_load_state_no_args(mocker):
|
|
|
156
155
|
|
|
157
156
|
|
|
158
157
|
def test_save_state_no_args(mocker):
|
|
159
|
-
fake_run = mocker.patch("pygitgo.commands.state.run_command")
|
|
158
|
+
fake_run = mocker.patch("pygitgo.commands.state.run_command", return_value="Saved working directory")
|
|
160
159
|
fake_success = mocker.patch("pygitgo.commands.state.success")
|
|
161
160
|
|
|
162
161
|
save_state()
|
|
163
162
|
|
|
164
|
-
fake_run.assert_called_once_with(["git", "stash", "push", "-m", "Auto-Save"])
|
|
163
|
+
fake_run.assert_called_once_with(["git", "stash", "push", "-m", "Auto-Save"], allow_fail=True)
|
|
165
164
|
fake_success.assert_called_once_with("\nState 'Auto-Save' saved successfully.\n")
|
|
166
165
|
|
|
167
166
|
def test_save_state_with_name(mocker):
|
|
168
|
-
fake_run = mocker.patch("pygitgo.commands.state.run_command")
|
|
167
|
+
fake_run = mocker.patch("pygitgo.commands.state.run_command", return_value="Saved working directory")
|
|
169
168
|
fake_success = mocker.patch("pygitgo.commands.state.success")
|
|
170
169
|
|
|
171
170
|
save_state("My-State")
|
|
172
171
|
|
|
173
|
-
fake_run.assert_called_once_with(["git", "stash", "push", "-m", "My-State"])
|
|
172
|
+
fake_run.assert_called_once_with(["git", "stash", "push", "-m", "My-State"], allow_fail=True)
|
|
174
173
|
fake_success.assert_called_once_with("\nState 'My-State' saved successfully.\n")
|
|
175
174
|
|
|
176
175
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|