Skip to content

Commit 6e5bd5c

Browse files
committed
first successful test for returning a refspec. (#450)
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.
1 parent 3f264af commit 6e5bd5c

File tree

6 files changed

+49
-21
lines changed

6 files changed

+49
-21
lines changed

git-refspec/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ pub struct RefSpecRef<'a> {
1111
mode: Mode,
1212
op: Operation,
1313
src: Option<&'a bstr::BStr>,
14-
dest: Option<&'a bstr::BStr>,
14+
dst: Option<&'a bstr::BStr>,
1515
}
1616

1717
/// An owned refspec.
@@ -20,7 +20,7 @@ pub struct RefSpec {
2020
mode: Mode,
2121
op: Operation,
2222
src: Option<bstr::BString>,
23-
dest: Option<bstr::BString>,
23+
dst: Option<bstr::BString>,
2424
}
2525

2626
mod spec;

git-refspec/src/parse.rs

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,25 +12,43 @@ pub(crate) mod function {
1212
use bstr::{BStr, ByteSlice};
1313

1414
/// Parse `spec` for use in `operation` and return it if it is valid.
15-
pub fn parse(mut spec: &BStr, _operation: Operation) -> Result<RefSpecRef<'_>, Error> {
15+
pub fn parse(mut spec: &BStr, operation: Operation) -> Result<RefSpecRef<'_>, Error> {
1616
let mode = match spec.get(0) {
1717
Some(&b'^') => {
1818
spec = &spec[1..];
1919
Mode::Negative
2020
}
21+
Some(&b'+') => {
22+
spec = &spec[1..];
23+
Mode::Force
24+
}
2125
Some(_) => Mode::Normal,
2226
None => return Err(Error::Empty),
2327
};
2428

25-
match spec.find_byte(b':') {
29+
let (src, dst) = match spec.find_byte(b':') {
2630
Some(pos) => {
27-
let (_src, _dst) = spec.split_at(pos);
31+
let (src, dst) = spec.split_at(pos);
32+
let dst = &dst[1..];
2833
if mode == Mode::Negative {
2934
return Err(Error::NegativeWithDestination);
3035
}
31-
todo!("with colon")
36+
let src = (!src.is_empty()).then(|| src.as_bstr());
37+
let dst = (!dst.is_empty()).then(|| dst.as_bstr());
38+
match (src, dst) {
39+
(None, None) => {}
40+
_ => todo!("src or dst handling"),
41+
};
42+
(src, dst)
3243
}
3344
None => todo!("no colon"),
34-
}
45+
};
46+
47+
Ok(RefSpecRef {
48+
op: operation,
49+
mode,
50+
src,
51+
dst,
52+
})
3553
}
3654
}

