执行 p4 别名命令导致输出中的行顺序混乱

Execute p4 aliased command result in messed wrong order of lines in output

我的 p4aliases.txt.

中有以下内容
diff-cl $(target-cl) = diff -dl //...@$(EQ)$(target-cl)

基本上,它与当前工作区中的文件与更改列表的目标搁置文件不同。

很好。我可以执行它。但是,当我将来自上述别名命令的结果与直接原始(非别名)命令进行比较时,如下所示

p4 diff -dl //...@=<target-cl>

aliased 命令的输出文本行顺序错误,例如根据某个文件的更改首先显示在一行文件显示之前,行顺序混乱。如果您使用非别名命令执行,则情况并非如此。

例子


预期结果

==== //depot/common.h#none - x:\mydir\project\src\common.h ====
==== //depot/file.cpp#none - x:\mydir\project\src\file.cpp ====
3a4
> added line 1
==== //depot/file.h#none - x:\mydir\project\src\file.h ====

实际结果

3a4
> added line 1
==== //depot/common.h#none - x:\mydir\project\src\common.h ====
==== //depot/file.cpp#none - x:\mydir\project\src\file.cpp ====
==== //depot/file.h#none - x:\mydir\project\src\file.h ====

我有 p4 版本 P4/NTX64/2021.1/2126753 (2021/05/12). Perforce 服务器版本(从 p4 info 获得)是 Server version: P4D/LINUX26X86_64/2017.1/1574018 (2017/10/02).

我该如何解决这个问题?

会不会是客户端和服务器版本太远了

更新

我通过从 ftp.perforce.com(在目录 perforce 中)下载旧的二进制文件,从 2016-2020 版本一直测试 p4 客户端。没运气。输出仍然一团糟。所以不是版本不匹配的问题

这看起来像是 p4 客户端中的错误。当客户端做 diff 时,它是由 ClientUser::Diff() 方法编写的,默认写入标准输出(即它不通过 ClientUser::OutputText() 路由输出):

https://workshop.perforce.com/projects/perforce_software-p4/files/2018-2/client/clientuser.cc#436 https://workshop.perforce.com/projects/perforce_software-p4/files/2018-2/client/clientuser.cc#573

命令 运行 的输出作为别名的一部分通过 ClientUserStrBuf 子类,该子类缓冲其所有输出。例如,文件 headers 由 ClientUserStrBuf::OutputInfo():

缓冲

https://workshop.perforce.com/projects/perforce_software-p4/files/2018-2/client/clientaliases.cc#1647

虽然没有 ClientUserStrBuf::Diff() 实现,因此 diff 输出直接进入标准输出,而 headers 被缓冲并在最后打印(大概在一些 post-processing 之后) -- 因此 diff 输出首先出现在控制台中。

我要做的修复是让基础 ClientUser::Diff() 实现在没有提供输出文件时通过 OutputText() 路由输出,这看起来像 least-surprise 行为;这将修复别名行为,甚至可能使其他可能遇到相同问题的客户端开发人员的生活变得更轻松。如果您与 Perforce 签订了支持合同,您可以将其作为错误报告提交,或者由于客户端是开源的,您可以自行修复和构建它。我认为没有不涉及修改客户端源代码的解决方法。

Samwise 有正确的方法来真正解决手头的问题,尽管理解代码并自行修复可能需要一些努力。

无论如何,如果我们采用这种方法,我们将无法利用错误修复和未来更新的好处,因为我们将坚持使用 p4 的 2018-2 版本,因为它是最新的可以在里面抓取源码

对于基于 Windows 的项目,我建议使用 WSL 然后与 p4.exe(是的,基于 Windows 的二进制文件)交互,对于 Linux-基于二进制。如果您没有使用 WSL,请找到我下面的类似 .bash_aliases 的解决方案来无缝解决别名 diff 操作。

将以下代码放入您的 ~/.bash_aliases

# p4 - fix of aliases diff operation
# platform independent, it will choose a correct binary path to execute properly
p4() {                                                                                                                                                                                                                                                                              cmd="p4.exe"    # default is Windows-based

    # get the last argument value, if "-lx" passed in then we know it's linux
    if [[ "${@: -1}" == "-lx" ]]; then
        cmd="/usr/local/bin/p4"
    fi

    if [[  == "diff-cl" ]]; then
        if [ -z "" ]; then
            echo "usage: p4 diff-cl <CL>"
            return 1
        fi
        $cmd diff -dl //...@= | diffp4 | less -r
    elif [[  == "diff-cl-fonly" ]]; then
        if [ -z "" ]; then
            echo "usage: p4 diff-cl-fonly <CL>"
            return 1
        fi
        $cmd diff -Od -dl -ds //...@= | diffp4 | grep ==== | less -r

    else
        $cmd "$@"
    fi
}

然后 source ~/.bash_aliases.

它的作用是允许您仍然使用 p4 及其所有原始命令和参数,通常 diff-cl 除外(这是我输入的别名的相同名称p4aliases.txt 对应 Windows 或 ~/.p4aliases 对应 Linux)。您可以安全地从 p4 的别名文件中删除 diff-cl 条目,或者将其保留在那里。我们在 ~/.bash_aliases 文件中的内容将在此类参数匹配时拦截然后执行原始命令,只是我们不必自己键入长命令。

我们稍后可以在上游 p4 修复后删除 ~/.bash_aliases 文件中的此类部分。

else部分,我们只是传递了所有的论点,它会照常执行。

Extra: diff-cl-fonly 仅列出有更改的文件(其仓库路径和本地工作区路径)。