fpc/packages/gitlab/examples/closetodo/closetodo.pp
2021-08-09 10:55:13 +02:00

190 lines
5.3 KiB
ObjectPascal

program closetodo;
{$mode objfpc}{$H+}
uses
{$IFDEF UNIX}
cthreads,
{$ENDIF}
Classes, SysUtils, CustApp, fpjson, gitlabclient,opensslsockets, jsonparser ;
type
{ TCloseTodoApplication }
TCloseTodoApplication = class(TCustomApplication)
private
FConfig : TGitlabConfig;
FClient : TGitLabClient;
FIDS : TStrings;
FIssueState: String;
FQuiet : Boolean;
FNoWrite : Boolean;
FToDoAction : String;
procedure CloseTodo(aID: int64);
procedure DoClientLog(Sender: TObject; const aMessage: string);
procedure DoResource(Sender: TObject; aPage, aIndex, aCount: Integer; aObject: TJSONObject; aContinue: Boolean);
protected
procedure DoRun; override;
public
constructor Create(TheOwner: TComponent); override;
destructor Destroy; override;
procedure Usage(const aError : String); virtual;
Property NoWrite : Boolean Read FNoWrite Write FNoWrite;
Property Quiet : Boolean Read FQuiet Write FQuiet;
Property ToDoAction : String Read FToDoAction Write FToDoAction;
Property IssueState : String Read FIssueState Write FIssueState;
end;
{ TCloseTodoApplication }
procedure TCloseTodoApplication.DoResource(Sender: TObject; aPage, aIndex,
aCount: Integer; aObject: TJSONObject; aContinue: Boolean);
Var
aData : TJSONData;
Msg,aState : String;
aBugID,aBugIID,aProjectID : Int64;
begin
Msg:=Format('[Page %d [%d/%d]: ',[aPage,aIndex,aCount]);
aProjectID:=0;
aBugID:=0;
aBugIID:=0;
aState:='';
aData:=aObject.FindPath('target.state');
if Assigned(aData) then
aState:=aData.AsString;
aData:=aObject.FindPath('project.id');
if Assigned(aData) then
aProjectID:=aData.AsInt64;
aData:=aObject.FindPath('target.id');
if Assigned(aData) then
aBugID:=aData.AsInt64;
aData:=aObject.FindPath('target.iid');
if Assigned(aData) then
aBugIID:=aData.Asint64;
DoClientLog(Self,Msg+Format('Project: %d, bug: %d, bug iid: %d, state : %s',[aProjectID,aBugID,aBugIID,aState]));
if (IssueState='any') or SameText(aState,IssueState) then
begin
if (FConfig.ProjectID=0) or (aProjectID=FConfig.ProjectID) then
FIDS.Add(IntToStr(aObject.Get('id',Int64(0))));
end
end;
procedure TCloseTodoApplication.CloseTodo(aID : int64);
Var
aResource : String;
begin
if (aID=-1) then
exit;
aResource:=Format('todos/%d/mark_as_done',[aID]);
Writeln('Posting ',aResource);
if not NoWrite then
FClient.CreateResource(aResource,Nil);
end;
procedure TCloseTodoApplication.DoClientLog(Sender: TObject;
const aMessage: string);
begin
if not FQuiet then
Writeln(aMessage);
end;
procedure TCloseTodoApplication.DoRun;
var
ErrorMsg: String;
ListFN,ConfigFN : String;
I : Integer;
begin
Terminate;
ErrorMsg:=CheckOptions('hc:l:qna:s:', ['help','config:','list:','quiet','no-write','action:','state:']);
if (ErrorMsg<>'') or HasOption('h','help') then
begin
Usage(ErrorMsg);
Exit;
end;
FQuiet:=HasOption('q','quiet');
FNoWrite:=HasOption('n','no-write');
ConfigFN:=GetOptionValue('c','config');
FToDoAction:=GetOptionValue('a','action');
if FToDoAction='' then
FToDoAction:='assigned';
FIssueState:=GetOptionValue('s','state');
if FIssueState='' then
FIssueState:='closed';
if ConfigFN='' then
begin
Usage('Need gitlab config file');
Exit;
end;
if not FileExists(ConfigFN)then
begin
Usage('Gitlab config file "'+ConfigFN+'" does not exist');
Exit;
end;
FConfig.LoadFromFile(ConfigFN,'');
FClient.Config:=FConfig;
ListFN:=GetOptionValue('l','list');
if FileExists(ListFN)then
FIDS.LoadFromFile(ListFN)
else
begin
FClient.ForEachResource('todos',['action',FTodoAction,'state','pending'],@DoResource);
if ListFN<>'' then
FIDS.SaveToFile(ListFN);
end;
For I:=0 to FIDS.Count-1 do
CloseTodo(StrToInt64Def(FIDS[i],-1));
Writeln(Format('Closed %d todos',[FIDS.Count]));
// stop program loop
Terminate;
end;
constructor TCloseTodoApplication.Create(TheOwner: TComponent);
begin
inherited Create(TheOwner);
FConfig.Reset;
FClient:=TGitLabClient.Create;
FClient.OnLog:=@DoClientLog;
StopOnException:=True;
FIDS:=TStringList.Create;
end;
destructor TCloseTodoApplication.Destroy;
begin
FreeAndNil(FIDS);
FreeAndNil(FClient);
inherited Destroy;
end;
procedure TCloseTodoApplication.Usage(const aError: String);
begin
if (aError<>'') then
Writeln('Error : ',aError);
Writeln('Usage: ', ExeName, ' [options]');
Writeln('Where [Options] is one or more of:');
Writeln('-a --action=TYPE Action of todo: default is "assigned". Other possibilities include:');
Writeln(' mentioned, build_failed, marked, approval_required, unmergeable, directly_addressed or merge_train_removed.');
Writeln('-c --config=FILE Config file');
Writeln('-h --help This help');
Writeln('-l --list=FILE if file exists, read todo IDS from list. If file does not exist, write file after querying gitlab');
Writeln('-n --no-write Do not actaully change the TODO item');
Writeln('-q --quiet less messages');
Writeln('-s --state=STATE State of issue coupled to TODO. default is "closed". If set to "any" all issues will be marked.');
end;
var
Application: TCloseTodoApplication;
begin
Application:=TCloseTodoApplication.Create(nil);
Application.Title:='Close Todos Application';
Application.Run;
Application.Free;
end.