* Add explicit conflict-checking to the package tools. Packages can

register a list of other packages with which they conflict (via the
  -C option to pkg_create), and they will refuse to install (unless -f is
  specified) if one of the listed packages is already present.

* Update documentation for the new feature as well as fleshing out some
  existing documentation.

* Bump PKG_INSTALL_VERSION so this feature can be tested for.

Submitted by:   Sergey Matveychuk <sem@ciam.ru>
PR:             bin/47145
MFC after:      2 weeks
This commit is contained in:
kris 2003-04-17 09:56:05 +00:00
parent 52a551e4c5
commit 7ec4223664
9 changed files with 104 additions and 18 deletions

View File

@ -71,13 +71,16 @@ pkg_do(char *pkg)
int code;
PackingList p;
struct stat sb;
int inPlace;
int inPlace, conflictsfound, i, errcode;
/* support for separate pre/post install scripts */
int new_m = 0;
char pre_script[FILENAME_MAX] = INSTALL_FNAME;
char post_script[FILENAME_MAX];
char pre_arg[FILENAME_MAX], post_arg[FILENAME_MAX];
char *conflict[2];
char **matched;
conflictsfound = 0;
code = 0;
zapLogDir = 0;
LogDir[0] = '\0';
@ -248,6 +251,33 @@ pkg_do(char *pkg)
goto success; /* close enough for government work */
}
/* Now check the packing list for conflicts */
for (p = Plist.head; p != NULL; p = p->next) {
if (p->type == PLIST_CONFLICTS) {
conflict[0] = strdup(p->name);
conflict[1] = NULL;
matched = matchinstalled(MATCH_GLOB, conflict, &errcode);
free(conflict[0]);
if (errcode == 0 && matched != NULL)
for (i = 0; matched[i] != NULL; i++)
if (isinstalledpkg(matched[i])) {
warnx("package '%s' conflicts with %s", Plist.name,
matched[i]);
conflictsfound = 1;
}
continue;
}
}
if(conflictsfound) {
if(!Force) {
warnx("please use pkg_delete first to remove conflicting package(s) or -f to force installation");
code = 1;
goto bomb;
} else
warnx("-f specified; proceeding anyway");
}
/* Now check the packing list for dependencies */
for (p = Plist.head; p ; p = p->next) {
char *deporigin;

View File

@ -208,20 +208,29 @@ ftp.
.Sh TECHNICAL DETAILS
The
.Nm
utility is fairly simple. It extracts each package's "packing list"
into a special staging directory, parses it,
and then runs through the following sequence to fully extract the contents:
utility extracts each package's "packing list" into a special staging
directory in /tmp (or $PKG_TMPDIR if set), parses it, and then runs
through the following sequence to fully extract the contents of the package:
.Bl -enum
.It
Check if the package is already recorded as installed. If so,
terminate installation.
A check is made to determine if the package is already recorded as installed.
If it is, installation is terminated.
.It
A check is made to determine if the package conflicts (from
.Cm @conflicts
directives, see
.Xr pkg_create 1 )
with an already-installed package.
If it is, installation is terminated.
.It
Scan all the package dependencies (from
.Cm @pkgdep
directives, see
.Xr pkg_create 1 )
and make sure each one is met. If not, try and find the missing
dependencies' packages and auto-install them; if they can't be found
are read from the packing list.
If any of these required packages is not currently installed,
an attempt is made to find and install it;
if the missing package cannot be found or installed,
the installation is terminated.
.It
Search for any
@ -388,7 +397,9 @@ period.
.Pp
The environment variable
.Ev PKG_DBDIR
specifies an alternative location for the installed package database.
specifies an alternative location for the installed package database,
default location is
.Pa /var/db/pkg .
.Pp
The environment variables
.Ev PKG_TMPDIR

View File

@ -37,6 +37,7 @@ extern char *SrcDir;
extern char *ExcludeFrom;
extern char *Mtree;
extern char *Pkgdeps;
extern char *Conflicts;
extern char *Origin;
extern char *InstalledPkg;
extern char PlayPen[];

View File

@ -16,7 +16,7 @@ __FBSDID("$FreeBSD$");
#include "lib.h"
#include "create.h"
static char Options[] = "YNOhjvyzf:p:P:c:d:i:I:k:K:r:t:X:D:m:s:o:b:";
static char Options[] = "YNOhjvyzf:p:P:C:c:d:i:I:k:K:r:t:X:D:m:s:o:b:";
char *Prefix = NULL;
char *Comment = NULL;
@ -32,6 +32,7 @@ char *Require = NULL;
char *ExcludeFrom = NULL;
char *Mtree = NULL;
char *Pkgdeps = NULL;
char *Conflicts = NULL;
char *Origin = NULL;
char *InstalledPkg = NULL;
char PlayPen[FILENAME_MAX];
@ -78,6 +79,10 @@ main(int argc, char **argv)
Contents = optarg;
break;
case 'C':
Conflicts = optarg;
break;
case 'c':
Comment = optarg;
break;
@ -195,11 +200,11 @@ static void
usage()
{
fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n",
"usage: pkg_create [-YNOhvy] [-P pkgs] [-p prefix] [-f contents] [-i iscript]",
" [-I piscript] [-k dscript] [-K pdscript] [-r rscript] ",
" [-t template] [-X excludefile] [-D displayfile] ",
" [-m mtreefile] [-o origin] -c comment -d description ",
" -f packlist pkg-filename",
"usage: pkg_create [-YNOhvy] [-P pkgs] [-C conflicts] [-p prefix] [-f contents] ",
" [-i iscript] [-I piscript] [-k dscript] [-K pdscript] ",
" [-r rscript] [-t template] [-X excludefile] ",
" [-D displayfile] [-m mtreefile] [-o origin] ",
" -c comment -d description -f packlist pkg-filename",
" pkg_create [-YNhvy] -b pkg-name [pkg-filename]");
exit(1);
}

