giterm 2.0.3 → 2.0.4

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.
Files changed (3) hide show
  1. checksums.yaml +4 -4
  2. data/giterm +86 -26
  3. metadata +4 -4
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2a819be71e11539fa2d3745023e362f954b1dca51aaea25ad4af4c1636ef7d50
4
- data.tar.gz: f5a4aa8801cf06cddf6f3b75ef19b0fac8b755537fe5402772353e3e98174b7f
3
+ metadata.gz: a01a43a0c33b199d4c4295839aeaa21accde4c8e9dee216c635ecc7835176e53
4
+ data.tar.gz: 1f0ac3d3d407e7e25e1e13513b67fff172b84d82d3ca15a70067941c4b685128
5
5
  SHA512:
6
- metadata.gz: 18f086fa4d30035af2c9c2264488ca02dcb247b159f67c84acf8978ac6f8268276d590dfa447b1521c90b7e6d0380b0df6a03faff3778306b99be73a7258159a
7
- data.tar.gz: e79072c30b13faee5e19096c93aba231163f52259cf055ac027422aaf240983204a95529d77a10031d4bc54075e45709957da4644b1e3ac9b71631018d888407
6
+ metadata.gz: 5c421275ade0738dbe055be7e0b2581471610111d125dfee77e99fb8a6a711e8416f5cf2d225a7fda1b745ebf2c41dc0c23159d37f861d2fcd09f29f20e0f1da
7
+ data.tar.gz: 003f4737089d19deecbac244b25201ca5fcacb97642c64abdb0f100c9b97c3abbe6519dd201f4e15e9940e0448d02f075419085f6499a1d81661ed2054c1b128
data/giterm CHANGED
@@ -7,7 +7,7 @@
7
7
  # Author: Geir Isene <g@isene.com> (adapted from RTFM)
8
8
  # Github: https://github.com/isene/GiTerm
9
9
  # License: Public domain
10
- @version = '2.0.3'
10
+ @version = '2.0.4'
11
11
 
12
12
  # SAVE & STORE TERMINAL {{{1
13
13
  ORIG_STTY = `stty -g 2>/dev/null`.chomp rescue ''
@@ -911,7 +911,26 @@ def github_request_http(endpoint)
911
911
 
912
912
  JSON.parse(body)
913
913
  else
914
- { error: "GitHub API error: #{response.code} - #{response.message}" }
914
+ error_msg = case response.code
915
+ when '401'
916
+ 'Authentication failed (token expired or invalid). Press T to update token.'
917
+ when '403'
918
+ remaining = response['X-RateLimit-Remaining']
919
+ if remaining == '0'
920
+ reset_time = response['X-RateLimit-Reset']
921
+ reset_in = reset_time ? ((reset_time.to_i - Time.now.to_i) / 60.0).ceil : '?'
922
+ "GitHub API rate limit exceeded. Resets in ~#{reset_in} minutes."
923
+ else
924
+ "Access forbidden (403). Check token permissions."
925
+ end
926
+ when '404'
927
+ 'Resource not found (404). Repository may be private or deleted.'
928
+ when '429'
929
+ 'Too many requests (429). Please wait a moment and retry.'
930
+ else
931
+ "GitHub API error: #{response.code} - #{response.message}"
932
+ end
933
+ { error: error_msg }
915
934
  end
916
935
  end
917
936
  rescue JSON::ParserError => e
@@ -931,33 +950,62 @@ end
931
950
 
932
951
  def github_request_curl(endpoint)
933
952
  begin
934
- # Build curl command as a string to ensure proper formatting
953
+ # Build curl command with separate connect and total timeouts
935
954
  url = "https://api.github.com#{endpoint}"
936
- curl_cmd = "curl -s -f --max-time 10 " \
955
+ curl_cmd = "curl -s --connect-timeout 10 --max-time 20 " \
956
+ "-w '\\n%{http_code}' " \
937
957
  "-H 'Authorization: token #{@github_token}' " \
938
958
  "-H 'Accept: application/vnd.github.v3+json' " \
939
959
  "-H 'User-Agent: GiTerm/1.0' " \
940
960
  "'#{url}'"
941
-
961
+
942
962
  # Debug: log the curl command (without showing full token)
943
963
  debug_cmd = curl_cmd.sub(@github_token, "#{@github_token[0..10]}...")
944
964
  log_debug("Executing curl: #{debug_cmd}")
945
-
965
+
946
966
  # Capture both stdout and stderr for better debugging
947
- result = `#{curl_cmd} 2>&1`
967
+ raw_result = `#{curl_cmd} 2>&1`
948
968
  exit_code = $?.exitstatus
