pub struct File { /* private fields */ }
Expand description
An index file whose state was read from a file on disk.
Implementations§
source§impl File
impl File
Consumption
sourcepub fn into_state(self) -> State
pub fn into_state(self) -> State
Take the state and discard the rest.
sourcepub fn into_parts(self) -> (State, PathBuf)
pub fn into_parts(self) -> (State, PathBuf)
Take all non-copy parts of the index.
source§impl File
impl File
Access
sourcepub fn path(&self) -> &Path
pub fn path(&self) -> &Path
The path from which the index was read or to which it is supposed to be written when used with File::from_state()
.
source§impl File
impl File
Initialization
sourcepub fn at(
path: impl Into<PathBuf>,
object_hash: Kind,
options: Options
) -> Result<Self, Error>
pub fn at(
path: impl Into<PathBuf>,
object_hash: Kind,
options: Options
) -> Result<Self, Error>
Open an index file at path
with options
, assuming object_hash
is used throughout the file.
sourcepub fn from_state(state: State, path: impl Into<PathBuf>) -> Self
pub fn from_state(state: State, path: impl Into<PathBuf>) -> Self
Consume state
and pretend it was read from path
, setting our checksum to null
.
File
instances created like that should be written to disk to set the correct checksum via [File::write()]
.
source§impl File
impl File
sourcepub fn verify_integrity(&self) -> Result<(), Error>
pub fn verify_integrity(&self) -> Result<(), Error>
Verify the integrity of the index to assure its consistency.
source§impl File
impl File
sourcepub fn write_to(
&self,
out: impl Write,
options: Options
) -> Result<(Version, ObjectId)>
pub fn write_to(
&self,
out: impl Write,
options: Options
) -> Result<(Version, ObjectId)>
Write the index to out
with options
, to be readable by File::at()
, returning the version that was actually written
to retain all information of this index.
Examples found in repository?
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
pub fn write(&mut self, options: write::Options) -> Result<(), Error> {
let mut lock = std::io::BufWriter::new(git_lock::File::acquire_to_update_resource(
&self.path,
git_lock::acquire::Fail::Immediately,
None,
)?);
let (version, digest) = self.write_to(&mut lock, options)?;
match lock.into_inner() {
Ok(lock) => lock.commit()?,
Err(err) => return Err(err.into_error().into()),
};
self.state.version = version;
self.checksum = Some(digest);
Ok(())
}
Methods from Deref<Target = State>§
sourcepub fn version(&self) -> Version
pub fn version(&self) -> Version
Return the version used to store this state’s information on disk.
sourcepub fn object_hash(&self) -> Kind
pub fn object_hash(&self) -> Kind
Return the kind of hashes used in this instance.
sourcepub fn entries(&self) -> &[Entry]
pub fn entries(&self) -> &[Entry]
Return our entries
Examples found in repository?
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
pub fn write_to(&self, out: impl std::io::Write, Options { extensions }: Options) -> std::io::Result<Version> {
let version = self.detect_required_version();
let mut write = CountBytes::new(out);
let num_entries = self
.entries()
.len()
.try_into()
.expect("definitely not 4billion entries");
let offset_to_entries = header(&mut write, version, num_entries)?;
let offset_to_extensions = entries(&mut write, self, offset_to_entries)?;
let (extension_toc, out) = self.write_extensions(write, offset_to_extensions, extensions)?;
if num_entries > 0
&& extensions
.should_write(extension::end_of_index_entry::SIGNATURE)
.is_some()
&& !extension_toc.is_empty()
{
extension::end_of_index_entry::write_to(out, self.object_hash, offset_to_extensions, extension_toc)?
}
Ok(version)
}
fn write_extensions<T>(
&self,
mut write: CountBytes<T>,
offset_to_extensions: u32,
extensions: Extensions,
) -> std::io::Result<(Vec<(extension::Signature, u32)>, T)>
where
T: std::io::Write,
{
type WriteExtFn<'a> = &'a dyn Fn(&mut dyn std::io::Write) -> Option<std::io::Result<extension::Signature>>;
let extensions: &[WriteExtFn<'_>] = &[
&|write| {
extensions
.should_write(extension::tree::SIGNATURE)
.and_then(|signature| self.tree().map(|tree| tree.write_to(write).map(|_| signature)))
},
&|write| {
self.is_sparse()
.then(|| extension::sparse::write_to(write).map(|_| extension::sparse::SIGNATURE))
},
];
let mut offset_to_previous_ext = offset_to_extensions;
let mut out = Vec::with_capacity(5);
for write_ext in extensions {
if let Some(signature) = write_ext(&mut write).transpose()? {
let offset_past_ext = write.count;
let ext_size = offset_past_ext - offset_to_previous_ext - (extension::MIN_SIZE as u32);
offset_to_previous_ext = offset_past_ext;
out.push((signature, ext_size));
}
}
Ok((out, write.inner))
}
}
impl State {
fn detect_required_version(&self) -> Version {
self.entries
.iter()
.find_map(|e| e.flags.contains(entry::Flags::EXTENDED).then(|| Version::V3))
.unwrap_or(Version::V2)
}
}
fn header<T: std::io::Write>(
out: &mut CountBytes<T>,
version: Version,
num_entries: u32,
) -> Result<u32, std::io::Error> {
let version = match version {
Version::V2 => 2_u32.to_be_bytes(),
Version::V3 => 3_u32.to_be_bytes(),
Version::V4 => 4_u32.to_be_bytes(),
};
out.write_all(crate::decode::header::SIGNATURE)?;
out.write_all(&version)?;
out.write_all(&num_entries.to_be_bytes())?;
Ok(out.count)
}
fn entries<T: std::io::Write>(out: &mut CountBytes<T>, state: &State, header_size: u32) -> Result<u32, std::io::Error> {
for entry in state.entries() {
entry.write_to(&mut *out, state)?;
match (out.count - header_size) % 8 {
0 => {}
n => {
let eight_null_bytes = [0u8; 8];
out.write_all(&eight_null_bytes[n as usize..])?;
}
};
}
Ok(out.count)
}
sourcepub fn path_backing(&self) -> &PathStorage
pub fn path_backing(&self) -> &PathStorage
Return our path backing, the place which keeps all paths one after another, with entries storing only the range to access them.
sourcepub fn take_path_backing(&mut self) -> PathStorage
pub fn take_path_backing(&mut self) -> PathStorage
Sometimes it’s needed to remove the path backing to allow certain mutation to happen in the state while supporting reading the entry’s path.
sourcepub fn return_path_backing(&mut self, backing: PathStorage)
pub fn return_path_backing(&mut self, backing: PathStorage)
After usage of the storage obtained by take_path_backing()
, return it here.
Note that it must not be empty.
sourcepub fn entries_with_paths_by_filter_map<'a, T>(
&'a self,
filter_map: impl FnMut(&'a BStr, &Entry) -> Option<T> + 'a
) -> impl Iterator<Item = (&'a BStr, T)> + 'a
pub fn entries_with_paths_by_filter_map<'a, T>(
&'a self,
filter_map: impl FnMut(&'a BStr, &Entry) -> Option<T> + 'a
) -> impl Iterator<Item = (&'a BStr, T)> + 'a
Runs filter_map
on all entries, returning an iterator over all paths along with the result of filter_map
.
sourcepub fn entries_mut(&mut self) -> &mut [Entry]
pub fn entries_mut(&mut self) -> &mut [Entry]
Return mutable entries in a slice.
sourcepub fn entries_mut_with_paths(
&mut self
) -> impl Iterator<Item = (&mut Entry, &BStr)>
pub fn entries_mut_with_paths(
&mut self
) -> impl Iterator<Item = (&mut Entry, &BStr)>
Return mutable entries along with their paths in an iterator.
sourcepub fn entries_mut_with_paths_in<'state, 'backing>(
&'state mut self,
backing: &'backing PathStorage
) -> impl Iterator<Item = (&'state mut Entry, &'backing BStr)>
pub fn entries_mut_with_paths_in<'state, 'backing>(
&'state mut self,
backing: &'backing PathStorage
) -> impl Iterator<Item = (&'state mut Entry, &'backing BStr)>
Return mutable entries along with their path, as obtained from backing
.
sourcepub fn entry_index_by_path_and_stage(
&self,
path: &BStr,
stage: Stage
) -> Option<usize>
pub fn entry_index_by_path_and_stage(
&self,
path: &BStr,
stage: Stage
) -> Option<usize>
Find the entry index in entries()
matching the given repository-relative
path
and stage
, or None
.
Use the index for accessing multiple stages if they exists, but at least the single matching entry.
sourcepub fn entry_by_path_and_stage(&self, path: &BStr, stage: Stage) -> Option<&Entry>
pub fn entry_by_path_and_stage(&self, path: &BStr, stage: Stage) -> Option<&Entry>
Like entry_index_by_path_and_stage()
,
but returns the entry instead of the index.
sourcepub fn entry(&self, idx: usize) -> &Entry
pub fn entry(&self, idx: usize) -> &Entry
Return the entry at idx
or panic if the index is out of bounds.
The idx
is typically returned by entry_by_path_and_stage().
sourcepub fn is_sparse(&self) -> bool
pub fn is_sparse(&self) -> bool
Returns a boolean value indicating whether the index is sparse or not.
An index is sparse if it contains at least one Mode::DIR entry.
Examples found in repository?
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
fn write_extensions<T>(
&self,
mut write: CountBytes<T>,
offset_to_extensions: u32,
extensions: Extensions,
) -> std::io::Result<(Vec<(extension::Signature, u32)>, T)>
where
T: std::io::Write,
{
type WriteExtFn<'a> = &'a dyn Fn(&mut dyn std::io::Write) -> Option<std::io::Result<extension::Signature>>;
let extensions: &[WriteExtFn<'_>] = &[
&|write| {
extensions
.should_write(extension::tree::SIGNATURE)
.and_then(|signature| self.tree().map(|tree| tree.write_to(write).map(|_| signature)))
},
&|write| {
self.is_sparse()
.then(|| extension::sparse::write_to(write).map(|_| extension::sparse::SIGNATURE))
},
];
let mut offset_to_previous_ext = offset_to_extensions;
let mut out = Vec::with_capacity(5);
for write_ext in extensions {
if let Some(signature) = write_ext(&mut write).transpose()? {
let offset_past_ext = write.count;
let ext_size = offset_past_ext - offset_to_previous_ext - (extension::MIN_SIZE as u32);
offset_to_previous_ext = offset_past_ext;
out.push((signature, ext_size));
}
}
Ok((out, write.inner))
}
sourcepub fn tree(&self) -> Option<&Tree>
pub fn tree(&self) -> Option<&Tree>
Access the tree
extension.
Examples found in repository?
More examples
88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
fn write_extensions<T>(
&self,
mut write: CountBytes<T>,
offset_to_extensions: u32,
extensions: Extensions,
) -> std::io::Result<(Vec<(extension::Signature, u32)>, T)>
where
T: std::io::Write,
{
type WriteExtFn<'a> = &'a dyn Fn(&mut dyn std::io::Write) -> Option<std::io::Result<extension::Signature>>;
let extensions: &[WriteExtFn<'_>] = &[
&|write| {
extensions
.should_write(extension::tree::SIGNATURE)
.and_then(|signature| self.tree().map(|tree| tree.write_to(write).map(|_| signature)))
},
&|write| {
self.is_sparse()
.then(|| extension::sparse::write_to(write).map(|_| extension::sparse::SIGNATURE))
},
];
let mut offset_to_previous_ext = offset_to_extensions;
let mut out = Vec::with_capacity(5);
for write_ext in extensions {
if let Some(signature) = write_ext(&mut write).transpose()? {
let offset_past_ext = write.count;
let ext_size = offset_past_ext - offset_to_previous_ext - (extension::MIN_SIZE as u32);
offset_to_previous_ext = offset_past_ext;
out.push((signature, ext_size));
}
}
Ok((out, write.inner))
}
sourcepub fn resolve_undo(&self) -> Option<&Vec<ResolvePath>>
pub fn resolve_undo(&self) -> Option<&Vec<ResolvePath>>
Obtain the resolve-undo extension.
sourcepub fn untracked(&self) -> Option<&UntrackedCache>
pub fn untracked(&self) -> Option<&UntrackedCache>
Obtain the untracked extension.
sourcepub fn fs_monitor(&self) -> Option<&FsMonitor>
pub fn fs_monitor(&self) -> Option<&FsMonitor>
Obtain the fsmonitor extension.
sourcepub fn verify_entries(&self) -> Result<(), Error>
pub fn verify_entries(&self) -> Result<(), Error>
Assure our entries are consistent.
sourcepub fn write_to(&self, out: impl Write, _: Options) -> Result<Version>
pub fn write_to(&self, out: impl Write, _: Options) -> Result<Version>
Serialize this instance to out
with options
.
Examples found in repository?
20 21 22 23 24 25 26 27 28 29 30 31
pub fn write_to(
&self,
mut out: impl std::io::Write,
options: write::Options,
) -> std::io::Result<(Version, git_hash::ObjectId)> {
let mut hasher = hash::Write::new(&mut out, self.state.object_hash);
let version = self.state.write_to(&mut hasher, options)?;
let hash = hasher.hash.digest();
out.write_all(&hash)?;
Ok((version, git_hash::ObjectId::from(hash)))
}