summaryrefslogtreecommitdiffstats
path: root/vendor/gix-index/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/gix-index/src/lib.rs')
-rw-r--r--vendor/gix-index/src/lib.rs201
1 files changed, 201 insertions, 0 deletions
diff --git a/vendor/gix-index/src/lib.rs b/vendor/gix-index/src/lib.rs
new file mode 100644
index 000000000..d8451c545
--- /dev/null
+++ b/vendor/gix-index/src/lib.rs
@@ -0,0 +1,201 @@
+//! ## Feature Flags
+#![cfg_attr(
+ feature = "document-features",
+ cfg_attr(doc, doc = ::document_features::document_features!())
+)]
+#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
+#![deny(unsafe_code, missing_docs, rust_2018_idioms)]
+
+use std::{ops::Range, path::PathBuf};
+
+use filetime::FileTime;
+pub use gix_hash as hash;
+
+///
+pub mod file;
+
+///
+pub mod extension;
+
+///
+pub mod entry;
+
+mod access;
+
+mod init;
+
+///
+pub mod decode;
+
+///
+pub mod verify;
+
+///
+pub mod write;
+
+/// All known versions of a git index file.
+#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
+#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
+pub enum Version {
+ /// Supports entries and various extensions.
+ V2 = 2,
+ /// Adds support for additional flags for each entry, called extended entries.
+ V3 = 3,
+ /// Supports deltified entry paths.
+ V4 = 4,
+}
+
+/// An entry in the index, identifying a non-tree item on disk.
+#[derive(Debug, Clone, Eq, PartialEq)]
+pub struct Entry {
+ /// The filesystem stat information for the file on disk.
+ pub stat: entry::Stat,
+ /// The object id for this entry's ODB representation (assuming it's up-to-date with it).
+ pub id: gix_hash::ObjectId,
+ /// Additional flags for use in algorithms and for efficiently storing stage information.
+ pub flags: entry::Flags,
+ /// The kind of item this entry represents - it's not all blobs in the index anymore.
+ pub mode: entry::Mode,
+ /// The range to lookup in the path backing to obtain the entry path relative to the repository.
+ /// This costs additional memory but is probably worth it given that paths can stay in one big allocation.
+ path: Range<usize>,
+}
+
+/// An index file whose state was read from a file on disk.
+#[derive(Clone)]
+pub struct File {
+ /// The state containing the actual index data.
+ pub(crate) state: State,
+ /// The path from which the index was read or to which it is supposed to be written.
+ pub(crate) path: PathBuf,
+ /// The checksum of all bytes prior to the checksum itself.
+ pub(crate) checksum: Option<gix_hash::ObjectId>,
+}
+
+/// The type to use and store paths to all entries.
+pub type PathStorage = Vec<u8>;
+/// The type to use and store paths to all entries, as reference
+pub type PathStorageRef = [u8];
+
+/// An in-memory cache of a fully parsed git index file.
+///
+/// As opposed to a snapshot, it's meant to be altered and eventually be written back to disk or converted into a tree.
+/// We treat index and its state synonymous.
+#[derive(Clone)]
+pub struct State {
+ /// The kind of object hash used when storing the underlying file.
+ ///
+ /// Empty states for example won't have a single object id, so deduction of the hash used isn't always possible.
+ object_hash: gix_hash::Kind,
+ /// The time at which the state was created, indicating its freshness compared to other files on disk.
+ ///
+ /// Note that on platforms that only have a precisions of a second for this time, we will treat all entries with the
+ /// same timestamp as this as potentially changed, checking more thoroughly if a change actually happened.
+ #[allow(dead_code)]
+ timestamp: FileTime,
+ version: Version,
+ entries: Vec<Entry>,
+ /// A memory area keeping all index paths, in full length, independently of the index version.
+ path_backing: PathStorage,
+ /// True if one entry in the index has a special marker mode
+ is_sparse: bool,
+
+ // Extensions
+ tree: Option<extension::Tree>,
+ link: Option<extension::Link>,
+ resolve_undo: Option<extension::resolve_undo::Paths>,
+ untracked: Option<extension::UntrackedCache>,
+ fs_monitor: Option<extension::FsMonitor>,
+}
+
+mod impls {
+ use std::fmt::{Debug, Formatter};
+
+ use crate::State;
+
+ impl Debug for State {
+ fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
+ for entry in &self.entries {
+ writeln!(
+ f,
+ "{} {}{:?} {} {}",
+ 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(self)
+ )?;
+ }
+ Ok(())
+ }
+ }
+}
+
+pub(crate) mod util {
+ use std::convert::TryInto;
+
+ #[inline]
+ pub fn var_int(data: &[u8]) -> Option<(u64, &[u8])> {
+ let (num, consumed) = gix_features::decode::leb64_from_read(data).ok()?;
+ let data = &data[consumed..];
+ (num, data).into()
+ }
+
+ #[inline]
+ pub fn read_u32(data: &[u8]) -> Option<(u32, &[u8])> {
+ split_at_pos(data, 4).map(|(num, data)| (u32::from_be_bytes(num.try_into().unwrap()), data))
+ }
+
+ #[inline]
+ pub fn read_u64(data: &[u8]) -> Option<(u64, &[u8])> {
+ split_at_pos(data, 8).map(|(num, data)| (u64::from_be_bytes(num.try_into().unwrap()), data))
+ }
+
+ #[inline]
+ pub fn from_be_u32(b: &[u8]) -> u32 {
+ u32::from_be_bytes(b.try_into().unwrap())
+ }
+
+ #[inline]
+ pub fn split_at_byte_exclusive(data: &[u8], byte: u8) -> Option<(&[u8], &[u8])> {
+ if data.len() < 2 {
+ return None;
+ }
+ data.iter().enumerate().find_map(|(idx, b)| {
+ (*b == byte).then(|| {
+ if idx == 0 {
+ (&[] as &[u8], &data[1..])
+ } else {
+ let (a, b) = data.split_at(idx);
+ (a, &b[1..])
+ }
+ })
+ })
+ }
+
+ #[inline]
+ pub fn split_at_pos(data: &[u8], pos: usize) -> Option<(&[u8], &[u8])> {
+ if data.len() < pos {
+ return None;
+ }
+ data.split_at(pos).into()
+ }
+}
+
+#[test]
+fn size_of_entry() {
+ assert_eq!(std::mem::size_of::<crate::Entry>(), 80);
+
+ // the reason we have our own time is half the size.
+ assert_eq!(std::mem::size_of::<crate::entry::Time>(), 8);
+ assert_eq!(std::mem::size_of::<filetime::FileTime>(), 16);
+}