Index: openacs-4/packages/acs-admin/www/apm/build-repository.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-admin/www/apm/Attic/build-repository.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-admin/www/apm/build-repository.tcl 4 Oct 2003 03:03:29 -0000 1.1 @@ -0,0 +1,68 @@ +ad_page_contract { + Build package repository. +} + +# TODO: anonymous cvs export the packages with a given CVS tag corresponding to the channel +# (channel-5-0-oracle, channel-5-1-postgresql, etc.) + + + +##### +# +# Read all package .info files, building manifest file +# +##### +set channel "[db_type]-5-0" + +set repository_dir "/web/lars/www/repository/$channel/" +set repository_url "http://lars.cph02.collaboraid.net/repository/$channel/" + +append manifest {} \n + +foreach spec_file [apm_scan_packages "[acs_root_dir]/packages"] { + with_catch errmsg { + array set version [apm_read_package_info_file $spec_file] + + append manifest { } {} \n + + append manifest { } {} [ad_quotehtml $version(package.key)] {} \n + append manifest { } {} [ad_quotehtml $version(name)] {} \n + append manifest { } {} [ad_quotehtml $version(package-name)] {} \n + append manifest { } {} [ad_quotehtml $version(package.type)] {} \n + + set apm_file "${repository_dir}${version(package.key)}-${version(name)}.apm" + + set cmd [list exec [apm_tar_cmd] cf - 2>/dev/null] + foreach file [apm_get_package_files -all_db_types -package_key $version(package.key)] { + lappend cmd -C "[acs_root_dir]/packages" + lappend cmd "$version(package.key)/$file" + } + + lappend cmd "|" [apm_gzip_cmd] -c ">" $apm_file + eval $cmd + + set apm_url "${repository_url}${version(package.key)}-${version(name)}.apm" + + append manifest { } {} $apm_url {} \n + foreach elm $version(provides) { + append manifest { } "" \n + } + + foreach elm $version(requires) { + append manifest { } "" \n + } + + append manifest { } {} \n + } { + global errorInfo + ns_log Error "Error while checking package info file $spec_file: $errmsg\n$errorInfo" + } +} +append manifest {} \n + +set fw [open "${repository_dir}manifest.xml" w] +puts $fw $manifest +close $fw + +ns_return 200 text/html "OK" + Index: openacs-4/packages/acs-admin/www/install/index.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-admin/www/install/index.adp,v diff -u -r1.2 -r1.3 --- openacs-4/packages/acs-admin/www/install/index.adp 2 Oct 2003 20:26:38 -0000 1.2 +++ openacs-4/packages/acs-admin/www/install/index.adp 4 Oct 2003 03:03:29 -0000 1.3 @@ -2,6 +2,20 @@ @page_title;noquote@ @context;noquote@ +

Install from OpenACS Repository

+ +

+ » Install new application +

+ +

+ » Install new service +

+ +

+ » Upgrade your system +

+

Install from local file system

@@ -16,6 +30,8 @@ » Upgrade your system

+ +

Already Installed Packages

Index: openacs-4/packages/acs-admin/www/install/index.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-admin/www/install/index.tcl,v diff -u -r1.4 -r1.5 --- openacs-4/packages/acs-admin/www/install/index.tcl 2 Oct 2003 20:28:22 -0000 1.4 +++ openacs-4/packages/acs-admin/www/install/index.tcl 4 Oct 2003 03:03:29 -0000 1.5 @@ -55,8 +55,19 @@ } -set local_install_url "local-install" +set local_install_url "install" -set local_service_install_url [export_vars -base "local-install" { { package_type apm_service } }] +set local_service_install_url [export_vars -base "install" { { package_type apm_service } }] -set local_upgrade_url [export_vars -base "local-install" { { package_type all } { upgrade_p 1 } }] +set local_upgrade_url [export_vars -base "install" { { package_type all } { upgrade_p 1 } }] + + + +set channel "[db_type]-5-0" +set repository_url "http://lars.cph02.collaboraid.net/repository/$channel/" + +set remote_install_url [export_vars -base "install" { repository_url }] + +set remote_service_install_url [export_vars -base "install" { { package_type apm_service } repository_url }] + +set remote_upgrade_url [export_vars -base "install" { { package_type all } { upgrade_p 1 } repository_url }] Index: openacs-4/packages/acs-admin/www/install/install-2.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-admin/www/install/install-2.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-admin/www/install/install-2.adp 4 Oct 2003 03:03:29 -0000 1.1 @@ -0,0 +1,34 @@ + + @page_title;noquote@ + @context;noquote@ + + + +

