Skip to main content

diff/
diff.rs

1//! Example of the `p4 diff` command using the builder pattern.
2//!
3//! `p4 diff` has three mutually exclusive modes, tracked at compile time by
4//! the command's type parameter:
5//!
6//! - [`Diff<Unselected>`](perforce_cli::cmd::diff::Diff): no mode selected yet — enter workspace mode with
7//!   [`Diff::force`](perforce_cli::cmd::diff::Diff::force), [`Diff::differing_only`](perforce_cli::cmd::diff::Diff::differing_only), or [`Diff::diff_nontext`](perforce_cli::cmd::diff::Diff::diff_nontext)
8#![cfg_attr(feature = "lt2019_1", doc = ".")]
9#![cfg_attr(
10    not(feature = "lt2019_1"),
11    doc = ", or stream-spec mode with [`Diff::stream_spec_mode`](perforce_cli::cmd::diff::Diff::stream_spec_mode)."
12)]
13//! - [`Diff<WorkspaceMode<M>>`](perforce_cli::cmd::diff::Diff): diff workspace files against the depot. The
14//!   inner `M` parameter isolates `-m max` ([`WorkspaceRegularMode`](perforce_cli::cmd::diff::WorkspaceRegularMode)) from
15//!   `-soptions` ([`WorkspaceDisplayMode`](perforce_cli::cmd::diff::WorkspaceDisplayMode)).
16#![cfg_attr(
17    not(feature = "lt2019_1"),
18    doc = "- [`Diff<StreamSpecMode>`](perforce_cli::cmd::diff::Diff): diff stream specs via `-As`."
19)]
20//!
21//! Run with:
22//!
23//! ```text
24//! cargo run --example diff
25//! ```
26
27use std::ffi::OsStr;
28
29use perforce_cli::P4Cli;
30use perforce_cli::cmd::DiffOptionsBuilder;
31use perforce_cli::cmd::diff::DisplayOptions;
32use perforce_cli::spawn::OutputExt1;
33use perforce_cli::spawn::ParameterizedOutput;
34#[cfg(not(feature = "lt2019_1"))]
35use perforce_cli::spawn::ParameterizedSpawn;
36
37fn main() -> std::io::Result<()> {
38    let p4 = P4Cli::default();
39
40    // Workspace mode: force a diff against head, use the unified format with
41    // whitespace-insensitive comparison, and limit output to the first 10
42    // files. `force(true)` transitions the command into `WorkspaceMode`, and
43    // `limit(10)` further transitions it into `WorkspaceRegularMode` (where
44    // `-soptions` is unavailable).
45    let mut diff = p4
46        .diff()
47        .force(true)
48        .diff_options(DiffOptionsBuilder::unified(None).ignore_all_whitespace())
49        .limit(10);
50
51    let files = [OsStr::new("//depot/project/src/...")];
52    let output = diff.output_with((&files,))?;
53    println!("{}", String::from_utf8_lossy(&output.stdout));
54
55    // Display mode: instead of full diffs, list only the unopened files that
56    // differ from the depot. `display_options` transitions `WorkspaceMode`
57    // into `WorkspaceDisplayMode`, where `-m max` is unavailable.
58    let mut list_changed = p4
59        .diff()
60        .force(true)
61        .display_options(DisplayOptions::UnopenedChanged);
62
63    let output = list_changed.output(files)?;
64    println!("{}", String::from_utf8_lossy(&output.stdout));
65
66    // Stream-spec mode: diff a privately edited stream spec against the head
67    // version of another stream. `stream_spec_mode` transitions the command
68    // into `StreamSpecMode`; the stream spec is passed to `spawn_with`.
69    #[cfg(not(feature = "lt2019_1"))]
70    {
71        let mut stream_diff = p4.diff().stream_spec_mode();
72        let mut child = stream_diff.spawn_with(("//streams/main@head",))?;
73        child.wait()?;
74    }
75
76    Ok(())
77}