[pacman-dev] [PATCH 1/5] Fix several issues with xdelta

Xavier Chantry shiningxc at gmail.com
Wed Feb 25 13:43:47 EST 2009


1) The changes to sync.c look big but there are mostly caused by
the indentation. Fix a bug where download_size == 0 because the packages and
deltas are already in the cache, but we still need to build the deltas list
and apply the deltas to create the final package.

2) Fix the gzip / md5sum issue by switching to xdelta3, disabling external
recompression and using gzip -n in pacman, and disable bsdtar compression
and using gzip -n in makepkg.

Signed-off-by: Xavier Chantry <shiningxc at gmail.com>
---
 doc/pacman.conf.5.txt |    2 +-
 lib/libalpm/delta.c   |    4 +-
 lib/libalpm/sync.c    |   98 +++++++++++++++++++++++--------------------------
 scripts/makepkg.sh.in |   28 +++-----------
 4 files changed, 55 insertions(+), 77 deletions(-)

diff --git a/doc/pacman.conf.5.txt b/doc/pacman.conf.5.txt
index fa21294..2f1fe3d 100644
--- a/doc/pacman.conf.5.txt
+++ b/doc/pacman.conf.5.txt
@@ -144,7 +144,7 @@ Options
 
 *UseDelta*::
 	Download delta files instead of complete packages if possible.  Requires
-	the xdelta program to be installed.
+	the xdelta3 program to be installed.
 
 *TotalDownload*::
 	When downloading, display the amount downloaded, download rate, ETA,
diff --git a/lib/libalpm/delta.c b/lib/libalpm/delta.c
index ff77501..337eb66 100644
--- a/lib/libalpm/delta.c
+++ b/lib/libalpm/delta.c
@@ -232,13 +232,13 @@ off_t _alpm_shortest_delta_path(alpm_list_t *deltas,
 		return(bestsize);
 	}
 
-	_alpm_log(PM_LOG_DEBUG, "started delta shortest-path search\n");
+	_alpm_log(PM_LOG_DEBUG, "started delta shortest-path search for '%s'\n", to);
 
 	vertices = delta_graph_init(deltas);
 
 	bestsize = delta_vert(vertices, to, to_md5, &bestpath);
 
-	_alpm_log(PM_LOG_DEBUG, "delta shortest-path search complete\n");
+	_alpm_log(PM_LOG_DEBUG, "delta shortest-path search complete : '%lld'\n", (long long)bestsize);
 
 	alpm_list_free_inner(vertices, _alpm_graph_free);
 	alpm_list_free(vertices);
diff --git a/lib/libalpm/sync.c b/lib/libalpm/sync.c
index 709a36d..71d8771 100644
--- a/lib/libalpm/sync.c
+++ b/lib/libalpm/sync.c
@@ -725,14 +725,9 @@ static int apply_deltas(pmtrans_t *trans)
 			CALLOC(to, len, sizeof(char), RET_ERR(PM_ERR_MEMORY, 1));
 			snprintf(to, len, "%s/%s", cachedir, d->to);
 
-			/* an example of the patch command: (using /cache for cachedir)
-			 * xdelta patch /path/to/pacman_3.0.0-1_to_3.0.1-1-i686.delta \
-			 *              /path/to/pacman-3.0.0-1-i686.pkg.tar.gz       \
-			 *              /cache/pacman-3.0.1-1-i686.pkg.tar.gz
-			 */
-
 			/* build the patch command */
-			snprintf(command, PATH_MAX, "xdelta patch %s %s %s", delta, from, to);
+			/* -R for disabling external recompression with gzip, -c for sending to stdout */
+			snprintf(command, PATH_MAX, "xdelta3 -d -q -R -c -s %s %s | gzip -n > %s", from, delta, to);
 
 			_alpm_log(PM_LOG_DEBUG, _("command: %s\n"), command);
 
@@ -848,29 +843,31 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
 
 				fname = alpm_pkg_get_filename(spkg);
 				ASSERT(fname != NULL, RET_ERR(PM_ERR_PKG_INVALID_NAME, -1));
-				if(spkg->download_size != 0) {
-					alpm_list_t *delta_path = spkg->delta_path;
-					if(delta_path) {
-						alpm_list_t *dlts = NULL;
-
-						for(dlts = delta_path; dlts; dlts = dlts->next) {
-							pmdelta_t *d = dlts->data;
-
-							if(d->download_size != 0) {
-								/* add the delta filename to the download list if
-								 * it's not in the cache */
-								files = alpm_list_add(files, strdup(d->delta));
-							}
-
-							/* keep a list of the delta files for md5sums */
-							deltas = alpm_list_add(deltas, d);
+				alpm_list_t *delta_path = spkg->delta_path;
+				if(delta_path) {
+					/* using deltas */
+					alpm_list_t *dlts = NULL;
+
+					for(dlts = delta_path; dlts; dlts = dlts->next) {
+						pmdelta_t *d = dlts->data;
+
+						if(d->download_size != 0) {
+							/* add the delta filename to the download list if needed */
+							files = alpm_list_add(files, strdup(d->delta));
 						}
 
-					} else {
-						/* not using deltas, so add the file to the download list */
+						/* keep a list of all the delta files for md5sums */
+						deltas = alpm_list_add(deltas, d);
+					}
+
+				} else {
+					/* not using deltas */
+					if(spkg->download_size != 0) {
+						/* add the filename to the download list if needed */
 						files = alpm_list_add(files, strdup(fname));
 					}
 				}
+
 			}
 		}
 
@@ -891,37 +888,34 @@ int _alpm_sync_commit(pmtrans_t *trans, pmdb_t *db_local, alpm_list_t **data)
 		handle->totaldlcb(0);
 	}
 
