eselect Developer Reference
1.
Introduction
About eselect
eselect is a framework for simplyfying and introducing consistency to the
various foo-config and blah-update tools. It is an option for
developers who don't like reinventing the wheel, not a mandatory tool.
Note:
This document assumes some basic familiarity with eselect. Please read then
eselect User Guide in case you do not know
the basics of eselect.
|
2.
Getting Started
Introduction
When porting your application to use the eselect framework, you will
generally need to create a module. Often this can be heavily based upon an
existing module, so check to see whether there is something that does almost
what you need first (symlink handling is a good example of something that
can be copied rather than reinvented).
A Simple Module
It's easiest to illustrate by example. Here's a simplified version of
the kernel.eselect module. It has three actions, show,
list, and set, plus the standard help, usage,
and version actions, and is installed to
$(datadir)/eselect/modules/.
Code Listing 2.1: kernel.eselect code |
# -*-eselect-*- vim: ft=eselect
# Copyright 2005-2012 Gentoo Foundation
# Distributed under the terms of the GNU GPL version 2 or later
DESCRIPTION="Manage the /usr/src/linux symlink"
MAINTAINER="eselect@gentoo.org"
VERSION="20120307"
# find a list of kernel symlink targets
find_targets() {
local f
for f in "${EROOT}"/usr/src/linux-[[:digit:]]*; do
[[ -d ${f} ]] && basename "${f}"
done
}
# remove the kernel symlink
remove_symlink() {
rm "${EROOT}/usr/src/linux"
}
# set the kernel symlink
set_symlink() {
local target=$1
if is_number "${target}"; then
local targets=( $(find_targets) )
target=${targets[target-1]}
fi
[[ -z ${target} || ! -d ${EROOT}/usr/src/${target} ]] \
&& die -q "Target \"$1\" doesn't appear to be valid!"
ln -s "${target}" "${EROOT}/usr/src/linux"
}
### show action ###
describe_show() {
echo "Show the current kernel symlink"
}
do_show() {
write_list_start "Current kernel symlink:"
if [[ -L ${EROOT}/usr/src/linux ]]; then
local kernel=$(canonicalise "${EROOT}/usr/src/linux")
write_kv_list_entry "${kernel%/}" ""
else
write_kv_list_entry "(unset)" ""
fi
}
### list action ###
describe_list() {
echo "List available kernel symlink targets"
}
do_list() {
local i targets=( $(find_targets) )
write_list_start "Available kernel symlink targets:"
for (( i = 0; i < ${#targets[@]}; i++ )); do
# highlight the target where the symlink is pointing to
[[ ${targets[i]} = \
$(basename "$(canonicalise "${EROOT}/usr/src/linux")") ]] \
&& targets[i]=$(highlight_marker "${targets[i]}")
done
write_numbered_list -m "(none found)" "${targets[@]}"
}
### set action ###
describe_set() {
echo "Set a new kernel symlink target"
}
describe_set_parameters() {
echo "<target>"
}
describe_set_options() {
echo "target : Target name or number (from 'list' action)"
}
do_set() {
[[ -z $1 ]] && die -q "You didn't tell me what to set the symlink to"
[[ $# -gt 1 ]] && die -q "Too many parameters"
if [[ -L ${EROOT}/usr/src/linux ]]; then
# existing symlink
remove_symlink || die -q "Couldn't remove existing symlink"
set_symlink "$1" || die -q "Couldn't set a new symlink"
elif [[ -e ${EROOT}/usr/src/linux ]]; then
# we have something strange
die -q "${EROOT}/usr/src/linux exists but is not a symlink"
else
set_symlink "$1" || die -q "Couldn't set a new symlink"
fi
}
|
As you can see, the format is fairly similar to that of an ebuild – it is
a bash script which is run in a special environment. This is intentional.
There are DESCRIPTION and VERSION variables globally which are used by
eselect and some of the default action handlers, and a series of
functions.
Warning:
In ebuilds, global scope code can cause problems. In eselect modules,
global scope code is absolutely forbidden. Your module will
be sourced for tasks other than running your actions. For example, if
eselect modules list is executed, your module will be sourced to
obtain the description. Any code being run here would be a very bad thing.
|
Unlike ebuilds, the function names are not fixed. Any function whose name
starts with do_ is considered to be an action implementation.
It is conventional to have a describe_ function for every do_
function that gives a short description of the function – this is used for
eselect modulename help, for example.
The describe_actions_options and describe_action_parameters
functions are optional.
All eselect modules are required to support the ROOT variable. For prefix
support, variables EPREFIX and EROOT are also defined and have the same
meaning as in ebuilds.
(These two variables appeared in eselect-1.2.)
Note:
If eselect is invoked as foo-config or foo-update (for
example, via a symlink), it will automatically execute the foo module.
|
All modules contributed to eselect should have a header indicating
copyright. This must be an exact copy of the header in the above example
(except for the years, of course).
Standard Action Names
The following list contains suggested allowed names for actions. If there is
no suitable name on the list for your task, it is best to ask for the list
to be updated – for consistency, it would be nice to have a standardised
list of action names.
- help
- Display a help message. Automatic.
- usage
- Display a usage message. Automatic.
- version
- Display the current version. Automatic.
- show
-
Used to display the current provider of a symlink, or the currently
installed module, or the current status.
- list
-
Used to display all available providers of a symlink, or all available
modules.
- set
- Used to set a new provider or a symlink.
- enable
- Used to enable an optional feature.
- disable
- Used to disable an optional feature.
- scan
- Read information off the current filesystem.
- update
-
Used to automatically select a new provider for a symlink (as opposed to
set, which generally takes a parameter manually selecting the
provider) or to gather system information that is vital to further
actions.
Note:
You can override the help, usage and version actions.
They are provided by default by lib/default.eselect. You should
only do this with a good reason. Removing them is not a good idea,
eselect assumes that they exist.
|
3.
Utility Functions
Introduction
eselect provides many utility functions. These are useful for standardised
output formatting. Where possible, these should be used, especially for
output. If a standard function is not available for the output format
required, consider implementing one.
The following categories of function are available by default:
To use any of the other functions, you have to first inherit the
corresponding library file.
General Utility Functions
These are implemented in libs/core.bash.
- die
-
The die function (which, unlike its ebuild counterpart, can
be called from within subshells) is used to exit with a fatal error.
It should be invoked as die -q "Message to display". If the
-q is not provided, a stacktrace will be displayed – this should
never happen because of user input error, only abnormal conditions.
- check_do
-
The check_do utility function checks that the first parameter is
a function, and then calls it with any additional parameters as its
arguments. If the function does not exist, die is called. Again,
this is mostly internal.
- do_action
-
The do_action utility function is the correct way to call a utility
function which is defined in another module. The first parameter is the
action, additional parameters are passed as arguments.
- inherit
-
The inherit function sources eselect library files based on their
name. In order to source the file libs/foo.bash you have to
add inherit foo in global scope of your module.
- sed
-
The sed function is a wrapper around GNU sed.
Output Utility Functions
These are implemented in libs/output.bash
- write_error_msg
-
The write_error_msg function displays an error message in the
standard format. It is similar to eerror.
- write_warning_msg
-
The write_warning_msg function displays a warning message in the
standard format. It is similar to ewarn.
- The write_list_ family of functions
-
To display a list, the write_list_ family of functions should be
used. If -p is passed as the first argument to these functions,
plain highlighting is used.
- write_list_start
-
Lists should always start with a header, which can be displayed using
write_list_start The Header.
- write_numbered_list_entry
-
To display a numbered list, the write_numbered_list_entry function
should be used for each item. The first parameter is the list item number,
the second is the list item text (remember to quote this).
- write_kv_list_entry
-
To display a keyword/value list, the write_kv_list_entry function
should be used. The first parameter is the key, the second the value.
- write_numbered_list
-
The write_numbered_list function is a wrapper around
write_numbered_list_entry that handles the numbering automatically.
Each parameter passed is displayed as a numbered list item, the first with
index 1, the second with index 2 and so on.
In eselect-1.2.2 or later, the -m option can be used to specify a
negative report message that is output for an empty list.
- highlight
-
The highlight utility function can be used to emphasise some text
which is to be displayed by any of the above functions. A typical
invocation might look like that in the
code listing shown below.
- highlight_warning
-
The highlight_warning function is like highlight, but for
warnings. It displays the text in question in red.
- highlight_marker
-
To mark a list entry as active/selected, the highlight_marker
function should be used. First argument is the list entry. The function
places a highlighted star (or its second argument instead, if set) behind
the entry. A typical invocation might look like that in the
code listing shown below.
- is_output_mode
-
The is_output_mode function returns true if and only if its
parameter is equal to eselect's output mode. Currently, only the default
and brief output modes are defined, the latter corresponding to
the --brief option.
(This function appeared in eselect-1.2.6.)
- space
-
The space utility function takes a single integer parameter.
It displays that many space characters.
Code Listing 3.1: highlight example |
write_list_start "This is $(highlight list) example"
write_kv_list_entry "First" "This is the first entry"
write_kv_list_entry "$(highlight Second)" "This is the $(highlight second) entry"
write_kv_list_entry "Third" "$(highlight The end)"
|
Code Listing 3.2: highlight_marker example |
for (( i = 0; i < ${#targets[@]}; i++ )); do
[[ test_if_target_is_active ]] \
&& targets[i]=$(highlight_marker "${targets[i]}")
done
|
Test Functions
These are implemented in libs/tests.bash.
- has
-
The has utility function is like Portage's hasq. It returns
true if and only if the first parameter is equal to any of the remaining
parameters.
- is_function
-
The is_function utility function returns true if and only if its
parameter exists and is a function. This is mostly used internally, but
may have some use for modules.
- is_number
-
Returns true if and only if the parameter is a positive whole number.
Path-Manipulation Functions
These are implemented in libs/path-manipulation.
- basename
-
The basename function is a transparent bash-only replacement for
the external basename application.
- dirname
-
The dirname function is a transparent bash-only replacement for
the external dirname application.
- canonicalise
-
The canonicalise function is a wrapper to either GNU
readlink -f or realpath.
- relative_name
-
The relative_name function converts a path name (passed as its
first argument) to be relative to a directory (second argument).
This can be used to generate a relative symlink from absolute paths.
(This function appeared in eselect-1.2.4.)
Manipulation Functions
These are implemented in libs/manip.bash.
- svn_date_to_version
-
If your module is kept in a CVS or subversion repository, then the
svn_date_to_version function can be used instead of manually
keeping track of VERSION. It is safe to use in global scope. The canonical
usage is as shown in the code listing
below.
Code Listing 3.3: svn_date_to_version usage |
SVN_DATE='$Date: $'
VERSION=$(svn_date_to_version "${SVN_DATE}")
svn propset svn:keywords "Date" modules/foo.eselect
|
Configuration Functions
These are implemented in libs/config.bash.
- store_config
-
The store_config function saves a key/value pair in a given
configuration file which is passed as first argument. This file is
a bash script consisting only of key/value pairs and should not be
altered manually. Comments in the file will be deleted each time
store_config is called. The function is invoked as
store_config filename key value.
- load_config
-
The load_config function loads a stored value from the module's
configuration file. It is invoked as load_config filename key and
prints the associated value.
- append_config
-
The append_config function adds an item to an already
stored value in the modules configuration file. It uses
load_config/store_config internally and should be
invoked as append_config filename key item. Note that the
item will not be appended if it occurs in the key's value already.
Multilib Functions
These are implemented in libs/multilib.bash.
- list_libdirs
-
The list_libdirs function returns a set of valid libdirs for the
used architecture. By default it uses /etc/ld.so.conf to
obtain all the valid libdirs. If this fails due to a missing or broken
file, this function uses uname to determine the architecture.
Package-Manager Functions
These are implemented in libs/package-manager.bash.
- arch
-
The arch function returns the correct value of ${ARCH} for the
current system. If the package manager cannot provide this information,
arch falls back to a uname -m and uname -s based
lookup-table.
- envvar
-
The envvar function retrieves the contents of a
configuration-environment variable for a given package. The syntax
is envvar ${package-name} ${var-name}.
- best_version
-
The best_version function returns the highest available version for
a given package dep atom.
- has_version
-
The has_version function checks whether a given versioned package
dep atom is installed.
- get_repositories
-
The get_repositories function returns a list of repositories known
to the package manager.
- get_repo_news_dir
-
The get_repo_news_dir function returns the directory where to find
GLEP 42 news items for a given repository.
The contents of this document, unless otherwise expressly stated, are licensed under the CC-BY-SA-2.5 license. The Gentoo Name and Logo Usage Guidelines apply.
|