From seggers@semyam.dinoco.de  Thu Jul 30 13:53:35 1998
Received: from tim.xenologics.com (tim.xenologics.com [194.77.5.24])
          by hub.freebsd.org (8.8.8/8.8.8) with ESMTP id NAA20175
          for <FreeBSD-gnats-submit@freebsd.org>; Thu, 30 Jul 1998 13:53:21 -0700 (PDT)
          (envelope-from seggers@semyam.dinoco.de)
Received: (from uucp@localhost)
	by tim.xenologics.com (8.8.5/8.8.8) with UUCP id WAA29879
	for FreeBSD-gnats-submit@freebsd.org; Thu, 30 Jul 1998 22:51:06 +0200 (MET DST)
Received: (from seggers@localhost)
	by semyam.dinoco.de (8.8.8/8.8.8) id WAA12888;
	Thu, 30 Jul 1998 22:50:20 +0200 (CEST)
	(envelope-from seggers)
Message-Id: <199807302050.WAA12888@semyam.dinoco.de>
Date: Thu, 30 Jul 1998 22:50:20 +0200 (CEST)
From: Stefan Eggers <seggers@semyam.dinoco.de>
Reply-To: seggers@semyam.dinoco.de
To: FreeBSD-gnats-submit@freebsd.org
Cc: seggers@semyam.dinoco.de
Subject: make dependencies more visible in sysinstall
X-Send-Pr-Version: 3.2

>Number:         7454
>Category:       bin
>Synopsis:       make dependencies more visible in sysinstall
>Confidential:   no
>Severity:       non-critical
>Priority:       medium
>Responsible:    jkh
>State:          closed
>Quarter:        
>Keywords:       
>Date-Required:  
>Class:          change-request
>Submitter-Id:   current-users
>Arrival-Date:   Thu Jul 30 14:00:01 PDT 1998
>Closed-Date:    Tue Feb 9 11:02:15 PST 1999
>Last-Modified:  Tue Feb  9 11:02:30 PST 1999
>Originator:     Stefan Eggers
>Release:        FreeBSD 3.0-CURRENT i386
>Organization:
none
>Environment:

	-current from last weekend.

>Description:

	Sysinstall does not mark packages added as dependencies in any
way.  One just notices they get added when one gets to really install-
ing them.

	My change makes sysinstall mark them with a D for dependency.
Nothing better for this came to my mind but I am open for suggestions
for a better marker.

>How-To-Repeat:

	Try the new sysinstall.

>Fix:
	
	Three diffs for the sysinstall source:

Index: config.c
===================================================================
RCS file: /usr2/FreeBSD/CVSROOT/src/release/sysinstall/config.c,v
retrieving revision 1.110
diff -u -r1.110 config.c
--- config.c	1998/03/24 09:51:54	1.110
+++ config.c	1998/07/20 11:35:17
@@ -691,12 +691,12 @@
 
 	/* Bring up the packages menu */
 	pos = scroll = 0;
-	index_menu(&top, &plist, &pos, &scroll);
+	index_menu(&top, &top, &plist, &pos, &scroll);
 
 	if (plist.kids && plist.kids->name) {
 	    /* Now show the packing list menu */
 	    pos = scroll = 0;
-	    ret = index_menu(&plist, NULL, &pos, &scroll);
+	    ret = index_menu(&plist, &plist, NULL, &pos, &scroll);
 	    if (ret & DITEM_LEAVE_MENU)
 		break;
 	    else if (DITEM_STATUS(ret) != DITEM_FAILURE) {

Index: index.c
===================================================================
RCS file: /usr2/FreeBSD/CVSROOT/src/release/sysinstall/index.c,v
retrieving revision 1.54
diff -u -r1.54 index.c
--- index.c	1998/03/24 09:51:55	1.54
+++ index.c	1998/07/30 20:36:53
@@ -46,7 +46,17 @@
 #define MAX_MENU	12
 #define _MAX_DESC	55
 
+/* A structure holding the root, top and plist pointer at once */
+struct ListPtrs
+{
+    PkgNodePtr root;	/* root of tree */
+    PkgNodePtr top;	/* part of tree we handle */
+    PkgNodePtr plist;	/* list of selected packages */
+};
+typedef struct ListPtrs* ListPtrsPtr;
+
 static int	index_extract_one(Device *dev, PkgNodePtr top, PkgNodePtr who, Boolean depended);
+static void	index_recorddeps(Boolean add, PkgNodePtr root, IndexEntryPtr ie);
 
 /* Smarter strdup */
 inline char *
@@ -174,6 +184,8 @@
     tmp->descrfile =	strip(_strdup(descr));
     tmp->maintainer =	_strdup(maint);
     tmp->deps =		_strdup(deps);
+    tmp->depc =		0;
+    tmp->installed =	package_exists(name);
     return tmp;
 }
 
@@ -261,6 +273,7 @@
 index_read(FILE *fp, PkgNodePtr papa)
 {
     char name[127], pathto[255], prefix[255], comment[255], descr[127], maint[127], cats[511], deps[511];
+    PkgNodePtr i;
 
     while (index_parse(fp, name, pathto, prefix, comment, descr, maint, cats, deps) != EOF) {
 	char *cp, *cp2, tmp[511];
@@ -277,6 +290,15 @@
 	/* Add to special "All" category */
 	index_register(papa, "All", idx);
     }
+
+    /* Adjust dependency counts */
+    for (i = papa->kids; i != NULL; i = i->next)
+	if (strcmp(i->name, "All") == 0)
+	    break;
+    for (i = i->kids; i != NULL; i = i->next)
+	if (((IndexEntryPtr)i->data)->installed)
+	    index_recorddeps(TRUE, papa, i->data);
+
     return 0;
 }
 
@@ -401,13 +423,20 @@
 int
 pkg_checked(dialogMenuItem *self)
 {
-    PkgNodePtr kp = self->data, plist = (PkgNodePtr)self->aux;
+    ListPtrsPtr lists = (ListPtrsPtr)self->aux;
+    PkgNodePtr kp = self->data, plist = lists->plist;
     int i;
 
     i = index_search(plist, kp->name, NULL) ? TRUE : FALSE;
-    if (kp->type == PACKAGE && plist)
-	return i || package_exists(kp->name);
-    else
+    if (kp->type == PACKAGE && plist) {
+	IndexEntryPtr ie = kp->data;
+	int markD, markX;
+
+	markD = ie->depc > 0; /* needed as dependency */
+	markX = i || ie->installed; /* selected or installed */
+	self->mark = markX ? 'X' : 'D';
+	return markD || markX;
+    } else
 	return FALSE;
 }
 
@@ -415,42 +444,57 @@
 pkg_fire(dialogMenuItem *self)
 {
     int ret;
-    PkgNodePtr sp, kp = self->data, plist = (PkgNodePtr)self->aux;
+    ListPtrsPtr lists = (ListPtrsPtr)self->aux;
+    PkgNodePtr sp, kp = self->data, plist = lists->plist;
 
     if (!plist)
 	ret = DITEM_FAILURE;
     else if (kp->type == PACKAGE) {
+	IndexEntryPtr ie = kp->data;
+
 	sp = index_search(plist, kp->name, NULL);
 	/* Not already selected? */
 	if (!sp) {
-	    if (!package_exists(kp->name)) {
+	    if (!ie->installed) {
 		PkgNodePtr np = (PkgNodePtr)safe_malloc(sizeof(PkgNode));
 
 		*np = *kp;
 		np->next = plist->kids;
 		plist->kids = np;
+		index_recorddeps(TRUE, lists->root, ie);
 		msgInfo("Added %s to selection list", kp->name);
 	    }
-	    else {
+	    else if (ie->depc == 0) {
 		WINDOW *save = savescr();
 
 		if (!msgYesNo("Do you really want to delete %s from the system?", kp->name))
 		    if (vsystem("pkg_delete %s %s", isDebug() ? "-v" : "", kp->name))
 			msgConfirm("Warning:  pkg_delete of %s failed.\n  Check debug output for details.", kp->name);
+		    else {
+			ie->installed = 0;
+			index_recorddeps(FALSE, lists->root, ie);
+		    }
 		restorescr(save);
 	    }
+	    else
+		msgConfirm("Warning: Package %s is needed by\n  %d other installed package%s.",
+			   kp->name, ie->depc, (ie->depc != 1) ? "s" : "");
 	}
 	else {
+	    index_recorddeps(FALSE, lists->root, ie);
 	    msgInfo("Removed %s from selection list", kp->name);
 	    index_delete(sp);
 	}
 	ret = DITEM_SUCCESS;
+	/* Mark menu for redraw if we had dependencies */
+	if (strlen(ie->deps) > 0)
+	    ret |= DITEM_RECREATE;
     }
     else {	/* Not a package, must be a directory */
 	int p, s;
 		    
 	p = s = 0;
-	index_menu(kp, plist, &p, &s);
+	index_menu(lists->root, kp, plist, &p, &s);
 	ret = DITEM_SUCCESS | DITEM_CONTINUE;
     }
     return ret;
@@ -467,8 +511,9 @@
 }
 
 int
-index_menu(PkgNodePtr top, PkgNodePtr plist, int *pos, int *scroll)
+index_menu(PkgNodePtr root, PkgNodePtr top, PkgNodePtr plist, int *pos, int *scroll)
 {
+    struct ListPtrs lists;
     int n, rval, maxname;
     int curr, max;
     PkgNodePtr kp;
@@ -476,6 +521,10 @@
     Boolean hasPackages;
     WINDOW *w;
 
+    lists.root = root;
+    lists.top = top;
+    lists.plist = plist;
+
     hasPackages = FALSE;
     nitems = NULL;
 
@@ -519,7 +568,7 @@
 		SAFE_STRCPY(buf, kp->desc);
 	    if (strlen(buf) > (_MAX_DESC - maxname))
 		buf[_MAX_DESC - maxname] = '\0';
-	    nitems = item_add(nitems, kp->name, buf, pkg_checked, pkg_fire, pkg_selected, kp, (int)plist, &curr, &max);
+	    nitems = item_add(nitems, kp->name, buf, pkg_checked, pkg_fire, pkg_selected, kp, (int)&lists, &curr, &max);
 	    ++n;
 	    kp = kp->next;
 	}
@@ -545,7 +594,7 @@
 
 		    /* These need to be set to point at the found item, actually.  Hmmm! */
 		    pos = scroll = 0;
-		    index_menu(menu, plist, &pos, &scroll);
+		    index_menu(root, menu, plist, &pos, &scroll);
 		}
 		else
 		    msgConfirm("Search string: %s yielded no hits.", cp);
@@ -606,7 +655,41 @@
 	}
     }
     /* Done with the deps?  Load the real m'coy */
-    if (DITEM_STATUS(status) == DITEM_SUCCESS)
+    if (DITEM_STATUS(status) == DITEM_SUCCESS) {
 	status = package_extract(dev, who->name, depended);
+	if (DITEM_STATUS(status) == DITEM_SUCCESS)
+	    id->installed = 1;
+    }
     return status;
+}
+
+static void
+index_recorddeps(Boolean add, PkgNodePtr root, IndexEntryPtr ie)
+{
+   char depends[1024], *space, *todo;
+   PkgNodePtr found;
+   IndexEntryPtr found_ie;
+
+   SAFE_STRCPY(depends, ie->deps);
+   for (todo = depends; todo != NULL; ) {
+      space = index(todo, ' ');
+      if (space != NULL)
+	 *space = '\0';
+
+      if (strlen(todo) > 0) { /* only non-empty dependencies */
+	  found = index_search(root, todo, NULL);
+	  if (found != NULL) {
+	      found_ie = found->data;
+	      if (add)
+		  ++found_ie->depc;
+	      else
+		  --found_ie->depc;
+	  }
+      }
+
+      if (space != NULL)
+	 todo = space + 1;
+      else
+	 todo = NULL;
+   }
 }

Index: sysinstall.h
===================================================================
RCS file: /usr2/FreeBSD/CVSROOT/src/release/sysinstall/sysinstall.h,v
retrieving revision 1.147
diff -u -r1.147 sysinstall.h
--- sysinstall.h	1998/07/18 09:42:01	1.147
+++ sysinstall.h	1998/07/20 11:39:35
@@ -316,6 +316,8 @@
     char *comment;		/* one line description		*/
     char *descrfile;		/* path to description file	*/
     char *deps;			/* packages this depends on	*/
