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