[gitg/mainlining: 1/4] Implement preserving mainlines on history lanes
- From: Jesse van den Kieboom <jessevdk src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gitg/mainlining: 1/4] Implement preserving mainlines on history lanes
- Date: Sun, 21 Dec 2014 20:17:24 +0000 (UTC)
commit 15e441e7733dd7d4e21fddf0b5b96340f7eaf4f3
Author: Jesse van den Kieboom <jessevdk gmail com>
Date: Sun Dec 21 19:33:33 2014 +0100
Implement preserving mainlines on history lanes
gitg/history/gitg-history.vala | 71 ++++++++++++++-----
libgitg/gitg-cell-renderer-lanes.vala | 34 ++++++++-
libgitg/gitg-commit-model.vala | 86 ++++++++++++++++++------
libgitg/gitg-lane.vala | 3 +-
libgitg/gitg-lanes.vala | 121 ++++++++++++++++++++++++++++-----
5 files changed, 253 insertions(+), 62 deletions(-)
---
diff --git a/gitg/history/gitg-history.vala b/gitg/history/gitg-history.vala
index 3869c06..d12fd05 100644
--- a/gitg/history/gitg-history.vala
+++ b/gitg/history/gitg-history.vala
@@ -504,42 +504,77 @@ namespace GitgHistory
return popup_menu_for_ref(references.first());
}
+ private Ggit.OId? id_for_ref(Ggit.Ref r)
+ {
+ Ggit.OId? id = null;
+
+ try
+ {
+ var resolved = r.resolve();
+
+ if (resolved.is_tag())
+ {
+ var t =
application.repository.lookup<Ggit.Tag>(resolved.get_target());
+
+ id = t.get_target_id();
+ }
+ else
+ {
+ id = resolved.get_target();
+ }
+ }
+ catch {}
+
+ return id;
+ }
+
private void update_walker()
{
d_selected.clear();
- var include = new Ggit.OId[0];
+ var include = new Gee.HashSet<Ggit.OId>((Gee.HashDataFunc)Ggit.OId.hash,
+ (Gee.EqualDataFunc)Ggit.OId.equal);
+
var isall = d_main.refs_list.is_all;
- foreach (var r in d_main.refs_list.selection)
+ var permanent = new Ggit.OId[0];
+
+ var seen = new Gee.HashSet<Ggit.OId>((Gee.HashDataFunc)Ggit.OId.hash,
+ (Gee.EqualDataFunc)Ggit.OId.equal);
+
+ try
{
- try
- {
- var resolved = r.resolve();
- Ggit.OId? id;
+ var head = id_for_ref(application.repository.get_head());
- if (resolved.is_tag())
- {
- var t =
application.repository.lookup<Ggit.Tag>(resolved.get_target());
+ if (head != null)
+ {
+ permanent += head;
+ seen.add(head);
+ }
+ } catch {}
- id = t.get_target_id();
- }
- else
- {
- id = resolved.get_target();
- }
+ foreach (var r in d_main.refs_list.selection)
+ {
+ var id = id_for_ref(r);
- include += id;
+ if (id != null)
+ {
+ include.add(id);
if (!isall)
{
d_selected.add(id);
+
+ if (seen.add(id))
+ {
+ permanent += id;
+ }
}
}
- catch {}
}
- d_commit_list_model.set_include(include);
+ d_commit_list_model.permanent_lanes = permanent;
+ d_commit_list_model.set_include(include.to_array());
d_commit_list_model.reload();
}
diff --git a/libgitg/gitg-cell-renderer-lanes.vala b/libgitg/gitg-cell-renderer-lanes.vala
index c3f5e6a..86f9c26 100644
--- a/libgitg/gitg-cell-renderer-lanes.vala
+++ b/libgitg/gitg-cell-renderer-lanes.vala
@@ -31,14 +31,34 @@ namespace Gitg
private delegate double DirectionFunc(double i);
- private uint num_lanes
+ private uint num_visible_lanes
{
- get { return commit.get_lanes().length(); }
+ get
+ {
+ int ret = 0;
+ int trailing_hidden = 0;
+
+ foreach (var lane in commit.get_lanes())
+ {
+ ++ret;
+
+ if ((lane.tag & LaneTag.HIDDEN) != 0)
+ {
+ trailing_hidden++;
+ }
+ else
+ {
+ trailing_hidden = 0;
+ }
+ }
+
+ return ret - trailing_hidden;
+ }
}
private uint total_width(Gtk.Widget widget)
{
- return num_lanes * lane_width +
+ return num_visible_lanes * lane_width +
LabelRenderer.width(widget, font_desc, labels);
}
@@ -117,6 +137,12 @@ namespace Gitg
foreach (var lane in commit.get_lanes())
{
+ if ((lane.tag & LaneTag.HIDDEN) != 0)
+ {
+ ++to;
+ continue;
+ }
+
var color = lane.color;
context.set_source_rgb(color.r, color.g, color.b);
@@ -203,7 +229,7 @@ namespace Gitg
{
int offset;
- offset = (int)(num_lanes * lane_width);
+ offset = (int)(num_visible_lanes * lane_width);
var rtl = (widget.get_style_context().get_state() & Gtk.StateFlags.DIR_RTL) != 0;
diff --git a/libgitg/gitg-commit-model.vala b/libgitg/gitg-commit-model.vala
index ba88f30..22f6ace 100644
--- a/libgitg/gitg-commit-model.vala
+++ b/libgitg/gitg-commit-model.vala
@@ -66,6 +66,7 @@ namespace Gitg
private Repository d_repository;
private Cancellable? d_cancellable;
private Commit[] d_ids;
+ private Commit[] d_hidden_ids;
private Thread<void*>? d_thread;
private Ggit.RevisionWalker? d_walker;
private uint d_advertized_size;
@@ -108,6 +109,8 @@ namespace Gitg
}
}
+ public Ggit.OId[] permanent_lanes { get; set; }
+
public signal void started();
public signal void update(uint added);
public signal void finished();
@@ -148,6 +151,7 @@ namespace Gitg
}
d_ids = new Commit[0];
+ d_hidden_ids = new Commit[0];
d_advertized_size = 0;
d_id_hash = new Gee.HashMap<Ggit.OId, int>();
@@ -247,6 +251,29 @@ namespace Gitg
});
}
+ private void resize_ids(ref Gitg.Commit[] ids, ref uint size)
+ {
+ if (ids.length == size)
+ {
+ lock(d_ids)
+ {
+ var oldlen = ids.length;
+
+ if (oldlen < 20000)
+ {
+ size *= 2;
+ }
+ else
+ {
+ size = (uint)((double)size * 1.2);
+ }
+
+ ids.resize((int)size);
+ ids.length = oldlen;
+ }
+ }
+ }
+
private async void walk()
{
Ggit.OId[] included = d_include;
@@ -273,11 +300,15 @@ namespace Gitg
d_walker.reset();
d_walker.set_sort_mode(d_sortmode);
+ var incset = new
Gee.HashSet<Ggit.OId>((Gee.HashDataFunc<Ggit.OId>)Ggit.OId.hash,
+
(Gee.EqualDataFunc<Ggit.OId>)Ggit.OId.equal);
+
foreach (Ggit.OId oid in included)
{
try
{
d_walker.push(oid);
+ incset.add(oid);
} catch {};
}
@@ -286,19 +317,38 @@ namespace Gitg
try
{
d_walker.hide(oid);
+ incset.remove(oid);
} catch {};
}
+ var permanent = new Ggit.OId[0];
+
+ foreach (Ggit.OId oid in permanent_lanes)
+ {
+ try
+ {
+ d_walker.push(oid);
+ permanent += oid;
+ } catch {}
+ }
+
+ d_lanes.reset(permanent, incset);
+
uint size;
+ uint hidden_size;
// Pre-allocate array to store commits
lock(d_ids)
{
d_ids = new Commit[1000];
+ d_hidden_ids = new Commit[100];
size = d_ids.length;
+ hidden_size = d_hidden_ids.length;
d_ids.length = 0;
+ d_hidden_ids.length = 0;
+
d_advertized_size = 0;
}
@@ -331,31 +381,26 @@ namespace Gitg
commit = d_repository.lookup<Commit>(id);
} catch { break; }
- lock(d_id_hash)
- {
- d_id_hash.set(id, d_ids.length);
- }
+ int mylane;
+ SList<Lane> lanes;
- // Add the id
- if (d_ids.length == size)
+ if (d_lanes.next(commit, out lanes, out mylane))
{
- lock(d_ids)
- {
- var oldlen = d_ids.length;
+ commit.update_lanes((owned)lanes, mylane);
- size *= 2;
-
- d_ids.resize((int)size);
- d_ids.length = oldlen;
+ lock(d_id_hash)
+ {
+ d_id_hash.set(id, d_ids.length);
}
- }
- d_ids += commit;
-
- int mylane;
- var lanes = d_lanes.next(commit, out mylane);
-
- commit.update_lanes((owned)lanes, mylane);
+ resize_ids(ref d_ids, ref size);
+ d_ids += commit;
+ }
+ else
+ {
+ resize_ids(ref d_hidden_ids, ref hidden_size);
+ d_hidden_ids += commit;
+ }
if (timer.elapsed() >= 200)
{
@@ -394,7 +439,6 @@ namespace Gitg
private void emit_started()
{
clear();
- d_lanes.reset();
started();
}
diff --git a/libgitg/gitg-lane.vala b/libgitg/gitg-lane.vala
index 65cd95b..f73841b 100644
--- a/libgitg/gitg-lane.vala
+++ b/libgitg/gitg-lane.vala
@@ -28,7 +28,8 @@ public enum LaneTag
END = 1 << 1,
SIGN_STASH = 1 << 2,
SIGN_STAGED = 1 << 3,
- SIGN_UNSTAGED = 1 << 4
+ SIGN_UNSTAGED = 1 << 4,
+ HIDDEN = 1 << 5
}
public class Lane : Object
diff --git a/libgitg/gitg-lanes.vala b/libgitg/gitg-lanes.vala
index f2d99f5..9194958 100644
--- a/libgitg/gitg-lanes.vala
+++ b/libgitg/gitg-lanes.vala
@@ -30,11 +30,12 @@ public class Lanes : Object
private SList<weak Commit> d_previous;
private Gee.LinkedList<LaneContainer> d_lanes;
private HashTable<Ggit.OId, CollapsedLane> d_collapsed;
+ private Gee.HashSet<Ggit.OId>? d_roots;
class LaneContainer
{
public Lane lane;
- public uint inactive;
+ public int inactive;
public Ggit.OId? from;
public Ggit.OId? to;
@@ -56,17 +57,40 @@ public class Lanes : Object
public void next(int index)
{
+ var hidden = is_hidden;
lane = lane.copy();
lane.tag = LaneTag.NONE;
lane.from = new SList<int>();
- lane.from.prepend(index);
- if (to != null)
+ if (!hidden)
+ {
+ lane.from.prepend(index);
+ }
+
+ is_hidden = hidden;
+
+ if (to != null && inactive >= 0)
{
++inactive;
}
}
+
+ public bool is_hidden
+ {
+ get { return (lane.tag & LaneTag.HIDDEN) != 0; }
+ set
+ {
+ if (value)
+ {
+ lane.tag |= LaneTag.HIDDEN;
+ }
+ else
+ {
+ lane.tag &= ~LaneTag.HIDDEN;
+ }
+ }
+ }
}
[Compact]
@@ -105,18 +129,35 @@ public class Lanes : Object
reset();
}
- public void reset()
+ public void reset(Ggit.OId[]? reserved = null,
+ Gee.HashSet<Ggit.OId>? roots = null)
{
d_previous = new SList<weak Commit>();
+
d_lanes = new Gee.LinkedList<LaneContainer>();
+ d_roots = roots;
Color.reset();
+ if (reserved != null)
+ {
+ foreach (var r in reserved)
+ {
+ var ct = new LaneContainer(null, r);
+ ct.inactive = -1;
+ ct.is_hidden = true;
+
+ d_lanes.add(ct);
+ }
+ }
+
d_collapsed.remove_all();
+ d_previous = new SList<weak Commit>();
}
- public SList<Lane> next(Commit next,
- out int nextpos)
+ public bool next(Commit next,
+ out SList<Lane> lanes,
+ out int nextpos)
{
var myoid = next.get_id();
@@ -128,10 +169,18 @@ public class Lanes : Object
LaneContainer? mylane = find_lane_by_oid(myoid, out nextpos);
+ if (mylane == null && d_roots != null && !d_roots.contains(myoid))
+ {
+ lanes = null;
+ return false;
+ }
+
if (mylane == null)
{
- // there is no lane reserver for this comit, add a new lane
- d_lanes.add(new LaneContainer(myoid, null));
+ // there is no lane reserved for this commit, add a new lane
+ mylane = new LaneContainer(myoid, null);
+
+ d_lanes.add(mylane);
nextpos = (int)d_lanes.size - 1;
}
else
@@ -141,16 +190,28 @@ public class Lanes : Object
mylane.to = null;
mylane.from = next.get_id();
- mylane.inactive = 0;
+
+ if (mylane.is_hidden && d_roots != null && d_roots.contains(myoid))
+ {
+ mylane.is_hidden = false;
+ mylane.lane.from = new SList<int>();
+ }
+
+ if (mylane.inactive >= 0)
+ {
+ mylane.inactive = 0;
+ }
}
- var res = lanes_list();
- prepare_lanes(next, nextpos);
+ var hidden = mylane.is_hidden;
+
+ lanes = lanes_list();
+ prepare_lanes(next, nextpos, hidden);
- return res;
+ return !hidden;
}
- private void prepare_lanes(Commit next, int pos)
+ private void prepare_lanes(Commit next, int pos, bool hidden)
{
var parents = next.get_parents();
var myoid = next.get_id();
@@ -177,18 +238,42 @@ public class Lanes : Object
// our lane instead.
mylane.to = poid;
mylane.from = myoid;
- mylane.lane.from.append(lnpos);
+
+ if (!container.is_hidden)
+ {
+ mylane.lane.from.append(lnpos);
+ mylane.is_hidden = false;
+ }
+
mylane.lane.color = mylane.lane.color.copy();
- mylane.inactive = 0;
+
+ if (mylane.inactive >= 0)
+ {
+ mylane.inactive = 0;
+ }
d_lanes.remove(container);
}
else
{
container.from = myoid;
- container.lane.from.append(pos);
+
+ if (!hidden)
+ {
+ container.lane.from.append(pos);
+ }
+
container.lane.color = container.lane.color.copy();
- container.inactive = 0;
+
+ if (!hidden)
+ {
+ container.is_hidden = false;
+ }
+
+ if (container.inactive >= 0)
+ {
+ container.inactive = 0;
+ }
}
continue;
@@ -201,7 +286,7 @@ public class Lanes : Object
mylane.lane.color = mylane.lane.color.copy();
}
- else
+ else if (!hidden)
{
// generate a new lane for this parent
var newlane = new LaneContainer(myoid, poid);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]