diff --git a/.all-contributorsrc b/.all-contributorsrc index 23427638e..b4ab87b6c 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -660,6 +660,15 @@ "contributions": [ "code" ] + }, + { + "login": "yarikoptic", + "name": "Yaroslav Halchenko", + "avatar_url": "https://avatars.githubusercontent.com/u/39889?v=4", + "profile": "https://github.com/yarikoptic", + "contributions": [ + "doc" + ] } ], "commitConvention": "angular" diff --git a/.codespellrc b/.codespellrc new file mode 100644 index 000000000..eceb2a91a --- /dev/null +++ b/.codespellrc @@ -0,0 +1,5 @@ +[codespell] +skip = .git,*.pdf,*.svg,package-lock.json,*.css,*.min.*,.codespellrc,__fixtures__,__tests__ +check-hidden = true +# ignore-regex = +ignore-words-list = ot,fo diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml new file mode 100644 index 000000000..3ebbf5504 --- /dev/null +++ b/.github/workflows/codespell.yml @@ -0,0 +1,22 @@ +--- +name: Codespell + +on: + push: + branches: [main] + pull_request: + branches: [main] + +permissions: + contents: read + +jobs: + codespell: + name: Check for spelling errors + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Codespell + uses: codespell-project/actions-codespell@v2 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c01f8458d..65ac48cfa 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -83,7 +83,7 @@ parse[*]Request: (input: stream) -> Object write[*]Response: (input: Object) -> stream ### How git works -If you want to contribute it may be usefull if you understand how git works under the hood. +If you want to contribute it may be useful if you understand how git works under the hood. This is great article that shows the details:
[A Hacker's Guide to Git](https://wildlyinaccurate.com/a-hackers-guide-to-git/).
But as first the introduction you can watch this video:
diff --git a/README.md b/README.md index 1963bcb0c..dd736fa91 100644 --- a/README.md +++ b/README.md @@ -367,6 +367,7 @@ Thanks goes to these wonderful people ([emoji key](https://github.com/kentcdodds
DanilKazanov

💻 📖 ⚠️
Eyal Hisco

🐛
Sebastien

💻 +
Yaroslav Halchenko

📖 diff --git a/__tests__/test-abortMerge.js b/__tests__/test-abortMerge.js index 4d56b9671..5543c9844 100644 --- a/__tests__/test-abortMerge.js +++ b/__tests__/test-abortMerge.js @@ -154,7 +154,7 @@ describe('abortMerge', () => { expect(await modified(index, head)).toBe(false) - // only since we didnt touch anything + // only since we didn't touch anything expect(await modified(workdir, head)).toBe(false) expect(await modified(index, workdir)).toBe(false) diff --git a/__tests__/test-hosting-providers.js b/__tests__/test-hosting-providers.js index fb08181d9..2c9cd610f 100644 --- a/__tests__/test-hosting-providers.js +++ b/__tests__/test-hosting-providers.js @@ -20,7 +20,7 @@ describe('Hosting Providers', () => { // These HTTPS Git credentials for AWS CodeCommit are for IAM user arn:aws:iam::260687965765:user/tester // which only has git access to the test repo: // https://git-codecommit.us-west-2.amazonaws.com/v1/repos/test.empty - // It is stored reversed because the GitHub one is stored reversed and I like being consistant. + // It is stored reversed because the GitHub one is stored reversed and I like being consistent. const password = reverse('=cYfZKeyeW3ig0yZrkzkd9ElDKYctLgV2WNOZ1Ctntnt') const username = 'tester-at-260687965765' it('fetch', async () => { @@ -62,7 +62,7 @@ describe('Hosting Providers', () => { describe('Azure DevOps', () => { // These git credentials are specific to https://isomorphic-git@dev.azure.com/isomorphic-git/isomorphic-git/_git/test.empty - // It is stored reversed because the GitHub one is stored reversed and I like being consistant. + // It is stored reversed because the GitHub one is stored reversed and I like being consistent. const password = reverse('ez8dMKyRfWpzMkhg3QJb5m') const username = 'isomorphicgittestpush' it('fetch', async () => { @@ -106,7 +106,7 @@ describe('Hosting Providers', () => { // This App Password is for the test account 'isomorphic-git' user on Bitbucket, // with "repositories.read" and "repositories.write" access. However the only repo the account has access to is // https://bitbucket.org/isomorphic-git/test.empty - // It is stored reversed because the GitHub one is stored reversed and I like being consistant. + // It is stored reversed because the GitHub one is stored reversed and I like being consistent. const password = reverse('TqSWhF3xLxEEXKQtZTwn') const username = 'isomorphic-git' it('push', async () => { @@ -194,7 +194,7 @@ describe('Hosting Providers', () => { // This Personal Access Token is for a test account (https://gitlab.com/isomorphic-git-test-push) // with "read_repository" and "write_repository" access. However the only repo it has write access to is // https://gitlab.com/isomorphic-git/test.empty - // It is stored reversed because the GitHub one is stored reversed and I like being consistant. + // It is stored reversed because the GitHub one is stored reversed and I like being consistent. const password = reverse('vjNzgKP7acS6e6vb2Q6g') const username = 'isomorphic-git-test-push' it('fetch', async () => { diff --git a/__tests__/test-listServerRefs.js b/__tests__/test-listServerRefs.js index fd4ed728b..9be310471 100644 --- a/__tests__/test-listServerRefs.js +++ b/__tests__/test-listServerRefs.js @@ -10,7 +10,7 @@ const localhost = // NOTE: // Protocol Version 1 is incapable of reporting all the symrefs in a repo // It reports HEAD but does not report refs/heads/symbol. -// So that descrepancy between the results for version 1 and version 2 is correct. +// So that discrepancy between the results for version 1 and version 2 is correct. describe('listServerRefs', () => { it('protocol 1', async () => { const refs = await listServerRefs({ diff --git a/docs/cache.md b/docs/cache.md index 564e33ebe..bcf46c999 100644 --- a/docs/cache.md +++ b/docs/cache.md @@ -29,7 +29,7 @@ test().catch(err => console.log(err)) Running this code on the `isomorphic-git` repo on my 2018 Macbook Pro takes over 2 minutes! -It is slow because every time you call `git.status` it has to re-read and re-parse one or more packfiles in `.git/objecs/pack`. +It is slow because every time you call `git.status` it has to re-read and re-parse one or more packfiles in `.git/objects/pack`. Each individual status may take relatively little time (10ms to 100ms) but if you have thousands of files that quickly adds up. Naively doing it in parallel will not help! @@ -76,7 +76,7 @@ This runs in 843ms on my machine. As you can see, you can easily write yourself into a performance trap using `isomorphic-git` commands in isolation. Unlike canonical `git` commands however, there is a way for `isomorphic-git` commands to cache intermediate results -and re-use them between commands. +and reuse them between commands. It used to do this by default, but that results in a memory leak if you never clear the cache. There is no single best caching strategy: diff --git a/docs/onAuthFailure.md b/docs/onAuthFailure.md index e19ce5f9e..aa1d483ea 100644 --- a/docs/onAuthFailure.md +++ b/docs/onAuthFailure.md @@ -8,7 +8,7 @@ This is helpful to know if you were using a saved password in the `onAuth` callb It also gives you an opportunity to retry the request with new credentials. As long as your `onAuthFailure` function returns credentials, it will keep trying. -This is the main reason we don't re-use the `onAuth` callback for this purpose. If we did, then a naive `onAuth` callback that simply returned saved credentials might loop indefinitely. +This is the main reason we don't reuse the `onAuth` callback for this purpose. If we did, then a naive `onAuth` callback that simply returned saved credentials might loop indefinitely. An `onAuthFailure` function is called with a `url` and an `auth` object and can return a GitAuth object: diff --git a/src/api/annotatedTag.js b/src/api/annotatedTag.js index 0575f02ed..d569e55cb 100644 --- a/src/api/annotatedTag.js +++ b/src/api/annotatedTag.js @@ -24,7 +24,7 @@ import { normalizeAuthorObject } from '../utils/normalizeAuthorObject.js' * @param {string} [args.tagger.email] - Default is `user.email` config. * @param {number} [args.tagger.timestamp=Math.floor(Date.now()/1000)] - Set the tagger timestamp field. This is the integer number of seconds since the Unix epoch (1970-01-01 00:00:00). * @param {number} [args.tagger.timezoneOffset] - Set the tagger timezone offset field. This is the difference, in minutes, from the current timezone to UTC. Default is `(new Date()).getTimezoneOffset()`. - * @param {string} [args.gpgsig] - The gpgsig attatched to the tag object. (Mutually exclusive with the `signingKey` option.) + * @param {string} [args.gpgsig] - The gpgsig attached to the tag object. (Mutually exclusive with the `signingKey` option.) * @param {string} [args.signingKey] - Sign the tag object using this private PGP key. (Mutually exclusive with the `gpgsig` option.) * @param {boolean} [args.force = false] - Instead of throwing an error if a tag named `ref` already exists, overwrite the existing tag. Note that this option does not modify the original tag object itself. * @param {object} [args.cache] - a [cache](cache.md) object diff --git a/src/api/listServerRefs.js b/src/api/listServerRefs.js index 25ed13446..57728eec9 100644 --- a/src/api/listServerRefs.js +++ b/src/api/listServerRefs.js @@ -25,12 +25,12 @@ import { writeListRefsRequest } from '../wire/writeListRefsRequest.js' * Hard numbers vary by situation, but here's some numbers from my machine: * * Using isomorphic-git in a browser, with a CORS proxy, listing only the branches (refs/heads) of https://github.com/isomorphic-git/isomorphic-git - * - Protocol Version 1 took ~300ms and transfered 84 KB. - * - Protocol Version 2 took ~500ms and transfered 4.1 KB. + * - Protocol Version 1 took ~300ms and transferred 84 KB. + * - Protocol Version 2 took ~500ms and transferred 4.1 KB. * * Using isomorphic-git in a browser, with a CORS proxy, listing only the branches (refs/heads) of https://gitlab.com/gitlab-org/gitlab - * - Protocol Version 1 took ~4900ms and transfered 9.41 MB. - * - Protocol Version 2 took ~1280ms and transfered 433 KB. + * - Protocol Version 1 took ~4900ms and transferred 9.41 MB. + * - Protocol Version 2 took ~1280ms and transferred 433 KB. * * Finally, there is a fun quirk regarding the `symrefs` parameter. * Protocol Version 1 will generally only return the `HEAD` symref and not others. diff --git a/src/commands/checkout.js b/src/commands/checkout.js index 31aaf03f7..90699a8ea 100644 --- a/src/commands/checkout.js +++ b/src/commands/checkout.js @@ -318,7 +318,7 @@ async function analyze({ // This is a kind of silly pattern but it worked so well for me in the past // and it makes intuitively demonstrating exhaustiveness so *easy*. - // This checks for the presense and/or absence of each of the 3 entries, + // This checks for the presence and/or absence of each of the 3 entries, // converts that to a 3-bit binary representation, and then handles // every possible combination (2^3 or 8 cases) with a lookup table. const key = [!!stage, !!commit, !!workdir].map(Number).join('') diff --git a/src/errors/IndexResetError.js b/src/errors/IndexResetError.js index bf1ee5510..19fc816c9 100644 --- a/src/errors/IndexResetError.js +++ b/src/errors/IndexResetError.js @@ -6,7 +6,7 @@ export class IndexResetError extends BaseError { */ constructor(filepath) { super( - `Could not merge index: Entry for '${filepath}' is not up to date. Either reset the index entry to HEAD, or stage your unstaged chages.` + `Could not merge index: Entry for '${filepath}' is not up to date. Either reset the index entry to HEAD, or stage your unstaged changes.` ) this.code = this.name = IndexResetError.code this.data = { filepath } diff --git a/src/managers/GitIgnoreManager.js b/src/managers/GitIgnoreManager.js index 0ae7e49d5..82e65091d 100644 --- a/src/managers/GitIgnoreManager.js +++ b/src/managers/GitIgnoreManager.js @@ -5,7 +5,7 @@ import { dirname } from '../utils/dirname.js' import { join } from '../utils/join.js' // I'm putting this in a Manager because I reckon it could benefit -// from a LOT of cacheing. +// from a LOT of caching. export class GitIgnoreManager { static async isIgnored({ fs, dir, gitdir = join(dir, '.git'), filepath }) { // ALWAYS ignore ".git" folders. diff --git a/src/managers/GitRemoteHTTP.js b/src/managers/GitRemoteHTTP.js index ccef4a011..11b8b6536 100644 --- a/src/managers/GitRemoteHTTP.js +++ b/src/managers/GitRemoteHTTP.js @@ -8,7 +8,7 @@ import { collect } from '../utils/collect.js' import { extractAuthFromUrl } from '../utils/extractAuthFromUrl.js' import { parseRefsAdResponse } from '../wire/parseRefsAdResponse.js' -// Try to accomodate known CORS proxy implementations: +// Try to accommodate known CORS proxy implementations: // - https://jcubic.pl/proxy.php? <-- uses query string // - https://cors.isomorphic-git.org <-- uses path const corsProxify = (corsProxy, url) => diff --git a/src/models/FileSystem.js b/src/models/FileSystem.js index 2eea5cc26..9d96efded 100644 --- a/src/models/FileSystem.js +++ b/src/models/FileSystem.js @@ -74,7 +74,7 @@ export class FileSystem { /** * Return true if a file exists, false if it doesn't exist. - * Rethrows errors that aren't related to file existance. + * Rethrows errors that aren't related to file existence. */ async exists(filepath, options = {}) { try { @@ -218,7 +218,7 @@ export class FileSystem { /** * Return the Stats of a file/symlink if it exists, otherwise returns null. - * Rethrows errors that aren't related to file existance. + * Rethrows errors that aren't related to file existence. */ async lstat(filename) { try { @@ -234,7 +234,7 @@ export class FileSystem { /** * Reads the contents of a symlink if it exists, otherwise returns null. - * Rethrows errors that aren't related to file existance. + * Rethrows errors that aren't related to file existence. */ async readlink(filename, opts = { encoding: 'buffer' }) { // Note: FileSystem.readlink returns a buffer by default diff --git a/src/models/GitConfig.js b/src/models/GitConfig.js index b0e023255..8a48c11ca 100644 --- a/src/models/GitConfig.js +++ b/src/models/GitConfig.js @@ -34,7 +34,7 @@ const schema = { // section starts with [ and ends with ] // section is alphanumeric (ASCII) with - and . // section is case insensitive -// subsection is optionnal +// subsection is optional // subsection is specified after section and one or more spaces // subsection is specified between double quotes const SECTION_LINE_REGEX = /^\[([A-Za-z0-9-.]+)(?: "(.*)")?\]$/ diff --git a/src/models/GitPktLine.js b/src/models/GitPktLine.js index 0b7fbc7b3..6b12171df 100644 --- a/src/models/GitPktLine.js +++ b/src/models/GitPktLine.js @@ -9,7 +9,7 @@ of the line, the pkt-len, indicates the total length of the line, in hexadecimal. The pkt-len includes the 4 bytes used to contain the length's hexadecimal representation. -A pkt-line MAY contain binary data, so implementors MUST ensure +A pkt-line MAY contain binary data, so implementers MUST ensure pkt-line parsing/formatting routines are 8-bit clean. A non-binary line SHOULD BE terminated by an LF, which if present diff --git a/website/blog/2018-04-02-contributing-workflow.md b/website/blog/2018-04-02-contributing-workflow.md index ae8705fff..9c68407ce 100644 --- a/website/blog/2018-04-02-contributing-workflow.md +++ b/website/blog/2018-04-02-contributing-workflow.md @@ -268,7 +268,7 @@ Branch issue-107 set up to track remote branch issue-107 from origin. ``` (If the linter had found any style problems, it would have fixed them using prettier. -I have not automated ammending the commit though, so I would have to fix the commit with +I have not automated amending the commit though, so I would have to fix the commit with `git add -u && git commit --amend --no-edit` and try pushing again.) Since it succeeded, it will show up on the [Github page](https://github.com/isomorphic-git/isomorphic-git) @@ -279,7 +279,7 @@ However, now I will tack on "(fixes #107)" to the end of the title just so Githu the issue and the PR. ... I lied. Github is not smart enough to use the PR title. :eyeroll: -I edit the PR description to be "fixes #107" and _then_ Github adds the "wmhilton referened this issue a minute ago" link to the PR to the issue. +I edit the PR description to be "fixes #107" and _then_ Github adds the "wmhilton referenced this issue a minute ago" link to the PR to the issue. Now we wait for the Continuous Integration (CI) system to do its thing. I didn't actually check if it would work in the browser - diff --git a/website/blog/2020-02-25-version-1-0-0.md b/website/blog/2020-02-25-version-1-0-0.md index fed8b1cee..c9e2548f8 100644 --- a/website/blog/2020-02-25-version-1-0-0.md +++ b/website/blog/2020-02-25-version-1-0-0.md @@ -38,7 +38,7 @@ And here's what it looks like in version 1.0: The functions themselves have been tweaked so that the [core object interfaces](https://github.com/isomorphic-git/isomorphic-git/blob/master/src/typedefs.js) (`CommitObject`, `TreeEntry`, `TagObject`, etc) are reused wherever possible, -so that all the functions feel consistant and there are no surprises. +so that all the functions feel consistent and there are no surprises. The result is a cleaner API where the documentation comes to you, right where you are. ## Better TypeScript Integration @@ -159,7 +159,7 @@ Everyone has benefitted from the bugfixes, perf, and usability enhancements that - The `autoTranslateSSH` feature was removed, since it is trivial to implement your own version using just the `UnknownTransportError.data.suggestion` - The `writeObject` function when used to write a tree now expects a plain array rather than an object with a property called `entries` which is the array. (This is so that argument to `writeObject` has the same shape as the arguments to `writeBlob`/`writeCommit`/`writeTag`/`writeTree`.) - The `noOverwrite` parameter was removed from `init` and is the new behavior. -- The `author.date`, `committer.date`, `tagger.date` parameters were removed in favor of `author.timestamp`, `comitter.timestamp`, `tagger.timestamp` in order to be clear about what is actually written and share the same shape as the return types in `readCommit`, `log`, and `readTag`. +- The `author.date`, `committer.date`, `tagger.date` parameters were removed in favor of `author.timestamp`, `committer.timestamp`, `tagger.timestamp` in order to be clear about what is actually written and share the same shape as the return types in `readCommit`, `log`, and `readTag`. ### The return types of some functions have changed: - Functions that used to return `Buffer` objects now return `Uint8Array` objects. (This is so we can eventually remove all internal dependencies on the Buffer browser polyfill, which is quite heavy!) diff --git a/website/pages/en/index.js b/website/pages/en/index.js index 116d06397..a3f56d49e 100644 --- a/website/pages/en/index.js +++ b/website/pages/en/index.js @@ -268,7 +268,7 @@ const TryGitRemoteInfo = props => (

Try it out!

- +
| Resolves successfully when filesystem operations are complete | diff --git a/website/versioned_docs/version-0.70.7/guide-webworker.md b/website/versioned_docs/version-0.70.7/guide-webworker.md index a800a6678..9ee63ba2a 100644 --- a/website/versioned_docs/version-0.70.7/guide-webworker.md +++ b/website/versioned_docs/version-0.70.7/guide-webworker.md @@ -28,9 +28,9 @@ Because of foresight and planning, most `isomorphic-git` functions are: The plugins (excepting `fs` plugin) also follow this pattern. This greatly simplifies the job of mapping `isomorphic-git` calls to a remote procedure call (RPC) API using `postMessage`. -If you already have a WebWorker in your project and a prefered way to communicating with it, then mapping `isomorphic-git` calls is easy. +If you already have a WebWorker in your project and a preferred way to communicating with it, then mapping `isomorphic-git` calls is easy. -If you don't already have a prefered WebWorker RPC solution, then the easiest way is to use the [MagicPortal](https://www.npmjs.com/package/magic-portal) which was designed specifically for `isomorphic-git` so it's a perfect match! +If you don't already have a preferred WebWorker RPC solution, then the easiest way is to use the [MagicPortal](https://www.npmjs.com/package/magic-portal) which was designed specifically for `isomorphic-git` so it's a perfect match! The examples below will use MagicPortal. ## Implementation diff --git a/website/versioned_docs/version-1.x/annotatedTag.md b/website/versioned_docs/version-1.x/annotatedTag.md index 4a188927a..d568c96bb 100644 --- a/website/versioned_docs/version-1.x/annotatedTag.md +++ b/website/versioned_docs/version-1.x/annotatedTag.md @@ -21,7 +21,7 @@ Create an annotated tag. | tagger.email | string | Default is `user.email` config. | | tagger.timestamp | number = Math.floor(Date.now()/1000) | Set the tagger timestamp field. This is the integer number of seconds since the Unix epoch (1970-01-01 00:00:00). | | tagger.timezoneOffset | number | Set the tagger timezone offset field. This is the difference, in minutes, from the current timezone to UTC. Default is `(new Date()).getTimezoneOffset()`. | -| gpgsig | string | The gpgsig attatched to the tag object. (Mutually exclusive with the `signingKey` option.) | +| gpgsig | string | The gpgsig attached to the tag object. (Mutually exclusive with the `signingKey` option.) | | signingKey | string | Sign the tag object using this private PGP key. (Mutually exclusive with the `gpgsig` option.) | | force | boolean = false | Instead of throwing an error if a tag named `ref` already exists, overwrite the existing tag. Note that this option does not modify the original tag object itself. | | cache | object | a [cache](cache.md) object | diff --git a/website/versioned_docs/version-1.x/cache.md b/website/versioned_docs/version-1.x/cache.md index dcd2a8b29..077f9ea56 100644 --- a/website/versioned_docs/version-1.x/cache.md +++ b/website/versioned_docs/version-1.x/cache.md @@ -30,7 +30,7 @@ test().catch(err => console.log(err)) Running this code on the `isomorphic-git` repo on my 2018 Macbook Pro takes over 2 minutes! -It is slow because every time you call `git.status` it has to re-read and re-parse one or more packfiles in `.git/objecs/pack`. +It is slow because every time you call `git.status` it has to re-read and re-parse one or more packfiles in `.git/objects/pack`. Each individual status may take relatively little time (10ms to 100ms) but if you have thousands of files that quickly adds up. Naively doing it in parallel will not help! @@ -77,7 +77,7 @@ This runs in 843ms on my machine. As you can see, you can easily write yourself into a performance trap using `isomorphic-git` commands in isolation. Unlike canonical `git` commands however, there is a way for `isomorphic-git` commands to cache intermediate results -and re-use them between commands. +and reuse them between commands. It used to do this by default, but that results in a memory leak if you never clear the cache. There is no single best caching strategy: diff --git a/website/versioned_docs/version-1.x/listServerRefs.md b/website/versioned_docs/version-1.x/listServerRefs.md index 9a5e9fe2b..368989521 100644 --- a/website/versioned_docs/version-1.x/listServerRefs.md +++ b/website/versioned_docs/version-1.x/listServerRefs.md @@ -49,12 +49,12 @@ But for large repos (or slow Internet connections), the decreased payload size o Hard numbers vary by situation, but here's some numbers from my machine: Using isomorphic-git in a browser, with a CORS proxy, listing only the branches (refs/heads) of https://github.com/isomorphic-git/isomorphic-git -- Protocol Version 1 took ~300ms and transfered 84 KB. -- Protocol Version 2 took ~500ms and transfered 4.1 KB. +- Protocol Version 1 took ~300ms and transferred 84 KB. +- Protocol Version 2 took ~500ms and transferred 4.1 KB. Using isomorphic-git in a browser, with a CORS proxy, listing only the branches (refs/heads) of https://gitlab.com/gitlab-org/gitlab -- Protocol Version 1 took ~4900ms and transfered 9.41 MB. -- Protocol Version 2 took ~1280ms and transfered 433 KB. +- Protocol Version 1 took ~4900ms and transferred 9.41 MB. +- Protocol Version 2 took ~1280ms and transferred 433 KB. Finally, there is a fun quirk regarding the `symrefs` parameter. Protocol Version 1 will generally only return the `HEAD` symref and not others. diff --git a/website/versioned_docs/version-1.x/onAuthFailure.md b/website/versioned_docs/version-1.x/onAuthFailure.md index ad8d1c52d..d43e9aea3 100644 --- a/website/versioned_docs/version-1.x/onAuthFailure.md +++ b/website/versioned_docs/version-1.x/onAuthFailure.md @@ -10,7 +10,7 @@ This is helpful to know if you were using a saved password in the `onAuth` callb It also gives you an opportunity to retry the request with new credentials. As long as your `onAuthFailure` function returns credentials, it will keep trying. -This is the main reason we don't re-use the `onAuth` callback for this purpose. If we did, then a naive `onAuth` callback that simply returned saved credentials might loop indefinitely. +This is the main reason we don't reuse the `onAuth` callback for this purpose. If we did, then a naive `onAuth` callback that simply returned saved credentials might loop indefinitely. An `onAuthFailure` function is called with a `url` and an `auth` object and can return a GitAuth object: