'How to create a TSvnItem for a specified URL

Short Version

How to perform svn cat in Delphi's subversion api wrapper?

Long Version

I want to get the contents of a file in subversion.

Here's a random public repository that lets you cat (i.e. display the contents of) a file:

>svn cat http://svn.code.sf.net/p/unicon/code/trunk/unicon/README
Unicon 13.x README


This is the Unicon distribution.  Please tell us
where it compiles, and when and how it doesn't.
...snip...

So that works.

Now how to do it in Delphi?

How do i read the contents (i.e. cat) a file in Delphi's Subversion API wrapper?

Based on this Stackoverflow answer, i try:

SvnItem: TSvnItem;

SvnItem := TSvnItem.Create(SvnClient, nil, 'http://svn.code.sf.net/p/unicon/code/trunk/unicon/README');

Unfortunately the call to create a TSvnItem throws an exception:

EAprError: The given path is misformatted or contained invalid characters

So what am i doing wrong?

For The Lazy

program Project1;

{$APPTYPE CONSOLE}

uses
    SysUtils, SvnClient;

procedure Main;
var
    SvnClient: TSvnClient;
    SvnItem: TSvnItem;
    url: string;
begin
    // Set the global variable where the subversion DLLs can be found.
    BaseDllDir := ExtractFilePath(ParamStr(0)); //Setting a global variable (yes, seriously)

    SvnClient := TSvnClient.Create;
    SvnClient.Initialize;

    url := 'http://svn.code.sf.net/p/unicon/code/trunk/unicon/README';
    SvnItem := TSvnItem.Create(SvnClient, nil, url);
end;

begin
    try
        Main;
    except
        on E: Exception do
            begin
                ExitCode := 1;
                Writeln(Format('[%s] %s', [E.ClassName, E.Message]));
            end;
    end;
end.

See also



Solution 1:[1]

It's not an answer; but it is a workaround for the next guy.

Thing that should work (but doesn't)

function GetSubversionFileContents(Client: TSvnClient; Url: string): TStream;
var
    item: TSvnItem;
    buffer: TBytes;
    ms: TMemoryStream;
begin
    //WARNING: This code doesn't work.
    item := TSvnItem.Create(Client, nil, Url); //throws exception
    buffer := item.GetBaseFile;
    item.Free;

    ms := TMemoryStream.Create;
    ms.Size := Length(buffer);
    if Length(buffer) > 0 then
        ms.Write(buffer[0], Length(buffer));
    ms.Seek(0, soFromBeginning);
end;

Hack workaround

function GetSubversionFileContents(Client: TSvnClient; Url: string): TStream;
var
    http: IWinHttpRequest;
    stm: IStream;
begin
    // Issue the WebDAV HTTP GET ourselves.
    // (SVN is just a wrapper around WebDAV)

    http := CoWinHttpRequest.Create;
    http.Open('GET', url, False);
    if Client.UserName <> '' then
        http.SetCredentials(Client.UserName, Client.Password, HTTPREQUEST_SETCREDENTIALS_FOR_SERVER);
    http.Send(EmptyParam);

    stm := IUnknown(http.ResponseStream) as IStream;
    Result := TOleStream.Create(stm);

    //TODO: Re-write the rest of the Subversion API into something modern (i.e. post-1995).
end;

Subversion is just an implementation of WebDAV - which is just REST but without the cool name. Which means you can issue a GET to the url to get the contents yourself directly.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1