Delphi 如何从存储库中的SVN项中删除属性?

Delphi 如何从存储库中的SVN项中删除属性?,delphi,svn,Delphi,Svn,我可以连接到存储库: var client: TSvnClient; url: string; begin BaseDllDir := ExtractFilePath(ParamStr(0))+'Subversion'; //dlls sitting in "Subversion" folder client := TSvnClient.Create; client.Initialize; url := 'https://repos.wowace.com/

我可以连接到存储库:

var 
   client: TSvnClient;
   url: string;
begin
   BaseDllDir := ExtractFilePath(ParamStr(0))+'Subversion'; //dlls sitting in "Subversion" folder
   client := TSvnClient.Create;
   client.Initialize;

   url := 'https://repos.wowace.com/wow/bank-items/tags/6.1.0.0';
我可以使用
client.List
的基本功能来获取项目列表:

var
   sl: TStrings;
begin
   sl := TStringList.Create;
   client.List(Url, svnDepthImmediates, False, sl);
   Log(sl.Text);
这将返回项目本身的列表,以及它的即时文件和目录项:

.=/tags/6.1.0.0
.pkgmeta=/tags/6.1.0.0/.pkgmeta
BankItems.lua=/tags/6.1.0.0/BankItems.lua
BankItems.toc=/tags/6.1.0.0/BankItems.toc
Bindings.xml=/tags/6.1.0.0/Bindings.xml
localization-deDE.lua=/tags/6.1.0.0/localization-deDE.lua
localization-enUS.lua=/tags/6.1.0.0/localization-enUS.lua
...snip...
我还可以使用
TSvnList.LoadList
获取
TSvnListItem
对象的列表:

var
   list: TSvnList;
   item: TSvnListItem;
begin
   list := TSvnList.Create(client);
   list.LoadList(Url, svnDepthImmediates, False);

    s := '';
    for i := 0 to list.Count-1 do
begin
    li := list.Items[i];

    s := s+
          '- Item '+intToStr(i)+#13#10+
          '   - **Path**: '+li.Path+#13#10+
          '   - **AbsolutePath**: '+li.AbsolutePath+#13#10+
          '   - **Size**: '+IntToStr(li.Size)+#13#10+
          '   - **Kind**: '+SvnNodeKindString(li.Kind)+#13#10+
          '   - **HasProps**: '+IfThen(li.HasProps, 'Yes', 'No')+#13#10+
          '   - **LastAuthor**: '+li.LastAuthor+#13#10+
          '   - **Time**: '+DateTimeToStr(li.Time)+#13#10+
          '   - **CreatedRevision**: '+IntToStr(li.CreatedRevision)+#13#10+#13#10;
end;
Log(s);
  • 项目0

    • 路径
    • 绝对路径:/tags/6.1.0.0
    • 大小:0
    • 种类:svnNodeDir
    • HasProps:否
    • 最新作者:nbluewiz
    • 时间:2015年2月25日10:13:29
    • CreatedRevision:227
  • 项目1

    • 路径:.pkgmeta
    • 绝对路径:/tags/6.1.0.0
    • 大小:22
    • 种类:svnNodeFile
    • HasProps:否
    • 最新作者:root
    • 时间2008年9月29日下午5:33:49
    • CreatedRevision:96
  • 项目2

    • 路径:BankItems.lua
    • 绝对路径:/tags/6.1.0.0
    • 大小:272471
    • 种类:svnNodeFile
    • HasProps:是
    • 最新作者:伯斯特洛克
    • 时间:2015年8月2日11:46:51
    • CreatedRevision:225
  • 项目3

    • 路径:BankItems.toc
    • 绝对路径:/tags/6.1.0.0
    • 大小:1776
    • 种类:svnNodeFile
    • HasProps:是
    • 最新作者:伯斯特洛克
    • 时间:2015年2月25日9:02:47
    • CreatedRevision:226
…剪断

这意味着我可以成功地连接到存储库并进行查询

现在是财产 现在我想从存储库中的项目中读取数据;或者一些更高级的元数据

您注意到
TSvnListItem
类有一个
HasProps
属性;但无法读取属性。为此,我认为我们需要
TSvnItem
对象:

TSvnItem = class
public
   //...snip...
   property SvnPathName: string;
   property URL: string;
   property Parent: TSvnItem;
   property PathName: string;
   property LastCommitAuthor: string;
   property LastCommitRevision: Integer;
   property LastCommitTime: TDateTime;
   property PropCount: Integer;
   property PropNames[Index: Integer]: string;
   property HistoryCount: Integer;
   property HistoryItems[Index: Integer]: TSvnHistoryItem;
