BringDAToolsImpl.mesa
Copyright Ó 1986, 1987, 1988 by Xerox Corporation. All rights reserved.
Created by Bertrand Serlet, October 21, 1986 10:11:12 pm PDT
Bertrand Serlet November 28, 1988 11:01:43 pm PST
DIRECTORY
BasicTime, Commander, CommandTool, DFClosure, DFUtilities, FS, IO, MessageWindow, ProcessProps, Rope, SystemNames;
BringDAToolsImpl: CEDAR PROGRAM
IMPORTS Commander, CommandTool, DFClosure, DFUtilities, FS, IO, MessageWindow, ProcessProps, Rope, 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
];
Match: PROC [pattern, file: ROPE] RETURNS [BOOL] = {
IF Rope.Fetch[file]#'[ THEN file ← FS.ExpandName[file].fullFName;
IF Rope.Fetch[pattern]#'[ THEN pattern ← FS.ExpandName[pattern].fullFName;
RETURN [Rope.Match[pattern, file, FALSE]];
};
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];
wDir: ROPE = IF Match[cedarFiles, serverName] OR Match[chestFiles, serverName] THEN commandsDir ELSE NIL;
wDir: ROPE = NIL; -- PATCHED FOR NOW (UNTIL Install pb solved) [BS]
BEGIN
attachedTo: ROPE;
created: BasicTime.GMT;
cmdData.considered ← cmdData.considered + 1;
[attachedTo: attachedTo, created: created] ← FS.FileInfo[name: localName, remoteCheck: FALSE, wDir: wDir ! 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 AND Rope.Equal[DFUtilities.RemoveVersionNumber[attachedTo], DFUtilities.RemoveVersionNumber[serverName], FALSE] 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, wDir: wDir
! 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;
};
Import: DFClosure.ImportProc = {
RETURN [IF Match[daToolsDFs, dfName] THEN all ELSE IF exported THEN public ELSE none];
};
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]};
BringDATools: Commander.CommandProc = {
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}];
rootDF: ROPE ← "DATools.df";
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
IF cmdData.switches['r] THEN LOOP ELSE {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};
'r, 'R => IF i=argv.argc-1
THEN {msg ← "Root DF file expected"; GO TO failed}
ELSE {cmdData.switches['r] ← TRUE; rootDF ← argv[i+1]};
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;
IF Rope.Fetch[rootDF]#'/ AND Rope.Fetch[rootDF]#'[
THEN rootDF ← Rope.Cat[daToolsDir, rootDF];
[] ← DFClosure.EnumerateClosure[rootDF, TRUE, File, Import, Error, Message, cmdData];
IF cmdData.failed
THEN result ← $Failure
ELSE {
MessageWindow.Append["BringDATools done!", TRUE];
out.PutF["BringDATools%g: %g files considered, %g files attached.\n", IO.rope[IF cmdData.switches['d] THEN Rope.Cat[" of ", rootDF] ELSE NIL], IO.int[cmdData.considered], IO.int[cmdData.attached]];
};
EXITS
failed => {result ← $Failure};
};
commandsDir: ROPE = SystemNames.LocalDir["Commands"];
daToolsDir: ROPE = Rope.Cat["[DATools7.0]<Top>"]; -- hack waiting for a decent SystemNames
daToolsDFs: ROPE = Rope.Cat[daToolsDir, "*.df*"];
cedarFiles: ROPE = Rope.Cat["[Cedar7.0]<", "*"]; -- hack waiting
chestFiles: ROPE = Rope.Cat["[CedarChest7.0]<", "*"]; -- hack waiting
doc: ROPE = "Brings in the current directory enough to be able to run all released DATools
-r: next argument specifies a root df file (instead of DATools.df)
-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
";
We register the command in the right Commands directory so that it can be used from several directories (for the release software for example)
Commander.Register["BringDATools", BringDATools, doc];
END.