DABringImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Created by Bertrand Serlet, October 21, 1986 10:11:12 pm PDT
Bertrand Serlet December 21, 1986 4:53:27 pm PST
Christian Jacobi, December 21, 1986 4:53:27 pm PST
DIRECTORY
BasicTime, Commander, CommandTool, DFClosure, DFUtilities, FileNames, FS, IO, MessageWindow, ProcessProps, Rope, SymTab, SystemNames;
DABringImpl: CEDAR PROGRAM
IMPORTS Commander, CommandTool, DFClosure, DFUtilities, FileNames, FS, IO, MessageWindow, ProcessProps, Rope, SymTab, SystemNames =
BEGIN
ROPE: TYPE ~ Rope.ROPE;
ROPES: TYPE ~ LIST OF ROPE;
STREAM: TYPE = IO.STREAM;
Switches: TYPE = PACKED ARRAY CHAR['a..'z] OF BOOL;
CmdData: TYPE = REF CmdDataRec; -- for user feedback
CmdDataRec: TYPE = RECORD [
out: STREAM,
considered: INT ← 0,
attached: INT ← 0,
switches: Switches ← ALL [FALSE],
failed: BOOLFALSE
];
File: DFClosure.FileProc = {
cmdData: CmdData = NARROW [data];
zap: BOOL = cmdData.switches['z] OR (cmdData.switches['y] AND DFUtilities.ClassifyFileExtension[name]=derived);
localName: ROPE = DFUtilities.RemoveVersionNumber[name];
serverName: ROPE = Rope.Cat[from, name];
BEGIN
attachedTo: ROPE;
created: BasicTime.GMT;
cmdData.considered ← cmdData.considered + 1;
[attachedTo: attachedTo, created: created] ← FS.FileInfo[name: localName, remoteCheck: FALSE ! FS.Error => GOTO Copy]; -- if the file is inexistent, we copy it!
IF attachedTo=NIL AND NOT zap THEN {cmdData.out.PutF["%g not copied: local version exists.\n", IO.rope[serverName]]; RETURN};
IF created=date.gmt THEN RETURN; -- already there
IF LOOPHOLE [created, INT]>LOOPHOLE [date.gmt, INT] AND NOT zap THEN {cmdData.out.PutF["%g not copied: local version is more recent.\n", IO.rope[serverName]]; RETURN};
GOTO Copy;
EXITS
Copy => {
IF cmdData.switches['v] AND NOT cmdData.switches['w] THEN cmdData.out.PutF["Attaching %g.\n", IO.rope[serverName]];
IF cmdData.switches['w]
THEN cmdData.out.PutF["%g would have been attached.\n", IO.rope[serverName]]
ELSE {
[] ← FS.Copy[
to: localName, from: serverName, wantedCreatedTime: date.gmt, attach: TRUE
! FS.Error => cmdData.out.PutF["%g can not be copied: %g.\n", IO.rope[serverName], IO.rope[error.explanation]];
];
cmdData.attached ← cmdData.attached + 1;
};
};
END;
};
daTop: ROPE = IO.PutFR["/DATools/DATools%g/Top/*.df", IO.rope[SystemNames.ReleaseName[]]];
cedarTop: ROPE = IO.PutFR["/Cedar/Cedar%g/Top/*.df", IO.rope[SystemNames.ReleaseName[]]];
Import: DFClosure.ImportProc = {
cmdData: CmdData = NARROW [data];
dfName ← FileNames.ConvertToSlashFormat[dfName];
RETURN [SELECT TRUE FROM
Rope.Match[daTop, dfName, FALSE]           => all,
NOT cmdData.switches['c] AND Rope.Match[cedarTop, dfName, FALSE] => none, -- those are already running
ENDCASE                   => public];
};
Error: DFClosure.ErrorProc = {
cmdData: CmdData = NARROW [data];
cmdData.out.PutF[message];
cmdData.out.PutF["\n"];
cmdData.failed ← kind=aborted;
};
Message: DFClosure.MessageProc = {MessageWindow.Append[message, TRUE]};
DABring: Commander.CommandProc = {
dfFileName, daBringFileName: Rope.ROPE;
what: Rope.ROPE = NARROW[cmd.procData.clientData];
out: STREAM = NARROW [ProcessProps.GetProp[$CommanderHandle], Commander.Handle].out;
cmdData: CmdData = NEW [CmdDataRec ← [out: out]];
argv: CommandTool.ArgumentVector ← CommandTool.Parse[cmd: cmd, starExpand: FALSE
! CommandTool.Failed => {msg ← errorMsg; GO TO failed}];
FOR i: NAT IN [1..argv.argc) DO
sense: BOOLTRUE;
arg: ROPE = argv[i];
IF Rope.Length[arg] = 0 THEN LOOP;
IF Rope.Fetch[arg, 0] # '- THEN {msg ← "Incorrect Syntax"; GO TO failed};
FOR index: INT IN [0..Rope.Length[arg]) DO
char: CHAR ← Rope.Fetch[arg, index];
SELECT char FROM
'- => LOOP;
'~ => {sense ← NOT sense; LOOP};
IN ['a..'z] => cmdData.switches[char] ← sense;
IN ['A..'Z] => cmdData.switches[char + ('a-'A)] ← sense;
ENDCASE => {msg ← "Incorrect Syntax"; GO TO failed};
sense ← TRUE;
ENDLOOP;
ENDLOOP;
daBringFileName ← IO.PutFR["/DATools/DATools%g/Top/DABring-%g.DABring",
IO.rope[SystemNames.ReleaseName[]],
IO.rope[what]
];
dfFileName ← MakeFile[daBringFileName, out];
IF dfFileName=NIL THEN GOTO failed;
[] ← DFClosure.EnumerateClosure[dfFileName, TRUE, File, Import, Error, Message, cmdData ! UNWIND => FS.Delete[dfFileName]];
FS.Delete[dfFileName];
IF cmdData.failed
THEN result ← $Failure
ELSE {
MessageWindow.Append["BringDATools done!", TRUE];
out.PutF["DABring %g: %g files considered, %g files attached.\n", [rope[what]], IO.int[cmdData.considered], IO.int[cmdData.attached]];
};
EXITS
failed => {result ← $Failure};
};
MakeFile: PROC [inputName: Rope.ROPE, msg: IO.STREAM] RETURNS [outputName: Rope.ROPENIL] = {
ToFileName: PROC [line: Rope.ROPE, msg: IO.STREAM] RETURNS [fn: Rope.ROPE] = {
ambiguous: BOOL;
[fn, ambiguous] ← FileNames.FileWithSearchRules[root: line, requireExtension: FALSE, requireExact: TRUE, searchRules: NIL, defaultExtension: ".df"];
IF fn=NIL THEN IO.PutF[msg, "did not find %g", [rope[line]]];
};
in: IO.STREAM;
handled: SymTab.Ref ← SymTab.Create[case: FALSE];
use: SymTab.Ref ← SymTab.Create[case: FALSE];
doFiles: LIST OF Rope.ROPE;
doFiles ← LIST[ToFileName[inputName, msg]];
--analyse input
IF doFiles.first=NIL THEN GOTO oops;
WHILE doFiles#NIL DO
fileName: Rope.ROPE ← doFiles.first; doFiles ← doFiles.rest;
IF ~SymTab.Insert[handled, fileName, $handled] THEN LOOP;
in ← FS.StreamOpen[fileName ! FS.Error => {IO.PutRope[msg, error.explanation]; GOTO oops}];
BEGIN
DO
line: Rope.ROPE; pos, leng: INT;
line ← IO.GetLineRope[in ! IO.EndOfStream => GOTO eos];
leng ← Rope.Length[line];
pos ← Rope.SkipOver[line, 0, " "];
IF (pos+2)>=leng THEN LOOP;
line ← Rope.Substr[line, pos]; leng ← leng-pos;
SELECT TRUE FROM
Rope.Match["P *", line, FALSE] => {
[] ← SymTab.Insert[use, ToFileName[Rope.Substr[line, 2], msg], $export];
};
Rope.Match["A *", line, FALSE] => {
[] ← SymTab.Store[use, ToFileName[Rope.Substr[line, 2], msg], $include];
};
Rope.Match["R *", line, FALSE] => {
n: Rope.ROPE ← ToFileName[Rope.Substr[line, 2], msg];
IF n=NIL THEN GOTO oops;
doFiles ← CONS[n, doFiles];
};
Rope.Match["--*", line, FALSE] => LOOP;
ENDCASE => {IO.PutRope[msg, "syntax error"]; GOTO oops};
ENDLOOP
EXITS eos => NULL;
END;
ENDLOOP;
IO.Close[in];
--create output
BEGIN
out: IO.STREAMFS.StreamOpen["///Temp/BringDATools.temp", $create];
Each: SymTab.EachPairAction = {
IO.PutF[out, "%g %g Of ~=\n",
[rope[(IF val=$include THEN "Include" ELSE "Exports Imports")]],
[rope[key]]
];
};
[] ← SymTab.Pairs[use, Each];
outputName ← FS.GetName[FS.OpenFileFromStream[out]].fullFName;
IO.Close[out];
END;
EXITS oops => NULL;
};
LoadDABring: Commander.CommandProc = {
argv: CommandTool.ArgumentVector;
argv ← CommandTool.Parse[cmd: cmd, starExpand: FALSE
! CommandTool.Failed => {msg ← errorMsg; GO TO failed}];
IF argv.argc#2 THEN {msg ← "needs 1 argument"; GO TO failed};
Register[argv[1]];
EXITS failed => {result ← $Failure};
};
doc: ROPE = "Brings in the current directory enough to be able to run all released DATools
-c: also bring public part of Cedar imports
-v: verbose (list files to be attached)
-w: warning only (no files attached)
-y: zap derived files regardless of date and local version
-z: zap files regardless of date and local version
";
Register: PROC [what: Rope.ROPE] = {
Commander.Register[
key: Rope.Cat["///", SystemNames.ReleaseName[], "/Commands/DABring", what],
proc: DABring, doc: doc, clientData: what
];
};
Commander.Register[
key: Rope.Cat["///", SystemNames.ReleaseName[], "/Commands/LoadDABring"],
proc: LoadDABring, doc: "Loads DABring command with particular file"
];
END.