program Make; {$mode objfpc}{$H+} uses {$IFDEF UNIX}{$IFDEF UseCThreads} cthreads, {$ENDIF}{$ENDIF} classes, sysUtils, custApp { you can add units after this }, math, tools, lowlevelunit, dateiBeziehungen, regExpr; type { tMake } tMake = class(tCustomApplication) protected procedure doRun; override; public constructor create(theOwner: tComponent); override; procedure writeHelp; virtual; end; function liesPruefsummenfile(sumNam: string; var dats: tDateienMitDaten): boolean; var f: textfile; i,j: longint; gutschlecht: tStringlistBArray; gefunden,gut: boolean; begin result:=false; if sumNam='' then begin writeln('Leerer Name als summendatei angegeben!'); exit; end; if not fileexists(sumNam) then begin assignfile(f,sumNam); rewrite(f); closefile(f); end; if not fileexists(sumNam) then begin writeln('Ich bin nicht in der Lage, die bisher nicht existierende Datei '''+sumNam+''' anzulegen!'); exit; end; gutschlecht:=testeSummen(sumNam); for gut:=false to true do for i:=0 to gutschlecht[gut].count-1 do begin gefunden:=false; for j:=0 to length(dats)-1 do if dats[j].name=gutschlecht[gut][i] then begin if gut then dats[j].aktuell:=aAktuell else dats[j].aktuell:=aVeraltet; gefunden:=true; break; end; if not gefunden then begin if not gut then begin // dateien mit ungültiger Prüfsumme können auch nicht vorhanden sein, setlength(dats,length(dats)+1); // dann werden sie einfach eingefügt dats[length(dats)-1]:=tDateiMitDatum.create; dats[length(dats)-1].name:=gutschlecht[gut][i]; dats[length(dats)-1].aktuell:=aVeraltet; continue; end; writeln('In der Summendatei gibt es eine Datei mit gültiger Prüfsumme, die ich nicht finden kann: '''+gutschlecht[gut][i]+'''!'); for gefunden:=false to true do gutschlecht[gefunden].free; exit; end; end; for gefunden:=false to true do gutschlecht[gefunden].free; result:=true; end; procedure zieleHinzufuegen(var ziele: tDateienMitDaten; ziel,quelle,inputfile: string; var dats: tDateienMitDaten); var i,ebene,ende: integer; s,t,u: string; wasda: boolean; begin if pos('{',ziel)=0 then begin if not quellersetzung(ziel,quelle,inputfile) then exit; ziel:=unescape(ziel); i:=0; wasda:=false; while i0) or (ziel[ende]<>'}') do begin inc(ende); case ziel[ende] of '{': inc(ebene); '}': dec(ebene); end{of case}; end; s:=copy(ziel,1,pos('{',ziel)-1); t:=copy(ziel,pos('{',ziel)+1,ende-pos('{',ziel)-1); u:=copy(ziel,ende+1,length(ziel)); if unescapedpos('..',t)>0 then begin for i:=strtoint(copy(t,1,unescapedpos('..',t)-1)) to strtoint(copy(t,unescapedpos('..',t)+2,length(t))) do zieleHinzufuegen(ziele,s+inttostr(i)+u,quelle,inputfile,dats); end else begin t:=t+','; while unescapedpos(',',t)>0 do begin zieleHinzufuegen(ziele,s+copy(t,1,unescapedpos(',',t)-1)+u,quelle,inputfile,dats); delete(t,1,unescapedpos(',',t)); end; end; end; end; procedure findeMehrZiele(var ziele: tDateienMitDaten; zieleFkt: tStringList; quelle,inputfile: string; var dats: tDateienMitDaten); var i: integer; begin for i:=0 to zieleFkt.count-1 do zieleHinzufuegen(ziele,zieleFkt[i],quelle,inputfile,dats); end; procedure findeWasZuTunIst(var mgl: tAbhaengigkeiten; out zuTun: tAbhaengigkeiten; var dats: tDateienMitDaten; inputfile: string); var i,j,k,l: integer; neues,schonDa: boolean; s: string; tmpZiele: tDateienMitDaten; ziA,quA: tAktualitaet; begin setlength(zuTun,0); repeat neues:=false; i:=0; while i0) then begin // quellen stehen schon fest, noch nicht auszuführen for j:=0 to length(mgl[i].quellen)-1 do findeMehrZiele(mgl[i].ziele,mgl[i].zieleFkt,mgl[i].quellen[j].name,inputfile,dats); if length(mgl[i].ziele)=0 then begin // immer noch keine ziele writeln('Warnung: Keine ziele für diese Abhängigkeit!'); writeln('quellen:'); for k:=0 to length(mgl[i].quellen)-1 do writeln(' '''+mgl[i].quellen[k].name+''''); writeln('zieleFkt:'); for k:=0 to mgl[i].zieleFkt.count-1 do writeln(' '''+mgl[i].zieleFkt[k]+''''); writeln(' - wird fortan ignoriert.'); mgl[i].abhArt:=aaIgnore; continue; end; quA:=aAktuell; for j:=0 to length(mgl[i].quellen)-1 do if mgl[i].quellen[j].aktuell<>aAktuell then quA:=aWirdErneuert; ziA:=aWirdErneuert; for j:=0 to length(mgl[i].ziele)-1 do ziA:=min(ziA,mgl[i].ziele[j].aktuell); if ziA ',mgl[i].befehle.text); setlength(zuTun,length(zuTun)+1); zuTun[length(zuTun)-1]:=tAbhaengigkeit.create(mgl[i]); setlength(mgl[i].erben,1); mgl[i].erben[0]:=zuTun[length(zuTun)-1]; for j:=0 to length(mgl[i].ziele)-1 do mgl[i].ziele[j].aktuell:=aWirdErneuert; neues:=true; end; end; aaIgnore: ; // keine ziele end{of case}; inc(i); end; until not neues; end; procedure tueWasZuTunIst(alles,zuTun: tAbhaengigkeiten; var dats: tDateienMitDaten; nurAnzeigen, allesNeu, unsicher: boolean; ausgabedatei,summendatei: string); var prior,i,j: integer; ausg: textfile; befehle,geaenderteDateien, alteDateien,sumDateien: tStringlist; ms,gefunden: boolean; lokTest: tRegExpr; begin befehle:=tStringlist.create; prior:=0; ms:=summendatei<>''; for i:=0 to length(zuTun)-1 do prior:=max(prior,zuTun[i].prioritaet); if ms then begin geaenderteDateien:=tStringlist.create; sumDateien:=dateienMitGueltigerSumme(summendatei); for i:=0 to length(dats)-1 do begin gefunden:=(dats[i].name=summendatei) or (dats[i].name=ausgabedatei); for j:=0 to sumDateien.count-1 do if sumDateien[j]=dats[i].name then begin gefunden:=true; sumDateien.delete(j); break; end; if not gefunden then geaenderteDateien.add(dats[i].name); end; sumDateien.free; if allesNeu then for i:=0 to length(alles)-1 do begin for j:=0 to length(alles[i].ziele)-1 do geaenderteDateien.add(alles[i].ziele[j].name); for j:=0 to length(alles[i].quellen)-1 do geaenderteDateien.add(alles[i].quellen[j].name); end; for i:=0 to length(zuTun)-1 do begin for j:=0 to length(zuTun[i].ziele)-1 do geaenderteDateien.add(zuTun[i].ziele[j].name); for j:=0 to length(zuTun[i].quellen)-1 do geaenderteDateien.add(zuTun[i].quellen[j].name); end; end; while prior>=0 do begin for i:=0 to length(zuTun)-1 do if zuTun[i].prioritaet=prior then for j:=0 to zuTun[i].befehle.count-1 do befehle.add(zuTun[i].befehle[j]); dec(prior); end; if not unsicher then begin lokTest:=tRegExpr.create; if extractfilepath(ausgabedatei)=extractfilepath(summendatei) then lokTest.expression:='^'+extractfilepath(ausgabedatei)+'/' else lokTest.expression:='^('+extractfilepath(ausgabedatei)+'|'+extractfilepath(summendatei)+')/'; for i:=0 to befehle.count-1 do testeObBefehlLokal(befehle[i],extractfiledir(ausgabedatei),lokTest); lokTest.free; end; if ms then begin for i:=geaenderteDateien.count-1 downto 0 do begin if geaenderteDateien[i]='.uralt.' then begin geaenderteDateien.delete(i); continue; end; for j:=0 to i-1 do if geaenderteDateien[i]=geaenderteDateien[j] then begin geaenderteDateien.delete(i); break; end; end; if geaenderteDateien.count>0 then befehle.add('echo -ne "Sha512summen erneuern ..."'); for i:=0 to geaenderteDateien.count-1 do befehle.add('/usr/bin/sha512sum "'+geaenderteDateien[i]+'" >> '+summendatei); if geaenderteDateien.count>0 then befehle.add('echo " fertig"'); if not nurAnzeigen then begin alteDateien:=tStringlist.create; alteDateien.loadFromFile(summendatei); for i:=alteDateien.count-1 downto 0 do for j:=0 to geaenderteDateien.count-1 do if trim(copy(alteDateien[i],pos(' ',alteDateien[i]),length(alteDateien[i])))=geaenderteDateien[j] then begin alteDateien.delete(i); break; end; alteDateien.saveToFile(summendatei); alteDateien.free; end; end; if length(zuTun)=0 then befehle.add('echo "Es gibt hier nichts zu tun!"'); if nurAnzeigen then begin writeln('befehle:'); for i:=0 to befehle.count-1 do writeln(befehle[i]); end else begin assignFile(ausg,ausgabedatei); rewrite(ausg); for i:=0 to befehle.count-1 do writeln(ausg,'('+befehle[i]+') || (read -p "Ein Fehler ist aufgetreten! ... "; exit 1)'); closeFile(ausg); end; befehle.free; if ms then geaenderteDateien.free; end; { tMake } procedure tMake.doRun; var inputfile,pruefsummenfile,errorMsg: string; mglAbhaengigkeiten,zutunAbhaengigkeiten: tAbhaengigkeiten; dateien: tDateienMitDaten; i: longint; begin errorMsg:=checkOptions('A:HWD:P:au','Ausgabe: Hilfe Watte Datei: Prüfsummen: alleSummenErneuern unsicher'); if errorMsg<>'' then begin showException(exception.create(errorMsg+#10'Hilfe: '+exename+' -H/--Hilfe')); terminate; exit; end; if hasOption('H','Hilfe') then begin writeHelp; terminate; exit; end; if (getOptionValue('A','Ausgabe')='') and not hasOption('W','Watte') then begin showException(exception.create('Ausgabedatei wird benötigt!')); terminate; exit; end; if hasOption('D','Datei') then inputfile:=getOptionValue('D','Datei') else inputfile:='Machdatei'; if hasOption('P','Prüfsummen') then pruefsummenfile:=getOptionValue('P','Prüfsummen') else begin showException(exception.create('Prüfsummendatei wird benötigt!')); terminate; exit; end; if fileexists(inputfile) then begin if not liesMakeFile(inputfile,mglAbhaengigkeiten,dateien) then begin showException(exception.create('Datei '''+inputfile+''' ist fehlerhaft!')); terminate; exit; end; end else begin showException(exception.create('Datei '''+inputfile+''' existiert nicht!')); terminate; exit; end; if not liesPruefsummenfile(pruefsummenfile,dateien) then begin showException(exception.create('Datei '''+pruefsummenfile+''' ist fehlerhaft!')); terminate; exit; end; for i:=0 to length(dateien)-1 do writeln(dateien[i].aktuell,' ',dateien[i].name); writeln('Regeln: '+inttostr(length(mglAbhaengigkeiten))+', Dateien: '+inttostr(length(dateien))); findeWasZuTunIst(mglAbhaengigkeiten,zuTunAbhaengigkeiten,dateien,inputfile); writeln('anzuwendende Regeln: '+inttostr(length(zuTunAbhaengigkeiten))); tueWasZuTunIst(mglAbhaengigkeiten,zuTunAbhaengigkeiten,dateien,hasOption('W','Watte'),hasOption('a','alleSummenErneuern'),hasOption('u','unsicher'),getOptionValue('A','Ausgabe'),pruefsummenfile); terminate; end; constructor tMake.create(theOwner: tComponent); begin inherited create(theOwner); stopOnException:=True; end; procedure tMake.writeHelp; begin writeln('Verwendung:'); writeln(' ',exeName,' -A/--Ausgabe $ausgabedatei -H/--Hilfe -W/--Watte -D/--Datei $Machdatei -P/--Prüfsummen $Prüfsummendatei -a/--alleSummenErneuern -u/--unsicher'); end; var application: tMake; begin application:=tMake.create(nil); application.run; application.free; end.