Package: reprepro
Version: 4.13.1-1
Severity: wishlist
Tags: patch

Hi,

I've created a patch that makes it possible to manually add multiple
references at once.

I've tested the already implemented _addreference action by referencing all
i386 packages in Squeeze but aborted after waiting for about 20
minutes. Then I wrote _addreferences which takes multiple references
either as command line arguments or on stdin at once. This action
makes it possible to reference all of Squeeze i386 in just about 20 seconds.

Regards,

Lukas
From 8785b08a19cf5b840c94ac2ac15501e3759f5495 Mon Sep 17 00:00:00 2001
From: Lukas Anzinger <l.anzin...@gmail.com>
Date: Wed, 12 Feb 2014 18:39:18 +0100
Subject: [PATCH] Add parameter _addreferences to manually add multiple
 references.

If multiple references should be added using the _addreference command in a
loop or with xargs is extremely slow. _addreferences allows to either pass a
list of references on the command line or via stdin to circumvent ARG_MAX.
---
 docs/manual.html              |  1 +
 docs/reprepro.1               |  5 +++++
 docs/reprepro.bash_completion |  1 +
 docs/reprepro.zsh_completion  |  8 ++++++++
 main.c                        | 30 ++++++++++++++++++++++++++++++
 5 files changed, 45 insertions(+)

diff --git a/docs/manual.html b/docs/manual.html
index 23faa2c..97e4b51 100644
--- a/docs/manual.html
+++ b/docs/manual.html
@@ -1325,6 +1325,7 @@ Some low level commands to access this are (take a look at the manpage for how t
 <dt class="command">dumpreferences</dt><dd>print a list of all references</dd>
 <dt class="command">_removereferences</dt><dd>remove everything referenced by a given identifier</dd>
 <dt class="command">_addreference</dt><dd>manually add a reference</dd>
+<dt class="command">_addreferences</dt><dd>manually add multiple references</dd>
 </dl>
 <h3>files.db / checksums.db</h3>
 These files contains what reprepro knows about your <tt class="dir">pool/</tt> directory,
diff --git a/docs/reprepro.1 b/docs/reprepro.1
index 2ed9298..7c74c31 100644
--- a/docs/reprepro.1
+++ b/docs/reprepro.1
@@ -1092,6 +1092,11 @@ the corresponding Packages or Sources file would get)
 .BI "_addreference " filekey " " identifier
 Manually mark \fIfilekey\fP to be needed by \fIidentifier\fP
 .TP
+.BI "_addreferences " identifier " \fR[\fR " filekeys " \fR]\fR"
+Manually mark one or more \fIfilekeys\fP to be needed by \fIidentifier\fP.
+If no command line arguments are given,
+stdin is read and every line treated as one filekey.
+.TP
 .BI "_removereferences " identifier
 Remove all references what is needed by
 .I identifier.
diff --git a/docs/reprepro.bash_completion b/docs/reprepro.bash_completion
index f339d4e..b548cef 100644
--- a/docs/reprepro.bash_completion
+++ b/docs/reprepro.bash_completion
@@ -315,6 +315,7 @@ _reprepro()
 		       	_addchecksums\
 			_addpackage\
 		       	_addreference\
+			_addreferences\
 		       	_detect\
 		       	_dumpcontents\
 		       	_fakeemptyfilelist\
diff --git a/docs/reprepro.zsh_completion b/docs/reprepro.zsh_completion
index 00f47cd..8025420 100644
--- a/docs/reprepro.zsh_completion
+++ b/docs/reprepro.zsh_completion
@@ -266,6 +266,7 @@ hiddencommands=(
 	_addchecksums:"add checksums to database"
 	_addmd5sums:"add checksums to database"
 	_addreference:"mark a filekey needed by an identifier"
+	_addreferences:"mark multiple filekeys needed by an identifier"
 	_detect:"look if the file belonging to a filekey exists and add to the database."
 	_dumpcontents:"output contents of a part of the repository"
 	_fakeemptyfilelist:"create an empty fake filelist cache item for a filekey"
@@ -501,6 +502,13 @@ case "$state" in
 			_reprepro_identifiers
 		fi
 		;;
+	  (_addreferences)
+		if [[ "$state" = "first argument" ]] ; then
+			_reprepro_identifiers
+		elif [[ "$state" = "second argument" ]] ; then
+			_reprepro_filekeys
+		fi
+		;;
 	  (__uncompress)
 		if [[ "$state" = "first argument" ]] ; then
 			uncompressions=(.gz .bz2 .lzma .xz .lz)
diff --git a/main.c b/main.c
index 2965341..7009721 100644
--- a/main.c
+++ b/main.c
@@ -617,6 +617,34 @@ ACTION_R(n, n, n, y, addreference) {
 	return references_increment(argv[1], argv[2]);
 }
 
+ACTION_R(n, n, n, y, addreferences) {
+	char buffer[5000], *nl;
+	int i;
+	retvalue r, ret;
+
+	ret = RET_NOTHING;
+
+	if (argc > 2) {
+		for (i = 2 ; i < argc ; i++) {
+			const char *filename = argv[i];
+			r = references_increment(filename, argv[1]);
+			RET_UPDATE(ret, r);
+		}
+	} else {
+		while (fgets(buffer, 4999, stdin) != NULL) {
+			nl = strchr(buffer, '\n');
+			if (nl == NULL) {
+				return RET_ERROR;
+			}
+			*nl = '\0';
+			r = references_increment(buffer, argv[1]);
+			RET_UPDATE(ret, r);
+		}
+	}
+
+	return ret;
+}
+
 static retvalue remove_from_target(struct distribution *distribution, struct trackingdata *trackingdata, struct target *target, int count, const char * const *names, int *todo, bool *gotremoved) {
 	retvalue result, r;
 	int i;
@@ -3856,6 +3884,8 @@ static const struct action {
 		1, 1, "_removereferences <identifier>"},
 	{"_addreference", 	A__R(addreference),
 		2, 2, "_addreference <reference> <referee>"},
+	{"_addreferences", 	A__R(addreferences),
+		1, -1, "_addreferences <referee> <references>"},
 	{"_fakeemptyfilelist",	A__F(fakeemptyfilelist),
 		1, 1, "_fakeemptyfilelist <filekey>"},
 	{"_addpackage",		A_Dact(addpackage),
-- 
1.8.5.3

Reply via email to