ADD: Possibility to use a search template for move operation (only for FileSystemFileSource). The template defines which files/directories to move and which to exclude.

This commit is contained in:
cobines 2012-04-19 06:56:09 +00:00
commit bf0fa71a4c
5 changed files with 56 additions and 17 deletions

View file

@ -201,7 +201,6 @@ inherited FileSystemCopyMoveOperationOptionsUI: TFileSystemCopyMoveOperationOpti
ClientHeight = 64
ClientWidth = 213
TabOrder = 1
Visible = False
object btnSearchTemplate: TBitBtn
AnchorSideLeft.Side = asrBottom
AnchorSideTop.Control = gbFileTemplate

View file

@ -249,7 +249,7 @@ begin
SearchTemplate := FTemplate;
FTemplate := nil;
end;
RemoveEmptyTemplateDirectories := cbExcludeEmptyDirectories.Checked;
ExcludeEmptyTemplateDirectories := cbExcludeEmptyDirectories.Checked;
end;
end;
@ -289,6 +289,12 @@ begin
SetCopyOption(Options, caoCopyTime, cbCopyTime.Checked);
SetCopyOption(Options, caoCopyOwnership, cbCopyOwnership.Checked);
CopyAttributesOptions := Options;
if Assigned(FTemplate) then
begin
SearchTemplate := FTemplate;
FTemplate := nil;
end;
ExcludeEmptyTemplateDirectories := cbExcludeEmptyDirectories.Checked;
end;
end;
@ -299,7 +305,6 @@ begin
inherited;
cbDropReadOnlyFlag.Visible := True;
cbFollowLinks.Visible := True;
gbFileTemplate.Visible := True;
end;
end.

View file

@ -24,7 +24,7 @@ type
private
FOperationHelper: TFileSystemOperationHelper;
FRemoveEmptyTemplateDirectories: Boolean;
FExcludeEmptyTemplateDirectories: Boolean;
FSearchTemplate: TSearchTemplate;
FSetPropertyError: TFileSourceOperationOptionSetPropertyError;
FSourceFilesTree: TFileTree; // source files including all files/dirs in subdirectories
@ -64,7 +64,7 @@ type
property FileExistsOption: TFileSourceOperationOptionFileExists read FFileExistsOption write FFileExistsOption;
property DirExistsOption: TFileSourceOperationOptionDirectoryExists read FDirExistsOption write FDirExistsOption;
property SetPropertyError: TFileSourceOperationOptionSetPropertyError read FSetPropertyError write FSetPropertyError;
property RemoveEmptyTemplateDirectories: Boolean read FRemoveEmptyTemplateDirectories write FRemoveEmptyTemplateDirectories;
property ExcludeEmptyTemplateDirectories: Boolean read FExcludeEmptyTemplateDirectories write FExcludeEmptyTemplateDirectories;
{en
Operation takes ownership of assigned template and will free it.
}
@ -125,6 +125,7 @@ begin
FSkipAllBigFiles := False;
FAutoRenameItSelf := False;
FCorrectSymLinks := gOperationOptionCorrectLinks;
FExcludeEmptyTemplateDirectories := True;
inherited Create(aSourceFileSource, aTargetFileSource, theSourceFiles, aTargetPath);
end;
@ -150,7 +151,7 @@ begin
try
TreeBuilder.SymLinkOption := Self.SymLinkOption;
TreeBuilder.SearchTemplate := Self.SearchTemplate;
TreeBuilder.RemoveEmptyTemplateDirectories := Self.RemoveEmptyTemplateDirectories;
TreeBuilder.ExcludeEmptyTemplateDirectories := Self.ExcludeEmptyTemplateDirectories;
TreeBuilder.BuildFromFiles(SourceFiles);
FSourceFilesTree := TreeBuilder.ReleaseTree;

View file

