Skip to content

Add topological walk #1336

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

Merged
merged 18 commits into from
Apr 7, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion examples/log.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ use clap::Parser;
use gix::{
bstr::{BString, ByteSlice},
date::time::format,
traverse::commit::Sorting,
traverse::commit::simple::Sorting,
};

fn main() {
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/hours/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ where
}
commit_idx += 1;
}
Err(gix::traverse::commit::ancestors::Error::Find { .. }) => {
Err(gix::traverse::commit::simple::Error::Find { .. }) => {
is_shallow = true;
break;
}
Expand Down
10 changes: 5 additions & 5 deletions gitoxide-core/src/index/information.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ pub struct Options {

#[cfg(feature = "serde")]
mod serde_only {
use gix::index::entry::Stage;

mod ext {
#[derive(serde::Serialize)]
Expand Down Expand Up @@ -115,11 +116,10 @@ mod serde_only {
let (mut intent_to_add, mut skip_worktree) = (0, 0);
for entry in f.entries() {
match entry.flags.stage() {
0 => stage_0_merged += 1,
1 => stage_1_base += 1,
2 => stage_2_ours += 1,
3 => stage_3_theirs += 1,
invalid => anyhow::bail!("Invalid stage {} encountered", invalid),
Stage::Unconflicted => stage_0_merged += 1,
Stage::Base => stage_1_base += 1,
Stage::Ours => stage_2_ours += 1,
Stage::Theirs => stage_3_theirs += 1,
}
match entry.mode {
gix::index::entry::Mode::DIR => dir += 1,
Expand Down
4 changes: 2 additions & 2 deletions gitoxide-core/src/pack/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,7 @@ where
.collect::<Result<Vec<_>, _>>()?;
let handle = repo.objects.into_shared_arc().to_cache_arc();
let iter = Box::new(
traverse::commit::Ancestors::new(tips, traverse::commit::ancestors::State::default(), handle.clone())
traverse::commit::Simple::new(tips, handle.clone())
.map(|res| res.map_err(|err| Box::new(err) as Box<_>).map(|c| c.id))
.inspect(move |_| progress.inc()),
);
Expand Down Expand Up @@ -361,7 +361,7 @@ pub mod input_iteration {
#[derive(Debug, thiserror::Error)]
pub enum Error {
#[error("input objects couldn't be iterated completely")]
Iteration(#[from] traverse::commit::ancestors::Error),
Iteration(#[from] traverse::commit::simple::Error),
#[error("An error occurred while reading hashes from standard input")]
InputLinesIo(#[from] std::io::Error),
#[error("Could not decode hex hash provided on standard input")]
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/query/engine/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -429,7 +429,7 @@ pub fn update(
break;
}
}
Err(gix::traverse::commit::ancestors::Error::Find { .. }) => {
Err(gix::traverse::commit::simple::Error::Find { .. }) => {
writeln!(err, "shallow repository - commit history is truncated").ok();
break;
}
Expand Down
7 changes: 7 additions & 0 deletions gitoxide-core/src/repository/attributes/validate_baseline.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,13 +262,18 @@ pub(crate) mod function {
}

#[derive(Debug)]
// See note on `Mismatch`
#[allow(dead_code)]
pub struct ExcludeLocation {
pub line: usize,
pub rela_source_file: String,
pub pattern: String,
}

#[derive(Debug)]
// We debug-print this structure, which makes all fields 'used', but it doesn't count.
// TODO: find a way to not have to do more work, but make the warning go away.
#[allow(dead_code)]
pub enum Mismatch {
Attributes {
actual: Vec<gix::attrs::Assignment>,
Expand All @@ -281,6 +286,8 @@ pub(crate) mod function {
}

#[derive(Debug)]
// See note on `Mismatch`
#[allow(dead_code)]
pub struct ExcludeMatch {
pub pattern: gix::glob::Pattern,
pub source: Option<PathBuf>,
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/commitgraph/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ pub(crate) mod function {
use std::{borrow::Cow, ffi::OsString};

use anyhow::{bail, Context};
use gix::{prelude::ObjectIdExt, traverse::commit::Sorting};
use gix::{prelude::ObjectIdExt, traverse::commit::simple::Sorting};

use crate::OutputFormat;

Expand Down
10 changes: 5 additions & 5 deletions gitoxide-core/src/repository/index/entries.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ pub(crate) mod function {
io::{BufWriter, Write},
};

use gix::index::entry::Stage;
use gix::{
bstr::{BStr, BString},
worktree::IndexPersistedOrInMemory,
Expand Down Expand Up @@ -392,11 +393,10 @@ pub(crate) mod function {
out,
"{} {}{:?} {} {}{}{}",
match entry.flags.stage() {
0 => " ",
1 => "BASE ",
2 => "OURS ",
3 => "THEIRS ",
_ => "UNKNOWN",
Stage::Unconflicted => " ",
Stage::Base => "BASE ",
Stage::Ours => "OURS ",
Stage::Theirs => "THEIRS ",
},
if entry.flags.is_empty() {
"".to_string()
Expand Down
2 changes: 1 addition & 1 deletion gitoxide-core/src/repository/revision/list.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ pub const PROGRESS_RANGE: std::ops::RangeInclusive<u8> = 0..=2;

pub(crate) mod function {
use anyhow::{bail, Context};
use gix::{hashtable::HashMap, traverse::commit::Sorting, Progress};
use gix::{hashtable::HashMap, traverse::commit::simple::Sorting, Progress};
use layout::{
backends::svg::SVGWriter,
core::{base::Orientation, geometry::Point, style::StyleAttr},
Expand Down
2 changes: 1 addition & 1 deletion gix-config/src/file/impls.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ impl<'a> TryFrom<&'a BStr> for File<'a> {

impl From<File<'_>> for BString {
fn from(c: File<'_>) -> Self {
c.into()
c.to_bstring()
}
}

Expand Down
9 changes: 8 additions & 1 deletion gix-config/src/file/includes/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,14 @@ fn append_followed_includes_recursively(
}

buf.clear();
std::io::copy(&mut std::fs::File::open(&config_path)?, buf)?;
std::io::copy(
&mut std::fs::File::open(&config_path).map_err(|err| Error::Io {
source: err,
path: config_path.to_owned(),
})?,
buf,
)
.map_err(Error::CopyBuffer)?;
let config_meta = Metadata {
path: Some(config_path),
trust: meta.trust,
Expand Down
7 changes: 5 additions & 2 deletions gix-config/src/file/includes/types.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use crate::{parse, path::interpolate};
use std::path::PathBuf;

/// The error returned when following includes.
#[derive(Debug, thiserror::Error)]
#[allow(missing_docs)]
pub enum Error {
#[error(transparent)]
Io(#[from] std::io::Error),
#[error("Failed to copy configuration file into buffer")]
CopyBuffer(#[source] std::io::Error),
#[error("Could not read included configuration file at '{}'", path.display())]
Io { path: PathBuf, source: std::io::Error },
#[error(transparent)]
Parse(#[from] parse::Error),
#[error(transparent)]
Expand Down
2 changes: 1 addition & 1 deletion gix-config/src/parse/comment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ impl Display for Comment<'_> {

impl From<Comment<'_>> for BString {
fn from(c: Comment<'_>) -> Self {
c.into()
c.to_bstring()
}
}

Expand Down
2 changes: 1 addition & 1 deletion gix-config/src/parse/event.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ impl Display for Event<'_> {

impl From<Event<'_>> for BString {
fn from(event: Event<'_>) -> Self {
event.into()
event.to_bstring()
}
}

Expand Down
2 changes: 1 addition & 1 deletion gix-config/src/parse/section/header.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ impl Display for Header<'_> {

impl From<Header<'_>> for BString {
fn from(header: Header<'_>) -> Self {
header.into()
header.to_bstring()
}
}

Expand Down
3 changes: 1 addition & 2 deletions gix-diff/tests/tree/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,11 +129,10 @@ mod changes {
}

fn all_commits(db: &gix_odb::Handle) -> HashMap<String, ObjectId> {
use gix_traverse::commit;
let mut buf = Vec::new();

let head = head_of(db);
commit::Ancestors::new(Some(head), commit::ancestors::State::default(), &db)
gix_traverse::commit::Simple::new(Some(head), &db)
.collect::<Result<Vec<_>, _>>()
.expect("valid iteration")
.into_iter()
Expand Down
19 changes: 10 additions & 9 deletions gix-index/src/access/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use std::{cmp::Ordering, ops::Range};
use bstr::{BStr, ByteSlice, ByteVec};
use filetime::FileTime;

use crate::entry::{Stage, StageRaw};
use crate::{entry, extension, AccelerateLookup, Entry, PathStorage, PathStorageRef, State, Version};

// TODO: integrate this somehow, somewhere, depending on later usage.
Expand Down Expand Up @@ -81,7 +82,7 @@ impl State {
res
})
.ok()?;
self.entry_index_by_idx_and_stage(path, idx, stage, stage_cmp)
self.entry_index_by_idx_and_stage(path, idx, stage as StageRaw, stage_cmp)
}

/// Walk as far in `direction` as possible, with [`Ordering::Greater`] towards higher stages, and [`Ordering::Less`]
Expand Down Expand Up @@ -112,7 +113,7 @@ impl State {
&self,
path: &BStr,
idx: usize,
wanted_stage: entry::Stage,
wanted_stage: entry::StageRaw,
stage_cmp: Ordering,
) -> Option<usize> {
match stage_cmp {
Expand All @@ -121,15 +122,15 @@ impl State {
.enumerate()
.rev()
.take_while(|(_, e)| e.path(self) == path)
.find_map(|(idx, e)| (e.stage() == wanted_stage).then_some(idx)),
.find_map(|(idx, e)| (e.stage_raw() == wanted_stage).then_some(idx)),
Ordering::Equal => Some(idx),
Ordering::Less => self
.entries
.get(idx + 1..)?
.iter()
.enumerate()
.take_while(|(_, e)| e.path(self) == path)
.find_map(|(ofs, e)| (e.stage() == wanted_stage).then_some(idx + ofs + 1)),
.find_map(|(ofs, e)| (e.stage_raw() == wanted_stage).then_some(idx + ofs + 1)),
}
}

Expand Down Expand Up @@ -291,15 +292,15 @@ impl State {
.binary_search_by(|e| {
let res = e.path(self).cmp(path);
if res.is_eq() {
stage_at_index = e.stage();
stage_at_index = e.stage_raw();
}
res
})
.ok()?;
let idx = if stage_at_index == 0 || stage_at_index == 2 {
idx
} else {
self.entry_index_by_idx_and_stage(path, idx, 2, stage_at_index.cmp(&2))?
self.entry_index_by_idx_and_stage(path, idx, Stage::Ours as StageRaw, stage_at_index.cmp(&2))?
};
Some(&self.entries[idx])
}
Expand Down Expand Up @@ -334,13 +335,13 @@ impl State {
+ self.entries[low..].partition_point(|e| e.path(self).get(..prefix_len).map_or(false, |p| p <= prefix));

let low_entry = &self.entries.get(low)?;
if low_entry.stage() != 0 {
if low_entry.stage_raw() != 0 {
low = self
.walk_entry_stages(low_entry.path(self), low, Ordering::Less)
.unwrap_or(low);
}
if let Some(high_entry) = self.entries.get(high) {
if high_entry.stage() != 0 {
if high_entry.stage_raw() != 0 {
high = self
.walk_entry_stages(high_entry.path(self), high, Ordering::Less)
.unwrap_or(high);
Expand Down Expand Up @@ -374,7 +375,7 @@ impl State {
.binary_search_by(|e| {
let res = e.path(self).cmp(path);
if res.is_eq() {
stage_at_index = e.stage();
stage_at_index = e.stage_raw();
}
res
})
Expand Down
17 changes: 17 additions & 0 deletions gix-index/src/entry/flags.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,23 @@ bitflags! {
impl Flags {
/// Return the stage as extracted from the bits of this instance.
pub fn stage(&self) -> Stage {
match self.stage_raw() {
0 => Stage::Unconflicted,
1 => Stage::Base,
2 => Stage::Ours,
3 => Stage::Theirs,
_ => unreachable!("BUG: Flags::STAGE_MASK is two bits, whose 4 possible values we have covered"),
}
}

/// Return an entry's stage as raw number between 0 and 4.
/// Possible values are:
///
/// * 0 = no conflict,
/// * 1 = base,
/// * 2 = ours,
/// * 3 = theirs
pub fn stage_raw(&self) -> u32 {
(*self & Flags::STAGE_MASK).bits() >> 12
}

Expand Down
29 changes: 27 additions & 2 deletions gix-index/src/entry/mod.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,23 @@
/// The stage of an entry, one of…
/// The stage of an entry.
#[derive(Default, Copy, Clone, Debug, PartialEq, Eq, Ord, PartialOrd, Hash)]
pub enum Stage {
/// This is the default, and most entries are in this stage.
#[default]
Unconflicted = 0,
/// The entry is the common base between 'our' change and 'their' change, for comparison.
Base = 1,
/// The entry represents our change.
Ours = 2,
/// The entry represents their change.
Theirs = 3,
}

// The stage of an entry, one of…
/// * 0 = no conflict,
/// * 1 = base,
/// * 2 = ours,
/// * 3 = theirs
pub type Stage = u32;
pub type StageRaw = u32;

///
#[allow(clippy::empty_docs)]
Expand Down Expand Up @@ -78,6 +92,17 @@ mod access {
pub fn stage(&self) -> entry::Stage {
self.flags.stage()
}

/// Return an entry's stage as raw number between 0 and 4.
/// Possible values are:
///
/// * 0 = no conflict,
/// * 1 = base,
/// * 2 = ours,
/// * 3 = theirs
pub fn stage_raw(&self) -> u32 {
self.flags.stage_raw()
}
}
}

Expand Down
1 change: 1 addition & 0 deletions gix-index/src/extension/fs_monitor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ use crate::{
};

#[derive(Clone)]
#[allow(dead_code)]
pub enum Token {
V1 { nanos_since_1970: u64 },
V2 { token: BString },
Expand Down
Loading