Skip to content

Commit

Permalink
Merge branch 'worktree-stack'
Browse files Browse the repository at this point in the history
  • Loading branch information
Byron committed Apr 13, 2022
2 parents 92fe564 + 8f4969f commit e90d3fd
Show file tree
Hide file tree
Showing 40 changed files with 1,862 additions and 325 deletions.
14 changes: 13 additions & 1 deletion Cargo.lock

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

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ members = [
"git-chunk",
"git-quote",
"git-object",
"git-glob",
"git-diff",
"git-traverse",
"git-index",
Expand Down
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ check: ## Build all code in suitable configurations
cd git-index && cargo check --features serde1
cd git-revision && cargo check --features serde1
cd git-attributes && cargo check --features serde1
cd git-glob && cargo check --features serde1
cd git-mailmap && cargo check --features serde1
cd git-worktree && cargo check --features serde1
cd git-actor && cargo check --features serde1
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ Crates that seem feature complete and need to see some more use before they can
* [git-revision](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-revision)
* [git-attributes](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-attributes)
* [git-quote](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-quote)
* [git-glob](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-glob)
* **idea**
* [git-note](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-note)
* [git-pathspec](https://github.com/Byron/gitoxide/blob/main/crate-status.md#git-pathspec)
Expand Down
12 changes: 4 additions & 8 deletions crate-status.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
### git-actor

* [x] read and write a signature that uniquely identifies an actor within a git repository

### git-hash
Expand Down Expand Up @@ -28,7 +27,6 @@
* [ ] Some examples

### git-pack

* **packs**
* [x] traverse pack index
* [x] 'object' abstraction
Expand Down Expand Up @@ -73,7 +71,6 @@
* [ ] Some examples

### git-odb

* **loose object store**
* [x] traverse
* [x] read
Expand Down Expand Up @@ -210,25 +207,21 @@ Check out the [performance discussion][git-traverse-performance] as well.
* [ ] Some examples

### git-attributes

* [x] parse git-ignore files (aka git-attributes without the attributes or negation)
* [x] parse git-attributes files
* [ ] create an attributes stack, ideally one that includes 'ignored' status from .gitignore files.
* [ ] support for built-in `binary` macro for `-text -diff -merge`

### git-quote

* **ansi-c**
* [x] quote
* [ ] unquote

### git-mailmap

* [x] parsing
* [x] lookup and mapping of author names

### git-pathspec

* [ ] parse
* [ ] check for match

Expand All @@ -238,6 +231,10 @@ A mechanism to associate metadata with any object, and keep revisions of it usin

* [ ] CRUD for git notes

### git-glob
* [ ] parse pattern
* [ ] a type for pattern matching

### git-worktree
* handle the working tree/checkout
- [x] checkout an index of files, executables and symlinks just as fast as git
Expand All @@ -263,7 +260,6 @@ A mechanism to associate metadata with any object, and keep revisions of it usin
* parse specifications into revisions (like `git rev-parse`)

### git-submodule

* CRUD for submodules
* try to handle with all the nifty interactions and be a little more comfortable than what git offers, lay a foundation for smarter git submodules.

Expand Down
3 changes: 2 additions & 1 deletion git-actor/src/signature/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
mod _ref {
use crate::{signature::decode, Signature, SignatureRef};
use bstr::ByteSlice;

use crate::{signature::decode, Signature, SignatureRef};

impl<'a> SignatureRef<'a> {
/// Deserialize a signature from the given `data`.
pub fn from_bytes<E>(data: &'a [u8]) -> Result<SignatureRef<'a>, nom::Err<E>>
Expand Down
4 changes: 2 additions & 2 deletions git-attributes/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ doctest = false

[features]
## Data structures implement `serde::Serialize` and `serde::Deserialize`.
serde1 = ["serde", "bstr/serde1"]
serde1 = ["serde", "bstr/serde1", "git-glob/serde1"]

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
git-quote = { version = "^0.2.0", path = "../git-quote" }
git-glob = { version = "^0.1.0", path = "../git-glob" }

bstr = { version = "0.2.13", default-features = false, features = ["std"]}
bitflags = "1.3.2"
unicode-bom = "1.1.4"
quick-error = "2.0.0"
serde = { version = "1.0.114", optional = true, default-features = false, features = ["derive"]}
Expand Down
16 changes: 0 additions & 16 deletions git-attributes/src/ignore.rs

This file was deleted.

2 changes: 0 additions & 2 deletions git-attributes/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,6 @@ pub enum State<'a> {
Unspecified,
}

pub mod ignore;

pub mod parse;

pub fn parse(buf: &[u8]) -> parse::Lines<'_> {
Expand Down
9 changes: 5 additions & 4 deletions git-attributes/src/parse/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@ use bstr::{BStr, BString, ByteSlice};
#[cfg_attr(feature = "serde1", derive(serde::Serialize, serde::Deserialize))]
pub enum Kind {
/// A pattern to match paths against
Pattern(BString, crate::ignore::pattern::Mode),
Pattern(git_glob::Pattern),
/// The name of the macro to define, always a valid attribute name
// TODO: turn it into its own type for maximum safety
Macro(BString),
}

Expand Down Expand Up @@ -162,14 +163,14 @@ fn parse_line(line: &BStr, line_number: usize) -> Option<Result<(Kind, Iter<'_>,
_ => unreachable!("BUG: check_attr() must only return attribute errors"),
}),
None => {
let (pattern, flags) = super::ignore::parse_line(line.as_ref())?;
if flags.contains(crate::ignore::pattern::Mode::NEGATIVE) {
let pattern = git_glob::Pattern::from_bytes(line.as_ref())?;
if pattern.mode.contains(git_glob::pattern::Mode::NEGATIVE) {
Err(Error::PatternNegation {
line: line.into_owned(),
line_number,
})
} else {
Ok(Kind::Pattern(pattern, flags))
Ok(Kind::Pattern(pattern))
}
}
};
Expand Down
76 changes: 4 additions & 72 deletions git-attributes/src/parse/ignore.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use bstr::{BString, ByteSlice};

use crate::ignore;
use bstr::ByteSlice;

pub struct Lines<'a> {
lines: bstr::Lines<'a>,
Expand All @@ -18,85 +16,19 @@ impl<'a> Lines<'a> {
}

impl<'a> Iterator for Lines<'a> {
type Item = (BString, ignore::pattern::Mode, usize);
type Item = (git_glob::Pattern, usize);

fn next(&mut self) -> Option<Self::Item> {
for line in self.lines.by_ref() {
self.line_no += 1;
if line.first() == Some(&b'#') {
continue;
}
match parse_line(line) {
match git_glob::Pattern::from_bytes(line) {
None => continue,
Some((line, flags)) => return Some((line, flags, self.line_no)),
Some(pattern) => return Some((pattern, self.line_no)),
}
}
None
}
}

#[inline]
pub(crate) fn parse_line(mut line: &[u8]) -> Option<(BString, ignore::pattern::Mode)> {
let mut mode = ignore::pattern::Mode::empty();
if line.is_empty() {
return None;
};
if line.first() == Some(&b'!') {
mode |= ignore::pattern::Mode::NEGATIVE;
line = &line[1..];
} else if line.first() == Some(&b'\\') {
let second = line.get(1);
if second == Some(&b'!') || second == Some(&b'#') {
line = &line[1..];
}
}
if line.iter().all(|b| b.is_ascii_whitespace()) {
return None;
}
let mut line = truncate_non_escaped_trailing_spaces(line);
if line.last() == Some(&b'/') {
mode |= ignore::pattern::Mode::MUST_BE_DIR;
line.pop();
}
if !line.contains(&b'/') {
mode |= ignore::pattern::Mode::NO_SUB_DIR;
}
if line.first() == Some(&b'*') && line[1..].find_byteset(br"*?[\").is_none() {
mode |= ignore::pattern::Mode::ENDS_WITH;
}
Some((line, mode))
}

/// We always copy just because that's ultimately needed anyway, not because we always have to.
fn truncate_non_escaped_trailing_spaces(buf: &[u8]) -> BString {
match buf.rfind_not_byteset(br"\ ") {
Some(pos) if pos + 1 == buf.len() => buf.into(), // does not end in (escaped) whitespace
None => buf.into(),
Some(start_of_non_space) => {
// This seems a bit strange but attempts to recreate the git implementation while
// actually removing the escape characters before spaces. We leave other backslashes
// for escapes to be handled by `glob/globset`.
let mut res: BString = buf[..start_of_non_space + 1].into();

let mut trailing_bytes = buf[start_of_non_space + 1..].iter();
let mut bare_spaces = 0;
while let Some(b) = trailing_bytes.next() {
match b {
b' ' => {
bare_spaces += 1;
}
b'\\' => {
res.extend(std::iter::repeat(b' ').take(bare_spaces));
bare_spaces = 0;
// Skip what follows, like git does, but keep spaces if possible.
if trailing_bytes.next() == Some(&b' ') {
res.push(b' ');
}
}
_ => unreachable!("BUG: this must be either backslash or space"),
}
}
res
}
}
}
Loading

0 comments on commit e90d3fd

Please sign in to comment.