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
use anyhow::{anyhow, Result};
use tokio::process;
async fn git(args: &[&str]) -> Result<String> {
println!("Running $ git {}", args.join(" "));
let output = process::Command::new("git").args(args).output().await?;
if output.status.success() {
Ok(String::from_utf8(output.stdout)?)
} else {
Err(anyhow!(
"Running git {} failed: {}",
args.join(" "),
output
.status
.code()
.map_or_else(|| "unknown".to_string(), |c| c.to_string())
))
}
}
async fn sha1(ref_: &str) -> Result<String> {
git(&["rev-parse", ref_])
.await
.map(|s| s.trim().to_string())
}
async fn changes(first: &str, second: &str) -> Result<Vec<String>> {
let res = tokio::try_join!(sha1(first), sha1(second));
let (first_sha1, second_sha1) = match res {
Ok((first_sha1, second_sha1)) => (first_sha1, second_sha1),
Err(e) => return Err(e),
};
Ok(git(&["diff", "--name-only", &first_sha1, &second_sha1])
.await?
.trim()
.split('\n')
.map(|s| s.to_string())
.collect())
}
pub async fn pull() -> Result<Vec<String>> {
git(&["fetch"]).await?;
let changed = changes("HEAD", "origin/master")
.await?
.iter()
.filter_map(|file| {
if file.starts_with("channels/") && file.ends_with(".toml") {
Some(format!(
"#{}",
file.trim_start_matches("channels/")
.trim_end_matches(".toml")
))
} else {
None
}
})
.collect();
git(&["pull"]).await?;
Ok(changed)
}