Skip to content

Commit

Permalink
draw edges-to-missing
Browse files Browse the repository at this point in the history
  • Loading branch information
gulbanana committed Mar 19, 2024
1 parent ec01ed8 commit 04c1008
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 17 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
### Added
- Git remotes in the status bar, with push & fetch commands.
- "Create branch" command on revisions.
- Display edges to commits that aren't in the queried revset, by drawing a line to nowhere.
- New config option gg.queries.log-page-size.
- Miscellaneous design improvements.

Expand Down
6 changes: 4 additions & 2 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,20 @@ These changes may or may not be implemented in the future.
* perf: better solution to slow immutability check - jj-lib will have a revset contains cache soon
* feat: alternate drag modes for copy/duplicate, maybe for rebase-all-descendants
* feat: log multiselect
* feat: log enter key
* feat: log filters (find commits that change path etc)
* feat: file select/multiselect? large moves could be tedious otherwise. maybe file menu?
* feat: redo/undo stack
* feat: operation menu - restores or views?
* feat: sub-file hunk changes
* feat: diffs and/or difftool
* feat: resolve workflow
* feat: tags display & management
* feat: tags display (readonly, perhaps - look at jj support)
* feat: view commit ids in log (configurable?)
* feat: view repo at different ops (slider? entire pane?)
* feat: progress display (probably in statusbar); useful for git & snapshot
* feat: repo in title
* feat: finish branch management
* feat: structured op descs - want to be able to present them more nicely, extracting ids etc. tags?
- there's a request for this to be part of jj
* feat: more mutations
Expand All @@ -33,7 +36,6 @@ These changes may or may not be implemented in the future.
* feat: more settings
- log revsets
* design: decide whether to remove edit menu and maybe add others
* design: draw missing (edge-to-nowhere) graph nodes?
* design: consider common signature control
* epic: categorical expansion - trays, modals, pinned commits etc
* chore: windows codesigning will break in august 2024; needs a new approach
5 changes: 5 additions & 0 deletions src-tauri/src/messages/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -185,6 +185,11 @@ pub enum LogLine {
target: LogCoordinates,
indirect: bool,
},
ToMissing {
source: LogCoordinates,
target: LogCoordinates,
indirect: bool,
},
}

