如何在不调用" -m"的情况下自动执行git commit选项,处理内部报价?

时间:2017-04-02 11:19:21

标签: c++ git

这是我的问题。我有一个C ++脚本,它将字符串作为将用于提交消息的消息。

这适用于几乎所有情况,但是当**First Iteration** 1 - 2017-04-05 2 - 2017-04-05 3 - 2017-04-05 **Second Iteration** 1 - 2017-04-06 2 - 2017-04-06 3 - 2017-04-06 **Third Iteration** 1 - 2017-04-07 2 - 2017-04-07 3 - 2017-04-07 包含转义单引号或双引号时出现问题,因此命令如下所示:

<msg>

所以git会感到困惑。

我不想考虑如何在提交消息中转义这些引号,所以我认为最好的方法是避免使用git commit -m 'A new message \' with many escaped \" \' quotes \"' 标志,只是做一个简单的-m并以某种方式将git commit传递给vi或ed,然后退出并保存

我尝试使用ed:

<msg>

VI

git commit | ed << <msg>

正如你所看到的,我对Linux很陌生,而且我还没有在网上找到任何描述我想要做的事情。 所以问题又是:在没有调用git commit | vi << I << <msg> << :wq 标志的情况下,提交git特定消息的shell命令的正确顺序是什么。我在这里做错了什么?

1 个答案:

答案 0 :(得分:3)

如果您刚刚运行Git,请不要生成shell;直接生成git并将["git", "commit", "-m", message]作为其argv传递。在C ++中:

#include <string>

extern "C" {
    #include <sys/wait.h>
    #include <unistd.h>
}

struct child_process {
    FILE* file;
    pid_t pid;

    child_process(FILE* file_, pid_t pid_) :
        file(file_),
        pid(pid_) {}
};

template<std::size_t n> static child_process popenv(std::string const& path, std::string const (&args)[n]) {
    char const* const c_path = path.c_str();
    char const* c_argv[n + 2];

    c_argv[0] = c_path;
    c_argv[n + 1] = NULL;

    std::size_t i = 1;

    for (std::string const& arg : args) {
        c_argv[i++] = arg.c_str();
    }

    int fds[2];
    pipe(fds);
    pid_t const pid = fork();

    if (pid == -1) {
        throw std::system_error(errno, std::system_category());
    }

    if (pid == 0) {
        dup2(fds[1], 1);
        execvp(c_path, const_cast<char* const*>(c_argv));
        _exit(EXIT_FAILURE);
    }

    return child_process(fdopen(fds[0], "r"), pid);
}

static int pclosev(child_process const& process) {
    int status;

    fclose(process.file);

    if (waitpid(process.pid, &status, 0) == -1) {
        throw std::system_error(errno, std::system_category());
    }

    return status;
}
std::string const message = "A new message ' with many escaped \" ' quotes \"";
child_process p = popenv("git", {"commit", "-m", message});

// read from p.file; use pclosev() instead of pclose()

如果由于某种原因确实需要shell,请在其argv中传递消息并运行git commit -m "$1"

如果您确实需要git commit出于某种原因从标准输入中读取其消息,请运行git commit -F -。 (-可以替换为任何文件来读取该文件。)