commitflow 1.0.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.
@@ -0,0 +1,216 @@
1
+ Metadata-Version: 2.4
2
+ Name: commitflow
3
+ Version: 1.0.0
4
+ Summary: CLI tool for maintaining consistent Git commits automatically
5
+ Author: Abhinav Kumar Singh
6
+ Requires-Python: >=3.8
7
+ Description-Content-Type: text/markdown
8
+ License-File: LICENSE
9
+ Requires-Dist: colorama
10
+ Dynamic: author
11
+ Dynamic: description
12
+ Dynamic: description-content-type
13
+ Dynamic: license-file
14
+ Dynamic: requires-dist
15
+ Dynamic: requires-python
16
+ Dynamic: summary
17
+
18
+ # CommitFlow
19
+
20
+ ![Python](https://img.shields.io/badge/python-3.9%2B-blue)
21
+ ![License](https://img.shields.io/github/license/abhinav9444/commitflow)
22
+ ![Tests](https://img.shields.io/github/actions/workflow/status/abhinav9444/commitflow/tests.yml)
23
+ <!--
24
+ ![PyPI](https://img.shields.io/pypi/v/commitflow)
25
+
26
+ -->
27
+ CommitFlow is a lightweight command-line tool that helps developers maintain consistent Git commits automatically without interrupting their workflow .
28
+ It provides a simple interface to commit progress, automate daily commits and keep your GitHub contribution graph active while you focus on actual development.
29
+
30
+ ## Why CommitFlow?
31
+ > ### CommitFlow is built to simplify a common developer habit: committing progress regularly.
32
+ Developers often forget to commit progress regularly while working across multiple projects. CommitFlow simplifies this by providing a clean command-line workflow that helps automate and manage daily commits. It is designed to be simple, practical and useful for everyday development workflows.
33
+ > ### If this tool helps your workflow, feel free to star the repository ! It means a lot !!
34
+
35
+ ## Features
36
+ - Automatic repository detection
37
+ - Commit preview before committing
38
+ - Interactive commit workflow
39
+ - Quick commit mode for frequent commits
40
+ - Automatic daily commits (Scheduled runs)
41
+ - Windows Task Scheduler support
42
+ - Linux cron support
43
+ - Configuration file support
44
+ - Logging system
45
+ - Cross-platform terminal color support
46
+
47
+ <!--
48
+ ## Usage
49
+ commitflow
50
+ commitflow --quick
51
+ commitflow --auto
52
+ commitflow --setup
53
+ commitflow --schedule
54
+ ---
55
+ -->
56
+ ## Installation
57
+ Install CommitFlow directly from PyPI:
58
+ ```bash
59
+ pip install commitflow
60
+ ```
61
+ Verify installation:
62
+ ```bash
63
+ commitflow --version
64
+ ```
65
+ ## Quick Start
66
+ Run CommitFlow in interactive mode. This mode guides you through the commit process step by step.
67
+ ```bash
68
+ commitflow
69
+ ```
70
+ You will be prompted for:
71
+ - repository path
72
+ - files to add
73
+ - commit message
74
+ - push confirmation
75
+
76
+ CommitFlow shows a preview before committing.
77
+
78
+ ## CLI Commands
79
+ ### Interactive Mode (Default)
80
+ Run the standard interactive workflow:
81
+ ```bash
82
+ commitflow
83
+ ```
84
+
85
+ ### Quick Mode
86
+ Use repository settings from your configuration file.
87
+ ``` bash
88
+ commitflow --quick
89
+ ```
90
+ Quick mode skips repository selection and speeds up the commit process.
91
+
92
+ ### Auto Mode
93
+ Fully automatic commit process:
94
+ ``` bash
95
+ commitflow --auto
96
+ ```
97
+ This mode:
98
+ - adds files automatically
99
+ - commits with a default message
100
+ - optionally pushes to remote
101
+
102
+ Auto mode is mainly used by schedulers.
103
+
104
+ ### Setup Wizard
105
+ Run the configuration wizard:
106
+ ``` bash
107
+ commitflow --setup
108
+ ```
109
+ The setup wizard asks for:
110
+ - repository path
111
+ - automatic push preference
112
+ - default commit message
113
+ - daily schedule time
114
+
115
+ It can also configure the system scheduler automatically.
116
+
117
+ ### Scheduler Setup
118
+ Create an automated daily commit task:
119
+ ```bash
120
+ commitflow --schedule
121
+ ```
122
+ CommitFlow supports:
123
+ - Windows Task Scheduler
124
+ - Linux/macOS cron
125
+
126
+ Scheduler settings such as power conditions and retry behavior can be customized during setup.
127
+
128
+ ### Example Workflow
129
+ Typical setup:
130
+ ``` bash
131
+ commitflow --setup
132
+ ```
133
+ After configuration, CommitFlow can run automatic commits daily.
134
+
135
+ Manual commits can also be executed anytime:
136
+ ``` bash
137
+ commitflow --quick
138
+ ```
139
+ ### Configuration File
140
+ CommitFlow stores configuration in:
141
+ ``` bash
142
+ ~/.commitflow_config.json
143
+ ```
144
+ Example configuration:
145
+ ```bash
146
+ {
147
+ "repo": "/projects/my-project",
148
+ "auto_push": true,
149
+ "auto_add": ".",
150
+ "commit_message": "daily progress update"
151
+ }
152
+ ```
153
+ ### Logs
154
+ CommitFlow keeps logs for debugging and activity tracking.
155
+ Default log location:
156
+ ``` bash
157
+ ~/.commitflow.log
158
+ ```
159
+ Log entries include:
160
+ - commit operations
161
+ - warnings
162
+ - errors
163
+ - scheduler events
164
+
165
+ ### Supported Platforms
166
+ - Windows
167
+ - Linux
168
+ <!--
169
+ Schedulers supported:
170
+ - Windows Task Scheduler
171
+ - cron
172
+ -->
173
+ <!--
174
+ Running Tests
175
+
176
+ Install development dependencies:
177
+
178
+ pip install pytest
179
+
180
+ Run tests:
181
+
182
+ pytest
183
+
184
+ GitHub Actions automatically runs tests on each push.
185
+
186
+ Project Structure
187
+ commitflow
188
+
189
+ ├── daily_git_assistant
190
+ │ ├── main.py
191
+ │ ├── config.py
192
+ │ ├── git_utils.py
193
+ │ ├── logger.py
194
+ │ ├── repo_scanner.py
195
+ │ ├── scheduler.py
196
+ │ ├── ui.py
197
+ │ └── modes
198
+
199
+ ├── tests
200
+ ├── setup.py
201
+ └── README.md
202
+ -->
203
+
204
+ ### Contributing
205
+ Contributions are welcome. If you would like to improve CommitFlow:
206
+ - Fork the repository
207
+ - Create a feature branch
208
+ - Submit a pull request
209
+
210
+ Bug reports and feature suggestions are appreciated.
211
+
212
+ ### License
213
+ This project is licensed under the MIT License.
214
+
215
+ ### Author
216
+ Abhinav Kumar Singh
@@ -0,0 +1,19 @@
1
+ commitflow-1.0.0.dist-info/licenses/LICENSE,sha256=xc-pONOWUH4mK8fw4GjVCS3-4_PvclWW0gsrFOVsPcA,1097
2
+ daily_git_assistant/__init__.py,sha256=Aj77VL1d5Mdku7sgCgKQmPuYavPpAHuZuJcy6bygQZE,21
3
+ daily_git_assistant/config.py,sha256=Nn1FTVziG9eZM4vAnxCPW9E0Hi_RZOUrwn3Wpxcv3Oc,2543
4
+ daily_git_assistant/git_utils.py,sha256=_5hMXH12qpdJDC-z5Dju39X4necC5do5pHfcXvzNJi8,3177
5
+ daily_git_assistant/logger.py,sha256=xVmf-e1FFs4eMCXu4ZR1IE1RB322uvdLtMfKGS_CGIk,1997
6
+ daily_git_assistant/main.py,sha256=tR1huAl0EFe4Jb5ZoK3gFqHcPl1VKYhSIalQ0RBKs0M,2127
7
+ daily_git_assistant/repo_scanner.py,sha256=ad4wXWPcmLmxzPBfOx4ProYu2I0EPqYrihIHiYUy-hU,2581
8
+ daily_git_assistant/scheduler.py,sha256=yipEOEoUbuIjLW2eh6SjrOzE3XXlxyAVu9FC-OIdX2Y,6590
9
+ daily_git_assistant/ui.py,sha256=6KdOQcUa1XfpvbYCYpPDiPpVyAgs9bf0GrEDDgS0WAU,3383
10
+ daily_git_assistant/modes/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ daily_git_assistant/modes/auto.py,sha256=qn0z8U14HsrIev_Uw_uaBf_Fr4c1OxtLnX8lZEFPgM8,2650
12
+ daily_git_assistant/modes/interactive.py,sha256=zv1ADexjpnJQjhARJavmAfyfNpDwKfJ8iYXhMZi4hls,3759
13
+ daily_git_assistant/modes/quick.py,sha256=Fli3U4iKPvRarTrlAk0zL8BSrex0-UxKHq6ZtmCuaRw,2961
14
+ daily_git_assistant/modes/setup.py,sha256=02Fs3h9z78I0KvvIXuhHKlq5Px3b4EiSrt4ZpFnaEdk,2214
15
+ commitflow-1.0.0.dist-info/METADATA,sha256=BiJJlNTrF6QjHF8bsnrj9TSg-Dk3REopclefAeQRcbA,5208
16
+ commitflow-1.0.0.dist-info/WHEEL,sha256=YCfwYGOYMi5Jhw2fU4yNgwErybb2IX5PEwBKV4ZbdBo,91
17
+ commitflow-1.0.0.dist-info/entry_points.txt,sha256=XnAqmSVYYmxDwOR9m3KIoisLIMBpl7i97FLQd_dWMvc,61
18
+ commitflow-1.0.0.dist-info/top_level.txt,sha256=1hLlmrsma5OW_nRh4oaaAjf3DFK1837HWHU0FlL0HMw,20
19
+ commitflow-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ commitflow = daily_git_assistant.main:main
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Abhinav Kumar Singh
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.
@@ -0,0 +1 @@
1
+ daily_git_assistant
@@ -0,0 +1 @@
1
+ __version__ = "1.0.0"
@@ -0,0 +1,126 @@
1
+ import os
2
+ import json
3
+ from pathlib import Path
4
+
5
+ # Default config file location
6
+ CONFIG_PATH = os.path.join(Path.home(), ".commitflow_config.json")
7
+
8
+ # Default configuration values
9
+ DEFAULT_CONFIG = {
10
+ "repo": "",
11
+ "auto_push": False,
12
+ "auto_add": ".",
13
+ "commit_message": "Daily progress update",
14
+ "schedule_time": "21:00"
15
+ }
16
+
17
+
18
+ def create_default_config():
19
+ """
20
+ Create a config file with default values if it does not exist.
21
+ """
22
+ if not os.path.exists(CONFIG_PATH):
23
+ try:
24
+ with open(CONFIG_PATH, "w") as f:
25
+ json.dump(DEFAULT_CONFIG, f, indent=4)
26
+
27
+ return DEFAULT_CONFIG
28
+
29
+ except Exception as e:
30
+ raise RuntimeError(f"Failed to create config file: {e}")
31
+
32
+ return load_config()
33
+
34
+
35
+ def load_config():
36
+ """
37
+ Load configuration from config file.
38
+ """
39
+ try:
40
+ with open(CONFIG_PATH, "r") as f:
41
+ config = json.load(f)
42
+
43
+ return config
44
+
45
+ except FileNotFoundError:
46
+
47
+ return create_default_config()
48
+
49
+ except json.JSONDecodeError:
50
+
51
+ raise RuntimeError(
52
+ "Config file corrupted. Delete ~/.commitflow_config.json and run setup again."
53
+ )
54
+
55
+
56
+ def save_config(config_data):
57
+ """
58
+ Save updated configuration.
59
+ """
60
+
61
+ try:
62
+
63
+ with open(CONFIG_PATH, "w") as f:
64
+ json.dump(config_data, f, indent=4)
65
+
66
+ except Exception as e:
67
+
68
+ raise RuntimeError(f"Failed to save config: {e}")
69
+
70
+
71
+ def update_config(key, value):
72
+ """
73
+ Update a single configuration field.
74
+ """
75
+
76
+ config = load_config()
77
+
78
+ config[key] = value
79
+
80
+ save_config(config)
81
+
82
+
83
+ def validate_repo_path(repo_path):
84
+ """
85
+ Ensure repository path exists and is valid.
86
+ """
87
+
88
+ if not repo_path:
89
+ raise ValueError("Repository path not set in config")
90
+
91
+ if not os.path.exists(repo_path):
92
+ raise ValueError(f"Repository path does not exist: {repo_path}")
93
+
94
+ return True
95
+
96
+
97
+ def get_repo():
98
+ """
99
+ Retrieve repository path from config.
100
+ """
101
+
102
+ config = load_config()
103
+
104
+ repo = config.get("repo", "")
105
+
106
+ validate_repo_path(repo)
107
+
108
+ return repo
109
+
110
+
111
+ def reset_config():
112
+ """
113
+ Reset configuration to default values.
114
+ """
115
+
116
+ try:
117
+
118
+ with open(CONFIG_PATH, "w") as f:
119
+
120
+ json.dump(DEFAULT_CONFIG, f, indent=4)
121
+
122
+ return True
123
+
124
+ except Exception as e:
125
+
126
+ raise RuntimeError(f"Failed to reset config: {e}")
@@ -0,0 +1,165 @@
1
+ import os
2
+ import subprocess
3
+
4
+
5
+ def run_git_command(cmd, repo_path):
6
+ """
7
+ Execute a git command safely.
8
+ """
9
+
10
+ try:
11
+
12
+ result = subprocess.run(
13
+ cmd,
14
+ cwd=repo_path,
15
+ capture_output=True,
16
+ text=True
17
+ )
18
+
19
+ return result
20
+
21
+ except Exception as e:
22
+
23
+ raise RuntimeError(f"Git command failed: {e}")
24
+
25
+
26
+ def is_git_repo(repo_path):
27
+ """
28
+ Validate whether a directory is a git repository.
29
+ """
30
+
31
+ if not os.path.exists(repo_path):
32
+ return False
33
+
34
+ result = run_git_command(["git", "rev-parse", "--is-inside-work-tree"], repo_path)
35
+
36
+ return result.returncode == 0
37
+
38
+
39
+ def get_repo_name(repo_path):
40
+ """
41
+ Get repository folder name.
42
+ """
43
+
44
+ return os.path.basename(os.path.abspath(repo_path))
45
+
46
+
47
+ def get_branch(repo_path):
48
+ """
49
+ Get current git branch.
50
+ """
51
+
52
+ result = run_git_command(["git", "branch", "--show-current"], repo_path)
53
+
54
+ if result.returncode != 0:
55
+ return "unknown"
56
+
57
+ return result.stdout.strip()
58
+
59
+
60
+ def get_remote_url(repo_path):
61
+ """
62
+ Retrieve repository remote URL.
63
+ """
64
+
65
+ result = run_git_command(
66
+ ["git", "config", "--get", "remote.origin.url"],
67
+ repo_path
68
+ )
69
+
70
+ if result.returncode != 0:
71
+ return "unknown"
72
+
73
+ return result.stdout.strip()
74
+
75
+
76
+ def get_status(repo_path):
77
+ """
78
+ Show git status.
79
+ """
80
+
81
+ result = run_git_command(["git", "status"], repo_path)
82
+
83
+ return result.stdout
84
+
85
+
86
+ def add_files(repo_path, files):
87
+ """
88
+ Stage files for commit.
89
+ """
90
+
91
+ result = run_git_command(["git", "add", files], repo_path)
92
+
93
+ if result.returncode != 0:
94
+ raise RuntimeError("Failed to add files")
95
+
96
+
97
+ def preview_staged_changes(repo_path):
98
+ """
99
+ Preview staged changes before committing.
100
+ """
101
+
102
+ result = run_git_command(["git", "diff", "--cached"], repo_path)
103
+
104
+ return result.stdout
105
+
106
+
107
+ def has_changes_to_commit(repo_path):
108
+ """
109
+ Detect if there are staged changes.
110
+ """
111
+
112
+ result = run_git_command(
113
+ ["git", "diff", "--cached", "--quiet"],
114
+ repo_path
115
+ )
116
+
117
+ # returncode 0 means no changes
118
+ return result.returncode != 0
119
+
120
+
121
+ def commit_changes(repo_path, message):
122
+ """
123
+ Commit staged changes.
124
+ """
125
+
126
+ result = run_git_command(
127
+ ["git", "commit", "-m", message],
128
+ repo_path
129
+ )
130
+
131
+ if result.returncode != 0:
132
+ raise RuntimeError("Commit failed")
133
+
134
+ return result.stdout
135
+
136
+
137
+ def push_changes(repo_path):
138
+ """
139
+ Push commit to remote repository.
140
+ """
141
+
142
+ result = run_git_command(["git", "push"], repo_path)
143
+
144
+ if result.returncode != 0:
145
+ raise RuntimeError("Push failed")
146
+
147
+ return result.stdout
148
+
149
+
150
+ def count_staged_files(repo_path):
151
+ """
152
+ Count number of staged files.
153
+ """
154
+
155
+ result = run_git_command(
156
+ ["git", "diff", "--name-only", "--cached"],
157
+ repo_path
158
+ )
159
+
160
+ if result.returncode != 0:
161
+ return 0
162
+
163
+ files = result.stdout.strip().splitlines()
164
+
165
+ return len(files)
@@ -0,0 +1,105 @@
1
+ import os
2
+ from pathlib import Path
3
+ from datetime import datetime
4
+
5
+
6
+ # Log file location
7
+ LOG_PATH = os.path.join(Path.home(), ".commitflow.log")
8
+
9
+ # Ensure log directory exists (future-proof safety)
10
+ try:
11
+ log_dir = os.path.dirname(LOG_PATH)
12
+ if log_dir:
13
+ os.makedirs(log_dir, exist_ok=True)
14
+ except Exception:
15
+ # Logging should never break the application
16
+ pass
17
+
18
+
19
+ def _write_log(level, message):
20
+ """
21
+ Internal function to write log messages.
22
+ """
23
+
24
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
25
+
26
+ log_entry = f"[{timestamp}] [{level}] {message}\n"
27
+
28
+ try:
29
+ with open(LOG_PATH, "a", encoding="utf-8") as log_file:
30
+ log_file.write(log_entry)
31
+
32
+ except Exception:
33
+ # Logging should never crash the application
34
+ pass
35
+
36
+
37
+ def log_info(message):
38
+ """
39
+ Log informational message.
40
+ """
41
+
42
+ _write_log("INFO", message)
43
+
44
+
45
+ def log_warning(message):
46
+ """
47
+ Log warning message.
48
+ """
49
+
50
+ _write_log("WARNING", message)
51
+
52
+
53
+ def log_error(message):
54
+ """
55
+ Log error message.
56
+ """
57
+
58
+ _write_log("ERROR", message)
59
+
60
+
61
+ def log_commit(repo, branch, files, message, pushed):
62
+ """
63
+ Specialized log for commit operations.
64
+ """
65
+
66
+ commit_log = (
67
+ f"repo={repo} "
68
+ f"branch={branch} "
69
+ f"files={files} "
70
+ f"message='{message}' "
71
+ f"pushed={pushed}"
72
+ )
73
+
74
+ _write_log("COMMIT", commit_log)
75
+
76
+
77
+ def read_logs(lines=20):
78
+ """
79
+ Read last N log entries.
80
+ """
81
+
82
+ if not os.path.exists(LOG_PATH):
83
+ return []
84
+
85
+ try:
86
+ with open(LOG_PATH, "r", encoding="utf-8") as f:
87
+ logs = f.readlines()
88
+
89
+ return logs[-lines:]
90
+
91
+ except Exception:
92
+ return []
93
+
94
+
95
+ def clear_logs():
96
+ """
97
+ Clear log file.
98
+ """
99
+
100
+ try:
101
+ if os.path.exists(LOG_PATH):
102
+ open(LOG_PATH, "w").close()
103
+
104
+ except Exception:
105
+ pass