mirror of
https://gitlab.com/freepascal.org/lazarus/lazarus.git
synced 2025-08-17 15:59:13 +02:00
Merged revision(s) 65363-65364 #94264d4795-#94264d4795 from trunk:
svn2revisioninc: add git describe ........ svn2revisioninc: refactor, improve lookup of git-svn-id ........ git-svn-id: branches/fixes_2_2@65380 -
This commit is contained in:
parent
0a415d125a
commit
822876a09e
@ -59,7 +59,7 @@ program Svn2RevisionInc;
|
|||||||
uses
|
uses
|
||||||
Classes, CustApp, SysUtils, Process, Dom, XmlRead,
|
Classes, CustApp, SysUtils, Process, Dom, XmlRead,
|
||||||
// LazUtils
|
// LazUtils
|
||||||
FileUtil, LazFileUtils, LazUTF8, UTF8Process, LazLogger;
|
FileUtil, LazFileUtils, LazUTF8, UTF8Process, LazLogger, StrUtils;
|
||||||
|
|
||||||
type
|
type
|
||||||
|
|
||||||
@ -76,6 +76,13 @@ type
|
|||||||
Verbose: boolean;
|
Verbose: boolean;
|
||||||
UseStdOut: boolean;
|
UseStdOut: boolean;
|
||||||
|
|
||||||
|
function RunCommand(ACmd: String; AParams: array of string; ABytesNeeded: Integer = -1): Boolean;
|
||||||
|
function RunCommand(ACmd: String; AParams: array of string; out ARes: String;
|
||||||
|
ABytesNeeded: Integer = -1): Boolean;
|
||||||
|
function SvnInPath: Boolean;
|
||||||
|
function GitInPath: Boolean;
|
||||||
|
function HgInPath: Boolean;
|
||||||
|
|
||||||
function FindRevision: boolean;
|
function FindRevision: boolean;
|
||||||
function IsValidRevisionInc: boolean;
|
function IsValidRevisionInc: boolean;
|
||||||
procedure WriteRevisionInc;
|
procedure WriteRevisionInc;
|
||||||
@ -85,8 +92,10 @@ type
|
|||||||
function ConstStart: string;
|
function ConstStart: string;
|
||||||
procedure Show(msg: string);
|
procedure Show(msg: string);
|
||||||
function IsThisGitUpstreamBranch: boolean;
|
function IsThisGitUpstreamBranch: boolean;
|
||||||
function GetGitBranchPoint: string;
|
function GetRevisionFromGitVersion(ACommitIsh: String = '') : boolean;
|
||||||
function GitRevisionFromGitCommit: boolean;
|
function GetGitCommitInRemoteBranch(ARemotePattern: String = '*'): string;
|
||||||
|
function GitRevisionFromRemoteSVNGitVersion: boolean;
|
||||||
|
function GitDescribeCommit(KeepRevStr: Boolean): boolean;
|
||||||
public
|
public
|
||||||
constructor Create(TheOwner: TComponent); override;
|
constructor Create(TheOwner: TComponent); override;
|
||||||
destructor Destroy; override;
|
destructor Destroy; override;
|
||||||
@ -99,119 +108,92 @@ var
|
|||||||
|
|
||||||
const
|
const
|
||||||
RevisionIncComment = '// Created by Svn2RevisionInc';
|
RevisionIncComment = '// Created by Svn2RevisionInc';
|
||||||
|
|
||||||
function SvnInPath: Boolean;
|
function TSvn2RevisionApplication.RunCommand(ACmd: String;
|
||||||
|
AParams: array of string; ABytesNeeded: Integer): Boolean;
|
||||||
var
|
var
|
||||||
P: TProcessUTF8;
|
ADummy: String;
|
||||||
|
begin
|
||||||
|
Result := RunCommand(ACmd, AParams, ADummy, ABytesNeeded);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSvn2RevisionApplication.RunCommand(ACmd: String;
|
||||||
|
AParams: array of string; out ARes: String; ABytesNeeded: Integer): Boolean;
|
||||||
|
const
|
||||||
|
cBufSize = 500;
|
||||||
|
var
|
||||||
|
p: TProcessUTF8;
|
||||||
|
Buffer: string;
|
||||||
|
n: LongInt;
|
||||||
|
t: QWord;
|
||||||
|
i: Integer;
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Result := True;
|
||||||
P := TProcessUTF8.Create(nil);
|
p := TProcessUTF8.Create(nil);
|
||||||
try
|
try
|
||||||
P.Options := [poUsePipes, poWaitOnExit];
|
|
||||||
P.CommandLine := 'svn --version';
|
|
||||||
try
|
try
|
||||||
P.Execute;
|
with p do begin
|
||||||
|
Executable := ACmd;
|
||||||
|
for i := 0 to high(AParams) do
|
||||||
|
Parameters.Add(AParams[i]);
|
||||||
|
Options := [poUsePipes];
|
||||||
|
|
||||||
|
Execute;
|
||||||
|
{ now process the output }
|
||||||
|
SetLength(Buffer, cBufSize);
|
||||||
|
ARes := '';
|
||||||
|
t := GetTickCount64;
|
||||||
|
while (ABytesNeeded < 0) or (Length(ARes) < ABytesNeeded) do begin
|
||||||
|
if Output.NumBytesAvailable > 0 then begin
|
||||||
|
n := OutPut.Read(Buffer[1], cBufSize);
|
||||||
|
ARes := ARes + Copy(Buffer, 1, n);
|
||||||
|
end
|
||||||
|
else begin
|
||||||
|
if not p.Running then
|
||||||
|
break;
|
||||||
|
if GetTickCount64 - t > 30 * 1000 then begin
|
||||||
|
Result := False;
|
||||||
|
exit
|
||||||
|
end;
|
||||||
|
if Stderr.NumBytesAvailable > 0 then begin
|
||||||
|
n := Stderr.Read(Buffer[1], cBufSize);
|
||||||
|
Show(Copy(Buffer, 1, n));
|
||||||
|
end;
|
||||||
|
sleep(10);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
except
|
except
|
||||||
Result := False;
|
Result := False;
|
||||||
end;
|
end;
|
||||||
finally
|
finally
|
||||||
P.Destroy;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
|
|
||||||
function GitInPath: Boolean;
|
|
||||||
var
|
|
||||||
P: TProcessUTF8;
|
|
||||||
begin
|
|
||||||
Result := True;
|
|
||||||
P := TProcessUTF8.Create(nil);
|
|
||||||
try
|
|
||||||
P.Options := [poUsePipes, poWaitOnExit];
|
|
||||||
P.CommandLine := 'git --version';
|
|
||||||
try
|
try
|
||||||
P.Execute;
|
p.Terminate(0);
|
||||||
except
|
finally
|
||||||
Result := False;
|
p.Free;
|
||||||
end;
|
end;
|
||||||
finally
|
|
||||||
P.Destroy;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
function HgInPath: Boolean;
|
function TSvn2RevisionApplication.SvnInPath: Boolean;
|
||||||
var
|
|
||||||
P: TProcessUTF8;
|
|
||||||
begin
|
begin
|
||||||
Result := True;
|
Result := RunCommand('svn', ['--version'], 0);
|
||||||
P := TProcessUTF8.Create(nil);
|
|
||||||
try
|
|
||||||
P.Options := [poUsePipes, poWaitOnExit];
|
|
||||||
P.CommandLine := 'hg --version';
|
|
||||||
try
|
|
||||||
P.Execute;
|
|
||||||
except
|
|
||||||
Result := False;
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
P.Destroy;
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
function TSvn2RevisionApplication.GitInPath: Boolean;
|
||||||
|
begin
|
||||||
|
Result := RunCommand('git', ['--version'], 0);
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSvn2RevisionApplication.HgInPath: Boolean;
|
||||||
|
begin
|
||||||
|
Result := RunCommand('hg', ['--version'], 0);
|
||||||
|
end;
|
||||||
|
|
||||||
function TSvn2RevisionApplication.FindRevision: boolean;
|
function TSvn2RevisionApplication.FindRevision: boolean;
|
||||||
var
|
var
|
||||||
GitDir: string;
|
GitDir: string;
|
||||||
|
|
||||||
|
|
||||||
function GetRevisionFromGitVersion : boolean;
|
|
||||||
var
|
|
||||||
GitVersionProcess: TProcessUTF8;
|
|
||||||
Buffer: string;
|
|
||||||
n: LongInt;
|
|
||||||
begin
|
|
||||||
Result:=false;
|
|
||||||
GitVersionProcess := TProcessUTF8.Create(nil);
|
|
||||||
try
|
|
||||||
with GitVersionProcess do begin
|
|
||||||
CommandLine := 'git log -1 --pretty=format:"%b"';
|
|
||||||
Options := [poUsePipes, poWaitOnExit];
|
|
||||||
try
|
|
||||||
CurrentDirectory:=GitDir;
|
|
||||||
Execute;
|
|
||||||
SetLength(Buffer, 80);
|
|
||||||
n:=OutPut.Read(Buffer[1], 80);
|
|
||||||
|
|
||||||
if (Pos('git-svn-id:', Buffer) > 0) then begin
|
|
||||||
//Read version is OK
|
|
||||||
Result:=true;
|
|
||||||
RevisionStr := Copy(Buffer, 1, n);
|
|
||||||
System.Delete(RevisionStr, 1, Pos('@', RevisionStr));
|
|
||||||
System.Delete(RevisionStr, Pos(' ', RevisionStr), Length(RevisionStr));
|
|
||||||
end;
|
|
||||||
except
|
|
||||||
// ignore error, default result is false
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
GitVersionProcess.Free;
|
|
||||||
end;
|
|
||||||
if Result then
|
|
||||||
begin
|
|
||||||
Show('Success retrieving revision with git log.');
|
|
||||||
end
|
|
||||||
else
|
|
||||||
begin
|
|
||||||
Show('Failed retrieving revision with git log.');
|
|
||||||
if n>0 then
|
|
||||||
begin
|
|
||||||
Show('');
|
|
||||||
Show('git log error output:');
|
|
||||||
Show(Copy(Buffer, 1, n));
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
Show('');
|
|
||||||
end;
|
|
||||||
|
|
||||||
function GetRevisionFromHgVersion : boolean;
|
function GetRevisionFromHgVersion : boolean;
|
||||||
var
|
var
|
||||||
HgVersionProcess: TProcessUTF8;
|
HgVersionProcess: TProcessUTF8;
|
||||||
@ -412,10 +394,13 @@ begin
|
|||||||
GitDir:= AppendPathDelim(SourceDirectory)+'.git';
|
GitDir:= AppendPathDelim(SourceDirectory)+'.git';
|
||||||
if DirectoryExistsUTF8(GitDir) and GitInPath then
|
if DirectoryExistsUTF8(GitDir) and GitInPath then
|
||||||
begin
|
begin
|
||||||
if IsThisGitUpstreamBranch then
|
Result := GetRevisionFromGitVersion;
|
||||||
Result := GetRevisionFromGitVersion
|
if not Result then begin
|
||||||
else
|
Result := GitRevisionFromRemoteSVNGitVersion;
|
||||||
Result := GitRevisionFromGitCommit;
|
end;
|
||||||
|
|
||||||
|
if GitDescribeCommit(Result) then
|
||||||
|
Result := True;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
@ -657,114 +642,95 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Determine the commit at which we branched away from 'upstream'. Note the
|
function TSvn2RevisionApplication.GetRevisionFromGitVersion(ACommitIsh: String
|
||||||
SHA1 commit we are looking for is always the last one in the list that has
|
): boolean;
|
||||||
the '-' prefix added.
|
|
||||||
Example output:
|
|
||||||
$ git rev-list --boundary HEAD...upstream
|
|
||||||
a39f9f70f96b9533377c2cad27155066a0b01411
|
|
||||||
3874aa82b83fedaa19459fedaa30f4582251b9a1
|
|
||||||
0379257d111d465bf28e879d6b87080d9e896648
|
|
||||||
5dd8ca18ef06520a524bfac9648103d440fbe0bc
|
|
||||||
-d1fba5c3f36a4816c933a8f7f361c585258b5b01
|
|
||||||
}
|
|
||||||
function TSvn2RevisionApplication.GetGitBranchPoint: string;
|
|
||||||
const
|
|
||||||
READ_BYTES = 2048;
|
|
||||||
var
|
var
|
||||||
p: TProcessUTF8;
|
s: String;
|
||||||
MemStream: TMemoryStream;
|
|
||||||
n, i, NumBytes, BytesRead: integer;
|
|
||||||
s: string;
|
|
||||||
sl: TStringList;
|
|
||||||
begin
|
begin
|
||||||
Result := '';
|
if ACommitIsh <> '' then
|
||||||
BytesRead := 0;
|
Result := RunCommand('git', ['log', '-1', '--pretty=format:"%b"', ACommitIsh], s)
|
||||||
sl := Nil;
|
else
|
||||||
MemStream := TMemoryStream.Create;
|
Result := RunCommand('git', ['log', '-1', '--pretty=format:"%b"'], s);
|
||||||
p := TProcessUTF8.Create(nil);
|
if not Result then
|
||||||
try
|
exit;
|
||||||
p.CommandLine := 'git rev-list --boundary HEAD...' + MainBranch;
|
|
||||||
p.Options := [poUsePipes];
|
// git-svn-id: http://svn.freepascal.org/svn/lazarus/trunk@60656 4005530d-fff6-0310-9dd1-cebe43e6787f
|
||||||
p.Execute;
|
Result := Pos('git-svn-id: ', s) > 0;
|
||||||
// read while the process is running
|
if Result then begin
|
||||||
while p.Running do begin
|
//Read version is OK
|
||||||
MemStream.SetSize(BytesRead + READ_BYTES); // make sure we have room
|
System.Delete(s, 1, Pos('git-svn-id: ', s));
|
||||||
// try reading it
|
System.Delete(s, 1, Pos('@', s));
|
||||||
NumBytes := p.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
|
if PosSet([' ', #10,#13], s) > 0 then
|
||||||
if NumBytes > 0 then
|
System.Delete(s, PosSet([' ', #10,#13], s), Length(s));
|
||||||
Inc(BytesRead, NumBytes)
|
RevisionStr := s;
|
||||||
else // no data, wait 100 ms
|
end;
|
||||||
Sleep(100);
|
if Result then
|
||||||
end;
|
begin
|
||||||
// read last part
|
Show('Success retrieving revision with git log.');
|
||||||
repeat
|
end
|
||||||
MemStream.SetSize(BytesRead + READ_BYTES);
|
else
|
||||||
NumBytes := p.Output.Read((MemStream.Memory + BytesRead)^, READ_BYTES);
|
begin
|
||||||
if NumBytes > 0 then
|
Show('Failed retrieving revision with git log.');
|
||||||
Inc(BytesRead, NumBytes);
|
|
||||||
until NumBytes <= 0;
|
|
||||||
MemStream.SetSize(BytesRead);
|
|
||||||
sl := TStringList.Create;
|
|
||||||
sl.LoadFromStream(MemStream);
|
|
||||||
{ now search for the '-' marker. Should be the last one, so search in reverse. }
|
|
||||||
for i := sl.Count-1 downto 0 do
|
|
||||||
begin
|
|
||||||
s := sl[i];
|
|
||||||
n := Pos('-', s);
|
|
||||||
if n > 0 then begin
|
|
||||||
Result := Copy(s, 2, Length(s));
|
|
||||||
exit;
|
|
||||||
end;
|
|
||||||
end;
|
|
||||||
finally
|
|
||||||
sl.Free;
|
|
||||||
p.Free;
|
|
||||||
MemStream.Free;
|
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
{ Get the branch point, and exact the SVN revision from that commit log }
|
{ Determine the closest parent commit that is in a remote branch
|
||||||
function TSvn2RevisionApplication.GitRevisionFromGitCommit: Boolean;
|
}
|
||||||
const
|
function TSvn2RevisionApplication.GetGitCommitInRemoteBranch(
|
||||||
cBufSize = 80;
|
ARemotePattern: String): string;
|
||||||
var
|
var
|
||||||
sha1: string;
|
|
||||||
p: TProcessUTF8;
|
|
||||||
Buffer: string;
|
|
||||||
n: LongInt;
|
|
||||||
s: string;
|
s: string;
|
||||||
|
begin
|
||||||
|
if not RunCommand('git',
|
||||||
|
['log', 'HEAD', '--not', '--remotes="'+ARemotePattern+'"', '--reverse', '--pretty=format:"%H"'],
|
||||||
|
Result, 40) // sha1 = 40 bytes
|
||||||
|
then begin
|
||||||
|
Result := '';
|
||||||
|
exit;
|
||||||
|
end;
|
||||||
|
|
||||||
|
if Result <> '' then
|
||||||
|
Result := Result + '~1'; // parent
|
||||||
|
end;
|
||||||
|
|
||||||
|
{ Get the branch point, and exact the SVN revision from that commit log }
|
||||||
|
function TSvn2RevisionApplication.GitRevisionFromRemoteSVNGitVersion: boolean;
|
||||||
|
var
|
||||||
|
sha1: string;
|
||||||
begin
|
begin
|
||||||
Result := False;
|
Result := False;
|
||||||
sha1 := GetGitBranchPoint;
|
// git svn uses /remote/svn/<branch> as remote
|
||||||
p := TProcessUTF8.Create(nil);
|
sha1 := GetGitCommitInRemoteBranch('svn/*');
|
||||||
try
|
if sha1 <> '' then begin
|
||||||
with p do begin
|
Result := GetRevisionFromGitVersion(sha1);
|
||||||
CommandLine := 'git show --summary --pretty=format:"%b" ' + sha1;
|
if not Result then begin
|
||||||
Options := [poUsePipes, poWaitOnExit];
|
sha1 := GetGitCommitInRemoteBranch; // try any remote branch
|
||||||
try
|
Result := GetRevisionFromGitVersion(sha1);
|
||||||
Execute;
|
|
||||||
{ now process the output }
|
|
||||||
SetLength(Buffer, cBufSize);
|
|
||||||
s := '';
|
|
||||||
repeat
|
|
||||||
n := OutPut.Read(Buffer[1], cBufSize);
|
|
||||||
s := s + Copy(Buffer, 1, n);
|
|
||||||
until n < cBufSize;
|
|
||||||
{ now search for our marker }
|
|
||||||
if (Pos('git-svn-id:', s) > 0) then
|
|
||||||
begin
|
|
||||||
Result := True;
|
|
||||||
RevisionStr := s;
|
|
||||||
System.Delete(RevisionStr, 1, Pos('@', RevisionStr));
|
|
||||||
System.Delete(RevisionStr, Pos(' ', RevisionStr), Length(RevisionStr));
|
|
||||||
end;
|
|
||||||
except
|
|
||||||
// ignore error, default result is false
|
|
||||||
end;
|
|
||||||
end;
|
end;
|
||||||
finally
|
end;
|
||||||
p.Free;
|
if Result then
|
||||||
|
RevisionStr := RevisionStr + '(B)'; // local commits "Based on"
|
||||||
|
end;
|
||||||
|
|
||||||
|
function TSvn2RevisionApplication.GitDescribeCommit(KeepRevStr: Boolean
|
||||||
|
): boolean;
|
||||||
|
var
|
||||||
|
s: string;
|
||||||
|
begin
|
||||||
|
Result := RunCommand('git', ['describe', '--always'], s);
|
||||||
|
if not Result then
|
||||||
|
exit;
|
||||||
|
|
||||||
|
if PosSet([#10,#13], s) > 0 then
|
||||||
|
System.Delete(s, PosSet([#10,#13], s), Length(s));
|
||||||
|
s := Trim(s);
|
||||||
|
Result := s <> '';
|
||||||
|
if Result then
|
||||||
|
begin
|
||||||
|
Result := True;
|
||||||
|
if KeepRevStr and (RevisionStr <> '') then
|
||||||
|
s := s + ' / ' + RevisionStr;
|
||||||
|
RevisionStr := s;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user