gitpush-tool 0.1.3__tar.gz → 0.2.0__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.
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitpush-tool
3
- Version: 0.1.3
3
+ Version: 0.2.0
4
4
  Summary: A CLI tool to simplify Git push operations with intelligent defaults and options.
5
- Home-page: https://github.com/yourusername/gitpush_tool
5
+ Home-page: https://github.com/inevitablegs/gitpush
6
6
  Author: Ganesh Sonawane
7
- Author-email: sonawaneganu3101@example.com
7
+ Author-email: sonawaneganu3101@gmail.com
8
8
  License: MIT
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: License :: OSI Approved :: MIT License
@@ -12,6 +12,7 @@ Classifier: Operating System :: OS Independent
12
12
  Requires-Python: >=3.6
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
+ Requires-Dist: requests>=2.25.0
15
16
  Dynamic: author
16
17
  Dynamic: author-email
17
18
  Dynamic: classifier
@@ -20,6 +21,7 @@ Dynamic: description-content-type
20
21
  Dynamic: home-page
21
22
  Dynamic: license
22
23
  Dynamic: license-file
24
+ Dynamic: requires-dist
23
25
  Dynamic: requires-python
24
26
  Dynamic: summary
25
27
 
@@ -0,0 +1 @@
1
+ __version__ = "0.2.0"
@@ -0,0 +1,285 @@
1
+ #!/usr/bin/env python3
2
+ import os
3
+ import argparse
4
+ import sys
5
+ import requests
6
+ from getpass import getpass
7
+ import json
8
+ from datetime import datetime
9
+
10
+ def get_github_token():
11
+ """Get GitHub token from various sources with priority order"""
12
+ # 1. Check environment variable
13
+ token = os.getenv("GITHUB_TOKEN")
14
+
15
+ # 2. Check token file
16
+ if not token:
17
+ token_path = os.path.join(os.path.dirname(__file__), '..', 'token')
18
+ if os.path.exists(token_path):
19
+ with open(token_path, 'r') as f:
20
+ token = f.read().strip()
21
+
22
+ # 3. Prompt user if still not found
23
+ if not token:
24
+ print("\n🔑 GitHub personal access token is required to create repositories.")
25
+ print("Create one at: https://github.com/settings/tokens (with 'repo' scope)")
26
+ token = getpass("Enter your GitHub token: ")
27
+
28
+ return token
29
+
30
+ def get_github_username():
31
+ """Get GitHub username from config or API"""
32
+ try:
33
+ # Try git config first
34
+ username = os.popen("git config github.user").read().strip()
35
+ if username:
36
+ return username
37
+
38
+ # Fallback to API if token exists
39
+ token = get_github_token()
40
+ if token:
41
+ headers = {
42
+ "Authorization": f"token {token}",
43
+ "Accept": "application/vnd.github+json"
44
+ }
45
+ response = requests.get("https://api.github.com/user", headers=headers)
46
+ if response.status_code == 200:
47
+ return response.json().get("login")
48
+ except:
49
+ pass
50
+ return None
51
+
52
+ def create_github_repo(repo_name, private=False, description=""):
53
+ """Create a new GitHub repository using the GitHub API"""
54
+ token = get_github_token()
55
+
56
+ if not token:
57
+ print("❌ GitHub token is required to create a repository")
58
+ return None
59
+
60
+ headers = {
61
+ "Authorization": f"token {token}",
62
+ "Accept": "application/vnd.github+json",
63
+ "X-GitHub-Api-Version": "2022-11-28"
64
+ }
65
+
66
+ data = {
67
+ "name": repo_name,
68
+ "description": description,
69
+ "private": private,
70
+ "auto_init": False,
71
+ "has_issues": True,
72
+ "has_projects": False,
73
+ "has_wiki": False
74
+ }
75
+
76
+ try:
77
+ response = requests.post(
78
+ "https://api.github.com/user/repos",
79
+ headers=headers,
80
+ json=data,
81
+ timeout=10
82
+ )
83
+
84
+ # Detailed error handling
85
+ if response.status_code == 401:
86
+ print("❌ Authentication failed. Invalid or expired token.")
87
+ print("Please create a new token with 'repo' scope at:")
88
+ print("https://github.com/settings/tokens")
89
+ return None
90
+
91
+ elif response.status_code == 403:
92
+ print("❌ Permission denied (403 Forbidden). Possible reasons:")
93
+ print("- Token doesn't have 'repo' scope")
94
+ print("- Token is restricted to specific repositories")
95
+ print("- GitHub API rate limit exceeded")
96
+
97
+ # Try to get rate limit info
98
+ try:
99
+ limits = requests.get(
100
+ "https://api.github.com/rate_limit",
101
+ headers=headers
102
+ ).json()
103
+ remaining = limits['resources']['core']['remaining']
104
+ reset_time = datetime.fromtimestamp(limits['resources']['core']['reset']).strftime('%Y-%m-%d %H:%M:%S')
105
+ print(f"⏳ API calls remaining: {remaining}")
106
+ print(f"🔄 Rate limit resets at: {reset_time}")
107
+ except:
108
+ pass
109
+
110
+ return None
111
+
112
+ elif response.status_code == 422:
113
+ error_data = response.json()
114
+ if 'errors' in error_data:
115
+ for error in error_data['errors']:
116
+ if error.get('field') == 'name' and 'already exists' in error.get('message', ''):
117
+ print(f"❌ Repository '{repo_name}' already exists")
118
+ return None
119
+ print(f"❌ Validation error: {error_data.get('message', 'Unknown error')}")
120
+ return None
121
+
122
+ elif response.status_code != 201:
123
+ print(f"❌ Failed to create repository (HTTP {response.status_code}): {response.text}")
124
+ return None
125
+
126
+ repo_url = response.json()["html_url"]
127
+ print(f"✅ Successfully created repository: {repo_url}")
128
+ return repo_url
129
+
130
+ except requests.exceptions.RequestException as e:
131
+ print(f"❌ Failed to create repository: {str(e)}")
132
+ if "Max retries exceeded" in str(e):
133
+ print("⚠️ Network connection problem detected")
134
+ return None
135
+
136
+ def create_with_gh_cli(repo_name, private=False, description=""):
137
+ """Alternative using GitHub CLI if installed"""
138
+ try:
139
+ private_flag = "--private" if private else "--public"
140
+ cmd = f"gh repo create {repo_name} {private_flag} --source=. --remote=origin --push"
141
+ if description:
142
+ cmd += f" --description \"{description}\""
143
+ return os.system(cmd) == 0
144
+ except:
145
+ return False
146
+
147
+ def initialize_repository(remote_url=None):
148
+ """Initialize git repository with sensible defaults"""
149
+ if not os.path.exists(".git"):
150
+ print("🛠 Initializing git repository")
151
+ os.system("git init")
152
+ os.system("git branch -M main")
153
+
154
+ if remote_url:
155
+ os.system(f"git remote add origin {remote_url}")
156
+
157
+ # Create basic .gitignore if doesn't exist
158
+ if not os.path.exists(".gitignore"):
159
+ with open(".gitignore", "w") as f:
160
+ f.write("""# Python
161
+ __pycache__/
162
+ *.py[cod]
163
+ *.so
164
+ .Python
165
+ env/
166
+ venv/
167
+ .env
168
+
169
+ # IDE
170
+ .vscode/
171
+ .idea/
172
+ *.swp
173
+ *.swo
174
+
175
+ # System
176
+ .DS_Store
177
+ Thumbs.db
178
+
179
+ # Project specific
180
+ *.log
181
+ *.tmp
182
+ *.bak
183
+ """)
184
+ print("📁 Created .gitignore file")
185
+
186
+ def check_for_updates():
187
+ """Check for newer versions on PyPI"""
188
+ try:
189
+ current_version = "0.2.0" # Should match your setup.py
190
+ response = requests.get("https://pypi.org/pypi/gitpush-tool/json", timeout=2)
191
+ latest_version = response.json()["info"]["version"]
192
+ if latest_version != current_version:
193
+ print(f"ℹ️ New version available: {latest_version} (you have {current_version})")
194
+ print(" Run 'pip install --upgrade gitpush-tool' to update")
195
+ except:
196
+ pass
197
+
198
+ def run():
199
+ parser = argparse.ArgumentParser(
200
+ description="🚀 Supercharged Git push tool with GitHub repo creation",
201
+ formatter_class=argparse.RawDescriptionHelpFormatter,
202
+ epilog="""Examples:
203
+ Basic push: gitpush_tool "Commit message"
204
+ Create new repo: gitpush_tool "Initial commit" --new-repo project-name
205
+ Private repository: gitpush_tool --new-repo private-project --private
206
+ Force push: gitpush_tool "Fix critical bug" --force
207
+ Push specific branch: gitpush_tool "Update feature" feature-branch upstream
208
+ """
209
+ )
210
+ parser.add_argument("commit", nargs="?", help="Commit message")
211
+ parser.add_argument("branch", nargs="?", default="main", help="Branch name (default: main)")
212
+ parser.add_argument("remote", nargs="?", default="origin", help="Remote name (default: origin)")
213
+ parser.add_argument("--force", action="store_true", help="Force push with --force-with-lease")
214
+ parser.add_argument("--tags", action="store_true", help="Push tags")
215
+ parser.add_argument("--init", action="store_true", help="Initialize git repo")
216
+ parser.add_argument("--new-repo", metavar="NAME", help="Create new GitHub repository")
217
+ parser.add_argument("--private", action="store_true", help="Make repository private")
218
+ parser.add_argument("--description", help="Repository description")
219
+
220
+ args = parser.parse_args()
221
+
222
+ if args.new_repo:
223
+ print(f"🆕 Creating repository: {args.new_repo}")
224
+ repo_url = create_github_repo(
225
+ args.new_repo,
226
+ private=args.private,
227
+ description=args.description or ""
228
+ )
229
+
230
+ # Fallback to GitHub CLI if API fails
231
+ if not repo_url:
232
+ print("⚠️ Falling back to GitHub CLI...")
233
+ if create_with_gh_cli(args.new_repo, args.private, args.description):
234
+ username = get_github_username()
235
+ if username:
236
+ repo_url = f"https://github.com/{username}/{args.new_repo}.git"
237
+ else:
238
+ repo_url = None
239
+ else:
240
+ print("❌ Could not create repository. Please check your credentials.")
241
+ print("You can install GitHub CLI with: brew install gh (Mac) or winget install --id GitHub.cli (Windows)")
242
+ sys.exit(1)
243
+
244
+ if repo_url:
245
+ initialize_repository(repo_url)
246
+ args.init = False # Already initialized
247
+ else:
248
+ sys.exit(1)
249
+
250
+ if args.init:
251
+ initialize_repository()
252
+
253
+ # Stage all changes
254
+ os.system("git add .")
255
+
256
+ if args.commit:
257
+ print(f"📦 Committing: '{args.commit}'")
258
+ commit_result = os.system(f'git commit -m "{args.commit}"')
259
+ if commit_result != 0:
260
+ print("❌ Commit failed")
261
+ sys.exit(1)
262
+ else:
263
+ print("⚠️ Skipping commit (no message provided)")
264
+
265
+ # Build push command
266
+ push_cmd = "git push"
267
+ if args.force:
268
+ push_cmd += " --force-with-lease"
269
+ if args.tags:
270
+ push_cmd += " --tags"
271
+ if args.remote and args.branch:
272
+ push_cmd += f" {args.remote} {args.branch}"
273
+
274
+ print(f"🚀 Executing: {push_cmd}")
275
+ push_result = os.system(push_cmd)
276
+
277
+ if push_result == 0:
278
+ print("✅ Successfully pushed changes")
279
+ else:
280
+ print("❌ Push failed")
281
+ sys.exit(1)
282
+
283
+ if __name__ == "__main__":
284
+ check_for_updates()
285
+ run()
@@ -1,10 +1,10 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: gitpush-tool
3
- Version: 0.1.3
3
+ Version: 0.2.0
4
4
  Summary: A CLI tool to simplify Git push operations with intelligent defaults and options.
