209 lines
5.3 KiB
ObjectPascal
209 lines
5.3 KiB
ObjectPascal
// SPDX-License-Identifier: LGPL-3.0-linking-exception
|
|
unit MacBundle;
|
|
|
|
{$mode objfpc}{$H+}
|
|
|
|
interface
|
|
|
|
uses
|
|
Classes, SysUtils, ReleaserTypes, laz2_XMLRead, laz2_XMLWrite, Laz2_DOM;
|
|
|
|
type
|
|
|
|
{ TMacBundle }
|
|
|
|
TMacBundle = class(TReleaserObject)
|
|
private
|
|
FBundlepath: string;
|
|
FFilename: string;
|
|
FXml: TXmlDocument;
|
|
FDict: TStringList;
|
|
FChanged: boolean;
|
|
function GetName: string;
|
|
function GetPListFilename: string;
|
|
function ReadDict(ARoot: TDOMNode): TStringList;
|
|
procedure UpdateDict(ARoot: TDOMNode; ADict: TStringList);
|
|
function GetPList: TDOMNode;
|
|
public
|
|
constructor Create(AParameters: TStringList; ALogicDir: string); override;
|
|
destructor Destroy; override;
|
|
property Filename: string read FFilename;
|
|
function GetVersion: TVersion;
|
|
procedure GetVersions(AVersionList: TStringList); override;
|
|
procedure CheckVersion(AVersion: TVersion); override;
|
|
property Name: string read GetName;
|
|
procedure Save; override;
|
|
procedure UpdateVersion(AVersion: TVersion); override;
|
|
end;
|
|
|
|
implementation
|
|
|
|
{ TMacBundle }
|
|
|
|
function TMacBundle.GetName: string;
|
|
begin
|
|
result := '';
|
|
if Assigned(FDict) then
|
|
result := FDict.Values['CFBundleName'];
|
|
if result = '' then
|
|
result := ChangeFileExt(ExtractFileName(FBundlepath),'');
|
|
end;
|
|
|
|
function TMacBundle.GetPListFilename: string;
|
|
begin
|
|
result := FBundlepath+PathDelim+'Contents'+PathDelim+'Info.plist';
|
|
end;
|
|
|
|
function TMacBundle.ReadDict(ARoot: TDOMNode): TStringList;
|
|
var
|
|
dict, entry: TDOMNode;
|
|
key: string;
|
|
begin
|
|
result := TStringList.Create;
|
|
if Assigned(ARoot) then
|
|
begin
|
|
dict := ARoot.FindNode('dict');
|
|
if Assigned(dict) then
|
|
begin
|
|
entry := dict.FirstChild;
|
|
while entry <> nil do
|
|
begin
|
|
if entry.NodeName = 'key' then
|
|
begin
|
|
key := entry.TextContent;
|
|
entry := entry.NextSibling;
|
|
if (entry <> nil) and (entry.NodeName = 'string') then
|
|
begin
|
|
result.Values[key] := entry.TextContent;
|
|
entry := entry.NextSibling;
|
|
end
|
|
else if (entry <> nil) and (entry.NodeName <> 'key') then
|
|
entry := entry.NextSibling;
|
|
end else
|
|
entry := entry.NextSibling;
|
|
end;
|
|
end else
|
|
raise exception.Create('"dict" node not found');
|
|
end;
|
|
end;
|
|
|
|
procedure TMacBundle.UpdateDict(ARoot: TDOMNode; ADict: TStringList);
|
|
var
|
|
dict, entry: TDOMNode;
|
|
key: string;
|
|
begin
|
|
if Assigned(ARoot) then
|
|
begin
|
|
dict := ARoot.FindNode('dict');
|
|
if Assigned(dict) then
|
|
begin
|
|
entry := dict.FirstChild;
|
|
while entry <> nil do
|
|
begin
|
|
if entry.NodeName = 'key' then
|
|
begin
|
|
key := entry.TextContent;
|
|
entry := entry.NextSibling;
|
|
if (entry <> nil) and (entry.NodeName = 'string') then
|
|
begin
|
|
entry.TextContent := ADict.Values[key];
|
|
entry := entry.NextSibling;
|
|
end
|
|
else if (entry <> nil) and (entry.NodeName <> 'key') then
|
|
entry := entry.NextSibling;
|
|
end else
|
|
entry := entry.NextSibling;
|
|
end;
|
|
end else
|
|
raise exception.Create('"dict" node not found');
|
|
end;
|
|
end;
|
|
|
|
function TMacBundle.GetPList: TDOMNode;
|
|
begin
|
|
result := FXml.FirstChild;
|
|
while (result <> nil) and not (result is TDOMElement) do result := result.NextSibling;
|
|
if (result = nil) or (result.NodeName <> 'plist') then raise exception.Create('"plist" node not found');
|
|
end;
|
|
|
|
constructor TMacBundle.Create(AParameters: TStringList; ALogicDir: string);
|
|
var
|
|
stream: TFileStream;
|
|
begin
|
|
inherited Create(AParameters, ALogicDir);
|
|
ExpectParamCount(1);
|
|
FBundlepath:= ExpandFileName(ReplaceVariables(Param[0]));
|
|
stream := TFileStream.Create(GetPListFilename, fmOpenRead);
|
|
try
|
|
ReadXMLFile(FXml,stream);
|
|
finally
|
|
stream.Free;
|
|
end;
|
|
FDict := ReadDict(GetPList);
|
|
writeln('Bundle ',Name,' version ',VersionToStr(GetVersion));
|
|
end;
|
|
|
|
destructor TMacBundle.Destroy;
|
|
begin
|
|
FXml.Free;
|
|
inherited Destroy;
|
|
end;
|
|
|
|
function TMacBundle.GetVersion: TVersion;
|
|
begin
|
|
if Assigned(FDict) then
|
|
result := StrToVersion(FDict.Values['CFBundleVersion'])
|
|
else raise exception.Create('Version node not found');
|
|
end;
|
|
|
|
procedure TMacBundle.GetVersions(AVersionList: TStringList);
|
|
var
|
|
ver: TVersion;
|
|
verStr: String;
|
|
begin
|
|
ver := GetVersion;
|
|
verStr := VersionToStr(ver);
|
|
if AVersionList.IndexOf(verStr)=-1 then
|
|
AVersionList.Add(verStr);
|
|
end;
|
|
|
|
procedure TMacBundle.CheckVersion(AVersion: TVersion);
|
|
begin
|
|
inherited CheckVersion(AVersion);
|
|
if AVersion<>GetVersion then raise exception.Create('Inconsistent version of bundle '+Name);
|
|
end;
|
|
|
|
procedure TMacBundle.Save;
|
|
begin
|
|
if FChanged then
|
|
begin
|
|
writeln('Updating bundle ', Name,'...');
|
|
WriteXMLFile(FXml, GetPListFilename);
|
|
end else
|
|
writeln('Bundle unchanged');
|
|
end;
|
|
|
|
procedure TMacBundle.UpdateVersion(AVersion: TVersion);
|
|
var
|
|
versionStr: String;
|
|
begin
|
|
if Assigned(FDict) then
|
|
begin
|
|
versionStr := VersionToStr(AVersion);
|
|
if FDict.Values['CFBundleVersion'] <> versionStr then
|
|
begin
|
|
FDict.Values['CFBundleVersion'] := versionStr;
|
|
FChanged := true;
|
|
end;
|
|
if FDict.Values['CFBundleShortVersionString'] <> versionStr then
|
|
begin
|
|
FDict.Values['CFBundleShortVersionString'] := versionStr;
|
|
FChanged := true;
|
|
end;
|
|
UpdateDict(GetPList, FDict);
|
|
end;
|
|
end;
|
|
|
|
end.
|
|
|