mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-09-14 09:29:19 +02:00
190 lines
5.3 KiB
ObjectPascal
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.
|
|
|