core-utils 0.1.2

A reimplementation of the GNU core utils in the Rust programming language
// Copyright (C) 2015, Alberto Corona <ac@albertocorona.com>
// All rights reserved. This file is part of core-utils, distributed under the
// GPL v3 license. For full terms please see the LICENSE file.

#![crate_type = "bin"]
#![crate_name = "rm"]
#![feature(path_ext)]

static UTIL: Prog = Prog { name: "rm", vers: "0.1.0", yr: "2015" };

extern crate pgetopts;
extern crate rpf;

use pgetopts::{Options};
use rpf::{Status,Styled,PathMod,Prog};

use std::env;
use std::fs;
use std::fs::{PathExt};
use std::path::{PathBuf};

fn exists(path: &PathBuf) -> bool {
    if !path.exists() {
        Status::Error.err(UTIL.name, String::from("cannot remove '".to_string()
                                                  + path.as_str() +
                                                  "': No such file or directory"
                                                 ));
    }
    return true;
}

fn rm_file(file: &PathBuf, verbose: bool) {
    match fs::remove_file(file) {
        Ok(_) => {
            if verbose {
                println!("Removed: '{}'", file.display());
            }
        },
        Err(e) => {
            Status::Error.err(UTIL.name, e.to_string());
            panic!();
        }
    };

}

fn rm_dir(dir: &PathBuf, verbose: bool) {
    match fs::remove_dir_all(dir) {
        Ok(_) => {
            if verbose {
                println!("Removed: '{}'", dir.display());
            }
        },
        Err(e) => {
            Status::Error.err(UTIL.name, e.to_string());
            panic!();
        }
    };
}

fn rm_target(path: &PathBuf, recurse: bool, verbose: bool) {
    if exists(path) {
        if path.is_file() {
            rm_file(path, verbose);
        } else if path.is_dir() && !recurse {
            Status::Error.err(UTIL.name, String::from("cannot remove \'".to_string() +
                                                      path.as_str() +
                                                      "\': Is a directory"));
        } else if path.is_dir() && recurse {
            rm_dir(path, verbose);
        }
    }
}

fn print_usage(opts: Options) {
    print!("{}: {} {}... {}...\n\
    Remove FILE(s) {}\n\
    {}:
    rm -r dir\tDeletes `dir` and all of its contents", "Usage".bold(), UTIL.name.bold(),
    "[OPTION]".underline(), "FILE".underline(), opts.options(), "Examples".bold());
}

fn main() {
    let args: Vec<String> = env::args().collect();
    let mut opts = Options::new();

    opts.optflag("v", "verbose", "Verbosely print operation");
    opts.optflag("r", "recursive", "Remove a directory and all of its contents");
    opts.optflag("h", "help", "Print help information");
    opts.optflag("", "version", "Print version information");

    let matches = match opts.parse(&args[1..]) {
        Ok(m) => { m },
        Err(e) => {
            Status::OptError.err(UTIL.name, e.to_string());
            panic!(e.to_string())
        }
    };

    let verb = matches.opt_present("v");
    let recurse = matches.opt_present("r");

    if matches.opt_present("h") {
        print_usage(opts);
    } else if matches.opt_present("version") {
        UTIL.copyright("Copyright (C) 2015 core-utils developers\n\
                       License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>.\n\
                       This is free software: you are free to change and redistribute it.\n\
                       There is NO WARRANTY, to the extent permitted by law.\n\n",
                       vec!["Alberto Corona"]);
    } else if !matches.free.is_empty() {
        for item in matches.free.iter() {
            rm_target(&PathBuf::from(&item), recurse, verb);
        }
    } else if matches.free.is_empty() {
        UTIL.prog_try();
    }
}