FIX: Bug [0002395] Buffered content of 7z archieve is obsolete #2

This commit is contained in:
Alexander Koblov 2020-05-02 11:45:17 +00:00
commit 546aee0a4e
5 changed files with 126 additions and 78 deletions

View file

@ -100,37 +100,43 @@ end;
procedure TMultiArchiveCalcStatisticsOperation.ProcessSubDirs(const srcPath: String);
var
I: Integer;
ArchiveItem: TArchiveItem;
AFileList: TList;
CurrFileName: String;
ArchiveItem: TArchiveItem;
ModificationTime: TDateTime;
begin
for I:= 0 to FMultiArchiveFileSource.ArchiveFileList.Count - 1 do
begin
ArchiveItem := TArchiveItem(FMultiArchiveFileSource.ArchiveFileList.Items[I]);
CurrFileName := PathDelim + ArchiveItem.FileName;
AFileList:= FMultiArchiveFileSource.ArchiveFileList.LockList;
try
for I:= 0 to AFileList.Count - 1 do
begin
ArchiveItem := TArchiveItem(AFileList.Items[I]);
CurrFileName := PathDelim + ArchiveItem.FileName;
if not IsInPath(srcPath, CurrFileName, True, False) then
Continue;
if not IsInPath(srcPath, CurrFileName, True, False) then
Continue;
if FMultiArchiveFileSource.FileIsDirectory(ArchiveItem) then
Inc(FStatistics.Directories)
else if FMultiArchiveFileSource.FileIsLink(ArchiveItem) then
Inc(FStatistics.Links)
else
begin
Inc(FStatistics.Files);
FStatistics.Size := FStatistics.Size + ArchiveItem.UnpSize;
try
with ArchiveItem do
ModificationTime := EncodeDate(Year, Month, Day) + EncodeTime(Hour, Minute, Second, 0);
if ModificationTime < FStatistics.OldestFile then
FStatistics.OldestFile := ModificationTime;
if ModificationTime > FStatistics.NewestFile then
FStatistics.NewestFile := ModificationTime;
except
on EConvertError do;
end;
if FMultiArchiveFileSource.FileIsDirectory(ArchiveItem) then
Inc(FStatistics.Directories)
else if FMultiArchiveFileSource.FileIsLink(ArchiveItem) then
Inc(FStatistics.Links)
else
begin
Inc(FStatistics.Files);
FStatistics.Size := FStatistics.Size + ArchiveItem.UnpSize;
try
with ArchiveItem do
ModificationTime := EncodeDate(Year, Month, Day) + EncodeTime(Hour, Minute, Second, 0);
if ModificationTime < FStatistics.OldestFile then
FStatistics.OldestFile := ModificationTime;
if ModificationTime > FStatistics.NewestFile then
FStatistics.NewestFile := ModificationTime;
except
on EConvertError do;
end;
end;
end;
finally
FMultiArchiveFileSource.ArchiveFileList.UnlockList;
end;
end;

View file