@ -12,7 +12,8 @@ uses
uFileSourceOperationOptionsUI,
uFile,
uFileSystemUtil,
DCOSUtils;
DCOSUtils,
uSearchTemplate;
type
@ -23,6 +24,8 @@ type
private
FCopyAttributesOptions: TCopyAttributesOptions;
FOperationHelper: TFileSystemOperationHelper;
FExcludeEmptyTemplateDirectories: Boolean;
FSearchTemplate: TSearchTemplate;
FSetPropertyError: TFileSourceOperationOptionSetPropertyError;
FSourceFilesTree: TFileTree; // source files including all files/dirs in subdirectories
FStatistics: TFileSourceMoveOperationStatistics; // local copy of statistics
@ -33,6 +36,7 @@ type
FFileExistsOption: TFileSourceOperationOptionFileExists;
FDirExistsOption: TFileSourceOperationOptionDirectoryExists;
FCorrectSymlinks: Boolean;
procedure SetSearchTemplate(AValue: TSearchTemplate);
protected
@ -56,6 +60,11 @@ type
property FileExistsOption: TFileSourceOperationOptionFileExists read FFileExistsOption write FFileExistsOption;
property DirExistsOption: TFileSourceOperationOptionDirectoryExists read FDirExistsOption write FDirExistsOption;
property SetPropertyError: TFileSourceOperationOptionSetPropertyError read FSetPropertyError write FSetPropertyError;
property ExcludeEmptyTemplateDirectories: Boolean read FExcludeEmptyTemplateDirectories write FExcludeEmptyTemplateDirectories;
{en
Operation takes ownership of assigned template and will free it.
}
property SearchTemplate: TSearchTemplate read FSearchTemplate write SetSearchTemplate;
end;
implementation
@ -81,6 +90,7 @@ begin
FCheckFreeSpace := gOperationOptionCheckFreeSpace;
FSkipAllBigFiles := False;
FCorrectSymlinks := gOperationOptionCorrectLinks;
FExcludeEmptyTemplateDirectories := True;
inherited Create(aFileSource, theSourceFiles, aTargetPath);
end;
@ -90,6 +100,7 @@ begin
inherited Destroy;
FreeAndNil(FSourceFilesTree);
FreeAndNil(FOperationHelper);
FreeAndNil(FSearchTemplate);
end;
procedure TFileSystemMoveOperation.Initialize;
@ -105,6 +116,9 @@ begin
try
// In move operation don't follow symlinks.
TreeBuilder.SymLinkOption := fsooslDontFollow;
TreeBuilder.SearchTemplate := Self.SearchTemplate;
TreeBuilder.ExcludeEmptyTemplateDirectories := Self.ExcludeEmptyTemplateDirectories;
TreeBuilder.BuildFromFiles(SourceFiles);
FSourceFilesTree := TreeBuilder.ReleaseTree;
FStatistics.TotalFiles := TreeBuilder.FilesCount;
@ -142,6 +156,12 @@ begin
FOperationHelper.ProcessTree(FSourceFilesTree);
end;
procedure TFileSystemMoveOperation.SetSearchTemplate(AValue: TSearchTemplate);
begin
FSearchTemplate.Free;
FSearchTemplate := AValue;
end;
procedure TFileSystemMoveOperation.Finalize;
begin
if Assigned(FOperationHelper) then

View file

