Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
85 changes: 78 additions & 7 deletions libmport/install_primative.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@

static char **get_dependencies(mportInstance *mport, mportPackageMeta *pack);
static char *find_file_with_prefix(const char *dir, const char *prefix);
static /*@null@*/ /*@only@*/ mportPackageMeta **lookup_current_os_installed(
/*@notnull@*/ mportInstance *, /*@notnull@*/ mportPackageMeta *,
/*@out@*/ mportPackageMeta **);

#define GOTO_CLEANUP_ON_MPORT_ERR(expr) \
do { \
Expand Down Expand Up @@ -144,12 +147,60 @@ find_file_with_prefix(const char *dir, const char *prefix)
return found_file;
}

/*
* Return the installed package(s) matching pkg->name, and set *match to the
* single entry whose os_release equals the running system's. The package name
* is not unique in the master DB (the same name can be installed under a
* different os_release), so scan every returned row rather than assuming the
* current-OS entry is first. Returns NULL (and sets *match to NULL) when the
* package is not installed under the current OS release; the caller owns the
* returned vector, and *match is an observer into it.
*/
static mportPackageMeta **
lookup_current_os_installed(mportInstance *mport, mportPackageMeta *pkg, mportPackageMeta **match)
{
mportPackageMeta **installed = NULL;
char *system_os_release;
int i;

*match = NULL;

if (mport_pkgmeta_search_master(mport, &installed, "pkg=%Q", pkg->name) != MPORT_OK)
return NULL;
if (installed == NULL)
return NULL;

system_os_release = mport_get_osrelease(mport);
if (system_os_release == NULL) {
mport_pkgmeta_vec_free(installed);
return NULL;
}

for (i = 0; installed[i] != NULL; i++) {
if (installed[i]->os_release != NULL &&
strcmp(installed[i]->os_release, system_os_release) == 0) {
*match = installed[i];
break;
}
}

free(system_os_release);

if (*match == NULL) {
mport_pkgmeta_vec_free(installed);
return NULL;
}

return installed;
}

MPORT_PUBLIC_API int
mport_install_primative(
mportInstance *mport, const char *filename, const char *prefix, mportAutomatic automatic)
{
mportBundleRead *bundle = NULL;
mportPackageMeta **already_installed = NULL;
mportPackageMeta *current_installed = NULL;
mportPackageMeta **pkgs = NULL;
mportPackageMeta *pkg = NULL;
int i;
Expand Down Expand Up @@ -184,19 +235,39 @@ mport_install_primative(
goto cleanup;
}

/* if we previously installed it and want to force, allow it.
In this case, automatic flag from previous install not honored
*/
if (mport_check_preconditions(mport, pkgs[0], MPORT_PRECHECK_INSTALLED) !=
MPORT_OK) {
if (mport->force) {
mport_delete_primative(mport, pkgs[0], 1);
/*
* Only packages installed under the current OS release are treated
* as update/reinstall candidates here. A copy installed under a
* different os_release is left for the normal install path below,
* where MPORT_PRECHECK_INSTALLED considers a differing os_release to
* be a distinct package (matching pre-existing --force behavior).
*/
already_installed = lookup_current_os_installed(mport, pkgs[0], &current_installed);
if (current_installed != NULL) {
int version_cmp =
mport_version_cmp(current_installed->version, pkgs[0]->version);

if (mport->force || version_cmp < 0) {
automatic = current_installed->automatic;
if (version_cmp < 0) {
mport_call_msg_cb(mport, "Updating %s from %s to %s.",
pkgs[0]->name, current_installed->version,
pkgs[0]->version);
}
if (mport_delete_primative(mport, current_installed, 1) !=
MPORT_OK) {
ret = mport_err_code();
goto cleanup;
}
} else {
mport_call_msg_cb(mport, "%s-%s: already installed.", pkgs[0]->name,
pkgs[0]->version);
ret = MPORT_OK;
goto cleanup;
}

mport_pkgmeta_vec_free(already_installed);
already_installed = NULL;
}

if (mport_check_preconditions(mport, pkgs[0], MPORT_PRECHECK_CONFLICTS) !=
Expand Down
4 changes: 4 additions & 0 deletions mport/mport.1
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,10 @@ package files.
If
.Fl A
is specified, mark the installed package as automatic.
If the package is already installed and the local package file contains a newer
version,
.Nm
updates it by removing the installed package and installing the local file.
For repository installs, use
.Cm install .
.It Cm annotate Op Fl a Op Fl q Fl S Ar package Ar tag
Expand Down
Loading