ReleaseToolsImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Doug Wyatt, June 13, 1986 0:44:04 am PDT
DIRECTORY
Basics,
Commander,
CommandTool,
DFUtilities,
FS,
IO,
PriorityQueue,
Rope;
ReleaseToolsImpl: CEDAR PROGRAM
IMPORTS Commander, CommandTool, DFUtilities, FS, IO, PriorityQueue, Rope
~ BEGIN
ROPE: TYPE ~ Rope.ROPE;
NameProc: TYPE ~ PROC [ROPE];
EnumerateDFItems: PROC [dfName: ROPE, action: NameProc,
includes, imports: BOOLTRUE] ~ {
stream: IO.STREAM ~ FS.StreamOpen[dfName];
processItemProc: DFUtilities.ProcessItemProc ~ {
WITH item SELECT FROM
item: REF DFUtilities.IncludeItem => IF includes THEN action[item.path1];
item: REF DFUtilities.ImportsItem => IF imports THEN action[item.path1];
ENDCASE;
};
DFUtilities.ParseFromStream[in: stream, proc: processItemProc];
IO.Close[stream];
};
EnumerateRemoteNames: PROC [pattern: ROPE, action: NameProc] ~ {
nameProc: FS.NameProc ~ {
cp: FS.ComponentPositions;
name: ROPENIL;
[fullFName: name, cp: cp] ← FS.ExpandName[name: fullFName];
name ← Rope.Substr[base: name, start: 0, len: cp.ext.start+cp.ext.length]; -- strip version
action[name];
RETURN[continue: TRUE];
};
FS.EnumerateForNames[pattern: pattern, proc: nameProc];
};
NameCompare: PROC [name1, name2: ROPE] RETURNS [Basics.Comparison] ~ {
RETURN[SELECT TRUE FROM
name1=NIL AND name2=NIL => equal,
name1=NIL => less,
name2=NIL => greater,
ENDCASE => Rope.Compare[s1: name1, s2: name2, case: FALSE]
];
};
AlphaSortPredicate: PriorityQueue.SortPred ~ {
name1: ROPE ~ NARROW[x];
name2: ROPE ~ NARROW[y];
RETURN[NameCompare[name1, name2]=less];
};
DFName: PROC [root: ROPE] RETURNS [ROPE] ~ {
cp: FS.ComponentPositions; name: ROPENIL;
[fullFName: name, cp: cp] ← FS.ExpandName[name: root];
IF (cp.base.start+cp.base.length)=cp.ext.start THEN name ← Rope.Concat[name, ".df"];
RETURN[name];
};
ShortName: PROC [name: ROPE] RETURNS [ROPE] ~ {
fullFName: ROPENIL; cp: FS.ComponentPositions; start, stop: INT;
[fullFName: fullFName, cp: cp] ← FS.ExpandName[name: name];
start ← cp.base.start; stop ← cp.ext.start+cp.ext.length;
RETURN[Rope.Substr[base: fullFName, start: start, len: stop-start]];
};
Directory: PROC [name: ROPE] RETURNS [ROPE] ~ {
cp: FS.ComponentPositions; fullFName: ROPENIL;
[fullFName: fullFName, cp: cp] ← FS.ExpandName[name: name];
RETURN[Rope.Substr[base: fullFName, start: 0, len: cp.base.start]];
};
CheckRootCommand: Commander.CommandProc ~ {
argv: CommandTool.ArgumentVector ← CommandTool.Parse[cmd: cmd];
FOR i: NAT IN [1..argv.argc) DO
CheckRoot[argv[i], cmd.out];
ENDLOOP;
};
CheckRoot: PROC [root: ROPE, out: IO.STREAM] ~ {
dfName: ROPE ~ DFName[root];
remoteDirectory, remotePattern: ROPENIL;
pq1: PriorityQueue.Ref ~ PriorityQueue.Predict[size: 200, pred: AlphaSortPredicate];
pq2: PriorityQueue.Ref ~ PriorityQueue.Predict[size: 200, pred: AlphaSortPredicate];
EachItemName: PROC [name: ROPE] ~ {
out.PutChar['.];
PriorityQueue.Insert[pq1, name];
IF remoteDirectory=NIL THEN remoteDirectory ← Directory[name];
};
EachRemoteName: PROC [name: ROPE] ~ {
out.PutChar['.];
PriorityQueue.Insert[pq2, name];
};
TopName: PROC [pq: PriorityQueue.Ref] RETURNS [ROPE] ~ {
IF PriorityQueue.Empty[pq] THEN RETURN[NIL]
ELSE RETURN[NARROW[PriorityQueue.Top[pq]]];
};
out.PutF["Checking %g ", IO.rope[dfName]];
EnumerateDFItems[dfName, EachItemName];
out.PutF[" %g files.\n", IO.int[PriorityQueue.Size[pq1]]];
remotePattern ← Rope.Concat[remoteDirectory, "*.df!H"];
out.PutF["Checking %g ", IO.rope[remotePattern]];
EnumerateRemoteNames[remotePattern, EachRemoteName];
out.PutF[" %g files.\n", IO.int[PriorityQueue.Size[pq2]]];
UNTIL PriorityQueue.Empty[pq1] AND PriorityQueue.Empty[pq2] DO
name1: ROPE ~ TopName[pq1];
name2: ROPE ~ TopName[pq2];
SELECT NameCompare[name1, name2] FROM
less => {
out.PutF["Deleted: %g\n", IO.rope[name1]];
[] ← PriorityQueue.Remove[pq1];
};
greater => {
out.PutF["New: %g\n", IO.rope[name2]];
[] ← PriorityQueue.Remove[pq2];
};
ENDCASE => {
[] ← PriorityQueue.Remove[pq1];
[] ← PriorityQueue.Remove[pq2];
};
ENDLOOP;
out.PutRope["\n"];
};
RootCompareCommand: Commander.CommandProc ~ {
argv: CommandTool.ArgumentVector ← CommandTool.Parse[cmd: cmd];
RootCompare[argv[1], argv[2], cmd.out];
};
RootCompare: PROC [root1, root2: ROPE, out: IO.STREAM] ~ {
df1: ROPE ~ DFName[root1];
df2: ROPE ~ DFName[root2];
pq1: PriorityQueue.Ref ~ PriorityQueue.Predict[size: 200, pred: AlphaSortPredicate];
pq2: PriorityQueue.Ref ~ PriorityQueue.Predict[size: 200, pred: AlphaSortPredicate];
EnumerateDF: PROC [df: ROPE, pq: PriorityQueue.Ref] ~ {
EachName: PROC [name: ROPE] ~ {
out.PutChar['.];
PriorityQueue.Insert[pq, ShortName[name]];
};
EnumerateDFItems[df, EachName];
};
TopName: PROC [pq: PriorityQueue.Ref] RETURNS [ROPE] ~ {
IF PriorityQueue.Empty[pq] THEN RETURN[NIL]
ELSE RETURN[NARROW[PriorityQueue.Top[pq]]];
};
out.PutF["Checking %g ", IO.rope[df1]];
EnumerateDF[df1, pq1];
out.PutF[" %g files.\n", IO.int[PriorityQueue.Size[pq1]]];
out.PutF["Checking %g ", IO.rope[df2]];
EnumerateDF[df2, pq2];
out.PutF[" %g files.\n", IO.int[PriorityQueue.Size[pq2]]];
UNTIL PriorityQueue.Empty[pq1] AND PriorityQueue.Empty[pq2] DO
name1: ROPE ~ TopName[pq1];
name2: ROPE ~ TopName[pq2];
SELECT NameCompare[name1, name2] FROM
less => {
out.PutF["Deleted: %g\n", IO.rope[name1]];
[] ← PriorityQueue.Remove[pq1];
};
greater => {
out.PutF["New: %g\n", IO.rope[name2]];
[] ← PriorityQueue.Remove[pq2];
};
ENDCASE => {
[] ← PriorityQueue.Remove[pq1];
[] ← PriorityQueue.Remove[pq2];
};
ENDLOOP;
out.PutRope["\n"];
};
Commander.Register[key: "CheckRoot", proc: CheckRootCommand];
Commander.Register[key: "RootCompare", proc: RootCompareCommand];
END.