1use chrono::prelude::*;
2use git2::Repository;
3use pathdiff;
4
5use crate::{errors::DiaryError, utils::git, Diary};
6pub struct CommitOptions {
7 pub entry_date: DateTime<Local>,
9 pub message: String,
10 pub push: bool,
11}
12
13pub fn commit(opts: &CommitOptions, diary: &Diary) -> Result<(), DiaryError> {
14 let entry_path = diary.get_entry_path(&opts.entry_date);
15 let relative_path = pathdiff::diff_paths(entry_path, diary.diary_path()).unwrap();
16
17 let repo = Repository::open(diary.diary_path())?;
18
19 git::add_and_commit(&repo, &relative_path, &opts.message)?;
20
21 if opts.push {
22 git::push_to_origin(&repo)?;
23 }
24 Ok(())
25}
26
27#[cfg(test)]
28mod test {
29 use chrono::prelude::*;
30 use git2::Repository;
31
32 use super::{commit, CommitOptions};
33 use crate::{
34 ops::{init, testing, InitOptions},
35 utils::git,
36 Diary,
37 };
38
39 #[test]
40 fn commit_today() {
41 let config = testing::temp_config();
42
43 let init_opts = InitOptions {
44 path: testing::temp_path(),
45 prefix: None,
46 git_repo: true,
47 };
48 init(&init_opts, config.diary_path()).unwrap();
49
50 let entry_date = Local.with_ymd_and_hms(2022, 1, 13, 0, 0, 0).unwrap();
51 testing::new_entry(&config, &entry_date);
52
53 let opts = CommitOptions {
54 entry_date,
55 message: "Test message".to_string(),
56 push: false,
57 };
58 let repo = Repository::open(config.diary_path()).unwrap();
59
60 let diary = Diary::from_config(&config).unwrap();
61 commit(&opts, &diary).unwrap();
62
63 let last_commit = git::find_last_commit(&repo).unwrap();
64 commit(&opts, &diary).unwrap();
65 assert!(last_commit.is_some());
66
67 let index = repo.index().unwrap();
68 assert_eq!(index.len(), 1)
69 }
70
71 #[test]
72 fn commit_multiple() {
73 let config = testing::temp_config();
74
75 let init_opts = InitOptions {
76 path: testing::temp_path(),
77 prefix: None,
78 git_repo: true,
79 };
80 init(&init_opts, config.diary_path()).unwrap();
81
82 let entry_date = Local.with_ymd_and_hms(2022, 1, 13, 0, 0, 0).unwrap();
83 testing::new_entry(&config, &entry_date);
84
85 let opts = CommitOptions {
86 entry_date,
87 message: "Test message".to_string(),
88 push: false,
89 };
90 let repo = Repository::open(config.diary_path()).unwrap();
91
92 let diary = Diary::from_config(&config).unwrap();
93 commit(&opts, &diary).unwrap();
94
95 let last_commit = git::find_last_commit(&repo).unwrap();
96 assert!(last_commit.is_some());
97
98 let entry_date = Local.with_ymd_and_hms(2022, 1, 14, 0, 0, 0).unwrap();
99 testing::new_entry(&config, &entry_date);
100
101 let opts = CommitOptions {
102 entry_date,
103 message: "Test message".to_string(),
104 push: false,
105 };
106 let repo = Repository::open(config.diary_path()).unwrap();
107
108 commit(&opts, &diary).unwrap();
109
110 let last_commit = git::find_last_commit(&repo).unwrap();
111 assert!(last_commit.is_some());
112
113 let index = repo.index().unwrap();
114 assert_eq!(index.len(), 2)
115 }
116
117 #[test]
118 #[should_panic(expected = "No such file or directory")]
119 fn commit_no_entry() {
120 let config = testing::temp_config();
121
122 let init_opts = InitOptions {
123 path: testing::temp_path(),
124 prefix: None,
125 git_repo: true,
126 };
127 init(&init_opts, config.diary_path()).unwrap();
128
129 let entry_date = Local.with_ymd_and_hms(2022, 1, 13, 0, 0, 0).unwrap();
130
131 let opts = CommitOptions {
132 entry_date,
133 message: "Test message".to_string(),
134 push: false,
135 };
136
137 let diary = Diary::from_config(&config).unwrap();
138 commit(&opts, &diary).unwrap();
139 }
140
141 #[test]
142 #[should_panic(expected = "remote 'origin' does not exist")]
143 fn commit_and_fail_to_push() {
144 let config = testing::temp_config();
145
146 let init_opts = InitOptions {
147 path: testing::temp_path(),
148 prefix: None,
149 git_repo: true,
150 };
151 init(&init_opts, config.diary_path()).unwrap();
152
153 let entry_date = Local.with_ymd_and_hms(2022, 1, 13, 0, 0, 0).unwrap();
154
155 testing::new_entry(&config, &entry_date);
156
157 let opts = CommitOptions {
158 entry_date,
159 message: "Test message".to_string(),
160 push: true,
161 };
162
163 let diary = Diary::from_config(&config).unwrap();
164 commit(&opts, &diary).unwrap();
165 }
166}