Ticket UUID: | 1733117 | |||
Title: | auto_path changes and avail package cacheing issues | |||
Type: | Bug | Version: | obsolete: 8.5a6 | |
Submitter: | flatworm | Created on: | 2007-06-07 22:39:09 | |
Subsystem: | 39. Package Manager | Assigned To: | dgp | |
Priority: | 5 Medium | Severity: | ||
Status: | Open | Last Modified: | 2007-06-09 00:35:57 | |
Resolution: | None | Closed By: | ||
Closed on: | ||||
Description: |
Package managing code might in certain cases not notice the availability of a more recent version of a package X that was made available by modifying auto_path at runtime if package manager have already seen any version of package X at the scanning stage. How to trigger: 1) We have a package named, say, "foo" somewhere accessible via $auto_path; 2) Then by some means (usually by calling [package require something]) we cause the package manager to make its run through the $auto_path scanning the packages. After that the package manager will know that the package "foo" is available. 3) Then we add another direcroty to auto_path which makes some more recent version of the same package "foo" available to the package manager. (Use case: we want to locally override a certain package in the standard package hierarchy). 4) Then [package require foo] will fetch the original version (not the latest) since the package manager won't rescan the directories listed on auto_path. From the Tclers' chatroom: [00:14]<jenglish> kostix - the default [package unknown] handler does keep track of auto_path adjustments -- if any pkgIndex.tcl diddles with auto_path (which, really, they shouldn't, but some do anyway...) it will scan the new directories too. [00:18]<jenglish> ... but IIRC the default [package unknown] handler has some short-circuiting logic; it might stop scanning for pkgIndex.tcl files once it finds a package that satisfies the requirements. The ways to overcome the problem are: 1) Add [package forget foo] before calling [package require foo]; 2) Specify the exact version in [package require] to make [package unknown] be not happy with the version of "foo" it already known about. My poposition is to make the package manager rescan the hierarchy on any change of auto_path (may be it's worth remembering the sorted list of normalized paths from auto_path and compare it with the similar list aquired from the changed auto_path to track changes which don't really change things). Changes to auto_path are rare and probably such change in behaviour won't lead to slowdowns. P.S. This issue is also confirmed to exist in 8.4.14 and .15 | |||
User Comments: |
dgp added on 2007-06-09 00:35:57:
Logged In: YES user_id=80530 Originator: NO since I'm short on time, here's what I had to say on this in the chat: dgpre 1733117 my intent is to follow up in detail in the Tracker... [12:02]dgpbut briefly the answer is "not a bug" [12:03]kbkHmm, "not a bug" perhaps but at least surprising. [12:04]dgpprobably the most surprising thing... [12:04]dgp...is that [package require $p $requirement] does *not* make any guarantee to provide the latest version available [12:05]dgpit only promises to satisfy the requirements passed in as arguments [12:05]dgpIf some documentation somewhere says otherwise, then *that* is a bug [12:06]kbkHmmm. OK so far. Would an explicit requirement of the version that was on the new auto_path have found it? [12:06]dgpso, if an app really, really, really won't be satisfies with anything other than the very latest available, they'll have to use the lower level [package] subcommands to accomplish that for themselves [12:06]dgpI think all the tools are there. [12:06]kbk(That militates in favour of aku's practice of advancing patch levels in tcllib modules with every bugfix) [12:08]dgpif the modified auto_path makes findable a new version of a package... [12:08]dgpthat was not findable before... [12:08]dgp...then a requirement that is only satisfied by that new version, and was not satisfied by the older ones available [12:08]dgpwill find the new one, yes. [12:10]kbkok, I'm almost satisfied... although "latest available version that satisfies requirements" would make a lot of sense. [12:10]kbkOtherwise, consider an app that does [package require foo 1.0; package require bar 1.0] [12:11]kbkwhere (properly unknown to the app writer), foo does [package require grill 1.1] and bar does [package require grill 1.2]. [12:11]dgpWithout thinking it fully through, I think a custom [package unknown] handler can do this [12:17]dgpso quickly, how a cusom [package unknown] can solve the posed problem.... [12:17]dgpstart with [::tclPkgUnknown] which searches according to the value of ::auto_path... [12:18]dgpaugment it with a variable trace on ::auto_path that calls [package forget] when ::auto_path is written to. [12:18]dgpthen register this modified package finder with [package unknown] [12:18]dgpand voila, your app has the feature requested. jenglish-- I think all you need is a way to say "scan this directory for available packages _now_". [12:21]jenglish([lappend auto_path ...] just says "scan this directory for packages the next time somebody asks for a package you don't already know about", which is error-prone and order-dependent) [12:22]dgp[lappend auto_path ...; eval [package unknown] Tcl [package provide Tcl]] [12:22]dgpThat's not 100%, but it works with [tclPkgUnknown] [12:23]dgpcan't be 100% because a cusom [package unknown] handler is free to provide anything that satisfies requirements even if that means ignoring later available versions. [12:24]jenglishwait, I thought the package [package unknown] handler was only responsible for providing ifneeded scripts - not for providing the packages themselves. [12:25]dgp[package unknown] is for finding packages. [12:25]dgpwhen [package require] determines it can't satisfy requirement it knows about. [12:25]dgpThe default [package unknown], [tclPkgUnknown] goes searching for every version of every package it can find. [12:26]dgp...but other custom ones don't have to do that. [12:26]dgpThey get passed the package and requirements being sought. [12:26]jenglishSo the contract for [package unknown] handlers is: either provide the package, or register an ifneeded script that will provide the package? [12:26]dgpand are free to search less broadly with the aim to satisfy the stated requirement. [12:26]dgpFor example, the Tcl Module [package unknown] routine [12:27]dgpno [package unknown] never [package provide]s a package [12:27]dgp(assuming proper, nonabusive, usage) jenglishTFM says: "For example, if [the package-unknown handler] is 'foo bar' [...] then Tcl will execute the command 'foo bar test 2.4' *to load the package*" (emphasis mine) [12:32]dgpthat would probably be better rephrased. [12:32]dgpthe task for [foo bar test 2.4] to accomplish is to run at least one [package ifneeded foo $x] command [12:32]dgpwhere [package vsatisfies 2.4 $x] is true [12:33]jenglishRelated: calling [package forget] when auto_path changes might not be a good idea -- you don't want to forget previous [package provide]s, just the [package ifneeded]s. [12:33]dgpor to run no [package ifneeded] command at all, in the cases where no satisfaction can be had. [12:33]dgpyou would pass the package name to [package forget] [12:34]dgpthere are details to get right, you are correct. [12:34]dgpI think all the tools are available to accomplish that. [12:35]dgpwhen I get back to full time, perhaps I can offer a complet example Leaving this open since there's doc improvement likely to be useful. flatworm added on 2007-06-08 05:43:04: Logged In: YES user_id=1350198 Originator: YES Correction: I don't mean "rescan packages when auto_path changes", I mean "Invalidate the cache of known packages when auto_path changes" so that any subsequent [package require] (or whatever) make the package manager to rescan the list of packages. flatworm added on 2007-06-08 05:39:11: File Added - 232193: pkgtest.zip |
Attachments:
- pkgtest.zip [download] added by flatworm on 2007-06-08 05:39:09. [details]