History

[ref] refactor

Sebastian Thiel committed 5 years ago

Commit eb0328f1 parent ce7f83b4 files · +49 −58Browse files

Unified · Split

4 files
  1. git-ref/src/store/file/transaction.rs +2 −2
  2. git-ref/src/transaction.rs +34 −37
  3. git-ref/tests/file/transaction.rs +7 −7
  4. git-ref/tests/refs.rs +6 −12
git-ref/src/store/file/transaction.rs+2−2
@@ -192,11 +192,11 @@ impl<'a> Transaction<'a> { · 191 unmodified lines
192 }192 }
193 193
194 for change in self.updates.iter_mut() {194 for change in self.updates.iter_mut() {
195 assert!(!change.update.deref, "Deref mode is turned into splits and turned off");
195 match &change.update.change {196 match &change.update.change {
196 Change::Update { .. } => {}197 Change::Update { .. } => {}
197 Change::Delete { deref, mode, .. } => {198 Change::Delete { mode, .. } => {
198 let lock = change.lock.take().expect("each ref is locked, even deletions");199 let lock = change.lock.take().expect("each ref is locked, even deletions");
199 assert!(!deref, "Deref mode is turned into splits and turned off");
200 let (rm_reflog, rm_ref) = match mode {200 let (rm_reflog, rm_ref) = match mode {
201 DeleteMode::RefAndRefLog => (true, true),201 DeleteMode::RefAndRefLog => (true, true),
202 DeleteMode::RefLogOnly => (true, false),202 DeleteMode::RefLogOnly => (true, false),
git-ref/src/transaction.rs+34−37
@@ -38,9 +38,6 @@ pub enum Change { · 37 unmodified lines
38 Update {38 Update {
39 /// How to treat the reference log.39 /// How to treat the reference log.
40 mode: UpdateMode,40 mode: UpdateMode,
41 /// If set, symbolic references will be dereferenced so the change gets applied to their target. Has no effect if the reference
42 /// isn't symbolic.
43 deref: bool,
44 /// The previous value of the ref, which will be used to assure the ref is still in the known `previous` state before41 /// The previous value of the ref, which will be used to assure the ref is still in the known `previous` state before
45 /// updating it. It will also be filled in automatically for use in the reflog, if applicable.42 /// updating it. It will also be filled in automatically for use in the reflog, if applicable.
46 previous: Option<Target>,43 previous: Option<Target>,
@@ -56,9 +53,6 @@ pub enum Change { · 9 unmodified lines
56 previous: Option<Target>,53 previous: Option<Target>,
57 /// How to thread the reference log during deletion.54 /// How to thread the reference log during deletion.
58 mode: DeleteMode,55 mode: DeleteMode,
59 /// If set, symbolic references will be dereferenced so the change gets applied to their target. Has no effect if the reference
60 /// isn't symbolic.
61 deref: bool,
62 },56 },
63}57}
64 58
@@ -69,6 +63,38 @@ pub struct RefEdit { · 4 unmodified lines
69 pub change: Change,63 pub change: Change,
70 /// The name of the reference to apply the change to64 /// The name of the reference to apply the change to
71 pub name: FullName,65 pub name: FullName,
66 /// If set, symbolic references identified by `name` will be dereferenced to have the `change` applied to their target.
67 /// This flag has no effect if the reference isn't symbolic.
68 pub deref: bool,
69}
70
71/// The way to deal with the Reflog in deletions.
72#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
73pub enum DeleteMode {
74 /// Delete the reference and the log
75 RefAndRefLog,
76 /// Delete only the reflog
77 RefLogOnly,
78}
79
80/// The way to deal with the Reflog in a particular edit
81///
82/// If the `create_unconditionally` field is set, create a reflog even if it otherwise wouldn't be created,
83/// as is the case for tags.
84#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
85pub enum UpdateMode {
86 /// As symbolic references only ever see this when you want to detach them, we won't try to dereference them
87 /// in this case and apply the change to it directly.
88 RefAndRefLog {
89 /// If set, update the reflog even if it otherwise wouldn't.
90 create_unconditionally: bool,
91 },
92 /// Only update the reflog but require this to be a symbolic ref so the actual update can be performed on the
93 /// referent.
94 RefLogOnly {
95 /// If set, update the reflog even if it otherwise wouldn't.
96 create_unconditionally: bool,
97 },
72}98}
73 99
74mod ext {100mod ext {
@@ -115,13 +141,13 @@ mod ext { · 40 unmodified lines
115 for edit in self.iter_mut() {141 for edit in self.iter_mut() {
116 let edit = edit.borrow_mut();142 let edit = edit.borrow_mut();
117 match edit.change {143 match edit.change {
118 Change::Delete { ref mut deref, .. } | Change::Update { ref mut deref, .. } => {144 Change::Delete { .. } | Change::Update { .. } => {
119 match store.find_one_existing(edit.name.to_partial()).ok() {145 match store.find_one_existing(edit.name.to_partial()).ok() {
120 Some(Target::Symbolic(_name)) => {146 Some(Target::Symbolic(_name)) => {
121 // todo!("split into new edit")147 // todo!("split into new edit")
122 }148 }
123 Some(Target::Peeled(_)) => {149 Some(Target::Peeled(_)) => {
124 *deref = false;150 edit.deref = false;
125 }151 }
126 None => {}152 None => {}
127 }153 }
@@ -134,32 +160,3 @@ mod ext { · 6 unmodified lines
134 }160 }
135}161}
136pub use ext::RefEditsExt;162pub use ext::RefEditsExt;
137
138/// The way to deal with the Reflog in deletions.
139#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
140pub enum DeleteMode {
141 /// Delete the reference and the log
142 RefAndRefLog,
143 /// Delete only the reflog
144 RefLogOnly,
145}
146
147/// The way to deal with the Reflog in a particular edit
148///
149/// If the `create_unconditionally` field is set, create a reflog even if it otherwise wouldn't be created,
150/// as is the case for tags.
151#[derive(PartialEq, Eq, Debug, Hash, Ord, PartialOrd, Clone, Copy)]
152pub enum UpdateMode {
153 /// As symbolic references only ever see this when you want to detach them, we won't try to dereference them
154 /// in this case and apply the change to it directly.
155 RefAndRefLog {
156 /// If set, update the reflog even if it otherwise wouldn't.
157 create_unconditionally: bool,
158 },
159 /// Only update the reflog but require this to be a symbolic ref so the actual update can be performed on the
160 /// referent.
161 RefLogOnly {
162 /// If set, update the reflog even if it otherwise wouldn't.
163 create_unconditionally: bool,
164 },
165}
git-ref/tests/file/transaction.rs+7−7
@@ -52,9 +52,9 @@ mod prepare_and_commit { · 51 unmodified lines
52 },52 },
53 new: Target::Symbolic(referent.try_into()?),53 new: Target::Symbolic(referent.try_into()?),
54 previous: None, // TODO: check failure if it doesn't exist54 previous: None, // TODO: check failure if it doesn't exist
55 deref: false,
56 },55 },
57 name: "HEAD".try_into()?,56 name: "HEAD".try_into()?,
57 deref: false,
58 }),58 }),
59 Fail::Immediately,59 Fail::Immediately,
60 );60 );
@@ -107,9 +107,9 @@ mod prepare_and_commit { · 46 unmodified lines
107 change: Change::Delete {107 change: Change::Delete {
108 previous: None,108 previous: None,
109 mode: DeleteMode::RefAndRefLog,109 mode: DeleteMode::RefAndRefLog,
110 deref: false,
111 },110 },
112 name: "DOES_NOT_EXIST".try_into().unwrap(),111 name: "DOES_NOT_EXIST".try_into().unwrap(),
112 deref: false,
113 }),113 }),
114 Fail::Immediately,114 Fail::Immediately,
115 )115 )
@@ -127,9 +127,9 @@ mod prepare_and_commit { · 11 unmodified lines
127 change: Change::Delete {127 change: Change::Delete {
128 previous: Some(Target::Peeled(ObjectId::null_sha1())),128 previous: Some(Target::Peeled(ObjectId::null_sha1())),
129 mode: DeleteMode::RefAndRefLog,129 mode: DeleteMode::RefAndRefLog,
130 deref: false,
131 },130 },
132 name: "DOES_NOT_EXIST".try_into().unwrap(),131 name: "DOES_NOT_EXIST".try_into().unwrap(),
132 deref: false,
133 }),133 }),
134 Fail::Immediately,134 Fail::Immediately,
135 )135 )
@@ -156,9 +156,9 @@ mod prepare_and_commit { · 20 unmodified lines
156 change: Change::Delete {156 change: Change::Delete {
157 previous: Some(Target::Peeled(ObjectId::null_sha1())),157 previous: Some(Target::Peeled(ObjectId::null_sha1())),
158 mode: DeleteMode::RefAndRefLog,158 mode: DeleteMode::RefAndRefLog,
159 deref: false,
160 },159 },
161 name: head.name().into(),160 name: head.name().into(),
161 deref: false,
162 }),162 }),
163 Fail::Immediately,163 Fail::Immediately,
164 )164 )
@@ -170,9 +170,9 @@ mod prepare_and_commit { · 5 unmodified lines
170 change: Change::Delete {170 change: Change::Delete {
171 previous: Some(Target::Symbolic("refs/heads/main".try_into()?)),171 previous: Some(Target::Symbolic("refs/heads/main".try_into()?)),
172 mode: DeleteMode::RefAndRefLog,172 mode: DeleteMode::RefAndRefLog,
173 deref: false
174 },173 },
175 name: head.name().into(),174 name: head.name().into(),
175 deref: false
176 }],176 }],
177 "the previous value was updated with the actual one"177 "the previous value was updated with the actual one"
178 );178 );
@@ -197,9 +197,9 @@ mod prepare_and_commit { · 18 unmodified lines
197 change: Change::Delete {197 change: Change::Delete {
198 previous: Some(Target::Symbolic("refs/heads/main".try_into()?)),198 previous: Some(Target::Symbolic("refs/heads/main".try_into()?)),
199 mode: DeleteMode::RefLogOnly,199 mode: DeleteMode::RefLogOnly,
200 deref: false,
201 },200 },
202 name: head.name().into(),201 name: head.name().into(),
202 deref: false,
203 }),203 }),
204 Fail::Immediately,204 Fail::Immediately,
205 )205 )
@@ -231,9 +231,9 @@ mod prepare_and_commit { · 25 unmodified lines
231 change: Change::Delete {231 change: Change::Delete {
232 previous: Some(Target::Symbolic("refs/heads/main".try_into().unwrap())),232 previous: Some(Target::Symbolic("refs/heads/main".try_into().unwrap())),
233 mode: DeleteMode::RefLogOnly,233 mode: DeleteMode::RefLogOnly,
234 deref: true,
235 },234 },
236 name: head.name().into(),235 name: head.name().into(),
236 deref: true,
237 }),237 }),
238 Fail::Immediately,238 Fail::Immediately,
239 )239 )
git-ref/tests/refs.rs+6−12
@@ -11,9 +11,9 @@ mod transaction { · 10 unmodified lines
11 change: Change::Delete {11 change: Change::Delete {
12 previous: None,12 previous: None,
13 mode: DeleteMode::RefAndRefLog,13 mode: DeleteMode::RefAndRefLog,
14 deref: false,
15 },14 },
16 name: name.try_into().expect("valid name"),15 name: name.try_into().expect("valid name"),
16 deref: false,
17 }17 }
18 }18 }
19 19
@@ -78,12 +78,6 @@ mod transaction { · 58 unmodified lines
78 }78 }
79 }79 }
80 80
81 fn is_deref(edit: &RefEdit) -> bool {
82 match edit.change {
83 Change::Delete { deref, .. } | Change::Update { deref, .. } => deref,
84 }
85 }
86
87 fn find<'a>(edits: &'a [RefEdit], name: &str) -> &'a RefEdit {81 fn find<'a>(edits: &'a [RefEdit], name: &str) -> &'a RefEdit {
88 let name: FullName = name.try_into().unwrap();82 let name: FullName = name.try_into().unwrap();
89 edits83 edits
@@ -103,36 +97,36 @@ mod transaction { · 13 unmodified lines
103 change: Change::Delete {97 change: Change::Delete {
104 previous: None,98 previous: None,
105 mode: DeleteMode::RefAndRefLog,99 mode: DeleteMode::RefAndRefLog,
106 deref: false,
107 },100 },
108 name: "SYMBOLIC_PROBABLY_BUT_DEREF_IS_FALSE_SO_IGNORED".try_into()?,101 name: "SYMBOLIC_PROBABLY_BUT_DEREF_IS_FALSE_SO_IGNORED".try_into()?,
102 deref: false,
109 },103 },
110 RefEdit {104 RefEdit {
111 change: Change::Delete {105 change: Change::Delete {
112 previous: None,106 previous: None,
113 mode: DeleteMode::RefAndRefLog,107 mode: DeleteMode::RefAndRefLog,
114 deref: true,
115 },108 },
116 name: "refs/heads/anything-but-not-symbolic".try_into()?,109 name: "refs/heads/anything-but-not-symbolic".try_into()?,
110 deref: true,
117 },111 },
118 RefEdit {112 RefEdit {
119 change: Change::Delete {113 change: Change::Delete {
120 previous: None,114 previous: None,
121 mode: DeleteMode::RefAndRefLog,115 mode: DeleteMode::RefAndRefLog,
122 deref: true,
123 },116 },
124 name: "refs/heads/does-not-exist-and-deref-is-ignored".try_into()?,117 name: "refs/heads/does-not-exist-and-deref-is-ignored".try_into()?,
118 deref: true,
125 },119 },
126 ];120 ];
127 121
128 edits.extend_with_splits_of_symbolic_refs(&store, |_| panic!("should not be called"))?;122 edits.extend_with_splits_of_symbolic_refs(&store, |_| panic!("should not be called"))?;
129 assert_eq!(edits.len(), 3, "no edit was added");123 assert_eq!(edits.len(), 3, "no edit was added");
130 assert!(124 assert!(
131 !is_deref(find(&edits, "refs/heads/anything-but-not-symbolic")),125 !find(&edits, "refs/heads/anything-but-not-symbolic").deref,
132 "the algorithm corrects these flags"126 "the algorithm corrects these flags"
133 );127 );
134 assert!(128 assert!(
135 is_deref(find(&edits, "refs/heads/does-not-exist-and-deref-is-ignored")),129 find(&edits, "refs/heads/does-not-exist-and-deref-is-ignored").deref,
136 "non-existing refs won't change the flag"130 "non-existing refs won't change the flag"
137 );131 );
138 store.assert_empty();132 store.assert_empty();