-
Notifications
You must be signed in to change notification settings - Fork 639
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
Use nodegit #1315
base: master
Are you sure you want to change the base?
Use nodegit #1315
Changes from all commits
5a5d89e
d2336c7
c7751e8
2df4bce
253ed24
537012e
7033598
eee5ddb
ae5d5d5
1fc0b53
2db2d87
6c3a361
8f774b6
49c7c55
94e8b47
2afd377
f3dc504
0c31897
88c1967
c611083
39ee6e0
dd6e171
64f1cbd
caf4144
e2b4be7
1e534f5
4c0a0bc
fe7d720
1526e0e
1679564
8ce61cc
482e863
4fe9a49
ac03f6d
decff6a
1f797a3
b9a9b42
30a9598
ea76d28
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
watch_file package-lock.json | ||
use flake | ||
layout node |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
# TODO | ||
|
||
## bugs | ||
|
||
- conflicts don't always have a diff | ||
- diff sometimes includes multiple deletions of the same file | ||
- new file shows as modified, with 0 additions and an oldFileName but not newFileName | ||
- new adds [new] | ||
- remote-tags-updated does not fetch new remote refs and update the tree | ||
- move watcher to repo class | ||
|
||
## ideas | ||
|
||
- staging: show staged files inline with checkboxes | ||
- [x] useStaging mode when index is populated | ||
- [ ] when clicking checkbox in useStaging, stage/unstage | ||
- [ ] when selecting text in diff let patch button add selected range to staged and switch to useStaging | ||
- [ ] Allow sorting branches by local first or just by date | ||
- [ ] alias all commits with numeric ids to limit mem use on client | ||
- [ ] load commit existence and parents separately from metadata | ||
- [ ] possibly cache them in a db so the entire tree, if loading commit tree from git is slow | ||
- [ ] conflict diffs should be shown better, like in vscode | ||
- [ ] be able to expand diff context, like on github | ||
|
||
- [ ] CRDT sync between TODO file and github issue :drool: |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,11 +13,10 @@ components.register('branches', (args) => { | |
}); | ||
|
||
class BranchesViewModel extends ComponentRoot { | ||
constructor(server, graph, repoPath) { | ||
constructor(server, /** @type {GitGraph} */ graph, repoPath) { | ||
super(); | ||
this.repoPath = repoPath; | ||
this.server = server; | ||
this.updateRefs = _.debounce(this._updateRefs, 250, this.defaultDebounceOption); | ||
this.branchesAndLocalTags = ko.observableArray(); | ||
this.current = ko.observable(); | ||
this.isShowRemote = ko.observable(storage.getItem(showRemote) != 'false'); | ||
|
@@ -45,6 +44,7 @@ class BranchesViewModel extends ComponentRoot { | |
this.refsLabel = ko.computed(() => this.current() || 'master (no commits yet)'); | ||
this.branchIcon = octicons['git-branch'].toSVG({ height: 18 }); | ||
this.closeIcon = octicons.x.toSVG({ height: 18 }); | ||
this.firstFetch = true; | ||
} | ||
|
||
checkoutBranch(branch) { | ||
|
@@ -66,75 +66,77 @@ class BranchesViewModel extends ComponentRoot { | |
this.updateRefs(); | ||
} | ||
} | ||
async _updateRefs(forceRemoteFetch) { | ||
updateRefs(forceRemoteFetch) { | ||
forceRemoteFetch = forceRemoteFetch || this.shouldAutoFetch || ''; | ||
if (this.firstFetch) forceRemoteFetch = ''; | ||
Comment on lines
70
to
+71
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Maybe we should separate these logics to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hmm yes - having the first fetch be remote makes it slow, that's why it does it twice. Perhaps some of this logic should move to the server side, where it can more easily decide when to git-fetch and can send events if the refs change. |
||
|
||
const branchesProm = this.server.getPromise('/branches', { path: this.repoPath() }); | ||
const refsProm = this.server.getPromise('/refs', { | ||
path: this.repoPath(), | ||
remoteFetch: forceRemoteFetch, | ||
}); | ||
const currentBranchProm = this.server | ||
.getPromise('/checkout', { path: this.repoPath() }) | ||
.then((branch) => this.current(branch)) | ||
.catch((err) => this.current('~error')); | ||
|
||
try { | ||
// set current branch | ||
(await branchesProm).forEach((b) => { | ||
if (b.current) { | ||
this.current(b.name); | ||
// refreshes tags branches and remote branches | ||
// TODO refresh remote refs separately, notify autofetch via ws | ||
const refsProm = this.server | ||
.getPromise('/refs', { path: this.repoPath(), remoteFetch: forceRemoteFetch }) | ||
.then((refs) => { | ||
const stamp = Date.now(); | ||
const locals = []; | ||
for (const { name, sha1, date } of refs) { | ||
const lname = name.replace('refs/tags', 'tag: refs/tags'); | ||
// side effect: registers the ref | ||
const ref = this.graph.getRef(lname, sha1); | ||
const node = ref.node(); | ||
if (date && !node.isInited()) { | ||
const ts = Date.parse(date); | ||
// Push down uninited nodes based on date | ||
if (!node.date || node.date > ts) node.date = ts; | ||
} | ||
ref.stamp = stamp; | ||
const { localRefName, isRemote, isBranch, isTag } = ref; | ||
if ( | ||
!( | ||
localRefName == 'refs/stash' || | ||
// Remote HEAD | ||
localRefName.endsWith('/HEAD') || | ||
(isRemote && !this.isShowRemote()) || | ||
(isBranch && !this.isShowBranch()) || | ||
(isTag && !this.isShowTag()) | ||
) | ||
) | ||
locals.push(ref); | ||
} | ||
}); | ||
} catch (e) { | ||
this.current('~error'); | ||
ungit.logger.warn('error while setting current branch', e); | ||
} | ||
|
||
try { | ||
// update branches and tags references. | ||
const refs = await refsProm; | ||
if (this.isSamePayload(refs)) { | ||
return; | ||
} | ||
|
||
const version = Date.now(); | ||
const sorted = refs | ||
.map((r) => { | ||
const ref = this.graph.getRef(r.name.replace('refs/tags', 'tag: refs/tags')); | ||
ref.node(this.graph.getNode(r.sha1)); | ||
ref.version = version; | ||
return ref; | ||
}) | ||
.sort((a, b) => { | ||
locals.sort((a, b) => { | ||
if (a.current() || b.current()) { | ||
// Current branch is always first | ||
return a.current() ? -1 : 1; | ||
} else if (a.isRemoteBranch === b.isRemoteBranch) { | ||
if (a.name < b.name) { | ||
return -1; | ||
} | ||
if (a.name > b.name) { | ||
return 1; | ||
} | ||
return 0; | ||
} else { | ||
} else if (a.isRemoteBranch !== b.isRemoteBranch) { | ||
// Remote branches show last | ||
return a.isRemoteBranch ? 1 : -1; | ||
} else { | ||
// Otherwise, sort by name, grouped by remoteness | ||
return a.name < b.name ? -1 : a.name > b.name ? 1 : 0; | ||
} | ||
}) | ||
.filter((ref) => { | ||
if (ref.localRefName == 'refs/stash') return false; | ||
if (ref.localRefName.endsWith('/HEAD')) return false; | ||
if (!this.isShowRemote() && ref.isRemote) return false; | ||
if (!this.isShowBranch() && ref.isBranch) return false; | ||
if (!this.isShowTag() && ref.isTag) return false; | ||
return true; | ||
}); | ||
this.branchesAndLocalTags(sorted); | ||
this.graph.refs().forEach((ref) => { | ||
// ref was removed from another source | ||
if (!ref.isRemoteTag && ref.value !== 'HEAD' && (!ref.version || ref.version < version)) { | ||
ref.remove(true); | ||
} | ||
this.branchesAndLocalTags(locals); | ||
this.graph.refs().forEach((ref) => { | ||
// ref was removed from another source | ||
if (!ref.isRemoteTag && ref.value !== 'HEAD' && ref.stamp !== stamp) { | ||
ref.remove(true); | ||
} | ||
}); | ||
this.graph.fetchCommits(); | ||
}) | ||
.catch((e) => this.server.unhandledRejection(e)); | ||
|
||
if (this.firstFetch) { | ||
refsProm.then(() => { | ||
this.firstFetch = false; | ||
// Fetch remotes on first load | ||
this.updateRefs(true); | ||
}); | ||
} catch (e) { | ||
ungit.logger.error('error during branch update: ', e); | ||
} | ||
return Promise.all([currentBranchProm, refsProm]); | ||
} | ||
|
||
branchRemove(branch) { | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of doing
firstFetch
flag. Maybe we should do something like this?Although, I'm little confused on why this quick succession of same calls are required?