[fpc-pascal] Is there some example of an FPC program for use in svn hook calls (email)?

Paul Breneman Paul2006 at BrenemanLabs.com
Thu Dec 14 19:17:52 CET 2017


On 12/14/2017 12:02 PM, Bo Berglund wrote:
> On Thu, 14 Dec 2017 10:26:22 +0000, Mark Morgan Lloyd
> <markMLl.fpc-pascal at telemetry.co.uk> wrote:
> 
>> On 14/12/17 10:00, Adriaan van Os wrote:
>>> Bo Berglund wrote:
>>>> Now I am looking at the same problem for svn and this time I need it>
>>>> to be cross-platform, hence using FPC.> Before I start on it myself I
>>>> wonder if someone here has already> written such a program for svn and
>>>> if so, if it is available as open> source?
>>> I use sendmail <https://en.wikipedia.org/wiki/Sendmail> from FPC, using
>>> AssignStream, fpgeterrno and PClose. Haven't tried that on Windows though.
>>
>> With the caveat that while Sendmail is a well-respected MTA, many unix
>> systems also provide a sendmail command as a generic mailer. On Windows
>> Blat is an alternative.
> But *sending email* is not the problem, I have done this in many
> applications using Indy TIdSMTP. Instead it is getting data out oof
> svn and formatting these in a friendly looking email to be sent....
> 
> Anyway I started on my own svn data collector and got stuck in a very
> basic function...
> 
> I used the information in the wiki page below on how to execute a
> command line program and retrieving its output data for processing.
> Look at the section towards the bottom with subject "Reading large
> output":
> http://wiki.freepascal.org/Executing_External_Programs
> 
> To get the subversion commit data one has to use svnlook, which is a
> command line program so I need to do this.
> 
> But when I use this approach I get no data at all, what could have
> gone wrong here?
> 
> When I reach the end of the repeat loop there is no data at all to
> process, i = 0!
> But when I run the command on the command line manually I do get svn
> data back.
> So what did I do wrong when I used the wiki solution?

I recently used the same code, so I tried to execute your code (below). 
I'd suggest adding the two lines (shown below) to troubleshoot. I didn't 
execute svnlook but ppcx64 with parameter -h and that works okay with 
your code.

> 
> var
>    //Command line parameters are:
>    REPOS_PATH,         //Full path to repository
>    REV,                //Revision number
>    TXN_NAME:  string;  //Transaction name
>    DataBuf,
>    Parms:   TStringList;
>    svncmd: string;
>    SCD: TSvnCommitData;
> 
> 
> function GetSvnData(Command: string; Parameters: TStringList; var
> SvnData: TStringList): boolean;
> {Command is the full path to the executable to run (<path>\svnlook.exe
> or <path>/svnlook
> Parameters contain the command line parameters. A typical parameter
> set could be
>   info
>   -r
>   2121
>   <repository path on server>
> 
>   The result from the command will be stored into the SvnData
> stringlist
>   }
> const
>    BUF_SIZE = 2048; // Buffer size for reading the output in chunks
> var
>    AProcess     : TProcess;
>    OutputStream : TStream;
>    BytesRead    : longint;
>    i: integer;
>    Buffer       : array[1..BUF_SIZE] of byte;
> begin
>    Result := false;
>    // Set up the process
>    AProcess := TProcess.Create(nil);
>    // Create a stream object to store the generated output in.
>    OutputStream := TMemoryStream.Create;
>    //Create the data buffer
>    try
>      AProcess.Executable := Command;
> 
>      // Process option poUsePipes has to be used so the output can be
> captured.
>      AProcess.Options := [poUsePipes];
> 
>      for i := 0 to Parameters.Count -1 do
>        AProcess.Parameters.Add(Parameters[i]);
> 
>      i := 0;
>      // Start the process (run the command)
>      AProcess.Execute;
> 
>      // All generated output from AProcess is read in a loop until no
> more data is available
>      repeat
>        // Get the new data from the process to a maximum of the buffer
> size that was allocated.
>        // Note that all read(...) calls will block except for the last
> one, which returns 0 (zero).
>        BytesRead := AProcess.Output.Read(Buffer, BUF_SIZE);
> 
>        // Add the bytes that were read to the stream for later usage
>        OutputStream.Write(Buffer, BytesRead);
>        Inc(i, BytesRead);
>      until BytesRead = 0;  // Stop if no more data is available
> 
>      OutputStream.Position := 0; // Required to make sure all data is
> copied from the start
>      SvnData.LoadFromStream(OutputStream);
>      Result := (i > 0); //(SvnData.Count > 0);

// I'd suggest adding these two lines to troubleshoot:
     writeln(SvnData.Text);
     writeln('Number of bytes = ', i);

>    finally
>      OutputStream.Free;;
>      AProcess.Free;
>    end;
> 
> end;
> 
> begin
>    //Check for the call parameters:
>    if ParamCount() < 3 then
>    begin
>      Writeln('Call parameters missing!');
>      exit;
>    end;
>    REPOS_PATH := ParamStr(1);
>    REV := ParamStr(2);
>    TXN_NAME := ParamStr(3);
>    Parms := TStringList.Create;
>    DataBuf := TStringList.Create;
>    SCD := TSvnCommitData.Create;
>    try
>      // The commands for Windows and *nix are different hence the
> $IFDEFs
>      {$IFDEF Windows}
>        svncmd := 'C:\Programs\Subversion\svnlook.exe';
>      {$ENDIF Windows}
>      {$IFDEF Unix}
>        svncmd := '/usr/bin/svnlook';
>      {$ENDIF Unix}
>      //Build the call for svnlook
>      {1. Get the starting information on the operation
>          svnlook info -r <REV> <REPOS_PATH>
>      }
>      Parms.Add('info');
>      Parms.Add('-r');
>      Parms.Add('REV');
>      Parms.Add('REPOS_PATH');
>      if GetSvnData(svncmd, Parms, DataBuf) then
>      begin
>        SCD.UserName := DataBuf[0];
>        SCD.CommitTime := DataBuf[1];
>        SCD.Logmessage := DataBuf[3];
>      end;
>    finally
>      SCD.Free;
>      DataBuf.Free;
>    end;
> end.
> 
> 
> 




More information about the fpc-pascal mailing list