<> <> <> <> <<>> 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: BOOL _ FALSE ]; 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 = 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: BOOL _ TRUE; 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]"]; -- 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 "; <> Commander.Register["BringDATools", BringDATools, doc]; END.