5
- Home-page: https://github.com/yourusername/gitpush_tool
5
+ Home-page: https://github.com/inevitablegs/gitpush
6
6
  Author: Ganesh Sonawane
7
- Author-email: sonawaneganu3101@example.com
7
+ Author-email: sonawaneganu3101@gmail.com
8
8
  License: MIT
9
9
  Classifier: Programming Language :: Python :: 3
10
10
  Classifier: License :: OSI Approved :: MIT License
@@ -12,6 +12,7 @@ Classifier: Operating System :: OS Independent
12
12
  Requires-Python: >=3.6
13
13
  Description-Content-Type: text/markdown
14
14
  License-File: LICENSE
15
+ Requires-Dist: requests>=2.25.0
15
16
  Dynamic: author
16
17
  Dynamic: author-email
17
18
  Dynamic: classifier
@@ -20,6 +21,7 @@ Dynamic: description-content-type
20
21
  Dynamic: home-page
21
22
  Dynamic: license
22
23
  Dynamic: license-file
24
+ Dynamic: requires-dist
23
25
  Dynamic: requires-python
24
26
  Dynamic: summary
25
27
 
@@ -9,4 +9,5 @@ gitpush_tool.egg-info/PKG-INFO
9
9
  gitpush_tool.egg-info/SOURCES.txt