We're sorry. Some packages which are required in order to + install the packages you want could not be found.

+ +
+ + +

The packages you want to install require some other + packages. These have been added to the list, and are marked + below.

+
+ +

This is the packagelist of packages we are going to install.

+ +

Please click the link below to begin installation.

+
+ +

+ + +

+ » Install above packagepackages +

+
+ + +

Please hit the Back button in your browser and go back and remove the packages we cannot install.

+ +
Index: openacs-4/packages/acs-admin/www/install/install-2.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-admin/www/install/install-2.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-admin/www/install/install-2.tcl 4 Oct 2003 03:03:29 -0000 1.1 @@ -0,0 +1,114 @@ +ad_page_contract { + Install packages - dependency check +} { + package_key:multiple + {repository_url ""} +} + +if { [llength $package_key] == 0 } { + ad_returnredirct . + ad_script_abort +} + + +##### +# +# Check dependencies +# +##### + +apm_get_package_repository -repository_url $repository_url -array repository + +array set result [apm_dependency_check_new \ + -repository_array repository \ + -package_keys $package_key] + +switch $result(status) { + ok { + set continue_url [export_vars -base "install-3" { repository_url }] + ad_set_client_property acs-admin install $result(install) + set page_title "Confirm" + } + failed { + set page_title "Missing Required Packages" + } + default { + error "Bad status returned from apm_depdendency_check_new: '$result(status)'" + } +} + +if { ![empty_string_p $repository_url] } { + set parent_page_title "Install From OpenACS Repository" +} else { + set parent_page_title "Install From Local File System" +} + + +set context [list [list "." "Install Software"] [list "install" $parent_page_title] $page_title] + + + +##### +# +# Build list to display to user +# +##### + +# Tells us whether there are any added or problematic packages in the list +set problems_p 0 +set extras_p 0 + +array set failed $result(failed) + +multirow create install package_key version_name package_name comment extra_p + +foreach key $result(packages) { + set extra_p [expr [lsearch $package_key $key] == -1] + if { $extra_p } { + set extras_p 1 + } + + if { [info exists failed($key)] } { + set problems_p 1 + set comments {} + foreach elm $failed($key) { + lappend comments "[lindex $elm 0] [lindex $elm 1]" + } + set comment "Requires [join $comments "; "]" + } else { + set comment {} + } + + array unset version + array set version $repository($key) + + multirow append install \ + $key \ + $version(name) \ + $version(package-name) \ + $comment \ + $extra_p +} + +template::list::create \ + -name install \ + -multirow install \ + -elements { + package_name { + label "Package" + } + version_name { + label "Version" + } + comment { + label "Error Message" + hide_p {[ad_decode $problems_p 1 0 1]} + } + extra_p { + label "Added" + display_eval {[ad_decode $extra_p 1 "*" ""]} + hide_p {[ad_decode $extras_p 1 0 1]} + html { align center } + } + } + Index: openacs-4/packages/acs-admin/www/install/install-3.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-admin/www/install/install-3.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-admin/www/install/install-3.tcl 4 Oct 2003 03:03:29 -0000 1.1 @@ -0,0 +1,123 @@ +ad_page_contract { + Install packages -- actual installation + + @param install Tcl list of packages to install in the order in which they should be installed +} { + {repository_url ""} +} + + +##### +# +# Display progress bar +# +##### + + +ad_progress_bar_begin \ + -title "Installing packages..." \ + -message_1 "Installing packages, please wait ..." \ + -message_2 "We will continue automatically when installation is complete." + + +##### +# +# Get packages to install +# +##### + +apm_get_package_repository -repository_url $repository_url -array repository + +set install [ad_get_client_property acs-admin install] + +if { [llength $install] == 0 } { + ns_log Notice "install-3.tcl: Nothing to install. Is this a double-click?" +} + +# We unset the client property so we won't install these packages twice +ad_set_client_property acs-admin install {} + + + + +##### +# +# Install packages +# +##### + +set success_p 1 + +foreach package_key $install { + ns_log Notice "Installing $package_key" + + array unset version + array set version $repository($package_key) + + if { [exists_and_not_null version(download_url)] } { + set spec_file [apm_load_apm_file -url $version(download_url)] + set package_path "[apm_workspace_install_dir]/$package_key" + } else { + set spec_file $version(path) + set package_path "[acs_root_dir]/packages" + } + + set final_version_name $version(name) + + if { [apm_package_version_installed_p $version(package.key) $version(name)] } { + # Already installed. + + # Enable this version, in case it's not already enabled + if { ![apm_package_enabled_p $version(package.key)] } { + ns_log Notice "Package $version(package.key) $version(name) is already installed but not enabled, enabling" + apm_version_enable -callback apm_dummy_callback [apm_highest_version $version(package.key)] + } else { + ns_log Notice "Package $version(package.key) $version(name) is already installed and enabled, skipping" + } + continue + } + + # Determine if we are upgrading or installing. + if { [apm_package_upgrade_p $package_key $final_version_name] == 1} { + ns_log Debug "Upgrading package [string totitle $version(package-name)] to $final_version_name." + set upgrade_p 1 + set initial_version_name [apm_highest_version $package_key] + } else { + set upgrade_p 0 + set initial_version_name "" + } + + # Find out which script is appropriate to be run. + set data_model_files [concat \ + [apm_data_model_scripts_find \ + -upgrade_from_version_name $initial_version_name \ + -upgrade_to_version_name $final_version_name \ + -package_path $package_path \ + $package_key] \ + [apm_ctl_files_find -package_path $package_path $package_key]] + + # Install the packages -- this actually copies the files into the right place in the file system and backs up any old files + set version_id [apm_package_install \ + -enable \ + -package_path $package_path \ + -load_data_model \ + -data_model_files $data_model_files \ + $spec_file] + + if { $version_id == 0 } { + # Installation of the package failed and we shouldn't continue with installation + # as there might be packages depending on the failed package. Ideally we should + # probably check for such dependencies and continue if there are none. + set success_p 0 + } +} + +##### +# +# Done +# +##### + +ad_progress_bar_end -url [export_vars -base install-4 { repository_url success_p }] + + Index: openacs-4/packages/acs-admin/www/install/install-4.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-admin/www/install/install-4.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-admin/www/install/install-4.adp 4 Oct 2003 03:03:29 -0000 1.1 @@ -0,0 +1,15 @@ + + @page_title;noquote@ + @context;noquote@ + +

