18e25f19bSMatthew Dillon /* 28e25f19bSMatthew Dillon * Copyright (c) 2019 The DragonFly Project. All rights reserved. 38e25f19bSMatthew Dillon * 48e25f19bSMatthew Dillon * This code is derived from software contributed to The DragonFly Project 58e25f19bSMatthew Dillon * by Matthew Dillon <dillon@backplane.com> 68e25f19bSMatthew Dillon * 78e25f19bSMatthew Dillon * This code uses concepts and configuration based on 'synth', by 88e25f19bSMatthew Dillon * John R. Marino <draco@marino.st>, which was written in ada. 98e25f19bSMatthew Dillon * 108e25f19bSMatthew Dillon * Redistribution and use in source and binary forms, with or without 118e25f19bSMatthew Dillon * modification, are permitted provided that the following conditions 128e25f19bSMatthew Dillon * are met: 138e25f19bSMatthew Dillon * 148e25f19bSMatthew Dillon * 1. Redistributions of source code must retain the above copyright 158e25f19bSMatthew Dillon * notice, this list of conditions and the following disclaimer. 168e25f19bSMatthew Dillon * 2. Redistributions in binary form must reproduce the above copyright 178e25f19bSMatthew Dillon * notice, this list of conditions and the following disclaimer in 188e25f19bSMatthew Dillon * the documentation and/or other materials provided with the 198e25f19bSMatthew Dillon * distribution. 208e25f19bSMatthew Dillon * 3. Neither the name of The DragonFly Project nor the names of its 218e25f19bSMatthew Dillon * contributors may be used to endorse or promote products derived 228e25f19bSMatthew Dillon * from this software without specific, prior written permission. 238e25f19bSMatthew Dillon * 248e25f19bSMatthew Dillon * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 258e25f19bSMatthew Dillon * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 268e25f19bSMatthew Dillon * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 278e25f19bSMatthew Dillon * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 288e25f19bSMatthew Dillon * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 298e25f19bSMatthew Dillon * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 308e25f19bSMatthew Dillon * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 318e25f19bSMatthew Dillon * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 328e25f19bSMatthew Dillon * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 338e25f19bSMatthew Dillon * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 348e25f19bSMatthew Dillon * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 358e25f19bSMatthew Dillon * SUCH DAMAGE. 368e25f19bSMatthew Dillon */ 378e25f19bSMatthew Dillon #include "dsynth.h" 388e25f19bSMatthew Dillon 391645cafeSMatthew Dillon typedef struct pinfo { 401645cafeSMatthew Dillon struct pinfo *next; 411645cafeSMatthew Dillon char *spath; 421645cafeSMatthew Dillon int foundit; 431645cafeSMatthew Dillon } pinfo_t; 441645cafeSMatthew Dillon 45*f4094b20SMatthew Dillon static void removePackagesMetaRecurse(pkg_t *pkg); 461645cafeSMatthew Dillon static int pinfocmp(const void *s1, const void *s2); 471645cafeSMatthew Dillon static void scanit(const char *path, const char *subpath, 481645cafeSMatthew Dillon int *countp, pinfo_t ***list_tailp); 491645cafeSMatthew Dillon pinfo_t *pinfofind(pinfo_t **ary, int count, char *spath); 50f7f25838SMatthew Dillon static void scandeletenew(const char *path); 511645cafeSMatthew Dillon 528e25f19bSMatthew Dillon void 531645cafeSMatthew Dillon DoRebuildRepo(int ask) 548e25f19bSMatthew Dillon { 551645cafeSMatthew Dillon char *buf; 561645cafeSMatthew Dillon 571645cafeSMatthew Dillon if (ask) { 581645cafeSMatthew Dillon if (askyn("Rebuild the repository? ") == 0) 591645cafeSMatthew Dillon return; 601645cafeSMatthew Dillon } 61f7f25838SMatthew Dillon 62f7f25838SMatthew Dillon /* 63f7f25838SMatthew Dillon * Scan the repository for temporary .new files and delete them. 64f7f25838SMatthew Dillon */ 65f7f25838SMatthew Dillon scandeletenew(RepositoryPath); 66f7f25838SMatthew Dillon 67f7f25838SMatthew Dillon /* 68f7f25838SMatthew Dillon * Issue the repo command to rebuild the repo 69f7f25838SMatthew Dillon */ 701645cafeSMatthew Dillon asprintf(&buf, "pkg repo -o %s %s", PackagesPath, RepositoryPath); 711645cafeSMatthew Dillon printf("Rebuilding repository\n"); 721645cafeSMatthew Dillon if (system(buf)) { 731645cafeSMatthew Dillon printf("Rebuild failed\n"); 741645cafeSMatthew Dillon } else { 751645cafeSMatthew Dillon printf("Rebuild succeeded\n"); 761645cafeSMatthew Dillon } 778e25f19bSMatthew Dillon } 788e25f19bSMatthew Dillon 798e25f19bSMatthew Dillon void 808e25f19bSMatthew Dillon DoUpgradePkgs(pkg_t *pkgs __unused, int ask __unused) 818e25f19bSMatthew Dillon { 828e25f19bSMatthew Dillon dfatal("Not Implemented"); 838e25f19bSMatthew Dillon } 848e25f19bSMatthew Dillon 858e25f19bSMatthew Dillon void 861645cafeSMatthew Dillon PurgeDistfiles(pkg_t *pkgs) 878e25f19bSMatthew Dillon { 881645cafeSMatthew Dillon pinfo_t *list; 891645cafeSMatthew Dillon pinfo_t *item; 901645cafeSMatthew Dillon pinfo_t **list_tail; 911645cafeSMatthew Dillon pinfo_t **ary; 921645cafeSMatthew Dillon char *dstr; 931645cafeSMatthew Dillon char *buf; 941645cafeSMatthew Dillon int count; 951645cafeSMatthew Dillon int delcount; 961645cafeSMatthew Dillon int i; 971645cafeSMatthew Dillon 981645cafeSMatthew Dillon printf("Scanning distfiles... "); 991645cafeSMatthew Dillon fflush(stdout); 1001645cafeSMatthew Dillon count = 0; 1011645cafeSMatthew Dillon list = NULL; 1021645cafeSMatthew Dillon list_tail = &list; 1031645cafeSMatthew Dillon scanit(DistFilesPath, NULL, &count, &list_tail); 1041645cafeSMatthew Dillon printf("Checking %d distfiles\n", count); 1051645cafeSMatthew Dillon fflush(stdout); 1061645cafeSMatthew Dillon 1071645cafeSMatthew Dillon ary = calloc(count, sizeof(pinfo_t *)); 1081645cafeSMatthew Dillon for (i = 0; i < count; ++i) { 1091645cafeSMatthew Dillon ary[i] = list; 1101645cafeSMatthew Dillon list = list->next; 1111645cafeSMatthew Dillon } 1121645cafeSMatthew Dillon ddassert(list == NULL); 1131645cafeSMatthew Dillon qsort(ary, count, sizeof(pinfo_t *), pinfocmp); 1141645cafeSMatthew Dillon 1151645cafeSMatthew Dillon for (; pkgs; pkgs = pkgs->bnext) { 1161645cafeSMatthew Dillon if (pkgs->distfiles == NULL || pkgs->distfiles[0] == 0) 1171645cafeSMatthew Dillon continue; 1181645cafeSMatthew Dillon ddprintf(0, "distfiles %s\n", pkgs->distfiles); 1191645cafeSMatthew Dillon dstr = strtok(pkgs->distfiles, " \t"); 1201645cafeSMatthew Dillon while (dstr) { 1211645cafeSMatthew Dillon for (;;) { 1224ea2ee4dSMatthew Dillon if (pkgs->distsubdir) { 1231645cafeSMatthew Dillon asprintf(&buf, "%s/%s", 1241645cafeSMatthew Dillon pkgs->distsubdir, dstr); 1251645cafeSMatthew Dillon item = pinfofind(ary, count, buf); 1261645cafeSMatthew Dillon ddprintf(0, "TEST %s %p\n", buf, item); 1271645cafeSMatthew Dillon free(buf); 1281645cafeSMatthew Dillon buf = NULL; 1291645cafeSMatthew Dillon } else { 1301645cafeSMatthew Dillon item = pinfofind(ary, count, dstr); 1311645cafeSMatthew Dillon ddprintf(0, "TEST %s %p\n", dstr, item); 1321645cafeSMatthew Dillon } 1331645cafeSMatthew Dillon if (item) { 1341645cafeSMatthew Dillon item->foundit = 1; 1351645cafeSMatthew Dillon break; 1361645cafeSMatthew Dillon } 1371645cafeSMatthew Dillon if (strrchr(dstr, ':') == NULL) 1381645cafeSMatthew Dillon break; 1391645cafeSMatthew Dillon *strrchr(dstr, ':') = 0; 1401645cafeSMatthew Dillon } 1411645cafeSMatthew Dillon dstr = strtok(NULL, " \t"); 1421645cafeSMatthew Dillon } 1431645cafeSMatthew Dillon } 1441645cafeSMatthew Dillon 1451645cafeSMatthew Dillon delcount = 0; 1461645cafeSMatthew Dillon for (i = 0; i < count; ++i) { 1471645cafeSMatthew Dillon item = ary[i]; 1481645cafeSMatthew Dillon if (item->foundit == 0) { 1491645cafeSMatthew Dillon ++delcount; 1501645cafeSMatthew Dillon } 1511645cafeSMatthew Dillon } 1521645cafeSMatthew Dillon if (askyn("Delete %d of %d items? ", delcount, count)) { 1531645cafeSMatthew Dillon printf("Deleting %d/%d obsolete source distfiles\n", 1541645cafeSMatthew Dillon delcount, count); 1551645cafeSMatthew Dillon for (i = 0; i < count; ++i) { 1561645cafeSMatthew Dillon item = ary[i]; 1571645cafeSMatthew Dillon if (item->foundit == 0) { 1581645cafeSMatthew Dillon asprintf(&buf, "%s/%s", 1591645cafeSMatthew Dillon DistFilesPath, item->spath); 1601645cafeSMatthew Dillon if (remove(buf) < 0) 1611645cafeSMatthew Dillon printf("Cannot delete %s\n", buf); 1621645cafeSMatthew Dillon free(buf); 1631645cafeSMatthew Dillon } 1641645cafeSMatthew Dillon } 1651645cafeSMatthew Dillon } 1661645cafeSMatthew Dillon 1671645cafeSMatthew Dillon 1681645cafeSMatthew Dillon free(ary); 1698e25f19bSMatthew Dillon } 1708e25f19bSMatthew Dillon 1718e25f19bSMatthew Dillon void 172*f4094b20SMatthew Dillon RemovePackages(pkg_t *list) 1738e25f19bSMatthew Dillon { 174*f4094b20SMatthew Dillon pkg_t *scan; 175*f4094b20SMatthew Dillon char *path; 176*f4094b20SMatthew Dillon 177*f4094b20SMatthew Dillon for (scan = list; scan; scan = scan->bnext) { 178*f4094b20SMatthew Dillon if ((scan->flags & PKGF_MANUALSEL) == 0) 179*f4094b20SMatthew Dillon continue; 180*f4094b20SMatthew Dillon if (scan->pkgfile) { 181*f4094b20SMatthew Dillon scan->flags &= ~PKGF_PACKAGED; 182*f4094b20SMatthew Dillon scan->pkgfile_size = 0; 183*f4094b20SMatthew Dillon asprintf(&path, "%s/%s", RepositoryPath, scan->pkgfile); 184*f4094b20SMatthew Dillon if (remove(path) == 0) 185*f4094b20SMatthew Dillon printf("Removed: %s\n", path); 186*f4094b20SMatthew Dillon free(path); 187*f4094b20SMatthew Dillon } 188*f4094b20SMatthew Dillon if (scan->pkgfile == NULL || 189*f4094b20SMatthew Dillon (scan->flags & (PKGF_DUMMY | PKGF_META))) { 190*f4094b20SMatthew Dillon removePackagesMetaRecurse(scan); 191*f4094b20SMatthew Dillon } 192*f4094b20SMatthew Dillon } 193*f4094b20SMatthew Dillon } 194*f4094b20SMatthew Dillon 195*f4094b20SMatthew Dillon static void 196*f4094b20SMatthew Dillon removePackagesMetaRecurse(pkg_t *pkg) 197*f4094b20SMatthew Dillon { 198*f4094b20SMatthew Dillon pkglink_t *link; 199*f4094b20SMatthew Dillon pkg_t *scan; 200*f4094b20SMatthew Dillon char *path; 201*f4094b20SMatthew Dillon 202*f4094b20SMatthew Dillon PKGLIST_FOREACH(link, &pkg->idepon_list) { 203*f4094b20SMatthew Dillon scan = link->pkg; 204*f4094b20SMatthew Dillon if (scan == NULL) 205*f4094b20SMatthew Dillon continue; 206*f4094b20SMatthew Dillon if (scan->pkgfile == NULL || 207*f4094b20SMatthew Dillon (scan->flags & (PKGF_DUMMY | PKGF_META))) { 208*f4094b20SMatthew Dillon removePackagesMetaRecurse(scan); 209*f4094b20SMatthew Dillon continue; 210*f4094b20SMatthew Dillon } 211*f4094b20SMatthew Dillon scan->flags &= ~PKGF_PACKAGED; 212*f4094b20SMatthew Dillon scan->pkgfile_size = 0; 213*f4094b20SMatthew Dillon 214*f4094b20SMatthew Dillon asprintf(&path, "%s/%s", RepositoryPath, scan->pkgfile); 215*f4094b20SMatthew Dillon if (remove(path) == 0) 216*f4094b20SMatthew Dillon printf("Removed: %s\n", path); 217*f4094b20SMatthew Dillon free(path); 218*f4094b20SMatthew Dillon } 2198e25f19bSMatthew Dillon } 2201645cafeSMatthew Dillon 2211645cafeSMatthew Dillon static int 2221645cafeSMatthew Dillon pinfocmp(const void *s1, const void *s2) 2231645cafeSMatthew Dillon { 2241645cafeSMatthew Dillon const pinfo_t *item1 = *(const pinfo_t *const*)s1; 2251645cafeSMatthew Dillon const pinfo_t *item2 = *(const pinfo_t *const*)s2; 2261645cafeSMatthew Dillon 2271645cafeSMatthew Dillon return (strcmp(item1->spath, item2->spath)); 2281645cafeSMatthew Dillon } 2291645cafeSMatthew Dillon 2301645cafeSMatthew Dillon pinfo_t * 2311645cafeSMatthew Dillon pinfofind(pinfo_t **ary, int count, char *spath) 2321645cafeSMatthew Dillon { 2331645cafeSMatthew Dillon pinfo_t *item; 2341645cafeSMatthew Dillon int res; 2351645cafeSMatthew Dillon int b; 2361645cafeSMatthew Dillon int e; 2371645cafeSMatthew Dillon int m; 2381645cafeSMatthew Dillon 2391645cafeSMatthew Dillon b = 0; 2401645cafeSMatthew Dillon e = count; 2411645cafeSMatthew Dillon while (b != e) { 2421645cafeSMatthew Dillon m = b + (e - b) / 2; 2431645cafeSMatthew Dillon item = ary[m]; 2441645cafeSMatthew Dillon res = strcmp(spath, item->spath); 2451645cafeSMatthew Dillon if (res == 0) 2461645cafeSMatthew Dillon return item; 2471645cafeSMatthew Dillon if (res < 0) { 2481645cafeSMatthew Dillon e = m; 2491645cafeSMatthew Dillon } else { 2501645cafeSMatthew Dillon b = m + 1; 2511645cafeSMatthew Dillon } 2521645cafeSMatthew Dillon } 2531645cafeSMatthew Dillon return NULL; 2541645cafeSMatthew Dillon } 2551645cafeSMatthew Dillon 2561645cafeSMatthew Dillon void 2571645cafeSMatthew Dillon scanit(const char *path, const char *subpath, 2581645cafeSMatthew Dillon int *countp, pinfo_t ***list_tailp) 2591645cafeSMatthew Dillon { 2601645cafeSMatthew Dillon struct dirent *den; 2611645cafeSMatthew Dillon pinfo_t *item; 2621645cafeSMatthew Dillon char *npath; 2631645cafeSMatthew Dillon char *spath; 2641645cafeSMatthew Dillon DIR *dir; 2651645cafeSMatthew Dillon struct stat st; 2661645cafeSMatthew Dillon 2671645cafeSMatthew Dillon if ((dir = opendir(path)) != NULL) { 2681645cafeSMatthew Dillon while ((den = readdir(dir)) != NULL) { 2691645cafeSMatthew Dillon if (den->d_namlen == 1 && den->d_name[0] == '.') 2701645cafeSMatthew Dillon continue; 2711645cafeSMatthew Dillon if (den->d_namlen == 2 && den->d_name[0] == '.' && 2721645cafeSMatthew Dillon den->d_name[1] == '.') 2731645cafeSMatthew Dillon continue; 2741645cafeSMatthew Dillon asprintf(&npath, "%s/%s", path, den->d_name); 2751645cafeSMatthew Dillon if (lstat(npath, &st) < 0) { 2761645cafeSMatthew Dillon free(npath); 2771645cafeSMatthew Dillon continue; 2781645cafeSMatthew Dillon } 2791645cafeSMatthew Dillon if (S_ISDIR(st.st_mode)) { 2801645cafeSMatthew Dillon if (subpath) { 2811645cafeSMatthew Dillon asprintf(&spath, "%s/%s", 2821645cafeSMatthew Dillon subpath, den->d_name); 2831645cafeSMatthew Dillon scanit(npath, spath, 2841645cafeSMatthew Dillon countp, list_tailp); 2851645cafeSMatthew Dillon free(spath); 2861645cafeSMatthew Dillon } else { 2871645cafeSMatthew Dillon scanit(npath, den->d_name, 2881645cafeSMatthew Dillon countp, list_tailp); 2891645cafeSMatthew Dillon } 2901645cafeSMatthew Dillon } else if (S_ISREG(st.st_mode)) { 2911645cafeSMatthew Dillon item = calloc(1, sizeof(*item)); 2921645cafeSMatthew Dillon if (subpath) { 2931645cafeSMatthew Dillon asprintf(&item->spath, "%s/%s", 2941645cafeSMatthew Dillon subpath, den->d_name); 2951645cafeSMatthew Dillon } else { 2961645cafeSMatthew Dillon item->spath = strdup(den->d_name); 2971645cafeSMatthew Dillon } 2981645cafeSMatthew Dillon **list_tailp = item; 2991645cafeSMatthew Dillon *list_tailp = &item->next; 3001645cafeSMatthew Dillon ++*countp; 3011645cafeSMatthew Dillon ddprintf(0, "scan %s\n", item->spath); 3021645cafeSMatthew Dillon } 3036a3a20b1SMatthew Dillon free(npath); 3041645cafeSMatthew Dillon } 3051645cafeSMatthew Dillon closedir(dir); 3061645cafeSMatthew Dillon } 3071645cafeSMatthew Dillon } 308f7f25838SMatthew Dillon 309f7f25838SMatthew Dillon /* 310f7f25838SMatthew Dillon * This removes any .new files left over in the repo. These can wind 311f7f25838SMatthew Dillon * being left around when dsynth is killed. 312f7f25838SMatthew Dillon */ 313f7f25838SMatthew Dillon static void 314f7f25838SMatthew Dillon scandeletenew(const char *path) 315f7f25838SMatthew Dillon { 316f7f25838SMatthew Dillon struct dirent *den; 317f7f25838SMatthew Dillon const char *ptr; 318f7f25838SMatthew Dillon DIR *dir; 319f7f25838SMatthew Dillon char *buf; 320f7f25838SMatthew Dillon 321f7f25838SMatthew Dillon if ((dir = opendir(path)) == NULL) 322f7f25838SMatthew Dillon dfatal_errno("Cannot scan directory %s", path); 323f7f25838SMatthew Dillon while ((den = readdir(dir)) != NULL) { 324f7f25838SMatthew Dillon if ((ptr = strrchr(den->d_name, '.')) != NULL && 325f7f25838SMatthew Dillon strcmp(ptr, ".new") == 0) { 326f7f25838SMatthew Dillon asprintf(&buf, "%s/%s", path, den->d_name); 327f7f25838SMatthew Dillon if (remove(buf) < 0) 328f7f25838SMatthew Dillon dfatal_errno("remove: Garbage %s\n", buf); 329f7f25838SMatthew Dillon printf("Deleted Garbage %s\n", buf); 330f7f25838SMatthew Dillon free(buf); 331f7f25838SMatthew Dillon } 332f7f25838SMatthew Dillon } 333f7f25838SMatthew Dillon closedir(dir); 334f7f25838SMatthew Dillon } 335