-
-
Notifications
You must be signed in to change notification settings - Fork 702
Branching #2890
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
Open
philocalyst
wants to merge
27
commits into
gitui-org:master
Choose a base branch
from
philocalyst:branching
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Branching #2890
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
e91b688
add: graph glyphs
philocalyst 72105f0
fix: moving to graph glyphs that fit GITUIs style more
philocalyst 6956349
add: buffer datastructure to hold graph representation
philocalyst cb5229f
add: buffer methods to facilitate updates against the graph
philocalyst bf2a36f
add: chunk datastructure
philocalyst 5458042
Connecting all of the modules together
philocalyst 7547363
add: connection type
philocalyst a663bc8
add: graphrow datatype
philocalyst f3c01bb
add: OIDS wrapper type
philocalyst 6cf99d8
add: core walker datastructure to stream process
philocalyst 577d1ad
add: walker methods
philocalyst 58d9fd0
refactor: extending the datatypes to work with the graph model
philocalyst a837bf9
incorporating the graph model into revlog and lib
philocalyst a7685a4
addition: key toggle for the graph view
philocalyst a4ccd6a
additions to revlog to support the graph view
philocalyst b802e10
addition: toggle graph to keybinds
philocalyst 4798d51
incoporated graph view with the commitlist
philocalyst 57bff13
Incoportaed the graph view
philocalyst 5619286
fixed refactor-related errs
philocalyst a45eef6
Now reusing lanes to remove whitespace
philocalyst 42a7bba
Formatting
philocalyst a4283bc
unit test #1
philocalyst 40a5cfc
fmt
philocalyst fb09f56
Added changelog entry
philocalyst d4c858b
Fixed clippy lints
philocalyst e74d481
More clippy lints
philocalyst 0b2bb3e
Fixed more clippy lints
philocalyst File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,235 @@ | ||
| use super::chunk::{Chunk, Markers}; | ||
| use im::Vector; | ||
| use std::collections::BTreeMap; | ||
|
|
||
| #[derive(Clone, Debug)] | ||
| pub enum DeltaOp { | ||
| Insert { index: usize, item: Option<Chunk> }, | ||
| Remove { index: usize }, | ||
| Replace { index: usize, new: Option<Chunk> }, | ||
| } | ||
|
|
||
| #[derive(Clone, Debug)] | ||
| pub struct Delta(pub Vec<DeltaOp>); | ||
|
|
||
| const CHECKPOINT_INTERVAL: usize = 100; | ||
|
|
||
| pub struct Buffer { | ||
| pub current: Vector<Option<Chunk>>, | ||
| pub deltas: Vec<Delta>, | ||
| pub checkpoints: BTreeMap<usize, Vector<Option<Chunk>>>, | ||
| mergers: Vec<u32>, | ||
| pending_delta: Vec<DeltaOp>, | ||
| } | ||
|
|
||
| impl Default for Buffer { | ||
| fn default() -> Self { | ||
| Self::new() | ||
| } | ||
| } | ||
|
|
||
| impl Buffer { | ||
| pub fn new() -> Self { | ||
| Self { | ||
| current: Vector::new(), | ||
| deltas: Vec::new(), | ||
| checkpoints: BTreeMap::new(), | ||
| mergers: Vec::new(), | ||
| pending_delta: Vec::new(), | ||
| } | ||
| } | ||
|
|
||
| pub fn merger(&mut self, alias: u32) { | ||
| self.mergers.push(alias); | ||
| } | ||
|
|
||
| pub fn update(&mut self, new_chunk: &Chunk) { | ||
| self.pending_delta.clear(); | ||
|
|
||
| let mut empty_lanes: Vec<usize> = self | ||
| .current | ||
| .iter() | ||
| .enumerate() | ||
| .filter_map(|(i, c)| c.is_none().then_some(i)) | ||
| .collect(); | ||
|
|
||
| // sort descending so we can pop the lowest index first | ||
| empty_lanes.sort_unstable_by(|a, b| b.cmp(a)); | ||
|
|
||
| let found_idx = if new_chunk.alias.is_some() { | ||
| self.current.iter().enumerate().find_map(|(i, c)| { | ||
| c.as_ref().and_then(|c| { | ||
| (c.parent_a == new_chunk.alias).then_some(i) | ||
| }) | ||
| }) | ||
| } else { | ||
| None | ||
| }; | ||
|
|
||
| if let Some(idx) = found_idx { | ||
| self.record_replace(idx, Some(new_chunk.clone())); | ||
| } else if let Some(empty_idx) = empty_lanes.pop() { | ||
| self.record_replace(empty_idx, Some(new_chunk.clone())); | ||
| } else { | ||
| self.record_insert( | ||
| self.current.len(), | ||
| Some(new_chunk.clone()), | ||
| ); | ||
| } | ||
|
|
||
| let current_length = self.current.len(); | ||
| for index in 0..current_length { | ||
| if Some(index) == found_idx { | ||
| continue; | ||
| } | ||
| if found_idx.is_none() && index == current_length - 1 { | ||
| continue; | ||
| } | ||
|
|
||
| if let Some(mut c) = self.current[index].clone() { | ||
| let changed = new_chunk.alias.is_some_and(|alias| { | ||
| let a = c.parent_a == Some(alias); | ||
| let b = c.parent_b == Some(alias); | ||
| if a { | ||
| c.parent_a = None; | ||
| } | ||
| if b { | ||
| c.parent_b = None; | ||
| } | ||
| a || b | ||
| }); | ||
|
|
||
| if changed { | ||
| if c.parent_a.is_none() && c.parent_b.is_none() { | ||
| self.record_replace(index, None); | ||
| } else { | ||
| self.record_replace(index, Some(c)); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| while let Some(alias) = self.mergers.pop() { | ||
| if let Some(index) = self.current.iter().position(|c| { | ||
| c.as_ref() | ||
| .is_some_and(|chunk| chunk.alias == Some(alias)) | ||
| }) { | ||
| if let Some(mut c) = self.current[index].clone() { | ||
| let parent_b = c.parent_b; | ||
| c.parent_b = None; | ||
| self.record_replace(index, Some(c)); | ||
|
|
||
| let new_lane = Chunk { | ||
| alias: None, | ||
| parent_a: parent_b, | ||
| parent_b: None, | ||
| marker: Markers::Commit, | ||
| }; | ||
|
|
||
| if let Some(empty_idx) = empty_lanes.pop() { | ||
| self.record_replace( | ||
| empty_idx, | ||
| Some(new_lane), | ||
| ); | ||
| } else { | ||
| self.record_insert( | ||
| self.current.len(), | ||
| Some(new_lane), | ||
| ); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
| while self.current.last().is_some_and(Option::is_none) { | ||
| self.record_remove(self.current.len() - 1); | ||
| } | ||
|
|
||
| let delta = Delta(self.pending_delta.clone()); | ||
| self.deltas.push(delta); | ||
|
|
||
| let current_step = self.deltas.len(); | ||
| if current_step > 0 && current_step % CHECKPOINT_INTERVAL == 0 | ||
| { | ||
| self.checkpoints | ||
| .insert(current_step - 1, self.current.clone()); | ||
| } | ||
| } | ||
|
|
||
| fn record_replace(&mut self, index: usize, new: Option<Chunk>) { | ||
| self.pending_delta.push(DeltaOp::Replace { | ||
| index, | ||
| new: new.clone(), | ||
| }); | ||
| self.current.set(index, new); | ||
| } | ||
|
|
||
| fn record_insert(&mut self, index: usize, item: Option<Chunk>) { | ||
| self.pending_delta.push(DeltaOp::Insert { | ||
| index, | ||
| item: item.clone(), | ||
| }); | ||
| self.current.insert(index, item); | ||
| } | ||
|
|
||
| fn record_remove(&mut self, index: usize) { | ||
| self.pending_delta.push(DeltaOp::Remove { index }); | ||
| self.current.remove(index); | ||
| } | ||
|
|
||
| pub fn decompress( | ||
| &self, | ||
| start: usize, | ||
| end: usize, | ||
| ) -> Vec<Vector<Option<Chunk>>> { | ||
| let (current_index, mut state) = | ||
| self.checkpoints.range(..=start).next_back().map_or_else( | ||
| || (None, Vector::new()), | ||
| |(&i, s)| (Some(i), s.clone()), | ||
| ); | ||
|
|
||
| let mut history = | ||
| Vec::with_capacity(end.saturating_sub(start) + 1); | ||
|
|
||
| if let Some(index) = current_index { | ||
| if index >= start && index <= end { | ||
| history.push(state.clone()); | ||
| } | ||
| } | ||
|
|
||
| let loop_start = current_index.map_or(0, |i| i + 1); | ||
|
|
||
| for delta_index in loop_start..=end { | ||
| if let Some(delta) = self.deltas.get(delta_index) { | ||
| Self::apply_delta_to_state(&mut state, delta); | ||
|
|
||
| if delta_index >= start { | ||
| history.push(state.clone()); | ||
| } | ||
| } else { | ||
| break; | ||
| } | ||
| } | ||
|
|
||
| history | ||
| } | ||
|
|
||
| fn apply_delta_to_state( | ||
| state: &mut Vector<Option<Chunk>>, | ||
| delta: &Delta, | ||
| ) { | ||
| for op in &delta.0 { | ||
| match op { | ||
| DeltaOp::Insert { index, item } => { | ||
| state.insert(*index, item.clone()); | ||
| } | ||
| DeltaOp::Remove { index } => { | ||
| state.remove(*index); | ||
| } | ||
| DeltaOp::Replace { index, new } => { | ||
| state.set(*index, new.clone()); | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| #[derive(Clone, Debug, PartialEq, Eq)] | ||
| pub enum Markers { | ||
| Uncommitted, | ||
| Commit, | ||
| } | ||
|
|
||
| #[derive(Clone, Debug)] | ||
| pub struct Chunk { | ||
| pub alias: Option<u32>, | ||
| pub parent_a: Option<u32>, | ||
| pub parent_b: Option<u32>, | ||
| pub marker: Markers, | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
please match the ususal format