-	if(handle->usedelta) {
+	/* if we have deltas to work with */
+	if(handle->usedelta && deltas) {
 		int ret = 0;
-
-		/* only output if there are deltas to work with */
-		if(deltas) {
-			errors = 0;
-			/* Check integrity of deltas */
-			EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_START, NULL, NULL);
-
-			for(i = deltas; i; i = i->next) {
-				pmdelta_t *d = alpm_list_getdata(i);
-				const char *filename = alpm_delta_get_filename(d);
-				const char *md5sum = alpm_delta_get_md5sum(d);
-
-				if(test_md5sum(trans, filename, md5sum) != 0) {
-					errors++;
-					*data = alpm_list_add(*data, strdup(filename));
-				}
-			}
-			if(errors) {
-				pm_errno = PM_ERR_DLT_INVALID;
-				goto error;
+		errors = 0;
+		/* Check integrity of deltas */
+		EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_START, NULL, NULL);
+
+		for(i = deltas; i; i = i->next) {
+			pmdelta_t *d = alpm_list_getdata(i);
+			const char *filename = alpm_delta_get_filename(d);
+			const char *md5sum = alpm_delta_get_md5sum(d);
+
+			if(test_md5sum(trans, filename, md5sum) != 0) {
+				errors++;
+				*data = alpm_list_add(*data, strdup(filename));
 			}
-			EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_DONE, NULL, NULL);
+		}
+		if(errors) {
+			pm_errno = PM_ERR_DLT_INVALID;
+			goto error;
+		}
+		EVENT(trans, PM_TRANS_EVT_DELTA_INTEGRITY_DONE, NULL, NULL);
 
-			/* Use the deltas to generate the packages */
-			EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_START, NULL, NULL);
-			ret = apply_deltas(trans);
-			EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_DONE, NULL, NULL);
+		/* Use the deltas to generate the packages */
+		EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_START, NULL, NULL);
+		ret = apply_deltas(trans);
+		EVENT(trans, PM_TRANS_EVT_DELTA_PATCHES_DONE, NULL, NULL);
 
-		}
 		if(ret) {
 			pm_errno = PM_ERR_DLT_PATCHFAILED;
 			goto error;
diff --git a/scripts/makepkg.sh.in b/scripts/makepkg.sh.in
index 52e80d1..9e0f249 100644
--- a/scripts/makepkg.sh.in
+++ b/scripts/makepkg.sh.in
@@ -975,7 +975,7 @@ create_package() {
 	# the null string rather than itself
 	shopt -s nullglob
 
-	if ! bsdtar -c${TAR_OPT}f "$pkg_file" $comp_files *; then
+	if ! bsdtar -c${TAR_OPT}f - $comp_files * | gzip -n > "$pkg_file"; then
 		error "$(gettext "Failed to create package file.")"
 		exit 1 # TODO: error code
 	fi
@@ -985,8 +985,8 @@ create_package() {
 create_xdelta() {
 	if [ "$(check_buildenv xdelta)" != "y" ]; then
 		return
-	elif [ ! "$(type -p xdelta)" ]; then
-		error "$(gettext "Cannot find the xdelta binary! Is xdelta installed?")"
+	elif [ ! "$(type -p xdelta3)" ]; then
+		error "$(gettext "Cannot find the xdelta3 binary! Is xdelta3 installed?")"
 		return
 	fi
 
@@ -1020,25 +1020,9 @@ create_xdelta() {
 		local delta_file="$PKGDEST/$pkgname-${latest_version}_to_$pkgver-$pkgrel-$CARCH.delta"
 		local ret=0
 
-		# xdelta will decompress base_file & pkg_file into TMP_DIR (or /tmp if
-		# TMP_DIR is unset) then perform the delta on the resulting tars
-		xdelta delta "$base_file" "$pkg_file" "$delta_file" || ret=$?
-
-		if [ $ret -eq 0 -o $ret -eq 1 ]; then
-			# Generate the final gz using xdelta for compression. xdelta will be our
-			# common denominator compression utility between the packager and the
-			# users. makepkg and pacman must use the same compression algorithm or
-			# the delta generated package may not match, producing md5 checksum
-			# errors.
-			msg2 "$(gettext "Recreating package tarball from delta to match md5 signatures")"
-			msg2 "$(gettext "NOTE: the delta should ONLY be distributed with this tarball")"
-			ret=0
-			xdelta patch "$delta_file" "$base_file" "$pkg_file" || ret=$?
-			if [ $ret -ne 0 ]; then
-				error "$(gettext "Could not generate the package from the delta.")"
-				exit 1
-			fi
-		else
+		xdelta3 -s "$base_file" "$pkg_file" "$delta_file" || ret=$?
+
+		if [ $ret -ne 0 ]; then
 			warning "$(gettext "Delta was not able to be created.")"
 		fi
 	else
-- 
1.6.1.3



More information about the pacman-dev mailing list