@ -29,6 +29,8 @@ type
public
// True if any of the subnodes (recursively) are links.
SubnodesHaveLinks: Boolean;
// Whether directory or subdirectories have any elements that will not be copied/moved.
SubnodesHaveExclusions: Boolean;
end;
TUpdateStatisticsFunction = procedure(var NewStatistics: TFileSourceCopyOperationStatistics) of object;
@ -57,7 +59,7 @@ type
FFilesSize: Int64;
FExcludeRootDir: Boolean;
FFileTemplate: TSearchTemplate;
FRemoveEmptyTemplateDirectories: Boolean;
FExcludeEmptyTemplateDirectories: Boolean;
FSymlinkOption: TFileSourceOperationOptionSymLink;
FRecursive: Boolean;
FFileChecks: TFindFileChecks;
@ -93,7 +95,7 @@ type
property FilesCount: Int64 read FFilesCount;
property DirectoriesCount: Int64 read FDirectoriesCount;
property ItemsCount: Int64 read GetItemsCount;
property RemoveEmptyTemplateDirectories: Boolean read FRemoveEmptyTemplateDirectories write FRemoveEmptyTemplateDirectories;
property ExcludeEmptyTemplateDirectories: Boolean read FExcludeEmptyTemplateDirectories write FExcludeEmptyTemplateDirectories;
{en
Does not take ownership of SearchTemplate and does not free it.
}
@ -443,10 +445,12 @@ procedure TFileSystemTreeBuilder.AddDirectory(aFile: TFile; CurrentNode: TFileTr
var
AddedNode: TFileTreeNode;
AddedIndex: Integer;
NodeData: TFileTreeNodeData;
begin
AddedIndex := CurrentNode.AddSubNode(aFile);
AddedNode := CurrentNode.SubNodes[AddedIndex];
AddedNode.Data := TFileTreeNodeData.Create;
NodeData := TFileTreeNodeData.Create;
AddedNode.Data := NodeData;
Inc(FDirectoriesCount);
@ -454,16 +458,19 @@ begin
begin
AddFilesInDirectory(aFile.FullPath + DirectorySeparator, AddedNode);
if Assigned(FFileTemplate) and FRemoveEmptyTemplateDirectories and
if Assigned(FFileTemplate) and FExcludeEmptyTemplateDirectories and
(AddedNode.SubNodesCount = 0) then
begin
CurrentNode.RemoveSubNode(AddedIndex);
(CurrentNode.Data as TFileTreeNodeData).SubnodesHaveExclusions := True;
end
else
begin
// Propagate flag to parent.
if (AddedNode.Data as TFileTreeNodeData).SubnodesHaveLinks then
// Propagate flags to parent.
if NodeData.SubnodesHaveLinks then
(CurrentNode.Data as TFileTreeNodeData).SubnodesHaveLinks := True;
if NodeData.SubnodesHaveExclusions then
(CurrentNode.Data as TFileTreeNodeData).SubnodesHaveExclusions := True;
end;
end;
end;
@ -514,7 +521,10 @@ begin
if Matches and (AFile.IsDirectory or AFile.IsLinkToDirectory) then
Matches := CheckDirectoryNameRelative(FFileChecks, aFile.FullPath, FRootDir);
if not Matches then
begin
(CurrentNode.Data as TFileTreeNodeData).SubnodesHaveExclusions := True;
Exit;
end;
end;
if aFile.IsDirectory then
@ -1105,8 +1115,12 @@ end;
function TFileSystemOperationHelper.ProcessDirectory(aNode: TFileTreeNode; AbsoluteTargetFileName: String): Boolean;
var
bRemoveDirectory: Boolean;
NodeData: TFileTreeNodeData;
begin
bRemoveDirectory := (FMode = fsohmMove);
NodeData := aNode.Data as TFileTreeNodeData;
// If some files will not be moved then source directory cannot be deleted.
bRemoveDirectory := (FMode = fsohmMove) and (NodeData.SubnodesHaveExclusions = False);
case TargetExists(aNode, AbsoluteTargetFileName) of
fsoterSkip:
@ -1119,11 +1133,11 @@ begin
begin
// Try moving whole directory tree. It can be done only if we don't have
// to process each subnode: if there are no links, or they're not being
// processed and if the files are not being renamed.
// processed, if the files are not being renamed or excluded.
if (FMode = fsohmMove) and
(not FRenamingFiles) and
((FCorrectSymlinks = False) or
((aNode.Data as TFileTreeNodeData).SubnodesHaveLinks = False)) and
((FCorrectSymlinks = False) or (NodeData.SubnodesHaveLinks = False)) and
(NodeData.SubnodesHaveExclusions = False) and
mbRenameFile(aNode.TheFile.FullPath, AbsoluteTargetFileName) then
begin
// Success.