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
|
use std::{fs::File, io::Write, path::Path, process::Command};
use tempfile::TempDir;
use crate::{DiffProvider, Git};
fn exec_git_cmd(args: &str, git_dir: &Path) {
let res = Command::new("git")
.arg("-C")
.arg(git_dir) // execute the git command in this directory
.args(args.split_whitespace())
.env_remove("GIT_DIR")
.env_remove("GIT_ASKPASS")
.env_remove("SSH_ASKPASS")
.env("GIT_TERMINAL_PROMPT", "false")
.env("GIT_AUTHOR_DATE", "2000-01-01 00:00:00 +0000")
.env("GIT_AUTHOR_EMAIL", "author@example.com")
.env("GIT_AUTHOR_NAME", "author")
.env("GIT_COMMITTER_DATE", "2000-01-02 00:00:00 +0000")
.env("GIT_COMMITTER_EMAIL", "committer@example.com")
.env("GIT_COMMITTER_NAME", "committer")
.env("GIT_CONFIG_COUNT", "2")
.env("GIT_CONFIG_KEY_0", "commit.gpgsign")
.env("GIT_CONFIG_VALUE_0", "false")
.env("GIT_CONFIG_KEY_1", "init.defaultBranch")
.env("GIT_CONFIG_VALUE_1", "main")
.output()
.unwrap_or_else(|_| panic!("`git {args}` failed"));
if !res.status.success() {
println!("{}", String::from_utf8_lossy(&res.stdout));
eprintln!("{}", String::from_utf8_lossy(&res.stderr));
panic!("`git {args}` failed (see output above)")
}
}
fn create_commit(repo: &Path, add_modified: bool) {
if add_modified {
exec_git_cmd("add -A", repo);
}
exec_git_cmd("commit -m message", repo);
}
fn empty_git_repo() -> TempDir {
let tmp = tempfile::tempdir().expect("create temp dir for git testing");
exec_git_cmd("init", tmp.path());
exec_git_cmd("config user.email test@helix.org", tmp.path());
exec_git_cmd("config user.name helix-test", tmp.path());
tmp
}
#[test]
fn missing_file() {
let temp_git = empty_git_repo();
let file = temp_git.path().join("file.txt");
File::create(&file).unwrap().write_all(b"foo").unwrap();
assert_eq!(Git.get_diff_base(&file), None);
}
#[test]
fn unmodified_file() {
let temp_git = empty_git_repo();
let file = temp_git.path().join("file.txt");
let contents = b"foo".as_slice();
File::create(&file).unwrap().write_all(contents).unwrap();
create_commit(temp_git.path(), true);
assert_eq!(Git.get_diff_base(&file), Some(Vec::from(contents)));
}
#[test]
fn modified_file() {
let temp_git = empty_git_repo();
let file = temp_git.path().join("file.txt");
let contents = b"foo".as_slice();
File::create(&file).unwrap().write_all(contents).unwrap();
create_commit(temp_git.path(), true);
File::create(&file).unwrap().write_all(b"bar").unwrap();
assert_eq!(Git.get_diff_base(&file), Some(Vec::from(contents)));
}
/// Test that `get_file_head` does not return content for a directory.
/// This is important to correctly cover cases where a directory is removed and replaced by a file.
/// If the contents of the directory object were returned a diff between a path and the directory children would be produced.
#[test]
fn directory() {
let temp_git = empty_git_repo();
let dir = temp_git.path().join("file.txt");
std::fs::create_dir(&dir).expect("");
let file = dir.join("file.txt");
let contents = b"foo".as_slice();
File::create(file).unwrap().write_all(contents).unwrap();
create_commit(temp_git.path(), true);
std::fs::remove_dir_all(&dir).unwrap();
File::create(&dir).unwrap().write_all(b"bar").unwrap();
assert_eq!(Git.get_diff_base(&dir), None);
}
/// Test that `get_file_head` does not return content for a symlink.
/// This is important to correctly cover cases where a symlink is removed and replaced by a file.
/// If the contents of the symlink object were returned a diff between a path and the actual file would be produced (bad ui).
#[cfg(any(unix, windows))]
#[test]
fn symlink() {
#[cfg(unix)]
use std::os::unix::fs::symlink;
#[cfg(not(unix))]
use std::os::windows::fs::symlink_file as symlink;
let temp_git = empty_git_repo();
let file = temp_git.path().join("file.txt");
let contents = b"foo".as_slice();
File::create(&file).unwrap().write_all(contents).unwrap();
let file_link = temp_git.path().join("file_link.txt");
symlink("file.txt", &file_link).unwrap();
create_commit(temp_git.path(), true);
assert_eq!(Git.get_diff_base(&file_link), None);
assert_eq!(Git.get_diff_base(&file), Some(Vec::from(contents)));
}
|