1use serde_derive::Deserialize;
2
3mod changelog;
4mod cli;
5mod error;
6mod git;
7
8pub use crate::changelog::{format, stats};
9pub use crate::cli::Cli;
10pub use crate::error::{Error, ErrorKind, Result};
11pub use crate::git::{all_commits, full_diff, Commit, Tag};
12
13use failure::ResultExt;
14use mktemp::Temp;
15use std::env;
16use std::fs::{self, File, OpenOptions};
17use std::io::{self, Write};
18use std::path::PathBuf;
19
20#[derive(Deserialize)]
21struct Config {
22 package: Package,
23}
24
25#[derive(Deserialize)]
26struct Package {
27 repository: String,
28}
29
30pub fn read_repo(dir: &str) -> crate::Result<String> {
33 let mut dir = PathBuf::from(dir);
34 dir.push("Cargo.toml");
35
36 let config = if dir.exists() {
37 let cargo_toml =
38 fs::read_to_string(dir).context(crate::ErrorKind::Other)?;
39 toml::from_str(&cargo_toml).context(crate::ErrorKind::Other)?
40 } else {
41 dir.pop();
42 Config {
43 package: Package {
44 repository: read_path_name(&dir).context(crate::ErrorKind::Other)?,
45 },
46 }
47 };
48 Ok(config.package.repository)
49}
50
51pub fn read_path_name(dir: &PathBuf) -> crate::Result<String> {
53 let path_name = if dir.eq(&PathBuf::from(".")) {
55 let path = env::current_dir()?;
56
57 String::from(
58 path
59 .file_name()
60 .ok_or_else(|| crate::ErrorKind::Other)?
61 .to_str()
62 .ok_or_else(|| crate::ErrorKind::Other)?,
63 )
64 } else {
65 String::from(
66 dir
67 .file_name()
68 .ok_or_else(|| crate::ErrorKind::Other)?
69 .to_str()
70 .ok_or_else(|| crate::ErrorKind::Other)?,
71 )
72 };
73
74 Ok(path_name)
75}
76
77pub fn prepend_file(file_path: &str, data: &str) -> crate::Result<()> {
79 let file_path = PathBuf::from(file_path);
80
81 let file = OpenOptions::new()
83 .create(true)
84 .append(true)
85 .open(&file_path)
86 .context(crate::ErrorKind::Other)?;
87 file.sync_all().context(crate::ErrorKind::Other)?;
88
89 let tmp_path = Temp::new_file().context(crate::ErrorKind::Other)?;
91 let mut tmp = File::create(&tmp_path).context(crate::ErrorKind::Other)?;
92 let mut src = File::open(&file_path).context(crate::ErrorKind::Other)?;
93
94 tmp
96 .write_all(data.as_bytes())
97 .context(crate::ErrorKind::Other)?;
98 tmp.write(b"\n\n").context(crate::ErrorKind::Other)?;
99 io::copy(&mut src, &mut tmp).context(crate::ErrorKind::Other)?;
100
101 fs::remove_file(&file_path).context(crate::ErrorKind::Other)?;
103 fs::copy(&tmp_path, &file_path).context(crate::ErrorKind::Other)?;
104
105 Ok(())
106}