mirror of
https://gitlab.gnome.org/GNOME/gitg
synced 2024-09-29 20:53:40 +00:00
Implement preserving mainlines on history lanes
This commit is contained in:
parent
0886b19872
commit
15e441e773
|
@ -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;
|
||||
|
||||
var permanent = new Ggit.OId[0];
|
||||
|
||||
var seen = new Gee.HashSet<Ggit.OId>((Gee.HashDataFunc)Ggit.OId.hash,
|
||||
(Gee.EqualDataFunc)Ggit.OId.equal);
|
||||
|
||||
try
|
||||
{
|
||||
var head = id_for_ref(application.repository.get_head());
|
||||
|
||||
if (head != null)
|
||||
{
|
||||
permanent += head;
|
||||
seen.add(head);
|
||||
}
|
||||
} catch {}
|
||||
|
||||
foreach (var r in d_main.refs_list.selection)
|
||||
{
|
||||
try
|
||||
var id = id_for_ref(r);
|
||||
|
||||
if (id != null)
|
||||
{
|
||||
var resolved = r.resolve();
|
||||
Ggit.OId? id;
|
||||
|
||||
if (resolved.is_tag())
|
||||
{
|
||||
var t = application.repository.lookup<Ggit.Tag>(resolved.get_target());
|
||||
|
||||
id = t.get_target_id();
|
||||
}
|
||||
else
|
||||
{
|
||||
id = resolved.get_target();
|
||||
}
|
||||
|
||||
include += id;
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// Add the id
|
||||
if (d_ids.length == size)
|
||||
{
|
||||
lock(d_ids)
|
||||
{
|
||||
var oldlen = d_ids.length;
|
||||
|
||||
size *= 2;
|
||||
|
||||
d_ids.resize((int)size);
|
||||
d_ids.length = oldlen;
|
||||
}
|
||||
}
|
||||
|
||||
d_ids += commit;
|
||||
|
||||
int mylane;
|
||||
var lanes = d_lanes.next(commit, out mylane);
|
||||
SList<Lane> lanes;
|
||||
|
||||
commit.update_lanes((owned)lanes, mylane);
|
||||
if (d_lanes.next(commit, out lanes, out mylane))
|
||||
{
|
||||
commit.update_lanes((owned)lanes, mylane);
|
||||
|
||||
lock(d_id_hash)
|
||||
{
|
||||
d_id_hash.set(id, d_ids.length);
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
||||
return res;
|
||||
lanes = lanes_list();
|
||||
prepare_lanes(next, nextpos, hidden);
|
||||
|
||||
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);
|
||||
|
|
Loading…
Reference in a new issue