diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..2af6ebe --- /dev/null +++ b/.travis.yml @@ -0,0 +1,9 @@ +language: rust +rust: + - nightly + - beta + - stable + +matrix: + allow_failures: + - rust: nightly diff --git a/Cargo.toml b/Cargo.toml index cd651c7..40e4128 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,9 +3,18 @@ name = "apt-pkg-native" version = "0.1.0" authors = ["Chris West (Faux) "] +description = "Bindings for libapt-pkg" +repository = "https://github.com/FauxFaux/apt-pkg-native-rs" +readme = "README.md" +categories = ["api-bindings", "os"] +license = "MIT" + [dependencies] lazy_static = "0.2.8" libc = "0.2.26" [build-dependencies] gcc = "0.3.51" + +[badges] +travis-ci = { repository = "FauxFaux/apt-pkg-native-rs" } diff --git a/LICENSE.MIT b/LICENSE.MIT new file mode 100644 index 0000000..72708cd --- /dev/null +++ b/LICENSE.MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2017 Chris West + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/README.md b/README.md new file mode 100644 index 0000000..aa934e3 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +This crate provides bindings to `libapt-pkg`. + +[![Build status](https://api.travis-ci.org/FauxFaux/apt-pkg-native-rs.png)](https://travis-ci.org/FauxFaux/apt-pkg-native-rs) +[![](http://meritbadge.herokuapp.com/apt-pkg-native)](https://crates.io/crates/apt-pkg-native) + + +### Documentation and Examples + +See the `examples/` folder for some partial implementations of some commands. + +https://docs.rs/apt-pkg-native + +### License Note + +While the code in this crate is available under a permissive MIT license, + it is useless without [`libapt-pkg`](https://tracker.debian.org/pkg/apt), + which is GPL2+. + +### Building + +`libapt-pkg-dev` must be installed. The [`gcc`](https://crates.io/crates/gcc) + crate is used to try and find a native compiler. diff --git a/src/lib.rs b/src/lib.rs index 1282f64..d34370b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,37 @@ +//! Here lies bindings to `libapt-pkg`, which is what the `apt`, `apt-get`, `apt-cache`, etc. +//! commands use to view and manipulate the state of packages on the system. +//! +//! Currently, not much is exposed. You can pretty much only view basic package +//! information, like with `apt-cache policy foo`. +//! +//! `libapt-pkg` has basically no documentation. `python-apt` is slightly better, +//! but is also pretty inconsistent on the documentation front. The design of this +//! crate is closer to `libapt-pkg`, despite it being pretty insane. +//! +//! The core concept here is an "iterator". Forget everything you know about iterators, +//! these iterators are pretty much pointers. The crate attempts to make them act +//! a bit more like Rust `Iterator`s, but is crippled by the insanity. +//! +//! Methods which "find" something will reposition one of these "iterators" at the right place +//! in an existing stream of items. Note that currently you don't technically need to call +//! `next()` before observing the result of a `find..()`, but hopefully this will be fixed. +//! +//! I recommend using `.map()` to turn an "iterator" into a Rust type as soon as possible. +//! The returned map-like thing *is* a Rust `Iterator`, so you can do normal operations on it. +//! +//! Here's an example: normally you wouldn't need this ugly `.map(|_| ())` (read as "map anything +//! to the empty object"), but here, it is *also* converting a sh... apt "iterator" into a +//! real Iterator. +//! +//! ```rust,no_run +//! extern crate apt_pkg_native; +//! let cache = apt_pkg_native::Cache::get_singleton(); +//! let total_packages = cache.iter().map(|_| ()).count(); +//! ``` +//! +//! `libapt-pkg` also just segfaults if you do anything wrong, or re-use anything at the wrong time, +//! or etc. I've tried to hide this, but I advise you not to push or outsmart the borrow checker. + #[macro_use] extern crate lazy_static; extern crate libc; diff --git a/src/sane.rs b/src/sane.rs index 5f5a87d..e8a5cea 100644 --- a/src/sane.rs +++ b/src/sane.rs @@ -4,18 +4,24 @@ use std::ffi; use libc; use raw; -/// A reference to the package cache singleton. -/// Basically just a collection of related methods. +/// A reference to the package cache singleton, +/// from which most functionality can be accessed. #[derive(Debug)] pub struct Cache { ptr: raw::PCache, } impl Cache { + /// Get a reference to the singleton. pub fn get_singleton() -> Cache { Cache { ptr: raw::pkg_cache_get() } } + /// Walk through all of the packages, in a random order. + /// + /// If there are multiple architectures, multiple architectures will be returned. + /// + /// See the module documentation for apologies about how this isn't an iterator. pub fn iter(&mut self) -> PkgIterator { unsafe { PkgIterator { @@ -26,6 +32,10 @@ impl Cache { } } + /// Find a package by name. It's not clear whether this picks a random arch, + /// or the primary one. + /// + /// The returned iterator will either be at the end, or at a package with the name. pub fn find_by_name(&mut self, name: &str) -> PkgIterator { unsafe { let name = ffi::CString::new(name).unwrap(); @@ -38,6 +48,9 @@ impl Cache { } } + /// Find a package by name and architecture. + /// + /// The returned iterator will either be at the end, or at a matching package. pub fn find_by_name_arch(&mut self, name: &str, arch: &str) -> PkgIterator { unsafe { let name = ffi::CString::new(name).unwrap(); @@ -52,7 +65,7 @@ impl Cache { } } - +/// An "iterator"/pointer to a point in a package list. #[derive(Debug)] pub struct PkgIterator<'c> { cache: &'c Cache, @@ -66,8 +79,7 @@ impl<'c> Drop for PkgIterator<'c> { } } -/// Iterator-like interface. -/// Can't implement Iterator due to the mutation / lifetime constraints? +/// Iterator-like interface impl<'c> PkgIterator<'c> { pub fn next(&mut self) -> Option<&Self> { unsafe { @@ -170,6 +182,7 @@ where } } +/// An "iterator"/pointer to a point in a version list. pub struct VerIterator<'c> { cache: PhantomData<&'c Cache>, first: bool, @@ -182,6 +195,7 @@ impl<'c> Drop for VerIterator<'c> { } } +/// Iterator-like interface impl<'c> VerIterator<'c> { pub fn next(&mut self) -> Option<&Self> { unsafe { @@ -234,6 +248,7 @@ where } } +/// Actual accessors impl<'c> VerIterator<'c> { pub fn version(&self) -> String { unsafe { diff --git a/src/simple.rs b/src/simple.rs index 044b05c..4a90a27 100644 --- a/src/simple.rs +++ b/src/simple.rs @@ -1,3 +1,5 @@ +//! Some structs representing basic concepts, and utilities to copy out of "iterators". + use sane; #[derive(Clone, Debug)]