#[derive(Serialize, Debug)]
Expand Down
61 changes: 48 additions & 13 deletions src-tauri/src/worker/queries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use jj_lib::{
backend::{BackendError, CommitId},
matchers::EverythingMatcher,
merged_tree::TreeDiffStream,
repo::Repo,
revset::Revset,
revset_graph::{RevsetGraphEdge, RevsetGraphEdgeType, TopoGroupedRevsetGraphIterator},
rewrite,
Expand Down Expand Up @@ -78,6 +79,7 @@ impl<'a, 'b> QuerySession<'a, 'b> {
let mut rows: Vec<LogRow> = Vec::with_capacity(self.state.page_size); // output rows to draw
let mut row = self.state.next_row;
let max = row + self.state.page_size;
let root_id = self.ws.repo().store().root_commit_id().clone();

while let Some((commit_id, commit_edges)) = self.iter.next() {
// output lines to draw for the current row
Expand All @@ -88,14 +90,9 @@ impl<'a, 'b> QuerySession<'a, 'b> {
let mut stem_known_immutable = false;
let mut padding = 0; // used to offset the commit summary past some edges

for (slot, stem) in self.state.stems.iter().enumerate() {
if let Some(LogStem { target, .. }) = stem {
if *target == commit_id {
column = slot;
padding = self.state.stems.len() - column - 1;
break;
}
}
if let Some(slot) = self.find_stem_for_commit(&commit_id) {
column = slot;
padding = self.state.stems.len() - column - 1;
}

// terminate any existing stem, removing it from the end or leaving a gap
Expand Down Expand Up @@ -154,16 +151,23 @@ impl<'a, 'b> QuerySession<'a, 'b> {
.truncate(self.state.stems.len() - empty_stems);

// merge edges into existing stems or add new ones to the right
let mut next_missing: Option<CommitId> = None;
'edges: for edge in commit_edges.iter() {
if edge.edge_type == RevsetGraphEdgeType::Missing {
continue;
if edge.target == root_id {
continue;
} else {
next_missing = Some(edge.target.clone());
}
}

let indirect = edge.edge_type != RevsetGraphEdgeType::Direct;

for (slot, stem) in self.state.stems.iter().enumerate() {
if let Some(stem) = stem {
if stem.target == edge.target {
lines.push(LogLine::ToIntersection {
indirect: edge.edge_type == RevsetGraphEdgeType::Indirect,
indirect,
source: LogCoordinates(column, row),
target: LogCoordinates(slot, row + 1),
});
Expand All @@ -177,7 +181,7 @@ impl<'a, 'b> QuerySession<'a, 'b> {
*stem = Some(LogStem {
source: LogCoordinates(column, row),
target: edge.target.clone(),
indirect: edge.edge_type == RevsetGraphEdgeType::Indirect,
indirect,
was_inserted: true,
known_immutable: header.is_immutable,
});
Expand All @@ -188,7 +192,7 @@ impl<'a, 'b> QuerySession<'a, 'b> {
self.state.stems.push(Some(LogStem {
source: LogCoordinates(column, row),
target: edge.target.clone(),
indirect: edge.edge_type == RevsetGraphEdgeType::Indirect,
indirect,
was_inserted: false,
known_immutable: header.is_immutable,
}));
Expand All @@ -200,8 +204,27 @@ impl<'a, 'b> QuerySession<'a, 'b> {
padding,
lines,
});

row = row + 1;

// terminate any temporary stems created for missing edges
match next_missing
.take()
.and_then(|id| self.find_stem_for_commit(&id))
{
Some(slot) => {
if let Some(terminated_stem) = &self.state.stems[slot] {
rows.last_mut().unwrap().lines.push(LogLine::ToMissing {
indirect: terminated_stem.indirect,
source: LogCoordinates(column, row - 1),
target: LogCoordinates(slot, row),
});
}
self.state.stems[slot] = None;
row = row + 1;
}
None => (),
};

if row == max {
break;
}
Expand All @@ -213,6 +236,18 @@ impl<'a, 'b> QuerySession<'a, 'b> {
has_more: self.iter.peek().is_some(),
})
}

fn find_stem_for_commit(&self, id: &CommitId) -> Option<usize> {
for (slot, stem) in self.state.stems.iter().enumerate() {
if let Some(LogStem { target, .. }) = stem {
if target == id {
return Some(slot);
}
}
}

None
}
}

// XXX this is reloading the header, which the client already has
Expand Down
2 changes: 1 addition & 1 deletion src/LogPane.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@
let enhancedLine = line as EnhancedLine;
enhancedLine.key = lineKey++;
if (line.type == "ToIntersection") {
if (line.type == "ToIntersection" || line.type == "ToMissing") {
// ToIntersection lines begin at their owning row, so they run from this row to the next one that we read (which may not be on the same page)
enhancedLine.child = row.revision;
enhancedRow.passingLines.push(enhancedLine);
Expand Down
2 changes: 1 addition & 1 deletion src/messages/LogLine.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// This file was generated by [ts-rs](https://github.com/Aleph-Alpha/ts-rs). Do not edit this file manually.
import type { LogCoordinates } from "./LogCoordinates";

export type LogLine = { "type": "FromNode", source: LogCoordinates, target: LogCoordinates, indirect: boolean, } | { "type": "ToNode", source: LogCoordinates, target: LogCoordinates, indirect: boolean, } | { "type": "ToIntersection", source: LogCoordinates, target: LogCoordinates, indirect: boolean, };
export type LogLine = { "type": "FromNode", source: LogCoordinates, target: LogCoordinates, indirect: boolean, } | { "type": "ToNode", source: LogCoordinates, target: LogCoordinates, indirect: boolean, } | { "type": "ToIntersection", source: LogCoordinates, target: LogCoordinates, indirect: boolean, } | { "type": "ToMissing", source: LogCoordinates, target: LogCoordinates, indirect: boolean, };

0 comments on commit 04c1008

Please sign in to comment.