Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

magithub--api-available-p seems to make request as "ghub" #363

Closed
glasserc opened this issue Aug 22, 2018 · 1 comment
Closed

magithub--api-available-p seems to make request as "ghub" #363

glasserc opened this issue Aug 22, 2018 · 1 comment

Comments

@glasserc
Copy link

Steps to reproduce:

  • Start a new emacs session
  • Navigate to a git repo with magithub.online = false
  • magit-status
  • C-u g to refresh

Expected result:

Should use my existing token to refresh this data.

Actual result:

Pops up the dialog asking if I want to create a new token:

Such a Github API token is not available:

  Host:    api.github.com
  User:    glasserc
  Package: ghub

  Scopes requested in `ghub-github-token-scopes':
    repo
  Store on Github as:
    "Emacs package ghub @ golden-cloud"
  Store locally according to option `auth-sources':
    ("~/.authinfo" "~/.authinfo.gpg" "~/.netrc" "secrets:Login")

WARNING: The token will be stored unencrypted in "~/.authinfo".
         If you don't want that, you have to abort and customize
         the `auth-sources' option.

;; ...

Of course, to add insult to injury, after about a second, this whole message disappears (Magithub is now offline: API is not responding quickly; consider customizing magithub-api-timeout' if this happens often`).

I was able to get a backtrace by setting debug-on-quit.