+    int  depc;			/* how many depend on me	*/
+    int  installed;		/* indicates if it is installed */
     char *maintainer;		/* maintainer			*/
 } IndexEntry;
 typedef IndexEntry *IndexEntryPtr;
@@ -540,7 +542,7 @@
 
 /* index.c */
 int		index_read(FILE *fp, PkgNodePtr papa);
-int		index_menu(PkgNodePtr top, PkgNodePtr plist, int *pos, int *scroll);
+int		index_menu(PkgNodePtr root, PkgNodePtr top, PkgNodePtr plist, int *pos, int *scroll);
 void		index_init(PkgNodePtr top, PkgNodePtr plist);
 void		index_node_free(PkgNodePtr top, PkgNodePtr plist);
 void		index_sort(PkgNodePtr top);
>Release-Note:
>Audit-Trail:
Responsible-Changed-From-To: freebsd-bugs->jkh 
Responsible-Changed-By: phk 
Responsible-Changed-When: Fri Jul 31 02:18:22 PDT 1998 
Responsible-Changed-Why:  
This one is Jordans, see also 7453 

From: Stefan Eggers <seggers@semyam.dinoco.de>
To: FreeBSD-gnats-submit@FreeBSD.ORG, freebsd-bugs@FreeBSD.ORG
Cc: seggers@semyam.dinoco.de
Subject: Re: bin/7454: make dependencies more visible in sysinstall 
Date: Fri, 31 Jul 1998 14:50:20 +0200

 Here is a slightly changed patch for the index.c file.  It doesn't
 require any change to libdialog anymore to be useable.   The other
 two patches are unchanged.
 
 Index: index.c
 ===================================================================
 RCS file: /usr2/FreeBSD/CVSROOT/src/release/sysinstall/index.c,v
 retrieving revision 1.54
 diff -u -r1.54 index.c
 --- index.c	1998/03/24 09:51:55	1.54
 +++ index.c	1998/07/31 12:45:07
 @@ -46,7 +46,17 @@
  #define MAX_MENU	12
  #define _MAX_DESC	55
  
 +/* A structure holding the root, top and plist pointer at once */
 +struct ListPtrs
 +{
 +    PkgNodePtr root;	/* root of tree */
 +    PkgNodePtr top;	/* part of tree we handle */
 +    PkgNodePtr plist;	/* list of selected packages */
 +};
 +typedef struct ListPtrs* ListPtrsPtr;
 +
  static int	index_extract_one(Device *dev, PkgNodePtr top, PkgNodePtr who, Boolean depended);
 +static void	index_recorddeps(Boolean add, PkgNodePtr root, IndexEntryPtr ie);
  
  /* Smarter strdup */
  inline char *
 @@ -174,6 +184,8 @@
      tmp->descrfile =	strip(_strdup(descr));
      tmp->maintainer =	_strdup(maint);
      tmp->deps =		_strdup(deps);
 +    tmp->depc =		0;
 +    tmp->installed =	package_exists(name);
      return tmp;
  }
  
 @@ -261,6 +273,7 @@
  index_read(FILE *fp, PkgNodePtr papa)
  {
      char name[127], pathto[255], prefix[255], comment[255], descr[127], maint[127], cats[511], deps[511];
 +    PkgNodePtr i;
  
      while (index_parse(fp, name, pathto, prefix, comment, descr, maint, cats, deps) != EOF) {
  	char *cp, *cp2, tmp[511];
 @@ -277,6 +290,15 @@
  	/* Add to special "All" category */
  	index_register(papa, "All", idx);
      }
 +
 +    /* Adjust dependency counts */
 +    for (i = papa->kids; i != NULL; i = i->next)
 +	if (strcmp(i->name, "All") == 0)
 +	    break;
 +    for (i = i->kids; i != NULL; i = i->next)
 +	if (((IndexEntryPtr)i->data)->installed)
 +	    index_recorddeps(TRUE, papa, i->data);
 +
      return 0;
  }
  
 @@ -401,13 +423,20 @@
  int
  pkg_checked(dialogMenuItem *self)
  {
 -    PkgNodePtr kp = self->data, plist = (PkgNodePtr)self->aux;
 +    ListPtrsPtr lists = (ListPtrsPtr)self->aux;
 +    PkgNodePtr kp = self->data, plist = lists->plist;
      int i;
  
      i = index_search(plist, kp->name, NULL) ? TRUE : FALSE;
 -    if (kp->type == PACKAGE && plist)
 -	return i || package_exists(kp->name);
 -    else
 +    if (kp->type == PACKAGE && plist) {
 +	IndexEntryPtr ie = kp->data;
 +	int markD, markX;
 +
 +	markD = ie->depc > 0; /* needed as dependency */
 +	markX = i || ie->installed; /* selected or installed */
 +	self->mark = markX ? 'X' : 'D';
 +	return markD || markX;
 +    } else
  	return FALSE;
  }
  
 @@ -415,42 +444,57 @@
  pkg_fire(dialogMenuItem *self)
  {
      int ret;
 -    PkgNodePtr sp, kp = self->data, plist = (PkgNodePtr)self->aux;
 +    ListPtrsPtr lists = (ListPtrsPtr)self->aux;
 +    PkgNodePtr sp, kp = self->data, plist = lists->plist;
  
      if (!plist)
  	ret = DITEM_FAILURE;
      else if (kp->type == PACKAGE) {
 +	IndexEntryPtr ie = kp->data;
 +
  	sp = index_search(plist, kp->name, NULL);
  	/* Not already selected? */
  	if (!sp) {
 -	    if (!package_exists(kp->name)) {
 +	    if (!ie->installed) {
  		PkgNodePtr np = (PkgNodePtr)safe_malloc(sizeof(PkgNode));
  
  		*np = *kp;
  		np->next = plist->kids;
  		plist->kids = np;
 +		index_recorddeps(TRUE, lists->root, ie);
  		msgInfo("Added %s to selection list", kp->name);
  	    }
 -	    else {
 +	    else if (ie->depc == 0) {
  		WINDOW *save = savescr();
  
  		if (!msgYesNo("Do you really want to delete %s from the system?", kp->name))
  		    if (vsystem("pkg_delete %s %s", isDebug() ? "-v" : "", kp->name))
  			msgConfirm("Warning:  pkg_delete of %s failed.\n  Check debug output for details.", kp->name);
 +		    else {
 +			ie->installed = 0;
 +			index_recorddeps(FALSE, lists->root, ie);
 +		    }
  		restorescr(save);
  	    }
 +	    else
 +		msgConfirm("Warning: Package %s is needed by\n  %d other installed package%s.",
 +			   kp->name, ie->depc, (ie->depc != 1) ? "s" : "");
  	}
  	else {
 +	    index_recorddeps(FALSE, lists->root, ie);
  	    msgInfo("Removed %s from selection list", kp->name);
  	    index_delete(sp);
  	}
  	ret = DITEM_SUCCESS;
 +	/* Mark menu for redraw if we had dependencies */
 +	if (strlen(ie->deps) > 0)
 +	    ret |= DITEM_REDRAW;
      }
      else {	/* Not a package, must be a directory */
  	int p, s;
  		    
  	p = s = 0;
 -	index_menu(kp, plist, &p, &s);
 +	index_menu(lists->root, kp, plist, &p, &s);
  	ret = DITEM_SUCCESS | DITEM_CONTINUE;
      }
      return ret;
 @@ -467,8 +511,9 @@
  }
  
  int
 -index_menu(PkgNodePtr top, PkgNodePtr plist, int *pos, int *scroll)
 +index_menu(PkgNodePtr root, PkgNodePtr top, PkgNodePtr plist, int *pos, int *scroll)
  {
 +    struct ListPtrs lists;
      int n, rval, maxname;
      int curr, max;
      PkgNodePtr kp;
 @@ -476,6 +521,10 @@
      Boolean hasPackages;
      WINDOW *w;
  
 +    lists.root = root;
 +    lists.top = top;
 +    lists.plist = plist;
 +
      hasPackages = FALSE;
      nitems = NULL;
  
 @@ -519,7 +568,7 @@
  		SAFE_STRCPY(buf, kp->desc);
  	    if (strlen(buf) > (_MAX_DESC - maxname))
  		buf[_MAX_DESC - maxname] = '\0';
 -	    nitems = item_add(nitems, kp->name, buf, pkg_checked, pkg_fire, pkg_selected, kp, (int)plist, &curr, &max);
 +	    nitems = item_add(nitems, kp->name, buf, pkg_checked, pkg_fire, pkg_selected, kp, (int)&lists, &curr, &max);
  	    ++n;
  	    kp = kp->next;
  	}
 @@ -545,7 +594,7 @@
  
  		    /* These need to be set to point at the found item, actually.  Hmmm! */
  		    pos = scroll = 0;
 -		    index_menu(menu, plist, &pos, &scroll);
 +		    index_menu(root, menu, plist, &pos, &scroll);
  		}
  		else
  		    msgConfirm("Search string: %s yielded no hits.", cp);
 @@ -606,7 +655,41 @@
  	}
      }
      /* Done with the deps?  Load the real m'coy */
 -    if (DITEM_STATUS(status) == DITEM_SUCCESS)
 +    if (DITEM_STATUS(status) == DITEM_SUCCESS) {
  	status = package_extract(dev, who->name, depended);
 +	if (DITEM_STATUS(status) == DITEM_SUCCESS)
 +	    id->installed = 1;
 +    }
      return status;
 +}
 +
 +static void
 +index_recorddeps(Boolean add, PkgNodePtr root, IndexEntryPtr ie)
 +{
 +   char depends[1024], *space, *todo;
 +   PkgNodePtr found;
 +   IndexEntryPtr found_ie;
 +
 +   SAFE_STRCPY(depends, ie->deps);
 +   for (todo = depends; todo != NULL; ) {
 +      space = index(todo, ' ');
 +      if (space != NULL)
 +	 *space = '\0';
 +
 +      if (strlen(todo) > 0) { /* only non-empty dependencies */
 +	  found = index_search(root, todo, NULL);
 +	  if (found != NULL) {
 +	      found_ie = found->data;
 +	      if (add)
 +		  ++found_ie->depc;
 +	      else
 +		  --found_ie->depc;
 +	  }
 +      }
 +
 +      if (space != NULL)
 +	 todo = space + 1;
 +      else
 +	 todo = NULL;
 +   }
  }
State-Changed-From-To: open->closed 
State-Changed-By: jkh 
State-Changed-When: Tue Feb 9 11:02:15 PST 1999 
State-Changed-Why:  
This was committed a week or two ago, thanks! 
>Unformatted:
