Skip to content

Commit 966a9e9

Browse files
committed
support for deletion (#450)
Even though for now everything is without validation
1 parent 701d46f commit 966a9e9

File tree

6 files changed

+104
-17
lines changed

6 files changed

+104
-17
lines changed

git-refspec/src/parse.rs

+6-3
Original file line numberDiff line numberDiff line change
@@ -36,10 +36,13 @@ pub(crate) mod function {
3636
let src = (!src.is_empty()).then(|| src.as_bstr());
3737
let dst = (!dst.is_empty()).then(|| dst.as_bstr());
3838
match (src, dst) {
39-
(None, None) => {}
39+
(None, None) => (None, None), // match all
40+
(None, Some(dst)) => match operation {
41+
Operation::Push => (None, Some(dst)),
42+
Operation::Fetch => (Some("HEAD".into()), Some(dst)),
43+
},
4044
_ => todo!("src or dst handling"),
41-
};
42-
(src, dst)
45+
}
4346
}
4447
None => todo!("no colon"),
4548
};

git-refspec/src/spec.rs

+16-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
use crate::types::Push;
2-
use crate::{Instruction, Mode, Operation, RefSpec, RefSpecRef};
2+
use crate::{Fetch, Instruction, Mode, Operation, RefSpec, RefSpecRef};
33
use bstr::BStr;
44

