ezgit-sync 0.1.0__py3-none-any.whl

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.
autogit/__init__.py ADDED
@@ -0,0 +1 @@
1
+ """Top-level package for auto_git."""
autogit/__main__.py ADDED
@@ -0,0 +1,4 @@
1
+ from .cli import app
2
+
3
+ if __name__ == "__main__":
4
+ app()
autogit/autogit.py ADDED
@@ -0,0 +1,139 @@
1
+ """Main module for autogit."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import subprocess
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ # ANSI Escape Sequences for Terminal Styling
10
+ COLOR_RESET = "\033[0m"
11
+ BOLD = "\033[1m"
12
+ DIM = "\033[2m"
13
+
14
+ COLOR_GREEN = "\033[92m"
15
+ COLOR_YELLOW = "\033[93m"
16
+ COLOR_RED = "\033[91m"
17
+ COLOR_CYAN = "\033[96m"
18
+
19
+
20
+ def log_success(message: str) -> None:
21
+ """Prints a styled success message."""
22
+ print(f"{COLOR_GREEN}{BOLD}[SUCCESS]{COLOR_RESET} {message}")
23
+
24
+
25
+ def log_warning(message: str) -> None:
26
+ """Prints a styled warning message."""
27
+ print(f"{COLOR_YELLOW}{BOLD}[WARNING]{COLOR_RESET} {message}")
28
+
29
+
30
+ def log_info(message: str) -> None:
31
+ """Prints a styled info message."""
32
+ print(f"{COLOR_CYAN}{BOLD}[INFO]{COLOR_RESET} {message}")
33
+
34
+
35
+ def log_error_with_reasons(title: str, reasons: list[str], raw_error: str | None = None) -> None:
36
+ """Formats and prints error explanations with probable causes and solutions."""
37
+ sys.stderr.write(f"\n{COLOR_RED}{BOLD}[ERROR] {title}{COLOR_RESET}\n")
38
+ sys.stderr.write(f"{BOLD}Possible Reasons & Solutions:{COLOR_RESET}\n")
39
+ for reason in reasons:
40
+ sys.stderr.write(f" • {reason}\n")
41
+
42
+ if raw_error:
43
+ sys.stderr.write(f"\n{DIM}Raw Git Error Details:\n{raw_error.strip()}{COLOR_RESET}\n")
44
+ sys.stderr.write("\n")
45
+
46
+
47
+ def run_git(args: list[str], repo_root: Path) -> str:
48
+ """Executes a git command and returns its stripped stdout."""
49
+ result = subprocess.run(
50
+ ["git", *args],
51
+ cwd=repo_root,
52
+ check=True,
53
+ capture_output=True,
54
+ text=True,
55
+ )
56
+ return result.stdout.strip()
57
+
58
+
59
+ def verify_git_repository(repo_root: Path) -> bool:
60
+ """Checks if the current working directory is inside a valid Git repository."""
61
+ try:
62
+ run_git(["rev-parse", "--is-inside-work-tree"], repo_root)
63
+ return True
64
+ except subprocess.CalledProcessError:
65
+ log_error_with_reasons(
66
+ title=f"The directory '{repo_root.name}' is not a valid Git repository.",
67
+ reasons=[
68
+ "Git is not initialized in this directory. Run 'git init' to create a new repository.",
69
+ "You might be running the command in the wrong folder. Navigate to your project root.",
70
+ ],
71
+ )
72
+ return False
73
+
74
+
75
+ def get_current_branch(repo_root: Path) -> str:
76
+ """Retrieves the name of the currently active branch."""
77
+ try:
78
+ branch = run_git(["rev-parse", "--abbrev-ref", "HEAD"], repo_root)
79
+ if branch == "HEAD":
80
+ raise RuntimeError("DETACHED_HEAD")
81
+ return branch
82
+ except (subprocess.CalledProcessError, RuntimeError) as exc:
83
+ raw_err = exc.stderr if isinstance(exc, subprocess.CalledProcessError) else str(exc)
84
+ log_error_with_reasons(
85
+ title="Failed to determine active Git branch.",
86
+ reasons=[
87
+ "This repository might be completely empty (no commits yet). Create an initial commit first: 'git add . && git commit -m \"initial commit\"'",
88
+ "Your repository might be in a 'detached HEAD' state. Switch to a branch using 'git checkout <branch-name>'.",
89
+ ],
90
+ raw_error=raw_err,
91
+ )
92
+ raise exc
93
+
94
+
95
+ def pull_remote_changes(repo_root: Path, branch: str) -> bool:
96
+ """Pulls recent changes from the remote repository."""
97
+ log_info(f"Pulling latest updates from origin/{branch}...")
98
+ try:
99
+ run_git(["pull", "origin", branch], repo_root)
100
+ return True
101
+ except subprocess.CalledProcessError as exc:
102
+ log_error_with_reasons(
103
+ title=f"Failed to pull changes from origin/{branch}.",
104
+ reasons=[
105
+ "There might be merge conflicts between local and remote files. Resolve conflicts manually.",
106
+ "The remote branch 'origin/{branch}' might not exist yet on the remote server.",
107
+ "You might be offline or lack permission to access the remote repository.",
108
+ ],
109
+ raw_error=exc.stderr,
110
+ )
111
+ return False
112
+
113
+
114
+ def has_local_changes(repo_root: Path) -> bool:
115
+ """Checks if there are uncommitted local modifications."""
116
+ status = run_git(["status", "--porcelain"], repo_root)
117
+ return bool(status)
118
+
119
+
120
+ def sync_local_changes(repo_root: Path, branch: str, commit_message: str) -> None:
121
+ """Stages, commits, and pushes local changes to the remote repository."""
122
+ log_info("Staging and committing local changes...")
123
+ run_git(["add", "-A"], repo_root)
124
+ run_git(["commit", "-m", commit_message], repo_root)
125
+
126
+ log_info(f"Pushing updates to origin/{branch}...")
127
+ try:
128
+ run_git(["push", "origin", branch], repo_root)
129
+ except subprocess.CalledProcessError as exc:
130
+ log_error_with_reasons(
131
+ title=f"Failed to push changes to origin/{branch}.",
132
+ reasons=[
133
+ "Remote contains commits that you do not have locally. Try pulling first.",
134
+ "You may not have write permissions for this remote repository.",
135
+ "Your authentication credentials (SSH key or GitHub token) might be missing or expired.",
136
+ ],
137
+ raw_error=exc.stderr,
138
+ )
139
+ raise exc
autogit/cli.py ADDED
@@ -0,0 +1,60 @@
1
+ """Console script for autogit."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import argparse
6
+ import sys
7
+ from pathlib import Path
8
+
9
+ from autogit.autogit import (
10
+ get_current_branch,
11
+ has_local_changes,
12
+ log_error,
13
+ log_success,
14
+ log_warning,
15
+ pull_remote_changes,
16
+ sync_local_changes,
17
+ verify_git_repository,
18
+ )
19
+
20
+
21
+ def main(argv: list[str] | None = None) -> int:
22
+ """Console script for autogit."""
23
+ parser = argparse.ArgumentParser(
24
+ description="Pull remote updates, stage, commit, and push the current repository to GitHub."
25
+ )
26
+ parser.add_argument(
27
+ "-m",
28
+ "--message",
29
+ default="Sync updates",
30
+ help="Commit message to use when creating the commit.",
31
+ )
32
+ args = parser.parse_args(argv)
33
+ repo_root = Path.cwd()
34
+
35
+ if not verify_git_repository(repo_root):
36
+ log_error(f"The current directory '{repo_root}' is not a valid Git repository.")
37
+ return 1
38
+
39
+ try:
40
+ branch = get_current_branch(repo_root)
41
+
42
+ if not pull_remote_changes(repo_root, branch):
43
+ return 1
44
+
45
+ if not has_local_changes(repo_root):
46
+ log_warning("No new local changes to commit after pulling updates.")
47
+ return 0
48
+
49
+ sync_local_changes(repo_root, branch, args.message)
50
+
51
+ log_success(f"Successfully synchronized repository with origin/{branch}.")
52
+ return 0
53
+
54
+ except Exception as exc:
55
+ log_error(f"An error occurred during synchronization: {exc}")
56
+ return 1
57
+
58
+ app = main
59
+ if __name__ == "__main__":
60
+ sys.exit(main())
autogit/py.typed ADDED
@@ -0,0 +1 @@
1
+ # Marker file for PEP 561
autogit/utils.py ADDED
@@ -0,0 +1,2 @@
1
+ def do_something_useful() -> None:
2
+ print("Replace this with a utility function")
@@ -0,0 +1,81 @@
1
+ Metadata-Version: 2.4
2
+ Name: ezgit-sync
3
+ Version: 0.1.0
4
+ Summary: This package is a basic git automator for deep learning and machine learning tasks.
5
+ Project-URL: bugs, https://github.com/hasanaliozkan-dev/autogit/issues
6
+ Project-URL: changelog, https://github.com/hasanaliozkan-dev/autogit/releases
7
+ Project-URL: documentation, https://hasanaliozkan-dev.github.io/autogit/
8
+ Project-URL: homepage, https://github.com/hasanaliozkan-dev/autogit
9
+ Author-email: Hasan Ali Özkan <hasanaliozkan@mu.edu.tr>
10
+ Maintainer-email: Hasan Ali Özkan <hasanaliozkan@mu.edu.tr>
11
+ License: MIT
12
+ License-File: LICENSE
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Typing :: Typed
16
+ Requires-Python: >=3.12
17
+ Requires-Dist: rich
18
+ Requires-Dist: typer
19
+ Description-Content-Type: text/markdown
20
+
21
+ # auto_git
22
+
23
+ ![PyPI version](https://img.shields.io/pypi/v/autogit.svg)
24
+
25
+ This package is a basic git automator for deep learning and machine learning tasks.
26
+
27
+ * [GitHub](https://github.com/hasanaliozkan-dev/autogit/) | [PyPI](https://pypi.org/project/autogit/) | [Documentation](https://hasanaliozkan-dev.github.io/autogit/)
28
+ * Created by [Hasan Ali Özkan](https://hasanaliozkan-dev.github.io/) | GitHub [@hasanaliozkan-dev](https://github.com/hasanaliozkan-dev) | PyPI [@hasanaliozkan](https://pypi.org/user/hasanaliozkan/)
29
+ * MIT License
30
+
31
+ ## Features
32
+
33
+ * TODO
34
+
35
+ ## Documentation
36
+
37
+ Documentation is built with [Zensical](https://zensical.org/) and deployed to GitHub Pages.
38
+
39
+ * **Live site:** https://hasanaliozkan-dev.github.io/autogit/
40
+ * **Preview locally:** `just docs-serve` (serves at http://localhost:8000)
41
+ * **Build:** `just docs-build`
42
+
43
+ API documentation is auto-generated from docstrings using [mkdocstrings](https://mkdocstrings.github.io/).
44
+
45
+ Docs deploy automatically on push to `main` via GitHub Actions. To enable this, go to your repo's Settings > Pages and set the source to **GitHub Actions**.
46
+
47
+ ## Development
48
+
49
+ To set up for local development:
50
+
51
+ ```sh
52
+ # Clone your fork
53
+ git clone git@github.com:your_username/autogit.git
54
+ cd autogit
55
+
56
+ # Install dependencies
57
+ uv sync
58
+
59
+ # Create a branch for development
60
+ git checkout -b feature/new-awesome-feature
61
+ ```
62
+
63
+ This installs the CLI globally but with live updates - any changes you make to the source code are immediately available when you run `autogit`.
64
+
65
+ Run tests:
66
+
67
+ ```bash
68
+ uv run pytest
69
+ ```
70
+
71
+ Run quality checks (format, lint, type check, test):
72
+
73
+ ```bash
74
+ just qa
75
+ ```
76
+
77
+ ## Author
78
+
79
+ auto_git was created in 2026 by Hasan Ali Özkan.
80
+
81
+ Built with [Cookiecutter](https://github.com/cookiecutter/cookiecutter) and the [audreyfeldroy/cookiecutter-pypackage](https://github.com/audreyfeldroy/cookiecutter-pypackage) project template.
@@ -0,0 +1,11 @@
1
+ autogit/__init__.py,sha256=NnmvoOhzsrQhG-0n-m1mVAqsP8U5n7FATgJrPuVtiB0,38
2
+ autogit/__main__.py,sha256=Qd-f8z2Q2vpiEP2x6PBFsJrpACWDVxFKQk820MhFmHo,59
3
+ autogit/autogit.py,sha256=WVykX1qGJyCskO9Phs6-b7C1Wx_0p6BpUyESZXDcJvc,5194
4
+ autogit/cli.py,sha256=pKiWmBagVYzaPWWkOT60iu54mzj1x7V2LD7KU4zE2kc,1557
5
+ autogit/py.typed,sha256=8PjyZ1aVoQpRVvt71muvuq5qE-jTFZkK-GLHkhdebmc,26
6
+ autogit/utils.py,sha256=HppGIYjTTn56wTOArW3kxDDc2bMnrGVBQB2DIaoLnI4,85
7
+ ezgit_sync-0.1.0.dist-info/METADATA,sha256=LlJ7xJX8rc9xk5_IECmemyVj5QubpMfiwg1UtXMgiks,2696
8
+ ezgit_sync-0.1.0.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
9
+ ezgit_sync-0.1.0.dist-info/entry_points.txt,sha256=f3gTyjE1mWQc45DlNd5ry0yEQnRRAwl1irLam9cGvTw,45
10
+ ezgit_sync-0.1.0.dist-info/licenses/LICENSE,sha256=OCptpIILuJZlFEE1yk_SKTrMfXvGHgTXSD07s-RM1bI,1074
11
+ ezgit_sync-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.31.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ autogit = autogit.cli:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026, Hasan Ali Özkan
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.