Skip to content

Commit a6110a9

Browse files
committed
add ssh sign feature
1 parent ebc994d commit a6110a9

23 files changed

+911
-62
lines changed

Diff for: Cargo.lock

+741-12
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: Cargo.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ tempfile = "3.4"
5959
maintenance = { status = "actively-developed" }
6060

6161
[features]
62-
default = ["ghemoji", "regex-fancy", "trace-libgit", "vendor-openssl"]
62+
default = ["asyncgit/common-lib", "ghemoji", "regex-fancy", "trace-libgit", "vendor-openssl"]
6363
ghemoji = ["gh-emoji"]
6464
# regex-* features are mutually exclusive.
6565
regex-fancy = ["syntect/regex-fancy"]

Diff for: asyncgit/Cargo.toml

+3-1
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ rayon = "1.8"
2727
rayon-core = "1.12"
2828
scopetime = { path = "../scopetime", version = "0.1" }
2929
serde = { version = "1.0", features = ["derive"] }
30+
ssh-key = { version = "0.6.4", features = ["crypto", "encryption"] }
3031
thiserror = "1.0"
3132
unicode-truncate = "0.2.0"
3233
url = "2.5"
@@ -39,6 +40,7 @@ serial_test = "1.0"
3940
tempfile = "3.4"
4041

4142
[features]
42-
default = ["trace-libgit"]
43+
common-lib = []
44+
default = ["common-lib", "trace-libgit"]
4345
trace-libgit = []
4446
vendor-openssl = ["openssl-sys"]

Diff for: asyncgit/src/error.rs

