mirror of
https://github.com/gitbutlerapp/gitbutler.git
synced 2024-11-28 04:47:42 +03:00
Merge pull request #3321 from gitbutlerapp/remove-line-file
remove linefile
This commit is contained in:
commit
4163ad23ff
2
.github/workflows/push.yaml
vendored
2
.github/workflows/push.yaml
vendored
@ -133,8 +133,6 @@ jobs:
|
||||
- ''
|
||||
- '*'
|
||||
- []
|
||||
- [git2]
|
||||
- [mmap]
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: ./.github/actions/check-crate
|
||||
|
61
Cargo.lock
generated
61
Cargo.lock
generated
@ -1334,18 +1334,6 @@ dependencies = [
|
||||
"cfg-if",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enum-as-inner"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a"
|
||||
dependencies = [
|
||||
"heck 0.4.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.48",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "enumflags2"
|
||||
version = "0.7.8"
|
||||
@ -1991,8 +1979,6 @@ dependencies = [
|
||||
name = "gitbutler-changeset"
|
||||
version = "0.0.0"
|
||||
dependencies = [
|
||||
"git2",
|
||||
"mmap-rs",
|
||||
"paste",
|
||||
"thiserror",
|
||||
]
|
||||
@ -2863,15 +2849,6 @@ version = "0.1.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||
|
||||
[[package]]
|
||||
name = "mach2"
|
||||
version = "0.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "malloc_buf"
|
||||
version = "0.0.6"
|
||||
@ -2986,23 +2963,6 @@ dependencies = [
|
||||
"windows-sys 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mmap-rs"
|
||||
version = "0.6.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "86968d85441db75203c34deefd0c88032f275aaa85cee19a1dcfff6ae9df56da"
|
||||
dependencies = [
|
||||
"bitflags 1.3.2",
|
||||
"combine",
|
||||
"libc",
|
||||
"mach2",
|
||||
"nix 0.26.4",
|
||||
"sysctl",
|
||||
"thiserror",
|
||||
"widestring",
|
||||
"windows 0.48.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "native-tls"
|
||||
version = "0.2.11"
|
||||
@ -3065,7 +3025,6 @@ dependencies = [
|
||||
"cfg-if",
|
||||
"libc",
|
||||
"memoffset 0.7.1",
|
||||
"pin-utils",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -5263,20 +5222,6 @@ dependencies = [
|
||||
"windows-sys 0.45.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysctl"
|
||||
version = "0.5.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ec7dddc5f0fee506baf8b9fdb989e242f17e4b11c61dfbb0635b705217199eea"
|
||||
dependencies = [
|
||||
"bitflags 2.4.0",
|
||||
"byteorder",
|
||||
"enum-as-inner",
|
||||
"libc",
|
||||
"thiserror",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sysinfo"
|
||||
version = "0.30.7"
|
||||
@ -6485,12 +6430,6 @@ version = "0.1.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9193164d4de03a926d909d3bc7c30543cecb35400c02114792c2cae20d5e2dbb"
|
||||
|
||||
[[package]]
|
||||
name = "widestring"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8"
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
|
@ -3,15 +3,8 @@ name = "gitbutler-changeset"
|
||||
version = "0.0.0"
|
||||
edition = "2021"
|
||||
|
||||
[features]
|
||||
default = ["git2", "mmap"]
|
||||
git2 = ["dep:git2"]
|
||||
mmap = ["dep:mmap-rs"]
|
||||
|
||||
[dependencies]
|
||||
thiserror.workspace = true
|
||||
git2 = { workspace = true, optional = true }
|
||||
mmap-rs = { version = "0.6.1", optional = true }
|
||||
|
||||
[dev-dependencies]
|
||||
paste = "1.0.14"
|
||||
|
@ -46,14 +46,7 @@
|
||||
#![allow(clippy::doc_markdown, clippy::missing_errors_doc)]
|
||||
#![feature(impl_trait_in_assoc_type, iter_map_windows, slice_as_chunks)]
|
||||
|
||||
mod linefile;
|
||||
mod signature;
|
||||
mod span;
|
||||
|
||||
#[cfg(feature = "mmap")]
|
||||
pub use self::linefile::mmap::MmapLineFile;
|
||||
pub use self::{
|
||||
linefile::{memory::MemoryLineFile, CrlfBehavior, LineEndings, LineFile},
|
||||
signature::Signature,
|
||||
span::LineSpan,
|
||||
};
|
||||
pub use self::{signature::Signature, span::LineSpan};
|
||||
|
@ -1,69 +0,0 @@
|
||||
use crate::LineSpan;
|
||||
use std::fmt;
|
||||
|
||||
pub mod memory;
|
||||
#[cfg(feature = "mmap")]
|
||||
pub mod mmap;
|
||||
|
||||
/// A file, delimited by lines. The line ending is unspecified;
|
||||
/// it is assumed the underlying implementation handles (and omits)
|
||||
/// line endings for us.
|
||||
///
|
||||
/// All text is assumed to be UTF-8.
|
||||
pub trait LineFile<'a> {
|
||||
/// The type of iterator returned by [`LineFile::lines`] and [`LineFile::extract`].
|
||||
type LineIterator: Iterator<Item = &'a str>;
|
||||
|
||||
/// Gets the line count of the file.
|
||||
fn line_count(&self) -> usize;
|
||||
|
||||
/// Returns a slice of lines given the span.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the span is out of bounds.
|
||||
fn extract(&'a self, span: LineSpan) -> Self::LineIterator;
|
||||
|
||||
/// Returns an iterator over the all lines of the file.
|
||||
fn lines(&'a self) -> Self::LineIterator {
|
||||
self.extract(LineSpan::new(0, self.line_count() - 1))
|
||||
}
|
||||
|
||||
/// Render the file to the given [`fmt::Write`]r.
|
||||
/// Will append each line, including the last, with the line ending
|
||||
/// specified by `line_endings`.
|
||||
fn render<W: fmt::Write>(
|
||||
&'a self,
|
||||
writer: &mut W,
|
||||
line_endings: LineEndings,
|
||||
) -> Result<(), fmt::Error> {
|
||||
for line in self.lines() {
|
||||
writer.write_str(line)?;
|
||||
match line_endings {
|
||||
LineEndings::Unix => writer.write_char('\n')?,
|
||||
LineEndings::Windows => writer.write_str("\r\n")?,
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
/// The behavior of CRLF (carriage return + line feed) characters
|
||||
/// when splitting a file into lines.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum CrlfBehavior {
|
||||
/// Trims carriage returns (`\r`) from the end of lines.
|
||||
Trim,
|
||||
/// Keeps carriage returns (`\r`) at the end of lines.
|
||||
Keep,
|
||||
}
|
||||
|
||||
/// Which line ending to emit when rendering files to a [`fmt::Write`]r.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
|
||||
pub enum LineEndings {
|
||||
/// Use Unix-style line endings (`\n`).
|
||||
Unix,
|
||||
/// Use Windows-style line endings (`\r\n`).
|
||||
Windows,
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
#![allow(clippy::module_name_repetitions)]
|
||||
|
||||
use crate::{CrlfBehavior, LineFile, LineSpan};
|
||||
|
||||
/// A [`LineFile`] stored in memory.
|
||||
pub struct MemoryLineFile {
|
||||
lines: Vec<String>,
|
||||
}
|
||||
|
||||
impl MemoryLineFile {
|
||||
/// Creates a new [`MemoryLineFile`] from the given lines.
|
||||
#[must_use]
|
||||
pub fn new(lines: Vec<String>) -> Self {
|
||||
Self { lines }
|
||||
}
|
||||
|
||||
/// Creates a new [`MemoryLineFile`] from the given text,
|
||||
/// with the given CRLF behavior.
|
||||
#[must_use]
|
||||
pub fn from_str(text: &str, crlf_behavior: CrlfBehavior) -> Self {
|
||||
MemoryLineFile {
|
||||
lines: text
|
||||
.split('\n')
|
||||
.map(|line| match crlf_behavior {
|
||||
CrlfBehavior::Trim => line.trim_end_matches('\r').to_owned(),
|
||||
CrlfBehavior::Keep => line.to_owned(),
|
||||
})
|
||||
.collect(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> LineFile<'a> for MemoryLineFile {
|
||||
type LineIterator = impl Iterator<Item = &'a str>;
|
||||
|
||||
#[inline]
|
||||
fn line_count(&self) -> usize {
|
||||
self.lines.len()
|
||||
}
|
||||
|
||||
#[must_use]
|
||||
fn extract(&'a self, span: LineSpan) -> Self::LineIterator {
|
||||
self.lines[span.start()..=span.end()]
|
||||
.iter()
|
||||
.map(AsRef::as_ref)
|
||||
}
|
||||
}
|
@ -1,87 +0,0 @@
|
||||
#![allow(clippy::module_name_repetitions)]
|
||||
|
||||
use crate::{CrlfBehavior, LineFile};
|
||||
use mmap_rs::{Error, Mmap};
|
||||
|
||||
/// A [`LineFile`] created from a read-only memory-mapped file.
|
||||
pub struct MmapLineFile {
|
||||
mmap: Mmap,
|
||||
line_slices: Vec<(usize, usize)>,
|
||||
}
|
||||
|
||||
impl MmapLineFile {
|
||||
/// Creates a new [`MmapLineFile`] from the given memory-mapped file.
|
||||
///
|
||||
/// Will attempt to make the Mmap read-only. Upon failure to do so,
|
||||
/// returns both the original [`Mmap`] and the error.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// Panics if the document's contents are not valid UTF-8.
|
||||
pub fn from_mmap(mmap: Mmap, crlf_behavior: CrlfBehavior) -> Result<Self, (Mmap, Error)> {
|
||||
let mmap = mmap.make_read_only()?;
|
||||
let mut line_slices = Vec::new();
|
||||
// We check it here to avoid having to check it in the loop.
|
||||
std::str::from_utf8(mmap.as_ref()).expect("mmap contents are not valid UTF-8");
|
||||
MmapLineFile::init_lines(mmap.as_slice(), &mut line_slices, crlf_behavior);
|
||||
Ok(Self { mmap, line_slices })
|
||||
}
|
||||
|
||||
/// Creates a new [`MmapLineFile`] from the given file path.
|
||||
/// **Unsafely** assumes the file is UTF-8 and will not attempt to convert it.
|
||||
///
|
||||
/// Will attempt to make the Mmap read-only. Upon failure to do so,
|
||||
/// returns both the original [`Mmap`] and the error.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This function is unsafe because it assumes the file is UTF-8. If it is not,
|
||||
/// the behavior is undefined.
|
||||
pub unsafe fn from_mmap_unsafe(
|
||||
mmap: Mmap,
|
||||
crlf_behavior: CrlfBehavior,
|
||||
) -> Result<Self, (Mmap, Error)> {
|
||||
let mmap = mmap.make_read_only()?;
|
||||
let mut line_slices = Vec::new();
|
||||
MmapLineFile::init_lines(mmap.as_slice(), &mut line_slices, crlf_behavior);
|
||||
Ok(Self { mmap, line_slices })
|
||||
}
|
||||
|
||||
fn init_lines(text: &[u8], lines: &mut Vec<(usize, usize)>, crlf_behavior: CrlfBehavior) {
|
||||
text.iter()
|
||||
.enumerate()
|
||||
.fold((0, false), |(start, cr), (i, c)| {
|
||||
if *c == b'\n' {
|
||||
lines.push((
|
||||
start,
|
||||
i - usize::from(cr && crlf_behavior == CrlfBehavior::Trim),
|
||||
));
|
||||
(i + 1, false)
|
||||
} else {
|
||||
(start, *c == b'\r')
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> LineFile<'a> for MmapLineFile {
|
||||
type LineIterator = impl Iterator<Item = &'a str>;
|
||||
|
||||
#[inline]
|
||||
fn line_count(&self) -> usize {
|
||||
self.line_slices.len()
|
||||
}
|
||||
|
||||
fn extract(&'a self, span: crate::LineSpan) -> Self::LineIterator {
|
||||
let mmap_ref = self.mmap.as_ref();
|
||||
|
||||
self.line_slices[span.start()..=span.end()]
|
||||
.iter()
|
||||
.map(|(start, end)| &mmap_ref[*start..=*end])
|
||||
// The unsafe variant has been checked in the constructors.
|
||||
// Either they called `from_mmap` and it was checked there,
|
||||
// or they called `from_mmap_unsafe` and the caller assumes
|
||||
// responsibility for the UTF-8 invariant.
|
||||
.map(|bytes| unsafe { std::str::from_utf8_unchecked(bytes) })
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user