Debugger entered--Lisp error: (quit)
  yes-or-no-p("Such a Github API token is not available:\n\n  Host:    api.github.com\n  User:    glasserc\n  Package: ghub\n\n  Scopes requested in `ghub-github-token-scopes':\n    repo\n  Store on Github as:\n    \"Emacs package ghub @ golden-cloud\"\n  Store locally according to option `auth-sources':\n    (\"~/.authinfo\" \"~/.authinfo.gpg\" \"~/.netrc\" \"secrets:Login\")\n\nWARNING: The token will be stored unencrypted in \"~/.authinfo\".\n         If you don't want that, you have to abort and customize\n         the `auth-sources' option.\n\nIf in doubt, then abort and first view the section of the Ghub\ndocumentation called \"Manually Creating and Storing a Token\".\n\nOtherwise confirm and then provide your Github username and\npassword at the next two prompts.  Depending on the backend\nyou might have to provide a passphrase and confirm that you\nreally want to save the token.\n\nCreate and store such a token? ")
  ghub--confirm-create-token("api.github.com" "glasserc" ghub)
  ghub--token("api.github.com" "glasserc" ghub nil nil)
  ghub--auth("api.github.com" nil "glasserc" nil)
  #f(compiled-function () #<bytecode 0x1cdaf49>)()
  ghub--retrieve(nil #s(ghub--req :url #s(url :type "https" :user nil :password nil :host "api.github.com" :portspec nil :filename "/rate_limit" :target nil :attributes nil :fullness t :silent nil :use-cookies t :asynchronous t) :silent nil :method "GET" :headers #f(compiled-function () #<bytecode 0x1cdaf49>) :handler ghub--handle-response :unpaginate nil :noerror nil :reader nil :callback nil :errorback nil :value nil :extra nil))
  #f(compiled-function (arg1 arg2 &rest rest) "Make a request for RESOURCE and return the response body.\n\nAlso place the response header in `ghub-response-headers'.\n\nMETHOD is the HTTP method, given as a string.\nRESOURCE is the resource to access, given as a string beginning\n  with a slash.\n\nPARAMS, QUERY, PAYLOAD and HEADERS are alists used to specify\n  data.  The Github API documentation is vague on how data has\n  to be transmitted and for a particular resource usually just\n  talks about \"parameters\".  Generally speaking when the METHOD\n  is \"HEAD\" or \"GET\", then they have to be transmitted as a\n  query, otherwise as a payload.\nUse PARAMS to automatically transmit like QUERY or PAYLOAD would\n  depending on METHOD.\nUse QUERY to explicitly transmit data as a query.\nUse PAYLOAD to explicitly transmit data as a payload.\n  Instead of an alist, PAYLOAD may also be a string, in which\n  case it gets encoded as UTF-8 but is otherwise transmitted as-is.\nUse HEADERS for those rare resources that require that the data\n  is transmitted as headers instead of as a query or payload.\n  When that is the case, then the API documentation usually\n  mentions it explicitly.\n\nIf SILENT is non-nil, then don't message progress reports and\n  the like.\n\nIf UNPAGINATE is t, then make as many requests as necessary to\n  get all values.  If UNPAGINATE is a natural number, then get\n  at most that many pages.  For any other non-nil value raise\n  an error.\nIf NOERROR is non-nil, then do not raise an error if the request\n  fails and return nil instead.  If NOERROR is `return', then\n  return the error payload instead of nil.\nIf READER is non-nil, then it is used to read and return from the\n  response buffer.  The default is `ghub--read-json-payload'.\n  For the very few resources that do not return JSON, you might\n  want to use `ghub--decode-payload'.\n\nIf USERNAME is non-nil, then make a request on behalf of that\n  user.  It is better to specify the user using the Git variable\n  `github.user' for \"api.github.com\", or `github.HOST.user' if\n  connecting to a Github Enterprise instance.\n\nEach package that uses `ghub' should use its own token. If AUTH\n  is nil, then the generic `ghub' token is used instead.  This\n  is only acceptable for personal utilities.  A packages that\n  is distributed to other users should always use this argument\n  to identify itself, using a symbol matching its name.\n\n  Package authors who find this inconvenient should write a\n  wrapper around this function and possibly for the\n  method-specific functions as well.\n\n  Some symbols have a special meaning.  `none' means to make an\n  unauthorized request.  `basic' means to make a password based\n  request.  If the value is a string, then it is assumed to be\n  a valid token.  `basic' and an explicit token string are only\n  intended for internal and debugging uses.\n\n  If AUTH is a package symbol, then the scopes are specified\n  using the variable `AUTH-github-token-scopes'.  It is an error\n  if that is not specified.  See `ghub-github-token-scopes' for\n  an example.\n\nIf HOST is non-nil, then connect to that Github instance.  This\n  defaults to \"api.github.com\".  When a repository is connected\n  to a Github Enterprise instance, then it is better to specify\n  that using the Git variable `github.host' instead of using this\n  argument.\n\nIf FORGE is `gitlab', then connect to Gitlab.com or, depending\n  on HOST, to another Gitlab instance.  This is only intended for\n  internal use.  Instead of using this argument you should use\n  function `glab-request' and other `glab-*' functions.\n\nIf CALLBACK and/or ERRORBACK is non-nil, then make one or more\n  asynchronous requests and call CALLBACK or ERRORBACK when\n  finished.  If an error occurred, then call ERRORBACK, or if\n  that is nil, then CALLBACK.  When no error occurred then call\n  CALLBACK.  When making asynchronous requests, then no errors\n  are signaled, regardless of the value of NOERROR.\n\nBoth callbacks are called with four arguments.\n  1. For CALLBACK, the combined value of the retrieved pages.\n     For ERRORBACK, the error that occured when retrieving the\n     last page.\n  2. The headers of the last page as an alist.\n  3. Status information provided by `url-retrieve'. Its `:error'\n     property holds the same information as ERRORBACK's first\n     argument.\n  4. A `ghub--req' struct, which can be passed to `ghub-continue'\n     (which see) to retrieve the next page, if any." #<bytecode 0x17c31dd>)("GET" "/rate_limit" nil :query nil :payload nil :unpaginate nil :headers nil :username nil :auth nil :host nil)
  apply(#f(compiled-function (arg1 arg2 &rest rest) "Make a request for RESOURCE and return the response body.\n\nAlso place the response header in `ghub-response-headers'.\n\nMETHOD is the HTTP method, given as a string.\nRESOURCE is the resource to access, given as a string beginning\n  with a slash.\n\nPARAMS, QUERY, PAYLOAD and HEADERS are alists used to specify\n  data.  The Github API documentation is vague on how data has\n  to be transmitted and for a particular resource usually just\n  talks about \"parameters\".  Generally speaking when the METHOD\n  is \"HEAD\" or \"GET\", then they have to be transmitted as a\n  query, otherwise as a payload.\nUse PARAMS to automatically transmit like QUERY or PAYLOAD would\n  depending on METHOD.\nUse QUERY to explicitly transmit data as a query.\nUse PAYLOAD to explicitly transmit data as a payload.\n  Instead of an alist, PAYLOAD may also be a string, in which\n  case it gets encoded as UTF-8 but is otherwise transmitted as-is.\nUse HEADERS for those rare resources that require that the data\n  is transmitted as headers instead of as a query or payload.\n  When that is the case, then the API documentation usually\n  mentions it explicitly.\n\nIf SILENT is non-nil, then don't message progress reports and\n  the like.\n\nIf UNPAGINATE is t, then make as many requests as necessary to\n  get all values.  If UNPAGINATE is a natural number, then get\n  at most that many pages.  For any other non-nil value raise\n  an error.\nIf NOERROR is non-nil, then do not raise an error if the request\n  fails and return nil instead.  If NOERROR is `return', then\n  return the error payload instead of nil.\nIf READER is non-nil, then it is used to read and return from the\n  response buffer.  The default is `ghub--read-json-payload'.\n  For the very few resources that do not return JSON, you might\n  want to use `ghub--decode-payload'.\n\nIf USERNAME is non-nil, then make a request on behalf of that\n  user.  It is better to specify the user using the Git variable\n  `github.user' for \"api.github.com\", or `github.HOST.user' if\n  connecting to a Github Enterprise instance.\n\nEach package that uses `ghub' should use its own token. If AUTH\n  is nil, then the generic `ghub' token is used instead.  This\n  is only acceptable for personal utilities.  A packages that\n  is distributed to other users should always use this argument\n  to identify itself, using a symbol matching its name.\n\n  Package authors who find this inconvenient should write a\n  wrapper around this function and possibly for the\n  method-specific functions as well.\n\n  Some symbols have a special meaning.  `none' means to make an\n  unauthorized request.  `basic' means to make a password based\n  request.  If the value is a string, then it is assumed to be\n  a valid token.  `basic' and an explicit token string are only\n  intended for internal and debugging uses.\n\n  If AUTH is a package symbol, then the scopes are specified\n  using the variable `AUTH-github-token-scopes'.  It is an error\n  if that is not specified.  See `ghub-github-token-scopes' for\n  an example.\n\nIf HOST is non-nil, then connect to that Github instance.  This\n  defaults to \"api.github.com\".  When a repository is connected\n  to a Github Enterprise instance, then it is better to specify\n  that using the Git variable `github.host' instead of using this\n  argument.\n\nIf FORGE is `gitlab', then connect to Gitlab.com or, depending\n  on HOST, to another Gitlab instance.  This is only intended for\n  internal use.  Instead of using this argument you should use\n  function `glab-request' and other `glab-*' functions.\n\nIf CALLBACK and/or ERRORBACK is non-nil, then make one or more\n  asynchronous requests and call CALLBACK or ERRORBACK when\n  finished.  If an error occurred, then call ERRORBACK, or if\n  that is nil, then CALLBACK.  When no error occurred then call\n  CALLBACK.  When making asynchronous requests, then no errors\n  are signaled, regardless of the value of NOERROR.\n\nBoth callbacks are called with four arguments.\n  1. For CALLBACK, the combined value of the retrieved pages.\n     For ERRORBACK, the error that occured when retrieving the\n     last page.\n  2. The headers of the last page as an alist.\n  3. Status information provided by `url-retrieve'. Its `:error'\n     property holds the same information as ERRORBACK's first\n     argument.\n  4. A `ghub--req' struct, which can be passed to `ghub-continue'\n     (which see) to retrieve the next page, if any." #<bytecode 0x17c31dd>) ("GET" "/rate_limit" nil :query nil :payload nil :unpaginate nil :headers nil :username nil :auth nil :host nil))
  magithub-debug--ghub-request-wrapper(#f(compiled-function (arg1 arg2 &rest rest) "Make a request for RESOURCE and return the response body.\n\nAlso place the response header in `ghub-response-headers'.\n\nMETHOD is the HTTP method, given as a string.\nRESOURCE is the resource to access, given as a string beginning\n  with a slash.\n\nPARAMS, QUERY, PAYLOAD and HEADERS are alists used to specify\n  data.  The Github API documentation is vague on how data has\n  to be transmitted and for a particular resource usually just\n  talks about \"parameters\".  Generally speaking when the METHOD\n  is \"HEAD\" or \"GET\", then they have to be transmitted as a\n  query, otherwise as a payload.\nUse PARAMS to automatically transmit like QUERY or PAYLOAD would\n  depending on METHOD.\nUse QUERY to explicitly transmit data as a query.\nUse PAYLOAD to explicitly transmit data as a payload.\n  Instead of an alist, PAYLOAD may also be a string, in which\n  case it gets encoded as UTF-8 but is otherwise transmitted as-is.\nUse HEADERS for those rare resources that require that the data\n  is transmitted as headers instead of as a query or payload.\n  When that is the case, then the API documentation usually\n  mentions it explicitly.\n\nIf SILENT is non-nil, then don't message progress reports and\n  the like.\n\nIf UNPAGINATE is t, then make as many requests as necessary to\n  get all values.  If UNPAGINATE is a natural number, then get\n  at most that many pages.  For any other non-nil value raise\n  an error.\nIf NOERROR is non-nil, then do not raise an error if the request\n  fails and return nil instead.  If NOERROR is `return', then\n  return the error payload instead of nil.\nIf READER is non-nil, then it is used to read and return from the\n  response buffer.  The default is `ghub--read-json-payload'.\n  For the very few resources that do not return JSON, you might\n  want to use `ghub--decode-payload'.\n\nIf USERNAME is non-nil, then make a request on behalf of that\n  user.  It is better to specify the user using the Git variable\n  `github.user' for \"api.github.com\", or `github.HOST.user' if\n  connecting to a Github Enterprise instance.\n\nEach package that uses `ghub' should use its own token. If AUTH\n  is nil, then the generic `ghub' token is used instead.  This\n  is only acceptable for personal utilities.  A packages that\n  is distributed to other users should always use this argument\n  to identify itself, using a symbol matching its name.\n\n  Package authors who find this inconvenient should write a\n  wrapper around this function and possibly for the\n  method-specific functions as well.\n\n  Some symbols have a special meaning.  `none' means to make an\n  unauthorized request.  `basic' means to make a password based\n  request.  If the value is a string, then it is assumed to be\n  a valid token.  `basic' and an explicit token string are only\n  intended for internal and debugging uses.\n\n  If AUTH is a package symbol, then the scopes are specified\n  using the variable `AUTH-github-token-scopes'.  It is an error\n  if that is not specified.  See `ghub-github-token-scopes' for\n  an example.\n\nIf HOST is non-nil, then connect to that Github instance.  This\n  defaults to \"api.github.com\".  When a repository is connected\n  to a Github Enterprise instance, then it is better to specify\n  that using the Git variable `github.host' instead of using this\n  argument.\n\nIf FORGE is `gitlab', then connect to Gitlab.com or, depending\n  on HOST, to another Gitlab instance.  This is only intended for\n  internal use.  Instead of using this argument you should use\n  function `glab-request' and other `glab-*' functions.\n\nIf CALLBACK and/or ERRORBACK is non-nil, then make one or more\n  asynchronous requests and call CALLBACK or ERRORBACK when\n  finished.  If an error occurred, then call ERRORBACK, or if\n  that is nil, then CALLBACK.  When no error occurred then call\n  CALLBACK.  When making asynchronous requests, then no errors\n  are signaled, regardless of the value of NOERROR.\n\nBoth callbacks are called with four arguments.\n  1. For CALLBACK, the combined value of the retrieved pages.\n     For ERRORBACK, the error that occured when retrieving the\n     last page.\n  2. The headers of the last page as an alist.\n  3. Status information provided by `url-retrieve'. Its `:error'\n     property holds the same information as ERRORBACK's first\n     argument.\n  4. A `ghub--req' struct, which can be passed to `ghub-continue'\n     (which see) to retrieve the next page, if any." #<bytecode 0x17c31dd>) "GET" "/rate_limit" nil :query nil :payload nil :unpaginate nil :headers nil :username nil :auth nil :host nil)
  apply(magithub-debug--ghub-request-wrapper #f(compiled-function (arg1 arg2 &rest rest) "Make a request for RESOURCE and return the response body.\n\nAlso place the response header in `ghub-response-headers'.\n\nMETHOD is the HTTP method, given as a string.\nRESOURCE is the resource to access, given as a string beginning\n  with a slash.\n\nPARAMS, QUERY, PAYLOAD and HEADERS are alists used to specify\n  data.  The Github API documentation is vague on how data has\n  to be transmitted and for a particular resource usually just\n  talks about \"parameters\".  Generally speaking when the METHOD\n  is \"HEAD\" or \"GET\", then they have to be transmitted as a\n  query, otherwise as a payload.\nUse PARAMS to automatically transmit like QUERY or PAYLOAD would\n  depending on METHOD.\nUse QUERY to explicitly transmit data as a query.\nUse PAYLOAD to explicitly transmit data as a payload.\n  Instead of an alist, PAYLOAD may also be a string, in which\n  case it gets encoded as UTF-8 but is otherwise transmitted as-is.\nUse HEADERS for those rare resources that require that the data\n  is transmitted as headers instead of as a query or payload.\n  When that is the case, then the API documentation usually\n  mentions it explicitly.\n\nIf SILENT is non-nil, then don't message progress reports and\n  the like.\n\nIf UNPAGINATE is t, then make as many requests as necessary to\n  get all values.  If UNPAGINATE is a natural number, then get\n  at most that many pages.  For any other non-nil value raise\n  an error.\nIf NOERROR is non-nil, then do not raise an error if the request\n  fails and return nil instead.  If NOERROR is `return', then\n  return the error payload instead of nil.\nIf READER is non-nil, then it is used to read and return from the\n  response buffer.  The default is `ghub--read-json-payload'.\n  For the very few resources that do not return JSON, you might\n  want to use `ghub--decode-payload'.\n\nIf USERNAME is non-nil, then make a request on behalf of that\n  user.  It is better to specify the user using the Git variable\n  `github.user' for \"api.github.com\", or `github.HOST.user' if\n  connecting to a Github Enterprise instance.\n\nEach package that uses `ghub' should use its own token. If AUTH\n  is nil, then the generic `ghub' token is used instead.  This\n  is only acceptable for personal utilities.  A packages that\n  is distributed to other users should always use this argument\n  to identify itself, using a symbol matching its name.\n\n  Package authors who find this inconvenient should write a\n  wrapper around this function and possibly for the\n  method-specific functions as well.\n\n  Some symbols have a special meaning.  `none' means to make an\n  unauthorized request.  `basic' means to make a password based\n  request.  If the value is a string, then it is assumed to be\n  a valid token.  `basic' and an explicit token string are only\n  intended for internal and debugging uses.\n\n  If AUTH is a package symbol, then the scopes are specified\n  using the variable `AUTH-github-token-scopes'.  It is an error\n  if that is not specified.  See `ghub-github-token-scopes' for\n  an example.\n\nIf HOST is non-nil, then connect to that Github instance.  This\n  defaults to \"api.github.com\".  When a repository is connected\n  to a Github Enterprise instance, then it is better to specify\n  that using the Git variable `github.host' instead of using this\n  argument.\n\nIf FORGE is `gitlab', then connect to Gitlab.com or, depending\n  on HOST, to another Gitlab instance.  This is only intended for\n  internal use.  Instead of using this argument you should use\n  function `glab-request' and other `glab-*' functions.\n\nIf CALLBACK and/or ERRORBACK is non-nil, then make one or more\n  asynchronous requests and call CALLBACK or ERRORBACK when\n  finished.  If an error occurred, then call ERRORBACK, or if\n  that is nil, then CALLBACK.  When no error occurred then call\n  CALLBACK.  When making asynchronous requests, then no errors\n  are signaled, regardless of the value of NOERROR.\n\nBoth callbacks are called with four arguments.\n  1. For CALLBACK, the combined value of the retrieved pages.\n     For ERRORBACK, the error that occured when retrieving the\n     last page.\n  2. The headers of the last page as an alist.\n  3. Status information provided by `url-retrieve'. Its `:error'\n     property holds the same information as ERRORBACK's first\n     argument.\n  4. A `ghub--req' struct, which can be passed to `ghub-continue'\n     (which see) to retrieve the next page, if any." #<bytecode 0x17c31dd>) ("GET" "/rate_limit" nil :query nil :payload nil :unpaginate nil :headers nil :username nil :auth nil :host nil))
  ghub-request("GET" "/rate_limit" nil :query nil :payload nil :unpaginate nil :headers nil :username nil :auth nil :host nil)
  ghubp-request(get "/rate_limit" nil nil)
  ghubp-ratelimit()
  magithub--api-available-p()
  magithub--refresh()
  run-hooks(magit-pre-refresh-hook)
  magit-run-hook-with-benchmark(magit-pre-refresh-hook)
  magit-refresh()
  funcall-interactively(magit-refresh)
  #<subr call-interactively>(magit-refresh nil nil)
  apply(#<subr call-interactively> magit-refresh (nil nil))
  call-interactively@ido-cr+-record-current-command(#<subr call-interactively> magit-refresh nil nil)
  apply(call-interactively@ido-cr+-record-current-command #<subr call-interactively> (magit-refresh nil nil))
  call-interactively(magit-refresh nil nil)
  command-execute(magit-refresh)

This led me to

magithub/magithub-core.el

Lines 333 to 347 in c5204a8

(let (api-status error-data response)
(condition-case err
(progn
(with-timeout (magithub-api-timeout
(signal 'magithub-api-timeout nil))
(setq response
;; /rate_limit is free for GitHub.com.
;; If rate limiting is disabled
;; (i.e. GHE), try using /meta which
;; should (hopefully) always work. See
;; also issue #107.
(or (ghubp-ratelimit)
(ghub-get "/meta" nil :auth 'magithub))
api-status (and response t)))

It looks like there's a magithub-request call missing here but I wouldn't swear to it.

@vermiculus
Copy link
Owner

Thanks for catching!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants