xref: /dragonfly/usr.bin/dsynth/repo.c (revision 6a3a20b1)
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 
451645cafeSMatthew Dillon static int pinfocmp(const void *s1, const void *s2);
461645cafeSMatthew Dillon static void scanit(const char *path, const char *subpath,
471645cafeSMatthew Dillon 			int *countp, pinfo_t ***list_tailp);
481645cafeSMatthew Dillon pinfo_t *pinfofind(pinfo_t **ary, int count, char *spath);
49f7f25838SMatthew Dillon static void scandeletenew(const char *path);
501645cafeSMatthew Dillon 
518e25f19bSMatthew Dillon void
521645cafeSMatthew Dillon DoRebuildRepo(int ask)
538e25f19bSMatthew Dillon {
541645cafeSMatthew Dillon 	char *buf;
551645cafeSMatthew Dillon 
561645cafeSMatthew Dillon 	if (ask) {
571645cafeSMatthew Dillon 		if (askyn("Rebuild the repository? ") == 0)
581645cafeSMatthew Dillon 			return;
591645cafeSMatthew Dillon 	}
60f7f25838SMatthew Dillon 
61f7f25838SMatthew Dillon 	/*
62f7f25838SMatthew Dillon 	 * Scan the repository for temporary .new files and delete them.
63f7f25838SMatthew Dillon 	 */
64f7f25838SMatthew Dillon 	scandeletenew(RepositoryPath);
65f7f25838SMatthew Dillon 
66f7f25838SMatthew Dillon 	/*
67f7f25838SMatthew Dillon 	 * Issue the repo command to rebuild the repo
68f7f25838SMatthew Dillon 	 */
691645cafeSMatthew Dillon 	asprintf(&buf, "pkg repo -o %s %s", PackagesPath, RepositoryPath);
701645cafeSMatthew Dillon 	printf("Rebuilding repository\n");
711645cafeSMatthew Dillon 	if (system(buf)) {
721645cafeSMatthew Dillon 		printf("Rebuild failed\n");
731645cafeSMatthew Dillon 	} else {
741645cafeSMatthew Dillon 		printf("Rebuild succeeded\n");
751645cafeSMatthew Dillon 	}
768e25f19bSMatthew Dillon }
778e25f19bSMatthew Dillon 
788e25f19bSMatthew Dillon void
798e25f19bSMatthew Dillon DoUpgradePkgs(pkg_t *pkgs __unused, int ask __unused)
808e25f19bSMatthew Dillon {
818e25f19bSMatthew Dillon 	dfatal("Not Implemented");
828e25f19bSMatthew Dillon }
838e25f19bSMatthew Dillon 
848e25f19bSMatthew Dillon void
851645cafeSMatthew Dillon PurgeDistfiles(pkg_t *pkgs)
868e25f19bSMatthew Dillon {
871645cafeSMatthew Dillon 	pinfo_t *list;
881645cafeSMatthew Dillon 	pinfo_t *item;
891645cafeSMatthew Dillon 	pinfo_t **list_tail;
901645cafeSMatthew Dillon 	pinfo_t **ary;
911645cafeSMatthew Dillon 	char *dstr;
921645cafeSMatthew Dillon 	char *buf;
931645cafeSMatthew Dillon 	int count;
941645cafeSMatthew Dillon 	int delcount;
951645cafeSMatthew Dillon 	int i;
961645cafeSMatthew Dillon 
971645cafeSMatthew Dillon 	printf("Scanning distfiles... ");
981645cafeSMatthew Dillon 	fflush(stdout);
991645cafeSMatthew Dillon 	count = 0;
1001645cafeSMatthew Dillon 	list = NULL;
1011645cafeSMatthew Dillon 	list_tail = &list;
1021645cafeSMatthew Dillon 	scanit(DistFilesPath, NULL, &count, &list_tail);
1031645cafeSMatthew Dillon 	printf("Checking %d distfiles\n", count);
1041645cafeSMatthew Dillon 	fflush(stdout);
1051645cafeSMatthew Dillon 
1061645cafeSMatthew Dillon 	ary = calloc(count, sizeof(pinfo_t *));
1071645cafeSMatthew Dillon 	for (i = 0; i < count; ++i) {
1081645cafeSMatthew Dillon 		ary[i] = list;
1091645cafeSMatthew Dillon 		list = list->next;
1101645cafeSMatthew Dillon 	}
1111645cafeSMatthew Dillon 	ddassert(list == NULL);
1121645cafeSMatthew Dillon 	qsort(ary, count, sizeof(pinfo_t *), pinfocmp);
1131645cafeSMatthew Dillon 
1141645cafeSMatthew Dillon 	for (; pkgs; pkgs = pkgs->bnext) {
1151645cafeSMatthew Dillon 		if (pkgs->distfiles == NULL || pkgs->distfiles[0] == 0)
1161645cafeSMatthew Dillon 			continue;
1171645cafeSMatthew Dillon 		ddprintf(0, "distfiles %s\n", pkgs->distfiles);
1181645cafeSMatthew Dillon 		dstr = strtok(pkgs->distfiles, " \t");
1191645cafeSMatthew Dillon 		while (dstr) {
1201645cafeSMatthew Dillon 			for (;;) {
1211645cafeSMatthew Dillon 				if (pkgs->distsubdir && pkgs->distsubdir[0]) {
1221645cafeSMatthew Dillon 					asprintf(&buf, "%s/%s",
1231645cafeSMatthew Dillon 						 pkgs->distsubdir, dstr);
1241645cafeSMatthew Dillon 					item = pinfofind(ary, count, buf);
1251645cafeSMatthew Dillon 					ddprintf(0, "TEST %s %p\n", buf, item);
1261645cafeSMatthew Dillon 					free(buf);
1271645cafeSMatthew Dillon 					buf = NULL;
1281645cafeSMatthew Dillon 				} else {
1291645cafeSMatthew Dillon 					item = pinfofind(ary, count, dstr);
1301645cafeSMatthew Dillon 					ddprintf(0, "TEST %s %p\n", dstr, item);
1311645cafeSMatthew Dillon 				}
1321645cafeSMatthew Dillon 				if (item) {
1331645cafeSMatthew Dillon 					item->foundit = 1;
1341645cafeSMatthew Dillon 					break;
1351645cafeSMatthew Dillon 				}
1361645cafeSMatthew Dillon 				if (strrchr(dstr, ':') == NULL)
1371645cafeSMatthew Dillon 					break;
1381645cafeSMatthew Dillon 				*strrchr(dstr, ':') = 0;
1391645cafeSMatthew Dillon 			}
1401645cafeSMatthew Dillon 			dstr = strtok(NULL, " \t");
1411645cafeSMatthew Dillon 		}
1421645cafeSMatthew Dillon 	}
1431645cafeSMatthew Dillon 
1441645cafeSMatthew Dillon 	delcount = 0;
1451645cafeSMatthew Dillon 	for (i = 0; i < count; ++i) {
1461645cafeSMatthew Dillon 		item = ary[i];
1471645cafeSMatthew Dillon 		if (item->foundit == 0) {
1481645cafeSMatthew Dillon 			++delcount;
1491645cafeSMatthew Dillon 		}
1501645cafeSMatthew Dillon 	}
1511645cafeSMatthew Dillon 	if (askyn("Delete %d of %d items? ", delcount, count)) {
1521645cafeSMatthew Dillon 		printf("Deleting %d/%d obsolete source distfiles\n",
1531645cafeSMatthew Dillon 		       delcount, count);
1541645cafeSMatthew Dillon 		for (i = 0; i < count; ++i) {
1551645cafeSMatthew Dillon 			item = ary[i];
1561645cafeSMatthew Dillon 			if (item->foundit == 0) {
1571645cafeSMatthew Dillon 				asprintf(&buf, "%s/%s",
1581645cafeSMatthew Dillon 					 DistFilesPath, item->spath);
1591645cafeSMatthew Dillon 				if (remove(buf) < 0)
1601645cafeSMatthew Dillon 					printf("Cannot delete %s\n", buf);
1611645cafeSMatthew Dillon 				free(buf);
1621645cafeSMatthew Dillon 			}
1631645cafeSMatthew Dillon 		}
1641645cafeSMatthew Dillon 	}
1651645cafeSMatthew Dillon 
1661645cafeSMatthew Dillon 
1671645cafeSMatthew Dillon 	free(ary);
1688e25f19bSMatthew Dillon }
1698e25f19bSMatthew Dillon 
1708e25f19bSMatthew Dillon void
1718e25f19bSMatthew Dillon RemovePackages(pkg_t *pkgs __unused)
1728e25f19bSMatthew Dillon {
1738e25f19bSMatthew Dillon 	dfatal("Not Implemented");
1748e25f19bSMatthew Dillon }
1751645cafeSMatthew Dillon 
1761645cafeSMatthew Dillon static int
1771645cafeSMatthew Dillon pinfocmp(const void *s1, const void *s2)
1781645cafeSMatthew Dillon {
1791645cafeSMatthew Dillon 	const pinfo_t *item1 = *(const pinfo_t *const*)s1;
1801645cafeSMatthew Dillon 	const pinfo_t *item2 = *(const pinfo_t *const*)s2;
1811645cafeSMatthew Dillon 
1821645cafeSMatthew Dillon 	return (strcmp(item1->spath, item2->spath));
1831645cafeSMatthew Dillon }
1841645cafeSMatthew Dillon 
1851645cafeSMatthew Dillon pinfo_t *
1861645cafeSMatthew Dillon pinfofind(pinfo_t **ary, int count, char *spath)
1871645cafeSMatthew Dillon {
1881645cafeSMatthew Dillon 	pinfo_t *item;
1891645cafeSMatthew Dillon 	int res;
1901645cafeSMatthew Dillon 	int b;
1911645cafeSMatthew Dillon 	int e;
1921645cafeSMatthew Dillon 	int m;
1931645cafeSMatthew Dillon 
1941645cafeSMatthew Dillon 	b = 0;
1951645cafeSMatthew Dillon 	e = count;
1961645cafeSMatthew Dillon 	while (b != e) {
1971645cafeSMatthew Dillon 		m = b + (e - b) / 2;
1981645cafeSMatthew Dillon 		item = ary[m];
1991645cafeSMatthew Dillon 		res = strcmp(spath, item->spath);
2001645cafeSMatthew Dillon 		if (res == 0)
2011645cafeSMatthew Dillon 			return item;
2021645cafeSMatthew Dillon 		if (res < 0) {
2031645cafeSMatthew Dillon 			e = m;
2041645cafeSMatthew Dillon 		} else {
2051645cafeSMatthew Dillon 			b = m + 1;
2061645cafeSMatthew Dillon 		}
2071645cafeSMatthew Dillon 	}
2081645cafeSMatthew Dillon 	return NULL;
2091645cafeSMatthew Dillon }
2101645cafeSMatthew Dillon 
2111645cafeSMatthew Dillon void
2121645cafeSMatthew Dillon scanit(const char *path, const char *subpath,
2131645cafeSMatthew Dillon        int *countp, pinfo_t ***list_tailp)
2141645cafeSMatthew Dillon {
2151645cafeSMatthew Dillon 	struct dirent *den;
2161645cafeSMatthew Dillon 	pinfo_t *item;
2171645cafeSMatthew Dillon 	char *npath;
2181645cafeSMatthew Dillon 	char *spath;
2191645cafeSMatthew Dillon 	DIR *dir;
2201645cafeSMatthew Dillon 	struct stat st;
2211645cafeSMatthew Dillon 
2221645cafeSMatthew Dillon 	if ((dir = opendir(path)) != NULL) {
2231645cafeSMatthew Dillon 		while ((den = readdir(dir)) != NULL) {
2241645cafeSMatthew Dillon 			if (den->d_namlen == 1 && den->d_name[0] == '.')
2251645cafeSMatthew Dillon 				continue;
2261645cafeSMatthew Dillon 			if (den->d_namlen == 2 && den->d_name[0] == '.' &&
2271645cafeSMatthew Dillon 			    den->d_name[1] == '.')
2281645cafeSMatthew Dillon 				continue;
2291645cafeSMatthew Dillon 			asprintf(&npath, "%s/%s", path, den->d_name);
2301645cafeSMatthew Dillon 			if (lstat(npath, &st) < 0) {
2311645cafeSMatthew Dillon 				free(npath);
2321645cafeSMatthew Dillon 				continue;
2331645cafeSMatthew Dillon 			}
2341645cafeSMatthew Dillon 			if (S_ISDIR(st.st_mode)) {
2351645cafeSMatthew Dillon 				if (subpath) {
2361645cafeSMatthew Dillon 					asprintf(&spath, "%s/%s",
2371645cafeSMatthew Dillon 						 subpath, den->d_name);
2381645cafeSMatthew Dillon 					scanit(npath, spath,
2391645cafeSMatthew Dillon 					       countp, list_tailp);
2401645cafeSMatthew Dillon 					free(spath);
2411645cafeSMatthew Dillon 				} else {
2421645cafeSMatthew Dillon 					scanit(npath, den->d_name,
2431645cafeSMatthew Dillon 					       countp, list_tailp);
2441645cafeSMatthew Dillon 				}
2451645cafeSMatthew Dillon 			} else if (S_ISREG(st.st_mode)) {
2461645cafeSMatthew Dillon 				item = calloc(1, sizeof(*item));
2471645cafeSMatthew Dillon 				if (subpath) {
2481645cafeSMatthew Dillon 					asprintf(&item->spath, "%s/%s",
2491645cafeSMatthew Dillon 						 subpath, den->d_name);
2501645cafeSMatthew Dillon 				} else {
2511645cafeSMatthew Dillon 					item->spath = strdup(den->d_name);
2521645cafeSMatthew Dillon 				}
2531645cafeSMatthew Dillon 				**list_tailp = item;
2541645cafeSMatthew Dillon 				*list_tailp = &item->next;
2551645cafeSMatthew Dillon 				++*countp;
2561645cafeSMatthew Dillon 				ddprintf(0, "scan   %s\n", item->spath);
2571645cafeSMatthew Dillon 			}
258*6a3a20b1SMatthew Dillon 			free(npath);
2591645cafeSMatthew Dillon 		}
2601645cafeSMatthew Dillon 		closedir(dir);
2611645cafeSMatthew Dillon 	}
2621645cafeSMatthew Dillon }
263f7f25838SMatthew Dillon 
264f7f25838SMatthew Dillon /*
265f7f25838SMatthew Dillon  * This removes any .new files left over in the repo.  These can wind
266f7f25838SMatthew Dillon  * being left around when dsynth is killed.
267f7f25838SMatthew Dillon  */
268f7f25838SMatthew Dillon static void
269f7f25838SMatthew Dillon scandeletenew(const char *path)
270f7f25838SMatthew Dillon {
271f7f25838SMatthew Dillon 	struct dirent *den;
272f7f25838SMatthew Dillon 	const char *ptr;
273f7f25838SMatthew Dillon 	DIR *dir;
274f7f25838SMatthew Dillon 	char *buf;
275f7f25838SMatthew Dillon 
276f7f25838SMatthew Dillon 	if ((dir = opendir(path)) == NULL)
277f7f25838SMatthew Dillon 		dfatal_errno("Cannot scan directory %s", path);
278f7f25838SMatthew Dillon 	while ((den = readdir(dir)) != NULL) {
279f7f25838SMatthew Dillon 		if ((ptr = strrchr(den->d_name, '.')) != NULL &&
280f7f25838SMatthew Dillon 		    strcmp(ptr, ".new") == 0) {
281f7f25838SMatthew Dillon 			asprintf(&buf, "%s/%s", path, den->d_name);
282f7f25838SMatthew Dillon 			if (remove(buf) < 0)
283f7f25838SMatthew Dillon 				dfatal_errno("remove: Garbage %s\n", buf);
284f7f25838SMatthew Dillon 			printf("Deleted Garbage %s\n", buf);
285f7f25838SMatthew Dillon 			free(buf);
286f7f25838SMatthew Dillon 		}
287f7f25838SMatthew Dillon 	}
288f7f25838SMatthew Dillon 	closedir(dir);
289f7f25838SMatthew Dillon }
290