Skip to content

Commit ac109ff

Browse files
committed
Handle KeyboardInterrupt gracefully in main function
1 parent 1c77177 commit ac109ff

1 file changed

Lines changed: 136 additions & 129 deletions

File tree

src/gitfetch/cli.py

Lines changed: 136 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -136,141 +136,148 @@ def parse_args() -> argparse.Namespace:
136136

137137

138138
def main() -> int:
139-
args = parse_args()
139+
try:
140+
args = parse_args()
140141

141-
if args.version:
142-
print(f"gitfetch version: {__version__}")
143-
# Check for updates from GitHub
144-
import requests
145-
try:
146-
resp = requests.get(
147-
"https://api.github.com/repos/Matars/gitfetch/releases/latest", timeout=3)
148-
if resp.status_code == 200:
149-
latest = resp.json()["tag_name"].lstrip("v")
150-
if latest != __version__:
151-
print(
152-
f"\033[93mUpdate available: {latest}\n"
153-
"Get it at: https://github.com/Matars/gitfetch/releases/latest\n"
154-
"Or run: brew update && brew upgrade gitfetch\033[0m")
155-
else:
156-
print("You are using the latest version.")
157-
else:
158-
print("Could not check for updates.")
159-
except Exception:
160-
print("Could not check for updates.")
161-
return 0
162-
163-
# Initialize config
164-
config_manager = ConfigManager()
165-
166-
# Check if gitfetch is initialized
167-
if not config_manager.is_initialized():
168-
print("🚀 Welcome to gitfetch! Let's set up your configuration.\n")
169-
if not _initialize_gitfetch(config_manager):
170-
print("Error: Initialization failed", file=sys.stderr)
171-
return 1
172-
print("\n✅ Configuration saved! You can now use gitfetch.\n")
173-
174-
# Initialize components
175-
cache_expiry = config_manager.get_cache_expiry_hours()
176-
cache_manager = CacheManager(cache_expiry_hours=cache_expiry)
177-
provider = config_manager.get_provider()
178-
provider_url = config_manager.get_provider_url()
179-
fetcher = _create_fetcher(provider, provider_url)
180-
181-
# Handle custom box character
182-
custom_box = args.custom_box
183-
184-
# Handle show date setting
185-
show_date = not args.no_date
186-
187-
formatter = DisplayFormatter(config_manager, custom_box, show_date,
188-
args.graph_only, not args.no_achievements,
189-
not args.no_languages, not args.no_issues,
190-
not args.no_pr, not args.no_account,
191-
not args.no_grid, args.width, args.height)
192-
if args.spaced:
193-
spaced = True
194-
elif args.not_spaced:
195-
spaced = False
196-
else:
197-
spaced = True
198-
199-
# Handle cache clearing
200-
if args.clear_cache:
201-
cache_manager.clear()
202-
print("Cache cleared successfully!")
203-
return 0
204-
205-
# Get username
206-
username = args.username
207-
if not username:
208-
# Try to get default username from config
209-
username = config_manager.get_default_username()
210-
if not username:
211-
# Fall back to authenticated user
142+
if args.version:
143+
print(f"gitfetch version: {__version__}")
144+
# Check for updates from GitHub
145+
import requests
212146
try:
213-
username = fetcher.get_authenticated_user()
214-
# Save as default for future use
215-
config_manager.set_default_username(username)
216-
config_manager.save()
147+
resp = requests.get(
148+
"https://api.github.com/repos/Matars/gitfetch/releases/latest", timeout=3)
149+
if resp.status_code == 200:
150+
latest = resp.json()["tag_name"].lstrip("v")
151+
if latest != __version__:
152+
print(
153+
f"\033[93mUpdate available: {latest}\n"
154+
"Get it at: https://github.com/Matars/gitfetch/releases/latest\n"
155+
"Or run: brew update && brew upgrade gitfetch\033[0m")
156+
else:
157+
print("You are using the latest version.")
158+
else:
159+
print("Could not check for updates.")
217160
except Exception:
218-
username = _prompt_username()
219-
if not username:
220-
print("Error: Username is required", file=sys.stderr)
221-
return 1
222-
223-
# Fetch data (with or without cache)
224-
try:
225-
if args.no_cache:
226-
user_data = fetcher.fetch_user_data(username)
227-
stats = fetcher.fetch_user_stats(username, user_data)
228-
cache_manager.cache_user_data(username, user_data, stats)
161+
print("Could not check for updates.")
162+
return 0
163+
164+
# Initialize config
165+
config_manager = ConfigManager()
166+
167+
# Check if gitfetch is initialized
168+
if not config_manager.is_initialized():
169+
print("🚀 Welcome to gitfetch! Let's set up your configuration.\n")
170+
if not _initialize_gitfetch(config_manager):
171+
print("Error: Initialization failed", file=sys.stderr)
172+
return 1
173+
print("\n✅ Configuration saved! You can now use gitfetch.\n")
174+
175+
# Initialize components
176+
cache_expiry = config_manager.get_cache_expiry_hours()
177+
cache_manager = CacheManager(cache_expiry_hours=cache_expiry)
178+
provider = config_manager.get_provider()
179+
provider_url = config_manager.get_provider_url()
180+
fetcher = _create_fetcher(provider, provider_url)
181+
182+
# Handle custom box character
183+
custom_box = args.custom_box
184+
185+
# Handle show date setting
186+
show_date = not args.no_date
187+
188+
formatter = DisplayFormatter(config_manager, custom_box, show_date,
189+
args.graph_only, not args.no_achievements,
190+
not args.no_languages, not args.no_issues,
191+
not args.no_pr, not args.no_account,
192+
not args.no_grid, args.width, args.height)
193+
if args.spaced:
194+
spaced = True
195+
elif args.not_spaced:
196+
spaced = False
229197
else:
230-
user_data = cache_manager.get_cached_user_data(username)
231-
stats = cache_manager.get_cached_stats(username)
232-
if user_data is None or stats is None:
233-
# Try to get stale cache for immediate display
234-
stale_user_data = cache_manager.get_stale_cached_user_data(
235-
username)
236-
stale_stats = cache_manager.get_stale_cached_stats(username)
237-
if stale_user_data is not None and stale_stats is not None:
238-
# Display stale cache immediately
239-
formatter.display(username, stale_user_data,
240-
stale_stats, spaced=spaced)
241-
print("\n🔄 Refreshing data in background...",
242-
file=sys.stderr)
243-
244-
# Refresh cache in background (don't wait for it)
245-
import threading
246-
247-
def refresh_cache():
248-
try:
249-
fresh_user_data = fetcher.fetch_user_data(username)
250-
fresh_stats = fetcher.fetch_user_stats(
251-
username, fresh_user_data)
252-
cache_manager.cache_user_data(
253-
username, fresh_user_data, fresh_stats)
254-
except Exception:
255-
pass
256-
thread = threading.Thread(
257-
target=refresh_cache, daemon=True)
258-
thread.start()
259-
return 0
260-
else:
261-
# No cache at all, fetch fresh data
262-
user_data = fetcher.fetch_user_data(username)
263-
stats = fetcher.fetch_user_stats(username, user_data)
264-
cache_manager.cache_user_data(username, user_data, stats)
265-
# else: fresh cache available, proceed to display
198+
spaced = True
266199

