Recent

Author Topic: [SOLVED] Detect folder in use  (Read 2475 times)

tudi_x

  • Hero Member
  • *****
  • Posts: 532
[SOLVED] Detect folder in use
« on: November 12, 2017, 03:56:49 pm »
hi All,
i am doing a backup for gogs.io. right now i have a 2 seconds sleep at line 100 in order to have time for the git clone commands to finish but i want to move to a thread approach therefore please advise how i could check that a folder is not in use anymore cross platform.
thank you

Code: Pascal  [Select][+][-]
  1. unit main;
  2.  
  3. {$mode objfpc}{$H+}
  4.  
  5. interface
  6.  
  7. uses
  8.   Classes, SysUtils, StdCtrls, FileUtil, Forms, Controls, Graphics, Dialogs,
  9.   Uni, pqconnection, PostgreSQLUniProvider,    //requires Devart Unidac from 6.3.12
  10.   AbZipper, AbUtils, AbArcTyp,
  11.   strutils,
  12.   Process;
  13.  
  14. type
  15.   TRepo = record
  16.     Name: string;
  17.     Owner: string;
  18.     UpdatedUNIX: cardinal;
  19.   end;
  20.  
  21. type
  22.   TRepos = array of TRepo;
  23.  
  24. type
  25.  
  26.   { TForm1 }
  27.  
  28.   TForm1 = class(TForm)
  29.     Memo1: TMemo;
  30.     PostgreSQLUniProvider1: TPostgreSQLUniProvider;
  31.     UniConnection1: TUniConnection;
  32.     UniQuery1: TUniQuery;
  33.     UniTransaction1: TUniTransaction;
  34.     procedure FormCreate(Sender: TObject);
  35.     procedure FormDestroy(Sender: TObject);
  36.     function ZipFolder(AFolderPath, AFileName: string): boolean;
  37.   private
  38.     _Repos: TRepos;
  39.     _ServerIP: string;
  40.     _ClonedInfo: TStringList;
  41.  
  42.     procedure RunClone(ARepo: TRepo);
  43.     function Occurrences(const ADelimiter, AText: string): integer;
  44.   end;
  45.  
  46. var
  47.   Form1: TForm1;
  48.  
  49. const
  50.   {$IFDEF WINDOWS}
  51.   _Delimiter = '\';
  52.   {$ENDIF}
  53.  
  54. implementation
  55.  
  56. {$R *.lfm}
  57.  
  58. { TForm1 }
  59.  
  60. procedure TForm1.FormCreate(Sender: TObject);
  61. var
  62.   app_folder: string;
  63.   i: word;
  64.  
  65. begin
  66.   _ClonedInfo := TStringList.Create;
  67.   app_folder := ExtractFileDir(Application.ExeName);
  68.  
  69.   try
  70.     _ServerIP := '192.168.1.26';
  71.     UniConnection1.Server := _ServerIP;
  72.     UniConnection1.Port := 5432;
  73.     UniConnection1.Username := 'postgres';
  74.     UniConnection1.Password := 'admin';
  75.     UniConnection1.ProviderName := 'PostgreSQL';
  76.     UniConnection1.Database := 'db_gogs';
  77.     UniConnection1.Connect;
  78.  
  79.     UniTransaction1.DefaultConnection := UniConnection1;
  80.  
  81.     UniQuery1.Transaction := UniTransaction1;
  82.     UniQuery1.Connection := UniConnection1;
  83.     UniQuery1.SQL.Text := 'select r.name, u.name, r.updated_unix from repository r, public.user u where r.owner_id = u.id';
  84.     UniQuery1.ExecSQL;
  85.  
  86.     SetLength(_Repos, UniQuery1.RecordCount);
  87.  
  88.     UniQuery1.First;
  89.     while not UniQuery1.EOF do
  90.     begin
  91.       _Repos[UniQuery1.RecNo - 1].Name := UniQuery1.Fields[0].AsString;
  92.       _Repos[UniQuery1.RecNo - 1].Owner := UniQuery1.Fields[1].AsString;
  93.       _Repos[UniQuery1.RecNo - 1].UpdatedUNIX := UniQuery1.Fields[2].AsInteger;
  94.  
  95.       RunClone(_Repos[UniQuery1.RecNo - 1]);
  96.  
  97.       UniQuery1.Next;
  98.     end;
  99.  
  100.     //sleep(2000);
  101.  
  102.     for i := low(_Repos) to high(_Repos) do
  103.     begin
  104.       if Occurrences(_Delimiter, app_folder) > 1 then
  105.       begin
  106.         ZipFolder(app_folder + _Delimiter + _Repos[i].Name, _Repos[i].Name + '.zip');
  107.       end
  108.       else
  109.       begin
  110.         if Pos(_Delimiter, app_folder) = Length(app_folder) then
  111.         begin
  112.           ZipFolder(app_folder + _Repos[i].Name, _Repos[i].Name + '.zip');
  113.         end
  114.         else
  115.         begin
  116.           ZipFolder(app_folder + _Delimiter + _Repos[i].Name, _Repos[i].Name + '.zip');
  117.         end;
  118.       end;
  119.     end;
  120.  
  121.   except
  122.     on E: Exception do
  123.     begin
  124.       ShowMessage(E.Message);
  125.     end;
  126.   end;
  127.  
  128. end;
  129.  
  130. procedure TForm1.FormDestroy(Sender: TObject);
  131. begin
  132.   if Assigned(_ClonedInfo) then
  133.     FreeAndNil(_ClonedInfo);
  134. end;
  135.  
  136. procedure TForm1.RunClone(ARepo: TRepo);
  137. var
  138.   url: string;
  139.   p: TProcess;
  140.  
  141. begin
  142.   url := 'http://' + _ServerIP + ':3000/' + ARepo.Owner + '/' + ARepo.Name + '.git';
  143.  
  144.   Memo1.Append(url);
  145.  
  146.   p := TProcess.Create(nil);
  147.   p.Executable := 'git';
  148.   p.Parameters.Add('clone');
  149.   p.Parameters.Add(url);
  150.   p.ShowWindow := swoHIDE;
  151.   p.Execute;
  152.   FreeAndNil(p);
  153. end;
  154.  
  155. function TForm1.ZipFolder(AFolderPath, AFileName: string): boolean;
  156. var
  157.   z: TAbZipper;
  158.  
  159. begin
  160.   Result := True;
  161.  
  162.   if DirectoryExists(AFolderPath) then
  163.   begin
  164.     try
  165.       Memo1.Append('zipping: ' + AFolderPath);
  166.  
  167.       z := TAbZipper.Create(self);
  168.       z.ArchiveType := atZip;
  169.       z.StoreOptions := [soRecurse];
  170.  
  171.       if Occurrences(_Delimiter, AFolderPath) > 1 then
  172.       begin
  173.         z.BaseDirectory := Copy(AFolderPath, 1, LastDelimiter(_Delimiter, AFolderPath));
  174.       end
  175.       else
  176.         z.BaseDirectory := AFolderPath;
  177.  
  178.       z.FileName := Copy(AFolderPath, 1, LastDelimiter(_Delimiter, AFolderPath)) + AFileName;
  179.       z.AddFiles(AFolderPath + _Delimiter + '*', faAnyFile);
  180.       z.Save;
  181.       z.CloseArchive;
  182.     finally
  183.       FreeAndNil(z);
  184.     end;
  185.   end
  186.   else
  187.     Result := False;
  188.  
  189. end;
  190.  
  191. function TForm1.Occurrences(const ADelimiter, AText: string): integer;
  192. var
  193.   offset: integer;
  194.  
  195. begin
  196.   Result := 0;
  197.   offset := PosEx(ADelimiter, AText, 1);
  198.  
  199.   while offset <> 0 do
  200.   begin
  201.     Inc(Result);
  202.     offset := PosEx(ADelimiter, AText, offset + length(ADelimiter));
  203.   end;
  204. end;
  205.  
  206.  
  207. end.
« Last Edit: November 19, 2017, 04:27:43 pm by tudi_x »
Lazarus 2.0.2 64b on Debian LXDE 10

ASerge

  • Hero Member
  • *****
  • Posts: 2223
Re: Detect folder in use
« Reply #1 on: November 12, 2017, 04:47:26 pm »
For your purposes, as I understand, it is required that the files in the directory are not opened. Therefore, you need to go through all the files and open them in exclusive mode (and then close, of course). If successful, you can copy them, but ... while you are doing this, someone else could open the file that you have already closed.

tudi_x

  • Hero Member
  • *****
  • Posts: 532
Re: Detect folder in use
« Reply #2 on: November 19, 2017, 04:27:28 pm »
thank you ASerge.
final version is attached. i am waiting for TProcess to exit before deleting the folder.
Lazarus 2.0.2 64b on Debian LXDE 10

 

TinyPortal © 2005-2018