1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335
|
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; ;
; Copyright 2011, 2013 Fidelity Information Services, Inc ;
; ;
; This source code contains the intellectual property ;
; of its copyright holder(s), and is made available ;
; under a license. If you do not know the terms of ;
; the license, please stop and do not read further. ;
; ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; dircompare
; The purpose of this routine is to take the ls -lR output of the regular
; GT.M development directory and massage it to look like what we expect from
; the installed directory
;
; mumps -r dircompare <filename> <deletefilename | NOP> <addfilename | NOP> <deletedirectory | NOP>
;
; <filename> is the output of ls -lR of pro in either the build directory or the install directory
; For each of the following NOP indicates that there are none
; <deletefilename> - delete entries - aka files missing from PRO
; <addfilename> - added entries - aka files added on to of PRO
; <deletedirectory> - deleted directories - aka dirs missing from PRO
;
; The first few lines of the three files are the copyright lines. Other
; comment lines may be included after ; the copyright lines and all are eaten
; before the data is read into the database. No spaces are allowed between the
; comments lines.
;
; <deletefilename>
; The format of the deletefile is shown below.
; Its purpose is to delete files from the list of permissions and files which
; are written to standard output.
;
; <addfilename>
; The format of the addfile is shown below.
; Its purpose is to add files to the list of permissions and files which are
; written to standard output. To add files before an existing entry, the tryadd
; function is used.
;
; To add files after the last file in a directory, the same format is used in the addfile, but the filename must be
; after the last entry (i.e. must not exist). The tryinsert function adds files to the end of a directory. It
; assumes that at least one file exists in the directory. An example of both forms is given prior to the loadadd function.
;
; <deletedirectory>
; The format of the deldirfile is shown below.
;
dircompare
; set etrap so we get debug info and exit mumps
set $etrap="use $P write $zstatus,!,""Error line: "" zprint @$zposition s x=$zjobexam() halt"
; read the delete file into global memory
kill ^delentries
kill ^addentries
kill ^deldirentries
kill ^debug
; Parse command line
if 4'=$LENGTH($ZCMDLINE," ") do
. write "Usage: dircompare <filename> <deletefilename | NOP> <addfilename | NOP> <deletedirectory | NOP>",! halt
set infile=$PIECE($ZCMDLINE," ",1)
if $ZSEARCH("foo.bar") ; ensure a new search
if '$$uniquefile("infile") halt
set deletefile=$PIECE($ZCMDLINE," ",2)
if "NOP"'=deletefile do
. if '$$uniquefile("deletefile") halt
. do loaddelete(deletefile)
set addfile=$PIECE($ZCMDLINE," ",3)
if "NOP"'=addfile do
. if '$$uniquefile("addfile") halt
. do loadadd(addfile)
set deldirfile=$PIECE($ZCMDLINE," ",4)
if "NOP"'=deldirfile do
. if '$$uniquefile("deldirfile") halt
. do loaddeldir(deldirfile)
set (directorydelete,nonewline)=1
open infile:(readonly)
use infile:exception="GOTO EOF"
for read dirname,x do ; read a directory and eat the next line which is size info; ; terminated by exception="GOTO EOF"
. set ^debug($i(readdirloop))=dirname
. if $DATA(^deldirentries(dirname)) set directorydelete=1 ; flag directory to delete
. else do
.. use $P
.. if 'nonewline write !
.. write dirname,!
.. set (directorydelete,nonewline)=0
. set ^debug(readdirloop,dirname,"state")=$select(directorydelete=1:"delete me",1:"use me")
. for use infile read x do quit:""=x
.. if ""=x do quit ; if it is a blank line then tryinsert
... ;in case a file(s) need(s) to be added to the end of the directory
... if $DATA(^addentries(dirname)) do tryinsert(dirname)
.. if directorydelete quit
.. set filename=$$getfilename(x) ; get the filename
.. if $DATA(^addentries(dirname)) do tryadd(dirname,filename,infile)
.. if $DATA(^delentries(dirname)),$$trydelete(dirname,filename) quit
.. set ext=$$getext(filename)
.. if (".hlp"=ext)!(".csh"=ext)!(".c"=ext) quit
.. if (".gtc"=ext) do zapgtc(.x) set filename=$$getfilename(x) ; get the modified filename
.. set perm=$PIECE(x," ",1) ; get the first piece which is the permission field
.. ; if it is a symbolic link then leave it alone. Otherwise, make some permission changes
.. if ("lrwxrwxrwx"'=perm)&("lrwxr-xr-x"'=perm) do
... do rmwrite(.perm),zapworld(.perm)
... if (".a"=ext)!(".o"=ext)!(".m"=ext)!(".dat"=ext)!(".gld"=ext)!(".h"=ext) do rmxall(.perm)
.. use $P
.. write perm," ",filename,!
EOF
if ('directorydelete&$DATA(^addentries(dirname))) do tryinsert(dirname)
for set unused=$order(^addentries($get(unused))) quit:unused="" do
. use $p write !,unused,! do tryinsert(unused)
close infile
halt
trydelete(dirname,filename)
quit $data(^delentries(dirname,filename))
tryadd(dirname,filename,infile)
set ret=0
if $DATA(^addentries(dirname,filename)) do
. use $P
. for j=1:1:^addentries(dirname,filename) do
. . write ^addentries(dirname,filename,j),!
. . set ^debug(readdirloop,dirname,$i(action))=$R
. set ^addentries(dirname)=$increment(^addentries(dirname),-j)
. kill ^addentries(dirname,filename)
. if $data(^addentries(dirname))<10 kill ^addentries(dirname)
. use infile
. quit
quit
tryinsert(dirname)
set nummatch=^addentries(dirname)
if $DATA(^addentries(dirname,"zzz_insert")) do
. use $P
. for j=1:1:^addentries(dirname,"zzz_insert") do
. . write ^addentries(dirname,"zzz_insert",j),!
. . set ^debug(readdirloop,dirname,$i(action))=$R
. set ^addentries(dirname)=$increment(^addentries(dirname),-j)
. kill ^addentries(dirname,"zzz_insert")
. if $data(^addentries(dirname))<10 kill ^addentries(dirname)
. use infile
quit
rmwrite(perm)
; do the equivalent of chmod a-w by translating permission w to -
set perm=$TRANSLATE(perm,"w","-")
quit
zapgtc(str)
set instr=str
set a=$FIND(instr,".gtc")
set str=$EXTRACT(instr,1,a-5)_$EXTRACT(instr,a,$LENGTH(instr))
; make remove group executable to match install if not a link
if '$FIND(instr,">") set str=$EXTRACT(str,1,6)_"-"_$EXTRACT(instr,8,$LENGTH(str))
; may need to do it to the modified string if it is a link
set a=$FIND(str,".gtc")
set str=$EXTRACT(str,1,a-5)_$EXTRACT(str,a,$LENGTH(str))
quit
makelink(perm,filename)
set perm="l"_$EXTRACT(perm,2,10)
set filename=filename_" -> ../"_filename
quit
zapworld(perm)
; get everything up to world field and add --- to tail
set perm=$EXTRACT(perm,1,7)_"---"
quit
addgrpx(perm)
set perm=$EXTRACT(perm,1,6)_"x"_$EXTRACT(perm,8,$LENGTH(perm))
quit
;do the equivalent of chmod a-x by translating x to - in perm
rmxall(perm)
set perm=$TRANSLATE(perm,"x","-")
quit
; loaddelete(fdelete) - fdelete is the name of the delete file to load
; assume delete file starts with a directory name followed by a colon and has a blank line before each subdirectory
; assumes the last line is not blank. It is ok to have a directory with no entries under it
; example:
;
; pro:
; test.m
; file.o
;
; pro/sub1:
; test.m -> ../test.m
;
; pro/sub1/sub2:
;
; pro/sub3:
; afile.m
;
; The format of the ^delentries array for the above example is:
; ^delentries("pro:","test.m")=""
; ^delentries("pro:","file.o")=""
; ^delentries("pro/sub1:","test.m -> ../test.m")=""
; ^delentries("pro/sub3:","afile.m")=""
loaddelete(fdelete)
new delentries,dirname,file
open fdelete:(readonly)
use fdelete
; eat the copyright lines which start with a # and any other comment lines with a # in them
for quit:$ZEOF read dirname do ; read the directory
. if ('$find(dirname,"#")) for read file quit:$ZEOF!'$length(file) do:$length(file)
.. set ^delentries(dirname,file)=""
close fdelete
quit
; loadadd(fadd)
; - fadd is the name of the add file to load
;
; assume addfile starts with a directory name follwed by a colon and has a blank line before each subdirectory
; assumes the last line is not blank. It is ok to have a directory with no entries under it
;
; the field separators must be a %
;
; the add entries start with a existing file before which the following permission and file will be inserted
; The exception to this rule is if the file or files is to be entered after the last entry in a directory
; In this case, you must use the file name zzz_insert which will not match any file in the directory
; There can be multiple files to insert before the current file (or after the final line if match not found)
; example:
;
; pro:
; gtmcshrc.gtc%-r-xr-x--- gtmbase
; gtmhelp.dat%-r-xr-x--- gtmcshrc
; gtmsecshr%-r-xr-x--- gtmprofile
; gtmsecshr%-r-xr-x--- gtmprofile2
; zzz_insert%lrwxrwxrwx GETPASS.m -> ../GETPASS.m
; pro/plugin:
; pro/plugin/gtmcrypt:
; utf8%-r--r----- source.tar
; pro/plugin/gtmcrypt/utf8:
; zzz_insert%lrwxrwxrwx GETPASS.m -> ../GETPASS.m
; ^addentries("pro/plugin/gtmcrypt/utf8:")=1
; ^addentries("pro/plugin/gtmcrypt/utf8:","zzz_insert")=1
; ^addentries("pro/plugin/gtmcrypt/utf8:","zzz_insert",1)="lrwxrwxrwx GETPASS.m -> ../GETPASS.m"
; ^addentries("pro/plugin/gtmcrypt:")=1
; ^addentries("pro/plugin/gtmcrypt:","utf8")=1
; ^addentries("pro/plugin/gtmcrypt:","utf8",1)="-r--r----- source.tar"
; ^addentries("pro/plugin:")=0
; ^addentries("pro:")=5
; ^addentries("pro:","gtmcshrc.gtc")=1
; ^addentries("pro:","gtmcshrc.gtc",1)="-r-xr-x--- gtmbase"
; ^addentries("pro:","gtmhelp.dat")=1
; ^addentries("pro:","gtmhelp.dat",1)="-r-xr-x--- gtmcshrc"
; ^addentries("pro:","gtmsecshr")=2
; ^addentries("pro:","gtmsecshr",1)="-r-xr-x--- gtmprofile"
; ^addentries("pro:","gtmsecshr",2)="-r-xr-x--- gtmprofile2"
; ^addentries("pro:","zzz_insert")=1
; ^addentries("pro:","zzz_insert",1)="lrwxrwxrwx GETPASS.m -> ../GETPASS.m"
; The ^addentries("pro/plugin/gtmcrypt/utf8:")=1 is 1 because there is only one unique input file to match
; The ^addentries("pro/plugin/gtmcrypt:")=1 is 1 because there is only one unique input file to match
; The ^addentries("pro/plugin:")=0 because there are no files to match
; The ^addentries("pro:")=5 is 5 because there are five unique input files to match and add files before
loadadd(fadd)
open fadd:(readonly)
use fadd
; read the first directory
for read dirname quit:'$find(dirname,"#")
set ^addentries(dirname)=0
use fadd
for read x quit:$ZEOF do
. if x="" read dirname set ^addentries(dirname)=0
. else do
.. ; parse the line
.. set match=$PIECE(x,"%",1)
.. set add=$PIECE(x,"%",2)
.. if '$DATA(^addentries(dirname,match)) set ^addentries(dirname,match)=0
.. set ^addentries(dirname)=^addentries(dirname)+1
.. set ^addentries(dirname,match)=^addentries(dirname,match)+1
.. set ^addentries(dirname,match,^addentries(dirname,match))=add
use $P
quit
; loaddeldir(fdeldir) - fdeldir is the name of the delete file to load
; example:
;
; pro:
; pro/sub1:
;
; The format of the ^delentries array for the above example is:
; ^deldirentries("pro:")=0
; ^deldirentries("pro/sub1:")=0
loaddeldir(fdeldir)
open fdeldir:(readonly)
use fdeldir
for read dirname quit:$ZEOF if '$find(dirname,"#") set ^deldirentries(dirname)=0
use $P
quit
; Ensure that the routine uses a file as input only once and that the target file exists
; f - is the name of a local which was just set by the CLI parser
uniquefile(f)
new fn,status,same
set status=1
for fn="infile","deletefile","addfile","deldirfile" do
. ; Skip when f and fn point to the same local
. quit:f=fn
. ; If the local (fn points to) DOES NOT exist in memory, quit
. quit:$data(@fn)=0
. ; The local (fn points to) exists in memory, quit if f and fn DO NOT point to the same file
. quit:@f'=@fn
. set status=0,same=1
. write !,f," and ",fn," files (",@f,") can't be the same",!
. quit
if $data(same) quit status
if ""=$ZSEARCH(@f) set status=0 write !,f," file: ",@f," does not exist",!
quit status
getext(file)
; return the extension of the filename or null if none
; get the last piece which will be the actual filename
quit $ZPARSE($piece(file," ",$length(file," ")),"TYPE")
; getfilename
; function to return the ninth field which is the file name
; there will be multiple spaces between the fields preceeding it so count them as one space
;
getfilename(line)
set col=1
set strlength=$LENGTH(line)
for quit:(col=9) do
. set position=$find(line," ")
. set line=$EXTRACT(line,position,strlength)
. if " "'=$EXTRACT(line,1) set col=col+1 ;next character is not a space so it is a valid field
quit line
|