+4
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,10 @@ pub enum Error {
8484
///
8585
#[error("git hook error: {0}")]
8686
Hooks(#[from] git2_hooks::HooksError),
87+
88+
///
89+
#[error("ssh key error: {0}")]
90+
SshKeyError(#[from] ssh_key::Error),
8791
}
8892

8993
///

Diff for: asyncgit/src/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,8 @@ pub use crate::{
7575
treefiles::AsyncTreeFilesJob,
7676
};
7777
pub use git2::message_prettify;
78+
#[cfg(feature = "common-lib")]
79+
pub use ssh_key;
7880
use std::{
7981
collections::hash_map::DefaultHasher,
8082
hash::{Hash, Hasher},

Diff for: asyncgit/src/sync/blame.rs

+4-4
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ mod tests {
175175
File::create(root.join(file_path))?.write_all(b"line 1\n")?;
176176

177177
stage_add_file(repo_path, file_path)?;
178-
commit(repo_path, "first commit")?;
178+
commit(repo_path, "first commit", None)?;
179179

180180
let blame = blame_file(repo_path, "foo", None)?;
181181

@@ -199,7 +199,7 @@ mod tests {
199199
file.write(b"line 2\n")?;
200200

201201
stage_add_file(repo_path, file_path)?;
202-
commit(repo_path, "second commit")?;
202+
commit(repo_path, "second commit", None)?;
203203

204204
let blame = blame_file(repo_path, "foo", None)?;
205205

@@ -233,7 +233,7 @@ mod tests {
233233
assert_eq!(blame.lines.len(), 2);
234234

235235
stage_add_file(repo_path, file_path)?;
236-
commit(repo_path, "third commit")?;
236+
commit(repo_path, "third commit", None)?;
237237

238238
let blame = blame_file(repo_path, "foo", None)?;
239239

@@ -258,7 +258,7 @@ mod tests {
258258
.unwrap();
259259

260260
stage_add_file(repo_path, file_path).unwrap();
261-
commit(repo_path, "first commit").unwrap();
261+
commit(repo_path, "first commit", None).unwrap();
262262

263263
assert!(blame_file(repo_path, "bar\\foo", None).is_ok());
264264
}

Diff for: asyncgit/src/sync/commit.rs

+53-16
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ use crate::{
55
};
66
use git2::{ErrorCode, ObjectType, Repository, Signature};
77
use scopetime::scope_time;
8+
use ssh_key::{HashAlg, LineEnding, PrivateKey};
89

910
///
1011
pub fn amend(
@@ -61,7 +62,11 @@ pub(crate) fn signature_allow_undefined_name(
6162
}
6263

6364
/// this does not run any git hooks, git-hooks have to be executed manually, checkout `hooks_commit_msg` for example
64-
pub fn commit(repo_path: &RepoPath, msg: &str) -> Result<CommitId> {
65+
pub fn commit(
66+
repo_path: &RepoPath,
67+
msg: &str,
68+
sk: Option<&PrivateKey>,
69+
) -> Result<CommitId> {
6570
scope_time!("commit");
6671

6772
let repo = repo(repo_path)?;
@@ -78,17 +83,49 @@ pub fn commit(repo_path: &RepoPath, msg: &str) -> Result<CommitId> {
7883
};
7984

8085
let parents = parents.iter().collect::<Vec<_>>();
81-
82-
Ok(repo
83-
.commit(
84-
Some("HEAD"),
86+
if let Some(sk) = sk {
87+
let buffer = repo.commit_create_buffer(
8588
&signature,
8689
&signature,
8790
msg,
8891
&tree,
8992
parents.as_slice(),
90-
)?
91-
.into())
93+
)?;
94+
let content = String::from_utf8(buffer.to_vec())?;
95+
let sig = sk
96+
.sign("git", HashAlg::Sha256, &buffer)?
97+
.to_pem(LineEnding::LF)?;
98+
let commit_id = repo.commit_signed(&content, &sig, None)?;
99+
match repo.head() {
100+
Ok(mut head) => {
101+
head.set_target(commit_id, msg)?;
102+
}
103+
Err(_) => {
104+
let config = repo.config()?;
105+
let default_branch_name = config
106+
.get_str("init.defaultBranch")
107+
.unwrap_or("master");
108+
repo.reference(
109+
&format!("refs/heads/{}", default_branch_name),
110+
commit_id,
111+
true,
112+
msg,
113+
)?;
114+
}
115+
}
116+
Ok(commit_id.into())
117+
} else {
118+
Ok(repo
119+
.commit(
120+
Some("HEAD"),
121+
&signature,
122+
&signature,
123+
msg,
124+
&tree,
125+
parents.as_slice(),
126+
)?
127+
.into())
128+
}
92129
}
93130

94131
/// Tag a commit.
@@ -162,7 +199,7 @@ mod tests {
162199

163200
assert_eq!(get_statuses(repo_path), (0, 1));
164201

165-
commit(repo_path, "commit msg").unwrap();
202+
commit(repo_path, "commit msg", None).unwrap();
166203

167204
assert_eq!(get_statuses(repo_path), (0, 0));
168205
}
@@ -188,7 +225,7 @@ mod tests {
188225

189226
assert_eq!(get_statuses(repo_path), (0, 1));
190227

191-
commit(repo_path, "commit msg").unwrap();
228+
commit(repo_path, "commit msg", None).unwrap();
192229

193230
assert_eq!(get_statuses(repo_path), (0, 0));
194231
}
@@ -205,7 +242,7 @@ mod tests {
205242
File::create(root.join(file_path1))?.write_all(b"test1")?;
206243

207244
stage_add_file(repo_path, file_path1)?;
208-
let id = commit(repo_path, "commit msg")?;
245+
let id = commit(repo_path, "commit msg", None)?;
209246

210247
assert_eq!(count_commits(&repo, 10), 1);
211248

@@ -244,7 +281,7 @@ mod tests {
244281

245282
stage_add_file(repo_path, file_path)?;
246283

247-
let new_id = commit(repo_path, "commit msg")?;
284+
let new_id = commit(repo_path, "commit msg", None)?;
248285

249286
tag_commit(repo_path, &new_id, "tag", None)?;
250287

@@ -286,7 +323,7 @@ mod tests {
286323

287324
stage_add_file(repo_path, file_path)?;
288325

289-
let new_id = commit(repo_path, "commit msg")?;
326+
let new_id = commit(repo_path, "commit msg", None)?;
290327

291328
tag_commit(repo_path, &new_id, "tag", Some("tag-message"))?;
292329

@@ -322,13 +359,13 @@ mod tests {
322359

323360
repo.config()?.remove("user.email")?;
324361

325-
let error = commit(repo_path, "commit msg");
362+
let error = commit(repo_path, "commit msg", None);
326363

327364
assert!(matches!(error, Err(_)));
328365

329366
repo.config()?.set_str("user.email", "email")?;
330367

331-
let success = commit(repo_path, "commit msg");
368+
let success = commit(repo_path, "commit msg", None);
332369

333370
assert!(matches!(success, Ok(_)));
334371
assert_eq!(count_commits(&repo, 10), 1);
@@ -358,7 +395,7 @@ mod tests {
358395

359396
repo.config()?.remove("user.name")?;
360397

361-
let mut success = commit(repo_path, "commit msg");
398+
let mut success = commit(repo_path, "commit msg", None);
362399

363400
assert!(matches!(success, Ok(_)));
364401
assert_eq!(count_commits(&repo, 10), 1);
@@ -371,7 +408,7 @@ mod tests {
371408

372409
repo.config()?.set_str("user.name", "name")?;
373410

374-
success = commit(repo_path, "commit msg");
411+
success = commit(repo_path, "commit msg", None);
375412

376413
assert!(matches!(success, Ok(_)));
377414
assert_eq!(count_commits(&repo, 10), 2);

Diff for: asyncgit/src/sync/commit_details.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ mod tests {
144144
stage_add_file(repo_path, file_path).unwrap();
145145

146146
let msg = invalidstring::invalid_utf8("test msg");
147-
let id = commit(repo_path, msg.as_str()).unwrap();
147+
let id = commit(repo_path, msg.as_str(), None).unwrap();
148148

149149
let res = get_commit_details(repo_path, id).unwrap();
150150

Diff for: asyncgit/src/sync/commit_files.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ mod tests {
180180

181181
stage_add_file(repo_path, file_path)?;
182182

183-
let id = commit(repo_path, "commit msg")?;
183+
let id = commit(repo_path, "commit msg", None)?;
184184

185185
let diff = get_commit_files(repo_path, id, None)?;
186186

@@ -222,7 +222,7 @@ mod tests {
222222

223223
File::create(root.join(file_path1))?.write_all(b"test")?;
224224
stage_add_file(repo_path, file_path1)?;
225-
commit(repo_path, "c1")?;
225+
commit(repo_path, "c1", None)?;
226226

227227
File::create(root.join(file_path1))?
228228
.write_all(b"modified")?;

Diff for: asyncgit/src/sync/commit_revert.rs

+3-1
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ use crate::{
44
sync::{repository::repo, utils::read_file},
55
};
66
use scopetime::scope_time;
7+
use ssh_key::PrivateKey;
78

89
const GIT_REVERT_HEAD_FILE: &str = "REVERT_HEAD";
910

@@ -40,10 +41,11 @@ pub fn revert_head(repo_path: &RepoPath) -> Result<CommitId> {
4041
pub fn commit_revert(
4142
repo_path: &RepoPath,
4243
msg: &str,
44+
sk: Option<&PrivateKey>,
4345
) -> Result<CommitId> {
4446
scope_time!("commit_revert");
4547

46-
let id = crate::sync::commit(repo_path, msg)?;
48+
let id = crate::sync::commit(repo_path, msg, sk)?;
4749

4850
repo(repo_path)?.cleanup_state()?;
4951

Diff for: asyncgit/src/sync/commits_info.rs

+6-5
Original file line numberDiff line numberDiff line change
@@ -172,10 +172,10 @@ mod tests {
172172

173173
File::create(root.join(file_path))?.write_all(b"a")?;
174174
stage_add_file(repo_path, file_path).unwrap();
175-
let c1 = commit(repo_path, "commit1").unwrap();
175+
let c1 = commit(repo_path, "commit1", None).unwrap();
176176
File::create(root.join(file_path))?.write_all(b"a")?;
177177
stage_add_file(repo_path, file_path).unwrap();
178-
let c2 = commit(repo_path, "commit2").unwrap();
178+
let c2 = commit(repo_path, "commit2", None).unwrap();
179179

180180
let res = get_commits_info(repo_path, &[c2, c1], 50).unwrap();
181181

@@ -197,7 +197,7 @@ mod tests {
197197

198198
File::create(root.join(file_path))?.write_all(b"a")?;
199199
stage_add_file(repo_path, file_path).unwrap();
200-
let c1 = commit(repo_path, "subject\nbody").unwrap();
200+
let c1 = commit(repo_path, "subject\nbody", None).unwrap();
201201

202202
let res = get_commits_info(repo_path, &[c1], 50).unwrap();
203203

@@ -219,7 +219,7 @@ mod tests {
219219
stage_add_file(repo_path, file_path).unwrap();
220220

221221
let msg = invalidstring::invalid_utf8("test msg");
222-
commit(repo_path, msg.as_str()).unwrap();
222+
commit(repo_path, msg.as_str(), None).unwrap();
223223

224224
let res = get_commits_info(
225225
repo_path,
@@ -245,7 +245,8 @@ mod tests {
245245
let foo_file = Path::new("foo");
246246
File::create(root.join(foo_file))?.write_all(b"a")?;
247247
stage_add_file(repo_path, foo_file).unwrap();
248-
let c1 = commit(repo_path, "subject: foo\nbody").unwrap();
248+
let c1 =
249+
commit(repo_path, "subject: foo\nbody", None).unwrap();
249250
let c1_rev = c1.get_short_string();
250251

251252
assert_eq!(

Diff for: asyncgit/src/sync/diff.rs

+3-3
Original file line numberDiff line numberDiff line change
@@ -599,7 +599,7 @@ mod tests {
599599

600600
stage_add_file(repo_path, file_path).unwrap();
601601

602-
commit(repo_path, "commit").unwrap();
602+
commit(repo_path, "commit", None).unwrap();
603603

604604
File::create(root.join(file_path))?.write_all(b"\x00\x02")?;
605605

@@ -655,13 +655,13 @@ mod tests {
655655

656656
stage_add_file(repo_path, file_path).unwrap();
657657

658-
commit(repo_path, "").unwrap();
658+
commit(repo_path, "", None).unwrap();
659659

660660
File::create(root.join(file_path))?.write_all(b"\x00\x02")?;
661661

662662
stage_add_file(repo_path, file_path).unwrap();
663663

664-
let id = commit(repo_path, "").unwrap();
664+
let id = commit(repo_path, "", None).unwrap();
665665

666666
let diff =
667667
get_diff_commit(repo_path, id, String::new(), None)

0 commit comments

Comments
 (0)