Project

General

Profile

« Previous | Next » 

Revision cac80f49

Added by Phil Davis almost 10 years ago

Provide compare_pkg_versions

This function parses and compares two strings to see which one seems to represent the greater "version". It splits the strings into pieces that are digits and pieces that are anything else. e.g.
"utility-24.9_5 pkg v4.5"
becomes
"utility-"
24
"."
9
"_"
5
" pkg v"
4
"."
5

A new version might be:
"utility-24.10_5 pkg v4.5"

Each component is compared.
If both corresponding components are "integer chunks" they are compared using "<" and ">" - that means that 10 becomes greater than 9.
If either component is not "integer" then string comparison is done. This makes the ordinary string changes work as expected and also stuff like "1.05" and "1.1" - a change like this will be seen as an upgrade.

Not that I have left the string comparison case-sensitive. If someone making their version string changes the "fixed text" they have put in the version string then anything is possible :) It is a bit difficult to guess all of that.

Also if people use alphabetic versioning that does not follow strcmp() sort order then there is always trouble - it works by luck with "-BETA" then "-RELEASE" because the English words happen to sort as expected.

View differences:

etc/inc/pkg-utils.inc
209 209
	return array();
210 210
}
211 211

  
212
/****f* pkg-utils/compare_pkg_versions
213
 * NAME
214
 *   compare_pkg_versions - Decide if the installed package is newer, the same or older than the available package.
215
 * INPUTS
216
 *   $installed_pkg_ver - the package version installed on the system.
217
 *   $available_pkg_ver - the package version available from the package server.
218
 * RESULT
219
 *   -1 - the installed package is older (an upgrade is available)
220
 *   0 - the package versions are the same
221
 *   1 - the installed package is newer (somebody has installed a newer version than is officially available)
222
 ******/
223
function compare_pkg_versions($installed_pkg_ver, $available_pkg_ver) {
224
	// If the strings are the same then short-cut all the processing.
225
	if (strcmp($installed_pkg_ver, $available_pkg_ver) == 0) {
226
		return 0;
227
	}
228

  
229
	// Split into pieces that are groups of digits and groups of non-digits.
230
	$installed_arr = preg_split( '/([0-9]+)/', $installed_pkg_ver, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
231
	$available_arr = preg_split( '/([0-9]+)/', $available_pkg_ver, -1, PREG_SPLIT_DELIM_CAPTURE | PREG_SPLIT_NO_EMPTY);
232
	foreach ($installed_arr as $n => $val) {
233
		if (array_key_exists($n, $available_arr)) {
234
			// Check if this piece looks like a genuine integer like "123", "0" rather than "05", "005", "1a", "abc".
235
			// Note: At this point the pieces cannot be like "-1", "+1" so we do not need to worry about those possibilities that filter_var() will see as "genuine integers".
236
			$val1_as_int = filter_var($val, FILTER_VALIDATE_INT);
237
			$val2_as_int = filter_var($available_arr[$n], FILTER_VALIDATE_INT);
238
			if (($val1_as_int === false) || ($val2_as_int === false)) {
239
				// One of them does not look like a genuine integer so use string comparison.
240
				if (strcmp($val, $available_arr[$n]) > 0) {
241
					return 1;
242
				} elseif (strcmp($val, $available_arr[$n]) < 0) {
243
					return -1;
244
				}
245
			} else {
246
				// Both look like genuine integers so compare as numbers.
247
				if ($val1_as_int > $val2_as_int) {
248
					return 1;
249
				} elseif ($val1_as_int < $val2_as_int) {
250
					return -1;
251
				}
252
			}
253
		} else {
254
			// The installed package version is greater, since all components have matched up to this point
255
			// and available_arr doesn't have any more data.
256
			return 1;
257
		}
258
	}
259

  
260
	if (count($available_arr) > count($installed_arr)) {
261
		// All the installed package components matched the corresponding available package components.
262
		// The available package is longer than the installed package, so the installed package is old.
263
		return -1;
264
	} else {
265
		// Both versions are of equal length and value.
266
		return 0;
267
	}
268

  
269
	return $resp ? $resp : array();
270
}
271

  
212 272
/*
213 273
 * resync_all_package_configs() Force packages to setup their configuration and rc.d files.
214 274
 * This function may also print output to the terminal indicating progress.

Also available in: Unified diff