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
//! Reporting for git-global.

use std::collections::HashMap;
use std::io::Write;

use json::{array, object};

use crate::repo::Repo;

/// A report containing the results of a git-global subcommand.
///
/// Contains overall messages and per-repo messages.
pub struct Report {
    messages: Vec<String>,
    repo_messages: HashMap<Repo, Vec<String>>,
    repos: Vec<Repo>,
    pad_repo_output: bool,
}

impl Report {
    /// Create a new `Report` for the given `Repo`s..
    pub fn new(repos: &[Repo]) -> Report {
        let mut repo_messages: HashMap<Repo, Vec<String>> = HashMap::new();
        for repo in repos {
            repo_messages.insert(repo.clone(), Vec::new());
        }
        Report {
            messages: Vec::new(),
            repos: repos.to_owned(),
            repo_messages,
            pad_repo_output: false,
        }
    }

    /// Declares the desire to separate output when showing per-repo messages.
    ///
    /// Sets flag that indicates a blank line should be inserted between
    /// messages for different repos when printing per-repo output.
    pub fn pad_repo_output(&mut self) {
        self.pad_repo_output = true;
    }

    /// Adds a message that applies to the overall operation.
    pub fn add_message(&mut self, message: String) {
        self.messages.push(message);
    }

    /// Adds a message that applies to the given repo.
    pub fn add_repo_message(&mut self, repo: &Repo, data_line: String) {
        if let Some(item) = self.repo_messages.get_mut(repo) {
            item.push(data_line)
        }
    }

    /// Writes all result messages to the given writer, as text.
    pub fn print<W: Write>(&self, writer: &mut W) {
        for msg in self.messages.iter() {
            writeln!(writer, "{}", msg).unwrap();
        }
        for repo in self.repos.iter() {
            let messages = self.repo_messages.get(repo).unwrap();
            if !messages.is_empty() {
                writeln!(writer, "{}", repo).unwrap();
                for line in messages.iter().filter(|l| !l.is_empty()) {
                    writeln!(writer, "{}", line).unwrap();
                }
                if self.pad_repo_output {
                    writeln!(writer).unwrap();
                }
            }
        }
    }

    /// Writes all result messages to the given writer, as JSON.
    pub fn print_json<W: Write>(&self, writer: &mut W) {
        let mut json = object! {
            "error" => false,
            "messages" => array![],
            "repo_messages" => object!{}
        };
        for msg in self.messages.iter() {
            json["results"]["messages"]
                .push(msg.to_string())
                .expect("Failing pushing message to JSON messages array.");
        }
        for (repo, messages) in self.repo_messages.iter() {
            json["repo_messages"][repo.path()] = array![];
            if !messages.is_empty() {
                for line in messages.iter().filter(|l| !l.is_empty()) {
                    json["repo_messages"][repo.path()]
                        .push(line.to_string())
                        .expect(
                            "Failed pushing line to JSON repo-messages array.",
                        );
                }
            }
        }
        writeln!(writer, "{:#}", json).unwrap();
    }
}