mirror of
https://github.com/sourcegit-scm/sourcegit.git
synced 2024-12-23 20:47:25 -08:00
optimize<WorkingCopy>: improve loading time for large number of local changes
This commit is contained in:
parent
4cd07d90a5
commit
5434629f4c
3 changed files with 154 additions and 87 deletions
|
@ -324,9 +324,10 @@ namespace SourceGit.Views.Widgets {
|
||||||
|
|
||||||
Task.Run(() => {
|
Task.Run(() => {
|
||||||
var changes = new Commands.LocalChanges(repo.Path, Models.Preference.Instance.Git.IncludeUntrackedInWC).Result();
|
var changes = new Commands.LocalChanges(repo.Path, Models.Preference.Instance.Git.IncludeUntrackedInWC).Result();
|
||||||
|
(pages.Get("working_copy") as WorkingCopy).SetData(changes);
|
||||||
|
|
||||||
Dispatcher.Invoke(() => {
|
Dispatcher.Invoke(() => {
|
||||||
badgeLocalChanges.Label = $"{changes.Count}";
|
badgeLocalChanges.Label = $"{changes.Count}";
|
||||||
(pages.Get("working_copy") as WorkingCopy).SetData(changes);
|
|
||||||
UpdateMergeBar(changes);
|
UpdateMergeBar(changes);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
|
@ -43,36 +43,38 @@ namespace SourceGit.Views.Widgets {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unstagedContainer.SetData(unstagedChanges);
|
Dispatcher.Invoke(() => {
|
||||||
stagedContainer.SetData(stagedChanges);
|
unstagedContainer.SetData(unstagedChanges);
|
||||||
|
stagedContainer.SetData(stagedChanges);
|
||||||
|
|
||||||
var current = repo.Branches.Find(x => x.IsCurrent);
|
var current = repo.Branches.Find(x => x.IsCurrent);
|
||||||
if (current != null && !string.IsNullOrEmpty(current.Upstream) && chkAmend.IsChecked != true) {
|
if (current != null && !string.IsNullOrEmpty(current.Upstream) && chkAmend.IsChecked != true) {
|
||||||
btnCommitAndPush.Visibility = Visibility.Visible;
|
btnCommitAndPush.Visibility = Visibility.Visible;
|
||||||
} else {
|
} else {
|
||||||
btnCommitAndPush.Visibility = Visibility.Collapsed;
|
btnCommitAndPush.Visibility = Visibility.Collapsed;
|
||||||
}
|
}
|
||||||
|
|
||||||
mergePanel.Visibility = Visibility.Collapsed;
|
mergePanel.Visibility = Visibility.Collapsed;
|
||||||
|
|
||||||
var diffTarget = unstagedContainer.DiffTarget;
|
var diffTarget = unstagedContainer.DiffTarget;
|
||||||
if (diffTarget != null) {
|
if (diffTarget != null) {
|
||||||
if (diffTarget.IsConflit) {
|
if (diffTarget.IsConflit) {
|
||||||
mergePanel.Visibility = Visibility.Visible;
|
mergePanel.Visibility = Visibility.Visible;
|
||||||
|
diffViewer.Reset();
|
||||||
|
} else {
|
||||||
|
diffViewer.Reload();
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
diffTarget = stagedContainer.DiffTarget;
|
||||||
|
if (diffTarget == null) {
|
||||||
diffViewer.Reset();
|
diffViewer.Reset();
|
||||||
} else {
|
} else {
|
||||||
diffViewer.Reload();
|
diffViewer.Reload();
|
||||||
}
|
}
|
||||||
|
});
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
diffTarget = stagedContainer.DiffTarget;
|
|
||||||
if (diffTarget == null) {
|
|
||||||
diffViewer.Reset();
|
|
||||||
} else {
|
|
||||||
diffViewer.Reload();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void TryLoadMergeMessage() {
|
public void TryLoadMergeMessage() {
|
||||||
|
|
|
@ -173,70 +173,112 @@ namespace SourceGit.Views.Widgets {
|
||||||
|
|
||||||
public void SetData(List<Models.Change> changes) {
|
public void SetData(List<Models.Change> changes) {
|
||||||
isLoadingData = true;
|
isLoadingData = true;
|
||||||
|
|
||||||
var oldSet = new Dictionary<string, Models.Change>();
|
|
||||||
var newSet = new Dictionary<string, Models.Change>();
|
|
||||||
foreach (var c in changes) newSet.Add(c.Path, c);
|
|
||||||
|
|
||||||
for (int i = Changes.Count - 1; i >= 0; i--) {
|
|
||||||
var old = Changes[i];
|
|
||||||
if (!newSet.ContainsKey(old.Path)) {
|
|
||||||
Changes.RemoveAt(i);
|
|
||||||
RemoveTreeNode(Nodes, old);
|
|
||||||
if (modeTree.Selected.Contains(old)) modeTree.Selected.Remove(old);
|
|
||||||
if (DiffTarget == old) DiffTarget = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
var cur = newSet[old.Path];
|
|
||||||
if (cur.Index != old.Index || cur.WorkTree != old.WorkTree) {
|
|
||||||
Changes.RemoveAt(i);
|
|
||||||
RemoveTreeNode(Nodes, old);
|
|
||||||
if (modeTree.Selected.Contains(old)) modeTree.Selected.Remove(old);
|
|
||||||
if (DiffTarget == old) DiffTarget = null;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
oldSet.Add(old.Path, old);
|
|
||||||
}
|
|
||||||
|
|
||||||
var isDefaultExpand = changes.Count <= 50;
|
var isDefaultExpand = changes.Count <= 50;
|
||||||
foreach (var c in changes) {
|
|
||||||
if (oldSet.ContainsKey(c.Path)) continue;
|
|
||||||
|
|
||||||
bool added = false;
|
if (changes.Count == 0) {
|
||||||
for (int i = 0; i < Changes.Count; i++) {
|
Changes.Clear();
|
||||||
if (c.Path.CompareTo(Changes[i].Path) < 0) {
|
Nodes.Clear();
|
||||||
Changes.Insert(i, c);
|
} else if (Changes.Count == 0) {
|
||||||
added = true;
|
var nodesMap = new Dictionary<string, ChangeNode>();
|
||||||
break;
|
foreach (var c in changes) {
|
||||||
|
Changes.Add(c);
|
||||||
|
|
||||||
|
int sepIdx = c.Path.IndexOf("/", StringComparison.Ordinal);
|
||||||
|
if (sepIdx < 0) {
|
||||||
|
var n = AddTreeNode(Nodes, c.Path, c, false, true);
|
||||||
|
nodesMap.Add(c.Path, n);
|
||||||
|
} else {
|
||||||
|
ObservableCollection<ChangeNode> last = Nodes;
|
||||||
|
do {
|
||||||
|
ChangeNode parent = null;
|
||||||
|
var path = c.Path.Substring(0, sepIdx);
|
||||||
|
if (!nodesMap.TryGetValue(path, out parent)) {
|
||||||
|
parent = AddTreeNode(last, path, null, isDefaultExpand, true);
|
||||||
|
nodesMap.Add(path, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
last = parent.Children;
|
||||||
|
sepIdx = c.Path.IndexOf('/', sepIdx + 1);
|
||||||
|
} while (sepIdx > 0);
|
||||||
|
|
||||||
|
var n = AddTreeNode(last, c.Path, c, false, true);
|
||||||
|
nodesMap.Add(c.Path, n);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
nodesMap.Clear();
|
||||||
|
} else {
|
||||||
|
var oldSet = new Dictionary<string, Models.Change>();
|
||||||
|
var newSet = new Dictionary<string, Models.Change>();
|
||||||
|
foreach (var c in changes) newSet.Add(c.Path, c);
|
||||||
|
|
||||||
if (!added) Changes.Add(c);
|
for (int i = Changes.Count - 1; i >= 0; i--) {
|
||||||
|
var old = Changes[i];
|
||||||
|
if (!newSet.ContainsKey(old.Path)) {
|
||||||
|
Changes.RemoveAt(i);
|
||||||
|
RemoveTreeNode(Nodes, old.Path);
|
||||||
|
if (modeTree.Selected.Contains(old)) modeTree.Selected.Remove(old);
|
||||||
|
if (DiffTarget == old) DiffTarget = null;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
int sepIdx = c.Path.IndexOf("/", StringComparison.Ordinal);
|
var cur = newSet[old.Path];
|
||||||
if (sepIdx < 0) {
|
if (cur.Index != old.Index || cur.WorkTree != old.WorkTree) {
|
||||||
GetOrAddTreeNode(Nodes, c.Path, c, false);
|
Changes.RemoveAt(i);
|
||||||
} else {
|
RemoveTreeNode(Nodes, old.Path);
|
||||||
ObservableCollection<ChangeNode> last = Nodes;
|
if (modeTree.Selected.Contains(old)) modeTree.Selected.Remove(old);
|
||||||
do {
|
if (DiffTarget == old) DiffTarget = null;
|
||||||
var path = c.Path.Substring(0, sepIdx);
|
continue;
|
||||||
last = GetOrAddTreeNode(last, path, null, isDefaultExpand).Children;
|
}
|
||||||
sepIdx = c.Path.IndexOf('/', sepIdx + 1);
|
|
||||||
} while (sepIdx > 0);
|
oldSet.Add(old.Path, old);
|
||||||
GetOrAddTreeNode(last, c.Path, c, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var nodesMap = new Dictionary<string, ChangeNode>();
|
||||||
|
GetTreeNodes(nodesMap, Nodes);
|
||||||
|
|
||||||
|
for (int i = 0; i < changes.Count; i++) {
|
||||||
|
var c = changes[i];
|
||||||
|
if (oldSet.ContainsKey(c.Path)) continue;
|
||||||
|
|
||||||
|
Changes.Insert(i, c);
|
||||||
|
|
||||||
|
int sepIdx = c.Path.IndexOf("/", StringComparison.Ordinal);
|
||||||
|
if (sepIdx < 0) {
|
||||||
|
var n = AddTreeNode(Nodes, c.Path, c, false, false);
|
||||||
|
nodesMap.Add(c.Path, n);
|
||||||
|
} else {
|
||||||
|
ObservableCollection<ChangeNode> last = Nodes;
|
||||||
|
do {
|
||||||
|
ChangeNode parent = null;
|
||||||
|
var path = c.Path.Substring(0, sepIdx);
|
||||||
|
if (!nodesMap.TryGetValue(path, out parent)) {
|
||||||
|
parent = AddTreeNode(last, path, null, isDefaultExpand, false);
|
||||||
|
nodesMap.Add(path, parent);
|
||||||
|
}
|
||||||
|
|
||||||
|
last = parent.Children;
|
||||||
|
sepIdx = c.Path.IndexOf('/', sepIdx + 1);
|
||||||
|
} while (sepIdx > 0);
|
||||||
|
|
||||||
|
var n = AddTreeNode(last, c.Path, c, false, false);
|
||||||
|
nodesMap.Add(c.Path, n);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
nodesMap.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
isLoadingData = false;
|
isLoadingData = false;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
private ChangeNode GetOrAddTreeNode(ObservableCollection<ChangeNode> nodes, string path, Models.Change change, bool isExpand) {
|
private void GetTreeNodes(Dictionary<string, ChangeNode> map, ObservableCollection<ChangeNode> nodes) {
|
||||||
foreach (var n in nodes) {
|
foreach (var n in nodes) {
|
||||||
if (n.Path == path) return n;
|
map.Add(n.Path, n);
|
||||||
|
if (n.IsFolder) GetTreeNodes(map, n.Children);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ChangeNode AddTreeNode(ObservableCollection<ChangeNode> nodes, string path, Models.Change change, bool isExpand, bool isSorted = false) {
|
||||||
var node = new ChangeNode();
|
var node = new ChangeNode();
|
||||||
node.Path = path;
|
node.Path = path;
|
||||||
node.Change = change;
|
node.Change = change;
|
||||||
|
@ -245,19 +287,35 @@ namespace SourceGit.Views.Widgets {
|
||||||
var added = false;
|
var added = false;
|
||||||
if (change == null) {
|
if (change == null) {
|
||||||
for (int i = 0; i < nodes.Count; i++) {
|
for (int i = 0; i < nodes.Count; i++) {
|
||||||
if (!nodes[i].IsFolder || nodes[i].Path.CompareTo(path) > 0) {
|
var n = nodes[i];
|
||||||
|
if (!n.IsFolder) {
|
||||||
added = true;
|
added = true;
|
||||||
nodes.Add(node);
|
nodes.Insert(i, node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isSorted) continue;
|
||||||
|
|
||||||
|
if (n.Path.CompareTo(path) > 0) {
|
||||||
|
added = true;
|
||||||
|
nodes.Insert(i, node);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
for (int i = 0; i < nodes.Count; i++) {
|
if (isSorted) {
|
||||||
if (nodes[i].IsFolder) continue;
|
added = true;
|
||||||
if (nodes[i].Path.CompareTo(path) > 0) {
|
nodes.Add(node);
|
||||||
added = true;
|
} else {
|
||||||
nodes.Add(node);
|
for (int i = 0; i < nodes.Count; i++) {
|
||||||
break;
|
var n = nodes[i];
|
||||||
|
if (n.IsFolder) continue;
|
||||||
|
|
||||||
|
if (n.Path.CompareTo(path) > 0) {
|
||||||
|
added = true;
|
||||||
|
nodes.Insert(i, node);
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -266,17 +324,23 @@ namespace SourceGit.Views.Widgets {
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool RemoveTreeNode(ObservableCollection<ChangeNode> nodes, Models.Change change) {
|
private bool RemoveTreeNode(ObservableCollection<ChangeNode> nodes, string path) {
|
||||||
for (int i = nodes.Count - 1; i >= 0; i--) {
|
for (int i = nodes.Count - 1; i >= 0; i--) {
|
||||||
var node = nodes[i];
|
var node = nodes[i];
|
||||||
if (node.Change == null) {
|
if (node.IsFolder) {
|
||||||
if (RemoveTreeNode(node.Children, change)) {
|
if (path.IndexOf(node.Path, StringComparison.Ordinal) < 0) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (RemoveTreeNode(node.Children, path)) {
|
||||||
if (node.Children.Count == 0) nodes.RemoveAt(i);
|
if (node.Children.Count == 0) nodes.RemoveAt(i);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else if (node.Change.Path == change.Path) {
|
} else {
|
||||||
nodes.RemoveAt(i);
|
if (path.Equals(node.Path, StringComparison.Ordinal)) {
|
||||||
return true;
|
nodes.RemoveAt(i);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue