expose version comparison

This commit is contained in:
Chris West (Faux) 2017-07-20 12:45:30 +01:00
parent 3314733ebb
commit 81b66ce2ae
4 changed files with 43 additions and 1 deletions

View File

@ -3,8 +3,9 @@
#include <assert.h>
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/cachefile.h>
#include <apt-pkg/pkgcache.h>
#include <apt-pkg/version.h>
struct PCache {
// Owned by us.
@ -48,6 +49,8 @@ extern "C" {
PCache *pkg_cache_create();
int32_t pkg_cache_compare_versions(PCache *cache, const char *left, const char *right);
// pkg_iter creation and deletion
PPkgIterator *pkg_cache_pkg_iter(PCache *cache);
PPkgIterator *pkg_cache_find_name(PCache *cache, const char *name);
@ -137,6 +140,11 @@ void pkg_cache_release(PCache *cache) {
delete cache;
}
int32_t pkg_cache_compare_versions(PCache *cache, const char *left, const char *right) {
// an int is returned here; presumably it will always be -1, 0 or 1.
return cache->cache->VS->DoCmpVersion(left, left+strlen(left), right, right+strlen(right));
}
PPkgIterator *pkg_cache_pkg_iter(PCache *cache) {
PPkgIterator *wrapper = new PPkgIterator();
wrapper->iterator = cache->cache->PkgBegin();

View File

@ -74,4 +74,13 @@ mod tests {
);
}
#[test]
fn compare_versions() {
use std::cmp::Ordering;
let cache = Cache::get_singleton();
assert_eq!(Ordering::Less, cache.compare_versions("3.0", "3.1"));
assert_eq!(Ordering::Greater, cache.compare_versions("3.1", "3.0"));
assert_eq!(Ordering::Equal, cache.compare_versions("3.0", "3.0"));
}
}

View File

@ -19,6 +19,7 @@ extern "C" {
fn init_config_system();
fn pkg_cache_create() -> PCache;
pub fn pkg_cache_compare_versions(cache: PCache, left: *const c_char, right: *const c_char) -> i32;
// Package iterators
// =================

View File

@ -1,3 +1,4 @@
use std::cmp;
use std::marker::PhantomData;
use std::ffi;
@ -52,6 +53,29 @@ impl Cache {
PkgIterator::new(self, ptr)
}
}
/// Compare two versions, returning an `Ordering`, as used by most Rusty `sort()` methods.
///
/// This uses the "versioning scheme" currently set, which, in theory, can change,
/// but in practice is always the "Standard .deb" scheme. As of 2017, there aren't even any
/// other implementations. As such, this may eventually become a static method somewhere.
///
/// # Examples
///
/// ```rust
/// # let mut cache = apt_pkg_native::Cache::get_singleton();
/// let mut packages = vec!["3.0", "3.1", "3.0~1"];
/// packages.sort_by(|left, right| cache.compare_versions(left, right));
/// assert_eq!(vec!["3.0~1", "3.0", "3.1"], packages);
/// ```
pub fn compare_versions(&self, left: &str, right: &str) -> cmp::Ordering {
unsafe {
let left = ffi::CString::new(left).unwrap();
let right = ffi::CString::new(right).unwrap();
raw::pkg_cache_compare_versions(self.ptr, left.as_ptr(), right.as_ptr()).cmp(&0)
}
}
}
/// An "iterator"/pointer to a point in a package list.