View File

@ -145,6 +145,22 @@ pkg_perform(char **pkgs)
printf(".\n");
}
/* Put the conflicts directly after the dependencies, if any */
if (Conflicts) {
if (Verbose && !PlistOnly)
printf("Registering conflicts:");
while (Conflicts) {
cp = strsep(&Conflicts, " \t\n");
if (*cp) {
add_plist(&plist, PLIST_CONFLICTS, cp);
if (Verbose && !PlistOnly)
printf(" %s", cp);
}
}
if (Verbose && !PlistOnly)
printf(".\n");
}
/* If a SrcDir override is set, add it now */
if (SrcDir) {
if (Verbose && !PlistOnly)

View File

@ -32,6 +32,7 @@
.Sh SYNOPSIS
.Nm
.Op Fl YNOhjvyz
.Op Fl C Ar conflicts
.Op Fl P Ar pkgs
.Op Fl p Ar prefix
.Op Fl f Ar contents
@ -142,6 +143,13 @@ executable program (or shell script). It will be invoked automatically
when the package is later installed.
It will be passed the package's name as
the first argument.
.It Fl C Ar conflicts
Set the initial package conflict list to
.Ar conflicts .
This is assumed to be a whitespace separated list of package names
and is meant as a convenient shorthand for specifying multiple
.Cm @conflicts
directives in the packing list (see PACKING LIST DETAILS section below).
.It Fl P Ar pkgs
Set the initial package dependency list to
.Ar pkgs .
@ -482,6 +490,11 @@ installed, and this package must be deinstalled before the
package is deinstalled. Multiple
.Cm @pkgdep
directives may be used if the package depends on multiple other packages.
.It Cm @conflicts Ar pkgcflname
Declare a conflict with the
.Ar pkgcflname
package, as the two packages contain references to the same files,
and so cannot co-exist on the same system.
.El
.Sh ENVIRONMENT
The environment variable

View File

@ -158,6 +158,10 @@ show_plist(const char *title, Package *plist, plist_t type, Boolean showall)
"\tdependency origin: %s\n", p->name);
break;
case PLIST_CONFLICTS:
printf(Quiet ? "@conflicts %s\n" : "Conflicts: %s\n", p->name);
break;
case PLIST_MTREE:
printf(Quiet ? "@mtree %s\n" : "\tPackage mtree file: %s\n", p->name);
break;

View File

@ -86,7 +86,7 @@
* Version of the package tools - increase only when some
* functionality used by bsd.port.mk is changed, added or removed
*/
#define PKG_INSTALL_VERSION 20020908
#define PKG_INSTALL_VERSION 20030417
#define PKG_WRAPCONF_FNAME "/var/db/pkg_install.conf"
#define main(argc, argv) real_main(argc, argv)
@ -99,8 +99,8 @@ enum _plist_t {
PLIST_FILE, PLIST_CWD, PLIST_CMD, PLIST_CHMOD,
PLIST_CHOWN, PLIST_CHGRP, PLIST_COMMENT, PLIST_IGNORE,
PLIST_NAME, PLIST_UNEXEC, PLIST_SRC, PLIST_DISPLAY,
PLIST_PKGDEP, PLIST_MTREE, PLIST_DIR_RM, PLIST_IGNORE_INST,
PLIST_OPTION, PLIST_ORIGIN, PLIST_DEPORIGIN
PLIST_PKGDEP, PLIST_CONFLICTS, PLIST_MTREE, PLIST_DIR_RM,
PLIST_IGNORE_INST, PLIST_OPTION, PLIST_ORIGIN, PLIST_DEPORIGIN
};
typedef enum _plist_t plist_t;

View File

@ -241,6 +241,8 @@ plist_cmd(const char *s, char **arg)
return PLIST_DISPLAY;
else if (!strcmp(cmd, "pkgdep"))
return PLIST_PKGDEP;
else if (!strcmp(cmd, "conflicts"))
return PLIST_CONFLICTS;
else if (!strcmp(cmd, "mtree"))
return PLIST_MTREE;
else if (!strcmp(cmd, "dirrm"))
@ -364,6 +366,10 @@ write_plist(Package *pkg, FILE *fp)
fprintf(fp, "%cpkgdep %s\n", CMD_CHAR, plist->name);
break;
case PLIST_CONFLICTS:
fprintf(fp, "%cconflicts %s\n", CMD_CHAR, plist->name);
break;
case PLIST_MTREE:
fprintf(fp, "%cmtree %s\n", CMD_CHAR, plist->name);
break;