*! version 1.0.0 03apr2002 program define adomaint version 7 gettoken subcmd 0 : 0, parse(" ,=") if `"`subcmd'"' == "" { Query exit } local l = length(`"`subcmd'"') if "`subcmd'" == substr("list", 1, max(1,`l')) { List `0' exit } if "`subcmd'" == substr("notes", 1, max(1,`l')) { Notes `0' exit } if "`subcmd'" == substr("query", 1, max(1,`l')) { Query `0' exit } if "`subcmd'" == "rmdups" { Rmdups `0' exit } if "`subcmd'" == "update" { Update `0' exit } if "`subcmd'" == "," { Query, `0' exit } if "`subcmd'" == "_use" { _Use `0' exit } di as err "adomaint: `subcmd': unrecognized subcommand" exit 198 end /* adomaint query */ program define Query, rclass syntax [, DIR(string) REfresh TRace] Fixdir dir `"`dir'"' *preserve _Use, dir(`dir') `refresh' `trace' local hascrawl = r(hascrawl) di qui sum idate ret local earlist : di %d r(min) ret local latest : di %d r(max) ret scalar n = _N qui count if status==0 ret scalar n_noinfo = r(N) qui count if status==1 ret scalar n_vanished = r(N) qui count if status==2 ret scalar n_dups = r(N) qui count if status==3 ret scalar n_lacking = r(N) qui count if status==4 ret scalar n_up_to_date = r(N) qui count if status==5 ret scalar n_out_of_date = r(N) di as txt "{col 6}{hline 64}" di as txt "{col 7}number of user-written packages installed:" /* */ "{col 51}" as res %9.0g return(n) di as txt "{col 30}earliest installed:" /* */ "{col 51}{res:`return(earlist)'}" di as txt "{col 32}latest installed:" /* */ "{col 51}{res:`return(latest)'}" di di as txt "{col 28}number of duplicates:" /* */ "{col 51}" as res %9.0g return(n_dups) /* */ as txt " (note 1)" di as txt "{col 22}number no longer available:" /* */ "{col 51}" as res %9.0g return(n_vanished) /* */ as txt " (note 2)" di as txt "{col 19}number known to be up-to-date:" /* */ "{col 51}" as res %9.0g return(n_up_to_date) /* */ as txt " (note 3)" di as txt "{col 18}number known to be out-to-date:" /* */ "{col 51}" as res %9.0g return(n_out_of_date) /* */ as txt " (note 4)" di as txt "{col 17}number lacking date information:" /* */ "{col 51}" as res %9.0g return(n_lacking) /* */ as txt " (note 5)" di di as txt "{col 22}number with no information:" /* */ "{col 51}" as res %9.0g return(n_noinfo) /* */ as txt " (note 6)" di as txt "{col 6}{hline 64}" di as txt `"{col 6}(type -{stata adomaint notes}- for the text of the notes)"' end program define Notes syntax help adomaint_notes end /* adomaint list { dups | vanished | up-to-date | out-of-date | ^^^^ ^^^ ^^ ^^^ lacking | noinfo | all } [, refresh trace dir()] ^^^ ^^^^^^ ^^ ^^ ^^^ */ program define List, rclass syntax [anything(name=cat id="package category")] /* */ [, DIR(string) REfresh TRace] Get_cat "`cat'" local cat = r(cat) Fixdir dir `"`dir'"' *preserve _Use, dir(`dir') `refresh' `trace' local hascrawl = r(hascrawl) if `cat'==. { List_cat 2 sys List_cat 1 sys List_cat 4 sys List_cat 5 sys List_cat 3 sys List_cat 0 sys } else List_cat `cat' end program define List_cat args cat sys if "`sys'"!="" { qui count if status==`cat' if r(N)==0 { exit } } Get_cat_title `cat' di as txt _n `"{title:`r(title)'}"' _n if "`sys'"!="" { qui count if status==`cat' if r(N)==0 { di as txt " (None)" exit } } preserve quietly keep if status==`cat' sort id local n = _N forvalues i=1(1)`n' { local pkg = substr(pkg[`i'], 1, length(pkg[`i'])-4) di as txt "{p 4 8}" di "[" id[`i'] "] {res:`pkg'} from " as res site[`i'] di "{p_end}" } end program define Rmdups, rclass syntax [, DIR(string) REfresh TRace] Fixdir dir `"`dir'"' preserve _Use, dir(`dir') `refresh' `trace' nomsg qui keep if status==2 ret scalar n_dups = _N ret scalar n_removed = 0 if _N==0 { di as txt "(you have no duplicates)" exit } local n = _N local cnt = 0 forvalues i=1(1)`n' { di as txt "{p 0 4} di as txt "uninstalling " as res pkg[`i'] as txt " from" di as res site[`i'] di as txt "{p_end}" local p : di "[*" uid[`i'] "]" * di "qui ado uninstall `p'" qui ado uninstall `p' local cnt = `cnt' + 1 } ret scalar n_removed = `cnt' end program define Update, rclass syntax [, DIR(string) REfresh TRace] Fixdir dir `"`dir'"' preserve _Use, dir("`dir'") `refresh' `trace' nomsg qui count if status==5 ret scalar n_out_of_date = r(N) ret scalar n_updated = 0 if r(N)==0 { di as txt /* */ "(you have no known-to-be-out-of-date packages installed)" exit } quietly count if status==2 if r(N) { di as err "{p}" di as err "You have duplicate packages installed;" di as err "they must be removed before you" di as err "can use -adomaint update-." di as err local cmd1 "admaint rmdups" local cmd2 "admaint update" if `"`dir'"'!="STBPLUS" & `"`dir'"'!="SJPLUS" { local cmd1 `"`cmd1', dir(`dir')"' local cmd2 `"`cmd2', dir(`dir')"' } di as err "{p}" di as err `"Type "{stata `"`cmd1'"'}" and then rerun"' di as err `""`cmd2'"."' exit 459 } quietly keep if status==5 sort id local more : set more capture noisily { set more off Update_u `"`dir'"' } set more `more' return scalar updated = r(updated) exit _rc end program define Update_u, rclass args dir local n = _N local cnt = 0 forvalues i=1(1)`n' { di di as txt "{p 0 4} di as txt "updating " as res pkg[`i'] as txt " from" di as res site[`i'] as txt ":" di as txt "{p_end}" local pkg = pkg[`i'] local site = site[`i'] local uid = uid[`i'] Install_pkg `"`dir'"' `"`site'"' `"`pkg'"' if r(installed) { local cnt = `cnt' + 1 Prove_Installed `"`dir'"' `"`site'"' `"`pkg'"' `uid' if r(installed)==0 { di as txt " (only the date changed; code is the same)" Ado_uninstall `"`dir'"' "[*`uid']" qui Install_pkg `"`dir'"' `"`site'"' `"`pkg'"' } else { di as txt " removing old package" Ado_uninstall `"`dir'"' [*`uid']" } } } return scalar updated = `cnt' end /* ------------------------------------------------------------------------ */ program define Prove_Installed, rclass args dir site pkg olduid preserve quietly { _Use, dir("`dir'") nomsg trkfile count if (site==`"`site'"' & pkg==`"`pkg'"') | uid=="`olduid'" ret scalar installed = (r(N)>=2) } end program define Install_pkg, rclass args dir site pkg ret scalar installed = 0 capture net from `"`site'"' if _rc { di as txt " site did not respond; skipping" exit } capture net describe `pkg' if _rc { di as txt " package cannot be found at site; skipping" exit } di as txt " loading update" Net_install `"`dir'"' `"`pkg', replace"' if r(rc) { di as txt " package installation failed; skipping" exit } ret scalar installed = 1 end program define Ado_uninstall args dir rest if "`dir'"=="SJPLUS" { local dir "STBPLUS" } qui ado uninstall `rest', from(`dir') end program define Net_install, rclass args dir rest Net_prolog `"`dir'"' capture net install `rest' ret scalar rc = _rc Net_epilog end program define Net_prolog args dir if `"`dir'"'=="SJPLUS" | `"`dir'"'=="STBPLUS" { qui net set ado STBPLUS } else qui net set ado STBPLUS end program define Net_epilog args dir if `"`dir'"'!="SJPLUS" & `"`dir'"'!="STBPLUS" { qui net set ado STBPLUS } end program define Get_cat, rclass args cat if `"`cat'"'=="all" | `"`cat'"'=="" { ret scalar cat = . exit } local l = length(`"`cat'"') if `"`cat'"' == "dups" { ret scalar cat = 2 exit } if `"`cat'"' == substr("vanished", 1, max(3,`l')) { ret scalar cat = 1 exit } if `"`cat'"' == substr("up-to-date", 1, max(2,`l')) { ret scalar cat = 4 exit } if `"`cat'"' == substr("out-to-date", 1, max(3,`l')) { ret scalar cat = 5 exit } if `"`cat'"' == substr("lacking", 1, max(3,`l')) { ret scalar cat = 3 exit } if `"`cat'"' == "noinfo" { ret scalar cat = 0 } di as err "{p 0 4}" di as err `""`cat'" found where"' di as err "{cmd:dups}," di as err "{cmd:vanished}," di as err "{cmd:up-to-date}," di as err "{cmd:out-of-date}," di as err "{cmd:lacking}," di as err "{cmd:noinfo}," di as err "or {cmd:all} expected" di as err "{p_end}" exit 198 end program define _Use, rclass syntax [, DIR(string) REfresh TRace noMSG TRKFILE LABEL] Fixdir dir `"`dir'"' Crawl_dsn crawldsn "`dir'" drop _all label drop _all Load_stata_trk, dir(`"`dir'"') if "`label'" != "" { label var site "trk: -net from- of pkg" label var id "trk: [#] used by -ado-" label var pkg "trk: pkg name" label var uid "trk: [*#] used by -ado-" label var idate "trk: installation date" label var pdate "trk: package date" label data `"stata.trk for `dir'"' } if "`trkfile'"!="" { exit } if (_N==0) { di as err "{p}" di as err "(you have no user-written ado-files installed" _c if `"`dir'"' "SJPLUS" { di as txt _n `"in `dir'"' _c } di as err ")" di as err "{p_end}" capture erase `"`crawldsn'"' exit 2000 } if "`refresh'"!="" { preserve di as txt "{p 0 4}" di as txt "(contacting sites to obtain up-to-date package date information)" di as txt "{p_end}" Get_pkgs_info, `trace' capture drop p_date char _dta[crawldate] "$S_DATE" char _dta[crawltime] "$S_TIME" sort site pkg idate uid qui save `"`crawldsn'"', replace restore } capture confirm file `"`crawldsn'"' if _rc { if "`msg'" == "" { di as txt "{p 0 4}" di as txt "(no previous web search information found;" di as txt "you should specify the -refresh- option)" di as txt "{p_end}" } qui gen byte info = 0 qui gen byte found = . qui gen byte c_pdate = . format c_pdate %d return scalar hascrawl = 0 Mark_status if "`label'" != "" { Label_web_vars } exit } else return scalar hascrawl = 1 char _dta[crawldate] char _dta[crawltime] cap drop _merge sort site pkg qui merge site pkg using `"`crawldsn'"', nokeep if "`msg'"=="" { Timediffmsg "`_dta[crawldate]'" "`_dta[crawltime]'" } qui gen byte info = (_merge==3) drop _merge Mark_status if "`label'" != "" { Label_web_vars } end program define Label_web_vars label var found "web: 1 if found, else 0" label var c_pdate "web: package date" label var info "web: 1 if found on web, else 0" label var status "package status" label define _status 0 "no info" 1 "vanished" 2 "dup" 3 "lacking" /* */ 4 "up-to-date" 5 "out-of-date" label values status _status end /* status: 0 no information (web info out of date) 1 package no longer exists (maybe) 2 package is a duplicate (should be eliminated) 3 package exists, cannot determine up-to-dateness 4 is known to be up-to-date 5 is known to be out-of-date */ program define Get_cat_title, rclass args cat if `cat'==2 { ret local title "Duplicate packages" exit } if `cat'==1 { ret local title "Packages that no longer exists (or site not responding)" exit } if `cat'==4 { ret local title "Packages known to be up-to-date" exit } if `cat'==5 { ret local title "Packages known to be out-of-date" exit } if `cat'==3 { ret local title "Packages lacking date information" exit } if `cat'==0 { ret local title "Packages with no information" exit } exit 198 end program define Mark_status quietly { gen byte status = 0 replace status = 1 if info & found==0 sort site pkg idate id by site pkg: replace status = 2 if _n<_N replace status = 3 if info & found & c_pdate==. & status!=2 replace status = 4 if info & found & pdate!=. & c_pdate!=. & /* */ pdate >= c_pdate & status!=2 replace status = 4 if info & found & idate!=. & c_pdate!=. & /* */ idate > c_pdate & status!=2 replace status = 5 if info & found & pdate!=. & c_pdate!=. & /* */ pdate < c_pdate & status!=2 replace status = 5 if info & found & idate!=. & c_pdate!=. & /* */ idate < c_pdate & status!=2 } end program define Timediffmsg args fdate ftime tempname d0 d1 dif local cdate "$S_DATE" local ctime "$S_TIME" scalar `d0' = date("`fdate'", "dmy")*24*60 + /* */ 60*real(substr("`ftime'",1,2)) + /* */ real(substr("`ftime'",4,2)) scalar `d1' = date("`cdate'", "dmy")*24*60 + /* */ 60*real(substr("`ctime'",1,2)) + /* */ real(substr("`ctime'",4,2)) scalar `dif' = `d1' - `d0' local days = int(`dif'/(60*24)) scalar `dif' = `dif' - `days'*60*24 local hours = int(`dif'/60) scalar `dif' = `dif' - `hours'*60 local mins = `dif' if `days' { local txt = cond(`days'>1, "`days' days, ", "1 day, ") } if `hours' { local sub = cond(`hours'>1, "`hours' hours, ", "1 hour, ") local txt "`txt'`sub'" } local sub = cond(`mins'==1, "1 minute", "`mins' minutes") local txt "`txt'`sub'" di as txt "{p 0 4}" di as txt "(using web information that is `txt' old)" di as txt "{p_end}" end program define Fixdir args dirname dir if `"`dir'"' == "" | `"`dir'"' == "STBPLUS" | `"`dir'"'== "SJPLUS" { c_local `dirname' "SJPLUS" } else if `"`dir'"' == "SITE" { c_local `dirname' "SITE" } else { di as err "dir() must be SJPLUS, STBPLUS, or SITE" di as err "(SJPLUS and STBPLUS mean the same thing)" exit 198 } end program define Unfixdir args dirname dir if "`dir'"=="SJPLUS" { c_local `dirname' "STBPLUS" } else c_local `dirname' "`dir'" end program define Crawl_dsn args name dir if `"`dir'"' == "" | `"`dir'"'=="SJPLUS" | `"`dir'"'=="STBPLUS" { local dir : sysdir STBPLUS c_local `name' `"`dir'adomaint_sjplus.dta"' exit } if `"`dir'"' == "SITE" { local dir : sysdir STBPLUS /* sic */ c_local `name' `"`dir'adomaint_site.dta"' exit } di as err `"adomaint: `dir': must be nothing, SJPLUS, STPLUS, or SITE"' di as err `"(SJPLUS and STBPLUS mean the same thing)"' exit 198 end /* ------------------------------------------------------------------------- */ program define Load_stata_trk syntax [, Dir(string) DEBUG] Unfixdir dir `"`dir'"' local dir : sysdir `"`dir'"' qui drop _all capture confirm file `"`dir'stata.trk"' if _rc { exit } quietly { infix str lt 1 str txt 3-83 /* */ if lt=="S" | lt=="N" | lt=="D" | lt=="U" | /* */ (lt=="d" & /* ----+----1----+--- */ lower(substr(trim(txt),1,18))=="distribution-date:") /* */ using `"`dir'stata.trk"' replace txt = trim(txt) replace txt = trim(substr(txt,19,.)) if lt=="d" compress gen long id = 1 if lt=="S" replace id = sum(id) compress id gen long n = _n compress n sort id n Make pkg N Make idate D Make pdate d Make uid U by id: keep if _n==1 drop lt n rename txt site } Remake_idate, `debug' Remake_pdate, `debug' end program define Make args newvar ltr gen str80 `newvar' = txt if lt=="`ltr'" compress `newvar' by id: replace `newvar' = `newvar'[_n-1] if `newvar'=="" by id: replace `newvar' = `newvar'[_N] by id: drop if lt=="`ltr'" end program define Remake_idate syntax [, DEBUG] tempvar x qui gen long `x' = date(idate, "dmy") format `x' %d if "`debug'"!="" { qui count if `x'==. & idate!="" if r(N) { di di as txt "idates missing `r(N)' cases" list id idate if `x'==. & idate!="" } } drop idate rename `x' idate end program define Remake_pdate syntax [, DEBUG] tempvar newdate Translate_pdate pdate into `newdate' if "`debug'"!="" { qui count if `newdate'==. & pdate!="" if r(N) { di di as txt "pdates missing `r(N)' cases" list id pdate if `newdate'==. & pdate!="" } } drop pdate rename `newdate' pdate end /* ------------------------------------------------------------------------- */ program define Get_pkgs_info local more : set more cap noi { set more off Get_pkgs_info_u `0' } local rc = _rc set more `more' exit `rc' end program define Get_pkgs_info_u syntax [, TRace] quietly { sort site pkg idate id by site pkg: keep if _n==_N } cap drop found cap drop c_pdate qui gen byte found = 0 qui gen long c_pdate = . format c_pdate %d local N = _N forvalues j=1(1)`N' { local site = site[`j'] local pkg = pkg[`j'] Get_pkg_info `"`site'"' `"`pkg'"', `trace' qui replace found = r(found) in `j' qui replace c_pdate = r(pdate) in `j' } end /* ------------------------------------------------------------------------- */ program define Get_pkg_info, rclass gettoken site 0 : 0, parse(" ,") gettoken pkg 0 : 0, parse(" ,") syntax [, TRace] if `"`site'"' == "" { error 198 } if `"`pkg'"' == "" { error 198 } ret scalar pdate = . tempfile pfile if "`trace'"!="" { di as txt "{p 0 4}" di as txt `"checking `pkg' at `site'{break}"' di as txt `"... contacting `site'{break}"' } capture copy `"`site'/`pkg'"' `pfile', text if _rc { if "`trace'" != "" { di as txt "... no such pkg or site did not respond" di } ret scalar found = 0 exit } if "`trace'" != "" { di as txt "...pkg information obtained" di } ret scalar found = 1 preserve quietly { drop _all infix str lt 1 str txt 3-83 if (lt=="d" & /* ----+----1----+--- */ lower(substr(trim(txt),1,18))=="distribution-date:") /* */ using `"`pfile'"' replace txt = trim(txt) replace txt = trim(substr(txt,19,.)) if lt=="d" Translate_pdate txt into pdate if _N==0 { exit } drop if pdate==. if _N==0 { exit } sort pdate ret scalar pdate = pdate[_N] } end /* ------------------------------------------------------------------------- */ program define Translate_pdate version 7 args orig into new nothing if "`into'" != "into" | "`nothing'"!="" { error 198 } tempvar f x newdate /* ISO format yyyymmdd */ qui gen byte `f' = (/* * */ substr(`orig',1,1)=="2" & real(`orig')!=. & /* */ length(`orig')==8) qui gen str10 `x' = /* */ substr(`orig',1,4) + "/" + /* */ substr(`orig',5,2) + "/" + /* */ substr(`orig',7,2) if `f' qui gen long `newdate' = date(`x', "ymd") if `f' drop `x' `f' /* house format ddMonyyyy */ qui replace `newdate' = date(`orig', "dmy") if `newdate'==. format `newdate' %d rename `newdate' `new' end /* ------------------------------------------------------------------------- */