Overview | Index by: file name | procedure name | procedure call | annotation
pms-1.0.tm (annotations | original source)

#
#    Copyright (C) 2010 Alexandros Stergiakis <alsterg@gmail.com>
#
#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU Affero General Public License as
#    published by the Free Software Foundation, either version 3 of the
#    License, or (at your option) any later version.
#
#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU Affero General Public License for more details.
#
#    You should have received a copy of the GNU Affero General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.
#

#//#
# The "pms" module enables Package Management System (PMS) operations. It supports the [http://www.opkg.org/ opkg] PMS.
#//#

module require base 1.0
module provide pms 1.0

package require uri 1.2.1

namespace eval ::module::pms {
namespace import ::helper::* ::module::api::*

# An order-sensitive list of tuples. Each tuple is a mapping of "name" => "url".
# Tuples are in order of configuration (first configured, first in the list).
variable Repositories

proc description {} {
    return "Package Management System"
}

proc version {} {
    exec opkg --version
}

proc check {} {
    if {[lempty [auto_execok opkg]]} {
        error "opkg is not installed"
    }
}

proc reset {} {
    Global TMP_DIR
    Module pms OPKG_FILE REP_DIR OVERLAY_ROOT_DIR
    
    file mkdir $REP_DIR $OVERLAY_ROOT_DIR
    fileutil::writeFile $OPKG_FILE \
"dest root /
dest ram $TMP_DIR
lists_dir ext $REP_DIR
option overlay_root $OVERLAY_ROOT_DIR
"

    variable Repositories {}
}

proc constructor {} {
    log::Info "Loading \"pms\" module: [description]"
    
    Global CONF_DIR
    parseconf pms [file join $CONF_DIR "pms.conf"]
    
    check

    reset

    # Finally load Command Specs
    sysconf loadspecs "modules/pms/pms.specs"
}

proc destructor {} {
    # First unload Command Specs
    sysconf remove "pms"
    
    reset
}

################
# Handlers
################

command ShPackageList {cmdline argstart sid out no arguments args} {
    Module pms OPKG_FILE
    OnError Error
    
    set type [dict get $arguments TYPE]
    
    switch -exact -- $type {
        "available" {
            exec opkg -f $OPKG_FILE list
        }
        "installed" {
            exec opkg -f $OPKG_FILE list-installed
        }
        "upgradable" {
            exec opkg -f $OPKG_FILE list-upgradable
        }
    }
}

command ShPackageInfo {cmdline argstart sid out no arguments args} {
    Module pms OPKG_FILE
    OnError Error
    
    if {[dict exists $arguments PACKAGE]} {
        exec opkg -f $OPKG_FILE info [dict get $arguments PACKAGE]
    } else {
        exec opkg -f $OPKG_FILE info
    }
}

command ShPackageStatus {cmdline argstart sid out no arguments args} {
    Module pms OPKG_FILE
    OnError Error
    
    if {[dict exists $arguments PACKAGE]} {
        exec opkg -f $OPKG_FILE status [dict get $arguments PACKAGE]
    } else {
        exec opkg -f $OPKG_FILE status
    }
}

command ShPackageFiles {cmdline argstart sid out no arguments args} {
    Module pms OPKG_FILE
    OnError Error
    exec opkg -f $OPKG_FILE files [dict get $arguments PACKAGE]
}

command UpdatePackages {cmdline argstart sid out no arguments args} {
    Module pms OPKG_FILE
    OnError Critical
    exec opkg -f $OPKG_FILE update
}

proc get_force_opts {arguments} {
    set opts [list]
    if {[dict exists $arguments force]} {
        foreach f [getall FORCE] {
            switch -exact -- $f {
                "depends" { lappend opts "--force-depends" }
                "maintainer" { lappend opts "--force-maintainer" }
                "reinstall" { lappend opts "--force-reinstall" }
                "overwrite" { lappend opts "--force-overwrite" }
                "downgrade" { lappend opts "--force-downgrade" }
                "space" { lappend opts "--force-space" }
                "removal" { lappend opts "--force-removal-of-dependent-packages" }
                "autoremove" { lappend opts "--force-autoremove" }
            }
        }
    }
    return $opts
}

command PackageUpgrade {cmdline argstart sid out no arguments args} {
    Module pms OPKG_FILE
    OnError Critical
    exec opkg -f $OPKG_FILE {*}[get_force_opts $arguments] upgrade
}

command PackageInstall {cmdline argstart sid out no arguments args} {
    Module pms OPKG_FILE
    OnError Critical
    exec opkg -f $OPKG_FILE {*}[get_force_opts $arguments] install [getall PACKAGE]
}

command PackageConfigure {cmdline argstart sid out no arguments args} {
    Module pms OPKG_FILE
    OnError Critical
    exec opkg -f $OPKG_FILE {*}[get_force_opts $arguments] configure [getall PACKAGE]
}

command PackageRemove {cmdline argstart sid out no arguments args} {
    Module pms OPKG_FILE
    OnError Critical
    exec opkg -f $OPKG_FILE {*}[get_force_opts $arguments] remove [getall PACKAGE]
}

command PackageFlag {cmdline argstart sid out no arguments args} {
    Module pms OPKG_FILE    
    exec opkg -f $OPKG_FILE {*}[get_force_opts $arguments] flag [dict get $arguments FLAG] [getall PACKAGE]
}

# @assume Supported URL types by opkg are only http and ftp.
command PackageRepository {cmdline argstart sid out no arguments args} {
    Module pms OPKG_FILE
    variable Repositories
    OnError Ignore
    
    set name [dict get $arguments NAME]
    if {[llength $name] != 1 || ! [string is alnum $name]} {
        ferror "not a valid name" [getpos NAME]
    }
    if {[lsearch -exact -index 0 $Repositories $name] >= 0} {
        ferror "name is already in use by a different repository" [getpos NAME]
    }
    
    set url [uri::canonicalize [dict get $arguments URL]]
    array set url_split [uri::split $url]
    if {$url_split(scheme) ni "http ftp"} {
        ferror "unsupported URL type" [getpos URL]
    }
    
    OnError Critical
    ::fileutil::appendToFile $OPKG_FILE "src/gz $name $url\n"
    lappend Repositories [list $name $url]
    return
}

proc print_pms_configuration {} {
    variable Repositories
    set result {}
    foreach e $Repositories {
        lassign $e name url
        append result "package repository $name $url\n"
    }
    
    if {! [lempty $result]} {
        set result "#\n${result}#\n"
    }
    
    return $result
}

} ;# End of Namespace

Overview | Index by: file name | procedure name | procedure call | annotation
File generated 2010-03-13 at 22:28.