#include "dsynth.h"
static int status_find_leaves(pkg_t *parent, pkg_t *pkg, pkg_t ***build_tailp,
int *app, int *hasworkp, int level, int first);
static void status_clear_trav(pkg_t *pkg);
static void startstatus(pkg_t **build_listp, pkg_t ***build_tailp);
void
DoStatus(pkg_t *pkgs)
{
pkg_t *build_list = NULL;
pkg_t **build_tail = &build_list;
pkg_t *scan;
int haswork = 1;
int first = 1;
for (scan = pkgs; scan; scan = scan->bnext) {
if ((scan->flags & PKGF_DUMMY) == 0)
++BuildTotal;
}
while (haswork) {
haswork = 0;
fflush(stdout);
for (scan = pkgs; scan; scan = scan->bnext) {
ddprintf(0, "SCANLEAVES %08x %s\n",
scan->flags, scan->portdir);
scan->flags |= PKGF_BUILDLOOP;
if (scan->flags & (PKGF_SUCCESS | PKGF_FAILURE |
PKGF_ERROR | PKGF_NOBUILD)) {
#if 0
ddprintf(0, "%s: already built\n",
scan->portdir);
#endif
} else {
int ap = 0;
status_find_leaves(NULL, scan, &build_tail,
&ap, &haswork, 0, first);
ddprintf(0, "TOPLEVEL %s %08x\n",
scan->portdir, ap);
}
scan->flags &= ~PKGF_BUILDLOOP;
status_clear_trav(scan);
}
first = 0;
fflush(stdout);
if (haswork == 0)
break;
startstatus(&build_list, &build_tail);
}
printf("Total packages that would be built: %d/%d\n",
BuildSuccessCount, BuildTotal);
}
static
int
status_find_leaves(pkg_t *parent, pkg_t *pkg, pkg_t ***build_tailp,
int *app, int *hasworkp, int level, int first)
{
pkglink_t *link;
pkg_t *scan;
int idep_count = 0;
int apsub;
ddprintf(level, "sbuild_find_leaves %d %s %08x {\n",
level, pkg->portdir, pkg->flags);
if (pkg->flags & PKGF_BUILDLIST) {
ddprintf(level, "} (already on build list)\n");
*app |= PKGF_NOTREADY;
return (pkg->idep_count);
}
++level;
PKGLIST_FOREACH(link, &pkg->idepon_list) {
scan = link->pkg;
if (scan == NULL)
continue;
ddprintf(level, "check %s %08x\t", scan->portdir, scan->flags);
if (scan->flags & PKGF_SUCCESS) {
ddprintf(0, "SUCCESS - OK\n");
++idep_count;
continue;
}
if (scan->flags & PKGF_ERROR) {
ddprintf(0, "ERROR - OK (propagate failure upward)\n");
*app |= PKGF_NOBUILD_S;
continue;
}
if (scan->flags & PKGF_NOBUILD) {
ddprintf(0, "NOBUILD - OK "
"(propagate failure upward)\n");
*app |= PKGF_NOBUILD_S;
continue;
}
if (scan->flags & PKGF_BUILDLIST) {
ddprintf(0, " [BUILDLIST]");
*app |= PKGF_NOTREADY;
}
if ((scan->flags & PKGF_PACKAGED) == 0) {
ddprintf(0, " [NOT_PACKAGED]");
*app |= PKGF_NOTREADY;
}
if (scan->flags & PKGF_BUILDTRAV) {
ddprintf(0, " [BUILDTRAV]\n");
*app |= PKGF_NOTREADY;
continue;
}
++idep_count;
if (scan->flags & PKGF_BUILDLOOP) {
dfatal("pkg dependency loop %s -> %s",
parent->portdir, scan->portdir);
}
scan->flags |= PKGF_BUILDLOOP;
apsub = 0;
ddprintf(0, " SUBRECURSION {\n");
idep_count += status_find_leaves(pkg, scan, build_tailp,
&apsub, hasworkp,
level + 1, first);
scan->flags &= ~PKGF_BUILDLOOP;
*app |= apsub;
if (apsub & PKGF_NOBUILD) {
ddprintf(level, "} (sub-nobuild)\n");
} else if (apsub & PKGF_ERROR) {
ddprintf(level, "} (sub-error)\n");
} else if (apsub & PKGF_NOTREADY) {
ddprintf(level, "} (sub-notready)\n");
} else {
ddprintf(level, "} (sub-ok)\n");
}
}
--level;
pkg->idep_count = idep_count;
pkg->flags |= PKGF_BUILDTRAV;
if ((pkg->flags & PKGF_NOBUILD) == 0 && (*app & PKGF_NOBUILD)) {
*hasworkp = 1;
} else if ((pkg->flags & PKGF_ERROR) == 0 && (*app & PKGF_ERROR)) {
*hasworkp = 1;
}
pkg->flags |= *app & ~PKGF_NOTREADY;
if ((pkg->flags & PKGF_PACKAGED) &&
(pkg->flags & (PKGF_NOTREADY|PKGF_ERROR|PKGF_NOBUILD))) {
pkg->flags &= ~PKGF_PACKAGED;
ddassert(pkg->pkgfile);
*hasworkp = 1;
}
if (pkg->flags & PKGF_ERROR) {
ddprintf(level, "} (ERROR - %s)\n", pkg->portdir);
} else if (pkg->flags & PKGF_NOBUILD) {
ddprintf(level, "} (SKIPPED - %s)\n", pkg->portdir);
} else if (*app & PKGF_NOTREADY) {
;
} else if (pkg->flags & PKGF_SUCCESS) {
ddprintf(level, "} (SUCCESS - %s)\n", pkg->portdir);
} else if (pkg->flags & PKGF_DUMMY) {
ddprintf(level, "} (DUMMY/META - SUCCESS)\n");
pkg->flags |= PKGF_SUCCESS;
*hasworkp = 1;
if (first) {
dlog(DLOG_ALL | DLOG_FILTER,
"[XXX] %s META-ALREADY-BUILT\n",
pkg->portdir);
} else {
dlog(DLOG_SUCC | DLOG_FILTER,
"[XXX] %s meta-node complete\n",
pkg->portdir);
}
} else if (pkg->flags & PKGF_PACKAGED) {
ddprintf(level, "} (PACKAGED - SUCCESS)\n");
pkg->flags |= PKGF_SUCCESS;
*hasworkp = 1;
if (first) {
dlog(DLOG_ALL | DLOG_FILTER,
"[XXX] %s ALREADY-BUILT\n",
pkg->portdir);
--BuildTotal;
}
} else {
*hasworkp = 1;
ddprintf(level, "} (ADDLIST - %s)\n", pkg->portdir);
pkg->flags |= PKGF_BUILDLIST;
**build_tailp = pkg;
*build_tailp = &pkg->build_next;
*app |= PKGF_NOTREADY;
}
return idep_count;
}
static
void
status_clear_trav(pkg_t *pkg)
{
pkglink_t *link;
pkg_t *scan;
pkg->flags &= ~PKGF_BUILDTRAV;
PKGLIST_FOREACH(link, &pkg->idepon_list) {
scan = link->pkg;
if (scan && (scan->flags & PKGF_BUILDTRAV))
status_clear_trav(scan);
}
}
static
void
startstatus(pkg_t **build_listp, pkg_t ***build_tailp)
{
pkg_t *pkg;
if (*build_listp == NULL)
return;
for (pkg = *build_listp; pkg; pkg = pkg->build_next) {
if ((pkg->flags & (PKGF_SUCCESS | PKGF_FAILURE |
PKGF_ERROR | PKGF_NOBUILD |
PKGF_RUNNING)) == 0) {
pkg->flags |= PKGF_SUCCESS;
++BuildSuccessCount;
++BuildCount;
pkg->flags &= ~PKGF_BUILDLIST;
printf(" N => %s\n", pkg->portdir);
}
}
*build_listp = NULL;
*build_tailp = build_listp;
}