55
/// Access
@@ -15,14 +15,29 @@ impl RefSpecRef<'_> {
1515
item.contains(&b'*')
1616
}
1717
match (self.op, self.mode, self.src, self.dst) {
18+
(Operation::Fetch, Mode::Normal | Mode::Force, Some(src), Some(dst)) => {
19+
Instruction::Fetch(Fetch::AndUpdateSingle {
20+
src,
21+
dst,
22+
allow_non_fast_forward: matches!(self.mode, Mode::Force),
23+
})
24+
}
1825
(Operation::Push, Mode::Normal | Mode::Force, Some(src), None) => Instruction::Push(Push::Single {
1926
src,
2027
dst: src,
2128
allow_non_fast_forward: matches!(self.mode, Mode::Force),
2229
}),
30+
(Operation::Push, Mode::Normal | Mode::Force, None, Some(dst)) => {
31+
Instruction::Push(Push::Delete { ref_or_pattern: dst })
32+
}
2333
(Operation::Push, Mode::Normal | Mode::Force, None, None) => Instruction::Push(Push::AllMatchingBranches {
2434
allow_non_fast_forward: matches!(self.mode, Mode::Force),
2535
}),
36+
(Operation::Fetch, Mode::Normal | Mode::Force, None, None) => {
37+
Instruction::Fetch(Fetch::AllMatchingBranches {
38+
allow_non_fast_forward: matches!(self.mode, Mode::Force),
39+
})
40+
}
2641
(Operation::Push, Mode::Normal | Mode::Force, Some(src), Some(dst)) if has_pattern(src) => {
2742
Instruction::Push(Push::MultipleWithGlob {
2843
src,

git-refspec/src/types.rs

+5
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,11 @@ pub enum Push<'a> {
7070

7171
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
7272
pub enum Fetch<'a> {
73+
/// TODO: figure out what this actually does - it's valid for sure and only fetches HEAD -> FETCH_HEAD apparently
74+
AllMatchingBranches {
75+
/// Unclear what this does, but it's allowed
76+
allow_non_fast_forward: bool,
77+
},
7378
Only {
7479
/// The ref name to fetch on the remote side, without updating the local side.
7580
src: &'a BStr,
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version https://git-lfs.github.com/spec/v1
2-
oid sha256:588dd4f20c618e60aff39c9cd47dd1300c83c39572f0c1db2c751ccbaca5709c
3-
size 9328
2+
oid sha256:515045d1eade39e1aeee1f171216ac389b8adc54af541b2ff49bf1b1ab68eae2
3+
size 9340

git-refspec/tests/fixtures/make_baseline.sh

+6
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,12 @@ baseline fetch 'HEAD:'
8484
baseline push ':refs/remotes/frotz/deleteme'
8585
baseline fetch ':refs/remotes/frotz/HEAD-to-me'
8686

87+
baseline push ':a'
88+
baseline push '+:a'
89+
90+
baseline fetch ':a'
91+
baseline fetch '+:a'
92+
8793
baseline fetch 'refs/heads/*/for-linus:refs/remotes/mine/*-blah'
8894
baseline push 'refs/heads/*/for-linus:refs/remotes/mine/*-blah'
8995

git-refspec/tests/parse/mod.rs

+69-11
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,10 @@ fn baseline() {
3131
match res {
3232
Ok(res) => match (res.is_ok(), err_code == 0) {
3333
(true, true) | (false, false) => {}
34-
_ => mismatch += 1,
34+
_ => {
35+
eprintln!("{res:?} {err_code}");
36+
mismatch += 1;
37+
}
3538
},
3639
Err(_) => {
3740
panics += 1;
@@ -40,8 +43,11 @@ fn baseline() {
4043
}
4144
if panics != 0 || mismatch != 0 {
4245
panic!(
43-
"Out of {} baseline entries, got {} mismatches and {} panics",
44-
count, mismatch, panics
46+
"Out of {} baseline entries, got {} right, ({} mismatches and {} panics)",
47+
count,
48+
count - (mismatch + panics),
49+
mismatch,
50+
panics
4551
);
4652
}
4753
}
@@ -68,11 +74,51 @@ mod invalid {
6874
}
6975
}
7076

71-
mod fetch {}
77+
mod fetch {
78+
use crate::parse::{assert_parse, b};
79+
use git_refspec::{Fetch, Instruction};
80+
81+
#[test]
82+
fn empty_lhs_colon_rhs_fetches_head_to_destination() {
83+
assert_parse(
84+
":a",
85+
Instruction::Fetch(Fetch::AndUpdateSingle {
86+
src: b("HEAD"),
87+
dst: b("a"),
88+
allow_non_fast_forward: false,
89+
}),
90+
);
91+
92+
assert_parse(
93+
"+:a",
94+
Instruction::Fetch(Fetch::AndUpdateSingle {
95+
src: b("HEAD"),
96+
dst: b("a"),
97+
allow_non_fast_forward: true,
98+
}),
99+
);
100+
}
101+
102+
#[test]
103+
fn colon_alone_is_for_fetching_into_fetchhead() {
104+
assert_parse(
105+
":",
106+
Instruction::Fetch(Fetch::AllMatchingBranches {
107+
allow_non_fast_forward: false,
108+
}),
109+
);
110+
assert_parse(
111+
"+:",
112+
Instruction::Fetch(Fetch::AllMatchingBranches {
113+
allow_non_fast_forward: true,
114+
}),
115+
);
116+
}
117+
}
72118

73119
mod push {
74-
use crate::parse::assert_parse;
75-
use git_refspec::{Instruction, Push};
120+
use crate::parse::{assert_parse, b};
121+
use git_refspec::{Instruction, Mode, Push};
76122

77123
#[test]
78124
fn colon_alone_is_for_pushing_matching_refs() {
@@ -89,23 +135,35 @@ mod invalid {
89135
}),
90136
);
91137
}
138+
139+
#[test]
140+
fn delete() {
141+
assert_parse(":a", Instruction::Push(Push::Delete { ref_or_pattern: b("a") }));
142+
let spec = assert_parse("+:a", Instruction::Push(Push::Delete { ref_or_pattern: b("a") }));
143+
assert_eq!(
144+
spec.mode(),
145+
Mode::Force,
146+
"force is set, even though it has no effect in the actual instruction"
147+
);
148+
}
92149
}
93150
}
94151

95152
mod util {
96153
use git_refspec::{Instruction, Operation, RefSpecRef};
97154

98-
// pub fn b(input: &str) -> &bstr::BStr {
99-
// input.into()
100-
// }
155+
pub fn b(input: &str) -> &bstr::BStr {
156+
input.into()
157+
}
101158

102159
pub fn try_parse(spec: &str, op: Operation) -> Result<RefSpecRef<'_>, git_refspec::parse::Error> {
103160
git_refspec::parse(spec.into(), op)
104161
}
105162

106-
pub fn assert_parse(spec: &str, expected: Instruction<'_>) {
163+
pub fn assert_parse<'a>(spec: &'a str, expected: Instruction<'_>) -> RefSpecRef<'a> {
107164
let spec = try_parse(spec, expected.operation()).expect("no error");
108-
assert_eq!(spec.instruction(), expected)
165+
assert_eq!(spec.instruction(), expected);
166+
spec
109167
}
110168
}
111169
pub use util::*;

0 commit comments

Comments
 (0)