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
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
use std::{
    env,
    error::Error,
    fmt,
    fmt::{Display, Formatter},
    path::PathBuf,
    process::{Command, Output},
    str,
    time::Duration,
};

use git2::{Config, Repository};
use pretty_assertions::assert_eq;
use std::path::Path;
use tempfile::TempDir;

#[must_use]
pub fn run_hook(working_dir: &Path, package: &str, arguments: Vec<&str>) -> Output {
    let toml_path = calculate_cargo_toml_path(package);
    let mut cargo_arguments = vec![
        "run",
        "--locked",
        "--quiet",
        "--manifest-path",
        &toml_path,
        "--",
    ];
    cargo_arguments.extend(arguments);

    Command::new("cargo")
        .current_dir(&working_dir)
        .args(cargo_arguments)
        .output()
        .expect("failed to execute process")
}

#[derive(Debug)]
struct PathError;

impl Error for PathError {}

impl Display for PathError {
    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
        write!(f, "Path not found")
    }
}

pub fn set_co_author(working_dir: &Path, author_name: &str, author_email: &str, index: i64) {
    Command::new("git")
        .current_dir(&working_dir)
        .arg("config")
        .arg("--local")
        .arg(format!("mit.author.coauthors.{}.name", index))
        .arg(author_name)
        .output()
        .expect("failed to execute process");
    Command::new("git")
        .current_dir(&working_dir)
        .arg("config")
        .arg("--local")
        .arg(format!("mit.author.coauthors.{}.email", index))
        .arg(author_email)
        .output()
        .expect("failed to execute process");
}

pub fn set_author_expires(expiration_time: Duration, working_dir: &Path) {
    let now = format!("{}", expiration_time.as_secs());
    Command::new("git")
        .current_dir(&working_dir)
        .arg("config")
        .arg("--local")
        .arg("--type")
        .arg("expiry-date")
        .arg("mit.author.expires")
        .arg(now)
        .output()
        .expect("failed to execute process");
}

/// # Panics
///
/// if it can't calculate the path to the cargo toml
#[must_use]
pub fn calculate_cargo_toml_path(package: &str) -> String {
    let boxed_path_error = || Box::from(PathError);
    let parent_directory = |x: PathBuf| x.parent().ok_or_else(boxed_path_error).map(PathBuf::from);
    let bin_root = |x: PathBuf| x.join(package);
    let cargo_toml = |x: PathBuf| x.join("Cargo.toml");
    let path_buf_to_string = |x: PathBuf| x.to_str().ok_or_else(boxed_path_error).map(String::from);

    env::current_exe()
        .map_err(Box::<dyn Error>::from)
        .and_then(parent_directory)
        .and_then(parent_directory)
        .and_then(parent_directory)
        .and_then(parent_directory)
        .map(bin_root)
        .map(cargo_toml)
        .and_then(path_buf_to_string)
        .unwrap()
}

#[must_use]
pub fn make_config() -> Config {
    let add_repository_to_path = |x: PathBuf| x.join("repository");
    TempDir::new()
        .map(TempDir::into_path)
        .map(add_repository_to_path)
        .map(Repository::init)
        .expect("Failed to initialise the repository")
        .expect("Failed create temporary directory")
        .config()
        .expect("Failed to get configuration")
}

/// # Panics
///
/// Panics on failed test
pub fn assert_output(
    output: &Output,
    expected_stdout: &str,
    expected_stderr: &str,
    expect_success: bool,
) {
    let stdout = str::from_utf8(&output.stdout).expect("stdout couldn't be parsed");
    let stderr = str::from_utf8(&output.stderr).expect("stderr couldn't be parsed");
    assert_eq!(
        stdout,
        expected_stdout,
        "Expected stdout to be {:?}, instead it contained {:?} stderr {:?} status {:?}",
        expected_stdout,
        stdout,
        stderr,
        output.status.code()
    );
    assert_eq!(
        stderr,
        expected_stderr,
        "Expected stderr to {:?}, instead it contained {:?} stderr {:?} status {:?}",
        expected_stderr,
        stderr,
        stdout,
        output.status.code()
    );
    assert_eq!(
        output.status.success(),
        expect_success,
        "Expected status to be {:?}, instead it was {:?}  stdout {:?} stderr {:?}",
        expect_success,
        &output.status.code(),
        stdout,
        stderr
    );
}

#[must_use]
pub fn setup_working_dir() -> PathBuf {
    let add_repository = |x: PathBuf| x.join("repository");
    let temp = TempDir::new()
        .map(TempDir::into_path)
        .map(add_repository)
        .expect("Unable to make path");
    Repository::init(&temp).expect("Couldn't create repo");

    temp
}