Faire un script qui se désinstalle proprement
#1
En tout premier lieu et afin de comprendre la suite, vous devriez vous familiariser avec le concept des namespaces.

Fonctionnement :
La procédure de désinstallation est automatiquement appelée si un .rehash est demandé.

Les binds du script sont supprimés, le namespace est détruit et toutes les ressources utilisées par le script sont ainsi libérées, ne laissant aucune trace.

Cela permet de modifier les binds de son script ou de renommer une procédure sans avoir besoin de .restart ensuite (un simple .rehash suffit), de désinstaller totalement un script sans nécessiter de .restart après qu'on l'ait enlevé du démarrage automatique dans eggdrop.conf, de travailler sur un script en cours de développement en s'assurant qu'aucune trace conflictuelle ne reste lorsque vous appliquez vos modifications avec .rehash.

Modèle :
tcl
if {[info commands NomDuNamespace::uninstall] eq "::NomDuNamespace::uninstall"} { NomDuNamespace::uninstall }
 
namespace eval NomDuNamespace {
	# binds divers (pour l'exemple)
	bind pub -|- !commande1 NomDuNamespace::pub_commande1
	bind pub -|- !commande2 NomDuNamespace::pub_commande2

	# bind de désinstallation (important)
	bind evnt - prerehash NomDuNamespace::uninstall

	# procédure de désinstallation
	proc uninstall {args} {
		putlog "Désallocation des ressources de \002NomDuScript...\002"
		# on supprime les binds qu'on a créé
		unbind pub -|- !commande1 NomDuNamespace::pub_commande1
		unbind pub -|- !commande2 NomDuNamespace::pub_commande2
		unbind evnt - prerehash NomDuNamespace::uninstall
		# on détruit le namespace et tout ce qu'il contient (variables et procédures)
		namespace delete ::NomDuNamespace
	}
}

# Procédures exemple :
proc NomDuNamespace::pub_commande1 {nick host handle chan arg} {
	...
}
 
proc NomDuNamespace::pub_commande2 {nick host handle chan arg} {
	...
}


Répondre Avertir
#2
L'idée d'un désinstalleur universel est intéressante mais avec ton exemple, ça ne fonctionnera pas si les binds comportent un namespace avec un chemin absolu ( donc commençant par :: ), ni avec des binds comportant des { }.
Je réfléchis à des solutions et je vous tiens au courant (ou si Artix veut pousser jusqu'au bout son idée il est le bienvenu Wink ).
Répondre Avertir
#3
Bah on peut simplement utiliser [namespace current] pour trouver le namespace puisque de toute évidance la procédure unsinstall sera dedans.
Répondre Avertir
#4
Desinstaller les timers
... est en fait super simple:

Il suffit de rajouter un commentaire après chaque timer créé (genre, ;#SCRIPT:Monscript)
Ensuite de tous les dégager dans la procédure de désinstallation :
tcl
foreach currentTimer [lsearch -inline -index 1 -glob [timers] "*;#SCRIPT:Monscript"] {
catch { killtimer [lindex $currentTimer 2] }
}


Répondre Avertir
#5
Petite mise à jour tardive, vu que j'avais totalement oublié l'existence de ce post.

Si votre script n'utilise pas de timers ou d'utimers, vous pouvez enlever les lignes correspondantes dans la procédure uninstall afin de ne pas encombrer inutilement votre code.
Si votre script ne déclare pas de package au moyen de package provide YOURSCRIPTNAME, vous pouvez enlever la ligne package forget YOURSCRIPTNAME.
Si votre script n'utilise pas de packs de langue (msgcat), vous pouvez enlever les lignes correspondantes.

A placer avant toute autre ligne de code dans votre script :
tcl
if {[::tcl::info::commands ::YOURNAMESPACE::uninstall] eq "::YOURNAMESPACE::uninstall"} { ::YOURNAMESPACE::uninstall }



Procédure à placer de préférence avant toute autre procédure dans votre script :
tcl
###############################################################################
# Procédure de désinstallation : le script se désinstalle totalement avant
# chaque rehash ou à chaque relecture au moyen de la commande "source" ou autre.
###############################################################################
proc ::YOURNAMESPACE::uninstall {args} {
putlog "Désallocation des ressources de YOURSCRIPTNAME..."
# Suppression des binds.
foreach binding [lsearch -inline -all -regexp [binds *[set ns [::tcl::string::range [namespace current] 2 end]]*] " \{?(::)?$ns"] {
unbind [lindex $binding 0] [lindex $binding 1] [lindex $binding 2] [lindex $binding 4]
}
# Arrêt des timers en cours.
foreach running_timer [timers] {
if { [::tcl::string::match "*[namespace current]::*" [lindex $running_timer 1]] } { killtimer [lindex $running_timer 2] }
}
# Arrêt des utimers en cours.
foreach running_utimer [utimers] {
if { [::tcl::string::match "*[namespace current]::*" [lindex $running_utimer 1]] } { killutimer [lindex $running_utimer 2] }
}
# On décharge les packs de langue.
if { [::tcl::dict::exists $::msgcat::Msgs [::msgcat::mclocale] [namespace current]] } {
::tcl::dict::unset ::msgcat::Msgs [::msgcat::mclocale] [namespace current]
}
namespace delete ::YOURNAMESPACE
# Suppression de la déclaration de package.
package forget YOURSCRIPTNAME
}



Bind :
tcl
bind evnt - prerehash ::YOURNAMESPACE::uninstall


Répondre Avertir


Atteindre :


Utilisateur(s) parcourant ce sujet : 1 visiteur(s)
Tchat 100% gratuit -Discutez en toute liberté