Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
WilliamVenner committed Dec 24, 2020
0 parents commit 92c0e14
Show file tree
Hide file tree
Showing 11 changed files with 451 additions and 0 deletions.
13 changes: 13 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
.vs

# Generated by Cargo
# will have compiled files and executables
debug/
target/

# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
Cargo.lock

# These are backup files generated by rustfmt
**/*.rs.bk
21 changes: 21 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
language: rust
rust:
- stable
- beta
- nightly
cache: cargo
jobs:
allow_failures:
- rust: nightly
fast_finish: true
addons:
apt:
packages:
- libgtk-3-dev
update: true
os:
- linux
- osx
- windows
script:
- cargo build --verbose --release --features gui
27 changes: 27 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
#![windows_subsystem = "windows"]

[package]
name = "blackhole"
version = "1.0.0"
authors = ["William Venner <[email protected]>"]
edition = "2018"
repository = "https://github.com/WilliamVenner/blackhole"
license = "MIT"
keywords = ["blackhole", "black hole", "forget", "ramdisk", "organization", "organisation", "organisation-tool", "organization-tool", "black-hole"]

[features]
gui = ["msgbox"]

[dependencies]
dirs = "3.0"
trash = "1.2"
msgbox = { version = "0.6.0", optional = true }

[target.'cfg(windows)'.dependencies]
powershell_script = "0.1"
winapi = { version = "0.3", features = ["winuser"] }
rust-ini = "0.16"
winreg = "0.8"

[target.'cfg(windows)'.build-dependencies]
winres = "0.1"
53 changes: 53 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<p align="center">
<img alt="Logo" src="https://i.imgur.com/VX8fAQI.png"/>
</p>

## Blackhole

[![Travis CI Build Status](https://travis-ci.com/WilliamVenner/blackhole.svg?token=GXuyFsyVxqMmbV5zG6B4&branch=master)](https://travis-ci.com/github/WilliamVenner/blackhole)

Blackhole is a simple program that creates a folder in your computer's home directory where **files may not return**.

Every time you start your computer/log into your user account, the Blackhole directory is moved to your computer's Recycle Bin/Trash, where you can restore it if needed.

## Releases

[Click here](https://github.com/WilliamVenner/blackhole/releases) for pre-built binaries.

## Requirements

* Your operating system must have some form of "Recycle Bin" or "Trash"
* Your operating system must provide you a home directory
* The program may require administrative/elevated privileges on some operating systems

## Windows

Blackhole will automatically add itself to your startup programs via the registry.

If contents are present, the `$BLACKHOLE` directory will be moved to the Recycle Bin every time you start up your computer.

The `$BLACKHOLE` directory will automatically be added to the Quick Access locations.

#### File Location

`%USERPROFILE%/$BLACKHOLE`

## Linux & MacOS

Purging the Blackhole at startup is not yet supported on these operating systems.

If you know Rust and a bit about your favourite OS, pull requests are appreciated.

#### File Location

`$HOME/$BLACKHOLE`

## Screenshots

<p align="center">
<img alt="Windows" src="https://i.imgur.com/LwHRoH5.png/">
</p>

## Credits

Icon made by [Flat Icons](https://www.flaticon.com/authors/flat-icons) from [www.flaticon.com](https://www.flaticon.com)
9 changes: 9 additions & 0 deletions build.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
use std::io;
#[cfg(windows)] use winres::WindowsResource;

fn main() -> io::Result<()> {
#[cfg(windows)] {
WindowsResource::new().set_icon("src/assets/blackhole.ico").compile()?;
}
Ok(())
}
Binary file added src/assets/blackhole.ico
Binary file not shown.
88 changes: 88 additions & 0 deletions src/blackhole.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
pub mod blackhole {
use crate::Show;

use std::{ffi::OsString, fs, io};
use dirs;
use trash;

pub struct Blackhole {
pub path: std::path::PathBuf
}

impl Blackhole {
pub fn new(should_purge: bool) -> Result<Blackhole, &'static str> {
let mut home_dir = match dirs::home_dir() {
Some(home_dir) => home_dir,
None => { return Err("Could not find a home directory!") },
};

home_dir.push("$BLACKHOLE");

let new = Blackhole { path: home_dir };

// If the blackhole directory doesn't exist, create it
new.create();
println!("Blackhole initialized!");

// If it does exist & we've started up in purge mode, delete it
if should_purge { new.purge() }

// Run any chores
#[cfg(any(windows, linux))]
new.chores();

Ok(new)
}

fn create(&self) {
if self.path.is_dir() { return };

match fs::create_dir(&self.path) {
Err(error) => Show::panic(&format!("Failed to CREATE blackhole directory (\"{:?}\") at {:?}", error, self.path)),
Ok(_) => return
}
}

fn empty(&self) -> Result<bool, io::Error> {
if !cfg!(windows) { return Ok(self.path.read_dir()?.next().is_none()) }

let desktop_ini: OsString = OsString::from("desktop.ini");
for entry in fs::read_dir(&self.path)? {
match entry?.path().file_name() {
None => continue,
Some(file_name) => {
if file_name != desktop_ini {
return Ok(false);
}
}
}
}

Ok(true)
}

fn purge(&self) {
match self.empty() {
Err(error) => Show::panic(&format!("Failed to READ blackhole directory (\"{:?}\") at {:?}", error, self.path)),
Ok(empty) => {
if empty {
println!("Blackhole directory empty.");
return
}
}
}

match trash::delete(&self.path) {
Err(error) => Show::panic(&format!("Failed to PURGE blackhole directory (\"{:?}\") at {:?}", error, self.path)),
Ok(_) => ()
}

println!("Purged Blackhole directory!");

self.create();
}
}

#[cfg(windows)] use crate::windows::Windows;
#[cfg(linux)] use crate::linux::Linux;
}
49 changes: 49 additions & 0 deletions src/linux.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
use crate::Blackhole;
use crate::Show;

use std::{env, fs};

pub trait Linux {
fn copy_executable();
fn chores(&self);
}

impl Linux for Blackhole {
fn copy_executable() {
// Locate the executable folder and symlink us there
let mut new_exe_path = match dirs::executable_dir() {
Ok(new_exe_path) => new_exe_path,
Err(error) => {
Show::panic("Error getting executable directory: {}", error);
return;
}
};

new_exe_path.push("blackhole");

let exe_path = match std::env::current_exe() {
Ok(exe_path) => exe_path,
Err(error) => {
Show::panic("Error getting executable path: {}", error);
return;
}
};

if exe_path == new_exe_path { return }

match fs::rename() {
Ok(_) => return,
Err(error) => {
Show::panic("Error moving executable to executables path: {}", error);
return;
}
}

Show::msg("Blackhole executable has been moved to {}", new_exe_path);
}

fn chores(&self) {
// If we're running Linux, copy the executable to the executables folder
Blackhole::copy_executable();
}
}
18 changes: 18 additions & 0 deletions src/main.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
use std::env;

mod show;
use show::show::Show;

mod blackhole;
use blackhole::blackhole::Blackhole;

#[cfg(windows)] mod windows;
#[cfg(linux)] mod linux;

fn main() {
let should_purge: bool = env::args_os().any(|arg| arg == "--purge");
match Blackhole::new(should_purge) {
Ok(blackhole) => { println!("Location: {}", blackhole.path.display()) },
Err(error) => { Show::panic(&String::from(error)); }
}
}
41 changes: 41 additions & 0 deletions src/show.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
pub mod show {
pub struct Show();

#[cfg(not(feature="gui"))]
impl Show {
pub fn panic(err: &String) {
panic!("Blackhole PANIC: {}", err);
}

pub fn error(err: &String) {
println!("Blackhole ERROR: {}", err);
}

pub fn msg(err: &String) {
println!("Blackhole INFO: {}", err);
}
}

#[cfg(feature="gui")] extern crate msgbox;
#[cfg(feature="gui")] use msgbox::IconType;
#[cfg(feature="gui")]
impl Show {
pub fn panic(err: &String) {
if msgbox::create("Blackhole PANIC", err, IconType::Error).is_err() {
panic!("Blackhole PANIC: {}", err);
}
}

pub fn error(err: &String) {
if msgbox::create("Blackhole ERROR", err, IconType::Error).is_err() {
println!("Blackhole ERROR: {}", err);
}
}

pub fn msg(err: &String) {
if msgbox::create("Blackhole", err, IconType::Info).is_err() {
println!("Blackhole INFO: {}", err);
}
}
}
}
Loading

0 comments on commit 92c0e14

Please sign in to comment.