2 * Copyright (c) 2019 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * This code uses concepts and configuration based on 'synth', by
8 * John R. Marino <draco@marino.st>, which was written in ada.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
20 * 3. Neither the name of The DragonFly Project nor the names of its
21 * contributors may be used to endorse or promote products derived
22 * from this software without specific, prior written permission.
24 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
32 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
34 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
40 #define PKG_HSIZE 32768
41 #define PKG_HMASK 32767
43 static int parsepkglist_file(const char *path, int debugstop);
44 static void childGetPackageInfo(bulk_t *bulk);
45 static void childGetBinaryDistInfo(bulk_t *bulk);
46 static void childOptimizeEnv(bulk_t *bulk);
47 static pkg_t *resolveDeps(pkg_t *dep_list, pkg_t ***list_tailp, int gentopo);
48 static void resolveFlavors(pkg_t *pkg, char *flavors, int gentopo);
49 static void resolveDepString(pkg_t *pkg, char *depstr,
50 int gentopo, int dep_type);
51 static pkg_t *processPackageListBulk(int total);
52 static int scan_and_queue_dir(const char *path, const char *level1, int level);
53 static int scan_binary_repo(const char *path);
55 static void pkgfree(pkg_t *pkg);
58 pkg_t *PkgHash1[PKG_HSIZE]; /* by portdir */
59 pkg_t *PkgHash2[PKG_HSIZE]; /* by pkgfile */
62 * Allocate a new pkg structure plus basic initialization.
64 static __inline pkg_t *
69 pkg = calloc(1, sizeof(*pkg));
70 pkg->idepon_list.next = &pkg->idepon_list;
71 pkg->idepon_list.prev = &pkg->idepon_list;
72 pkg->deponi_list.next = &pkg->deponi_list;
73 pkg->deponi_list.prev = &pkg->deponi_list;
79 * Simple hash for lookups
82 pkghash(const char *str)
86 hv = (hv << 5) ^ *str;
89 hv = hv ^ (hv / PKG_HSIZE) ^ (hv / PKG_HSIZE / PKG_HSIZE);
90 return (hv & PKG_HMASK);
100 pkgp = &PkgHash1[pkghash(pkg->portdir)];
101 while ((scan = *pkgp) != NULL) {
102 if (strcmp(pkg->portdir, scan->portdir) == 0)
104 pkgp = &scan->hnext1;
106 ddassert(scan == NULL || (scan->flags & PKGF_PLACEHOLD));
107 if (scan && (scan->flags & PKGF_PLACEHOLD)) {
108 ddassert(scan->idepon_list.next == &scan->idepon_list);
109 ddassert(scan->deponi_list.next == &scan->deponi_list);
111 pkg->hnext1 = scan->hnext1;
121 pkgp = &PkgHash2[pkghash(pkg->pkgfile)];
122 while ((scan = *pkgp) != NULL) {
123 if (strcmp(pkg->pkgfile, scan->pkgfile) == 0)
125 pkgp = &scan->hnext2;
133 pkg_find(const char *match)
138 pkgp = &PkgHash1[pkghash(match)];
139 for (pkg = *pkgp; pkg; pkg = pkg->hnext1) {
140 if (strcmp(pkg->portdir, match) == 0)
143 pkgp = &PkgHash2[pkghash(match)];
144 for (pkg = *pkgp; pkg; pkg = pkg->hnext2) {
145 if (strcmp(pkg->pkgfile, match) == 0)
152 * Parse a specific list of ports via origin name (portdir/subdir)
155 ParsePackageList(int n, char **ary, int debugstop)
164 initbulk(childGetPackageInfo, MaxBulk);
167 * Always include ports-mgmt/pkg. s4 is "x" meaning not a manual
168 * selection, "d" meaning DEBUGSTOP mode, or NULL.
170 queuebulk("ports-mgmt", "pkg", NULL, "x");
172 for (i = 0; i < n; ++i) {
179 if (stat(l1, &st) == 0 && S_ISREG(st.st_mode)) {
180 total += parsepkglist_file(l1, debugstop);
184 l2 = strchr(l1, '/');
186 printf("Bad portdir specification: %s\n", l1);
192 l3 = strchr(l2, '@');
195 queuebulk(l1, l2, l3, (debugstop ? "d" : NULL));
199 printf("Processing %d ports\n", total);
201 list = processPackageListBulk(total);
203 dfatal("Bad specifications, exiting");
212 parsepkglist_file(const char *path, int debugstop)
222 if ((fp = fopen(path, "r")) == NULL) {
223 dpanic_errno("Cannot read %s\n", path);
230 while ((base = fgetln(fp, &len)) != NULL) {
231 if (len == 0 || base[len-1] != '\n')
234 l1 = strtok(base, " \t\r\n");
236 printf("Badly formatted pkg info line: %s\n", base);
239 l2 = strchr(l1, '/');
241 printf("Badly formatted specification: %s\n", l1);
245 l3 = strchr(l2, '@');
248 queuebulk(l1, l2, l3, (debugstop ? "d" : NULL));
257 * Parse packages from the list installed on the system.
260 GetLocalPackageList(void)
271 initbulk(childGetPackageInfo, MaxBulk);
274 fp = popen("pkg info -a -o", "r");
277 * Always include ports-mgmt/pkg. s4 is "x" meaning not a manual
278 * selection, "d" meaning DEBUGSTOP mode, or NULL.
280 queuebulk("ports-mgmt", "pkg", NULL, "x");
282 while ((base = fgetln(fp, &len)) != NULL) {
283 if (len == 0 || base[len-1] != '\n')
286 if (strtok(base, " \t") == NULL) {
287 printf("Badly formatted pkg info line: %s\n", base);
290 l1 = strtok(NULL, " \t");
292 printf("Badly formatted pkg info line: %s\n", base);
296 l2 = strchr(l1, '/');
298 printf("Badly formatted specification: %s\n", l1);
302 l3 = strchr(l2, '@');
305 queuebulk(l1, l2, l3, NULL);
310 printf("Processing %d ports\n", total);
312 list = processPackageListBulk(total);
318 GetFullPackageList(void)
322 initbulk(childGetPackageInfo, MaxBulk);
323 total = scan_and_queue_dir(DPortsPath, NULL, 1);
324 printf("Scanning %d ports\n", total);
326 return processPackageListBulk(total);
330 * Caller has queued the process list for bulk operation. We retrieve
331 * the results and clean up the bulk operation (we may have to do a second
332 * bulk operation so we have to be the ones to clean it up).
335 processPackageListBulk(int total)
349 while ((bulk = getbulk()) != NULL) {
351 if ((count & 255) == 0) {
353 (double)count * 100.0 / (double)total + 0.001);
357 *list_tail = bulk->list;
359 while ((scan = *list_tail) != NULL) {
360 if (bulk->s4 == NULL || bulk->s4[0] != 'x')
361 scan->flags |= PKGF_MANUALSEL;
363 list_tail = &scan->bnext;
368 printf("100.00%%\n");
369 printf("\nTotal %d\n", count);
373 * Resolve all dependencies for the related packages, potentially
374 * adding anything that could not be found to the list. This will
375 * continue to issue bulk operations and process the result until
376 * no dependencies are left.
378 printf("Resolving dependencies...");
382 dep_list = resolveDeps(dep_list, &list_tail, 0);
389 * Generate the topology
391 resolveDeps(list, NULL, 1);
394 * Do a final count, ignore place holders.
396 * Also set stop_fail if appropriate. Check for direct specifications
397 * which fail to probe and any direct dependencies of those
398 * specifications, but don't recurse (for now)... don't check indirect
399 * dependencies (i.e. A -> B -> C where A is directly specified, B
400 * is adirect dependency, and C fails to probe).
404 for (scan = list; scan; scan = scan->bnext) {
405 if ((scan->flags & PKGF_ERROR) == 0) {
408 if ((scan->flags & PKGF_MANUALSEL) && MaskProbeAbort == 0) {
412 * Directly specified package failed to probe
414 if (scan->flags & PKGF_CORRUPT)
418 * Directly specified package had a direct dependency
419 * that failed to probe (don't go further).
421 PKGLIST_FOREACH(link, &scan->idepon_list) {
423 (link->pkg->flags & PKGF_CORRUPT)) {
429 printf("Total Returned %d\n", count);
432 * Check to see if any PKGF_MANUALSEL packages
435 printf("Aborting, %d packages failed to probe\n", stop_fail);
440 * Scan our binary distributions and related dependencies looking
441 * for any packages that have already been built.
443 initbulk(childGetBinaryDistInfo, MaxBulk);
444 total = scan_binary_repo(RepositoryPath);
446 printf("Scanning %d packages\n", total);
448 while ((bulk = getbulk()) != NULL) {
450 if ((count & 255) == 0) {
452 (double)count * 100.0 / (double)total + 0.001);
457 printf("100.00%%\n");
458 printf("\nTotal %d\n", count);
462 printf("all done\n");
468 GetPkgPkg(pkg_t *list)
473 for (scan = list; scan; scan = scan->bnext) {
474 if (strcmp(scan->portdir, "ports-mgmt/pkg") == 0)
479 * This will force pkg to be built, but generally this code
480 * is not reached because the package list processing code
481 * adds ports-mgmt/pkg unconditionally.
483 initbulk(childGetPackageInfo, MaxBulk);
484 queuebulk("ports-mgmt", "pkg", NULL, "x");
486 dassert(bulk, "Cannot find ports-mgmt/pkg");
496 * Try to optimize the environment by supplying information that
497 * the ports system would generally have to run stuff to get on
500 * See childOptimizeEnv() for the actual handling. We execute
501 * a single make -V... -V... for ports-mgmt/pkg from within the
502 * bulk system (which handles the environment and disables
503 * /etc/make.conf), and we then call addbuildenv() as appropriate.
513 initbulk(childOptimizeEnv, MaxBulk);
514 queuebulk("ports-mgmt", "pkg", NULL, NULL);
521 * Run through the list resolving dependencies and constructing the topology
522 * linkages. This may append packages to the list. Dependencies to dummy
523 * nodes which do not specify a flavor do not need special handling, the
524 * search code in build.c will properly follow the first flavor.
527 resolveDeps(pkg_t *list, pkg_t ***list_tailp, int gentopo)
529 pkg_t *ret_list = NULL;
534 for (scan = list; scan; scan = scan->bnext) {
535 use = pkg_find(scan->portdir);
536 resolveFlavors(use, scan->flavors, gentopo);
537 resolveDepString(use, scan->fetch_deps,
538 gentopo, DEP_TYPE_FETCH);
539 resolveDepString(use, scan->ext_deps,
540 gentopo, DEP_TYPE_EXT);
541 resolveDepString(use, scan->patch_deps,
542 gentopo, DEP_TYPE_PATCH);
543 resolveDepString(use, scan->build_deps,
544 gentopo, DEP_TYPE_BUILD);
545 resolveDepString(use, scan->lib_deps,
546 gentopo, DEP_TYPE_LIB);
547 resolveDepString(use, scan->run_deps,
548 gentopo, DEP_TYPE_RUN);
552 * No bulk ops are queued when doing the final topology
555 * Avoid entering duplicate results from the bulk ops. Duplicate
556 * results are mostly filtered out, but not always. A dummy node
557 * representing multiple flavors will parse-out the flavors
561 while ((bulk = getbulk()) != NULL) {
563 if (ret_list == NULL)
564 ret_list = bulk->list;
565 **list_tailp = bulk->list;
567 while ((scan = **list_tailp) != NULL) {
569 *list_tailp = &scan->bnext;
578 * Resolve a generic node that has flavors, queue to retrieve info for
579 * each flavor and setup linkages as appropriate.
582 resolveFlavors(pkg_t *pkg, char *flavors, int gentopo)
593 if ((pkg->flags & PKGF_DUMMY) == 0)
595 if (pkg->flavors == NULL || pkg->flavors[0] == 0)
597 flavor_base = strdup(flavors);
598 flavor_scan = flavor_base;
602 flavor = strsep(&flavor_scan, " \t");
603 } while (flavor && *flavor == 0);
608 * Iterate each flavor generating "s1/s2@flavor".
610 * queuebulk() info for each flavor, and set-up the
611 * linkages in the topology generation pass.
613 asprintf(&portdir, "%s@%s", pkg->portdir, flavor);
614 s1 = strdup(pkg->portdir);
615 s2 = strchr(s1, '/');
618 dpkg = pkg_find(portdir);
619 if (dpkg && gentopo) {
625 link = calloc(1, sizeof(*link));
627 link->next = &pkg->idepon_list;
628 link->prev = pkg->idepon_list.prev;
629 link->next->prev = link;
630 link->prev->next = link;
631 link->dep_type = DEP_TYPE_BUILD;
633 link = calloc(1, sizeof(*link));
635 link->next = &dpkg->deponi_list;
636 link->prev = dpkg->deponi_list.prev;
637 link->next->prev = link;
638 link->prev->next = link;
639 link->dep_type = DEP_TYPE_BUILD;
641 } else if (gentopo == 0 && dpkg == NULL) {
643 * Use a place-holder to prevent duplicate
644 * dependencies from being processed. The placeholder
645 * will be replaced by the actual dependency.
648 dpkg->portdir = portdir;
649 dpkg->flags = PKGF_PLACEHOLD;
651 queuebulk(s1, s2, flavor, NULL);
659 resolveDepString(pkg_t *pkg, char *depstr, int gentopo, int dep_type)
669 if (depstr == NULL || depstr[0] == 0)
672 copy_base = strdup(depstr);
677 dep = strsep(©, " \t");
678 } while (dep && *dep == 0);
683 * Ignore dependencies prefixed with ${NONEXISTENT}
685 if (strncmp(dep, "/nonexistent:", 13) == 0)
688 dep = strchr(dep, ':');
689 if (dep == NULL || *dep != ':') {
690 printf("Error parsing dependency for %s: %s\n",
691 pkg->portdir, copy_base);
697 * Strip-off any DPortsPath prefix. EXTRACT_DEPENDS
698 * often (always?) generates this prefix.
700 if (strncmp(dep, DPortsPath, strlen(DPortsPath)) == 0) {
701 dep += strlen(DPortsPath);
707 * Strip-off any tag (such as :patch). We don't try to
708 * organize dependencies at this fine a grain (for now).
710 tag = strchr(dep, ':');
715 * Locate the dependency
717 if ((dpkg = pkg_find(dep)) != NULL) {
722 * NOTE: idep_count is calculated recursively
725 ddprintf(0, "Add Dependency %s -> %s\n",
726 pkg->portdir, dpkg->portdir);
727 link = calloc(1, sizeof(*link));
729 link->next = &pkg->idepon_list;
730 link->prev = pkg->idepon_list.prev;
731 link->next->prev = link;
732 link->prev->next = link;
733 link->dep_type = dep_type;
735 link = calloc(1, sizeof(*link));
737 link->next = &dpkg->deponi_list;
738 link->prev = dpkg->deponi_list.prev;
739 link->next->prev = link;
740 link->prev->next = link;
741 link->dep_type = dep_type;
748 * This shouldn't happen because we already took a first
749 * pass and should have generated the pkgs.
752 printf("Topology Generate failed for %s: %s\n",
753 pkg->portdir, copy_base);
758 * Separate out the two dports directory components and
759 * extract the optional '@flavor' specification.
761 sep = strchr(dep, '/');
763 printf("Error parsing dependency for %s: %s\n",
764 pkg->portdir, copy_base);
770 * The flavor hangs off the separator, not the tag
772 flavor = strrchr(sep, '@');
775 flavor = strrchr(tag, '@');
777 flavor = strrchr(sep, '@');
783 ddprintf(0, "QUEUE DEPENDENCY FROM PKG %s: %s/%s@%s\n",
784 pkg->portdir, dep, sep, flavor);
786 ddprintf(0, "QUEUE DEPENDENCY FROM PKG %s: %s/%s\n",
787 pkg->portdir, dep, sep);
790 * Use a place-holder to prevent duplicate dependencies from
791 * being processed. The placeholder will be replaced by
792 * the actual dependency.
796 asprintf(&dpkg->portdir, "%s/%s@%s", dep, sep, flavor);
798 asprintf(&dpkg->portdir, "%s/%s", dep, sep);
799 dpkg->flags = PKGF_PLACEHOLD;
802 queuebulk(dep, sep, flavor, NULL);
808 FreePackageList(pkg_t *pkgs __unused)
810 dfatal("not implemented");
814 * Scan some or all dports to allocate the related pkg structure. Dependencies
815 * are stored but not processed.
820 childGetPackageInfo(bulk_t *bulk)
830 const char *cav[MAXCAC];
835 * If the package has flavors we will loop on each one. If a flavor
836 * is not passed in s3 we will loop on all flavors, otherwise we will
837 * only process the passed-in flavor.
839 flavor = bulk->s3; /* usually NULL */
843 asprintf(&portpath, "%s/%s/%s", DPortsPath, bulk->s1, bulk->s2);
845 asprintf(&flavarg, "FLAVOR=%s", flavor);
850 cav[cac++] = MAKE_BINARY;
852 cav[cac++] = portpath;
854 cav[cac++] = flavarg;
855 cav[cac++] = "-VPKGVERSION";
856 cav[cac++] = "-VPKGFILE:T";
857 cav[cac++] = "-VALLFILES";
858 cav[cac++] = "-VDIST_SUBDIR";
859 cav[cac++] = "-VMAKE_JOBS_NUMBER";
860 cav[cac++] = "-VIGNORE";
861 cav[cac++] = "-VFETCH_DEPENDS";
862 cav[cac++] = "-VEXTRACT_DEPENDS";
863 cav[cac++] = "-VPATCH_DEPENDS";
864 cav[cac++] = "-VBUILD_DEPENDS";
865 cav[cac++] = "-VLIB_DEPENDS";
866 cav[cac++] = "-VRUN_DEPENDS";
867 cav[cac++] = "-VSELECTED_OPTIONS";
868 cav[cac++] = "-VDESELECTED_OPTIONS";
869 cav[cac++] = "-VUSE_LINUX";
870 cav[cac++] = "-VFLAVORS";
871 cav[cac++] = "-VUSES";
873 fp = dexec_open(cav, cac, &pid, NULL, 1, 1);
879 asprintf(&pkg->portdir, "%s/%s@%s", bulk->s1, bulk->s2, flavor);
881 asprintf(&pkg->portdir, "%s/%s", bulk->s1, bulk->s2);
884 while ((ptr = fgetln(fp, &len)) != NULL) {
885 if (len == 0 || ptr[len-1] != '\n') {
886 dfatal("Bad package info for %s/%s response line %d",
887 bulk->s1, bulk->s2, line);
892 case 1: /* PKGVERSION */
893 asprintf(&pkg->version, "%s", ptr);
895 case 2: /* PKGFILE */
896 asprintf(&pkg->pkgfile, "%s", ptr);
898 case 3: /* ALLFILES (aka DISTFILES + patch files) */
899 asprintf(&pkg->distfiles, "%s", ptr);
901 case 4: /* DIST_SUBDIR */
902 pkg->distsubdir = strdup_or_null(ptr);
904 case 5: /* MAKE_JOBS_NUMBER */
905 pkg->make_jobs_number = strtol(ptr, NULL, 0);
908 pkg->ignore = strdup_or_null(ptr);
910 case 7: /* FETCH_DEPENDS */
911 pkg->fetch_deps = strdup_or_null(ptr);
913 case 8: /* EXTRACT_DEPENDS */
914 pkg->ext_deps = strdup_or_null(ptr);
916 case 9: /* PATCH_DEPENDS */
917 pkg->patch_deps = strdup_or_null(ptr);
919 case 10: /* BUILD_DEPENDS */
920 pkg->build_deps = strdup_or_null(ptr);
922 case 11: /* LIB_DEPENDS */
923 pkg->lib_deps = strdup_or_null(ptr);
925 case 12: /* RUN_DEPENDS */
926 pkg->run_deps = strdup_or_null(ptr);
928 case 13: /* SELECTED_OPTIONS */
929 pkg->pos_options = strdup_or_null(ptr);
931 case 14: /* DESELECTED_OPTIONS */
932 pkg->neg_options = strdup_or_null(ptr);
934 case 15: /* USE_LINUX */
938 case 16: /* FLAVORS */
939 asprintf(&pkg->flavors, "%s", ptr);
942 asprintf(&pkg->uses, "%s", ptr);
943 if (strstr(pkg->uses, "metaport"))
944 pkg->flags |= PKGF_META;
947 printf("EXTRA LINE: %s\n", ptr);
953 printf("DPort not found: %s/%s\n", bulk->s1, bulk->s2);
954 pkg->flags |= PKGF_NOTFOUND;
955 } else if (line != 17 + 1) {
956 printf("DPort corrupt: %s/%s\n", bulk->s1, bulk->s2);
957 pkg->flags |= PKGF_CORRUPT;
959 if (dexec_close(fp, pid)) {
960 printf("make -V* command for %s/%s failed\n",
962 pkg->flags |= PKGF_CORRUPT;
969 if (bulk->s4 && bulk->s4[0] == 'd')
970 pkg->flags |= PKGF_DEBUGSTOP;
973 * Mark as a dummy node, the front-end will iterate the flavors
974 * and create sub-nodes for us.
976 * Get rid of elements returned that are for the first flavor.
977 * We are creating a dummy node here, not the node for the first
980 if (flavor == NULL && pkg->flavors && pkg->flavors[0]) {
981 pkg->flags |= PKGF_DUMMY;
982 freestrp(&pkg->fetch_deps);
983 freestrp(&pkg->ext_deps);
984 freestrp(&pkg->patch_deps);
985 freestrp(&pkg->build_deps);
986 freestrp(&pkg->lib_deps);
987 freestrp(&pkg->run_deps);
988 freestrp(&pkg->pkgfile);
992 * Only one pkg is put on the return list now. This code no
993 * longer creates pseudo-nodes for flavors (the frontend requests
994 * each flavor instead).
1000 * Query the package (at least to make sure it hasn't been truncated)
1001 * and mark it as PACKAGED if found.
1006 childGetBinaryDistInfo(bulk_t *bulk)
1012 const char *cav[MAXCAC];
1019 asprintf(&repopath, "%s/%s", RepositoryPath, bulk->s1);
1022 cav[cac++] = PKG_BINARY;
1023 cav[cac++] = "query";
1025 cav[cac++] = repopath;
1026 cav[cac++] = "%n-%v";
1028 fp = dexec_open(cav, cac, &pid, NULL, 1, 0);
1029 deleteme = DeleteObsoletePkgs;
1031 while ((ptr = fgetln(fp, &len)) != NULL) {
1032 if (len == 0 || ptr[len-1] != '\n')
1035 snprintf(buf, sizeof(buf), "%s%s", ptr, UsePkgSufx);
1037 pkg = pkg_find(buf);
1039 pkg->flags |= PKGF_PACKAGED;
1042 ddprintf(0, "Note: package scan, not in list, "
1043 "skipping %s\n", buf);
1046 if (dexec_close(fp, pid)) {
1047 printf("pkg query command failed for %s\n", repopath);
1050 dlog(DLOG_ALL | DLOG_STDOUT,
1051 "Deleting obsolete package %s\n", repopath);
1058 childOptimizeEnv(bulk_t *bulk)
1065 const char *cav[MAXCAC];
1069 asprintf(&portpath, "%s/%s/%s", DPortsPath, bulk->s1, bulk->s2);
1072 cav[cac++] = MAKE_BINARY;
1074 cav[cac++] = portpath;
1075 cav[cac++] = "-V_PERL5_FROM_BIN";
1077 fp = dexec_open(cav, cac, &pid, NULL, 1, 1);
1081 while ((ptr = fgetln(fp, &len)) != NULL) {
1082 if (len == 0 || ptr[len-1] != '\n') {
1083 dfatal("Bad package info for %s/%s response line %d",
1084 bulk->s1, bulk->s2, line);
1089 case 1: /* _PERL5_FROM_BIN */
1090 addbuildenv("_PERL5_FROM_BIN", ptr, BENV_ENVIRONMENT);
1093 printf("childOptimizeEnv: EXTRA LINE: %s\n", ptr);
1099 printf("DPort not found: %s/%s\n", bulk->s1, bulk->s2);
1100 } else if (line != 1 + 1) {
1101 printf("DPort corrupt: %s/%s\n", bulk->s1, bulk->s2);
1103 if (dexec_close(fp, pid)) {
1104 printf("childOptimizeEnv() failed\n");
1109 scan_and_queue_dir(const char *path, const char *level1, int level)
1118 dir = opendir(path);
1119 dassert(dir, "Cannot open dports path \"%s\"", path);
1121 while ((den = readdir(dir)) != NULL) {
1122 if (den->d_namlen == 1 && den->d_name[0] == '.')
1124 if (den->d_namlen == 2 &&
1125 den->d_name[0] == '.' && den->d_name[1] == '.')
1127 asprintf(&s1, "%s/%s", path, den->d_name);
1128 if (lstat(s1, &st) < 0 || !S_ISDIR(st.st_mode)) {
1133 count += scan_and_queue_dir(s1, den->d_name, 2);
1137 asprintf(&s2, "%s/Makefile", s1);
1138 if (lstat(s2, &st) == 0) {
1139 queuebulk(level1, den->d_name, NULL, NULL);
1151 scan_binary_repo(const char *path)
1159 dir = opendir(path);
1160 dassert(dir, "Cannot open repository path \"%s\"", path);
1163 * NOTE: Test includes the '.' in the suffix.
1165 while ((den = readdir(dir)) != NULL) {
1166 len = strlen(den->d_name);
1168 strcmp(den->d_name + len - 4, UsePkgSufx) == 0) {
1169 queuebulk(den->d_name, NULL, NULL, NULL);
1182 freestrp(&pkg->portdir);
1183 freestrp(&pkg->version);
1184 freestrp(&pkg->pkgfile);
1185 freestrp(&pkg->ignore);
1186 freestrp(&pkg->fetch_deps);
1187 freestrp(&pkg->ext_deps);
1188 freestrp(&pkg->patch_deps);
1189 freestrp(&pkg->build_deps);
1190 freestrp(&pkg->lib_deps);
1191 freestrp(&pkg->run_deps);
1192 freestrp(&pkg->pos_options);
1193 freestrp(&pkg->neg_options);
1194 freestrp(&pkg->flavors);