Skip to content

Commit

Permalink
Merge branch 'index-information'
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Jan 24, 2022
2 parents 1feb118 + 3541e33 commit 025f157
Show file tree
Hide file tree
Showing 18 changed files with 467 additions and 84 deletions.
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 git-bitmap/src/ewah.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,6 @@ mod access {
pub struct Vec {
num_bits: u32,
bits: std::vec::Vec<u64>,
/// RLW is an offset into the `bits` buffer, so `1` translates into &bits[1] essentially.
/// RLW is an offset into the `bits` buffer, so `1` translates into &bits\[1] essentially.
rlw: usize,
}
8 changes: 8 additions & 0 deletions git-hash/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,14 @@ impl FromStr for Kind {
}
}

impl std::fmt::Display for Kind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Kind::Sha1 => f.write_str("SHA1"),
}
}
}

impl Kind {
/// Returns the shortest hash we support
#[inline]
Expand Down
2 changes: 1 addition & 1 deletion git-index/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ path = "tests/index-single-threaded.rs"
required-features = ["internal-testing-to-avoid-being-run-by-cargo-test-all"]

[features]
serde1 = ["serde"]
serde1 = ["serde", "smallvec/serde", "git-hash/serde1"]

internal-testing-git-features-parallel = ["git-features/parallel"]
internal-testing-to-avoid-being-run-by-cargo-test-all = []
Expand Down
11 changes: 11 additions & 0 deletions git-index/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ pub(crate) mod at_rest {
bitflags! {
/// In-memory flags
pub struct Flags: u32 {
const STAGE_MASK = 0x3000;
// TODO: could we use the pathlen ourselves to save 8 bytes? And how to handle longer paths than that? 0 as sentinel maybe?
const PATH_LEN = 0x0fff;
const UPDATE = 1 << 16;
Expand Down Expand Up @@ -88,11 +89,21 @@ bitflags! {
}
}

impl Flags {
pub fn stage(&self) -> u32 {
(*self & Flags::STAGE_MASK).bits >> 12
}
}

#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Copy)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub struct Time {
pub secs: u32,
pub nsecs: u32,
}

#[derive(PartialEq, Eq, Hash, Ord, PartialOrd, Clone, Copy)]
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub struct Stat {
pub mtime: Time,
pub ctime: Time,
Expand Down
37 changes: 37 additions & 0 deletions git-index/src/extension/fs_monitor.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
use bstr::BString;

use crate::{
extension::{FsMonitor, Signature},
util::{read_u32, read_u64, split_at_byte_exclusive},
};

pub enum Token {
V1 { nanos_since_1970: u64 },
V2 { token: BString },
}

pub const SIGNATURE: Signature = *b"FSMN";

pub fn decode(data: &[u8]) -> Option<FsMonitor> {
let (version, data) = read_u32(data)?;
let (token, data) = match version {
1 => {
let (nanos_since_1970, data) = read_u64(data)?;
(Token::V1 { nanos_since_1970 }, data)
}
2 => {
let (token, data) = split_at_byte_exclusive(data, 0)?;
(Token::V2 { token: token.into() }, data)
}
_ => return None,
};

let (ewah_size, data) = read_u32(data)?;
let (entry_dirty, data) = git_bitmap::ewah::decode(&data[..ewah_size as usize]).ok()?;

if !data.is_empty() {
return None;
}

FsMonitor { token, entry_dirty }.into()
}
46 changes: 4 additions & 42 deletions git-index/src/extension/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@ pub struct Iter<'a> {
/// It allows to more quickly build trees by avoiding as it can quickly re-use portions of the index and its associated tree ids
/// if there was no change to them. Portions of this tree are invalidated as the index is changed.
pub struct Tree {
name: SmallVec<[u8; 23]>,
pub name: SmallVec<[u8; 23]>,
/// Only set if there are any entries in the index we are associated with.
id: Option<tree::NodeId>,
children: Vec<Tree>,
pub id: Option<tree::NodeId>,
pub children: Vec<Tree>,
}

pub struct Link {
Expand Down Expand Up @@ -50,45 +50,7 @@ pub struct FsMonitor {

mod iter;

pub(crate) mod fs_monitor {
use bstr::BString;

use crate::{
extension::{FsMonitor, Signature},
util::{read_u32, read_u64, split_at_byte_exclusive},
};

pub enum Token {
V1 { nanos_since_1970: u64 },
V2 { token: BString },
}

pub const SIGNATURE: Signature = *b"FSMN";

pub fn decode(data: &[u8]) -> Option<FsMonitor> {
let (version, data) = read_u32(data)?;
let (token, data) = match version {
1 => {
let (nanos_since_1970, data) = read_u64(data)?;
(Token::V1 { nanos_since_1970 }, data)
}
2 => {
let (token, data) = split_at_byte_exclusive(data, 0)?;
(Token::V2 { token: token.into() }, data)
}
_ => return None,
};

let (ewah_size, data) = read_u32(data)?;
let (entry_dirty, data) = git_bitmap::ewah::decode(&data[..ewah_size as usize]).ok()?;

if !data.is_empty() {
return None;
}

FsMonitor { token, entry_dirty }.into()
}
}
pub(crate) mod fs_monitor;

pub(crate) mod decode;

Expand Down
4 changes: 2 additions & 2 deletions git-index/src/extension/tree.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ pub const SIGNATURE: Signature = *b"TREE";

pub struct NodeId {
/// The id of the directory tree of the associated tree object.
id: git_hash::ObjectId,
pub id: git_hash::ObjectId,
/// The amount of non-tree entries contained within, and definitely not zero.
entry_count: u32,
pub entry_count: u32,
}

/// A recursive data structure
Expand Down
19 changes: 17 additions & 2 deletions git-index/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ use filetime::FileTime;

pub mod file;

pub(crate) mod extension;
pub mod extension;

pub mod entry;

mod access {
use crate::{Entry, State, Version};
use crate::{extension, Entry, State, Version};

impl State {
pub fn version(&self) -> Version {
Expand All @@ -22,6 +22,21 @@ mod access {
pub fn entries(&self) -> &[Entry] {
&self.entries
}
pub fn tree(&self) -> Option<&extension::Tree> {
self.tree.as_ref()
}
pub fn link(&self) -> Option<&extension::Link> {
self.link.as_ref()
}
pub fn resolve_undo(&self) -> Option<&extension::resolve_undo::Paths> {
self.resolve_undo.as_ref()
}
pub fn untracked(&self) -> Option<&extension::UntrackedCache> {
self.untracked.as_ref()
}
pub fn fs_monitor(&self) -> Option<&extension::FsMonitor> {
self.fs_monitor.as_ref()
}
}
}

Expand Down
7 changes: 5 additions & 2 deletions git-repository/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ test = true

[features]
default = ["max-performance", "one-stop-shop"]
unstable = []
serde1 = ["git-pack/serde1", "git-object/serde1", "git-protocol/serde1", "git-transport/serde1", "git-ref/serde1", "git-odb/serde1"]
unstable = ["git-index"]
serde1 = ["git-pack/serde1", "git-object/serde1", "git-protocol/serde1", "git-transport/serde1", "git-ref/serde1", "git-odb/serde1", "git-index/serde1"]
# enable when https://github.com/RustCrypto/asm-hashes/issues/17 is fixed
# max-performance = ["git-features/parallel", "git-features/zlib-ng-compat", "git-features/fast-sha1"]
max-performance = ["git-features/parallel", "git-features/zlib-ng-compat", "git-pack/pack-cache-lru-static", "git-pack/pack-cache-lru-dynamic"]
Expand Down Expand Up @@ -54,6 +54,9 @@ git-transport = { version = "^0.15.0", path = "../git-transport", optional = tru
git-diff = { version = "^0.13.0", path = "../git-diff", optional = true }
git-features = { version = "^0.19.1", path = "../git-features", features = ["progress"] }

# unstable only
git-index = { version ="^0.1.0", path = "../git-index", optional = true }

signal-hook = { version = "0.3.9", default-features = false }
thiserror = "1.0.26"
clru = "0.5.0"
Expand Down
3 changes: 3 additions & 0 deletions git-repository/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@
//! * [`url`]
//! * [`actor`]
//! * [`bstr`][bstr]
//! * [`index`]
//! * [`objs`]
//! * [`odb`]
//! * [`pack`][odb::pack]
Expand Down Expand Up @@ -118,6 +119,8 @@ pub use git_features::{parallel, progress, progress::Progress, threading};
pub use git_hash as hash;
#[doc(inline)]
pub use git_hash::{oid, ObjectId};
#[cfg(all(feature = "unstable", feature = "git-index"))]
pub use git_index as index;
pub use git_lock as lock;
pub use git_object as objs;
pub use git_object::bstr;
Expand Down
63 changes: 63 additions & 0 deletions gitoxide-core/src/index/entries.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
use git_repository as git;

#[cfg(feature = "serde1")]
pub(crate) fn to_json(
mut out: &mut impl std::io::Write,
file: &git::index::File,
entry: &git::index::Entry,
is_last: bool,
) -> anyhow::Result<()> {
use git_repository::bstr::ByteSlice;

#[cfg_attr(feature = "serde1", derive(serde::Serialize))]
struct Entry<'a> {
stat: &'a git::index::entry::Stat,
hex_id: String,
flags: u32,
mode: u32,
path: std::borrow::Cow<'a, str>,
}

serde_json::to_writer(
&mut out,
&Entry {
stat: &entry.stat,
hex_id: entry.id.to_hex().to_string(),
flags: entry.flags.bits(),
mode: entry.mode.bits(),
path: entry.path(&file.state).to_str_lossy(),
},
)?;

if is_last {
out.write_all(b"\n")?;
} else {
out.write_all(b",\n")?;
}
Ok(())
}

pub(crate) fn to_human(
out: &mut impl std::io::Write,
file: &git::index::File,
entry: &git::index::Entry,
) -> std::io::Result<()> {
writeln!(
out,
"{} {}{:?} {} {}",
match entry.flags.stage() {
0 => "BASE ",
1 => "OURS ",
2 => "THEIRS ",
_ => "UNKNOWN",
},
if entry.flags.is_empty() {
"".to_string()
} else {
format!("{:?} ", entry.flags)
},
entry.mode,
entry.id,
entry.path(&file.state)
)
}
Loading

0 comments on commit 025f157

Please sign in to comment.