949
-
950
- if exit_code == 0 && !result.empty?
951
- JSON.parse(result)
969
+
970
+ if exit_code == 0
971
+ # Extract HTTP status code from the last line (-w appends it)
972
+ lines = raw_result.rstrip.split("\n")
973
+ http_code = lines.last.strip
974
+ body = lines[0...-1].join("\n")
975
+
976
+ if http_code == '200' && !body.empty?
977
+ JSON.parse(body)
978
+ elsif body.empty?
979
+ { error: 'Empty response body from GitHub API.' }
980
+ else
981
+ error_msg = case http_code
982
+ when '401'
983
+ 'Authentication failed (token expired or invalid). Press T to update token.'
984
+ when '403'
985
+ parsed = JSON.parse(body) rescue {}
986
+ if parsed['message']&.include?('rate limit')
987
+ 'GitHub API rate limit exceeded. Wait a few minutes and retry.'
988
+ else
989
+ "Access forbidden (403). Check token permissions."
990
+ end
991
+ when '404'
992
+ 'Resource not found (404). Repository may be private or deleted.'
993
+ when '429'
994
+ 'Too many requests (429). Please wait a moment and retry.'
995
+ else
996
+ "GitHub API error (HTTP #{http_code})."
997
+ end
998
+ { error: error_msg }
999
+ end
952
1000
  else
953
1001
  error_msg = case exit_code
954
- when 22 then 'HTTP error (likely 401/403 - check token)'
955
- when 6 then 'Could not resolve host (network issue)'
956
- when 7 then 'Failed to connect (network issue)'
957
- when 28 then 'Operation timeout'
958
- else "curl failed (exit code: #{exit_code})"
1002
+ when 6 then 'Could not resolve host. Check network connection.'
1003
+ when 7 then 'Failed to connect to GitHub. Check network connection.'
1004
+ when 28 then 'Request timed out. GitHub may be slow or unreachable.'
1005
+ when 35 then 'SSL/TLS connection error.'
1006
+ else "Network error (curl exit code: #{exit_code})."
959
1007
  end
960
- { error: "#{error_msg}. Response: #{result[0..100]}" }
1008
+ { error: error_msg }
961
1009
  end
962
1010
  rescue JSON::ParserError => e
963
1011
  { error: "Invalid JSON from curl: #{e.message}" }
@@ -1348,15 +1396,21 @@ def github_issues
1348
1396
  return if @selected_repo.empty?
1349
1397
 
1350
1398
  result = github_request("/repos/#{@selected_repo}/issues?state=open&per_page=50")
1351
-
1352
- if result[:error]
1399
+
1400
+ if result.is_a?(Hash) && result[:error]
1353
1401
  @p_left.say(result[:error].fg(196))
1402
+ @p_bottom.say('Failed to load issues.')
1354
1403
  return
1355
1404
  end
1356
-
1405
+
1406
+ unless result.is_a?(Array)
1407
+ @p_left.say('Unexpected response format from GitHub API.'.fg(196))
1408
+ return
1409
+ end
1410
+
1357
1411
  result.each do |issue|
1358
1412
  next if issue['pull_request'] # Skip PRs
1359
-
1413
+
1360
1414
  @github_issues << {
1361
1415
  number: issue['number'],
1362
1416
  title: issue['title'],
@@ -1435,12 +1489,18 @@ def github_pull_requests
1435
1489
  return if @selected_repo.empty?
1436
1490
 
1437
1491
  result = github_request("/repos/#{@selected_repo}/pulls?state=open&per_page=50")
1438
-
1439
- if result[:error]
1492
+
1493
+ if result.is_a?(Hash) && result[:error]
1440
1494
  @p_left.say(result[:error].fg(196))
1495
+ @p_bottom.say('Failed to load pull requests.')
1441
1496
  return
1442
1497
  end
1443
-
1498
+
1499
+ unless result.is_a?(Array)
1500
+ @p_left.say('Unexpected response format from GitHub API.'.fg(196))
1501
+ return
1502
+ end
1503
+
1444
1504
  result.each do |pr|
1445
1505
  @github_prs << {
1446
1506
  number: pr['number'],
@@ -1557,14 +1617,14 @@ def github_search_repositories
1557
1617
  # Perform the search
1558
1618
  result = github_request("/search/repositories?q=#{CGI.escape(query)}&sort=stars&order=desc&per_page=50")
1559
1619
 
1560
- if result[:error]
1620
+ if result.is_a?(Hash) && result[:error]
1561
1621
  @p_left.clear
1562
1622
  @p_left.say("Search Error: #{result[:error]}".fg(196))
1563
1623
  return
1564
1624
  end
1565
-
1625
+
1566
1626
  # Process search results
1567
- if result['items'] && result['items'].any?
1627
+ if result.is_a?(Hash) && result['items'] && result['items'].any?
1568
1628
  result['items'].each do |repo|
1569
1629
  @github_search_results << {
1570
1630
  id: repo['id'],
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: giterm
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.0.3
4
+ version: 2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Geir Isene
8
8
  autorequire:
9
9
  bindir: "."
10
10
  cert_chain: []
11
- date: 2025-10-27 00:00:00.000000000 Z
11
+ date: 2026-03-21 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rcurses
@@ -54,8 +54,8 @@ dependencies:
54
54
  version: '13.0'
55
55
  description: 'GiTerm is a powerful terminal interface for Git and GitHub, providing
56
56
  an intuitive TUI for repository management, issue tracking, and pull request handling.
57
- Version 2.0.3: Improved README display with markdown filtering and urxvt-compatible
58
- symbols.'
57
+ Version 2.0.4: Improved GitHub API error recovery with specific messages for auth,
58
+ rate-limit, and network failures.'
59
59
  email:
60
60
  - g@isene.com
61
61
  executables: