awpack 0.1.0

A package manager for the Awesome tiling window manager
pub use self::error::Error;
pub use self::package::{Package, PackagePath, PackageError};
pub use self::package_manager::PackageManager;

mod package_manager;
mod package;
mod error;

extern crate git2;
extern crate toml;
extern crate walkdir;
extern crate clap;

use std::{env, process};

use clap::{Arg, App, SubCommand};

fn main() {
    let directory = env::home_dir().unwrap().
        join(".config").
        join("awesome").
        join("awpack");

    let mut package_manager = match PackageManager::new(directory) {
        Ok(pacman) => pacman,
        Err(e) => {
            println!("error: {}", e);
            process::exit(1);
        },
    };

    let matches = App::new("awpack")
                              .version("0.1")
                              .author("Dylan McKay <dylanmckay34@gmail.com>")
                              .about("Manage packages for the Awesome window manager")
                              .subcommand(SubCommand::with_name("install")
                                          .about("installs a new package")
                                          .arg_from_usage("-d, --debug 'Print debug information'")
                                          .arg(Arg::with_name("package")
                                               .required(true)
                                               .help("the package to install")))
                              .subcommand(SubCommand::with_name("uninstall")
                                          .about("uninstalls a new package")
                                          .arg(Arg::with_name("package")
                                               .required(true)
                                               .help("the package to uninstall")))
                              .subcommand(SubCommand::with_name("info")
                                          .about("queries install packages")
                                          .arg(Arg::with_name("package")
                                               .required(false)
                                               .help("the package to show")))
                              .subcommand(SubCommand::with_name("update")
                                          .about("updates packages")
                                          .arg(Arg::with_name("package")
                                               .required(false)
                                               .help("the package to updae")))
                              .get_matches();

    match matches.subcommand() {
        ("install", Some(submatch)) => {
            let package_path = self::parse_package_path(submatch.value_of("package"));

            match package_manager.install(&package_path) {
                Ok(..) => println!("installed {}", package_path),
                Err(e) => println!("error: {}", e),
            }
        },
        ("uninstall", Some(submatch)) => {
            let package_path = self::parse_package_path(submatch.value_of("package"));

            match package_manager.uninstall(&package_path) {
                Ok(..) => println!("uninstalled {}", package_path),
                Err(e) => println!("error: {}", e),
            }
        },
        ("update", Some(submatch)) => {
            if let Some(package_path) = submatch.value_of("package") {
                let package_path = self::parse_package_path(Some(package_path));

                match package_manager.lookup_mut(&package_path) {
                    Some(package) => self::update_package(package),
                    None => {
                        println!("package is not installed");
                        process::exit(1);
                    },
                }
            } else {
                for package in package_manager.packages.values_mut() {
                    self::update_package(package);
                }
            }
        },
        ("info", Some(submatch)) => {

            if submatch.is_present("package") {
                let package_path = self::parse_package_path(submatch.value_of("package"));
                match package_manager.lookup(&package_path) {
                    Some(package) => {
                        println!("{} ({})", package.remote_path, package.revision);
                    },
                    None => {
                        println!("package is not installed");
                        process::exit(1);
                    },
                }
            } else {
                for package in package_manager.packages.values() {
                    println!("{}", package.name);
                }
            }

        },
        _ => (),
    }
}

fn update_package(package: &mut Package) {
    println!("updating {}", package.remote_path);

    match package.update() {
        Ok(was_changed) => {
            if was_changed {
                println!("updated to {}", package.revision);
            } else {
                println!("already up-to-date");
            }
        },
        Err(e) => {
            println!("error: {}", e);
            process::exit(1);
        },
    }
}

fn parse_package_path(name: Option<&str>) -> PackagePath {
    let text = match name {
        Some(package) => package,
        None => {
            println!("no package given");
            process::exit(1);
        },
    };

    match text.parse() {
        Ok(path) => path,
        Err(..) => {
            println!("'{}' is not a valid package", text);
            process::exit(1);
        },
    }
}