Skip to content

Commit 0ba1b73

Browse files
committed
sketch all possible instructions of fetch and push refspecs (#450)
1 parent 5e4ee9b commit 0ba1b73

File tree

4 files changed

+113
-5
lines changed

4 files changed

+113
-5
lines changed

git-refspec/src/lib.rs

+92-1
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,83 @@ pub enum Operation {
2424
Fetch,
2525
}
2626

27+
pub enum Instruction<'a> {
28+
Push(Push<'a>),
29+
Fetch(Fetch<'a>),
30+
}
31+
32+
pub enum Push<'a> {
33+
/// Push a single ref knowing only one ref name.
34+
SingleMatching {
35+
/// The name of the ref to push from `src` to `dest`.
36+
src_and_dest: &'a BStr,
37+
/// If true, allow non-fast-forward updates of `dest`.
38+
allow_non_fast_forward: bool,
39+
},
40+
/// Exclude a single ref.
41+
ExcludeSingle {
42+
/// A single full ref name to exclude.
43+
src: &'a BStr,
44+
},
45+
/// Exclude multiple refs with single `*` glob.
46+
ExcludeMultipleWithGlob {
47+
/// A ref pattern with a single `*`.
48+
src: &'a BStr,
49+
},
50+
/// Push a single ref or refspec to a known destination ref.
51+
Single {
52+
/// The source ref or refspec to push.
53+
src: &'a BStr,
54+
/// The ref to update with the object from `src`.
55+
dest: &'a BStr,
56+
/// If true, allow non-fast-forward updates of `dest`.
57+
allow_non_fast_forward: bool,
58+
},
59+
/// Push a multiple refs to matching destination refs, with exactly a single glob on both sides.
60+
MultipleWithGlob {
61+
/// The source ref to match against all refs for pushing.
62+
src: &'a BStr,
63+
/// The ref to update with object obtained from `src`, filling in the `*` with the portion that matched in `src`.
64+
dest: &'a BStr,
65+
/// If true, allow non-fast-forward updates of `dest`.
66+
allow_non_fast_forward: bool,
67+
},
68+
}
69+
70+
pub enum Fetch<'a> {
71+
Only {
72+
/// The ref name to fetch on the remote side, without updating the local side.
73+
src: &'a BStr,
74+
},
75+
/// Exclude a single ref.
76+
ExcludeSingle {
77+
/// A single full ref name to exclude.
78+
src: &'a BStr,
79+
},
80+
/// Exclude multiple refs with single `*` glob.
81+
ExcludeMultipleWithGlob {
82+
/// A ref pattern with a single `*`.
83+
src: &'a BStr,
84+
},
85+
AndUpdateSingle {
86+
/// The ref name to fetch on the remote side.
87+
src: &'a BStr,
88+
/// The local destination to update with what was fetched.
89+
dest: &'a BStr,
90+
/// If true, allow non-fast-forward updates of `dest`.
91+
allow_non_fast_forward: bool,
92+
},
93+
/// Similar to `FetchAndUpdate`, but src and destination contain a single glob to fetch and update multiple refs.
94+
AndUpdateMultipleWithGlob {
95+
/// The ref glob to match against all refs on the remote side for fetching.
96+
src: &'a BStr,
97+
/// The local destination to update with what was fetched by replacing the single `*` with the matching portion from `src`.
98+
dest: &'a BStr,
99+
/// If true, allow non-fast-forward updates of `dest`.
100+
allow_non_fast_forward: bool,
101+
},
102+
}
103+
27104
/// A refspec with references to the memory it was parsed from.
28105
#[derive(PartialEq, Eq, Copy, Clone, Hash, Debug)]
29106
pub struct RefSpecRef<'a> {
@@ -46,8 +123,22 @@ pub mod parse;
46123
pub use parse::function::parse;
47124

48125
mod spec {
49-
use crate::{RefSpec, RefSpecRef};
126+
use crate::{Instruction, Mode, RefSpec, RefSpecRef};
127+
128+
/// Access
129+
impl RefSpecRef<'_> {
130+
/// Return the refspec mode.
131+
pub fn mode(&self) -> Mode {
132+
self.mode
133+
}
134+
135+
/// Transform the state of the refspec into an instruction making clear what to do with it.
136+
pub fn instruction(&self) -> Instruction<'_> {
137+
todo!()
138+
}
139+
}
50140

141+
/// Conversion
51142
impl RefSpecRef<'_> {
52143
/// Convert this ref into a standalone, owned copy.
53144
pub fn to_owned(&self) -> RefSpec {
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
version https://git-lfs.github.com/spec/v1
2-
oid sha256:5aac946f32882b76ca1a1d980cdd56fb812e9059ba59074ef141dd0bb4b32903
3-
size 9320
2+
oid sha256:588dd4f20c618e60aff39c9cd47dd1300c83c39572f0c1db2c751ccbaca5709c
3+
size 9328

git-refspec/tests/fixtures/make_baseline.sh

+3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ baseline fetch '^a:b'
3131
baseline fetch '^:'
3232
baseline fetch '^:b'
3333

34+
baseline fetch '^refs/heads/qa/*/*'
35+
baseline push '^refs/heads/qa/*/*'
36+
3437
baseline push 'refs/heads/*:refs/remotes/frotz'
3538
baseline push 'refs/heads:refs/remotes/frotz/*'
3639

git-refspec/tests/parse/mod.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -70,14 +70,28 @@ mod invalid {
7070

7171
mod fetch {}
7272

73-
mod push {}
73+
mod push {
74+
use crate::parse::assert_parse;
75+
use git_refspec::{Mode, Operation};
76+
77+
#[test]
78+
#[ignore]
79+
fn colon_alone_is_for_pushing_matching_refs() {
80+
assert_parse(":", Operation::Push, None, None, Mode::Normal);
81+
}
82+
}
7483
}
7584

7685
mod util {
77-
use git_refspec::{Operation, RefSpecRef};
86+
use git_refspec::{Mode, Operation, RefSpecRef};
7887

7988
pub fn try_parse(spec: &str, op: Operation) -> Result<RefSpecRef<'_>, git_refspec::parse::Error> {
8089
git_refspec::parse(spec.into(), op)
8190
}
91+
92+
pub fn assert_parse(spec: &str, op: Operation, _src: Option<&str>, _dest: Option<&str>, mode: Mode) {
93+
let spec = try_parse(spec, op).expect("no error");
94+
assert_eq!(spec.mode(), mode);
95+
}
8296
}
8397
pub use util::*;

0 commit comments

Comments
 (0)