git/testutil/
create_commit.rs

1#![cfg(not(tarpaulin_include))]
2
3use std::path::Path;
4
5use lazy_static::lazy_static;
6
7use crate::{testutil::JAN_2021_EPOCH, Repository};
8
9lazy_static! {
10	static ref DEFAULT_COMMIT_OPTIONS: CreateCommitOptions = CreateCommitOptions::new();
11}
12
13/// Options for creating a new commit.
14#[derive(Debug)]
15pub struct CreateCommitOptions {
16	author_name: String,
17	author_email: String,
18	author_time: Option<i64>,
19	committer_name: Option<String>,
20	committer_email: Option<String>,
21	committer_time: i64,
22	head_name: String,
23	message: String,
24}
25
26impl CreateCommitOptions {
27	/// Create a new instance.
28	#[inline]
29	#[must_use]
30	pub fn new() -> Self {
31		Self {
32			author_name: String::from("Author"),
33			author_email: String::from("author@example.com"),
34			author_time: None,
35			committer_name: None,
36			committer_email: None,
37			committer_time: JAN_2021_EPOCH,
38			head_name: String::from("main"),
39			message: String::from("title\n\nbody"),
40		}
41	}
42
43	/// Set the author name and related email address.
44	#[inline]
45	pub fn author(&mut self, name: &str) -> &mut Self {
46		self.author_name = String::from(name);
47		self.author_email = format!("{}@example.com", name.to_lowercase());
48		self
49	}
50
51	/// Set the author name.
52	#[inline]
53	pub fn author_name(&mut self, name: &str) -> &mut Self {
54		self.author_name = String::from(name);
55		self
56	}
57
58	/// Set the author email address.
59	#[inline]
60	pub fn author_email(&mut self, email: &str) -> &mut Self {
61		self.author_email = String::from(email);
62		self
63	}
64
65	/// Set the authored commit time.
66	#[inline]
67	pub fn author_time(&mut self, time: i64) -> &mut Self {
68		self.author_time = Some(time);
69		self
70	}
71
72	/// Set the committer name and related email address.
73	#[inline]
74	pub fn committer(&mut self, name: &str) -> &mut Self {
75		self.committer_name = Some(String::from(name));
76		self.committer_email = Some(format!("{}@example.com", name.to_lowercase()));
77		self
78	}
79
80	/// Set the committer name.
81	#[inline]
82	pub fn committer_name(&mut self, name: &str) -> &mut Self {
83		self.committer_name = Some(String::from(name));
84		self
85	}
86
87	/// Set the committer email.
88	#[inline]
89	pub fn committer_email(&mut self, email: &str) -> &mut Self {
90		self.committer_email = Some(String::from(email));
91		self
92	}
93
94	/// Set the committed commit time.
95	#[inline]
96	pub fn commit_time(&mut self, time: i64) -> &mut Self {
97		self.committer_time = time;
98		self
99	}
100
101	/// Set the head name.
102	#[inline]
103	pub fn head_name(&mut self, name: &str) -> &mut Self {
104		self.head_name = String::from(name);
105		self
106	}
107
108	/// Set the commit message.
109	#[inline]
110	pub fn message(&mut self, message: &str) -> &mut Self {
111		self.message = String::from(message);
112		self
113	}
114}
115
116/// Add a path to the working index.
117///
118/// # Panics
119/// If the path cannot be added to the index.
120#[inline]
121pub fn add_path_to_index(repo: &Repository, path: &Path) {
122	repo.add_path_to_index(path).unwrap();
123}
124
125/// Remove a path to the working index.
126///
127/// # Panics
128/// If the path cannot be removed from the index.
129#[inline]
130pub fn remove_path_from_index(repo: &Repository, path: &Path) {
131	repo.remove_path_from_index(path).unwrap();
132}
133
134/// Create a commit based on the provided options. If `options` is not provided, will create a
135/// commit using the default options. This function does not add modified or new files to the stage
136/// before creating a commit.
137///
138/// # Panics
139/// If any Git operation cannot be performed.
140#[inline]
141pub fn create_commit(repository: &Repository, options: Option<&CreateCommitOptions>) {
142	let opts = options.unwrap_or(&DEFAULT_COMMIT_OPTIONS);
143	let author_sig = git2::Signature::new(
144		opts.author_name.as_str(),
145		opts.author_email.as_str(),
146		&git2::Time::new(opts.author_time.unwrap_or(opts.committer_time), 0),
147	)
148	.unwrap();
149	let committer_sig = git2::Signature::new(
150		opts.committer_name.as_ref().unwrap_or(&opts.author_name).as_str(),
151		opts.committer_email.as_ref().unwrap_or(&opts.author_email).as_str(),
152		&git2::Time::new(opts.committer_time, 0),
153	)
154	.unwrap();
155	let ref_name = format!("refs/heads/{}", opts.head_name);
156
157	repository
158		.create_commit_on_index(ref_name.as_str(), &author_sig, &committer_sig, opts.message.as_str())
159		.unwrap();
160}