File: dircompare.m.txt

package info (click to toggle)
fis-gtm 6.3-007-1
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 36,284 kB
  • sloc: ansic: 328,861; asm: 5,182; csh: 5,102; sh: 1,918; awk: 291; makefile: 69; sed: 13
file content (335 lines) | stat: -rwxr-xr-x 12,554 bytes parent folder | download | duplicates (3)
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