source: cprs/branches/tmg-cprs/m_files/TMGPAT3.m

Last change on this file was 796, checked in by Kevin Toppenberg, 14 years ago

Initial upload

File size: 30.3 KB
Line 
1TMGPAT3 ;TMG/kst/Patching tools ;09/17/08
2 ;;1.0;TMG-LIB;**1**;09/17/08
3 ;
4 ;"Kevin Toppenberg MD
5 ;"GNU General Public License (GPL) applies
6 ;"9/26/08
7
8 ;"=======================================================================
9 ;" API -- Public Functions.
10 ;"=======================================================================
11 ;"NEWPACK -- Install a new package from ftp server.
12 ;"CONSOLE --show how many patches for a package are available and have not been installed yet
13 ;"RESCAN -- show how many patches for a package are available and have not been installed yet
14 ;"ShowPatches(PckInit,Ver) -- show installed patches, using scroll box.
15 ;"EditNotes -- launch an editor for editing notes about patching.
16
17 ;"=======================================================================
18 ;"Private Functions
19 ;"=======================================================================
20 ;"PrepAvail(pArray,Option) -- prepair an array with patch status, for use with Scroller^TMGUSRIF
21 ;"HndOnSel(pArray,Option,Info) -- handle ON SELECT event from Scroller^TMGUSRIF
22 ;"HndOnCmd(pArray,Option,Info) -- handle ON SELECT event from Scroller
23 ;"StoreMissing(PckInit,pArray) store the list of missing patches with the pending patches
24 ;"DownPck(PatchName,Option,Msg) -- Given a package name, ensure all pending patches are local.
25 ;"$$Rpt1Avail^TMGPAT3(PatchName)
26 ;"$$RptAvail^TMGPAT3(PckInit)
27 ;"Scan4New(MaxDays,Option) -- scan all packages and determine how many patches are pending for each
28 ;"Scan41(PckInit,MaxDays,Option) -- scan one package and determine how many patches are pending
29 ;"Scan41a1Ver(PckInit,Ver,MaxDays,Option) -- scan one package and determine how many patches are pending
30 ;"GetNew(PckInit,Ver,pArray,RefreshNeeded,Option) -- Get array of **just** patches still to be installed for a given package/version
31 ;"GetAvail(PckInit,Ver,pArray,RefreshNeeded,Option) -- return array of all patches for a given package/version
32 ;"GetPList(PckInit,Ver,pArray) -- get a list of applied patches, from PACKAGE file, into Array
33 ;"PrepPatchList(PckInit,Ver,pShowArray,ByPatchNum) -- prepair the patch list for display in scroll box.
34 ;"HndOnPCmd(pArray,Option,Info) -- handle ON SELECT event from Scroller
35 ;"ShowAvail -- Show data that tallies the available patches.
36 ;"IncLineCt(lineCount,pageLen)
37 ;"=======================================================================
38 ;"=======================================================================
39
40 ;"NOTE: This Module should be re-written. Rather than store the data in the global ^TMG(...
41 ;" the Fileman file 22709 should be used. As it is now, it is a duplication of organization.
42
43NEWPACK
44 ;"Purpose: Install a new package from ftp server.
45
46 new %,DIR,PckInit,Ver,X,Y,Msg
47
48 do Logo^TMGPAT1
49 set %=1
50 write "Install a NEW PACKAGE from ftp.va.gov" do YN^DICN write !
51 if %'=1 goto NPDone
52 set DIR(0)="F^2:4"
53 set DIR("A")="Enter PACKAGE prefix (? for help)"
54 set DIR("?")="Enter Namespace initials."
55 set DIR("?",1)="Enter namespace package prefix initials."
56 set DIR("?",2)="E.g. for Fileman, enter: DI"
57 set DIR("?",3)="Enter ^ to abort."
58 do ^DIR write ! ;"results in X and Y
59 if Y="^" goto NPDone
60 set PckInit=Y
61
62 new Array,result
63 write "Fetching info from VA ftp server..."
64 set result=$$GetPckList^TMGKERNL(PckInit,.Array)
65 write " Done.",!
66 if result=0 goto NPDone
67 new IEN9d4 set IEN9d4=+$order(^DIC(9.4,"C",PckInit,""))
68 if IEN9d4'>0 do goto NPDone
69 . do AddMsg^TMGPAT2("Can't find PACKAGE named '"_PckInit_"'",1,.Msg)
70
71NPDone
72 if $$ShowMsg^TMGPAT2(.Msg)
73 write "Goodbye.",!
74 quit
75
76;"====================================================================
77
78CONSOLE
79 new Array,Option
80 do PrepAvail("Array",.Option)
81 set Option("FOOTER",1,1)="^ Exit"
82 set Option("FOOTER",1,2)="? Help"
83 set Option("FOOTER",1,3)="[F1] SHOW Compl"
84 set Option("FOOTER",1,4)="[F3] Hx"
85 set Option("FOOTER",1,5)="[F4] Downld Pak"
86 set Option("FOOTER",1,6)="[F5] Notes"
87 set Option("FOOTER",1,7)="[F6] Add Waiting"
88 set Option("ON SELECT")="HndOnSel^TMGPAT3"
89 set Option("ON CMD")="HndOnCmd^TMGPAT3"
90 write #
91 do Scroller^TMGUSRIF("Array",.Option)
92 quit
93
94PrepAvail(pArray,Option)
95 ;"Purpose: To prepair an array with patch status, for use with Scroller^TMGUSRIF
96 ;"Input: pArray -- PASS BY NAME. Array to put info into. Prior data is killed.
97 ;" Option -- PASS BY REFERENCE. Prior data is NOT killed. See Scroller^TMGUSRIF for details
98 ;" Option("HIDE EMPTY")=0 OPTIONAL. Default is 0. If 1 then, entries with no patches.
99 ;" Also-- Uses global variable...
100 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version)=Count
101 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version,"DATE REFRESHED")=Last date server checked.
102 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version,"PATCHES",######)=AAAA*NN.NN*NNNN SEQ #1234"
103 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version,"PATCHES",######)=AAAA*NN.NN*NNNN SEQ #1234"
104 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,"FULL NAME")=Package name
105 ;"Results: None
106
107 set pArray=$get(pArray) goto:(pArray="") pAvDone
108 kill @pArray
109 new Hinder,Blocked
110 new oneLine,lineCt set lineCt=1
111 new PckInit set PckInit=""
112 new grandTotal set grandTotal=0
113 new hideEmpty set hideEmpty=$get(Option("HIDE EMPTY"),1)
114 for set PckInit=$order(^TMG("KIDS","PENDING PATCHES",PckInit)) quit:(PckInit="") do
115 . new total set total=0
116 . new Ver set Ver=""
117 . new PackageName set PackageName=$get(^TMG("KIDS","PENDING PATCHES",PckInit,"FULL NAME"))
118 . for set Ver=$order(^TMG("KIDS","PENDING PATCHES",PckInit,Ver)) quit:(+Ver'>0) do
119 . . set total=total+$get(^TMG("KIDS","PENDING PATCHES",PckInit,Ver))
120 . set grandTotal=grandTotal+total
121 . if (total=0)&(hideEmpty=1) quit
122 . set oneLine="("_PckInit_") "_PackageName_" "
123 . set oneLine=$$LJ^XLFSTR($extract(oneLine,1,40),40)_"--> "_$$RJ^XLFSTR(total,3)_" patches. "
124 . new tempArray,current,maxVer
125 . set maxVer=0,Ver="",current=""
126 . for set Ver=$order(^TMG("KIDS","PENDING PATCHES",PckInit,Ver)) quit:(+Ver'>0) do
127 . . if Ver'>maxVer quit
128 . . new temp set temp=$$GetLastPackage^TMGPAT1(PckInit,Ver)
129 . . if temp'="" set maxVer=Ver,current=temp
130 . set oneLine=oneLine_"Currently @ "_current
131 . set @pArray@(lineCt,oneLine)=$piece(current,"*",1,2)
132 . set lineCt=lineCt+1
133 . new i set i=""
134 . for set i=$order(^TMG("KIDS","PENDING PATCHES",PckInit,"WAITING FOR",i)) quit:(i="") do
135 . . set oneLine=" Waiting for "_i
136 . . set @pArray@(lineCt,oneLine)=$piece(i,"*",1,2)
137 . . set lineCt=lineCt+1
138 . . new init set init=$piece(i,"*",1)
139 . . set Hinder(init,PckInit)=""
140 . . set Blocked(PckInit)=1
141
142 if '$data(Hinder) goto pAV2
143
144 new count for count=1:1:5 do
145 . set init="" for set init=$order(Hinder(init)) quit:(init="") do
146 . . new init1,init2 set init1=init,init2=""
147 . . for set init2=$order(Hinder(init,init2)) quit:(init2="") do
148 . . . quit:(init2=init)
149 . . . merge Hinder(init,init2)=Hinder(init2)
150
151 set @pArray@(lineCt,"--- SUMMARY ------------------------------")=""
152 set lineCt=lineCt+1
153 new spaces set $piece(spaces," ",20)=" "
154 new ref set ref="Hinder"
155 new hideArray
156 set init=""
157 for set ref=$query(@ref) quit:(ref="") do
158 . if $$OREF^DILF($query(@ref))[$$OREF^DILF(ref) quit
159 . new count,node,done set done=0
160 . for count=1:1:$qlength(ref) do quit:done
161 . . set node=$qsubscript(ref,count)
162 . . set oneLine=$select((count=1):"#",1:"")
163 . . set oneLine=oneLine_$extract(spaces,1,count*3)_"Package "_node
164 . . if (count=1)&($get(Blocked(node))=1) set done=1 quit
165 . . if count=1 set oneLine=oneLine_" is hindering..."
166 . . else if count<$qlength(ref) set oneLine=oneLine_", which is hindering..."
167 . . if $get(hideArray(count))=oneLine quit
168 . . set hideArray(count)=oneLine
169 . . set @pArray@(lineCt,oneLine)="",lineCt=lineCt+1
170
171pAV2 set Option("HEADER",1)="TMG Patch Helper-- "_grandTotal_" Patches to be installed in all packages."
172
173pAvDone
174 quit
175
176
177HndOnSel(pArray,Option,Info)
178 ;"Purpose: handle ON SELECT event from Scroller^TMGUSRIF
179 ;"Input: pArray,Option,Info -- see documentation in Scroller^TMGUSRIF
180 ;" Info has this:
181 ;" Info("CURRENT LINE","NUMBER")=number currently highlighted line
182 ;" Info("CURRENT LINE","TEXT")=Text of currently highlighted line
183 ;" Info("CURRENT LINE","RETURN")=return value of currently highlighted line
184
185 new PatchName,PckInit,Ver
186 set PatchName=$get(Info("CURRENT LINE","RETURN"))
187 do ParsePatchName^TMGPAT2(PatchName,.PckInit,.Ver)
188 if (PckInit="")&(Ver="") do goto HOSDone
189 . write "?? The line selected specify any command ??",!
190 do DONEXTPK^TMGPAT1(PckInit,Ver)
191 do PrepAvail(pArray,.Option)
192HOSDone
193 do PressToCont^TMGUSRIF
194 write #
195 quit
196
197
198HndOnCmd(pArray,Option,Info) ;"Part of TestScrl
199 ;"Purpose: handle ON SELECT event from Scroller
200 ;"Input: pArray,Option,Info -- see documentation in Scroller
201 ;" Info has this:
202 ;" Info("USER INPUT")=input
203 ;" Info("CURRENT LINE","NUMBER")=number currently highlighted line
204 ;" Info("CURRENT LINE","TEXT")=Text of currently highlighted line
205 ;" Info("CURRENT LINE","RETURN")=return value of currently highlighted line
206
207 new input set input=$$UP^XLFSTR($get(Info("USER INPUT")))
208 if input["F2" do
209 . set Option("FOOTER",1,3)="[F1] SHOW compl"
210 . set Option("HIDE EMPTY")=1
211 else if input="RESCAN" do
212 . do RESCAN
213 else if input["F1" do
214 . set Option("FOOTER",1,3)="[F2] HIDE compl"
215 . set Option("HIDE EMPTY")=0
216 else if input["F3" do
217 . new PatchName set PatchName=$get(Info("CURRENT LINE","RETURN")) quit:(PatchName="")
218 . new PckInit,Ver
219 . do ParsePatchName^TMGPAT2(PatchName,.PckInit,.Ver)
220 . if $$ShowPatches(PckInit,Ver)
221 else if input["F4" do
222 . new PatchName set PatchName=$get(Info("CURRENT LINE","RETURN")) quit:(PatchName="")
223 . new Option set Option("VERBOSE")=1
224 . new % set %=1
225 . write "Ensure that all pending patches for ",PatchName," have been downloaded"
226 . do YN^DICN write !
227 . if %'=1 quit
228 . do DownPck(PatchName,.Option)
229 . do PressToCont^TMGUSRIF
230 else if input["F5" do
231 . do EditNotes
232 . do PressToCont^TMGUSRIF
233 else if input["F6" do ;"Add Waiting"
234 . if Info("CURRENT LINE","TEXT")'["-->" do quit
235 . . write !,"Please first select containing '-->'",!
236 . . do PressToCont^TMGUSRIF
237 . new PatchName set PatchName=$get(Info("CURRENT LINE","RETURN")) quit:(PatchName="")
238 . new PckInit set PckInit=$piece(PatchName,"*",1)
239 . new % set %=1
240 . write !,"Manually add a 'Waiting For' entry for ",PatchName
241 . do YN^DICN write !
242 . if %'=1 quit
243 . new DIR,DIRUT set DIR(0)="F",DIR("A")="Enter what "_PatchName_" is waiting for"
244 . do ^DIR write ! if $data(DIRUT) quit
245 . do AddMissing(PckInit,Y)
246 . do PressToCont^TMGUSRIF
247 else if input="NEWPACK" do
248 . do NEWPACK
249 else if input="?" do
250 . write !,"Use UP and DOWN cursor keys to select package, then ENTER to work on.",!
251 . write "Enter 'NEWPACK' to install a NEW package.",!
252 . write "Enter 'RESCAN' to rescan the ftp.va.gov server",!
253 . write "Enter ^ at the ':' prompt to quit",!
254 . do PressToCont^TMGUSRIF
255 else if input'="" do
256 . write !,"Input ",$get(Info("USER INPUT"))," not recognized.",!
257 . do PressToCont^TMGUSRIF
258
259 do PrepAvail(pArray,.Option)
260 write #
261 quit
262
263
264StoreMissing(PckInit,pArray)
265 ;"Purpose: to store the list of missing patches with the pending patches
266 kill ^TMG("KIDS","PENDING PATCHES",PckInit,"WAITING FOR")
267 merge ^TMG("KIDS","PENDING PATCHES",PckInit,"WAITING FOR")=@pArray
268 quit
269
270AddMissing(PckInit,PatchName)
271 ;"Purpose: Add a missing patche to pending patches
272 set ^TMG("KIDS","PENDING PATCHES",PckInit,"WAITING FOR",PatchName)=""
273 quit
274
275DownPck(PatchName,Option,Msg)
276 ;"Purpose: given a patch name, ensure all pending patches are local.
277 ;"Input: PatchName -- patch name, e.g. ABC*1.0*123
278 ;" Option -- Optional. PASS BY REFERENCE.
279 ;" Option("VERBOSE")=1 --> puts output to console
280 ;" Msg -- PASS BY REFERANCE, an OUT PARAMETER
281 ;" Errors are stored in Msg("ERROR",x)=Message
282 ;" Msg("ERROR")=count of last error
283 ;" Message are store in Msg(x)=Message
284 ;" Msg=count of last message+1
285 ;"Results: none
286
287 new PckInit,Ver,PatchNum,seqNum,Info
288 do ParsePatchName^TMGPAT2(PatchName,.PckInit,.Ver,.PatchNum,.seqNum)
289 do Scan41a1Ver(PckInit,Ver,90)
290 new total set total=+$get(^TMG("KIDS","PENDING PATCHES",PckInit,Ver))
291 new count set count=1
292 new patch set patch=""
293 for set patch=$order(^TMG("KIDS","PENDING PATCHES",PckInit,Ver,"PATCHES",patch)) quit:(patch="") do
294 . new patchName set patchName=$get(^TMG("KIDS","PENDING PATCHES",PckInit,Ver,"PATCHES",patch))
295 . if $get(Option("VERBOSE"))=1 write count,"/",total,". ---- ",patchName," ----",!
296 . new IENS set IENS=$$GetIENS^TMGPAT2(patchName) quit:(IENS="")
297 . if $$EnsureLocal^TMGPAT2(IENS,.Info,.Msg,.Option)=0 do
298 . . do AddMsg^TMGPAT2("Unable to download patch to local file system.",1,Msg)
299 . set count=count+1
300
301 if $get(Option("VERBOSE"))=1 do
302 . if $$ShowMsg^TMGPAT2(.Msg)
303
304 quit
305
306Rpt1Avail(PatchName)
307 ;"Purpose: given a patch name (e.g. ABC*1.0*123), return pending patches.
308 new PckInit,Ver,PatchNum,seqNum
309 new count set count=-1
310 do ParsePatchName^TMGPAT2(PatchName,.PckInit,.Ver,.PatchNum,.seqNum)
311 if ($get(PckInit)="")!($get(Ver)="") goto Rpt1Done
312 do Scan41a1Ver(PckInit,Ver,90)
313 set count=+$get(^TMG("KIDS","PENDING PATCHES",PckInit,Ver))
314Rpt1Done
315 quit count
316
317RptAvail(PckInit)
318 ;"Purpose: given a package (e.g. ABC), return pending patches.
319 new total set total=0
320 new Ver set Ver=""
321 for set Ver=$order(^TMG("KIDS","PENDING PATCHES",PckInit,Ver)) quit:(+Ver'>0) do
322 . set total=total+$get(^TMG("KIDS","PENDING PATCHES",PckInit,Ver))
323 quit total
324
325RESCAN
326 ;"Purpose: To show how many patches for a package are available and have not been installed yet
327 write !
328 new DUOUT,DIR
329 set DIR("A")="Search ftp server if data is older than __ days old? (SLOW!)"
330 set DIR("B")=90
331 set DIR(0)="N^0:999:0"
332 do ^DIR write !
333 new Option
334 set Option("VERBOSE")=0
335 if $get(DUOUT) quit
336 do Scan4New(+Y,.Option)
337 ;"if '$get(DUOUT) do ShowAvail
338SADone quit
339
340
341
342Scan4New(MaxDays,Option)
343 ;"Purpose: to scan all packages and determine how many patches are pending for each
344 ;"Input: MaxDays -- the number of days that old days can be used. If last refresh
345 ;" was greater than this number, then ftp.va.gov is queried again.
346 ;" Option -- Optional. PASS BY REFERENCE.
347 ;" Option("VERBOSE")=1 --> puts output to console
348 ;"Output: Results will be stored:
349 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version)=Count
350 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version,"DATE REFRESHED")=Last date server checked.
351 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version,"PATCHES",######)=AAAA*NN.NN*NNNN SEQ #1234"
352 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version,"PATCHES",######)=AAAA*NN.NN*NNNN SEQ #1234"
353 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,"FULL NAME")=Package name
354 ;"
355 ;"Results: none
356
357 ;"NOTE: This function should be re-written. Rather than store the data in the global ^TMG(...
358 ;" the Fileman file 22709 should be used. As it is now, it is a duplication of organization.
359
360 set MaxDays=+$get(MaxDays)
361 new PackageName set PackageName=""
362 for set PackageName=$order(^DIC(9.4,"B",PackageName)) quit:(PackageName="") do
363 . new IEN9d4 set IEN9d4=+$order(^DIC(9.4,"B",PackageName,"")) quit:(IEN9d4'>0)
364 . new PckInit set PckInit=$piece($get(^DIC(9.4,IEN9d4,0)),"^",2) ;"0;2 = Package prefix
365 . do Scan41(PckInit,MaxDays,.Option)
366
367 quit
368
369Scan41(PckInit,MaxDays,Option)
370 ;"Purpose: to scan one package and determine how many patches are pending
371 ;"Input: PckInit -- Package Initials/prefix
372 ;" MaxDays -- the cutoff for when to requery the server
373 ;" Option -- PASS BY REFERENCE.
374 ;" Option("VERBOSE")=1 to be verbose.
375 ;"Output: Results will be stored:
376 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version)=Count
377 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version,"DATE REFRESHED")=Last date server checked.
378 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version,"PATCHES",######)=AAAA*NN.NN*NNNN SEQ #1234"
379 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version,"PATCHES",######)=AAAA*NN.NN*NNNN SEQ #1234"
380 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,"FULL NAME")=Package name
381 ;"Results: none
382
383 new IEN9d4 set IEN9d4=+$order(^DIC(9.4,"C",PckInit,""))
384 new PackageName set PackageName=""
385 if IEN9d4>0 set PackageName=$piece($get(^DIC(9.4,IEN9d4,0)),"^",1)
386 if $get(Option("VERBOSE"))=1 write "Checking Package: ",PackageName," (",PckInit,")...",!
387 set ^TMG("KIDS","PENDING PATCHES",PckInit,"FULL NAME")=PackageName
388 ;"kill ^TMG("KIDS","PENDING PATCHES",PckInit,"DATE REFRESHED") ;"force refresh
389 set Ver=""
390 for set Ver=$order(^DIC(9.4,IEN9d4,22,"B",Ver)) quit:(Ver="") do
391 . do Scan41a1Ver(PckInit,Ver,MaxDays,.Option)
392
393 quit
394
395
396Scan41a1Ver(PckInit,Ver,MaxDays,Option)
397 ;"Purpose: to scan one package and determine how many patches are pending
398 ;"Input: PckInit -- Package Initials/prefix
399 ;" Ver -- The version of the Package
400 ;" MaxDays -- the cutoff for when to requery the server
401 ;" Option -- PASS BY REFERENCE.
402 ;" Option("VERBOSE")=1 to be verbose.
403 ;"Output: Results will be stored:
404 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version)=Count
405 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version,"DATE REFRESHED")=Last date server checked.
406 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version,"PATCHES",######)=AAAA*NN.NN*NNNN SEQ #1234"
407 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,Version,"PATCHES",######)=AAAA*NN.NN*NNNN SEQ #1234"
408 ;" ^TMG("KIDS","PENDING PATCHES",PackageInitials,"FULL NAME")=Package name
409 ;"Results: none
410
411 ;"kill ^TMG("KIDS","PENDING PATCHES",PckInit,"DATE REFRESHED") ;"force refresh
412 if $get(PckInit)="" goto S41Done
413 if $get(Ver)="" goto S41Done
414 set MaxDays=+$get(MaxDays,90)
415 if $get(Option("VERBOSE"))=1 write " Ver: ",Ver," ",!
416 new RefreshNeeded
417 new lastCheck set lastCheck=$get(^TMG("KIDS","PENDING PATCHES",PckInit,"DATE REFRESHED"))
418 if lastCheck'="" do
419 . new X,Y,%DT,X1,X2
420 . set X=lastCheck,%DT="TS"
421 . do ^%DT ;"result in Y
422 . set X=0
423 . do NOW^%DTC ;"returns date in X
424 . set X1=X,X2=Y
425 . do ^%DTC ;"returns X=X1-X2
426 . set RefreshNeeded=(X>MaxDays)
427 else set RefreshNeeded=1
428 new pArray set pArray=$name(^TMG("KIDS","PENDING PATCHES",PckInit,Ver,"PATCHES"))
429 new count set count=$$GetNew(PckInit,Ver,pArray,RefreshNeeded,.Option)
430 if $get(Option("VERBOSE"))=1 write " ",count," patches to be installed.",!
431 set ^TMG("KIDS","PENDING PATCHES",PckInit,Ver)=count
432 if RefreshNeeded do
433 . new %,%I,X,Y
434 . do NOW^%DTC set Y=%
435 . X ^DD("DD") ;"result in Y
436 . set ^TMG("KIDS","PENDING PATCHES",PckInit,"DATE REFRESHED")=Y
437
438S41Done
439 quit
440
441
442GetNew(PckInit,Ver,pArray,RefreshNeeded,Option)
443 ;"Purpose: Get array of **just** patches still to be installed for a given package/version
444 ;"Input: PckInit -- this is the namespace of the package to get patches for, e.g. 'DI' for fileman
445 ;" Ver -- the package version
446 ;" pArray -- PASS BY NAME. An OUT PARAMETER. Format:
447 ;" @pArray@(######)=AAAA*NN.NN*NNNN SEQ #1234"
448 ;" @pArray@(######)=AAAA*NN.NN*NNNN SEQ #1234"
449 ;" NeedsRefresh -- 0 if refreshing not needed (just ensure file exists)
450 ;" Option -- Optional. PASS BY REFERENCE.
451 ;" Option("VERBOSE")=1 --> puts output to console
452 ;"Results: Number of patches still to be installed.
453
454 new count set count=0
455
456 do GetAvail(PckInit,Ver,pArray,.RefreshNeeded,.Option)
457 new LastPck set LastPck=$$GetLastPackage^TMGPAT1(PckInit,Ver)
458 new lastSeq set lastSeq=+$piece(LastPck,"SEQ #",2)
459 if lastSeq="" kill @pArray goto GNDone
460 new i set i=""
461 for set i=$order(@pArray@(i)) quit:(i="") do
462 . if +i'>lastSeq kill @pArray@(i) quit
463 . set count=count+1
464GNDone
465 quit count
466
467
468
469GetAvail(PckInit,Ver,pArray,RefreshNeeded,Option)
470 ;"Purpose: return array of all patches for a given package/version
471 ;"Input: PckInit -- this is the namespace of the package to get patches for, e.g. 'DI' for fileman
472 ;" Ver -- the package version
473 ;" pArray -- PASS BY NAME. An OUT PARAMETER. Format:
474 ;" @pArray@(######)=AAAA*NN.NN*NNNN SEQ #1234"
475 ;" @pArray@(######)=AAAA*NN.NN*NNNN SEQ #1234"
476 ;" NeedsRefresh -- 0 if refreshing not needed (just ensure file exists)
477 ;" Option -- Optional. PASS BY REFERENCE.
478 ;" Option("VERBOSE")=1 --> puts output to console
479 ;"results: none
480
481 kill @pArray
482 if $$RefreshPackge^TMGPAT2(PckInit,.Msg,.RefreshNeeded,.Option)
483
484 new IEN9d4 set IEN9d4=+$order(^DIC(9.4,"C",PckInit,""))
485 if IEN9d4'>0 goto GADone
486 new PckIEN set PckIEN=+$order(^TMG(22709,"B",IEN9d4,""))
487 if PckIEN'>0 goto GADone
488 new VerIEN set VerIEN=+$order(^TMG(22709,PckIEN,1,"B",Ver,""))
489 if VerIEN'>0 set VerIEN=+$order(^TMG(22709,PckIEN,1,"B",$piece(Ver,".0",1),""))
490 if VerIEN'>0 goto GADone
491
492 new patchIEN,nextSeq
493 set patchIEN=0
494 for set patchIEN=$order(^TMG(22709,PckIEN,1,VerIEN,1,patchIEN)) quit:(patchIEN'>0) do
495 . new node0 set node0=$get(^TMG(22709,PckIEN,1,VerIEN,1,patchIEN,0)) quit:(node0="")
496 . new patchNum set patchNum=$piece(node0,"^",2)
497 . new oneSeqNum set oneSeqNum=$piece(node0,"^",2)
498 . if oneSeqNum'>0 set oneSeqNum=0
499 . set @pArray@($$RJ^XLFSTR(oneSeqNum,6,"0"))=PckInit_"*"_Ver_"*"_patchNum_" SEQ #"_oneSeqNum
500
501GADone
502 quit
503
504
505TestPList ;"temp function.
506 new PckInit,Ver,Array
507 do GetPckVer^TMGPAT1(.PckInit,.Ver)
508 if Ver="^" goto TPLDone
509 if $$GetPList(PckInit,Ver,"Array")=0 goto TPLDone
510 zwr Array(*)
511TPLDone quit
512
513
514GetPList(PckInit,Ver,pArray)
515 ;"Purpose: to get a list of applied patches, from PACKAGE file, into Array
516 ;"Input:
517 ;"Input: PckInit -- this is the namespace of the package to get patches for, e.g. 'DI' for fileman
518 ;" Ver -- the package version
519 ;" pArray -- PASS BY NAME. An OUT PARAMETER. Format:
520 ;" @pArray@(OrderNum)=PatchName
521 ;" @pArray@(OrderNum,"i",".01")=PatchName
522 ;" @pArray@(OrderNum,"i",".02")=Patch Date
523 ;" @pArray@(OrderNum,"i",".03")=Applied By
524 ;" @pArray@(OrderNum)=PatchName
525 ;"Results: 1 if OK, 0 if error
526 ;
527 new result set result=1
528 ;
529 new IEN9d4,IEN9d49
530 if $$GetPVIEN^TMGPAT1(PckInit,Ver,.IEN9d4,.IEN9d49)=0 set result=0 goto GPLDone
531 ;
532 new orderNum set orderNum=1
533 new patchIEN set patchIEN=0
534 for set patchIEN=$order(^DIC(9.4,IEN9d4,22,IEN9d49,"PAH",patchIEN)) quit:(+patchIEN'>0) do
535 . new s set s=$get(^DIC(9.4,IEN9d4,22,IEN9d49,"PAH",patchIEN,0))
536 . set @pArray@(orderNum)=$piece(s,"^",1) ;"0;1=.01 --PATCH APPLICATION HISTORY
537 . new IENS set IENS=patchIEN_","_IEN9d49_","_IEN9d4_","
538 . new TMGDATA,TMGMSG
539 . do GETS^DIQ(9.4901,IENS,".01;.02;.03","","TMGDATA","TMGMSG")
540 . merge @pArray@(orderNum,"i")=TMGDATA("9.4901",IENS)
541 . ;"zwr TMGDATA(*)
542 . set orderNum=orderNum+1
543 ;
544GPLDone quit result
545
546
547SHOWPLST
548 ;"Purpose: query user for package and version, then show patches.
549 new PckInit,Ver,Array
550 do GetPckVer^TMGPAT1(.PckInit,.Ver)
551 if Ver="^" goto SLPDone
552 if $$ShowPatches(PckInit,Ver)
553SLPDone quit
554
555
556ShowPatches(PckInit,Ver)
557 ;"Purpose: to show installed patches, using scroll box.
558 ;"Input: PckInit -- this is the namespace of the package to get patches for, e.g. 'DI' for fileman
559 ;" Ver -- the package version
560 ;"Results: 1 if OK, 0 if error
561
562 new TMGPCKI set TMGPCKI=PckInit ;"used in HndOnPCmd^TMGPAT3
563 new TMGPVER set TMGPVER=Ver ;"used in HndOnPCmd^TMGPAT3
564 new TMGSORT set TMGSORT=2 ;"sort by SEQ number. Used in HndOnPCmd^TMGPAT3
565 new TMGSARRAY
566 set TMGSARRAY(0)="SORT by IEN order"
567 set TMGSARRAY(1)="SORT by PATCH num"
568 set TMGSARRAY(2)="SORT by SEQ num"
569 new Option,ShowArray,result
570 set Option("HEADER",1)="Applied patches for package "_PckInit_" "_TMGSARRAY(TMGSORT)
571 set Option("FOOTER",1,1)="^ Done"
572 set Option("FOOTER",1,2)="? Help"
573 set Option("FOOTER",1,3)="[F1] "_TMGSARRAY(0)
574 set Option("FOOTER",1,4)="[F2] Fix Missing PATCH"
575 set Option("FOOTER",1,5)="[F3] Fix Missing SEQ"
576 set Option("ON CMD")="HndOnPCmd^TMGPAT3"
577 set Option("SHOW INDEX")=1
578
579 do PrepPatchList(PckInit,Ver,"ShowArray",TMGSORT)
580 if $data(ShowArray)=0 do
581 . do AskVer^TMGPAT1(PckInit,.Ver)
582 . do PrepPatchList(PckInit,Ver,"ShowArray",TMGSORT)
583
584 write #
585 do Scroller^TMGUSRIF("ShowArray",.Option)
586
587SPDone quit 1
588
589PrepPatchList(PckInit,Ver,pShowArray,Mode)
590 ;"Purpose: to prepair the patch list for display in scroll box.
591 ;"Input: PckInit -- this is the namespace of the package to get patches for, e.g. 'DI' for fileman
592 ;" Ver -- the package version
593 ;" pShowArray -- PASS BY NAME, an OUT PARAMATER
594 ;" Mode -- OPTIONAL. 0: Otherwise by IEN order
595 ;" 1: Then sorted by patch number,
596 ;" 2: Otherwise by SEQ Num
597
598 set ByPatchNum=+$get(ByPatchNum)
599 new index set index=1
600 new showI set showI=1
601 kill @pShowArray
602 new Array,tempA
603 if $$GetPList(.PckInit,.Ver,"Array")=0 goto PPLDone
604 if Mode=0 goto PPL2
605
606 new Num
607 for set index=$order(Array(index)) quit:(index="") do
608 . if Mode=1 set Num=+$piece(Array(index)," ",1)
609 . else set Num=+$piece(Array(index),"SEQ #",2)
610 . new s,patch
611 . set patch=PckInit_"*"_Ver_"*"_$get(Array(index))
612 . set s=$$LJ^XLFSTR(patch,25)
613 . set s=s_" Applied: "_$get(Array(index,"i",".02"))_" "
614 . set s=s_" By: "_$get(Array(index,"i",".03"))
615 . set tempA(Num)=s
616 set Num=""
617 for set Num=$order(tempA(Num)) quit:(Num="") do
618 . new s set s=$get(tempA(Num)) quit:(s="")
619 . set @pShowArray@(showI,s)=$piece(s," Applied",1)
620 . set showI=showI+1
621 goto PPLDone
622
623PPL2 for set index=$order(Array(index)) quit:(index="") do
624 . new s,patch
625 . set patch=PckInit_"*"_Ver_"*"_$get(Array(index))
626 . set s=$$LJ^XLFSTR(patch,25)
627 . set s=s_" Applied: "_$get(Array(index,"i",".02"))_" "
628 . set s=s_" By: "_$get(Array(index,"i",".03"))
629 . set @pShowArray@(showI,s)=patch
630 . set showI=showI+1
631
632PPLDone quit
633
634HndOnPCmd(pArray,Option,Info)
635 ;"Purpose: handle ON SELECT event from Scroller
636 ;"Input: pArray,Option,Info -- see documentation in Scroller
637 ;" Info has this: Info("USER INPUT")=input
638 ;"NOTE: uses global-scope vars set up in ShowPatches:
639 ;" TMGPCKI,TMGPVER,TMGSORT
640
641 new input set input=$$UP^XLFSTR($get(Info("USER INPUT")))
642 if input["F1" do
643 . set Option("HEADER",1)="Applied patches for package "_PckInit_" "_TMGSARRAY(TMGSORT)
644 . do PrepPatchList(TMGPCKI,TMGPVER,pArray,TMGSORT)
645 . set TMGSORT=TMGSORT+1
646 . if TMGSORT=3 set TMGSORT=0
647 . set Option("FOOTER",1,3)="[F1] "_TMGSARRAY(TMGSORT)
648 else if input["F2" do
649 . do FixMisInit^TMGPAT1(TMGPCKI,TMGPVER,0)
650 . do PressToCont^TMGUSRIF
651 else if input["F3" do
652 . do FixMisInit^TMGPAT1(TMGPCKI,TMGPVER,1)
653 . do PrepPatchList(TMGPCKI,TMGPVER,pArray,TMGSORT)
654 . do PressToCont^TMGUSRIF
655 else if input="?" do
656 . write !,"Use UP and DOWN cursor keys to scroll.",!
657 . write "Press F1 or F2 to change sorting",!
658 . write "Enter ^ at the ':' prompt when done",!
659 . do PressToCont^TMGUSRIF
660 else if input'="" do
661 . write !,"Input ",$get(Info("USER INPUT"))," not recognized.",!
662 . do PressToCont^TMGUSRIF
663
664 write #
665 quit
666
667EditNotes
668 ;"Purpose: to launch an editor for editing notes about patching.
669 new FPName set FPName=$get(^TMG("KIDS","PATCH DIR"),"/tmp/")_"Patch_Notes.txt"
670 if $$EditHFSFile^TMGKERNL(FPName)
671 quit
Note: See TracBrowser for help on using the repository browser.