History

refactor (#450)

Sebastian Thiel committed 4 years ago

Commit d37fd041 parent afc0a3d2 files · +112 −113Browse files

Showing the changes to git-refspec/src (2 of 2 files). Show all

Unified · Split

2 files
  1. git-refspec/src/match_group/mod.rs +1 −113
  2. git-refspec/src/match_group/validate.rs +111 −0
git-refspec/src/match_group/mod.rs+1−113
@@ -7,119 +7,7 @@ pub(crate) mod types; · 6 unmodified lines
7pub use types::{Item, Mapping, Outcome, Source, SourceRef};7pub use types::{Item, Mapping, Outcome, Source, SourceRef};
8 8
9///9///
10pub mod validate {10pub mod validate;
11 use crate::match_group::{Outcome, Source};
12 use bstr::BString;
13 use std::collections::BTreeMap;
14
15 /// All possible issues found while validating matched mappings.
16 #[derive(Debug, PartialEq, Eq)]
17 pub enum Issue {
18 /// Multiple sources try to write the same destination.
19 ///
20 /// Note that this issue doesn't take into consideration that these sources might contain the same object behind a reference.
21 Conflict {
22 /// The unenforced full name of the reference to be written.
23 destination_full_ref_name: BString,
24 /// The list of sources that map to this destination.
25 sources: Vec<Source>,
26 /// The list of specs that caused the mapping conflict, each matching the respective one in `sources` to allow both
27 /// `sources` and `specs` to be zipped together.
28 specs: Vec<BString>,
29 },
30 }
31
32 impl std::fmt::Display for Issue {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 match self {
35 Issue::Conflict {
36 destination_full_ref_name,
37 sources,
38 specs,
39 } => {
40 write!(
41 f,
42 "Conflicting destination {destination_full_ref_name:?} would be written by {}",
43 sources
44 .iter()
45 .zip(specs.iter())
46 .map(|(src, spec)| format!("{src} ({spec:?})"))
47 .collect::<Vec<_>>()
48 .join(", ")
49 )
50 }
51 }
52 }
53 }
54
55 /// All possible fixes corrected while validating matched mappings.
56 #[derive(Debug, PartialEq, Eq)]
57 pub enum Fix {}
58
59 /// The error returned [outcome validation][Outcome::validated()].
60 #[derive(Debug)]
61 pub struct Error {
62 /// All issues discovered during validation.
63 pub issues: Vec<Issue>,
64 }
65
66 impl std::fmt::Display for Error {
67 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
68 write!(
69 f,
70 "Found {} {} the refspec mapping to be used: \n\t{}",
71 self.issues.len(),
72 (self.issues.len() == 1)
73 .then(|| "issue that prevents")
74 .unwrap_or("issues that prevent"),
75 self.issues
76 .iter()
77 .map(|issue| issue.to_string())
78 .collect::<Vec<_>>()
79 .join("\n\t")
80 )
81 }
82 }
83
84 impl std::error::Error for Error {}
85
86 impl<'spec, 'item> Outcome<'spec, 'item> {
87 /// Validate all mappings or dissolve them into an error stating the discovered issues.
88 /// Return `(modified self, issues)` providing a fixed-up set of mappings in `self` with the fixed `issues`
89 /// provided as part of it.
90 /// Terminal issues are communicated using the [`Error`] type accordingly.
91 pub fn validated(self) -> Result<(Self, Vec<Fix>), Error> {
92 let fixed = Vec::new();
93 let mut sources_by_destinations = BTreeMap::new();
94 for (dst, (spec_index, src)) in self
95 .mappings
96 .iter()
97 .filter_map(|m| m.rhs.as_ref().map(|dst| (dst.as_ref(), (m.spec_index, &m.lhs))))
98 {
99 let sources = sources_by_destinations.entry(dst).or_insert_with(Vec::new);
100 if !sources.iter().any(|(_, lhs)| lhs == &src) {
101 sources.push((spec_index, src))
102 }
103 }
104 let mut issues = Vec::new();
105 for (dst, conflicting_sources) in sources_by_destinations.into_iter().filter(|(_, v)| v.len() > 1) {
106 issues.push(Issue::Conflict {
107 destination_full_ref_name: dst.to_owned(),
108 specs: conflicting_sources
109 .iter()
110 .map(|(spec_idx, _)| self.group.specs[*spec_idx].to_bstring())
111 .collect(),
112 sources: conflicting_sources.into_iter().map(|(_, src)| src.to_owned()).collect(),
113 })
114 }
115 if !issues.is_empty() {
116 Err(Error { issues })
117 } else {
118 Ok((self, fixed))
119 }
120 }
121 }
122}
123 11
124/// Initialization12/// Initialization
125impl<'a> MatchGroup<'a> {13impl<'a> MatchGroup<'a> {
git-refspec/src/match_group/validate.rs+111−0
@@ -0,0 +1,111 @@
1use crate::match_group::{Outcome, Source};
2use bstr::BString;
3use std::collections::BTreeMap;
4
5/// All possible issues found while validating matched mappings.
6#[derive(Debug, PartialEq, Eq)]
7pub enum Issue {
8 /// Multiple sources try to write the same destination.
9 ///
10 /// Note that this issue doesn't take into consideration that these sources might contain the same object behind a reference.
11 Conflict {
12 /// The unenforced full name of the reference to be written.
13 destination_full_ref_name: BString,
14 /// The list of sources that map to this destination.
15 sources: Vec<Source>,
16 /// The list of specs that caused the mapping conflict, each matching the respective one in `sources` to allow both
17 /// `sources` and `specs` to be zipped together.
18 specs: Vec<BString>,
19 },
20}
21
22impl std::fmt::Display for Issue {
23 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
24 match self {
25 Issue::Conflict {
26 destination_full_ref_name,
27 sources,
28 specs,
29 } => {
30 write!(
31 f,
32 "Conflicting destination {destination_full_ref_name:?} would be written by {}",
33 sources
34 .iter()
35 .zip(specs.iter())
36 .map(|(src, spec)| format!("{src} ({spec:?})"))
37 .collect::<Vec<_>>()
38 .join(", ")
39 )
40 }
41 }
42 }
43}
44
45/// All possible fixes corrected while validating matched mappings.
46#[derive(Debug, PartialEq, Eq)]
47pub enum Fix {}
48
49/// The error returned [outcome validation][Outcome::validated()].
50#[derive(Debug)]
51pub struct Error {
52 /// All issues discovered during validation.
53 pub issues: Vec<Issue>,
54}
55
56impl std::fmt::Display for Error {
57 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
58 write!(
59 f,
60 "Found {} {} the refspec mapping to be used: \n\t{}",
61 self.issues.len(),
62 (self.issues.len() == 1)
63 .then(|| "issue that prevents")
64 .unwrap_or("issues that prevent"),
65 self.issues
66 .iter()
67 .map(|issue| issue.to_string())
68 .collect::<Vec<_>>()
69 .join("\n\t")
70 )
71 }
72}
73
74impl std::error::Error for Error {}
75
76impl<'spec, 'item> Outcome<'spec, 'item> {
77 /// Validate all mappings or dissolve them into an error stating the discovered issues.
78 /// Return `(modified self, issues)` providing a fixed-up set of mappings in `self` with the fixed `issues`
79 /// provided as part of it.
80 /// Terminal issues are communicated using the [`Error`] type accordingly.
81 pub fn validated(self) -> Result<(Self, Vec<Fix>), Error> {
82 let fixed = Vec::new();
83 let mut sources_by_destinations = BTreeMap::new();
84 for (dst, (spec_index, src)) in self
85 .mappings
86 .iter()
87 .filter_map(|m| m.rhs.as_ref().map(|dst| (dst.as_ref(), (m.spec_index, &m.lhs))))
88 {
89 let sources = sources_by_destinations.entry(dst).or_insert_with(Vec::new);
90 if !sources.iter().any(|(_, lhs)| lhs == &src) {
91 sources.push((spec_index, src))
92 }
93 }
94 let mut issues = Vec::new();
95 for (dst, conflicting_sources) in sources_by_destinations.into_iter().filter(|(_, v)| v.len() > 1) {
96 issues.push(Issue::Conflict {
97 destination_full_ref_name: dst.to_owned(),
98 specs: conflicting_sources
99 .iter()
100 .map(|(spec_idx, _)| self.group.specs[*spec_idx].to_bstring())
101 .collect(),
102 sources: conflicting_sources.into_iter().map(|(_, src)| src.to_owned()).collect(),
103 })
104 }
105 if !issues.is_empty() {
106 Err(Error { issues })
107 } else {
108 Ok((self, fixed))
109 }
110 }
111}