Done installing packages.

+ + +

Unfortunately, we had some errors. Please check your server error log or contact your system administrator.

+
+ +

+ » Please restart your server +

+
+ Index: openacs-4/packages/acs-admin/www/install/install-4.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-admin/www/install/install-4.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-admin/www/install/install-4.tcl 4 Oct 2003 03:03:29 -0000 1.1 @@ -0,0 +1,16 @@ +ad_page_contract { + Install from local file system +} { + {repository_url ""} + {success_p 0} +} + +if { ![empty_string_p $repository_url] } { + set parent_page_title "Install From OpenACS Repository" +} else { + set parent_page_title "Install From Local File System" +} +set page_title "Installation Complete" + +set context [list [list "." "Install Software"] [list "install" $parent_page_title] $page_title] + Index: openacs-4/packages/acs-admin/www/install/install.adp =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-admin/www/install/install.adp,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-admin/www/install/install.adp 4 Oct 2003 03:03:29 -0000 1.1 @@ -0,0 +1,21 @@ + + @page_title;noquote@ + @context;noquote@ + + + +

No packages on your system need upgrading.

+
+ + +

There are no un-installed applications in your file system.

+
+ +

There are no un-installed applications in the OpenACS repository.

+
+
+

» Go back to software installation + + +

+ Index: openacs-4/packages/acs-admin/www/install/install.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-admin/www/install/install.tcl,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ openacs-4/packages/acs-admin/www/install/install.tcl 4 Oct 2003 03:03:29 -0000 1.1 @@ -0,0 +1,107 @@ +ad_page_contract { + Install from local file system +} { + {package_type "apm_application"} + {upgrade_p 0} + {repository_url ""} +} + + +if { ![empty_string_p $repository_url] } { + set page_title "Install From OpenACS Repository" +} else { + set page_title "Install From Local File System" +} + +set context [list [list "." "Install Software"] $page_title] + + +##### +# +# Get list of packages available for install/upgrade +# +##### + +apm_get_installed_versions -array installed_versions +set upgrades_p 0 +array set package [list] + +apm_get_package_repository -repository_url $repository_url -array repository + +foreach package_key [array names repository] { + array unset version + array set version $repository($package_key) + + if { [string equal $package_type "all"] || [string equal $version(package.type) $package_type] } { + set package_key $version(package.key) + + # If in upgrade mode, only add to list if it's an upgrade + if { !$upgrade_p || [string $version(install_type) upgrade] } { + set package([string toupper $version(package-name)]) \ + [list \ + $version(package.key) \ + $version(package-name) \ + $version(name) \ + $version(package.type) \ + $version(install_type)] + } + } +} + + +##### +# +# Output the list +# +##### + +# Sort the list alphabetically (in case package_name and package_key doesn't sort the same) +multirow create packages package_key package_name version_name package_type install_type +foreach name [lsort -ascii [array names package]] { + set row $package($name) + multirow append packages \ + [lindex $row 0] \ + [lindex $row 1] \ + [lindex $row 2] \ + [lindex $row 3] \ + [lindex $row 4] +} + +multirow extend packages install_url +multirow foreach packages { + set install_url [export_vars -base install-2 { package_key repository_url }] +} + +# Build the list-builder list +template::list::create \ + -name packages \ + -multirow packages \ + -key package_key \ + -bulk_actions { + "Install checked applications" "install-2" "Install checked applications" + } \ + -bulk_action_export_vars { + repository_url + } \ + -elements { + package_name { + label "Application" + } + version_name { + label "Version" + } + upgrade { + label "Upgrade" + hide_p {[ad_decode $upgrades_p 1 0 1]} + display_eval {[ad_decode $install_type "upgrade" "Upgrade" ""]} + } + install { + label "Install" + link_url_col install_url + link_html { title "Install single application" } + display_template {Install} + } + } + + + Fisheye: Tag 1.4 refers to a dead (removed) revision in file `openacs-4/packages/acs-admin/www/install/local-install-2.adp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1.5 refers to a dead (removed) revision in file `openacs-4/packages/acs-admin/www/install/local-install-2.tcl'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1.9 refers to a dead (removed) revision in file `openacs-4/packages/acs-admin/www/install/local-install-3.tcl'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1.3 refers to a dead (removed) revision in file `openacs-4/packages/acs-admin/www/install/local-install-4.adp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1.3 refers to a dead (removed) revision in file `openacs-4/packages/acs-admin/www/install/local-install-4.tcl'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1.3 refers to a dead (removed) revision in file `openacs-4/packages/acs-admin/www/install/local-install.adp'. Fisheye: No comparison available. Pass `N' to diff? Fisheye: Tag 1.5 refers to a dead (removed) revision in file `openacs-4/packages/acs-admin/www/install/local-install.tcl'. Fisheye: No comparison available. Pass `N' to diff? Index: openacs-4/packages/acs-tcl/tcl/apm-file-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/apm-file-procs.tcl,v diff -u -r1.27 -r1.28 --- openacs-4/packages/acs-tcl/tcl/apm-file-procs.tcl 25 Sep 2003 10:47:56 -0000 1.27 +++ openacs-4/packages/acs-tcl/tcl/apm-file-procs.tcl 4 Oct 2003 03:04:04 -0000 1.28 @@ -504,14 +504,40 @@ } ad_proc -private apm_load_apm_file { - { - -callback apm_dummy_callback - } file_path + {-callback apm_dummy_callback} + {-url {}} + {file_path {}} } { Uncompresses and loads an APM file into the filesystem. + @param url If specified, will download the APM file first. + + @return If successful, a path to the .info file of the package uncompressed + into the apm-workspace directory + } { + apm_callback_and_log $callback "
  • Downloading $url..." + if { [catch { + # Open a destination file. + set file_path [ns_tmpnam].apm + set fileChan [open $file_path w+ 0600] + # Open the channel to the server. + set httpChan [lindex [ns_httpopen GET $url] 0] + ns_log Debug "APM: Copying data from $url" + # Copy the data + fcopy $httpChan $fileChan + # Clean up. + ns_log Debug "APM: Done copying data." + close $httpChan + close $fileChan + } errmsg] } { + apm_callback_and_log $callback "Unable to download. Please check your URL.. + The following error was returned:
    [ad_quotehtml $errmsg]
    +	
    [ad_footer]" + return + } + if {![file exists $file_path]} { apm_callback_and_log $callback " The file cannot be found. Your URL or your file name is incorrect. Please verify that the file name @@ -597,10 +623,15 @@ apm_callback_and_log $callback "
  • Extracting files into the filesytem." apm_callback_and_log $callback "
  • $pretty_name $version_name ready for installation." + + # LARS: This looks odd -- package_key is not a directory # Remove the directory if it exists. - if {[file exists $package_key]} { - file delete -force $package_key - } + #if {[file exists $package_key]} { + # file delete -force $package_key + #} + exec sh -c "cd $install_path ; [apm_gunzip_cmd] -q -c $file_path | [apm_tar_cmd] xf -" 2>/dev/null + + return "${install_path}/${package_key}/${package_key}.info" } } Index: openacs-4/packages/acs-tcl/tcl/apm-install-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/apm-install-procs.tcl,v diff -u -r1.58 -r1.59 --- openacs-4/packages/acs-tcl/tcl/apm-install-procs.tcl 3 Oct 2003 15:17:27 -0000 1.58 +++ openacs-4/packages/acs-tcl/tcl/apm-install-procs.tcl 4 Oct 2003 03:04:04 -0000 1.59 @@ -208,16 +208,20 @@ spec_files } { Check dependencies of all the packages provided. - @param spec_files A list of spec files to be processed. + + @param spec_files A list of spec files to be processed. + @param initial_install Only process spec files with the initial install attribute. - @param pkg_info_all If you supply this argument, when a - requirement goes unsatisfied, instead of failing, this proc will - try to add whatever other packages are needed to the install set. The list of package keys to - add will be the third element in the list returned. + + @param pkg_info_all If you supply this argument, when a + requirement goes unsatisfied, instead of failing, this proc will + try to add whatever other packages are needed to the install set. The list of package keys to + add will be the third element in the list returned. + @return A list whose first element indicates whether dependencies were satisfied (1 if so, 0 otherwise).\ - The second element is the package info list with the packages ordered according to dependencies.\ - Packages that can be installed come first. Any packages that failed the dependency check come last. - The third element is a list of package keys on additional packages to install, in order to satisfy dependencies. + The second element is the package info list with the packages ordered according to dependencies.\ + Packages that can be installed come first. Any packages that failed the dependency check come last. + The third element is a list of package keys on additional packages to install, in order to satisfy dependencies. } { #### Iterate over the list of info files. ## Every time we satisfy another package, remove it from install_pend, and loop again. @@ -362,6 +366,245 @@ return [list 1 $install_in $extra_package_keys] } +ad_proc -private apm_dependency_check_new { + {-repository_array:required} + {-package_keys:required} +} { + Checks dependencies and finds out which packages are required to install the requested packages. + In case some packages cannot be installed due to failed dependencies, it returns which packages out + of the requested can be installed, and which packages, either originally requested or required by those, + could not be installed, and why. + + @param package_keys The list of package_keys of the packages requested to be installed. + + @param repository_array Name of an array in the caller's namespace containing the repository of + available packages as returned by apm_get_package_repository. + + @return An array list with the following elements: + +
      + +
    • status: 'ok' or 'failed'. + +
    • install: If status is 'ok', this is the complete list of packages that need to be installed, + in the order in which they need to be installed. + If status is 'failed', the list of packages that can be installed. + +
    • failed: If status is 'failed', an array list keyed by package_key of 2-tuples of + (required-uri, required-version) of requirements that could not be satisfied. + +
    • packages: The list of package_keys of the packages touched upon, either because they + were originally requested, or because they were required. If status is 'ok', + will be identical to 'install'. + + +
    + + @see apm_get_package_repository +} { + upvar 1 $repository_array repository + + array set result { + status failed + install {} + failed {} + packages {} + } + + # 'pending_packages' is an array keyed by package_key with a value of 1 for each package pending installation + # When dependencies have been met, the entry will be unset + array set pending_packages [list] + foreach package_key $package_keys { + set pending_packages($package_key) 1 + } + + # 'installed_packages' is an array keyed by package_key with a value of 1 for each package + # whose dependencies have been met and is ready to be installed + array set installed_packages [list] + + # 'provided' will keep track of what we've provided with the currently installed packages + # combined with the packages which we're already able to install + apm_get_installed_provides -array provided + + # 'required' will keep track of unsatisfied dependencies + # keyed by (service-uri) and will contain the largest version number required + array set required [list] + + # 'required_by' will keep track of unsatisfied dependencies + # keyed by (service-uri) and will contain the largest version number required + array set required_by [list] + + # Just to get us started + set updated_p 1 + + ns_log Notice "LARS: STARTING DEPENDENCY CHECK" + + # Outer loop tries to find a package from the repository to add if + # we're stuck because of unsatisfied dependencies + while { $updated_p } { + + # Keep looping over pending_package_keys, trying to add packages + # So long as we've added another, try looping again, as there may be cross-dependencies + while { $updated_p && [llength [array names pending_packages]] > 0 } { + set updated_p 0 + + # Try to add a package from + foreach package_key [array names pending_packages] { + + array unset version + array set version $repository($package_key) + + set satisfied_p 1 + foreach req $version(requires) { + set req_uri [lindex $req 0] + set req_version [lindex $req 1] + + if { ![info exists provided($req_uri)] || \ + [apm_version_names_compare $provided($req_uri) $req_version]== -1 } { + + ns_log Notice "LARS: $package_key requires $req_uri $req_version => failed" + + set satisfied_p 0 + + # Mark this as a requirement + if { ![info exists required($req_uri)] || \ + [apm_version_names_compare $required($req_uri) $req_version] == -1 } { + set required($req_uri) $req_version + } + } else { + ns_log Notice "LARS: $package_key requires $req_uri $req_version => OK" + } + } + + if { $satisfied_p } { + # Record as set to go + set installed_packages($package_key) 1 + + # Remove from pending list + unset pending_packages($package_key) + + # Add to install-list, as this is important for ordering the installation of packages correctly + lappend result(install) $package_key + + # Add to list of packages touched + lappend result(packages) $package_key + + # Record what this package provides, and remove it from the required list, if appropriate + foreach prov $version(provides) { + set prov_uri [lindex $prov 0] + set prov_version [lindex $prov 1] + # If what we provide is not already provided, or the alredady provided version is + # less than what we provide, record this new provision + if { ![info exists provided($prov_uri)] || \ + [apm_version_names_compare $provided($prov_uri) $prov_version] == -1 } { + set provided($prov_uri) $prov_version + } + # If what we provide is required, and the required version is less than what we provide, + # drop the requirement + if { [info exists required($prov_uri)] && \ + [apm_version_names_compare $required($prov_uri) $prov_version] <= 0 } { + array unset required($prov_uri) + } + } + + # Another package has been added, so repeat + set updated_p 1 + } + } + } + + # Inner loop completed. Either we're done, or there are packages that have dependencies + # not currently on the pending_package_keys list. + + set updated_p 0 + + if { [llength [array names pending_packages]] > 0 } { + # There are packages that have unsatisfied dependencies + # Those unmet requirements will be registered in the 'required' array + + # Let's find a package which satisfies at least one of the requirements in 'required' + + foreach package_key [array names repository] { + if { [info exists pending_packages($package_key)] || \ + [info exists installed_packages($package_key)] } { + # Packages already on the pending list, or already verified ok won't help us any + continue + } + + array unset version + array set version $repository($package_key) + + ns_log Notice "LARS: Considering $package_key: [array get version]" + + # Let's see if this package provides anything we need + foreach prov $version(provides) { + set prov_uri [lindex $prov 0] + set prov_version [lindex $prov 1] + + if { [info exists required($prov_uri)] && \ + [apm_version_names_compare $required($prov_uri) $prov_version] <= 0 } { + + ns_log Notice "LARS: Adding $package_key, as it provides $prov_uri $prov_version" + + # If this package provides something that's required in a version high enough + # add it to the pending list + set pending_packages($package_key) 1 + + # We've changed something + set updated_p 1 + + # Let's try for another go at installing packages + break + } + } + + # Break all the way back to installing pending packages again + if { $updated_p } { + break + } + } + } + } + + if { [llength [array names pending_packages]] == 0 } { + set result(status) ok + } else { + set result(status) failed + + array set failed [list] + + # There were problems, now be helpful + + # Find out which packages couldn't be installed and why + foreach package_key [array names pending_packages] { + array unset version + array set version $repository($package_key) + + # Add to touched upon packages + lappend result(packages) $package_key + + # Find unsatisfied requirements + foreach req $version(requires) { + set req_uri [lindex $req 0] + set req_version [lindex $req 1] + if { ![info exists provided($req_uri)] || \ + [apm_version_names_compare $provided($req_uri) $req_version] == -1 } { + lappend failed($package_key) [list $req_uri $req_version] + if { [info exists provided($req_uri)] } { + ns_log Notice "LARS: Failed dependency: $package_key requires $req_uri $req_version, but we only provide $provided($req_uri)" + } else { + ns_log Notice "LARS: Failed dependency: $package_key requires $req_uri $req_version, but we don't have it" + } + } + } + } + + set result(failed) [array get failed] + } + + return [array get result] +} + ad_proc -private apm_load_catalog_files { -upgrade:boolean package_key @@ -1191,6 +1434,7 @@ } ad_proc -private apm_ctl_files_find { + {-package_path ""} package_key } { @@ -1203,7 +1447,7 @@ } { - set file_list [apm_get_package_files -file_types [list ctl_file] -package_key $package_key] + set file_list [apm_get_package_files -file_types [list ctl_file] -package_path $package_path -package_key $package_key] set files [list] foreach path $file_list { @@ -1365,29 +1609,40 @@ ns_log Notice "Finished mounting of core packages" } -ad_proc -private apm_version_name_compare { - version_name_1 - version_name_2 -} { - Compare two version names (e.g. '1.2d3' and '3.5b') as for which comes before which. The example here would return -1. - @param version_name_1 the first version name - @param version_name_2 the second version name - @return 1 if version_name_1 comes after version_name_2, 0 if they are the same, -1 if version_name_1 comes before version_name_2. - @author Lars Pind -} { - db_1row select_sortable_versions {} - return [string compare $sortable_version_1 $sortable_version_2] -} - ad_proc -public apm_version_names_compare { version_name_1 version_name_2 } { - Compare two version names (e.g. '1.2d3' and '3.5b') as for which comes before which. The example here would return -1. + Compare two version names for which is earlier than the other. + + Example: + +
      + +
    • apm_version_names_compare "1.2d3" "3.5b" => -1 + +
    • apm_version_names_compare "3.5b" "3.5b" => 0 + +
    • apm_version_names_compare "3.5b" "1.2d3" => 1 + +
    + @param version_name_1 the first version name + @param version_name_2 the second version name - @return 1 if version_name_1 comes after version_name_2, 0 if they are the same, -1 if version_name_1 comes before version_name_2. + @return + +
      + +
    • -1: the first version is smallest + +
    • 0: they're identical + +
    • 1: the second version is smallest + +
    + @author Lars Pind } { db_1row select_sortable_versions {} @@ -1481,6 +1736,129 @@ } +ad_proc -private apm_get_package_repository { + {-repository_url ""} + {-array:required} +} { + Gets a list of packages available for install from either a remote package repository + or the local file system. + + @param repository_url The URL for the repository channel to get from, or the empty string to + seach the local file system instead. + + @param array Name of an array where you want the repository stored. It will be keyed by package-key, + and each entry will be an array list list what's returned by apm_read_package_info_file. + + @see apm_read_package_info_file + + @author Lars Pind (lars@collaboraid.biz) +} { + # This will be a list of array-lists of packages available for install + upvar 1 $array repository + + apm_get_installed_versions -array installed_version + + if { ![empty_string_p $repository_url] } { + set manifest_url "${repository_url}manifest.xml" + + # See if we already have it in a client property + set manifest [ad_get_client_property acs-admin [string range $manifest_url end-49 end]] + + if { [empty_string_p $manifest] } { + # Nope, get it now + array set result [ad_httpget -url $manifest_url] + + if { ![string equal $result(status) 200] } { + error "Couldn't get the package list. Please try again later." + } + + set manifest $result(page) + + # Store for subsequent requests + ad_set_client_property acs-admin [string range $manifest_url end-49 end] $manifest + } + + # Parse manifest + + set tree [xml_parse -persist $manifest] + set root_node [xml_doc_get_first_node $tree] + + foreach package_node [xml_node_get_children_by_name $root_node "package"] { + array unset version + set version(package.key) [xml_node_get_content [xml_node_get_first_child_by_name $package_node "package-key"]] + set version(name) [xml_node_get_content [xml_node_get_first_child_by_name $package_node "version"]] + set version(package-name) [xml_node_get_content [xml_node_get_first_child_by_name $package_node "pretty-name"]] + set version(package.type) [xml_node_get_content [xml_node_get_first_child_by_name $package_node "package-type"]] + set version(download_url) [xml_node_get_content [xml_node_get_first_child_by_name $package_node "download-url"]] + + foreach dependency_type { provides requires } { + set version($dependency_type) {} + foreach dependency_node [xml_node_get_children_by_name $package_node "$dependency_type"] { + lappend version($dependency_type) \ + [list [xml_node_get_attribute $dependency_node "url"] \ + [xml_node_get_attribute $dependency_node "version"]] + } + } + + if { ![info exists installed_version($version(package.key))] } { + # Package is not installed + set version(install_type) install + } elseif { [string equal $version(name) $installed_version($version(package.key))] || \ + [apm_higher_version_installed_p $version(package.key) $version(name)] != 1 } { + # This version or a higher version already installed + set version(install_type) already_installed + } else { + # Earlier version installed, this is an upgrade + set version(install_type) upgrade + } + + ns_log Notice "LARS: $version(package.key) = $version(install_type) -- [array get installed_version]" + + if { ![string equal $version(install_type) already_installed] } { + set repository($version(package.key)) [array get version] + } + } + } else { + # Parse spec files + foreach spec_file [apm_scan_packages "[acs_root_dir]/packages"] { + with_catch errmsg { + array unset version + array set version [apm_read_package_info_file $spec_file] + + # If the package doesn't support this RDBMS, it's not really available for install + if { [apm_package_supports_rdbms_p -package_key $version(package.key)] } { + + if { ![info exists installed_version($version(package.key))] } { + # Package is not installed + set version(install_type) install + } elseif { [string equal $version(name) $installed_version($version(package.key))] || \ + [apm_higher_version_installed_p $version(package.key) $version(name)] != 1 } { + # This version or a higher version already installed + set version(install_type) already_installed + } else { + # Earlier version installed, this is an upgrade + set version(install_type) upgrade + } + + if { ![string equal $version(install_type) already_installed] } { + set repository($version(package.key)) [array get version] + } + } + } { + # We don't error hard here, because we don't want the whole process to fail if there's just one + # package with a bad .info file + global errorInfo + ns_log Error "Error while checking package info file $spec_file: $errmsg\n$errorInfo" + } + } + } +} + + + + + + ############## # # Deprecated Procedures Index: openacs-4/packages/acs-tcl/tcl/apm-procs.tcl =================================================================== RCS file: /usr/local/cvsroot/openacs-4/packages/acs-tcl/tcl/apm-procs.tcl,v diff -u -r1.57 -r1.58 --- openacs-4/packages/acs-tcl/tcl/apm-procs.tcl 3 Oct 2003 10:13:43 -0000 1.57 +++ openacs-4/packages/acs-tcl/tcl/apm-procs.tcl 4 Oct 2003 03:04:04 -0000 1.58 @@ -1504,6 +1504,56 @@ db_exec_plsql apm_package_instance_delete {} } +ad_proc -public apm_get_installed_versions { + -array:required +} { + Sets the current installed version of packages installed on this system + in an array keyed by package_key. + + @param array Name of array in caller's namespace where you want this set +} { + upvar 1 $array installed_version + + db_foreach installed_packages { + select package_key, version_name + from apm_package_versions + where enabled_p = 't' + } { + set installed_version($package_key) $version_name + } +} + +ad_proc -public apm_get_installed_provides { + -array:required +} { + Sets the dependencies provided by the packages installed on this system + in an array keyed by dependency service-uri. + + @param array Name of array in caller's namespace where you want this set +} { + upvar 1 $array installed_provides + + # All packages provides themselves + apm_get_installed_versions -array installed_provides + + # Now check what the provides clauses say + db_foreach installed_provides { + select service_uri, + service_version + from apm_package_dependencies d, + apm_package_versions v + where d.dependency_type = 'provides' + and d.version_id = v.version_id + and v.enabled_p = 't' + } { + if { ![info exists installed_provides($service_uri)] || \ + [apm_version_names_compare $installed_provides($service_uri) $service_version] == -1 } { + set installed_provides($service_uri) $service_version + } + } +} + + ## ## Logging ##