end;
给定一个任意项目,获得其父项的URL肯定很好。或获取历史记录或属性:

item := TSvnItem.Create(client, Url);
s := '';
for i := 0 to item.PropCount-1 do
begin
   s := s+'"'+item.PropNames[i]+'" = "'+item.PropValueFromIndex[i]+'"'+#13#10;
end;
Log(s);
除非任何使用
TSvnItem
访问任何内容的尝试都会导致错误:

C:\Program Files(x86)\Contoso\Grobber不是工作副本

这是真的;事实并非如此

TSvnItem.Create
还有其他重载,其中一个显然成功:

item := TSvnItem.Create(client, nil, Url);
但该构造函数在以下方面失败:

给定路径格式错误或包含无效字符

它在构造函数内部失败,原因是:

FSvnPathName := FSvnClient.NativePathToSvnPath(FPathName, SubPool);
而这反过来又会失败

function TSvnClient.NativePathToSvnPath(const NativePath: string; SubPool: PAprPool = nil): string;    
begin
   //...snip...
   AprCheck(apr_filepath_merge(SvnPath, '', PAnsiChar(UTF8Encode(NativePath)), APR_FILEPATH_TRUENAME, SubPool));
所以我被难住了。由于Delphi Svn库中没有任何文档,我……被难住了

最小可重复示例 该Url是公开的,可供任何人使用:

但您必须确保提供所有DLL:

program Project1;

{$APPTYPE CONSOLE}

uses System.SysUtils, SvnClient;

var
  client: TSvnClient;
  item: TSvnItem;
begin
  try
     client := TSvnClient.Create;
     BaseDllDir := ExtractFilePath(ParamStr(0));
     client.Initialize;
     item := TSvnItem.Create(client, nil, 'https://repos.wowace.com/wow/bank-items/tags/6.1.0.0/BankItems.lua');
     Writeln('ItemCount: '+IntToStr(item.PropCount));
  except
     on E: Exception do
        Writeln(E.ClassName, ': ', E.Message);
  end;
end.

注意SvnClient(1.9)中URL重载上方的注释

{TSvnItem for URL是一种黑客行为,现在不要期望 除了异步历史加载之外,还有什么其他方法可以工作} 构造函数创建(ASvnClient:TSvnClient;const AURL:string);超载

它确实与工作目录一起工作

procedure TForm1.btLoadPropClick(Sender: TObject);
const 
  url = 'svn://hub/vcl/Trunk/Jedi/';
  WorkDir = 'D:\VCL\Jedi';
var
  i: Integer;
  item: TSvnItem;
begin
  item := TSvnItem.Create(FClient, nil, WorkDir);
  Memo1.Lines.Add('============== Props ============================');
  for i := 0 to Pred(item.PropCount) do begin
    Memo1.Lines.Add(item.PropNames[i] + '" = "' + item.PropValueFromIndex[i]);
  end;
  item.Free;
end;
编辑: 第2085行的TSvnItem.ReloadProps中似乎有一个bug:

将第2085行更改为以下代码似乎可以解决问题:

        AprCheck(apr_filepath_merge(TruePath, PAnsiChar(UTF8Encode(URL)), PAnsiChar(UTF8Encode(FPathName)), APR_FILEPATH_TRUENAME, SubPool));

注意SvnClient(1.9)中URL重载上方的注释

{TSvnItem for URL是一种黑客行为,现在不要期望 除了异步历史加载之外,还有什么其他方法可以工作} 构造函数创建(ASvnClient:TSvnClient;const AURL:string);超载

它确实与工作目录一起工作

procedure TForm1.btLoadPropClick(Sender: TObject);
const 
  url = 'svn://hub/vcl/Trunk/Jedi/';
  WorkDir = 'D:\VCL\Jedi';
var
  i: Integer;
  item: TSvnItem;
begin
  item := TSvnItem.Create(FClient, nil, WorkDir);
  Memo1.Lines.Add('============== Props ============================');
  for i := 0 to Pred(item.PropCount) do begin
    Memo1.Lines.Add(item.PropNames[i] + '" = "' + item.PropValueFromIndex[i]);
  end;
  item.Free;
end;
编辑: 第2085行的TSvnItem.ReloadProps中似乎有一个bug:

将第2085行更改为以下代码似乎可以解决问题:

        AprCheck(apr_filepath_merge(TruePath, PAnsiChar(UTF8Encode(URL)), PAnsiChar(UTF8Encode(FPathName)), APR_FILEPATH_TRUENAME, SubPool));