Skip to content

Commit

Permalink
first successful test for returning a refspec. (#450)
Browse files Browse the repository at this point in the history
It's the simplest possible one, but it shows the test framework is up to
the task now so it can be test-driven.
We should be able to construct a test for each possible instruction and
eventually pass all tests, including the baseline ones.
  • Loading branch information
Byron committed Aug 6, 2022
1 parent 3f264af commit 6e5bd5c
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 21 deletions.
4 changes: 2 additions & 2 deletions git-refspec/src/lib.rs
Expand Up @@ -11,7 +11,7 @@ pub struct RefSpecRef<'a> {
mode: Mode,
op: Operation,
src: Option<&'a bstr::BStr>,
dest: Option<&'a bstr::BStr>,
dst: Option<&'a bstr::BStr>,
}

/// An owned refspec.
Expand All @@ -20,7 +20,7 @@ pub struct RefSpec {
mode: Mode,
op: Operation,
src: Option<bstr::BString>,
dest: Option<bstr::BString>,
dst: Option<bstr::BString>,
}

mod spec;
Expand Down
28 changes: 23 additions & 5 deletions git-refspec/src/parse.rs
Expand Up @@ -12,25 +12,43 @@ pub(crate) mod function {
use bstr::{BStr, ByteSlice};

/// Parse `spec` for use in `operation` and return it if it is valid.
pub fn parse(mut spec: &BStr, _operation: Operation) -> Result<RefSpecRef<'_>, Error> {
pub fn parse(mut spec: &BStr, operation: Operation) -> Result<RefSpecRef<'_>, Error> {
let mode = match spec.get(0) {
Some(&b'^') => {
spec = &spec[1..];
Mode::Negative
}
Some(&b'+') => {
spec = &spec[1..];
Mode::Force
}
Some(_) => Mode::Normal,
None => return Err(Error::Empty),
};

match spec.find_byte(b':') {
let (src, dst) = match spec.find_byte(b':') {
Some(pos) => {
let (_src, _dst) = spec.split_at(pos);
let (src, dst) = spec.split_at(pos);
let dst = &dst[1..];
if mode == Mode::Negative {
return Err(Error::NegativeWithDestination);
}
todo!("with colon")
let src = (!src.is_empty()).then(|| src.as_bstr());
let dst = (!dst.is_empty()).then(|| dst.as_bstr());
match (src, dst) {
(None, None) => {}
_ => todo!("src or dst handling"),
};
(src, dst)
}
None => todo!("no colon"),
}
};

Ok(RefSpecRef {
op: operation,
mode,
src,
dst,
})
}
}
14 changes: 7 additions & 7 deletions git-refspec/src/spec.rs
Expand Up @@ -14,25 +14,25 @@ impl RefSpecRef<'_> {
fn has_pattern(item: &BStr) -> bool {
item.contains(&b'*')
}
match (self.op, self.mode, self.src, self.dest) {
match (self.op, self.mode, self.src, self.dst) {
(Operation::Push, Mode::Normal | Mode::Force, Some(src), None) => Instruction::Push(Push::Single {
src,
dest: src,
dst: src,
allow_non_fast_forward: matches!(self.mode, Mode::Force),
}),
(Operation::Push, Mode::Normal | Mode::Force, None, None) => Instruction::Push(Push::AllMatchingBranches {
allow_non_fast_forward: matches!(self.mode, Mode::Force),
}),
(Operation::Push, Mode::Normal | Mode::Force, Some(src), Some(dest)) if has_pattern(src) => {
(Operation::Push, Mode::Normal | Mode::Force, Some(src), Some(dst)) if has_pattern(src) => {
Instruction::Push(Push::MultipleWithGlob {
src,
dest,
dst,
allow_non_fast_forward: matches!(self.mode, Mode::Force),
})
}
(Operation::Push, Mode::Normal | Mode::Force, Some(src), Some(dest)) => Instruction::Push(Push::Single {
(Operation::Push, Mode::Normal | Mode::Force, Some(src), Some(dst)) => Instruction::Push(Push::Single {
src,
dest,
dst,
allow_non_fast_forward: matches!(self.mode, Mode::Force),
}),
(Operation::Push, Mode::Negative, Some(src), None) if has_pattern(src) => {
Expand All @@ -57,7 +57,7 @@ impl RefSpecRef<'_> {
mode: self.mode,
op: self.op,
src: self.src.map(ToOwned::to_owned),
dest: self.dest.map(ToOwned::to_owned),
dst: self.dst.map(ToOwned::to_owned),
}
}
}
13 changes: 9 additions & 4 deletions git-refspec/src/types.rs
Expand Up @@ -33,6 +33,11 @@ pub enum Push<'a> {
/// If true, allow non-fast-forward updates of the matched destination branch.
allow_non_fast_forward: bool,
},
/// Delete the destination ref or glob pattern, with only a single `*` allowed.
Delete {
/// The reference or pattern to delete on the remote.
ref_or_pattern: &'a BStr,
},
/// Exclude a single ref.
ExcludeSingle {
/// A single full ref name to exclude.
Expand All @@ -48,7 +53,7 @@ pub enum Push<'a> {
/// The source ref or refspec to push.
src: &'a BStr,
/// The ref to update with the object from `src`.
dest: &'a BStr,
dst: &'a BStr,
/// If true, allow non-fast-forward updates of `dest`.
allow_non_fast_forward: bool,
},
Expand All @@ -57,7 +62,7 @@ pub enum Push<'a> {
/// The source ref to match against all refs for pushing.
src: &'a BStr,
/// The ref to update with object obtained from `src`, filling in the `*` with the portion that matched in `src`.
dest: &'a BStr,
dst: &'a BStr,
/// If true, allow non-fast-forward updates of `dest`.
allow_non_fast_forward: bool,
},
Expand All @@ -83,7 +88,7 @@ pub enum Fetch<'a> {
/// The ref name to fetch on the remote side.
src: &'a BStr,
/// The local destination to update with what was fetched.
dest: &'a BStr,
dst: &'a BStr,
/// If true, allow non-fast-forward updates of `dest`.
allow_non_fast_forward: bool,
},
Expand All @@ -92,7 +97,7 @@ pub enum Fetch<'a> {
/// The ref glob to match against all refs on the remote side for fetching.
src: &'a BStr,
/// The local destination to update with what was fetched by replacing the single `*` with the matching portion from `src`.
dest: &'a BStr,
dst: &'a BStr,
/// If true, allow non-fast-forward updates of `dest`.
allow_non_fast_forward: bool,
},
Expand Down
7 changes: 6 additions & 1 deletion git-refspec/tests/parse/mod.rs
Expand Up @@ -75,14 +75,19 @@ mod invalid {
use git_refspec::{Instruction, Push};

#[test]
#[ignore]
fn colon_alone_is_for_pushing_matching_refs() {
assert_parse(
":",
Instruction::Push(Push::AllMatchingBranches {
allow_non_fast_forward: false,
}),
);
assert_parse(
"+:",
Instruction::Push(Push::AllMatchingBranches {
allow_non_fast_forward: true,
}),
);
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions gitoxide-core/src/repository/revision/resolve.rs
Expand Up @@ -7,7 +7,7 @@ pub struct Options {
}

pub(crate) mod function {
use anyhow::{bail, Context};
use anyhow::Context;
use std::ffi::OsString;

use git_repository as git;
Expand Down Expand Up @@ -45,7 +45,7 @@ pub(crate) mod function {
#[cfg(feature = "serde1")]
OutputFormat::Json => {
if explain {
bail!("Explanations are only for human consumption")
anyhow::bail!("Explanations are only for human consumption")
}
serde_json::to_writer_pretty(
&mut out,
Expand Down

0 comments on commit 6e5bd5c

Please sign in to comment.