git-refspec/src/spec.rs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,25 @@ impl RefSpecRef<'_> {
1414
fn has_pattern(item: &BStr) -> bool {
1515
item.contains(&b'*')
1616
}
17-
match (self.op, self.mode, self.src, self.dest) {
17+
match (self.op, self.mode, self.src, self.dst) {
1818
(Operation::Push, Mode::Normal | Mode::Force, Some(src), None) => Instruction::Push(Push::Single {
1919
src,
20-
dest: src,
20+
dst: src,
2121
allow_non_fast_forward: matches!(self.mode, Mode::Force),
2222
}),
2323
(Operation::Push, Mode::Normal | Mode::Force, None, None) => Instruction::Push(Push::AllMatchingBranches {
2424
allow_non_fast_forward: matches!(self.mode, Mode::Force),
2525
}),
26-
(Operation::Push, Mode::Normal | Mode::Force, Some(src), Some(dest)) if has_pattern(src) => {
26+
(Operation::Push, Mode::Normal | Mode::Force, Some(src), Some(dst)) if has_pattern(src) => {
2727
Instruction::Push(Push::MultipleWithGlob {
2828
src,
29-
dest,
29+
dst,
3030
allow_non_fast_forward: matches!(self.mode, Mode::Force),
3131
})
3232
}
33-
(Operation::Push, Mode::Normal | Mode::Force, Some(src), Some(dest)) => Instruction::Push(Push::Single {
33+
(Operation::Push, Mode::Normal | Mode::Force, Some(src), Some(dst)) => Instruction::Push(Push::Single {
3434
src,
35-
dest,
35+
dst,
3636
allow_non_fast_forward: matches!(self.mode, Mode::Force),
3737
}),
3838
(Operation::Push, Mode::Negative, Some(src), None) if has_pattern(src) => {
@@ -57,7 +57,7 @@ impl RefSpecRef<'_> {
5757
mode: self.mode,
5858
op: self.op,
5959
src: self.src.map(ToOwned::to_owned),
60-
dest: self.dest.map(ToOwned::to_owned),
60+
dst: self.dst.map(ToOwned::to_owned),
6161
}
6262
}
6363
}

git-refspec/src/types.rs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ pub enum Push<'a> {
3333
/// If true, allow non-fast-forward updates of the matched destination branch.
3434
allow_non_fast_forward: bool,
3535
},
36+
/// Delete the destination ref or glob pattern, with only a single `*` allowed.
37+
Delete {
38+
/// The reference or pattern to delete on the remote.
39+
ref_or_pattern: &'a BStr,
40+
},
3641
/// Exclude a single ref.
3742
ExcludeSingle {
3843
/// A single full ref name to exclude.
@@ -48,7 +53,7 @@ pub enum Push<'a> {
4853
/// The source ref or refspec to push.
4954
src: &'a BStr,
5055
/// The ref to update with the object from `src`.
51-
dest: &'a BStr,
56+
dst: &'a BStr,
5257
/// If true, allow non-fast-forward updates of `dest`.
5358
allow_non_fast_forward: bool,
5459
},
@@ -57,7 +62,7 @@ pub enum Push<'a> {
5762
/// The source ref to match against all refs for pushing.
5863
src: &'a BStr,
5964
/// The ref to update with object obtained from `src`, filling in the `*` with the portion that matched in `src`.
60-
dest: &'a BStr,
65+
dst: &'a BStr,
6166
/// If true, allow non-fast-forward updates of `dest`.
6267
allow_non_fast_forward: bool,
6368
},
@@ -83,7 +88,7 @@ pub enum Fetch<'a> {
8388
/// The ref name to fetch on the remote side.
8489
src: &'a BStr,
8590
/// The local destination to update with what was fetched.
86-
dest: &'a BStr,
91+
dst: &'a BStr,
8792
/// If true, allow non-fast-forward updates of `dest`.
8893
allow_non_fast_forward: bool,
8994
},
@@ -92,7 +97,7 @@ pub enum Fetch<'a> {
9297
/// The ref glob to match against all refs on the remote side for fetching.
9398
src: &'a BStr,
9499
/// The local destination to update with what was fetched by replacing the single `*` with the matching portion from `src`.
95-
dest: &'a BStr,
100+
dst: &'a BStr,
96101
/// If true, allow non-fast-forward updates of `dest`.
97102
allow_non_fast_forward: bool,
98103
},

git-refspec/tests/parse/mod.rs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,14 +75,19 @@ mod invalid {
7575
use git_refspec::{Instruction, Push};
7676

7777
#[test]
78-
#[ignore]
7978
fn colon_alone_is_for_pushing_matching_refs() {
8079
assert_parse(
8180
":",
8281
Instruction::Push(Push::AllMatchingBranches {
8382
allow_non_fast_forward: false,
8483
}),
8584
);
85+
assert_parse(
86+
"+:",
87+
Instruction::Push(Push::AllMatchingBranches {
88+
allow_non_fast_forward: true,
89+
}),
90+
);
8691
}
8792
}
8893
}

gitoxide-core/src/repository/revision/resolve.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ pub struct Options {
77
}
88

99
pub(crate) mod function {
10-
use anyhow::{bail, Context};
10+
use anyhow::Context;
1111
use std::ffi::OsString;
1212

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

0 commit comments

Comments
 (0)