10
10
  gitpush_tool.egg-info/dependency_links.txt
11
11
  gitpush_tool.egg-info/entry_points.txt
12
+ gitpush_tool.egg-info/requires.txt
12
13
  gitpush_tool.egg-info/top_level.txt
@@ -0,0 +1 @@
1
+ requests>=2.25.0
@@ -3,20 +3,22 @@ from pathlib import Path
3
3
 
4
4
  setup(
5
5
  name="gitpush-tool",
6
- version="0.1.3",
6
+ version="0.2.0",
7
7
  packages=find_packages(),
8
- install_requires=[],
8
+ install_requires=[
9
+ 'requests>=2.25.0',
10
+ ],
9
11
  entry_points={
10
12
  "console_scripts": [
11
13
  "gitpush_tool=gitpush_tool.cli:run"
12
14
  ],
13
15
  },
14
16
  author="Ganesh Sonawane",
15
- author_email="sonawaneganu3101@example.com",
17
+ author_email="sonawaneganu3101@gmail.com",
16
18
  description="A CLI tool to simplify Git push operations with intelligent defaults and options.",
17
19
  long_description=Path("README.md").read_text(encoding="utf-8"),
18
20
  long_description_content_type="text/markdown",
19
- url="https://github.com/yourusername/gitpush_tool",
21
+ url="https://github.com/inevitablegs/gitpush",
20
22
  license="MIT",
21
23
  classifiers=[
22
24
  "Programming Language :: Python :: 3",
@@ -1 +0,0 @@
1
- __version__ = "0.1.3"
@@ -1,140 +0,0 @@
1
- import os
2
- import argparse
3
- import sys
4
- import requests
5
- from getpass import getpass
6
-
7
- import os
8
- import argparse
9
- import sys
10
- import requests
11
- from getpass import getpass
12
- import json
13
-
14
- def create_github_repo(repo_name, private=False, description=""):
15
- """Create a new GitHub repository using the GitHub API"""
16
- # Get GitHub token from environment or prompt
17
- token = os.getenv("GITHUB_TOKEN")
18
- if not token:
19
- token_path = os.path.join(os.path.dirname(__file__), '..', 'token')
20
- if os.path.exists(token_path):
21
- with open(token_path, 'r') as f:
22
- token = f.read().strip()
23
- else:
24
- token = getpass("Enter your GitHub personal access token (requires repo scope): ")
25
-
26
- if not token:
27
- print("❌ GitHub token is required to create a repository")
28
- return None
29
-
30
- headers = {
31
- "Authorization": f"token {token}",
32
- "Accept": "application/vnd.github.v3+json"
33
- }
34
-
35
- data = {
36
- "name": repo_name,
37
- "description": description,
38
- "private": private,
39
- "auto_init": False
40
- }
41
-
42
- try:
43
- response = requests.post(
44
- "https://api.github.com/user/repos",
45
- headers=headers,
46
- json=data
47
- )
48
-
49
- # More detailed error handling
50
- if response.status_code == 401:
51
- print("❌ Authentication failed. Please check your GitHub token:")
52
- print("- Make sure the token has the 'repo' scope")
53
- print("- Ensure the token hasn't expired")
54
- return None
55
- elif response.status_code == 422:
56
- error_data = response.json()
57
- if 'errors' in error_data:
58
- for error in error_data['errors']:
59
- if error.get('field') == 'name' and 'already exists' in error.get('message', ''):
60
- print(f"❌ Repository '{repo_name}' already exists on your account")
61
- return None
62
- print(f"❌ Validation error: {error_data.get('message', 'Unknown error')}")
63
- return None
64
- elif response.status_code != 201:
65
- print(f"❌ Failed to create repository (HTTP {response.status_code}): {response.text}")
66
- return None
67
-
68
- repo_url = response.json()["html_url"]
69
- print(f"✅ Successfully created repository: {repo_url}")
70
- return repo_url
71
-
72
- except requests.exceptions.RequestException as e:
73
- print(f"❌ Failed to create repository: {str(e)}")
74
- if "Max retries exceeded" in str(e):
75
- print("⚠️ Network connection problem detected")
76
- return None
77
-
78
- def run():
79
- parser = argparse.ArgumentParser(
80
- description="📦 Simple CLI to automate git operations and GitHub repository creation."
81
- )
82
- parser.add_argument("commit", nargs="?", help="Commit message. If omitted, no commit will be made.")
83
- parser.add_argument("branch", nargs="?", default="main", help="Branch to push to (default: main).")
84
- parser.add_argument("remote", nargs="?", default="origin", help="Remote name (default: origin).")
85
- parser.add_argument("--force", action="store_true", help="Force push (use with caution).")
86
- parser.add_argument("--tags", action="store_true", help="Push all local tags.")
87
- parser.add_argument("--init", action="store_true", help="Run 'git init' before pushing.")
88
- parser.add_argument("--new-repo", metavar="REPO_NAME", help="Create a new GitHub repository with this name.")
89
- parser.add_argument("--private", action="store_true", help="Make the new repository private.")
90
- parser.add_argument("--description", help="Description for the new repository.")
91
-
92
- args = parser.parse_args()
93
-
94
- # Create new GitHub repository if requested
95
- if args.new_repo:
96
- print(f"🆕 Creating new GitHub repository: {args.new_repo}")
97
- repo_url = create_github_repo(
98
- args.new_repo,
99
- private=args.private,
100
- description=args.description or ""
101
- )
102
- if not repo_url:
103
- sys.exit(1)
104
-
105
- print(f"✅ Repository created: {repo_url}")
106
-
107
- # Initialize git if not already a repo
108
- if not os.path.exists(".git"):
109
- args.init = True
110
-
111
- # Set up git remote
112
- os.system(f"git remote add {args.remote} {repo_url}")
113
-
114
- if args.init:
115
- print("🛠 Initializing git repository...")
116
- os.system("git init")
117
-
118
- os.system("git add .")
119
-
120
- if args.commit:
121
- print(f"📦 Committing with message: '{args.commit}'")
122
- os.system(f'git commit -m "{args.commit}"')
123
- else:
124
- print("⚠️ No commit message provided. Skipping commit step.")
125
-
126
- push_cmd = "git push"
127
-
128
- if args.force:
129
- push_cmd += " --force-with-lease"
130
-
131
- if args.tags:
132
- push_cmd += " --tags"
133
-
134
- if args.remote and args.branch:
135
- push_cmd += f" {args.remote} {args.branch}"
136
- elif args.branch:
137
- push_cmd += f" origin {args.branch}"
138
-
139
- print(f"🚀 Running: {push_cmd}")
140
- os.system(push_cmd)
File without changes
File without changes
File without changes
File without changes