Skip to main content

git_policy_cli/
rule_status_hints.rs

1//! What:
2//!  The pure decision of the status-hints transform:
3//!  insert
4//!       `-c advice.statusHints=false` before `git status` unless the caller set that key.
5//! Why:
6//!  Git's stock status hints suggest `git add <file>...` and `git commit -a`,
7//!  forms the
8//!      wrapper's policies reject;
9//!  the wrapper prints accurate guidance instead.
10//!
11//! In TS you'd write (pseudocode):
12//! ```ts
13//! // statusHintsOff(['status']) => ['-c', 'advice.statusHints=false', 'status']
14//! ```
15
16/// What:
17///  Bring the override reading,
18///  the global-option boundary and the rewrite helpers
19///       into this file.
20/// Why:
21///   The decision combines them;
22///  it owns no parsing of its own.
23///
24/// In TS you'd write (pseudocode):
25/// ```ts
26/// import { parseStatusPreRegion } from '../parser/status.ts';
27/// import { parseGlobalOptions } from '../parse-global-options.ts';
28/// ```
29use super::command_status::has_status_hints_override;
30use super::global_arguments::{GlobalLayout, GlobalOutcome, global_layout};
31use super::rule_argument_rewrite::{ArgumentRewrite, insert_tokens};
32/// `OsString` is owned operating-system text of raw bytes (sibling `String` must be UTF-8).
33use std::ffi::OsString;
34
35/// Tokens inserted before `status` so Git itself does not print its stock hints.
36pub const QUIET_INJECTION: &[&str] = &["-c", "advice.statusHints=false"];
37
38/// What:
39///  Whether the caller configured `advice.statusHints` before the subcommand,
40///       whatever the subcommand is.
41///  `&[OsString]` borrows the full argument list.
42/// Why:
43///   The entry point also asks this to decide whether to print its own note,
44///  and it
45///       asks about the raw arguments,
46///  before any transform ran.
47///
48/// In TS you'd write (pseudocode):
49/// ```ts
50/// function hasExplicitStatusHintsOverride(args: readonly string[]): boolean;
51/// ```
52pub fn has_explicit_status_hints_override(arguments: &[OsString]) -> bool {
53    let layout: GlobalLayout = global_layout(arguments);
54    // `&arguments[..n]` borrows the first `n` tokens: the completed global options.
55    return has_status_hints_override(&arguments[..layout.prefix_len]);
56}
57
58/// What:
59///  Decide the transform for one command line.
60/// Why:
61///   The tokens go immediately before `status`,
62///  after every caller-supplied global
63///       option,
64///  so those survive and Git still reads the inserted pair as global.
65///
66/// In TS you'd write (pseudocode):
67/// ```ts
68/// function statusHintsOff(args: readonly string[]): readonly string[];
69/// ```
70pub fn status_hints_off(arguments: &[OsString]) -> ArgumentRewrite {
71    let layout: GlobalLayout = global_layout(arguments);
72    if layout.outcome != GlobalOutcome::Command
73        || arguments[layout.prefix_len].as_encoded_bytes() != b"status"
74    {
75        return ArgumentRewrite::Unchanged;
76    }
77    if has_status_hints_override(&arguments[..layout.prefix_len]) {
78        return ArgumentRewrite::Unchanged;
79    }
80    return ArgumentRewrite::Rewritten(insert_tokens(
81        arguments,
82        layout.prefix_len,
83        QUIET_INJECTION,
84    ));
85}
86
87/// Every `status-hints-off.unit.test.ts` case and a real-Git control of the injection.
88#[cfg(test)]
89#[path = "rule_status_hints_tests.rs"]
90mod tests;