@ -8,7 +8,7 @@ uses
Classes, SysUtils, contnrs, DCStringHashListUtf8, uOSUtils,
uMultiArc, uFile, uFileSourceProperty, uFileSourceOperationTypes,
uArchiveFileSource, uFileProperty, uFileSource, uFileSourceOperation,
uMultiArchiveUtil, DCBasicTypes;
uMultiArchiveUtil, DCBasicTypes, uClassesEx;
type
@ -18,7 +18,7 @@ type
['{71BF41D3-1E40-4E84-83BB-B6D3E0DEB6FC}']
function GetPassword: String;
function GetArcFileList: TObjectList;
function GetArcFileList: TThreadObjectList;
function GetMultiArcItem: TMultiArcItem;
function FileIsLink(ArchiveItem: TArchiveItem): Boolean;
@ -30,7 +30,7 @@ type
out FilesCount: Int64; out FilesSize: Int64);
property Password: String read GetPassword;
property ArchiveFileList: TObjectList read GetArcFileList;
property ArchiveFileList: TThreadObjectList read GetArcFileList;
property MultiArcItem: TMultiArcItem read GetMultiArcItem;
end;
@ -40,7 +40,7 @@ type
private
FPassword: String;
FOutputParser: TOutputParser;
FArcFileList : TObjectList;
FArcFileList : TThreadObjectList;
FMultiArcItem: TMultiArcItem;
FAllDirsList,
FExistsDirList: TStringHashListUtf8;
@ -56,7 +56,7 @@ type
function FileIsLink(ArchiveItem: TArchiveItem): Boolean;
function FileIsDirectory(ArchiveItem: TArchiveItem): Boolean;
function GetArcFileList: TObjectList;
function GetArcFileList: TThreadObjectList;
protected
@ -116,7 +116,7 @@ type
class function CheckAddonByName(const anArchiveFileName: String): Boolean;
property Password: String read GetPassword;
property ArchiveFileList: TObjectList read GetArcFileList;
property ArchiveFileList: TThreadObjectList read GetArcFileList;
property MultiArcItem: TMultiArcItem read GetMultiArcItem;
end;
@ -237,7 +237,7 @@ begin
inherited Create(anArchiveFileSource, anArchiveFileName);
FMultiArcItem := aMultiArcItem;
FArcFileList := TObjectList.Create(True);
FArcFileList := TThreadObjectList.Create;
FOutputParser := TOutputParser.Create(aMultiArcItem, anArchiveFileName);
FOutputParser.OnGetArchiveItem:= @OnGetArchiveItem;
@ -342,6 +342,7 @@ end;
function TMultiArchiveFileSource.SetCurrentWorkingDirectory(NewDir: String): Boolean;
var
I: Integer;
AFileList: TList;
ArchiveItem: TArchiveItem;
begin
Result := False;
@ -352,20 +353,25 @@ begin
NewDir := IncludeTrailingPathDelimiter(NewDir);
// Search file list for a directory with name NewDir.
for I := 0 to FArcFileList.Count - 1 do
begin
ArchiveItem := TArchiveItem(FArcFileList.Items[I]);
if FileIsDirectory(ArchiveItem) and (Length(ArchiveItem.FileName) > 0) then
AFileList:= FArcFileList.LockList;
try
// Search file list for a directory with name NewDir.
for I := 0 to AFileList.Count - 1 do
begin
if NewDir = IncludeTrailingPathDelimiter(GetRootDir() + ArchiveItem.FileName) then
Exit(True);
ArchiveItem := TArchiveItem(AFileList.Items[I]);
if FileIsDirectory(ArchiveItem) and (Length(ArchiveItem.FileName) > 0) then
begin
if NewDir = IncludeTrailingPathDelimiter(GetRootDir() + ArchiveItem.FileName) then
Exit(True);
end;
end;
finally
FArcFileList.UnlockList;
end;
end;
end;
function TMultiArchiveFileSource.GetArcFileList: TObjectList;
function TMultiArchiveFileSource.GetArcFileList: TThreadObjectList;
begin
Result := FArcFileList;
end;
@ -609,6 +615,7 @@ procedure TMultiArchiveFileSource.FillAndCount(const FileMask: String; Files: TF
var
aFile: TFile;
I, J: Integer;
AFileList: TList;
sFileName: String;
MaskList: TMaskList;
ArchiveItem: TArchiveItem;
@ -621,37 +628,42 @@ begin
else begin
MaskList:= TMaskList.Create(FileMask);
end;
for I := 0 to ArchiveFileList.Count - 1 do
begin
ArchiveItem := TArchiveItem(ArchiveFileList.Items[I]);
sFileName:= PathDelim + ArchiveItem.FileName;
// And name matches file mask
if ((MaskList = nil) or MaskList.Matches(ExtractFileNameEx(ArchiveItem.FileName))) then
AFileList:= ArchiveFileList.LockList;
try
for I := 0 to AFileList.Count - 1 do
begin
for J := 0 to Files.Count - 1 do
begin
aFile := Files[J];
ArchiveItem := TArchiveItem(AFileList.Items[I]);
sFileName:= PathDelim + ArchiveItem.FileName;
if (aFile.FullPath = sFileName) or // Item in the list is a file, only compare names.
(aFile.AttributesProperty.IsDirectory and IsInPath(aFile.FullPath, sFileName, True, False)) then // Check if 'FileName' is in this directory or any of its subdirectories.
begin
if FileIsDirectory(ArchiveItem) then
begin
if CountDirs then Inc(FilesCount);
end
else
begin
Inc(FilesCount);
Inc(FilesSize, aFile.Size);
end;
aFile:= TMultiArchiveFileSource.CreateFile(ExtractFilePathEx(ArchiveItem.FileName), ArchiveItem, FMultiArcItem.FFormMode);
aFile.FullPath:= ExcludeFrontPathDelimiter(aFile.FullPath);
NewFiles.Add(aFile);
end;
end; // for J
end;
end; // for I
// And name matches file mask
if ((MaskList = nil) or MaskList.Matches(ExtractFileNameEx(ArchiveItem.FileName))) then
begin
for J := 0 to Files.Count - 1 do
begin
aFile := Files[J];
if (aFile.FullPath = sFileName) or // Item in the list is a file, only compare names.
(aFile.AttributesProperty.IsDirectory and IsInPath(aFile.FullPath, sFileName, True, False)) then // Check if 'FileName' is in this directory or any of its subdirectories.
begin
if FileIsDirectory(ArchiveItem) then
begin
if CountDirs then Inc(FilesCount);
end
else
begin
Inc(FilesCount);
Inc(FilesSize, aFile.Size);
end;
aFile:= TMultiArchiveFileSource.CreateFile(ExtractFilePathEx(ArchiveItem.FileName), ArchiveItem, FMultiArcItem.FFormMode);
aFile.FullPath:= ExcludeFrontPathDelimiter(aFile.FullPath);
NewFiles.Add(aFile);
end;
end; // for J
end;
end; // for I
finally
ArchiveFileList.UnlockList;
end;
MaskList.Free;
end;

View file

@ -41,6 +41,11 @@ var
begin
FFiles.Clear;
if FMultiArchiveFileSource.Changed then
begin
FMultiArchiveFileSource.Reload(Path);
end;
if not FileSource.IsPathAtRoot(Path) then
begin
aFile := TMultiArchiveFileSource.CreateFile(Path);
@ -49,8 +54,9 @@ begin
FFiles.Add(AFile);
end;
ArcFileList := FMultiArchiveFileSource.ArchiveFileList;
for I := 0 to ArcFileList.Count - 1 do
ArcFileList := FMultiArchiveFileSource.ArchiveFileList.Clone;
try
for I := 0 to ArcFileList.Count - 1 do
begin
CheckOperationState;
@ -63,6 +69,9 @@ begin
aFile := TMultiArchiveFileSource.CreateFile(Path, TArchiveItem(ArcFileList.Items[I]), FFormMode);
FFiles.Add(AFile);
end;
finally
ArcFileList.Free;
end;
end;
end.

View file

@ -71,7 +71,7 @@ type
public
procedure Clear;
function Clone: TObjectList;
function Add(AObject: TObject): Integer;
function Add(AObject: TObjectEx): Integer;
function LockList: TObjectList;
procedure UnlockList;
end;
@ -135,7 +135,7 @@ begin
end;
end;
function TThreadObjectList.Add(AObject: TObject): Integer;
function TThreadObjectList.Add(AObject: TObjectEx): Integer;
begin
Result:= FList.Add(AObject);
end;

View file

@ -3,7 +3,7 @@
-------------------------------------------------------------------------
Implementation of multi archiver support
Copyright (C) 2010-2019 Koblov Alexander (Alexx2000@mail.ru)
Copyright (C) 2010-2020 Koblov Alexander (Alexx2000@mail.ru)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -27,7 +27,7 @@ unit uMultiArc;
interface
uses
Classes, SysUtils, DCBasicTypes, uMasks;
Classes, SysUtils, DCBasicTypes, uMasks, uClassesEx;
const
MaxSignSize = 1024;
@ -81,7 +81,7 @@ type
{ TArchiveItem }
TArchiveItem = class
TArchiveItem = class(TObjectEx)
FileName,
FileExt,
FileLink: String;
@ -94,6 +94,7 @@ type
Minute,
Second: Word;
Attributes: TFileAttrs;
function Clone: TArchiveItem; override;
end;
{ TMultiArcItem }
@ -176,6 +177,26 @@ uses
crc, LCLProc, StrUtils, Math, FileUtil, DCClassesUtf8, uDCUtils, DCOSUtils,
DCStrUtils;
{ TArchiveItem }
function TArchiveItem.Clone: TArchiveItem;
begin
Result:= TArchiveItem.Create;
Result.FileName:= FileName;
Result.FileExt:= FileExt;
Result.FileLink:= FileLink;
Result.PackSize:= PackSize;
Result.UnpSize:= UnpSize;
Result.Year:= Year;
Result.Month:= Month;
Result.Day:= Day;
Result.Hour:= Hour;
Result.Minute:= Minute;
Result.Second:= Second;
Result.Attributes:= Attributes;
end;
{ TMultiArcList }
function TMultiArcList.GetCount: LongInt;