smart-commit-tool 2.0.2__tar.gz → 2.0.3__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.
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/PKG-INFO +1 -1
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/pyproject.toml +1 -1
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/src/smart_commit/services/git.py +32 -13
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/.github/workflows/smart_commit_ci.yml +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/.gitignore +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/LICENSE +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/README.md +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/README.ru.md +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/assets/demonstration.gif +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/src/smart_commit/cli.py +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/src/smart_commit/config.py +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/src/smart_commit/constants.py +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/src/smart_commit/exceptions.py +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/src/smart_commit/logger.py +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/src/smart_commit/services/ci.py +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/src/smart_commit/services/security.py +0 -0
- {smart_commit_tool-2.0.2 → smart_commit_tool-2.0.3}/src/smart_commit/services/validator.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "smart-commit-tool"
|
|
7
|
-
version = "2.0.
|
|
7
|
+
version = "2.0.3"
|
|
8
8
|
description = "Automated pre-push workflow manager with built-in code quality enforcement and smart branch protection."
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.11"
|
|
@@ -7,21 +7,32 @@ from ..logger import Console, logger
|
|
|
7
7
|
class GitService:
|
|
8
8
|
@classmethod
|
|
9
9
|
def _run(cls, cmd: list[str], silent: bool = True) -> subprocess.CompletedProcess:
|
|
10
|
-
"""Internal helper for executing Git commands."""
|
|
10
|
+
"""Internal helper for executing Git commands with combined output."""
|
|
11
11
|
logger.debug(f"Git CMD: {' '.join(cmd)}")
|
|
12
|
-
return subprocess.run(cmd, capture_output=
|
|
12
|
+
return subprocess.run(cmd, capture_output=True, text=True)
|
|
13
13
|
|
|
14
14
|
@classmethod
|
|
15
15
|
def ensure_repo(cls):
|
|
16
|
-
"""Checks for repository initialization
|
|
17
|
-
|
|
16
|
+
"""Checks for repository initialization, Detached HEAD, and ongoing merges/rebases."""
|
|
17
|
+
git_dir = Path(".git")
|
|
18
|
+
if not git_dir.exists():
|
|
18
19
|
Console.warning("Git not initialized. Initializing now...")
|
|
19
20
|
cls._run(["git", "init"])
|
|
21
|
+
is_rebase = (git_dir / "rebase-apply").exists() or (
|
|
22
|
+
git_dir / "rebase-merge"
|
|
23
|
+
).exists()
|
|
24
|
+
is_merge = (git_dir / "MERGE_HEAD").exists()
|
|
25
|
+
|
|
26
|
+
if is_rebase or is_merge:
|
|
27
|
+
raise GitOperationError(
|
|
28
|
+
"🛑 Git is currently in the middle of a REBASE or MERGE.\n"
|
|
29
|
+
"Please resolve conflicts manually or run 'git rebase --abort', then try again."
|
|
30
|
+
)
|
|
20
31
|
|
|
21
32
|
res = cls._run(["git", "branch", "--show-current"])
|
|
22
33
|
if not res.stdout.strip():
|
|
23
34
|
raise GitOperationError(
|
|
24
|
-
"You are in a DETACHED HEAD state.
|
|
35
|
+
"You are in a DETACHED HEAD state. Please switch to a branch (e.g., 'git checkout main')."
|
|
25
36
|
)
|
|
26
37
|
|
|
27
38
|
@classmethod
|
|
@@ -76,33 +87,41 @@ class GitService:
|
|
|
76
87
|
|
|
77
88
|
@classmethod
|
|
78
89
|
def commit(cls, message: str):
|
|
79
|
-
"""Commits changes
|
|
90
|
+
"""Commits changes. Ignores 'nothing to commit' errors to allow push-only flows."""
|
|
80
91
|
res = cls._run(["git", "commit", "-m", message])
|
|
92
|
+
|
|
81
93
|
if res.returncode != 0:
|
|
82
|
-
|
|
83
|
-
|
|
94
|
+
output = (res.stdout + res.stderr).lower()
|
|
95
|
+
if "nothing to commit" in output or "working tree clean" in output:
|
|
96
|
+
return
|
|
97
|
+
|
|
98
|
+
raise GitOperationError(
|
|
99
|
+
f"Commit failed. Git says:\n{res.stderr or res.stdout}"
|
|
100
|
+
)
|
|
84
101
|
|
|
85
102
|
@classmethod
|
|
86
103
|
def push_with_retry(cls, branch: str):
|
|
87
|
-
"""Pushes to remote, attempting a pull --rebase if rejected."""
|
|
104
|
+
"""Pushes to remote, attempting a pull --rebase if rejected or diverged."""
|
|
88
105
|
Console.info(f"Pushing to branch: {branch}...")
|
|
89
106
|
res = cls._run(["git", "push", "-u", "origin", branch])
|
|
90
107
|
|
|
91
108
|
if res.returncode == 0:
|
|
92
109
|
Console.success(f"Code successfully pushed to origin/{branch}!")
|
|
93
110
|
return
|
|
111
|
+
Console.warning("Push rejected or branches diverged. Remote changes detected.")
|
|
112
|
+
Console.info("Synchronizing via pull --rebase...")
|
|
94
113
|
|
|
95
|
-
Console.warning("Push rejected. Remote changes detected.")
|
|
96
|
-
Console.info("Synchronizing (pull --rebase)...")
|
|
97
114
|
pull_res = cls._run(["git", "pull", "origin", branch, "--rebase"])
|
|
98
115
|
|
|
99
116
|
if pull_res.returncode != 0:
|
|
100
117
|
error_msg = pull_res.stderr.strip() or pull_res.stdout.strip()
|
|
118
|
+
cls._run(["git", "rebase", "--abort"])
|
|
101
119
|
raise GitOperationError(
|
|
102
|
-
f"🛑 Rebase conflict detected
|
|
120
|
+
f"🛑 Rebase conflict! Conflicts were detected with remote files.\n"
|
|
121
|
+
f"Sync aborted. Please resolve manually. Git says:\n{error_msg}"
|
|
103
122
|
)
|
|
104
123
|
|
|
105
|
-
Console.success("Sync successful. Retrying push...")
|
|
124
|
+
Console.success("Sync successful. Retrying final push...")
|
|
106
125
|
push_retry = cls._run(["git", "push", "-u", "origin", branch])
|
|
107
126
|
|
|
108
127
|
if push_retry.returncode != 0:
|
|
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
|