【问题标题】:Windows diff tool to extract lines of code written and time spend [closed]Windows diff 工具,用于提取编写的代码行和时间花费 [关闭]
【发布时间】:2026-02-15 01:05:02
【问题描述】:

是否有适用于 Windows 的工具可以读取 Delphi 历史文件。
并提取每个会话编写的代码行以及会话的时间戳。

我想要什么信息

session_id   date+time             filename      lines_of_code changed
1            1-1-2011 - 13:14:36   unit1.pas     100
....

我必须从中提取什么信息
我正在使用 Delphi 2007。
源文件中的每一次更改都会写入一个名为 history 的子目录,如下所示:

name                date_changed    type     size
project1.dpr.~1~    date-time       ~1~      1  kb
project1.dpr.~2~    date-time       ~2~      1  kb
unit1.pas.~1~       date-time       ~1~      83 kb
...

每个历史文件都包含完整的源代码,而不仅仅是差异。
(因此,如果您想恢复到源文件,您可以只对旧文件进行编码)

不是颠覆
未来我将使用颠覆程序来跟踪这些东西,但对于过去的东西我也想有一些记录。
因此,除非 subversion 克隆可以索引 history 文件夹中的旧源文件备份,否则我现在不会寻找它。

【问题讨论】:

  • 我从未见过能够准确处理编程会话中发生的事情的自动化工具。当您尝试从历史文件的时间戳推断所花费的时间时,情况将更加如此。查看但不更改文件怎么办?那是花在问题上而不是改变上的时间。改变一大堆,然后不保存而是重新加载怎么样。那是不会记录的编辑时间。反过来说:你有一个文件打开了 x 小时,但只在编程会话结束时查看它,当你更改用户消息中的单个字符时......
  • diff 工具需要提取在文件的 2 个存储版本之间更改的代码行。
  • 那么问题标题中的“时间花费”呢?
  • 这将是一个不错的奖励,但您可以从 #of 行数和时间戳中推断出很多。
  • 你应该试试Windiff,它有一个非常好的GUI,而且它是开源的。

标签: delphi delphi-2007 static-code-analysis lines-of-code


【解决方案1】:

我会直言不讳。

在我看来,您好像是一名项目经理,正在涉足极其危险的领域。 Johan(强烈)否认自己是一名项目经理。 :D
尽管除了希望专门检查 Delphi 历史之外,这听起来更像是一个超级用户问题而不是编程问题。

请参考以下链接了解此类方法的危险:
-2000 Lines of code
Measuring Knowledge Workers
Productivity 2.0

每当您尝试将代码行与时间关联起来时,都会以牺牲许多其他因素为代价。下面的列表肯定不是详尽无遗的!

  • 特定开发人员对一段代码的熟悉程度。
  • 一段代码的脆弱性。
  • 错误或功能的复杂性....与代码行无关
  • 现有冗余。
  • 引入了冗余。
  • 工作的准确性。
  • 工作的彻底性。
  • 在特定时间进行的工作的性质。
  • 手写代码与生成代码(生成 dprs,部分生成 dfms - 设置属性就像编写代码)。
  • 现有代码的可读性。
  • 现有代码的灵活性。

编辑
我知道我还没有真正回答你的问题,但我恳请你给予应有的考虑。请仔细考虑您要达到的目标。


EDIT2
即使对于非项目经理,这个建议也成立。您无法从时间和代码行之间的相关性中得出有意义的结论。从科学的角度来看,“干扰”太多了。

我重复一遍:请仔细考虑您要达到的目标
你的评论说“当你在什么地方工作了多长时间”。这对我来说听起来像是时间表信息,在这种情况下,只需影响哪些文件就足够了。

因此,您可以通过以下 DOS 命令的组合来逃脱:dirfindstrsort

【讨论】:

  • @craig 对不起,我不是项目经理,对不起,让你们都兴奋起来了,我需要这个工具来解决我工作时的问题,我工作了多长时间
  • @Johan:别担心,我没有生气。对于指责你是项目经理,我深表歉意。很抱歉冒犯了你。 :) 但是,我仍然坚持我的回答。您无法在时间和代码行之间绘制有意义的相关性。
  • 顺便说一句,markdown 中的删除线效果是怎么做的?
  • +1,不错的清单。我知道 -2000 的文章,想在我的答案中放一个链接,但谷歌让我失望了。
  • markdown 支持有限的 html,strike 和 /strike 就是其中之一。
【解决方案2】:

几乎任何生成所谓的“差异兼容”差异文件或“补丁”的差异工具都可以用于这项工作。例如,我相信你可以使用这个:http://gnuwin32.sourceforge.net/packages/diffutils.htm

只需调用命令行工具,将文件的新旧版本作为参数并对其输出进行Annalize:您基本上关心以单个-+ 开头的行。这将使您粗略估计更改的行数。如果您想变得花哨,则需要修改算法以正确检测更改的块,但这很多更加困难,因为 diff 的工作是生成用于转换“旧”文件的输出进入“新”文件,不计算更改。行编辑通常显示为先删除后添加。

以下是使用 diff 会遇到的问题:

  • 移动的行同时显示为删除和添加,并且可能会被计算两次,即使程序员所做的只是稍微重构代码。
  • 编辑的行数可能不止一次。

由于您不关心实际的diff,并且您想要粗略估计更改的代码行,这里还有一个非常简单的想法,它为您提供了一个数字。不是很准确,但是再一次,LOC 计数无论如何都不能准确地衡量程序员的性能!此代码同时查看 OLD 和 NEW 文件,并给出在 OLD 中找到但在 NEW 中未找到的行数加上在 NEW 中找到但在 OLD 中未找到的行数

function CountLineChanges(const OldFile, NewFile:string):Integer;
var OldL: TStringList;
    NewL: TStringList;
    i: Integer;

  procedure FillListWithStringsFromFile(const FileName: string; const L:TStringList);
  var F: TStringList;
      i,n: Integer;
      s: string;
  begin
    F := TStringList.Create;
    try
      F.LoadFromFile(FileName);
      for i:=0 to F.Count-1 do
      begin
        s := F[i];
        if L.IndexOf(s) = -1 then
          L.Add(s)
        else
          begin
            // Seeing this line again!
            n := 1;
            while L.IndexOf(s + '#' + IntToStr(n)) <> -1 do
              Inc(n);
            L.Add(s + '#' + IntToStr(n));
          end;
      end;
    finally F.Free;
    end;
  end;

begin
  OldL := TStringList.Create;
  try
    OldL.Sorted := True;
    NewL := TStringList.Create;
    try
      NewL.Sorted := True;

      FillListWithStringsFromFile(OldFile, OldL);
      FillListWithStringsFromFile(NewFile, NewL);

      Result := 0;
      for i:=0 to OldL.Count-1 do
        if NewL.IndexOf(OldL[i]) = -1 then
          Inc(Result);
      for i:=0 to NewL.Count-1 do
        if OldL.IndexOf(NewL[i]) = -1 then
          Inc(Result);

    finally NewL.Free;
    end;
  finally OldL.Free;
  end;
end;

此代码的问题:

  • 代码块从一个地方移动到另一个地方会导致0
  • 所有编辑的行都被精确计算两次。

【讨论】:

  • 感谢您回答问题
【解决方案3】:

IMO,您应该改用您的源存储库历史记录。即颠覆。它将向您显示所有用户的所有签到日志以及时间戳。永远。

【讨论】:

  • 感谢 Chris,但我想事后提取此信息,而不是为将来保留此数据。