Skip to content

Commit e8c072e

Browse files
committed
refactor (#450)
1 parent c23a21d commit e8c072e

File tree

5 files changed

+182
-253
lines changed

5 files changed

+182
-253
lines changed

git-refspec/src/spec.rs

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
use crate::types::Push;
22
use crate::{Fetch, Instruction, Mode, Operation, RefSpec, RefSpecRef};
3-
use bstr::BStr;
43

54
/// Access
65
impl RefSpecRef<'_> {
@@ -11,28 +10,15 @@ impl RefSpecRef<'_> {
1110

1211
/// Transform the state of the refspec into an instruction making clear what to do with it.
1312
pub fn instruction(&self) -> Instruction<'_> {
14-
fn has_pattern(item: &BStr) -> bool {
15-
item.contains(&b'*')
16-
}
1713
match self.op {
1814
Operation::Fetch => match (self.mode, self.src, self.dst) {
1915
(Mode::Normal | Mode::Force, Some(src), None) => Instruction::Fetch(Fetch::Only { src }),
20-
(Mode::Normal | Mode::Force, Some(src), Some(dst)) if has_pattern(src) => {
21-
Instruction::Fetch(Fetch::AndUpdateMultipleWithGlob {
22-
src,
23-
dst,
24-
allow_non_fast_forward: matches!(self.mode, Mode::Force),
25-
})
26-
}
27-
(Mode::Normal | Mode::Force, Some(src), Some(dst)) => Instruction::Fetch(Fetch::AndUpdateSingle {
16+
(Mode::Normal | Mode::Force, Some(src), Some(dst)) => Instruction::Fetch(Fetch::AndUpdate {
2817
src,
2918
dst,
3019
allow_non_fast_forward: matches!(self.mode, Mode::Force),
3120
}),
32-
(Mode::Negative, Some(src), None) if has_pattern(src) => {
33-
Instruction::Fetch(Fetch::ExcludeMultipleWithGlob { src })
34-
}
35-
(Mode::Negative, Some(src), None) => Instruction::Fetch(Fetch::ExcludeSingle { src }),
21+
(Mode::Negative, Some(src), None) => Instruction::Fetch(Fetch::Exclude { src }),
3622
(mode, src, dest) => {
3723
unreachable!(
3824
"BUG: fetch instructions with {:?} {:?} {:?} are not possible",
@@ -41,7 +27,7 @@ impl RefSpecRef<'_> {
4127
}
4228
},
4329
Operation::Push => match (self.mode, self.src, self.dst) {
44-
(Mode::Normal | Mode::Force, Some(src), None) => Instruction::Push(Push::Single {
30+
(Mode::Normal | Mode::Force, Some(src), None) => Instruction::Push(Push::Matching {
4531
src,
4632
dst: src,
4733
allow_non_fast_forward: matches!(self.mode, Mode::Force),
@@ -52,22 +38,12 @@ impl RefSpecRef<'_> {
5238
(Mode::Normal | Mode::Force, None, None) => Instruction::Push(Push::AllMatchingBranches {
5339
allow_non_fast_forward: matches!(self.mode, Mode::Force),
5440
}),
55-
(Mode::Normal | Mode::Force, Some(src), Some(dst)) if has_pattern(src) => {
56-
Instruction::Push(Push::MultipleWithGlob {
57-
src,
58-
dst,
59-
allow_non_fast_forward: matches!(self.mode, Mode::Force),
60-
})
61-
}
62-
(Mode::Normal | Mode::Force, Some(src), Some(dst)) => Instruction::Push(Push::Single {
41+
(Mode::Normal | Mode::Force, Some(src), Some(dst)) => Instruction::Push(Push::Matching {
6342
src,
6443
dst,
6544
allow_non_fast_forward: matches!(self.mode, Mode::Force),
6645
}),
67-
(Mode::Negative, Some(src), None) if has_pattern(src) => {
68-
Instruction::Push(Push::ExcludeMultipleWithGlob { src })
69-
}
70-
(Mode::Negative, Some(src), None) => Instruction::Push(Push::ExcludeSingle { src }),
46+
(Mode::Negative, Some(src), None) => Instruction::Push(Push::Exclude { src }),
7147
(mode, src, dest) => {
7248
unreachable!(
7349
"BUG: push instructions with {:?} {:?} {:?} are not possible",

git-refspec/src/types.rs

Lines changed: 15 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ pub enum Instruction<'a> {
2626
Fetch(Fetch<'a>),
2727
}
2828

29-
/// Note that all sources can either be a ref-name, partial or full, or a rev-spec. Destinations can only be a partial or full ref name.
29+
/// Note that all sources can either be a ref-name, partial or full, or a rev-spec, unless specified otherwise, on the local side.
30+
/// Destinations can only be a partial or full ref names on the remote side.
3031
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
3132
pub enum Push<'a> {
3233
/// Push all local branches to the matching destination on the remote, which has to exist to be updated.
@@ -40,67 +41,40 @@ pub enum Push<'a> {
4041
ref_or_pattern: &'a BStr,
4142
},
4243
/// Exclude a single ref.
43-
ExcludeSingle {
44-
/// A single full ref name to exclude.
45-
src: &'a BStr,
46-
},
47-
/// Exclude multiple refs with single `*` glob.
48-
ExcludeMultipleWithGlob {
49-
/// A ref pattern with a single `*`.
44+
Exclude {
45+
/// A full or partial ref name to exclude, or multiple if a single `*` is used.
5046
src: &'a BStr,
5147
},
5248
/// Push a single ref or refspec to a known destination ref.
53-
Single {
54-
/// The source ref or refspec to push.
55-
src: &'a BStr,
56-
/// The ref to update with the object from `src`.
57-
dst: &'a BStr,
58-
/// If true, allow non-fast-forward updates of `dest`.
59-
allow_non_fast_forward: bool,
60-
},
61-
/// Push a multiple refs to matching destination refs, with exactly a single glob on both sides.
62-
MultipleWithGlob {
63-
/// The source ref to match against all refs for pushing, as pattern with a single `*`.
49+
Matching {
50+
/// The source ref or refspec to push. If pattern, it contains a single `*`.
6451
src: &'a BStr,
65-
/// The ref to update with object obtained from `src`, filling in the `*` with the portion that matched in `src`.
52+
/// The ref to update with the object from `src`. If `src` is a pattern, this is a pattern too.
6653
dst: &'a BStr,
6754
/// If true, allow non-fast-forward updates of `dest`.
6855
allow_non_fast_forward: bool,
6956
},
7057
}
7158

72-
/// Note that any source can either be a ref name (full or partial) or a fully spelled out hex-sha for an object.
59+
/// Note that any source can either be a ref name (full or partial) or a fully spelled out hex-sha for an object, on the remote side.
7360
///
74-
/// Destinations can only be a partial or full ref-name.
61+
/// Destinations can only be a partial or full ref-names on the local side.
7562
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
7663
pub enum Fetch<'a> {
7764
Only {
7865
/// The ref name to fetch on the remote side, without updating the local side. This will write the result into `FETCH_HEAD`.
7966
src: &'a BStr,
8067
},
8168
/// Exclude a single ref.
82-
ExcludeSingle {
83-
/// A single full ref name to exclude.
69+
Exclude {
70+
/// A single partial or full ref name to exclude on the remote, or a pattern with a single `*`.
8471
src: &'a BStr,
8572
},
86-
/// Exclude multiple refs with single `*` glob.
87-
ExcludeMultipleWithGlob {
88-
/// A ref pattern with a single `*`.
89-
src: &'a BStr,
90-
},
91-
AndUpdateSingle {
92-
/// The ref name to fetch on the remote side.
93-
src: &'a BStr,
94-
/// The local destination to update with what was fetched.
95-
dst: &'a BStr,
96-
/// If true, allow non-fast-forward updates of `dest`.
97-
allow_non_fast_forward: bool,
98-
},
99-
/// Similar to `FetchAndUpdate`, but src and destination contain a single glob to fetch and update multiple refs.
100-
AndUpdateMultipleWithGlob {
101-
/// The ref glob to match against all refs on the remote side for fetching, as pattern with a single `*`.
73+
AndUpdate {
74+
/// The ref name to fetch on the remote side, or a pattern with a single `*` to match against.
10275
src: &'a BStr,
103-
/// The local destination to update with what was fetched by replacing the single `*` with the matching portion from `src`.
76+
/// The local destination to update with what was fetched, or a pattern whose single `*` will be replaced with the matching portion
77+
/// of the `*` from `src`.
10478
dst: &'a BStr,
10579
/// If true, allow non-fast-forward updates of `dest`.
10680
allow_non_fast_forward: bool,

git-refspec/tests/parse/fetch.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
use crate::parse::{assert_parse, b};
2+
use git_refspec::{Fetch, Instruction, Mode};
3+
4+
#[test]
5+
fn exclude() {
6+
assert_parse("^a", Instruction::Fetch(Fetch::Exclude { src: b("a") }));
7+
assert_parse("^a*", Instruction::Fetch(Fetch::Exclude { src: b("a*") }));
8+
}
9+
10+
#[test]
11+
fn lhs_colon_empty_fetches_only() {
12+
assert_parse("src:", Instruction::Fetch(Fetch::Only { src: b("src") }));
13+
let spec = assert_parse("+src:", Instruction::Fetch(Fetch::Only { src: b("src") }));
14+
assert_eq!(
15+
spec.mode(),
16+
Mode::Force,
17+
"force is set, even though it has no effect in the actual instruction"
18+
);
19+
}
20+
21+
#[test]
22+
fn lhs_colon_rhs_updates_single_ref() {
23+
assert_parse(
24+
"a:b",
25+
Instruction::Fetch(Fetch::AndUpdate {
26+
src: b("a"),
27+
dst: b("b"),
28+
allow_non_fast_forward: false,
29+
}),
30+
);
31+
assert_parse(
32+
"+a:b",
33+
Instruction::Fetch(Fetch::AndUpdate {
34+
src: b("a"),
35+
dst: b("b"),
36+
allow_non_fast_forward: true,
37+
}),
38+
);
39+
40+
assert_parse(
41+
"a/*:b/*",
42+
Instruction::Fetch(Fetch::AndUpdate {
43+
src: b("a/*"),
44+
dst: b("b/*"),
45+
allow_non_fast_forward: false,
46+
}),
47+
);
48+
assert_parse(
49+
"+a/*:b/*",
50+
Instruction::Fetch(Fetch::AndUpdate {
51+
src: b("a/*"),
52+
dst: b("b/*"),
53+
allow_non_fast_forward: true,
54+
}),
55+
);
56+
}
57+
58+
#[test]
59+
fn empty_lhs_colon_rhs_fetches_head_to_destination() {
60+
assert_parse(
61+
":a",
62+
Instruction::Fetch(Fetch::AndUpdate {
63+
src: b("HEAD"),
64+
dst: b("a"),
65+
allow_non_fast_forward: false,
66+
}),
67+
);
68+
69+
assert_parse(
70+
"+:a",
71+
Instruction::Fetch(Fetch::AndUpdate {
72+
src: b("HEAD"),
73+
dst: b("a"),
74+
allow_non_fast_forward: true,
75+
}),
76+
);
77+
}
78+
79+
#[test]
80+
fn colon_alone_is_for_fetching_head_into_fetchhead() {
81+
assert_parse(":", Instruction::Fetch(Fetch::Only { src: b("HEAD") }));
82+
let spec = assert_parse("+:", Instruction::Fetch(Fetch::Only { src: b("HEAD") }));
83+
assert_eq!(spec.mode(), Mode::Force, "it's set even though it's not useful");
84+
}
85+
86+
#[test]
87+
fn empty_refspec_is_enough_for_fetching_head_into_fetchhead() {
88+
assert_parse("", Instruction::Fetch(Fetch::Only { src: b("HEAD") }));
89+
}

0 commit comments

Comments
 (0)