267-
# Display the results
268-
formatter.display(username, user_data, stats, spaced=spaced)
200+
# Handle cache clearing
201+
if args.clear_cache:
202+
cache_manager.clear()
203+
print("Cache cleared successfully!")
204+
return 0
269205

270-
return 0
271-
except Exception as e:
272-
print(f"Error: {e}", file=sys.stderr)
273-
return 1
206+
# Get username
207+
username = args.username
208+
if not username:
209+
# Try to get default username from config
210+
username = config_manager.get_default_username()
211+
if not username:
212+
# Fall back to authenticated user
213+
try:
214+
username = fetcher.get_authenticated_user()
215+
# Save as default for future use
216+
config_manager.set_default_username(username)
217+
config_manager.save()
218+
except Exception:
219+
username = _prompt_username()
220+
if not username:
221+
print("Error: Username is required", file=sys.stderr)
222+
return 1
223+
224+
# Fetch data (with or without cache)
225+
try:
226+
if args.no_cache:
227+
user_data = fetcher.fetch_user_data(username)
228+
stats = fetcher.fetch_user_stats(username, user_data)
229+
cache_manager.cache_user_data(username, user_data, stats)
230+
else:
231+
user_data = cache_manager.get_cached_user_data(username)
232+
stats = cache_manager.get_cached_stats(username)
233+
if user_data is None or stats is None:
234+
# Try to get stale cache for immediate display
235+
stale_user_data = cache_manager.get_stale_cached_user_data(
236+
username)
237+
stale_stats = cache_manager.get_stale_cached_stats(
238+
username)
239+
if stale_user_data is not None and stale_stats is not None:
240+
# Display stale cache immediately
241+
formatter.display(username, stale_user_data,
242+
stale_stats, spaced=spaced)
243+
print("\n🔄 Refreshing data in background...",
244+
file=sys.stderr)
245+
246+
# Refresh cache in background (don't wait for it)
247+
import threading
248+
249+
def refresh_cache():
250+
try:
251+
fresh_user_data = fetcher.fetch_user_data(
252+
username)
253+
fresh_stats = fetcher.fetch_user_stats(
254+
username, fresh_user_data)
255+
cache_manager.cache_user_data(
256+
username, fresh_user_data, fresh_stats)
257+
except Exception:
258+
pass
259+
thread = threading.Thread(
260+
target=refresh_cache, daemon=True)
261+
thread.start()
262+
return 0
263+
else:
264+
# No cache at all, fetch fresh data
265+
user_data = fetcher.fetch_user_data(username)
266+
stats = fetcher.fetch_user_stats(username, user_data)
267+
cache_manager.cache_user_data(
268+
username, user_data, stats)
269+
# else: fresh cache available, proceed to display
270+
271+
# Display the results
272+
formatter.display(username, user_data, stats, spaced=spaced)
273+
274+
return 0
275+
except Exception as e:
276+
print(f"Error: {e}", file=sys.stderr)
277+
return 1
278+
except KeyboardInterrupt:
279+
print("\nInterrupted by user.", file=sys.stderr)
280+
return 130
274281

275282

276283
def _prompt_username() -> Optional[str]:

0 commit comments

Comments
 (0)