VersionMap2CommandsImpl.mesa
Copyright Ó 1990 by Xerox Corporation. All rights reserved.
Last tweaked by Mike Spreitzer on April 10, 1992 9:40 am PDT
DIRECTORY Commander, CommanderOps, IO, MorePfsEnumeration, PFS, PFSNames, RefTab, Rope, RopeHash, VersionMap2, VersionMap2Binding, VersionMap2BindingByPattern, VersionMap2FromPattern, VersionMap2Pretty;
VersionMap2CommandsImpl: CEDAR PROGRAM
IMPORTS Commander, CommanderOps, IO, MorePfsEnumeration, PFS, PFSNames, RefTab, Rope, RopeHash, VersionMap2, VersionMap2Binding, VersionMap2BindingByPattern, VersionMap2FromPattern, VersionMap2Pretty
=
BEGIN OPEN VM2:VersionMap2, VM2BP:VersionMap2BindingByPattern, VM2Pretty:VersionMap2Pretty;
ROPE: TYPE ~ Rope.ROPE;
VLS: PROC [cmd: Commander.Handle] RETURNS [result: REF ANYNIL, msg: ROPENIL] --Commander.CommandProc-- ~ {
argv: CommanderOps.ArgumentVector ← CommanderOps.Parse[cmd];
map: VM2.Map;
pattern: VM2.VersionTuple ← [];
IF argv.argc < 3 OR argv.argc > 5 THEN RETURN [$Failure, "Usage: VM2LS <fileName or $mapName> <full name pattern> [<created> [<version stamp>]]"];
{ENABLE PFS.Error => {
msg ← IO.PutFR["Error[%g, %g]", [atom[error.code]], [rope[error.explanation]] ];
GOTO Fail};
PrintMatch: PROC [vt: VM2.VersionTuple] RETURNS [BOOL] ~ {
cmd.out.PutRope[VM2Pretty.FormatTuple[vt]];
cmd.out.PutRope["\n"];
RETURN [FALSE]};
IF argv[1].Length[] > 0 AND argv[1].Fetch[0] = '$
THEN map ← VersionMap2Binding.GetMap[argv[1].Substr[1]]
ELSE map ← VM2.MapFromFile[PFS.PathFromRope[argv[1]], VM2.nullCreated, TRUE];
pattern.name ← VM2Pretty.ParseName[argv[2]];
IF argv.argc > 3 THEN pattern.created ← VM2Pretty.ParseCreated[argv[3]];
IF argv.argc > 4 THEN pattern.stamp ← VM2Pretty.ParseStamp[argv[4]];
IF map.ScanMatches[PrintMatch, TRUE, pattern].found THEN ERROR;
RETURN};
EXITS Fail => result ← $Failure};
ListList: PROC [cmd: Commander.Handle] RETURNS [result: REF ANYNIL, msg: ROPENIL] --Commander.CommandProc-- ~ {
argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd];
PerRoot: PROC [root: ROPE] RETURNS [stop: BOOL] ~ {
PerItem: PROC [pattern: VM2.Name] RETURNS [stop: BOOL] ~ {
cmd.out.PutF1[" %g", [rope[PFS.RopeFromPath[pattern]]] ];
RETURN[FALSE]};
cmd.out.PutF1["%g =>", [rope[root]] ];
VM2BP.ScanList[root, PerItem];
cmd.out.PutRope["\n"];
RETURN [FALSE]};
IF argv.argc<2
THEN VM2BP.ScanLists[PerRoot]
ELSE FOR i: NAT IN (0..argv.argc) DO [] ← PerRoot[argv[i]] ENDLOOP;
RETURN};
ListAdd: PROC [cmd: Commander.Handle] RETURNS [result: REF ANYNIL, msg: ROPENIL] --Commander.CommandProc-- ~ {
argv: CommanderOps.ArgumentVector ~ CommanderOps.Parse[cmd];
IF argv.argc<2 THEN RETURN [$Failure, "Usage: WatchPatternVersions <root> <pat>..."];
FOR i: NAT IN (1..argv.argc) DO
pat: VM2.Name ~ PFS.PathFromRope[argv[i]];
abs: VM2.Name ~ PFS.AbsoluteName[pat];
VM2BP.AddToList[argv[1], abs];
ENDLOOP;
RETURN};
Key: TYPE ~ REF KeyPrivate;
KeyPrivate: TYPE ~ RECORD [shortName: ROPE, created: VM2.Created];
ListCollisions: PROC [cmd: Commander.Handle] RETURNS [result: REF ANYNIL, msg: ROPENIL] --Commander.CommandProc-- ~ {
argv: CommanderOps.ArgumentVector ← CommanderOps.Parse[cmd];
map: VM2.Map;
detect: RefTab.Ref ~ RefTab.Create[hash: Hash, equal: Equal];
doit: RefTab.Ref ~ RefTab.Create[hash: Hash, equal: Equal];
IF argv.argc # 2 THEN RETURN [$Failure, "Usage: VM2LS <fileName or $mapName>"];
{ENABLE PFS.Error => {
msg ← IO.PutFR["Error[%g, %g]", [atom[error.code]], [rope[error.explanation]] ];
GOTO Fail};
NoteTuple: PROC [vt: VM2.VersionTuple] RETURNS [BOOL] ~ {
lc: PFSNames.Component ~ vt.name.ShortName[];
key: Key ~ NEW [KeyPrivate ← [lc.ComponentRope[], vt.created]];
IF NOT detect.Insert[key, $T] THEN [] ← doit.Store[key, $T];
RETURN [FALSE]};
Report: PROC [key, val: REF ANY] RETURNS [quit: BOOLFALSE] ~ {
k: Key ~ NARROW[key];
PrintCollider: PROC [vt: VM2.VersionTuple] RETURNS [BOOL] ~ {
vlc: PFSNames.Component ~ vt.name.ShortName[];
mod: VM2.Name ~ vt.name.ReplaceShortName[[name: [NIL, 0, 0], version: vlc.version]];
cmd.out.PutF["\t%g ver %g\n", [rope[VM2Pretty.FormatName[mod]]], [rope[VM2Pretty.FormatStamp[vt.stamp]]] ];
RETURN [FALSE]};
cmd.out.PutF["%g of %g:", [rope[k.shortName]], [rope[VM2Pretty.FormatCreated[k.created]]] ];
IF map.ScanMatches[PrintCollider, FALSE, [VM2.ShortNameToPattern[k.shortName].name, k.created]].found THEN ERROR;
cmd.out.PutRope["\n"];
RETURN};
IF argv[1].Length[] > 0 AND argv[1].Fetch[0] = '$
THEN map ← VersionMap2Binding.GetMap[argv[1].Substr[1]]
ELSE map ← VM2.MapFromFile[PFS.PathFromRope[argv[1]], VM2.nullCreated, TRUE];
IF map.Scan[NoteTuple, FALSE].found THEN ERROR;
cmd.out.PutF1["%g collisions.\n", [integer[doit.GetSize]] ];
IF doit.Pairs[Report] THEN ERROR;
RETURN};
EXITS Fail => result ← $Failure};
TestPSM: PROC [cmd: Commander.Handle] RETURNS [result: REF ANYNIL, msg: ROPENIL] --Commander.CommandProc-- ~ {
argv: CommanderOps.ArgumentVector ← CommanderOps.Parse[cmd];
pat1, pat2, better, worse: VM2.Name;
mismatch: BOOL;
IF argv.argc#3 THEN RETURN [$Failure, "Usage: test-psm pat1 pat2"];
pat1 ← VM2Pretty.ParseName[argv[1]];
pat2 ← VM2Pretty.ParseName[argv[2]];
[mismatch, better, worse] ← VersionMap2FromPattern.NamePatternSortMerge[pat1, pat2];
cmd.out.PutF["%g, %g => ", [rope[VM2Pretty.FormatName[pat1]]], [rope[VM2Pretty.FormatName[pat2]]] ];
IF mismatch THEN cmd.out.PutRope["mismatch.\n"]
ELSE cmd.out.PutF["%g, %g\n", [rope[VM2Pretty.FormatName[better]]], [rope[VM2Pretty.FormatName[worse]]] ];
RETURN};
LS: PROC [cmd: Commander.Handle] RETURNS [result: REF ANYNIL, msg: ROPENIL] --Commander.CommandProc-- ~ {
argv: CommanderOps.ArgumentVector ← CommanderOps.Parse[cmd];
PerInfo: PROC [fullFName, attachedTo: PFS.PATH, uniqueID: PFS.UniqueID, bytes: INT, mutability: PFS.Mutability, fileType: PFS.FileType] RETURNS [continue: BOOLTRUE] ~ {
cmd.out.PutF["%g %8g %g", [time[uniqueID.egmt.gmt]], [integer[bytes]], [rope[PFS.RopeFromPath[fullFName]]] ];
IF attachedTo#NIL THEN cmd.out.PutF1[" -> %g", [rope[PFS.RopeFromPath[attachedTo]]] ];
cmd.out.PutRope["\n"];
RETURN};
FOR i: NAT IN (0..argv.argc) DO
ENABLE PFS.Error => {
cmd.err.PutF["%g => PFS.Error[%g, %g]\n", [rope[argv[i]]], [atom[error.code]], [rope[error.explanation]] ];
CONTINUE};
pat: PFS.PATH ~ PFS.PathFromRope[argv[i]];
abs: PFS.PATH ~ PFS.AbsoluteName[pat];
MorePfsEnumeration.EnumerateForInfo[abs, PerInfo];
ENDLOOP;
RETURN};
Hash: PROC [key: REF ANY] RETURNS [CARDINAL] ~ {
k: Key ~ NARROW[key];
cc: CARD ~ LOOPHOLE[k.created.egmt.gmt];
RETURN [RopeHash.FromRope[rope: k.shortName, case: FALSE, seed: (cc + cc/65536) MOD 65536]]};
Equal: PROC [key1, key2: REF ANY] RETURNS [BOOL] ~ {
k1: Key ~ NARROW[key1];
k2: Key ~ NARROW[key2];
RETURN [k1.created=k2.created AND k1.shortName.Equal[k2.shortName, FALSE]]};
Commander.Register["VM2LS", VLS, "<fileName or $mapName> <full name pattern> [<create date> [<version stamp>]] --- lists matching tuples in the indicated map"];
Commander.Register["LS2", LS, "<file name pattern>... --- VM2-style file enumeration"];
Commander.Register["ListShortAndCreatedCollisions", ListCollisions, "<fileName or $mapName> --- lists sets of tuples with equal shortname & create date"];
Commander.Register["WatchPatternVersions", ListAdd, "<root> <pat>* --- be willing to look in files with names matching given patterns for version stamps for lists identified by <root><kind> (for all <kind>)"];
Commander.Register["ListPatternVersionsWatches", ListList, "<root>* --- list patterns watched for version map lists identified by <root><kind> (for all <kind>) for each given <root>, or all <root>s if none given"];
Commander.Register["test-psm", TestPSM, "<pat1 > <pat2> --- sort/merges two VM2 name patterns"];
END.