summarylogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.SRCINFO19
-rw-r--r--PKGBUILD34
-rw-r--r--pkgcacheclean.840
-rw-r--r--pkgcacheclean.c347
4 files changed, 28 insertions, 412 deletions
diff --git a/.SRCINFO b/.SRCINFO
index 22af4499bc13..20ef9ca66bb5 100644
--- a/.SRCINFO
+++ b/.SRCINFO
@@ -1,17 +1,16 @@
-# Generated by mksrcinfo v8
-# Thu Sep 7 12:13:40 UTC 2017
pkgbase = pkgcacheclean
- pkgdesc = Application to clean the pacman cache
+ pkgdesc = Application to clean the pacman package cache
pkgver = 1.9.0
- pkgrel = 2
- url = https://bbs.archlinux.org/viewtopic.php?pid=841774
- arch = any
+ pkgrel = 3
+ url = https://github.com/dbermond/pkgcacheclean/
+ arch = x86_64
license = GPL
depends = pacman>=5
- source = pkgcacheclean.c
- source = pkgcacheclean.8
- md5sums = e4d09851f6052beab8179b88e21e2f6b
- md5sums = 965889f755e4611c12f8c9ac0048372d
+ source = pkgcacheclean-1.9.0.tar.gz::https://github.com/dbermond/pkgcacheclean/archive/v1.9.0.tar.gz
+ source = https://github.com/dbermond/pkgcacheclean/releases/download/v1.9.0/pkgcacheclean-1.9.0.tar.gz.asc
+ validpgpkeys = 3FFA6AB7B69AAE6CCA263DDE019A7474297D8577
+ sha256sums = 0efa1183ad556d26f5d7dbb8f34b8f6b0a6fdf0060f345e320db53b8804424e5
+ sha256sums = SKIP
pkgname = pkgcacheclean
diff --git a/PKGBUILD b/PKGBUILD
index bb723be8e521..cdb0e9abe9d8 100644
--- a/PKGBUILD
+++ b/PKGBUILD
@@ -1,28 +1,32 @@
-# Maintainer: Auguste Pop <auguste [at] gmail [dot] com>
+# Maintainer : Daniel Bermond < gmail-com: danielbermond >
+# Contributor: Wojciech OchmaƄski <wojciech.ochmanski@gmail.com>
+# Contributor: Fredrik Strandin <fredrik@strandin.name>
+# Contributor: Auguste Pop <auguste [at] gmail [dot] com>
pkgname=pkgcacheclean
pkgver=1.9.0
-pkgrel=2
-pkgdesc="Application to clean the pacman cache"
-arch=('any')
-url='https://bbs.archlinux.org/viewtopic.php?pid=841774'
+pkgrel=3
+pkgdesc='Application to clean the pacman package cache'
+arch=('x86_64')
+url='https://github.com/dbermond/pkgcacheclean/'
license=('GPL')
depends=('pacman>=5')
-source=($pkgname.c
- $pkgname.8)
-md5sums=('e4d09851f6052beab8179b88e21e2f6b'
- '965889f755e4611c12f8c9ac0048372d')
+source=("${pkgname}-${pkgver}.tar.gz"::"https://github.com/dbermond/pkgcacheclean/archive/v${pkgver}.tar.gz"
+ "https://github.com/dbermond/pkgcacheclean/releases/download/v${pkgver}/pkgcacheclean-${pkgver}.tar.gz.asc")
+sha256sums=('0efa1183ad556d26f5d7dbb8f34b8f6b0a6fdf0060f345e320db53b8804424e5'
+ 'SKIP')
+validpgpkeys=('3FFA6AB7B69AAE6CCA263DDE019A7474297D8577') # Daniel Bermond
build()
{
- cd "$srcdir"
- gcc -o $pkgname $CFLAGS -DVERSION=\"$pkgver\" -DCARCH=\"$CARCH\" \
- $pkgname.c -lalpm $LDFLAGS
- gzip --keep --force $pkgname.8
+ cd "${pkgname}-${pkgver}"
+
+ make
}
package()
{
- install -m 755 -D "$srcdir/$pkgname" "$pkgdir/usr/bin/$pkgname"
- install -m 644 -D "$srcdir/$pkgname.8.gz" "$pkgdir/usr/share/man/man8/$pkgname.8.gz"
+ cd "${pkgname}-${pkgver}"
+
+ make DESTDIR="$pkgdir" PREFIX='/usr' install
}
diff --git a/pkgcacheclean.8 b/pkgcacheclean.8
deleted file mode 100644
index d2d1c5e125ac..000000000000
--- a/pkgcacheclean.8
+++ /dev/null
@@ -1,40 +0,0 @@
-.TH pkgcacheclean 8 "2016-05-22" "pkgcacheclean 1.8.2" "pkgcacheclean manual"
-.SH NAME
-pkgcacheclean \- a simple utility to clean pacman cache
-.SH SYNOPSIS
-.B pkgcacheclean
-[option...] [preserve_number]
-.SH DESCRIPTION
-For installed packages, \fIpreserve_number\fR of versions are reserved. This
-includes the current version and the newest (\fIpreserve_number\fR - 1) of the
-remaining. For uninstalled packages all versions are deleted. The default
-number is 2.
-.SH OPTIONS
-.TP
-\-n, \-\-dry-run
-Perform a trial run with no changes made
-.TP
-\-d, \-\-cachedir=PATH
-Set alternative (absolute) cache directory PATH. Default is /var/cache/pacman/pkg/
-.TP
-\-k, \-\-all\-as\-installed
-Treat not-installed packages as installed
-.TP
-\-v, \-\-verbose
-Verbose output
-.TP
-\-q, \-\-quiet
-Suppress output, default
-.TP
-\-?, \-\-help
-Give a help list
-.TP
-\-\-usage
-Give a short usage message
-.TP
-\-V, \-\-version
-Print program version
-.SH EXAMPLES
-.TP
-Do a verbose dry-run for cleaning up all but the latest 3 versions:
-.B pkgcacheclean -nv 3
diff --git a/pkgcacheclean.c b/pkgcacheclean.c
deleted file mode 100644
index 36996df78338..000000000000
--- a/pkgcacheclean.c
+++ /dev/null
@@ -1,347 +0,0 @@
-#include <argp.h>
-#include <dirent.h>
-#include <inttypes.h>
-#include <limits.h>
-#include <regex.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <unistd.h>
-
-#include <alpm.h>
-
-#define ROOT "/"
-#define DBPATH "/var/lib/pacman/"
-#define CACHEDIR "/var/cache/pacman/pkg/"
-
-/*
- * This is a very stupid and simple limit of the longest human readable file
- * size. Maximum file size that will be representable will be:
- * 999.9 YiB\0
- * which "should be enough".
- */
-#define LONGEST_HUMAN_READABLE 10
-#define NUM_HUMAN_READABLE_UNITS 9
-
-const char *argp_program_version = "pkgcacheclean "VERSION;
-const char *argp_program_bug_address = "auguste@gmail.com";
-
-static char doc[] =
- "pkgcacheclean -- a simple utility to clean pacman cache.\v"
- "For installed packages, preserve_number of versions are reserved. This\n"
- "includes the current version and the newest (preserve_number - 1) of\n"
- "the remaining. For uninstalled packages all versions are deleted.\n"
- "The default number is 2.";
-static char args_doc[] = "[preserve_number]";
-
-static struct argp_option options[] =
-{
- { .doc = "" },
- { .name = "dry-run", .key = 'n', .doc = "Perform a trial run with no changes made" },
- { .name = "cachedir", .key = 'd', .arg = "PATH",
- .doc = "Set alternative (absolute) cache directory PATH. Default is "CACHEDIR },
- { .name = "all-as-installed", .key = 'k',
- .doc = "Treat not-installed packages as installed" },
- { .name = "verbose", .key = 'v', .doc = "Verbose output" },
- { .name = "human-readable", .key = 'h', .doc = "Human readable file size" },
- { .name = "quiet", .key = 'q', .doc = "Suppress output, default" },
- { .doc = NULL }
-};
-
-static regex_t pkgnamesplit;
-static regex_t pkgnametest;
-
-struct pkginfo
-{
- char *name;
- char *version;
- char *filename;
-};
-
-struct arguments
-{
- int dry_run;
- int preserve;
- int keep;
- int verbose;
- int human_readable;
- char *cachedir;
-};
-
-static char *dupsubstr(const char *str, const int start, const int end)
-{
- char *ret;
- const size_t len = (size_t)(end - start);
-
- ret = (char *)malloc(sizeof(char) * (len + 1));
- strncpy(ret, str + start, len);
- ret[len] = '\0';
-
- return ret;
-}
-
-static struct pkginfo * get_pkginfo_from_filename(const char * const filename)
-{
- struct pkginfo *ret;
- static regmatch_t match[3];
-
- ret = (struct pkginfo *)malloc(sizeof(struct pkginfo));
- regexec(&pkgnamesplit, filename, 3, match, 0);
- ret->name = dupsubstr(filename, match[1].rm_so, match[1].rm_eo);
- ret->version = dupsubstr(filename, match[2].rm_so, match[2].rm_eo);
- ret->filename = strdup(filename);
-
- return ret;
-}
-
-static struct pkginfo * get_pkginfo_from_pmpkg(alpm_pkg_t *pmpkg)
-{
- struct pkginfo *ret;
-
- ret = (struct pkginfo *)malloc(sizeof(struct pkginfo));
- ret->name = strdup(alpm_pkg_get_name(pmpkg));
- ret->version = strdup(alpm_pkg_get_version(pmpkg));
- ret->filename = NULL;
-
- return ret;
-}
-
-static void free_pkginfo(struct pkginfo * pkg)
-{
- free(pkg->name);
- free(pkg->version);
- free(pkg->filename);
- free(pkg);
-}
-
-static int pkgcomp(const void *a, const void *b)
-{
- struct pkginfo *ap = *(struct pkginfo **)a;
- struct pkginfo *bp = *(struct pkginfo **)b;
-
- int namecomp = strcmp(ap->name, bp->name);
-
- return namecomp ? namecomp : -alpm_pkg_vercmp(ap->version,
- bp->version);
-}
-
-static int pkgnamecomp(const void *a, const void *b)
-{
- return strcmp((*(struct pkginfo **)a)->name,
- (*(struct pkginfo **)b)->name);
-}
-
-static int ispackage(const struct dirent *file)
-{
- return regexec(&pkgnametest, file->d_name, 0, NULL, 0) == 0;
-}
-
-static void free_pkginfo_array(struct pkginfo **pkgs, const size_t n)
-{
- size_t i;
-
- for (i = 0; i < n; i++)
- free_pkginfo(pkgs[i]);
- free(pkgs);
-}
-
-static off_t get_file_size(const char *filename)
-{
- struct stat st;
-
- stat(filename, &st);
- return st.st_size;
-}
-
-static void human_readable(off_t total_size, char* buf)
-{
- const char* units[NUM_HUMAN_READABLE_UNITS] = {
- "B",
- "KiB",
- "MiB",
- "GiB",
- "TiB",
- "PiB",
- "EiB",
- "ZiB",
- "YiB"
- };
- unsigned char num_divisions = 0;
- float human_size = total_size;
-
- while (human_size > 1024 && num_divisions < (NUM_HUMAN_READABLE_UNITS - 1))
- {
- human_size /= 1024;
- num_divisions++;
- }
-
- snprintf(buf, LONGEST_HUMAN_READABLE, "%.1f %s",
- human_size,
- units[num_divisions]);
-}
-
-static error_t parse_opt(int key, char *arg, struct argp_state *state)
-{
- struct arguments *argument = (struct arguments *)(state -> input);
-
- switch (key)
- {
- case 'n':
- argument->dry_run = 1;
- break;
- case 'v':
- argument->verbose = 1;
- break;
- case 'h':
- argument->human_readable = 1;
- break;
- case 'k':
- argument->keep = 1;
- case 'q':
- argument->verbose = 0;
- break;
- case 'd':
- argument->cachedir = arg;
- break;
- case ARGP_KEY_ARG:
- if (argument->preserve)
- return ARGP_ERR_UNKNOWN;
- argument->preserve = atoi(arg);
- if (argument->preserve <= 0)
- return ARGP_ERR_UNKNOWN;
- break;
- default:
- return ARGP_ERR_UNKNOWN;
- }
-
- return 0;
-}
-
-int main(const int argc, char ** __restrict__ argv)
-{
- int count = 0;
- size_t i, len, m = 0, n;
- off_t total_size = 0;
- alpm_handle_t *handle;
- struct stat st;
- struct dirent **dir;
- enum _alpm_errno_t error;
- struct pkginfo **cachepkg, **localpkg = NULL;
- struct pkginfo **hit = NULL;
- const char *current = "", *name;
- char cachedir[PATH_MAX] = CACHEDIR;
- char human_readable_buf[LONGEST_HUMAN_READABLE];
- struct argp arg_parser = { .options = options, .parser = parse_opt,
- .args_doc = args_doc, .doc = doc };
- struct arguments args = { .dry_run = 0, .preserve = 0, .keep = 0,
- .verbose = 0, .human_readable = 0,
- .cachedir = NULL };
-
- argp_parse(&arg_parser, argc, argv, 0, NULL, &args);
- if (!args.preserve)
- args.preserve = 2;
-
- if (!args.dry_run && getuid())
- {
- puts("please run as root.");
- exit(EXIT_FAILURE);
- }
-
- if (args.cachedir)
- strcpy(cachedir, args.cachedir);
- if (!((stat(cachedir, &st) == 0) && ((st.st_mode & S_IFMT) == S_IFDIR)))
- {
- printf("Cache directory does not exist or is not a valid directory: "
- "\"%s\".\n", cachedir);
- exit(EXIT_FAILURE);
- }
- len = strlen(cachedir);
- if (len && cachedir[len - 1] != '/')
- {
- cachedir[len] = '/';
- cachedir[++len] = '\0';
- }
- regcomp(&pkgnamesplit, "^(.*)-([^-]*-[^-]*)-[^-]*$", REG_EXTENDED);
- regcomp(&pkgnametest, "^.*-("CARCH"|any).[^-]*$", REG_EXTENDED);
-
- handle = alpm_initialize(ROOT, DBPATH, &error);
-
- n = (size_t)scandir(cachedir, &dir, ispackage, NULL);
- cachepkg = (struct pkginfo **)malloc(sizeof(struct pkginfo *) * n);
- for (i = 0; i < n; free(dir[i]), i++)
- cachepkg[i] = get_pkginfo_from_filename(dir[i]->d_name);
- free(dir);
- qsort(cachepkg, n, sizeof(struct pkginfo *), pkgcomp);
-
- if (!args.keep)
- {
- alpm_db_t *db;
- alpm_list_t *pkglist;
-
- db = alpm_get_localdb(handle);
- pkglist = alpm_db_get_pkgcache(db);
- m = alpm_list_count(pkglist);
- localpkg = (struct pkginfo **)malloc(sizeof(struct pkginfo *) * m);
- for (i = 0; i < m; i++, pkglist = alpm_list_next(pkglist))
- localpkg[i] = get_pkginfo_from_pmpkg((alpm_pkg_t *)(pkglist->data));
- qsort(localpkg, m, sizeof(struct pkginfo *), pkgnamecomp);
- }
-
- for (i = 0; i < n; i++)
- {
- name = cachepkg[i]->name;
- if (strcmp(name, current))
- {
- current = name;
- if (args.keep)
- {
- int j;
- for (j = (int)i - 1; j >= 0; j--)
- if (pkgnamecomp(cachepkg + i, cachepkg + j))
- break;
- hit = cachepkg + j + 1;
- count = 0;
- }
- else
- {
- hit = (struct pkginfo **)bsearch(cachepkg + i, localpkg, m,
- sizeof(struct pkginfo *), pkgnamecomp);
- count = hit ? 0 : args.preserve;
- }
- }
- if (!hit || alpm_pkg_vercmp((*hit)->version,
- cachepkg[i]->version))
- {
- count++;
- if (count >= args.preserve)
- {
- strcpy(cachedir + len, cachepkg[i]->filename);
- if (args.verbose)
- printf("remove: %s\n", cachepkg[i]->filename);
- if (args.verbose || args.human_readable)
- total_size += get_file_size(cachedir);
- if (!args.dry_run)
- unlink(cachedir);
- }
- }
- }
-
- if (args.human_readable)
- {
- human_readable(total_size, human_readable_buf);
- printf("\ntotal: %s\n", human_readable_buf);
- }
- else if (args.verbose)
- printf("\ntotal: %"PRIuMAX" bytes\n", (uintmax_t)total_size);
-
- free_pkginfo_array(cachepkg, n);
- if (!args.keep)
- free_pkginfo_array(localpkg, m);
-
- alpm_release(handle);
- regfree(&pkgnametest);
- regfree(&pkgnamesplit);
-
- return EXIT_SUCCESS;
-}