Skip to main content

tagit_diff/
lib.rs

1//! Implementation for the `tagit diff` command.
2
3use std::{io::Write, process::Command};
4
5use itertools::Itertools;
6use owo_colors::OwoColorize;
7use tagit_core::{Tagit, out};
8use tagit_workspace::{WorkspaceEntry, with_workspace_entries};
9
10/// List workspace members whose sources differ from the tag they declare.
11pub fn diff() -> anyhow::Result<()> {
12    with_workspace_entries(
13        false,
14        false,
15        |WorkspaceEntry {
16             version,
17             tag_prefix,
18             paths,
19             name,
20             ..
21         }| {
22            let tag = &*format!("{tag_prefix}{version}");
23            let no_diff = paths.is_empty()
24                || !Tagit::exists(tag)?
25                || Command::new("git")
26                    .arg("diff-index")
27                    .arg("--quiet")
28                    .arg(tag)
29                    .args(paths)
30                    .status()?
31                    .success();
32            if !no_diff {
33                out!(
34                    "differs",
35                    "{} ({}; some of {})",
36                    name.purple(),
37                    tag.dimmed(),
38                    paths.iter().map(|path| path.display()).join(" ").dimmed(),
39                );
40                let stdout = Command::new("git")
41                    .arg("--no-pager")
42                    .arg("diff")
43                    .arg("--color")
44                    .arg("-U0")
45                    .arg(tag)
46                    .arg("--")
47                    .args(paths)
48                    .output()?
49                    .stdout;
50                std::io::stdout().write_all(&stdout)?;
51            }
52            Ok(())
53        },
54    )
55}