isomorphic-git / isomorphic-git/isomorphic-git
Repository in inconsistent state after git fetch
- Dominant language
- JavaScript
- Stars
- 8.4k
- Forks
- 491
- Avg merge
- 2h 53m
- Merged PRs (30d)
- 7
Description
When using isomorphic-git with lightning-fs in the browser, I occasionally find the repository in an inconsistent state where you cannot read the commit of remote HEAD after `git fetch`:
```js
let oid = await git.resolveRef({ fs, dir, ref: 'refs/remotes/origin/main' })
// Throws "Uncaught NotFoundError: Could not find ${oid}."
await git.readCommit({ fs, dir, oid })
```
I suspect the cause of this problem is that the `fetch` implementation is non-atomic. Quoting [Using IndexedDB](https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API/Using_IndexedDB#warning_about_browser_shutdown) on MDN:
> Since the user can exit the browser at any time, this means that you cannot rely upon any
> particular transaction to complete, and on older browsers, you don't even get told when they don't
> complete. ...you should take care to always leave your database in a consistent state at the end
> of every transaction.
In the `_fetch` function, the remote refs are updated before the packfile is written. As lightning-fs writes the cache to IndexedDB with a debounce of 500ms, if the user closes the tab between the persistence of remote refs and packfile, the remote HEAD will point to a nonexistent object.
This can be reproduced by adding `await new Promise(r => setTimeout(r, 1000));` before [this line](https://github.com/isomorphic-git/isomorphic-git/blob/v1.8.0/src/commands/fetch.js#L345), and closing the tab during the sleeping.
A possible fix might be expose the [`DefaultBackend._saveSuperblock`](https://github.com/isomorphic-git/lightning-fs/blob/v4.4.1/src/DefaultBackend.js#L79) method and allow the user to manually persist the FS after fetching, instead of relying on saving it regularly.
Contributor guide
Assessment
This issue has not been assessed yet.