Skip to content

Commit

Permalink
Merge branch 'consecutive-negotiation'
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed May 18, 2023
2 parents 78d28a7 + 56f4d30 commit 4507f94
Show file tree
Hide file tree
Showing 42 changed files with 890 additions and 481 deletions.
18 changes: 5 additions & 13 deletions Cargo.lock

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

1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,6 @@ members = [
"cargo-smart-release",
"tests/tools",

"gix-revision/tests",
"gix-diff/tests",
"gix-pack/tests",
"gix-index/tests",
Expand Down
3 changes: 2 additions & 1 deletion crate-status.md
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,7 @@ Make it the best-performing implementation and the most convenient one.

### gix-revision
* [x] `describe()` (similar to `git name-rev`)
* [x] primitives to help with graph traversal, along with commit-graph acceleration.
* parse specifications
* [x] parsing and navigation
* [x] revision ranges
Expand Down Expand Up @@ -638,7 +639,7 @@ See its [README.md](https://github.com/Byron/gitoxide/blob/main/gix-lock/README.
* **Id**
* [x] short hashes with detection of ambiguity.
* **Commit**
* [x] `describe()` like functionality
* [x] `git describe` like functionality, with optional commit-graph acceleration
* [x] create new commit from tree
* **Objects**
* [x] lookup
Expand Down
3 changes: 1 addition & 2 deletions gitoxide-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,14 @@ async-client = ["gix/async-network-client-async-std", "gix-transport-configurati

#! ### Other
## Data structures implement `serde::Serialize` and `serde::Deserialize`.
serde = ["gix-commitgraph/serde", "gix/serde", "serde_json", "dep:serde", "bytesize/serde"]
serde = ["gix/serde", "serde_json", "dep:serde", "bytesize/serde"]


[dependencies]
# deselect everything else (like "performance") as this should be controllable by the parent application.
gix = { version = "^0.44.1", path = "../gix", default-features = false }
gix-pack-for-configuration-only = { package = "gix-pack", version = "^0.35.0", path = "../gix-pack", default-features = false, features = ["pack-cache-lru-dynamic", "pack-cache-lru-static"] }
gix-transport-configuration-only = { package = "gix-transport", version = "^0.31.0", path = "../gix-transport", default-features = false }
gix-commitgraph = { version = "^0.14.0", path = "../gix-commitgraph" }
serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"] }
anyhow = "1.0.42"
thiserror = "1.0.34"
Expand Down
8 changes: 4 additions & 4 deletions gitoxide-core/src/commitgraph/verify.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use std::{io, path::Path};

use anyhow::{Context as AnyhowContext, Result};
use gix_commitgraph::{graph::verify::Outcome, Graph};
use gix::commitgraph::Graph;

use crate::OutputFormat;

Expand Down Expand Up @@ -31,15 +31,15 @@ pub fn graph_or_file<W1, W2>(
mut out,
output_statistics,
}: Context<W1, W2>,
) -> Result<gix_commitgraph::graph::verify::Outcome>
) -> Result<gix::commitgraph::verify::Outcome>
where
W1: io::Write,
W2: io::Write,
{
let g = Graph::at(path).with_context(|| "Could not open commit graph")?;

#[allow(clippy::unnecessary_wraps, unknown_lints)]
fn noop_processor(_commit: &gix_commitgraph::file::Commit<'_>) -> std::result::Result<(), std::fmt::Error> {
fn noop_processor(_commit: &gix::commitgraph::file::Commit<'_>) -> std::result::Result<(), std::fmt::Error> {
Ok(())
}
let stats = g
Expand All @@ -57,7 +57,7 @@ where
Ok(stats)
}

fn print_human_output(out: &mut impl io::Write, stats: &Outcome) -> io::Result<()> {
fn print_human_output(out: &mut impl io::Write, stats: &gix::commitgraph::verify::Outcome) -> io::Result<()> {
writeln!(out, "number of commits with the given number of parents")?;
let mut parent_counts: Vec<_> = stats.parent_counts.iter().map(|(a, b)| (*a, *b)).collect();
parent_counts.sort_by_key(|e| e.0);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
use crate::{
file::{self, Commit, File},
graph::{self, Graph},
};
use crate::{file, file::Commit, File, Graph, Position};

/// Access
impl Graph {
/// Returns the commit at the given position `pos`.
///
/// # Panics
/// If `pos` is greater or equal to [`num_commits()`][Graph::num_commits()].
pub fn commit_at(&self, pos: graph::Position) -> Commit<'_> {
pub fn commit_at(&self, pos: Position) -> Commit<'_> {
let r = self.lookup_by_pos(pos);
r.file.commit_at(r.pos)
}
Expand All @@ -24,7 +21,7 @@ impl Graph {
///
/// # Panics
/// If `pos` is greater or equal to [`num_commits()`][Graph::num_commits()].
pub fn id_at(&self, pos: graph::Position) -> &gix_hash::oid {
pub fn id_at(&self, pos: Position) -> &gix_hash::oid {
let r = self.lookup_by_pos(pos);
r.file.id_at(r.pos)
}
Expand All @@ -40,7 +37,7 @@ impl Graph {
}

/// Translate the given `id` to its position in the file.
pub fn lookup(&self, id: impl AsRef<gix_hash::oid>) -> Option<graph::Position> {
pub fn lookup(&self, id: impl AsRef<gix_hash::oid>) -> Option<Position> {
Some(self.lookup_by_id(id.as_ref())?.graph_pos)
}

Expand All @@ -59,15 +56,15 @@ impl Graph {
return Some(LookupByIdResult {
file,
file_pos: lex_pos,
graph_pos: graph::Position(current_file_start + lex_pos.0),
graph_pos: Position(current_file_start + lex_pos.0),
});
}
current_file_start += file.num_commits();
}
None
}

fn lookup_by_pos(&self, pos: graph::Position) -> LookupByPositionResult<'_> {
fn lookup_by_pos(&self, pos: Position) -> LookupByPositionResult<'_> {
let mut remaining = pos.0;
for (file_index, file) in self.files.iter().enumerate() {
match remaining.checked_sub(file.num_commits()) {
Expand All @@ -88,7 +85,7 @@ impl Graph {
#[derive(Clone)]
struct LookupByIdResult<'a> {
pub file: &'a File,
pub graph_pos: graph::Position,
pub graph_pos: Position,
pub file_pos: file::Position,
}

Expand Down
5 changes: 4 additions & 1 deletion gix-commitgraph/src/file/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@ use std::{
path::Path,
};

use crate::file::{self, commit::Commit, File, COMMIT_DATA_ENTRY_SIZE_SANS_HASH};
use crate::{
file::{self, commit::Commit, COMMIT_DATA_ENTRY_SIZE_SANS_HASH},
File,
};

/// Access
impl File {
Expand Down
31 changes: 16 additions & 15 deletions gix-commitgraph/src/file/commit.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ use std::{
};

use crate::{
file::{self, File, EXTENDED_EDGES_MASK, LAST_EXTENDED_EDGE_MASK, NO_PARENT},
graph,
file::{self, EXTENDED_EDGES_MASK, LAST_EXTENDED_EDGE_MASK, NO_PARENT},
File, Position,
};

/// The error used in the [`file::commit`][self] module.
Expand All @@ -25,6 +25,7 @@ pub enum Error {
}

/// A commit as stored in a [`File`].
#[derive(Copy, Clone)]
pub struct Commit<'a> {
file: &'a File,
pos: file::Position,
Expand Down Expand Up @@ -72,11 +73,11 @@ impl<'a> Commit<'a> {
}

/// Returns an iterator over the parent positions for lookup in the owning [Graph][crate::Graph].
pub fn iter_parents(&'a self) -> impl Iterator<Item = Result<graph::Position, Error>> + 'a {
pub fn iter_parents(self) -> Parents<'a> {
// I didn't find a combinator approach that a) was as strict as ParentIterator, b) supported
// fuse-after-first-error behavior, and b) was significantly shorter or more understandable
// than ParentIterator. So here we are.
ParentIterator {
Parents {
commit_data: self,
state: ParentIteratorState::First,
}
Expand All @@ -88,7 +89,7 @@ impl<'a> Commit<'a> {
}

/// Returns the first parent of this commit.
pub fn parent1(&self) -> Result<Option<graph::Position>, Error> {
pub fn parent1(&self) -> Result<Option<Position>, Error> {
self.iter_parents().next().transpose()
}

Expand Down Expand Up @@ -127,13 +128,13 @@ impl<'a> PartialEq for Commit<'a> {
}

/// An iterator over parents of a [`Commit`].
pub struct ParentIterator<'a> {
commit_data: &'a Commit<'a>,
pub struct Parents<'a> {
commit_data: Commit<'a>,
state: ParentIteratorState<'a>,
}

impl<'a> Iterator for ParentIterator<'a> {
type Item = Result<graph::Position, Error>;
impl<'a> Iterator for Parents<'a> {
type Item = Result<Position, Error>;

fn next(&mut self) -> Option<Self::Item> {
let state = std::mem::replace(&mut self.state, ParentIteratorState::Exhausted);
Expand Down Expand Up @@ -221,7 +222,7 @@ enum ParentIteratorState<'a> {
#[derive(Clone, Copy, Debug)]
enum ParentEdge {
None,
GraphPosition(graph::Position),
GraphPosition(Position),
ExtraEdgeIndex(u32),
}

Expand All @@ -233,22 +234,22 @@ impl ParentEdge {
if raw & EXTENDED_EDGES_MASK != 0 {
ParentEdge::ExtraEdgeIndex(raw & !EXTENDED_EDGES_MASK)
} else {
ParentEdge::GraphPosition(graph::Position(raw))
ParentEdge::GraphPosition(Position(raw))
}
}
}

enum ExtraEdge {
Internal(graph::Position),
Last(graph::Position),
Internal(Position),
Last(Position),
}

impl ExtraEdge {
pub fn from_raw(raw: u32) -> Self {
if raw & LAST_EXTENDED_EDGE_MASK != 0 {
Self::Last(graph::Position(raw & !LAST_EXTENDED_EDGE_MASK))
Self::Last(Position(raw & !LAST_EXTENDED_EDGE_MASK))
} else {
Self::Internal(graph::Position(raw))
Self::Internal(Position(raw))
}
}
}
9 changes: 6 additions & 3 deletions gix-commitgraph/src/file/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,12 @@ use std::{
use bstr::ByteSlice;
use memmap2::Mmap;

use crate::file::{
ChunkId, File, BASE_GRAPHS_LIST_CHUNK_ID, COMMIT_DATA_CHUNK_ID, COMMIT_DATA_ENTRY_SIZE_SANS_HASH,
EXTENDED_EDGES_LIST_CHUNK_ID, FAN_LEN, HEADER_LEN, OID_FAN_CHUNK_ID, OID_LOOKUP_CHUNK_ID, SIGNATURE,
use crate::{
file::{
ChunkId, BASE_GRAPHS_LIST_CHUNK_ID, COMMIT_DATA_CHUNK_ID, COMMIT_DATA_ENTRY_SIZE_SANS_HASH,
EXTENDED_EDGES_LIST_CHUNK_ID, FAN_LEN, HEADER_LEN, OID_FAN_CHUNK_ID, OID_LOOKUP_CHUNK_ID, SIGNATURE,
},
File,
};

/// The error used in [`File::at()`].
Expand Down
37 changes: 7 additions & 30 deletions gix-commitgraph/src/file/mod.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,6 @@
//! Operations on a single commit-graph file.

use std::{
fmt::{Display, Formatter},
ops::Range,
path::PathBuf,
};

use memmap2::Mmap;
use std::fmt::{Display, Formatter};

pub use self::{commit::Commit, init::Error};

Expand All @@ -16,7 +10,7 @@ mod init;
pub mod verify;

const COMMIT_DATA_ENTRY_SIZE_SANS_HASH: usize = 16;
const FAN_LEN: usize = 256;
pub(crate) const FAN_LEN: usize = 256;
const HEADER_LEN: usize = 8;

const SIGNATURE: &[u8] = b"CGPH";
Expand All @@ -34,31 +28,14 @@ const NO_PARENT: u32 = 0x7000_0000;
const EXTENDED_EDGES_MASK: u32 = 0x8000_0000;
const LAST_EXTENDED_EDGE_MASK: u32 = 0x8000_0000;

/// A single commit-graph file.
///
/// All operations on a `File` are local to that graph file. Since a commit graph can span multiple
/// files, all interesting graph operations belong on [`Graph`][crate::Graph].
pub struct File {
base_graph_count: u8,
base_graphs_list_offset: Option<usize>,
commit_data_offset: usize,
data: Mmap,
extra_edges_list_range: Option<Range<usize>>,
fan: [u32; FAN_LEN],
oid_lookup_offset: usize,
path: PathBuf,
hash_len: usize,
object_hash: gix_hash::Kind,
}

/// The position of a given commit within a graph file, starting at 0.
///
/// Commits within a graph file are sorted in lexicographical order by OID; a commit's lexigraphical position
/// Commits within a graph file are sorted in lexicographical order by OID; a commit's lexicographical position
/// is its position in this ordering. If a commit graph spans multiple files, each file's commits
/// start at lexigraphical position 0, so it is unique across a single file but is not unique across
/// the whole commit graph. Each commit also has a graph position ([`graph::Position`][crate::graph::Position]),
/// which is unique /// across the whole commit graph. In order to avoid accidentally mixing lexigraphical positions with graph
/// positions, distinct types are used for each.
/// start at lexicographical position 0, so it is unique across a single file but is not unique across
/// the whole commit graph. Each commit also has a graph position ([`Position`][crate::Position]),
/// which is unique across the whole commit graph.
/// In order to avoid accidentally mixing lexicographical positions with graph positions, distinct types are used for each.
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
pub struct Position(pub u32);

Expand Down
5 changes: 1 addition & 4 deletions gix-commitgraph/src/file/verify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,7 @@ use std::{
path::Path,
};

use crate::{
file::{self, File},
GENERATION_NUMBER_INFINITY, GENERATION_NUMBER_MAX,
};
use crate::{file, File, GENERATION_NUMBER_INFINITY, GENERATION_NUMBER_MAX};

/// The error used in [`File::traverse()`].
#[derive(thiserror::Error, Debug)]
Expand Down
Loading

0 comments on commit 4507f94

Please sign in to comment.