Rust 空命令标准输出

问题描述 投票:0回答:1

我正在使用

Command
来生成
git diff {HASH} --unified=100000 --no-color --patch-with-raw --exit-code -- {FILE}
。但我的标准输出和标准错误都是空的。我尝试了很多方法来获取标准输出(
cli.wait()
cli.stdout.take()
),但它也没有按预期工作。

pub fn get_commit_file_changes(hash: &str, file: &str) -> Option<String> {
    let file_path = format!("\"./{}\"", file);

    let mut cli = std::process::Command::new("git")
        .args([
            "diff",
            hash,
            "--unified=100000", // to get the whole file
            "--no-color",
            "--patch-with-raw",
            "--exit-code",
            "--", // to separate paths from revisions
            &file_path,
        ])
        .stdout(std::process::Stdio::piped())
        .stderr(std::process::Stdio::piped())
        .spawn()
        .expect("failed to spawn cmd process");

    let output = cli
        .wait_with_output()
        .expect("failed to wait for child process");

    if !output.status.success() {
        return None;
    }

    let stdout = String::from_utf8(output.stdout).unwrap();
    let stderr = String::from_utf8(output.stderr).unwrap();

    if !stderr.is_empty() {
        return None;
    }

    if stdout.is_empty() {
        return None;
    }

    return Some(stdout.split("\n").skip(4).collect::<Vec<&str>>().join("\n"));
}

我尝试过生成 shell(特定于操作系统),然后执行 git 命令,但它也不起作用。

#[cfg(target_os = "windows")]
const SHELL: &str = "cmd";

#[cfg(not(target_os = "windows"))]
const SHELL: &str = "sh";

#[cfg(target_os = "windows")]
const SHELL_FLAG: &str = "/C";

#[cfg(not(target_os = "windows"))]
const SHELL_FLAG: &str = "-c";

let mut cli = std::process::Command::new(SHELL)
    .args([
        SHELL_FLAG,
        "git",
        "diff",
// ...

所需输出

C:\Users\dallen\Desktop\gitty>git diff 76a9cea6bcdfc716a769e75001dadb770023a27f --unified=100000 --no-color --patch-with-raw --exit-code -- "./src-tauri/src/git/commit/mod.rs"
:100644 100644 309edda 0000000 M        src-tauri/src/git/commit/mod.rs

diff --git a/src-tauri/src/git/commit/mod.rs b/src-tauri/src/git/commit/mod.rs
index 309edda..ba536fc 100644
--- a/src-tauri/src/git/commit/mod.rs
+++ b/src-tauri/src/git/commit/mod.rs
@@ -1,286 +1,331 @@
-use std::io::Read;
+use std::{
+    io::{BufRead, BufReader, Read},
+    process::Output,
+};

 use serde::Serialize;

-use crate::utils::subprocess::create_git_cli;
+use crate::utils::subprocess::{create_git_cli, read_to_string};

 #[derive(Serialize)]
 pub struct Commit {
     pub hash: String,
     pub author: String,
     pub timestamp: u64,
     pub message: String,
     pub description: Option<String>,
 }
...
rust tauri
1个回答
0
投票

问题是由于您在文件路径周围放置的引号造成的。

如果您在 shell 中执行该命令,shell 将使用

"
,您将得到输出:

$ git diff -- "foo"
diff --git a/foo b/foo
index e69de29..5716ca5 100644
--- a/foo
+++ b/foo
@@ -0,0 +1 @@
+bar

如果在 Rust 中执行

Command::new("git").args(r#""foo""##)
,Rust 会将
"
传递给
git
,结果与此等效:

$ git diff -- \"foo\"

因为新文件名不存在,所以

git diff
输出没有差异。

通过相信 Rust 能够正确地转义路径,并通过删除

--exit-code
以确保成功退出代码(尽管存在差异),我们得到了工作代码:

pub fn get_commit_file_changes(hash: &str, file_path: &str) -> Option<String> {
    let mut cli = std::process::Command::new("git")
        .args([
            "diff",
            hash,
            "--unified=100000", // to get the whole file
            "--no-color",
            "--patch-with-raw",
            "--", // to separate paths from revisions
            &file_path,
        ])
        .stdout(std::process::Stdio::piped())
        .stderr(std::process::Stdio::piped())
        .spawn()
        .expect("failed to spawn cmd process");

    let output = cli
        .wait_with_output()
        .expect("failed to wait for child process");

    if !output.status.success() {
        return None;
    }

    let stdout = String::from_utf8(output.stdout).unwrap();
    let stderr = String::from_utf8(output.stderr).unwrap();

    if !stderr.is_empty() {
        return None;
    }

    if stdout.is_empty() {
        return None;
    }

    return Some(stdout.split("\n").skip(4).collect::<Vec<&str>>().join("\n"));
}
© www.soinside.com 2019 - 2024. All rights reserved.