(**************************************************************************** * WANT - A build management tool. * * Copyright (c) 2001-2003 Juancarlo Anez, Caracas, Venezuela. * * All rights reserved. * * * * This library is free software; you can redistribute it and/or * * modify it under the terms of the GNU Lesser General Public * * License as published by the Free Software Foundation; either * * version 2.1 of the License, or (at your option) any later version. * * * * This library is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * * Lesser General Public License for more details. * * * * You should have received a copy of the GNU Lesser General Public * * License along with this library; if not, write to the Free Software * * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * ****************************************************************************) { @brief @author Juancarlo Aņez } unit PatternSets; interface uses Classes, JALOwnedTrees, WildPaths, WantUtils, WantClasses; type TPatternPart = class(TScriptElement) protected procedure SetValue(Value: string); virtual; abstract; published property name: string write SetValue; end; TIncludeElement = class(TPatternPart) procedure SetValue(Value: string); override; end; TExcludeElement = class(TPatternPart) procedure SetValue(Value: string); override; end; TPatternSet = class(TScriptElement) protected FIncludes: TStrings; FExcludes: TStrings; FPatternSets: array of TPatternSet; procedure InsertNotification(Child :TTree); override; procedure AddPatternSet(APatternSet: TPatternSet); procedure SetRefId(Id :string); procedure SetIncludes(Value: TStrings); procedure SetExcludes(Value: TStrings); procedure DoInclude( Files: TStrings; Pattern: TPath; Base: string; IncAtt: TFileAttributes = AnyFileAttribute; ExcAtt: TFileAttributes = [] ); virtual; procedure DoExclude(Files: TStrings; Pattern: TPath; Base: string); virtual; procedure DoIncludes(Files: TStrings; Base: string; IncAtt: TFileAttributes = AnyFileAttribute; ExcAtt: TFileAttributes = [] ); virtual; procedure DoExcludes(Files: TStrings; Base: string); virtual; public constructor Create(Owner: TScriptElement); override; destructor Destroy; override; procedure Include(Pattern: TPath); overload; procedure Exclude(Pattern: TPath); overload; function Paths : TPaths; procedure GetPaths(Files: TStrings); procedure AddPaths(Paths: TPaths); function SystemPaths: TSystemPaths; function RelativePaths: TPaths; function MovePaths(ToBase: TPath): TPaths; property Includes: TStrings read FIncludes; property Excludes: TStrings read FExcludes; published function createInclude: TIncludeElement; function createExclude: TExcludeElement; property id; property refid :string write SetRefId; end; TCustomFileSet = class(TPatternSet) public procedure AddDefaultPatterns; virtual; property dir: TPath read GetBaseDir write SetBaseDir; end; TCustomDirSet = class(TCustomFileSet) protected procedure DoIncludes(Files: TStrings; Base: string; IncAtt: TFileAttributes = AnyFileAttribute; ExcAtt: TFileAttributes = [] ); override; procedure DoExcludes(Files: TStrings; Base: string); override; end; TFileSet = class(TCustomFileSet) published property dir; end; TDirSet = class(TCustomDirSet) published property dir; end; implementation { TIncludeElement } procedure TIncludeElement.SetValue(Value: string); begin (Owner as TPatternSet).Include(Value); end; { TExcludeElement } procedure TExcludeElement.SetValue(Value: string); begin (Owner as TPatternSet).Exclude(Value); end; { TPatternSet } constructor TPatternSet.Create(Owner: TScriptElement); begin inherited Create(Owner); FIncludes := TStringList.Create; FExcludes := TStringList.Create; end; destructor TPatternSet.Destroy; begin FreeAndNil(FIncludes); FreeAndNil(FExcludes); inherited Destroy; end; procedure TPatternSet.SetIncludes(Value: TStrings); begin FIncludes.Assign(Value); end; procedure TPatternSet.SetExcludes(Value: TStrings); begin FExcludes.Assign(Value); end; procedure TPatternSet.Include(Pattern: TPath); begin Assert(Pattern <> ''); FIncludes.Add(Pattern); end; procedure TPatternSet.Exclude(Pattern: TPath); begin FExcludes.Add(Pattern); end; procedure TPatternSet.DoInclude(Files: TStrings; Pattern: TPath; Base: string; IncAtt, ExcAtt: TFileAttributes); begin Wild(Files, Pattern, Base, IncAtt, ExcAtt); end; procedure TPatternSet.DoExclude(Files: TStrings; Pattern: TPath; Base: string); var Excluded: TPaths; Path : TPath; f : Integer; begin Excluded := SplitPath(ToRelativePath(Pattern)); for f := Files.Count-1 downto 0 do begin Path := ToRelativePath(Files[f]); if IsMatch(Excluded, SplitPath(Path)) then Files.Delete(f); end; end; function TPatternSet.createInclude: TIncludeElement; begin Result := TIncludeElement.Create(Self); end; function TPatternSet.createExclude: TExcludeElement; begin Result := TExcludeElement.Create(Self); end; procedure TPatternSet.DoIncludes(Files: TStrings; Base: string; IncAtt, ExcAtt: TFileAttributes); var i: Integer; begin if (Base <> '') and (FIncludes.Count = 0) and (Length(FPatternSets) = 0) then DoInclude(Files, '**', Base, IncAtt, ExcAtt) else for i := 0 to FIncludes.Count-1 do DoInclude(Files, FIncludes[i], Base, IncAtt, ExcAtt); for i := Low(FPatternSets) to High(FPatternSets) do FPatternSets[i].DoIncludes(Files, Base, IncAtt, ExcAtt); end; procedure TPatternSet.DoExcludes(Files: TStrings; Base: string); var i: Integer; begin for i := 0 to FExcludes.Count-1 do DoExclude(Files, FExcludes[i], Base); for i := Low(FPatternSets) to High(FPatternSets) do FPatternSets[i].DoExcludes(Files, Base); end; procedure TPatternSet.AddPatternSet(APatternSet: TPatternSet); begin SetLength(FPatternSets, 1+Length(FPatternSets)); FPatternSets[High(FPatternSets)] := APatternSet; end; procedure TPatternSet.SetRefId(Id: string); begin AddPatternSet(Project.FindChild(Id, TPatternSet) as TPatternSet); end; function TPatternSet.Paths: TPaths; var Files : TStringList; begin Files := TStringList.Create; try Files.Sorted := True; Log(vlDebug, 'fileset basedir="%s"', [basedir]); GetPaths(Files); Result := StringsToPaths(Files); finally FreeAndNil(Files); end; end; procedure TPatternSet.AddPaths(Paths: TPaths); var Files : TStringList; i, n : Integer; begin Files := TStringList.Create; try Files.Sorted := True; GetPaths(Files); n := Length(Paths); SetLength(Paths, n + Files.Count); for i := 0 to Files.Count-1 do Paths[i+n] := Files[i]; finally FreeAndNil(Files); end; end; procedure TPatternSet.GetPaths(Files: TStrings); begin DoIncludes(Files, BasePath); DoExcludes(Files, BasePath); end; function TPatternSet.MovePaths(ToBase: TPath): TPaths; begin Result := WildPaths.MovePaths(Paths, BasePath, ToBase); end; function TPatternSet.RelativePaths: TPaths; begin Result := ToRelativePaths(Paths, BasePath); end; function TPatternSet.SystemPaths: TSystemPaths; begin Result := ToSystemPaths(Paths); end; procedure TPatternSet.InsertNotification(Child: TTree); begin if Child is TPatternSet then AddPatternSet(TPatternSet(Child)); end; { TCustomFileSet } procedure TCustomFileSet.AddDefaultPatterns; begin // add the default Ant excludes Exclude('**/CVS/**'); Exclude('**/.cvsignore'); Exclude('**/*~'); Exclude('**/#*#'); Exclude('**/%*%'); // Some additional excludes Exclude('**/*.*~*'); Exclude('**/*.bak'); Exclude('**/dunit.ini'); end; { TCustomDirSet } procedure TCustomDirSet.DoIncludes(Files: TStrings; Base: string; IncAtt, ExcAtt: TFileAttributes); begin inherited DoIncludes(Files, Base, [Directory], ExcAtt); //inherited DoIncludes(Files, Base, IncAtt, ExcAtt); end; procedure TCustomDirSet.DoExcludes(Files: TStrings; Base: string); var f : Integer; begin for f := Files.Count-1 downto 0 do if not PathIsdir(PathConcat(Base, Files[f])) then Files.Delete(f); inherited DoExcludes(Files, Base); end; initialization RegisterElement(TPatternSet); end.