Skip to content

Commit 147bb8c

Browse files
committed
feat(hooks): Reference transaction support
1 parent 85155e8 commit 147bb8c

File tree

1 file changed

+91
-1
lines changed

1 file changed

+91
-1
lines changed

src/hooks.rs

Lines changed: 91 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ impl Hooks {
114114
/// The hook should be run after any automatic note copying (see "notes.rewrite.<command>" in
115115
/// git-config(1)) has happened, and thus has access to these notes.
116116
///
117-
/// **changedd_shas:**
117+
/// **changed_shas (old, new):**
118118
/// - For the squash and fixup operation, all commits that were squashed are listed as being rewritten to the squashed commit. This means
119119
/// that there will be several lines sharing the same new-sha1.
120120
/// - The commits are must be listed in the order that they were processed by rebase.
@@ -138,6 +138,96 @@ impl Hooks {
138138

139139
Ok(())
140140
}
141+
142+
/// Run `reference-transaction` hook to signal that all reference updates have been queued to the transaction.
143+
///
144+
/// **changed_refs (old, new, name):**
145+
/// - `name` is the full name of the ref
146+
/// - `old` is zeroed out when force updating the reference regardless of its current value or
147+
/// when the reference is to be created anew
148+
///
149+
/// On success, call either
150+
/// - `run_reference_transaction_committed`
151+
/// - `run_reference_transaction_aborted`.
152+
///
153+
/// On failure, the transaction is considered aborted
154+
pub fn run_reference_transaction_prepare(
155+
&self,
156+
repo: &git2::Repository,
157+
changed_refs: &[(git2::Oid, git2::Oid, &str)],
158+
) -> Result<(), std::io::Error> {
159+
let name = "reference-transaction";
160+
let state = "prepare";
161+
let args = [state];
162+
let mut stdin = String::new();
163+
for (old_oid, new_oid, ref_name) in changed_refs {
164+
use std::fmt::Write;
165+
writeln!(stdin, "{} {} {}", old_oid, new_oid, ref_name).expect("Always writeable");
166+
}
167+
168+
let code = self.run_hook(repo, name, &args, Some(stdin.as_bytes()), &[])?;
169+
if code == 0 {
170+
Ok(())
171+
} else {
172+
log::trace!("Hook `{}` failed with code {}", name, code);
173+
Err(std::io::Error::new(
174+
std::io::ErrorKind::Interrupted,
175+
format!("`{}` hook failed with code {}", name, code),
176+
))
177+
}
178+
}
179+
180+
/// Run `reference-transaction` hook to signal that all reference updates have been applied
181+
///
182+
/// **changed_refs (old, new, name):**
183+
/// - `name` is the full name of the ref
184+
/// - `old` is zeroed out when force updating the reference regardless of its current value or
185+
/// when the reference is to be created anew
186+
pub fn run_reference_transaction_committed(
187+
&self,
188+
repo: &git2::Repository,
189+
changed_refs: &[(git2::Oid, git2::Oid, &str)],
190+
) -> Result<(), std::io::Error> {
191+
let name = "reference-transaction";
192+
let state = "committed";
193+
let args = [state];
194+
let mut stdin = String::new();
195+
for (old_oid, new_oid, ref_name) in changed_refs {
196+
use std::fmt::Write;
197+
writeln!(stdin, "{} {} {}", old_oid, new_oid, ref_name).expect("Always writeable");
198+
}
199+
200+
let code = self.run_hook(repo, name, &args, Some(stdin.as_bytes()), &[])?;
201+
log::trace!("Hook `{}` failed with code {}", name, code);
202+
203+
Ok(())
204+
}
205+
206+
/// Run `reference-transaction` hook to signal that no changes have been made
207+
///
208+
/// **changed_refs (old, new, name):**
209+
/// - `name` is the full name of the ref
210+
/// - `old` is zeroed out when force updating the reference regardless of its current value or
211+
/// when the reference is to be created anew
212+
pub fn run_reference_transaction_aborted(
213+
&self,
214+
repo: &git2::Repository,
215+
changed_refs: &[(git2::Oid, git2::Oid, &str)],
216+
) -> Result<(), std::io::Error> {
217+
let name = "reference-transaction";
218+
let state = "aborted";
219+
let args = [state];
220+
let mut stdin = String::new();
221+
for (old_oid, new_oid, ref_name) in changed_refs {
222+
use std::fmt::Write;
223+
writeln!(stdin, "{} {} {}", old_oid, new_oid, ref_name).expect("Always writeable");
224+
}
225+
226+
let code = self.run_hook(repo, name, &args, Some(stdin.as_bytes()), &[])?;
227+
log::trace!("Hook `{}` failed with code {}", name, code);
228+
229+
Ok(())
230+
}
141231
}
142232

143233
const PUSH_HOOKS: &[&str] = &[

0 commit comments

Comments
 (0)