<commit_before>extern crate kernel32;
extern crate user32;
extern crate winapi;
extern crate libc;
extern crate gdi32;

use winapi::windef::HWND;
use winapi::windef::HMENU;
use winapi::windef::HBRUSH;
use winapi::minwindef::HINSTANCE;

use winapi::minwindef::UINT;
use winapi::minwindef::DWORD;
use winapi::minwindef::WPARAM;
use winapi::minwindef::LPARAM;
use winapi::minwindef::LRESULT;
use winapi::winnt::LPCWSTR;

use winapi::winuser::WS_OVERLAPPEDWINDOW;
use winapi::winuser::WS_VISIBLE;
use winapi::winuser::WNDCLASSW;
use winapi::winuser::CF_BITMAP;

use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;

const g_class_name: str = "winshot";

// Rectangle represents screen coordinates
struct Rectangle {
	x: i32,
	y: i32,
	x2: i32,
	y2: i32,
}

// convert normal string to wide string
#[allow(dead_code)]
fn to_wstring(str: &str) -> *const u16 {
	let v: Vec<u16> = OsStr::new(str).encode_wide() . chain(Some(0).into_iter()).collect();
	v.as_ptr()
}

// This is our window message handler function. Currently,
// it only processes the WM_DESTROY message to exit our window properly on close event.
#[allow(dead_code)]
pub unsafe extern "system" fn window_proc(h_wnd: HWND, msg: UINT, w_param: WPARAM, l_param: LPARAM) -> LRESULT {
	if msg == winapi::winuser::WM_DESTROY {
		user32::PostQuitMessage(0);
	}

	match msg {
		winapi::winuser::WM_DESTROY => user32::PostQuitMessage(0),
		winapi::winuser::WM_MOUSEMOVE => 0 as LRESULT,
		winapi::winuser::WM_LBUTTONDOWN => 0 as LRESULT,
		winapi::winuser::WM_LBUTTONUP => 0 as LRESULT,
		_ => user32::DefWindowProcW(h_wnd, msg, w_param, l_param),
	}
}

// The following function hides the Console Window since we are building a GUI application.
#[allow(dead_code)]
fn hide_console_window() {
	let window = unsafe {
		kernel32::GetConsoleWindow()
	};

	if window != std::ptr::null_mut() {
		unsafe {
			user32::ShowWindow(window, winapi::SW_HIDE)
		};
	}
}

fn normalize_coords(rect: Rectangle) -> Rectangle {
    let Rectangle{mut x, mut y, mut x2, mut y2} = rect;

    if x > x2 {
        let tmp = x;
        x = x2;
        x2 = tmp;
    }
    if y > y2 {
        let tmp = y;
        y = y2;
        y2 = tmp;
    }

    Rectangle{x: x, y: y, x2: x2, y2: y2}
}

fn get_screen_rect() -> Rectangle {
	Rectangle{
		x /* left */: user32::GetSystemMetrics(winapi::winuser::SM_XVIRTUALSCREEN),
		y /* top */: user32::GetSystemMetrics(winapi::winuser::SM_YVIRTUALSCREEN),
		x2 /* right */: user32::GetSystemMetrics(winapi::winuser::SM_CXVIRTUALSCREEN) + x,
		y2 /* bottom */: user32::GetSystemMetrics(winapi::winuser::SM_CYVIRTUALSCREEN) + y,
	}
}

fn capture_screen_clipboard(hwnd: HWND, rect: mut Rectangle) -> bool {
	// normalize coordinates
	rect = normalize_coords(rect);
	let w = rect.x2 - rect.x;
	let h = rect.y2 - rect.y;

	let screen_dc = user32::GetDC(0 as HWND);
	let shot_dc = gdi32::CreateCompatibleDC(screen_dc);
	let shot_bitmap = gdi32::CreateCompatibleBitmap(screen_dc, w, h);
	let old_obj = gdi32::SelectObject(shot_dc, shot_bitmap);

	if !gdi32::BitBlt(shot_dc, 0, 0, w, h, screen_dc, rect.x, rect.y, 0 as DWORD) {
		println!("{:?}", "BitBlt failed? Perhaps.");
		false
	}

	let mut ret = false;
	if user32::OpenClipboard(hwnd) {
		if user32::EmptyClipboard() {
			if user32::SetClipboardData(CF_BITMAP, shot_bitmap) {
				ret = true;
			}
			user32::CloseClipboard();
		}
	} else {
		println!("{:?}", "could not open clipboard");
	}

	// Clean up
	gdi32::DeleteDC(shot_dc);
	gdi32::DeleteDC(screen_dc);
	gdi32::SelectObject(shot_dc, old_obj);

	return ret;
}

fn main() {
	unsafe {
		let hInstance = kernel32::GetModuleHandle(0 as LPCWSTR);
		let m_class_name = to_wstring(g_class_name);
		let wnd = WNDCLASSW {
			hInstance: hInstance,
			lpszClassName: m_class_name,
			lpszMenuName: 0 as LPCWSTR,
			lpfnWndProc: Some(window_proc),
			cbClsExtra: 0,
			cbWndExtra: 0,
			style: winapi::winuser::CS_HREDRAW | winapi::winuser::CS_VREDRAW,
			hbrBackground: 0,
			hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDC_CROSS),
			hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
		}

		user32::RegisterClassW(&wnd);
		let rect = get_screen_rect();
		let exstyle = winapi::winuser::WS_EX_TRANSPARENT;
		let style = winapi::winuser::WS_POPUP;

		let win = user32::CreateWindowEx(exstyle,
			m_class_name,
			m_class_name,
			style,
			// dimensions
			0, 0, rect.x2, rect.y2,
			0, // no parent
			0, // no menu
			hInstance, // module_instance
			0 as LPARAM,
		)

		user32::ShowWindow(win, winapi::winuser::SW_SHOW);
		user32::ShowWindow(win, winapi::winuser::SW_SHOWMAXIMIZED);
		user32::SetForegroundWindow(win);

		capture_screen_clipboard(win, 0, 0, 200, 200);
		user32::DestroyWindow(win);
	}
}

// fn main() {
// 	// Here our unsafe code goes
// 	unsafe {
// 		// First we hide the console window
// 		hide_console_window();

// 		// Then we initialize the WNDCLASS structure
// 		let m_class_name = to_wstring(g_class_name);
// 		let wnd = WNDCLASSW {
// 			hInstance: 0 as HINSTANCE,
// 			lpszClassName = m_class_name,
// 			lpszMenuName: 0 as LPCWSTR,
// 			lpfnWndProc: Some(window_proc),

// 			style: winapi::winuser::CS_HREDRAW | winapi::winuser::CS_VREDRAW,

// 			cbClsExtra: 0,
// 			cbWndExtra: 0,

// 			hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
// 			hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
// 			hbrBackground: 16 as HBRUSH,

// 		};

// 		// Register our class
// 		user32::RegisterClassW(&wnd);

// 		let h_wnd_desktop = user32::GetDesktopWindow();

// 		user32::CreateWindowExA(0, "my_window".as_ptr() as *mut _,
// 			"Simple Window".as_ptr() as *mut _, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
// 			0, 0, 400, 400, h_wnd_desktop, 0 as HMENU, 0 as HINSTANCE,
// 			std::ptr::null_mut());

// 		let mut msg = winapi::winuser::MSG {
// 			hwnd: 0 as HWND,
// 			message: 0 as UINT,
// 			wParam: 0 as WPARAM,
// 			lParam: 0 as LPARAM,
// 			time: 0 as DWORD,
// 			pt : winapi::windef::POINT{ x: 0, y: 0, },
// 		};

// 		// Kick off the application loop
// 		loop {
// 			let pm = user32::PeekMessageW(&mut msg, 0 as HWND, 0, 0, winapi::winuser::PM_REMOVE);

// 			if pm == 0 {
// 				continue;
// 			}

// 			if msg.message == winapi::winuser::WM_QUIT {
// 				break;
// 			}

// 			user32::TranslateMessage(&mut msg);
// 			user32::DispatchMessageW(&mut msg);
// 		}
// 	}
// }<commit_msg>wtfbbq?<commit_after>extern crate kernel32;
extern crate user32;
extern crate winapi;
extern crate libc;
extern crate gdi32;

use winapi::windef::HWND;
use winapi::windef::HMENU;
use winapi::windef::HBRUSH;
use winapi::minwindef::HINSTANCE;

use winapi::minwindef::UINT;
use winapi::minwindef::DWORD;
use winapi::minwindef::WPARAM;
use winapi::minwindef::LPARAM;
use winapi::minwindef::LRESULT;
use winapi::winnt::LPCWSTR;

use winapi::winuser::WS_OVERLAPPEDWINDOW;
use winapi::winuser::WS_VISIBLE;
use winapi::winuser::WNDCLASSW;
use winapi::winuser::CF_BITMAP;

use std::os::windows::ffi::OsStrExt;
use std::ffi::OsStr;

const g_class_name: str = "winshot";

// Rectangle represents screen coordinates
struct Rectangle {
	x: i32,
	y: i32,
	x2: i32,
	y2: i32,
}

// convert normal string to wide string
#[allow(dead_code)]
fn to_wstring(str: &str) -> *const u16 {
	let v: Vec<u16> = OsStr::new(str).encode_wide() . chain(Some(0).into_iter()).collect();
	v.as_ptr()
}

// This is our window message handler function. Currently,
// it only processes the WM_DESTROY message to exit our window properly on close event.
#[allow(dead_code)]
pub unsafe extern "system" fn window_proc(h_wnd: HWND, msg: UINT, w_param: WPARAM, l_param: LPARAM) -> LRESULT {
	if msg == winapi::winuser::WM_DESTROY {
		user32::PostQuitMessage(0);
	}

	match msg {
		winapi::winuser::WM_DESTROY => user32::PostQuitMessage(0),
		winapi::winuser::WM_MOUSEMOVE => 0 as LRESULT,
		winapi::winuser::WM_LBUTTONDOWN => 0 as LRESULT,
		winapi::winuser::WM_LBUTTONUP => 0 as LRESULT,
		_ => user32::DefWindowProcW(h_wnd, msg, w_param, l_param),
	}
}

// The following function hides the Console Window since we are building a GUI application.
#[allow(dead_code)]
fn hide_console_window() {
	let window = unsafe {
		kernel32::GetConsoleWindow()
	};

	if window != std::ptr::null_mut() {
		unsafe {
			user32::ShowWindow(window, winapi::SW_HIDE)
		};
	}
}

fn normalize_coords(rect: Rectangle) -> Rectangle {
    let Rectangle{mut x, mut y, mut x2, mut y2} = rect;

    if x > x2 {
        let tmp = x;
        x = x2;
        x2 = tmp;
    }
    if y > y2 {
        let tmp = y;
        y = y2;
        y2 = tmp;
    }

    Rectangle{x: x, y: y, x2: x2, y2: y2}
}

fn get_screen_rect() -> Rectangle {
	Rectangle{
		x /* left */: user32::GetSystemMetrics(winapi::winuser::SM_XVIRTUALSCREEN),
		y /* top */: user32::GetSystemMetrics(winapi::winuser::SM_YVIRTUALSCREEN),
		x2 /* right */: user32::GetSystemMetrics(winapi::winuser::SM_CXVIRTUALSCREEN) + x,
		y2 /* bottom */: user32::GetSystemMetrics(winapi::winuser::SM_CYVIRTUALSCREEN) + y,
	}
}

fn capture_screen_clipboard(hwnd: HWND, rect: mut Rectangle) -> bool {
	// normalize coordinates
	rect = normalize_coords(rect);
	let w = rect.x2 - rect.x;
	let h = rect.y2 - rect.y;

	let screen_dc = user32::GetDC(0 as HWND);
	let shot_dc = gdi32::CreateCompatibleDC(screen_dc);
	let shot_bitmap = gdi32::CreateCompatibleBitmap(screen_dc, w, h);
	let old_obj = gdi32::SelectObject(shot_dc, shot_bitmap);

	if !gdi32::BitBlt(shot_dc, 0, 0, w, h, screen_dc, rect.x, rect.y, 0 as DWORD) {
		println!("{:?}", "BitBlt failed? Perhaps.");
		false
	}

	let mut ret = false;
	if user32::OpenClipboard(hwnd) {
		if user32::EmptyClipboard() {
			if user32::SetClipboardData(CF_BITMAP, shot_bitmap) {
				ret = true;
			}
			user32::CloseClipboard();
		}
	} else {
		println!("{:?}", "could not open clipboard");
	}

	// Clean up
	gdi32::DeleteDC(shot_dc);
	gdi32::DeleteDC(screen_dc);
	gdi32::SelectObject(shot_dc, old_obj);

	return ret;
}

fn main() {
	unsafe {
		let hInstance = kernel32::GetModuleHandle(0 as LPCWSTR);
		let m_class_name = to_wstring(g_class_name);
		let wnd = WNDCLASSW {
			hInstance: hInstance,
			lpszClassName: m_class_name,
			lpszMenuName: 0 as LPCWSTR,
			lpfnWndProc: Some(window_proc),
			cbClsExtra: 0,
			cbWndExtra: 0,
			style: winapi::winuser::CS_HREDRAW | winapi::winuser::CS_VREDRAW,
			hbrBackground: 0,
			hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDC_CROSS),
			hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
		};

		user32::RegisterClassW(&wnd);
		let rect = get_screen_rect();
		let exstyle = winapi::winuser::WS_EX_TRANSPARENT;
		let style = winapi::winuser::WS_POPUP;

		let win = user32::CreateWindowEx(exstyle,
			m_class_name,
			m_class_name,
			style,
			// dimensions
			0, 0, rect.x2, rect.y2,
			0, // no parent
			0, // no menu
			hInstance, // module_instance
			0 as LPARAM,
		);

		user32::ShowWindow(win, winapi::winuser::SW_SHOW);
		user32::ShowWindow(win, winapi::winuser::SW_SHOWMAXIMIZED);
		user32::SetForegroundWindow(win);

		capture_screen_clipboard(win, Rectangle{
			x: 0,
			y: 0,
			x2: 200,
			y2: 200,
		});
		user32::DestroyWindow(win);
	}
}

// fn main() {
// 	// Here our unsafe code goes
// 	unsafe {
// 		// First we hide the console window
// 		hide_console_window();

// 		// Then we initialize the WNDCLASS structure
// 		let m_class_name = to_wstring(g_class_name);
// 		let wnd = WNDCLASSW {
// 			hInstance: 0 as HINSTANCE,
// 			lpszClassName = m_class_name,
// 			lpszMenuName: 0 as LPCWSTR,
// 			lpfnWndProc: Some(window_proc),

// 			style: winapi::winuser::CS_HREDRAW | winapi::winuser::CS_VREDRAW,

// 			cbClsExtra: 0,
// 			cbWndExtra: 0,

// 			hIcon: user32::LoadIconW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
// 			hCursor: user32::LoadCursorW(0 as HINSTANCE, winapi::winuser::IDI_APPLICATION),
// 			hbrBackground: 16 as HBRUSH,

// 		};

// 		// Register our class
// 		user32::RegisterClassW(&wnd);

// 		let h_wnd_desktop = user32::GetDesktopWindow();

// 		user32::CreateWindowExA(0, "my_window".as_ptr() as *mut _,
// 			"Simple Window".as_ptr() as *mut _, WS_OVERLAPPEDWINDOW | WS_VISIBLE,
// 			0, 0, 400, 400, h_wnd_desktop, 0 as HMENU, 0 as HINSTANCE,
// 			std::ptr::null_mut());

// 		let mut msg = winapi::winuser::MSG {
// 			hwnd: 0 as HWND,
// 			message: 0 as UINT,
// 			wParam: 0 as WPARAM,
// 			lParam: 0 as LPARAM,
// 			time: 0 as DWORD,
// 			pt : winapi::windef::POINT{ x: 0, y: 0, },
// 		};

// 		// Kick off the application loop
// 		loop {
// 			let pm = user32::PeekMessageW(&mut msg, 0 as HWND, 0, 0, winapi::winuser::PM_REMOVE);

// 			if pm == 0 {
// 				continue;
// 			}

// 			if msg.message == winapi::winuser::WM_QUIT {
// 				break;
// 			}

// 			user32::TranslateMessage(&mut msg);
// 			user32::DispatchMessageW(&mut msg);
// 		}
// 	}
// }<|endoftext|>


<commit_before>// TODO:
//  * add option to debug: print all errors
//  * show repo state
//  * colors

extern crate git2;

use std::io::{self, Write};

use std::collections::HashMap;

use git2::Error;
use git2::{Repository,Branch,BranchType,Oid,Reference,StatusShow};
use git2::{StatusOptions,Statuses,Status,RepositoryState};
use git2::{STATUS_WT_MODIFIED,STATUS_WT_DELETED,STATUS_WT_NEW,STATUS_WT_TYPECHANGE,STATUS_WT_RENAMED};
use git2::{STATUS_INDEX_MODIFIED,STATUS_INDEX_DELETED,STATUS_INDEX_NEW,STATUS_INDEX_TYPECHANGE,STATUS_INDEX_RENAMED};

struct Program {
    repo: Repository,
}

fn get_branch_remote(reference: Reference) -> Option<Oid> {
    let b = Branch::wrap(reference);
    let upstream = match b.upstream() {
        Ok(u) => u,
        Err(_) => return None,
    };
    upstream.get().target()
}

impl Program {
    fn get_head(&self) -> Option<Reference> {
        match self.repo.head() {
            Ok(head) => Some(head),
            Err(e) => None,
        }
    }

    fn get_current_branch_oid(&self) -> Option<Oid> {
        let head = self.get_head();
        match head {
            Some(v) => v.target(),
            None => None,
        }
    }

    fn get_current_branch_name(&self) -> String {
        let blank = String::from("");
        let h = match self.get_head() {
            Some(v) => v,
            None => return blank,
        };
        if h.is_branch() {
            match h.shorthand() {
                Some(v) => v.to_string(),
                None => blank,
            }
        } else {
            let hash = match h.target() {
                Some(v) => v.to_string(),
                None => blank,
            };
            let (s, _) = hash.split_at(7);
            s.to_string()
        }
    }

    fn get_current_branch_remote_oid(&self) -> Option<Oid> {
        match self.get_head() {
            Some(r) => get_branch_remote(r),
            None => None
        }
    }

    fn get_current_branch_ahead_behind(&self) -> Option<(usize, usize)> {
        let rm_oid = match self.get_current_branch_remote_oid() {
            Some(r) => r,
            None => return None
        };
        let oid = match self.get_current_branch_oid() {
            Some(r) => r,
            None => return None
        };
        let res = self.repo.graph_ahead_behind(oid, rm_oid);
        match res {
            Ok(r) => Some(r),
            Err(_) => None
        }
    }

    fn get_upstream_branch_ahead_behind(&self) -> Option<(usize, usize)>  {
        let upstream_reference = match self.find_upstream_repo_branch() {
            Ok(u) => u.into_reference(),
            Err(_) => return None,
        };
        let upstream_reference_oid = match upstream_reference.target() {
            Some(u) => u,
            None => return None,
        };
        let oid = match self.get_current_branch_oid() {
            Some(r) => r,
            None => return None
        };
        let res = self.repo.graph_ahead_behind(oid, upstream_reference_oid);
        match res {
            Ok(r) => Some(r),
            Err(_) => None
        }
    }

    fn find_upstream_repo_branch(&self) -> Result<Branch, Error> {
        let us_branch_name = format!("{}{}", "upstream/", self.get_current_branch_name());
        self.repo.find_branch(&us_branch_name, BranchType::Remote)
    }

    fn get_status(&self) -> Option<Statuses> {
        let mut so = StatusOptions::new();
        let mut opts = so.show(StatusShow::IndexAndWorkdir);
        opts.include_untracked(true);
        match self.repo.statuses(Some(&mut opts)) {
            Ok(s) => Some(s),
            Err(e) => None,
        }
    }

    fn get_repository_state(&self) -> RepositoryState {
        self.repo.state()
    }

    fn get_file_status(&self) -> Option<HashMap<&str, u32>> {
        let mut d = HashMap::new();

        let changed = STATUS_WT_MODIFIED | STATUS_WT_DELETED | STATUS_WT_TYPECHANGE | STATUS_WT_RENAMED;
        let staged = STATUS_INDEX_MODIFIED | STATUS_INDEX_DELETED | STATUS_INDEX_TYPECHANGE | STATUS_INDEX_RENAMED | STATUS_INDEX_NEW;

        let statuses = match self.get_status() {
            Some(x) => x,
            None => return None,
        };

        for s in statuses.iter() {
            let file_status = s.status();
            // println!("{}", s.path().unwrap());

            if file_status.intersects(changed) {
                let counter = d.entry("U").or_insert(0);
                *counter += 1;
            };
            if file_status.contains(STATUS_WT_NEW) {
                let counter = d.entry("N").or_insert(0);
                *counter += 1;
            };
            if file_status.intersects(staged) {
                let counter = d.entry("A").or_insert(0);
                *counter += 1;
            };
        }
        Some(d)
    }

    fn run(&self) {
        print!("{}|", self.get_current_branch_name());

        match self.get_current_branch_ahead_behind() {
            // FIXME: cover case behind && ahead
            Some((_, behind)) if behind > 0 => print!("-{}", behind),
            Some((ahead, _)) if ahead > 0 => print!("+{}", ahead),
            Some(_) => {}
            None => {}
        }

        match self.get_upstream_branch_ahead_behind() {
            Some((ahead, behind)) => print!("U+{}-{}|", ahead, behind),
            None => {}
        }

        let statuses = match self.get_file_status() {
            Some(s) => {
                for (k, v) in s {
                    if v > 0 {
                        print!("{}{}", k, v);
                    }
                }
            },
            None => {}
        };

        // println!("{:?}", program.get_repository_state());

        print!("\n");
    }
}

fn main() {
    let repo = match Repository::open(".") {
        Ok(repo) => repo,
        Err(_) => return (),
    };
    let program = Program{ repo: repo };
    program.run();
}
<commit_msg>show repository state<commit_after>// TODO:
//  * add option to debug: print all errors
//  * show repo state
//  * colors

extern crate git2;

use std::collections::HashMap;

use git2::Error;
use git2::{Repository,Branch,BranchType,Oid,Reference,StatusShow};
use git2::{StatusOptions,Statuses,RepositoryState};
use git2::{STATUS_WT_MODIFIED,STATUS_WT_DELETED,STATUS_WT_NEW,STATUS_WT_TYPECHANGE,STATUS_WT_RENAMED};
use git2::{STATUS_INDEX_MODIFIED,STATUS_INDEX_DELETED,STATUS_INDEX_NEW,STATUS_INDEX_TYPECHANGE,STATUS_INDEX_RENAMED};

struct Program {
    repo: Repository,
}

fn get_branch_remote(reference: Reference) -> Option<Oid> {
    let b = Branch::wrap(reference);
    let upstream = match b.upstream() {
        Ok(u) => u,
        Err(_) => return None,
    };
    upstream.get().target()
}

impl Program {
    fn get_head(&self) -> Option<Reference> {
        match self.repo.head() {
            Ok(head) => Some(head),
            Err(_) => None,
        }
    }

    fn get_current_branch_oid(&self) -> Option<Oid> {
        let head = self.get_head();
        match head {
            Some(v) => v.target(),
            None => None,
        }
    }

    fn get_current_branch_name(&self) -> String {
        let blank = String::from("");
        let h = match self.get_head() {
            Some(v) => v,
            None => return blank,
        };
        if h.is_branch() {
            match h.shorthand() {
                Some(v) => v.to_string(),
                None => blank,
            }
        } else {
            let hash = match h.target() {
                Some(v) => v.to_string(),
                None => blank,
            };
            let (s, _) = hash.split_at(7);
            s.to_string()
        }
    }

    fn get_current_branch_remote_oid(&self) -> Option<Oid> {
        match self.get_head() {
            Some(r) => get_branch_remote(r),
            None => None
        }
    }

    fn get_current_branch_ahead_behind(&self) -> Option<(usize, usize)> {
        let rm_oid = match self.get_current_branch_remote_oid() {
            Some(r) => r,
            None => return None
        };
        let oid = match self.get_current_branch_oid() {
            Some(r) => r,
            None => return None
        };
        let res = self.repo.graph_ahead_behind(oid, rm_oid);
        match res {
            Ok(r) => Some(r),
            Err(_) => None
        }
    }

    fn get_upstream_branch_ahead_behind(&self) -> Option<(usize, usize)>  {
        let upstream_reference = match self.find_upstream_repo_branch() {
            Ok(u) => u.into_reference(),
            Err(_) => return None,
        };
        let upstream_reference_oid = match upstream_reference.target() {
            Some(u) => u,
            None => return None,
        };
        let oid = match self.get_current_branch_oid() {
            Some(r) => r,
            None => return None
        };
        let res = self.repo.graph_ahead_behind(oid, upstream_reference_oid);
        match res {
            Ok(r) => Some(r),
            Err(_) => None
        }
    }

    fn find_upstream_repo_branch(&self) -> Result<Branch, Error> {
        let us_branch_name = format!("{}{}", "upstream/", self.get_current_branch_name());
        self.repo.find_branch(&us_branch_name, BranchType::Remote)
    }

    fn get_status(&self) -> Option<Statuses> {
        let mut so = StatusOptions::new();
        let mut opts = so.show(StatusShow::IndexAndWorkdir);
        opts.include_untracked(true);
        match self.repo.statuses(Some(&mut opts)) {
            Ok(s) => Some(s),
            Err(_) => None,
        }
    }

    fn get_repository_state(&self) -> String {
        let state = self.repo.state();
        match state {
            RepositoryState::Clean => String::from(""),
            RepositoryState::Merge => String::from("merge"),
            RepositoryState::Revert => String::from("revert"),
            RepositoryState::RevertSequence => String::from("revert"),
            RepositoryState::CherryPick => String::from("cherry-pick"),
            RepositoryState::CherryPickSequence => String::from("cherry-pick"),
            RepositoryState::Bisect => String::from("bisect"),
            RepositoryState::Rebase => String::from("rebase"),
            RepositoryState::RebaseInteractive => String::from("rebase"),
            RepositoryState::RebaseMerge => String::from("rebase"),
            RepositoryState::ApplyMailbox => String::from("apply"),
            RepositoryState::ApplyMailboxOrRebase => String::from("apply"),
        }
    }

    fn get_file_status(&self) -> Option<HashMap<&str, u32>> {
        let mut d = HashMap::new();

        let changed = STATUS_WT_MODIFIED | STATUS_WT_DELETED | STATUS_WT_TYPECHANGE | STATUS_WT_RENAMED;
        let staged = STATUS_INDEX_MODIFIED | STATUS_INDEX_DELETED | STATUS_INDEX_TYPECHANGE | STATUS_INDEX_RENAMED | STATUS_INDEX_NEW;

        let statuses = match self.get_status() {
            Some(x) => x,
            None => return None,
        };

        for s in statuses.iter() {
            let file_status = s.status();
            // println!("{}", s.path().unwrap());

            if file_status.intersects(changed) {
                let counter = d.entry("U").or_insert(0);
                *counter += 1;
            };
            if file_status.contains(STATUS_WT_NEW) {
                let counter = d.entry("N").or_insert(0);
                *counter += 1;
            };
            if file_status.intersects(staged) {
                let counter = d.entry("A").or_insert(0);
                *counter += 1;
            };
        }
        Some(d)
    }

    fn run(&self) {
        print!("{}|", self.get_current_branch_name());

        match self.get_current_branch_ahead_behind() {
            // FIXME: cover case behind && ahead
            Some((_, behind)) if behind > 0 => print!("-{}", behind),
            Some((ahead, _)) if ahead > 0 => print!("+{}", ahead),
            Some(_) => {}
            None => {}
        }

        match self.get_upstream_branch_ahead_behind() {
            Some((ahead, behind)) => print!("U+{}-{}|", ahead, behind),
            None => {}
        }

        match self.get_file_status() {
            Some(s) => {
                for (k, v) in s {
                    if v > 0 {
                        print!("{}{}", k, v);
                    }
                }
            },
            None => {}
        };

        print!("{}", self.get_repository_state());

        print!("\n");
    }
}

fn main() {
    let repo = match Repository::open(".") {
        Ok(repo) => repo,
        Err(_) => return (),
    };
    let program = Program{ repo: repo };
    program.run();
}
<|endoftext|>


<commit_before>use std::io::{Write, BufWriter};
use std::fs::File;
mod vector;
use vector::Vec3;
mod ray;
use ray::Ray;

fn color(ray : Ray) -> Vec3 {
  let unit_direction = ray.direction().unit_vector();
  let t = 0.5 * (unit_direction.y() + 1.0);
  return Vec3::new(1.0,1.0,1.0) * (1.0 - t) + Vec3::new(0.5,0.7,1.0) * t;
}

fn main() {
  let nx = 200;
  let ny = 100;
  let data = format!("{}\n{} {}\n{}\n", "P3", nx, ny, 255);
  let f = File::create("target/image.ppm").expect("Unable to create file");
  let mut f = BufWriter::new(f);
  f.write_all(data.as_bytes()).expect("Unable to write data");

  let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0);
  let horizontal = Vec3::new(4.0, 0.0, 0.0);
  let vertical = Vec3::new(0.0, 2.0, 0.0);
  let origin = Vec3::new(0.0, 0.0, 0.0);

  for j in (0..ny).rev() {
    for i in 0..nx {
      let u = i as f64 / nx as f64;
      let v = j as f64 / ny as f64;
      let r = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
      let col = color(r);

      let ir = (255.99*col.r()) as i32;
      let ig = (255.99*col.g()) as i32;
      let ib = (255.99*col.b()) as i32;
      f.write_all(format!("{} {} {}\n", ir, ig, ib).as_bytes()).expect("Unable to write data");
    }
  }
}<commit_msg>Add basic check for a sphere<commit_after>use std::io::{Write, BufWriter};
use std::fs::File;
mod vector;
use vector::{Vec3, dot, cross, unit_vector};
mod ray;
use ray::Ray;

fn hit_sphere(center: Vec3, radius: f64, ray: Ray) -> bool {
  let oc = ray.origin() - center;
  let a: f64 = dot(ray.direction(), ray.direction());
  let b: f64 = dot(oc, ray.direction()) * 2.0;
  let c: f64 = dot(oc, oc) - radius * radius;
  let discriminant = b * b - 4.0 * a * c;
  return discriminant > 0.0
}

fn color(ray : Ray) -> Vec3 {
  if hit_sphere(Vec3::new(0.0, 0.0, -1.0), 0.5, ray) {
    return Vec3::new(1.0, 0.0, 0.0);
  }
  let unit_direction = ray.direction().unit_vector();
  let t = 0.5 * (unit_direction.y() + 1.0);
  return Vec3::new(1.0,1.0,1.0) * (1.0 - t) + Vec3::new(0.5,0.7,1.0) * t;
}

fn main() {
  let nx = 200;
  let ny = 100;
  let data = format!("{}\n{} {}\n{}\n", "P3", nx, ny, 255);
  let f = File::create("target/image.ppm").expect("Unable to create file");
  let mut f = BufWriter::new(f);
  f.write_all(data.as_bytes()).expect("Unable to write data");

  let lower_left_corner = Vec3::new(-2.0, -1.0, -1.0);
  let horizontal = Vec3::new(4.0, 0.0, 0.0);
  let vertical = Vec3::new(0.0, 2.0, 0.0);
  let origin = Vec3::new(0.0, 0.0, 0.0);

  for j in (0..ny).rev() {
    for i in 0..nx {
      let u = i as f64 / nx as f64;
      let v = j as f64 / ny as f64;
      let r = Ray::new(origin, lower_left_corner + horizontal * u + vertical * v);
      let col = color(r);

      let ir = (255.99*col.r()) as i32;
      let ig = (255.99*col.g()) as i32;
      let ib = (255.99*col.b()) as i32;
      f.write_all(format!("{} {} {}\n", ir, ig, ib).as_bytes()).expect("Unable to write data");
    }
  }
}<|endoftext|>


<commit_before>#![allow(non_upper_case_globals)]

#![allow(dead_code)]
#![allow(unused_assignments)]
#![allow(unused_variables)]

#[macro_use] extern crate lazy_static;

use std::ffi::OsStr;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::{ Path, PathBuf };

lazy_static! {
    static ref HOME: PathBuf = std::env::home_dir().unwrap();

    static ref build_props: PathBuf = PathBuf::from("project/build.properties");

    static ref sbt_launch_dir: PathBuf = { let mut p = PathBuf::from(&*HOME); p.push(".sbt/launchers"); p };

    static ref script_name: String = {
        let n = std::env::args().nth(0).unwrap();
        let n = Path::new(&n).file_name().unwrap().to_str().unwrap();
        n.to_string()
    };

}

const sbt_launch_ivy_release_repo: &'static str = "http://repo.typesafe.com/typesafe/ivy-releases";
const sbt_launch_mvn_release_repo: &'static str = "http://repo.scala-sbt.org/scalasbt/maven-releases";

macro_rules! echoerr(($($arg:tt)*) => (writeln!(&mut ::std::io::stderr(), $($arg)*).unwrap();));

fn build_props_sbt() -> String {
    if let Ok(f) = File::open(&*build_props) {
        let f = BufReader::new(f);
        for line in f.lines() {
            let line = line.unwrap();
            if line.starts_with("sbt.version") {
                let line = line.replace("=", " ");
                let line = line.replace("\r", " ");
                return line.split_whitespace().nth(1).unwrap().to_owned();
            }
        }
    }
    "".to_owned()
}

fn jar_file(version: &str) -> PathBuf {
    let mut p = PathBuf::from(&*sbt_launch_dir);
    p.push(version);
    p.push("sbt-launch.jar");
    p
}

fn url_base(version: &str) -> &'static str { match version {
    s if s.starts_with("0.7.")  => "http://simple-build-tool.googlecode.com",
    s if s.starts_with("0.10.") => sbt_launch_ivy_release_repo,
    "0.11.1" | "0.11.2"         => sbt_launch_ivy_release_repo,
 // "0.*-yyyymmdd-hhMMss"       => sbt_launch_ivy_snapshot_repo, // https://repo.scala-sbt.org/scalasbt/ivy-snapshots
    s if s.starts_with("0.")    => sbt_launch_ivy_release_repo,
 // "*-yyyymmdd-hhMMss"         => sbt_launch_mvn_snapshot_repo, // http://repo.scala-sbt.org/scalasbt/maven-snapshots
    _                           => sbt_launch_mvn_release_repo,
} }

fn make_url(version: &str) -> String {
    let base = url_base(version);
    match version {
        s if s.starts_with("0.7.")  => format!("{}/files/sbt-launch-0.7.7.jar", base),
        s if s.starts_with("0.10.") => format!("{}/org.scala-tools.sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        "0.11.1" | "0.11.2"         => format!("{}/org.scala-tools.sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        s if s.starts_with("0.")    => format!("{}/org.scala-sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        _                           => format!("{}/org/scala-sbt/sbt-launch/{}/sbt-launch.jar", base, version),
    }
}

fn download_url(sbt_version: &str, url: &str, jar: &Path) -> bool {
    echoerr!("Downloading sbt launcher for {}:", sbt_version);
    echoerr!("  From  {}", url);
    echoerr!("    To  {}", jar.display());

    std::fs::create_dir_all(jar.parent().unwrap()).unwrap();

    extern crate hyper;
    let mut r = BufReader::new(hyper::client::Client::new().get(url).send().unwrap());
    let mut buf = [0; 16384];
    let mut jar2 = std::io::BufWriter::new(File::create(jar).unwrap());
    while {
        let bc = r.read(&mut buf).unwrap();
        jar2.write(&buf[0..bc]).unwrap();
        bc > 0
    } {}
    jar2.flush().unwrap();
    File::open(jar).is_ok()
}

fn exec_runner<S: AsRef<OsStr>>(args: &[S]) {
    use std::os::unix::process::CommandExt;
    let err = std::process::Command::new(&args[0]).args(&args[1..]).exec();
    println!("error: {}", err);
    if let Some(err) = err.raw_os_error() {
        std::process::exit(err);
    }
    std::process::exit(-1)
}

struct App<'a> {
           sbt_jar: PathBuf,
       sbt_version: String,
           verbose: bool,
          java_cmd: &'a OsStr,
    extra_jvm_opts: Vec<&'a OsStr>,
         java_args: Vec<&'a OsStr>,
      sbt_commands: Vec<&'a OsStr>,
     residual_args: Vec<&'a OsStr>,
}

impl<'a> App<'a> {
    fn new() -> App<'a> {
        App {
                 sbt_jar: PathBuf::new(),
             sbt_version: Default::default(),
                 verbose: Default::default(),
                java_cmd: "java".as_ref(),
          extra_jvm_opts: vec!["-Xms512m".as_ref(), "-Xmx1536m".as_ref(), "-Xss2m".as_ref()],
               java_args: Default::default(),
            sbt_commands: Default::default(),
           residual_args: Default::default(),
        }
    }

    fn vlog(&self, s: &str) { if self.verbose { echoerr!("{}", s); } }

    fn set_sbt_version(&mut self) {
        self.sbt_version=build_props_sbt();
        // sbt_version="${sbt_explicit_version:-$(build_props_sbt)}"
        // [[ -n "$sbt_version" ]] || sbt_version=$sbt_release_version
    }

    fn add_residual(&mut self, s: &'a str) {
        self.vlog(&format!("[residual] arg = {}", s));
        self.residual_args.push(s.as_ref());
    }

    fn process_args(&mut self) {
        for arg in std::env::args().skip(1) {
            match arg.as_ref() {
                "-v" => self.verbose = true,
                s    => panic!("fu"), // self.add_residual(&s),
            }
        }
    }

    fn acquire_sbt_jar(&mut self) -> bool {
        ({
            self.sbt_jar = jar_file(&self.sbt_version);
            File::open(self.sbt_jar.as_path()).is_ok()
        }) || ({
            self.sbt_jar = PathBuf::from(&*HOME);
            self.sbt_jar.push(format!(".ivy2/local/org.scala-sbt/sbt-launch/{}/jars/sbt-launch.jar", self.sbt_version));
            File::open(self.sbt_jar.as_path()).is_ok()
        }) || ({
            self.sbt_jar = jar_file(&self.sbt_version);
            download_url(&self.sbt_version, &make_url(&self.sbt_version), &self.sbt_jar)
        })
    }

    fn run(&mut self) {
        let argument_count = self.residual_args.len();

        self.set_sbt_version();

        if argument_count == 0 {
            self.vlog(&format!("Starting {}: invoke with -help for other options", *script_name));
            self.residual_args = vec!["shell".as_ref()];
        }

        // no jar? download it.
        File::open(self.sbt_jar.as_path()).is_ok() || self.acquire_sbt_jar() || {
            // still no jar? uh-oh.
            println!("Download failed. Obtain the jar manually and place it at {}", self.sbt_jar.display());
            std::process::exit(1);
        };

        let mut exec_args: Vec<&OsStr> = Vec::new();
        exec_args.push(self.java_cmd.as_ref());
        exec_args.append(&mut self.extra_jvm_opts.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut self.java_args.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut vec!["-jar".as_ref(), self.sbt_jar.as_ref()]);
        exec_args.append(&mut self.sbt_commands.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut self.residual_args.iter().map(AsRef::as_ref).collect());

        exec_runner(&exec_args)
    }
}

fn main() {
    let mut app = App::new();
    app.process_args();
    app.run()
}
<commit_msg>Finish implementing -v in exec_runner<commit_after>#![allow(non_upper_case_globals)]

#![allow(dead_code)]
#![allow(unused_assignments)]
#![allow(unused_variables)]

#[macro_use] extern crate lazy_static;

use std::ffi::OsStr;
use std::fs::File;
use std::io::BufReader;
use std::io::prelude::*;
use std::path::{ Path, PathBuf };

lazy_static! {
    static ref HOME: PathBuf = std::env::home_dir().unwrap();

    static ref build_props: PathBuf = PathBuf::from("project/build.properties");

    static ref sbt_launch_dir: PathBuf = { let mut p = PathBuf::from(&*HOME); p.push(".sbt/launchers"); p };

    static ref script_name: String = {
        let n = std::env::args().nth(0).unwrap();
        let n = Path::new(&n).file_name().unwrap().to_str().unwrap();
        n.to_string()
    };

}

const sbt_launch_ivy_release_repo: &'static str = "http://repo.typesafe.com/typesafe/ivy-releases";
const sbt_launch_mvn_release_repo: &'static str = "http://repo.scala-sbt.org/scalasbt/maven-releases";

macro_rules! echoerr(($($arg:tt)*) => (writeln!(&mut ::std::io::stderr(), $($arg)*).unwrap();));

fn build_props_sbt() -> String {
    if let Ok(f) = File::open(&*build_props) {
        let f = BufReader::new(f);
        for line in f.lines() {
            let line = line.unwrap();
            if line.starts_with("sbt.version") {
                let line = line.replace("=", " ");
                let line = line.replace("\r", " ");
                return line.split_whitespace().nth(1).unwrap().to_owned();
            }
        }
    }
    "".to_owned()
}

fn jar_file(version: &str) -> PathBuf {
    let mut p = PathBuf::from(&*sbt_launch_dir);
    p.push(version);
    p.push("sbt-launch.jar");
    p
}

fn url_base(version: &str) -> &'static str { match version {
    s if s.starts_with("0.7.")  => "http://simple-build-tool.googlecode.com",
    s if s.starts_with("0.10.") => sbt_launch_ivy_release_repo,
    "0.11.1" | "0.11.2"         => sbt_launch_ivy_release_repo,
 // "0.*-yyyymmdd-hhMMss"       => sbt_launch_ivy_snapshot_repo, // https://repo.scala-sbt.org/scalasbt/ivy-snapshots
    s if s.starts_with("0.")    => sbt_launch_ivy_release_repo,
 // "*-yyyymmdd-hhMMss"         => sbt_launch_mvn_snapshot_repo, // http://repo.scala-sbt.org/scalasbt/maven-snapshots
    _                           => sbt_launch_mvn_release_repo,
} }

fn make_url(version: &str) -> String {
    let base = url_base(version);
    match version {
        s if s.starts_with("0.7.")  => format!("{}/files/sbt-launch-0.7.7.jar", base),
        s if s.starts_with("0.10.") => format!("{}/org.scala-tools.sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        "0.11.1" | "0.11.2"         => format!("{}/org.scala-tools.sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        s if s.starts_with("0.")    => format!("{}/org.scala-sbt/sbt-launch/{}/sbt-launch.jar", base, version),
        _                           => format!("{}/org/scala-sbt/sbt-launch/{}/sbt-launch.jar", base, version),
    }
}

fn download_url(sbt_version: &str, url: &str, jar: &Path) -> bool {
    echoerr!("Downloading sbt launcher for {}:", sbt_version);
    echoerr!("  From  {}", url);
    echoerr!("    To  {}", jar.display());

    std::fs::create_dir_all(jar.parent().unwrap()).unwrap();

    extern crate hyper;
    let mut r = BufReader::new(hyper::client::Client::new().get(url).send().unwrap());
    let mut buf = [0; 16384];
    let mut jar2 = std::io::BufWriter::new(File::create(jar).unwrap());
    while {
        let bc = r.read(&mut buf).unwrap();
        jar2.write(&buf[0..bc]).unwrap();
        bc > 0
    } {}
    jar2.flush().unwrap();
    File::open(jar).is_ok()
}

struct App<'a> {
           sbt_jar: PathBuf,
       sbt_version: String,
           verbose: bool,
          java_cmd: &'a OsStr,
    extra_jvm_opts: Vec<&'a OsStr>,
         java_args: Vec<&'a OsStr>,
      sbt_commands: Vec<&'a OsStr>,
     residual_args: Vec<&'a OsStr>,
}

impl<'a> App<'a> {
    fn new() -> App<'a> {
        App {
                 sbt_jar: PathBuf::new(),
             sbt_version: Default::default(),
                 verbose: Default::default(),
                java_cmd: "java".as_ref(),
          extra_jvm_opts: vec!["-Xms512m".as_ref(), "-Xmx1536m".as_ref(), "-Xss2m".as_ref()],
               java_args: Default::default(),
            sbt_commands: Default::default(),
           residual_args: Default::default(),
        }
    }

    fn vlog(&self, s: &str) -> bool { if self.verbose { echoerr!("{}", s); true } else { false } }

    fn set_sbt_version(&mut self) {
        self.sbt_version=build_props_sbt();
        // sbt_version="${sbt_explicit_version:-$(build_props_sbt)}"
        // [[ -n "$sbt_version" ]] || sbt_version=$sbt_release_version
    }

    fn add_residual(&mut self, s: &'a str) {
        self.vlog(&format!("[residual] arg = {}", s));
        self.residual_args.push(s.as_ref());
    }

    fn process_args(&mut self) {
        for arg in std::env::args().skip(1) {
            match arg.as_ref() {
                "-v" => self.verbose = true,
                s    => panic!("fu"), // self.add_residual(&s),
            }
        }
    }

    fn acquire_sbt_jar(&mut self) -> bool {
        ({
            self.sbt_jar = jar_file(&self.sbt_version);
            File::open(self.sbt_jar.as_path()).is_ok()
        }) || ({
            self.sbt_jar = PathBuf::from(&*HOME);
            self.sbt_jar.push(format!(".ivy2/local/org.scala-sbt/sbt-launch/{}/jars/sbt-launch.jar", self.sbt_version));
            File::open(self.sbt_jar.as_path()).is_ok()
        }) || ({
            self.sbt_jar = jar_file(&self.sbt_version);
            download_url(&self.sbt_version, &make_url(&self.sbt_version), &self.sbt_jar)
        })
    }

    fn exec_runner<S: AsRef<OsStr>>(&self, args: &[S]) {
        self.vlog("# Executing command line:") && {
            for arg in args {
                let arg = arg.as_ref();
                if !arg.is_empty() {
                    let arg = arg.to_string_lossy();
                    if arg.contains(" ") {
                        echoerr!("\"{}\"", arg);
                    } else {
                        echoerr!("{}", arg);
                    }
                }
            }
            self.vlog("")
        };

        use std::os::unix::process::CommandExt;
        let err = std::process::Command::new(&args[0]).args(&args[1..]).exec();
        println!("error: {}", err);
        if let Some(err) = err.raw_os_error() {
            std::process::exit(err);
        }
        std::process::exit(-1)
    }

    fn run(&mut self) {
        let argument_count = self.residual_args.len();

        self.set_sbt_version();

        if argument_count == 0 {
            self.vlog(&format!("Starting {}: invoke with -help for other options", *script_name));
            self.residual_args = vec!["shell".as_ref()];
        }

        // no jar? download it.
        File::open(self.sbt_jar.as_path()).is_ok() || self.acquire_sbt_jar() || {
            // still no jar? uh-oh.
            println!("Download failed. Obtain the jar manually and place it at {}", self.sbt_jar.display());
            std::process::exit(1);
        };

        let mut exec_args: Vec<&OsStr> = Vec::new();
        exec_args.push(self.java_cmd.as_ref());
        exec_args.append(&mut self.extra_jvm_opts.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut self.java_args.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut vec!["-jar".as_ref(), self.sbt_jar.as_ref()]);
        exec_args.append(&mut self.sbt_commands.iter().map(AsRef::as_ref).collect());
        exec_args.append(&mut self.residual_args.iter().map(AsRef::as_ref).collect());

        self.exec_runner(&exec_args)
    }
}

fn main() {
    let mut app = App::new();
    app.process_args();
    app.run()
}
<|endoftext|>


<commit_before>#[macro_use]
extern crate clap;

use clap::{App, ArgGroup, ArgMatches, SubCommand};

arg_enum!{
    #[derive(Debug)]
    enum DomainRec {
        A,
        AAAA,
        CNAME,
        MX,
        NS,
        SRV,
        TXT
    }
}

fn parse_args<'a, 'b>() -> ArgMatches<'a, 'b> {
    let dns_args = "[name]     'The name to use'
                    [data]     'The user data'
                    [priority] 'The priority to set'
                    [port]     'The port to use'
                    [weight]   'The weight value'";
    App::new("docli")
        .version(&format!("v{}", crate_version!()))
        .about("A utility for managing DigitalOcean infrastructure")
        .author("Kevin K. <kbknapp@gmail.com>")
        .args_from_usage("-d --debug         'Displays JSON being sent to server'
                          -n --nosend        'Does NOT execute network send of JSON'
                          -t --token [token] 'Digital Ocean Auth Token (Defaults to contents \
                                              of DO_AUTH_TOKEN env var if omitted)'")
        .subcommand(SubCommand::new("list")
            .about("Commands for displaying available information")
            .subcommand(SubCommand::new("regions")
                .about("Displays available regions"))
            .subcommand(SubCommand::new("sizes")
                .about("Displays available droplet sizes"))
            .subcommand(SubCommand::new("images")
                .args_from_usage("--distrobutions   'Displays all distrobution images'
                                  --applications    'Displays all application images'
                                  --private         'Displays all private user images'
                                  --available       'Displays all available images (Default)'")
                .about("Displays avaiable droplet images")
                .arg_group(ArgGroup::with_name("images").add_all(vec!["distrobutions",
                                                                      "applications",
                                                                      "private",
                                                                      "available"])))
            .subcommand(SubCommand::new("ssh-keys")
                .about("Displays available SSH keys"))
            .subcommand(SubCommand::new("droplets")
                .about("Displays available droplets"))
            .subcomamnd(SubCommand::new("domains")
                .about("Displays available domains"))
            .subcomamnd(SubCommand::new("account-info")
                .about("Displays all account information"))
            .subcommand(SubCommand::new("account-actions")
                .about("Displays all current and previous account actions")))
        .subcommand(SubCommand::new("account")
            .about("Commands related to a single account")
            .subcommand(SubCommand::new("retrieve-actions")
                .about("Gets information about a particular account action")
                .arg_from_usage("<action_id> 'The action id to retrieve")))
        .subcommand(SubCommand::new("domains")
            .about("Commands for managing domains")
            .subcommand(SubCommand::new("create")
                .about("Creates a new domain")
                .args_from_usage("<name> 'The name for the domain'
                                  <ip>   'The IP address of the domain'"))
            .subcommand(SubCommand::new("retrieve")
                .about("Gets information on a particular domain")
                .arg_from_usage("<name> 'The name of the domain to get'"))
            .subcommand(SubCommand::new("delete")
                .about("Deletes a domain")
                .arg_from_usage("<name> 'The domain to delete'")))
        .subcommand(SubCommand::new("domain")
            .about("Commands for managing a specific domain")
            .arg_from_usage("<name> 'The domain name to use'")
            .subcommand(SubCommand::new("create-record")
                .about("Creates a new DNS record for a domain")
                .arg_from_usage("<type> 'The type of record to create (i.e. A, AAAA, CNAME, \
                                         MX, NS, SRV, TXT)'")
                .args_from_usage(dns_args))
            .subcommand(SubCommand::new("retrieve-record")
                .about("Gets information on a specific DNS record")
                .arg_from_usage("<id>   'The domain ID to retrieve info on'"))
            .subcommand(SubCommand::new("update-record")
                .about("Updates a DNS record")
                .arg_from_usage("<type> 'The type of record to create (i.e. A, AAAA, CNAME, \
                                         MX, NS, SRV, TXT)'")
                .args_from_usage(dns_args))
            .subcommand(SubCommand::new("delete-record")
                .about("Deletes a DNS record")
                .arg_from_usage("<id>   'The domain ID to delete'")))
        .subcommand(SubCommand::new("droplets")
            .about("Commands for managing droplets")
            .subcommand(SubCommand::new("list-all-neighbors")
                .about("Displays all droplets running on the same physical hardware"))
            .subcommand(SubCommand::new("list-upgrades")
                .about("Displays all droplets with pending upgrades"))
            .subcommand(SubCommand::new("create")
                .about("Creates a new droplet")
                .args_from_usage("<name>                      'The name of the droplet'
                                  -r --region <region>        'The region of the droplet'
                                  -z --size <size>            'The size of the droplet'
                                  -i --image <image>          'The image to use'
                                  -s --ssh-keys [ssh_keys]... 'Any ssh keys to add'
                                  --backups                   'Allow backups'
                                  --ipv6                      'Use IPv6'
                                  --private-networking        'Use private networking'
                                  -u --user-data [data]       'User data'")))
        .subcommand(SubCommand::new("droplet")
            .about("Commands for managing a single droplet")
            .arg_from_usage("<id> 'The droplet ID to use'")
            .subcommand(SubCommand::new("retrieve")
                .about("Display the information on the droplet"))
            .subcommand(SubCommand::new("list-kernels")
                .about("Display all available kernels"))
            .subcommand(SubCommand::new("list-snapshots")
                .about("Display all snapshots"))
            .subcommand(SubCommand::new("list-backups")
                .about("Display all backups"))
            .subcommand(SubCommand::new("list-actions")
                .about("Display all current and previous actions"))
            .subcommand(SubCommand::new("list-neighbors")
                .about("Display all droplets running on the same physical hardware"))
            .subcommand(SubCommand::new("delete")
                .about("Deletes a droplet"))
            .subcommand(SubCommand::new("disable-backups")
                .about("Disables backups for a droplet"))
            .subcommand(SubCommand::new("reboot")
                .about("Reboots a droplet"))
            .subcommand(SubCommand::new("power-cycle")
                .about("Performs a power cycle on a droplet"))
            .subcommand(SubCommand::new("shutdown")
                .about("Shutsdown a droplet"))
            .subcommand(SubCommand::new("power-off")
                .about("Powers a droplet off"))
            .subcommand(SubCommand::new("power-on")
                .about("Turns on a droplet"))
            .subcommand(SubCommand::new("restore")
                .about("Restores a droplet from an image")
                .arg_from_usage("<image> 'The image to restore to'"))
            .subcommand(SubCommand::new("password-reset")
                .about("Resets the root password for a droplet"))
            .subcommand(SubCommand::new("resize")
                .about("Resizes a droplet")
                .args_from_usage("--disk 'Resizes the disk'
                                  <size> 'The new size to use'"))
            .subcommand(SubCommand::new("rebuild")
                .about("Rebuilds a droplet from an image")
                .arg_from_usage("<image> 'The image to use'"))
            .subcommand(SubCommand::new("rename")
                .about("Renames a droplet")
                .arg_from_usage("<name> 'The new name of the droplet'"))
            .subcommand(SubCommand::new("change-kernel")
                .about("Changes the kernel of a droplet")
                .arg_from_usage("<kernel_id> 'The kernel ID to use'"))
            .subcommand(SubCommand::new("enable-ipv6")
                .about("Enables IPv6 addresses"))
            .subcommand(SubCommand::new("enable-private-networking")
                .about("Enables private networking"))
            .subcommand(SubCommand::new("snapshot")
                .about("Creates a snapshot of a droplet"))
            .subcommand(SubCommand::new("retrieve-action")
                .about("Displays a specific action for a droplet")
                .arg_from_usage("<action_id> 'The action ID to display'"))
            .subcommand(SubCommand::new("upgrade")
                .about("Performs pending upgrades")))
        .subcommand(SubCommand::new("image")
            .about("Gets or sets information on a particular image")
            .arg_from_usage("<id> 'The image ID to use'")
            .subcommand(SubCommand::new("list-actions")
                .about("Lists all previous and current actions for an image"))
            .subcommand(SubCommand::new("retrieve")
                .about("Displays a particular image")
                .arg_from_usage("--slug 'The <id> provided to \'docli image\' is a slug and \
                                         NOT an image ID'"))
            .subcommand(SubCommand::new("update")
                .about("Performs pending updates"))
            .subcommand(SubCommand::new("delete")
                .about("Deletes an image"))
            .subcommand(SubCommand::new("transfer")
                .about("Transfers an image to a new region")
                .arg_from_usage("<region> 'The region to transfer to'"))
            .subcommand(SubCommand::new("convert")
                .about("Converts a an image (i.e. from a snapshot to a backup)"))
            .subcommand(SubCommand::new("retrieve-action")
                .about("Displays a particular action of an image")
                .arg_from_usage("<action_id> 'The action ID to display'")))
        .subcommand(SubCommand::new("ssh-keys")
            .about("Gets or sets information on SSH keys")
            .subcommand(SubCommand::new("create")
                .about("Creatse a new SSH key")
                .arg_from_usage("<name>       'The name of the SSH key'
                                 <public_key> 'The public key of the SSH key'"))
            .subcommand(SubCommand::new("retrieve")
                .about("Displays information on a particular key")
                .args_from_usage("<key_id>       'The key ID of the key to display'
                                  <finger_print> 'The fingerprint of the key to display'"))
            .subcommand(SubCommand::new("update")
                .about("Updates a particular SSH key")
                .args_from_usage("<name>         'The new name to use'
                                  <key_id>       'The key ID to update'
                                  <finger_print> 'The fingerprint of the key to update'")
                .arg_group(ArgGroup::with_name("sshkeys")
                    .add_all(vec!["key_id",
                                  "finger_print"])
                    .required(true)))
            .subcommand(SubCommand::new("destroy")
                .about("Destroys a particular SSH key")
                .args_from_usage("<key_id>       'The key ID to update'
                                  <finger_print> 'The fingerprint of the key to update'")
                .arg_group(ArgGroup::with_name("sshkeys")
                    .add_all(vec!["key_id",
                                  "finger_print"])
                    .required(true))))
        .subcommand(SubCommand::new("list-regions")
            .about("Display all available regions"))
        .subcommand(SubCommand::new("list-sizes")
            .about("Display all available sizes"))
        .get_matches()
}

fn get_auth_token(m: &ArgMatches) -> String {
    let tok = if let Some(auth_tok) = m.value_of("token") {
            auth_tok.to_owned()
    } else {
        std::env::vars().filter(|&(ref k, _)| k == "DO_AUTH_TOKEN")
                        .map(|(_, v)| v.clone() )
                        .next().unwrap_or("".to_owned())
    };
    if tok.len() != 64 {
        println!("No DigitalOcean Auth Token found.\n\n\
        Use `docli --token <token>` or set the DO_AUTH_TOKEN environment variable and try again");
        std::process::exit(1);
    }
    tok
}

fn main() {
    let m = parse_args();

    let DEBUG = m.is_present("debug");
    let SEND = m.is_present("nosend");
    let AUTH_TOKEN = get_auth_token(&m);

    match m.subcommand() {
        ("account", Some(m))  =>(),
        ("domains", Some(m))  =>(),
        ("domain", Some(m))   =>(),
        ("droplets", Some(m)) =>(),
        ("droplet", Some(m))  =>(),
        ("image", Some(m))    =>(),
        ("ssh-keys", Some(m)) =>(),
        ("list", Some(m))     =>(),
        _                     => println!("No command was provided\n\n{}",m.usage())
    }

    println!("Done");
}
<commit_msg>fixup! refactor(subcommands): re-order and change subcommands<commit_after>#[macro_use]
extern crate clap;

use clap::{App, ArgGroup, ArgMatches, SubCommand};

arg_enum!{
    #[derive(Debug)]
    enum DomainRec {
        A,
        AAAA,
        CNAME,
        MX,
        NS,
        SRV,
        TXT
    }
}

fn parse_args<'a, 'b>() -> ArgMatches<'a, 'b> {
    let dns_args = "[name]     'The name to use'
                    [data]     'The user data'
                    [priority] 'The priority to set'
                    [port]     'The port to use'
                    [weight]   'The weight value'";
    App::new("docli")
        .version(&format!("v{}", crate_version!()))
        .about("A utility for managing DigitalOcean infrastructure")
        .author("Kevin K. <kbknapp@gmail.com>")
        .args_from_usage("-d --debug         'Displays JSON being sent to server'
                          -n --nosend        'Does NOT execute network send of JSON'
                          -t --token [token] 'Digital Ocean Auth Token (Defaults to contents \
                                              of DO_AUTH_TOKEN env var if omitted)'")
        .subcommand(SubCommand::new("list")
            .about("Commands for displaying available information")
            .subcommand(SubCommand::new("regions")
                .about("Displays available regions"))
            .subcommand(SubCommand::new("sizes")
                .about("Displays available droplet sizes"))
            .subcommand(SubCommand::new("images")
                .args_from_usage("--distrobutions   'Displays all distrobution images'
                                  --applications    'Displays all application images'
                                  --private         'Displays all private user images'
                                  --available       'Displays all available images (Default)'")
                .about("Displays avaiable droplet images")
                .arg_group(ArgGroup::with_name("images").add_all(vec!["distrobutions",
                                                                      "applications",
                                                                      "private",
                                                                      "available"])))
            .subcommand(SubCommand::new("ssh-keys")
                .about("Displays available SSH keys"))
            .subcommand(SubCommand::new("droplets")
                .about("Displays available droplets"))
            .subcommand(SubCommand::new("domains")
                .about("Displays available domains"))
            .subcommand(SubCommand::new("account-info")
                .about("Displays all account information"))
            .subcommand(SubCommand::new("account-actions")
                .about("Displays all current and previous account actions")))
        .subcommand(SubCommand::new("account")
            .about("Commands related to a single account")
            .subcommand(SubCommand::new("retrieve-actions")
                .about("Gets information about a particular account action")
                .arg_from_usage("<action_id> 'The action id to retrieve")))
        .subcommand(SubCommand::new("domains")
            .about("Commands for managing domains")
            .subcommand(SubCommand::new("create")
                .about("Creates a new domain")
                .args_from_usage("<name> 'The name for the domain'
                                  <ip>   'The IP address of the domain'"))
            .subcommand(SubCommand::new("retrieve")
                .about("Gets information on a particular domain")
                .arg_from_usage("<name> 'The name of the domain to get'"))
            .subcommand(SubCommand::new("delete")
                .about("Deletes a domain")
                .arg_from_usage("<name> 'The domain to delete'")))
        .subcommand(SubCommand::new("domain")
            .about("Commands for managing a specific domain")
            .arg_from_usage("<name> 'The domain name to use'")
            .subcommand(SubCommand::new("create-record")
                .about("Creates a new DNS record for a domain")
                .arg_from_usage("<type> 'The type of record to create (i.e. A, AAAA, CNAME, \
                                         MX, NS, SRV, TXT)'")
                .args_from_usage(dns_args))
            .subcommand(SubCommand::new("retrieve-record")
                .about("Gets information on a specific DNS record")
                .arg_from_usage("<id>   'The domain ID to retrieve info on'"))
            .subcommand(SubCommand::new("update-record")
                .about("Updates a DNS record")
                .arg_from_usage("<type> 'The type of record to create (i.e. A, AAAA, CNAME, \
                                         MX, NS, SRV, TXT)'")
                .args_from_usage(dns_args))
            .subcommand(SubCommand::new("delete-record")
                .about("Deletes a DNS record")
                .arg_from_usage("<id>   'The domain ID to delete'")))
        .subcommand(SubCommand::new("droplets")
            .about("Commands for managing droplets")
            .subcommand(SubCommand::new("list-all-neighbors")
                .about("Displays all droplets running on the same physical hardware"))
            .subcommand(SubCommand::new("list-upgrades")
                .about("Displays all droplets with pending upgrades"))
            .subcommand(SubCommand::new("create")
                .about("Creates a new droplet")
                .args_from_usage("<name>                      'The name of the droplet'
                                  -r --region <region>        'The region of the droplet'
                                  -z --size <size>            'The size of the droplet'
                                  -i --image <image>          'The image to use'
                                  -s --ssh-keys [ssh_keys]... 'Any ssh keys to add'
                                  --backups                   'Allow backups'
                                  --ipv6                      'Use IPv6'
                                  --private-networking        'Use private networking'
                                  -u --user-data [data]       'User data'")))
        .subcommand(SubCommand::new("droplet")
            .about("Commands for managing a single droplet")
            .arg_from_usage("<id> 'The droplet ID to use'")
            .subcommand(SubCommand::new("retrieve")
                .about("Display the information on the droplet"))
            .subcommand(SubCommand::new("list-kernels")
                .about("Display all available kernels"))
            .subcommand(SubCommand::new("list-snapshots")
                .about("Display all snapshots"))
            .subcommand(SubCommand::new("list-backups")
                .about("Display all backups"))
            .subcommand(SubCommand::new("list-actions")
                .about("Display all current and previous actions"))
            .subcommand(SubCommand::new("list-neighbors")
                .about("Display all droplets running on the same physical hardware"))
            .subcommand(SubCommand::new("delete")
                .about("Deletes a droplet"))
            .subcommand(SubCommand::new("disable-backups")
                .about("Disables backups for a droplet"))
            .subcommand(SubCommand::new("reboot")
                .about("Reboots a droplet"))
            .subcommand(SubCommand::new("power-cycle")
                .about("Performs a power cycle on a droplet"))
            .subcommand(SubCommand::new("shutdown")
                .about("Shutsdown a droplet"))
            .subcommand(SubCommand::new("power-off")
                .about("Powers a droplet off"))
            .subcommand(SubCommand::new("power-on")
                .about("Turns on a droplet"))
            .subcommand(SubCommand::new("restore")
                .about("Restores a droplet from an image")
                .arg_from_usage("<image> 'The image to restore to'"))
            .subcommand(SubCommand::new("password-reset")
                .about("Resets the root password for a droplet"))
            .subcommand(SubCommand::new("resize")
                .about("Resizes a droplet")
                .args_from_usage("--disk 'Resizes the disk'
                                  <size> 'The new size to use'"))
            .subcommand(SubCommand::new("rebuild")
                .about("Rebuilds a droplet from an image")
                .arg_from_usage("<image> 'The image to use'"))
            .subcommand(SubCommand::new("rename")
                .about("Renames a droplet")
                .arg_from_usage("<name> 'The new name of the droplet'"))
            .subcommand(SubCommand::new("change-kernel")
                .about("Changes the kernel of a droplet")
                .arg_from_usage("<kernel_id> 'The kernel ID to use'"))
            .subcommand(SubCommand::new("enable-ipv6")
                .about("Enables IPv6 addresses"))
            .subcommand(SubCommand::new("enable-private-networking")
                .about("Enables private networking"))
            .subcommand(SubCommand::new("snapshot")
                .about("Creates a snapshot of a droplet"))
            .subcommand(SubCommand::new("retrieve-action")
                .about("Displays a specific action for a droplet")
                .arg_from_usage("<action_id> 'The action ID to display'"))
            .subcommand(SubCommand::new("upgrade")
                .about("Performs pending upgrades")))
        .subcommand(SubCommand::new("image")
            .about("Gets or sets information on a particular image")
            .arg_from_usage("<id> 'The image ID to use'")
            .subcommand(SubCommand::new("list-actions")
                .about("Lists all previous and current actions for an image"))
            .subcommand(SubCommand::new("retrieve")
                .about("Displays a particular image")
                .arg_from_usage("--slug 'The <id> provided to \'docli image\' is a slug and \
                                         NOT an image ID'"))
            .subcommand(SubCommand::new("update")
                .about("Performs pending updates"))
            .subcommand(SubCommand::new("delete")
                .about("Deletes an image"))
            .subcommand(SubCommand::new("transfer")
                .about("Transfers an image to a new region")
                .arg_from_usage("<region> 'The region to transfer to'"))
            .subcommand(SubCommand::new("convert")
                .about("Converts a an image (i.e. from a snapshot to a backup)"))
            .subcommand(SubCommand::new("retrieve-action")
                .about("Displays a particular action of an image")
                .arg_from_usage("<action_id> 'The action ID to display'")))
        .subcommand(SubCommand::new("ssh-keys")
            .about("Gets or sets information on SSH keys")
            .subcommand(SubCommand::new("create")
                .about("Creatse a new SSH key")
                .arg_from_usage("<name>       'The name of the SSH key'
                                 <public_key> 'The public key of the SSH key'"))
            .subcommand(SubCommand::new("retrieve")
                .about("Displays information on a particular key")
                .args_from_usage("<key_id>       'The key ID of the key to display'
                                  <finger_print> 'The fingerprint of the key to display'"))
            .subcommand(SubCommand::new("update")
                .about("Updates a particular SSH key")
                .args_from_usage("<name>         'The new name to use'
                                  <key_id>       'The key ID to update'
                                  <finger_print> 'The fingerprint of the key to update'")
                .arg_group(ArgGroup::with_name("sshkeys")
                    .add_all(vec!["key_id",
                                  "finger_print"])
                    .required(true)))
            .subcommand(SubCommand::new("destroy")
                .about("Destroys a particular SSH key")
                .args_from_usage("<key_id>       'The key ID to update'
                                  <finger_print> 'The fingerprint of the key to update'")
                .arg_group(ArgGroup::with_name("sshkeys")
                    .add_all(vec!["key_id",
                                  "finger_print"])
                    .required(true))))
        .subcommand(SubCommand::new("list-regions")
            .about("Display all available regions"))
        .subcommand(SubCommand::new("list-sizes")
            .about("Display all available sizes"))
        .get_matches()
}

fn get_auth_token(m: &ArgMatches) -> String {
    let tok = if let Some(auth_tok) = m.value_of("token") {
            auth_tok.to_owned()
    } else {
        std::env::vars().filter(|&(ref k, _)| k == "DO_AUTH_TOKEN")
                        .map(|(_, v)| v.clone() )
                        .next().unwrap_or("".to_owned())
    };
    if tok.len() != 64 {
        println!("No DigitalOcean Auth Token found.\n\n\
        Use `docli --token <token>` or set the DO_AUTH_TOKEN environment variable and try again");
        std::process::exit(1);
    }
    tok
}

fn main() {
    let m = parse_args();

    let DEBUG = m.is_present("debug");
    let SEND = m.is_present("nosend");
    let AUTH_TOKEN = get_auth_token(&m);

    match m.subcommand() {
        ("account", Some(m))  =>(),
        ("domains", Some(m))  =>(),
        ("domain", Some(m))   =>(),
        ("droplets", Some(m)) =>(),
        ("droplet", Some(m))  =>(),
        ("image", Some(m))    =>(),
        ("ssh-keys", Some(m)) =>(),
        ("list", Some(m))     =>(),
        _                     => println!("No command was provided\n\n{}",m.usage())
    }

    println!("Done");
}
<|endoftext|>


<commit_before>extern crate ansi_term;
#[macro_use]
extern crate clap;
extern crate hyper;
extern crate libsnatch;
extern crate num_cpus;

use ansi_term::Colour::{Green, Yellow, Red};
use clap::{App, Arg};
use libsnatch::download::download_chunks;
use libsnatch::write::OutputFileWriter;
use libsnatch::util::prompt_user;
use libsnatch::filesize::format_filesize;
use libsnatch::cargo_helper::get_cargo_info;
use std::fs::File;
use std::path::Path;
use std::process::exit;

static DEFAULT_FILENAME: &'static str = "index.html";

fn main() {

    // Parse arguments

    let argparse = App::new("Snatch")
        .about("Snatch, a simple, fast and interruptable download accelerator, written in Rust.")
        .version(crate_version!())
        .arg(Arg::with_name("file")
            .long("file")
            .short("f")
            .takes_value(true)
            .help("The local file to save the remote content file"))
        .arg(Arg::with_name("threads")
            .long("threads")
            .short("t")
            .takes_value(true)
            .help("Threads which can use to download"))
        .arg(Arg::with_name("debug")
            .long("debug")
            .short("d")
            .help("Active the debug mode"))
        .arg(Arg::with_name("force")
            .long("force")
            .help("Assume Yes to all queries and do not prompt"))
        .arg(Arg::with_name("url")
            .index(1)
            //.multiple(true)
            .required(true))
        .get_matches();

    // Get informations from arguments

    let url = argparse.value_of("url").unwrap();

    let file = argparse.value_of("file")
        .unwrap_or_else(|| url.split('/').last().unwrap_or(DEFAULT_FILENAME));

    let threads: usize = value_t!(argparse, "threads", usize).unwrap_or(num_cpus::get_physical());

    if argparse.is_present("debug") {
        println!("# [{}] version: {}",
                 Yellow.bold().paint("DEBUG_MODE"),
                 crate_version!());
        println!("# [{}] file: {}", Yellow.bold().paint("DEBUG_MODE"), file);
        println!("# [{}] threads: {}",
                 Yellow.bold().paint("DEBUG_MODE"),
                 threads);
    }

    let local_path = Path::new(&file);

    if local_path.exists() {
        if local_path.is_dir() {
            panic!(Red.bold()
                .paint("[ERROR] The local path to store the remote content is already exists, \
                        and is a directory!"));
        }
        if !argparse.is_present("force") {
            let user_input = prompt_user(Yellow.bold(),
                                         "[WARNING] The path to store the file already exists! \
                                          Do you want to override it? [y/N]");

            if !(user_input == "y" || user_input == "Y") {
                exit(0);
            }
        } else {
            println!("{}",
                     Yellow.bold()
                         .paint("[WARNING] The path to store the file already exists! \
                                 It is going to be overriden."));
        }
    }

    let cargo_info = get_cargo_info(&url).expect("fail to parse url");
    println!("# Remote content length: {}", format_filesize(cargo_info.content_length));

    let local_file = File::create(local_path).expect("[ERROR] Cannot create a file !");

    local_file.set_len(cargo_info.content_length)
        .expect("[ERROR] Cannot extend file to download size!");
    let out_file = OutputFileWriter::new(local_file);

    download_chunks(cargo_info, out_file, threads as u64, &url);

    println!("{} Your download is available in {}",
             Green.bold().paint("Done!"),
             local_path.to_str().unwrap());
}
<commit_msg>Format code<commit_after>extern crate ansi_term;
#[macro_use]
extern crate clap;
extern crate hyper;
extern crate libsnatch;
extern crate num_cpus;

use ansi_term::Colour::{Green, Yellow, Red};
use clap::{App, Arg};
use libsnatch::download::download_chunks;
use libsnatch::write::OutputFileWriter;
use libsnatch::util::prompt_user;
use libsnatch::filesize::format_filesize;
use libsnatch::cargo_helper::get_cargo_info;
use std::fs::File;
use std::path::Path;
use std::process::exit;

static DEFAULT_FILENAME: &'static str = "index.html";

fn main() {

    // Parse arguments

    let argparse = App::new("Snatch")
        .about("Snatch, a simple, fast and interruptable download accelerator, written in Rust.")
        .version(crate_version!())
        .arg(Arg::with_name("file")
            .long("file")
            .short("f")
            .takes_value(true)
            .help("The local file to save the remote content file"))
        .arg(Arg::with_name("threads")
            .long("threads")
            .short("t")
            .takes_value(true)
            .help("Threads which can use to download"))
        .arg(Arg::with_name("debug")
            .long("debug")
            .short("d")
            .help("Active the debug mode"))
        .arg(Arg::with_name("force")
            .long("force")
            .help("Assume Yes to all queries and do not prompt"))
        .arg(Arg::with_name("url")
            .index(1)
            //.multiple(true)
            .required(true))
        .get_matches();

    // Get informations from arguments

    let url = argparse.value_of("url").unwrap();

    let file = argparse.value_of("file").unwrap_or_else(|| {
                                                            url.split('/')
                                                                .last()
                                                                .unwrap_or(DEFAULT_FILENAME)
                                                        });

    let threads: usize = value_t!(argparse, "threads", usize).unwrap_or(num_cpus::get_physical());

    if argparse.is_present("debug") {
        println!("# [{}] version: {}",
                 Yellow.bold().paint("DEBUG_MODE"),
                 crate_version!());
        println!("# [{}] file: {}", Yellow.bold().paint("DEBUG_MODE"), file);
        println!("# [{}] threads: {}",
                 Yellow.bold().paint("DEBUG_MODE"),
                 threads);
    }

    let local_path = Path::new(&file);

    if local_path.exists() {
        if local_path.is_dir() {
            panic!(Red.bold()
                .paint("[ERROR] The local path to store the remote content is already exists, \
                        and is a directory!"));
        }
        if !argparse.is_present("force") {
            let user_input = prompt_user(Yellow.bold(),
                                         "[WARNING] The path to store the file already exists! \
                                          Do you want to override it? [y/N]");

            if !(user_input == "y" || user_input == "Y") {
                exit(0);
            }
        } else {
            println!("{}",
                     Yellow.bold().paint("[WARNING] The path to store the file already exists! \
                                 It is going to be overriden."));
        }
    }

    let cargo_info = get_cargo_info(&url).expect("fail to parse url");
    println!("# Remote content length: {}",
             format_filesize(cargo_info.content_length));

    let local_file = File::create(local_path).expect("[ERROR] Cannot create a file !");

    local_file.set_len(cargo_info.content_length)
        .expect("[ERROR] Cannot extend file to download size!");
    let out_file = OutputFileWriter::new(local_file);

    download_chunks(cargo_info, out_file, threads as u64, &url);

    println!("{} Your download is available in {}",
             Green.bold().paint("Done!"),
             local_path.to_str().unwrap());
}
<|endoftext|>


<commit_before>#![recursion_limit = "1024"] // error_chain

extern crate websocket;
extern crate env_logger;
#[macro_use]
extern crate log;
#[macro_use]
extern crate error_chain;
extern crate url;
extern crate clap;

use std::thread;
use std::io::{stdin,stdout};

use websocket::{Message, Sender, Receiver, DataFrame};
use websocket::message::Type;
use websocket::client::request::Url;
use websocket::Client;

use std::borrow::Borrow;
use std::io::{Error as IoError, ErrorKind as IoErrorKind, Write, Read};

error_chain! {
    foreign_links {
        ::std::io::Error, Io;
        log::SetLoggerError, Log;
        ::url::ParseError, Url;
        ::websocket::result::WebSocketError, Ws;
        ::std::env::VarError, Ev;
    }
    errors {
        InvalidSpecifier(t : String) {
            description("invalid specifier")
            display("Invalid client or server specifier `{}`", t)
        }
    }
}

// Initialize logger with default "info" log level:
fn init_logger() -> Result<()> {
    let mut builder = env_logger::LogBuilder::new();
    builder.filter(None, log::LogLevelFilter::Info);
    if ::std::env::var("RUST_LOG").is_ok() {
       builder.parse(&::std::env::var("RUST_LOG")?);
    }
    builder.init()?;
    Ok(())
}

struct SenderWrapper<T: Sender> (T);

impl<T: Sender> ::std::io::Write for SenderWrapper<T> {
    fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
        let message = Message::binary(buf);
        let ret;
        let len = buf.len();
        if len > 0 {
            debug!("Sending message of {} bytes", len);
            ret = self.0.send_message(&message);
        } else {
            // Interpret zero length buffer is request
            // to close communication

            debug!("Sending the closing message");
            ret = self.0.send_message(&Message::close());
        }
        ret.map_err(|e|IoError::new(IoErrorKind::BrokenPipe, e))?;
        Ok(len)
    }
    fn flush(&mut self) -> ::std::io::Result<()> {
        Ok(())
    }
}

struct ReceiverWrapper<T: Receiver<DataFrame>> (T);

impl<T:Receiver<DataFrame>> ::std::io::Read for ReceiverWrapper<T> {
    fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
        let ret = self.0.recv_message();
        let msg : Message = ret.map_err(|e|IoError::new(IoErrorKind::BrokenPipe, e))?;

        match msg.opcode {
            Type::Close => {
                Ok(0)
            }
            Type::Ping => {
                // Sender used to be in a separate thread with a channel
                // now there's no channel, so trickier to combine ping replies
                // and usual data exchange
                unimplemented!();
            }
            _ => {
                let msgpayload : &[u8] = msg.payload.borrow();
                let len = msgpayload.len();
                debug!("Received message of {} bytes", len);

                assert!(buf.len() >= len);

                buf[0..len].copy_from_slice(msgpayload);

                Ok(len)
            }
        }
    }
}

struct Peer<R, W>
    where R : Read + Send + 'static, W: Write + Send + 'static
{
    reader: R,
    writer: W,
}

type IPeer = Peer<Box<Read+Send>, Box<Write+Send>>;

struct DataExchangeSession<R1, R2, W1, W2>
    where R1 : Read  + Send + 'static,
          R2 : Read  + Send + 'static,
          W1 : Write + Send + 'static,
          W2 : Write + Send + 'static,
{
    peer1: Peer<R1, W1>,
    peer2: Peer<R2, W2>,
}

impl<R1,R2,W1,W2> DataExchangeSession<R1,R2,W1,W2>
    where R1 : Read  + Send + 'static,
          R2 : Read  + Send + 'static,
          W1 : Write + Send + 'static,
          W2 : Write + Send + 'static,
{
    fn data_exchange(self) -> Result<()> {

        let mut reader1 = self.peer1.reader;
        let mut writer1 = self.peer1.writer;
        let mut reader2 = self.peer2.reader;
        let mut writer2 = self.peer2.writer;

        let receive_loop = thread::spawn(move || -> Result<()> {
            // Actual data transfer happens here
            ::std::io::copy(&mut reader1, &mut writer2)?;
            writer2.write(b"")?; // signal close
            Ok(())
        });

        // Actual data transfer happens here
        ::std::io::copy(&mut reader2, &mut writer1)?;
        writer1.write(b"")?; // Signal close

        debug!("Waiting for receiver side to exit");

        receive_loop.join().map_err(|x|format!("{:?}",x))?
    }
}

fn get_websocket_peer(urlstr: &str) -> Result<
        Peer<
            ReceiverWrapper<websocket::client::Receiver<websocket::WebSocketStream>>,
            SenderWrapper<websocket::client::Sender<websocket::WebSocketStream>>>
        > {
    let url = Url::parse(urlstr)?;

    info!("Connecting to {}", url);

    let request = Client::connect(url)?;

    let response = request.send()?; // Send the request and retrieve a response

    info!("Validating response...");

    response.validate()?; // Validate the response

    info!("Successfully connected");

    let (sender, receiver) = response.begin().split();

    let peer = Peer {
        reader : ReceiverWrapper(receiver),
        writer : SenderWrapper(sender),
    };
    Ok(peer)
}

fn get_tcp_peer(addr: &str) -> Result<
        Peer<
            ::std::net::TcpStream,
            ::std::net::TcpStream,
        >> {
    let sock = ::std::net::TcpStream::connect(addr)?;

    let peer = Peer {
        reader : sock.try_clone()?,
        writer : sock.try_clone()?,
    };
    info!("Connected to TCP {}", addr);
    Ok(peer)
}

fn get_stdio_peer() -> Result<Peer<std::io::Stdin, std::io::Stdout>> {
    Ok(
        Peer {
            reader : stdin(),
            writer : stdout(),
        }
    )
}

impl<R,W> Peer<R,W>
    where R : Read + Send + 'static, W: Write + Send + 'static
{
    fn upcast(self) -> IPeer  {
        Peer {
            reader: Box::new(self.reader) as Box<Read +Send>,
            writer: Box::new(self.writer) as Box<Write+Send>,
        }
    }
}

trait Server
{
    fn start_serving(&self, spec: &str, once: bool) {

    }
}

enum Spec {
    Server(Box<Server + Send>),
    Client(IPeer)
}

fn get_peer_by_spec(specifier: &str) -> Result<Spec> {
    use Spec::{Server,Client};
    match specifier {
        x if x == "-"               => Ok(Client(get_stdio_peer()?.upcast())),
        x if x.starts_with("ws:")   => Ok(Client(get_websocket_peer(x)?.upcast())),
        x if x.starts_with("wss:")  => Ok(Client(get_websocket_peer(x)?.upcast())),
        x if x.starts_with("tcp:")  => Ok(Client(get_tcp_peer(&x[4..])?.upcast())),
        x => Err(ErrorKind::InvalidSpecifier(x.to_string()).into()),
    }
}

fn try_main() -> Result<()> {
    //env_logger::init()?;
    init_logger()?;

    // setup command line arguments
    let matches = ::clap::App::new("websocat")
        .version("0.1")
        .author("Vitaly \"_Vi\" Shukela <vi0oss@gmail.com>")
        .about("Exchange binary data between binary websocket and something.\nSocat analogue with websockets.")
        .arg(::clap::Arg::with_name("spec1")
             .help("First specifier.")
             .required(true)
             .index(1))
        .arg(::clap::Arg::with_name("spec2")
             .help("Second specifier.")
             .required(true)
             .index(2))
        .after_help(r#"
Specifiers can be:
  ws[s]://<rest of websocket URL>    Connect to websocket
  tcp:<socket address>               Connect to TCP
  tcp-l:<socer address>
  -                                  stdin/stdout
  (more to be implemented)

Examples:
  websocat - wss://myserver/mysocket
    Connect stdin/stdout to secure web socket once.
    Like netcat, but for websocket.
  websocat ws://localhost:1234/ tcp:localhost:1235
    Connect both to websocket and to TCP and exchange data.
  websocat tcp-l::::9559 ws://echo.websocket.org/
    Listen TCPv6 port 9959 on address :: and forward
    all connections to a public loopback websocket

Specify listening part first, unless you want websocat to serve once.
"#)
        .get_matches();

    let spec1  = matches.value_of("spec1") .ok_or("no listener_spec" )?;
    let spec2 = matches.value_of("spec2").ok_or("no connector_spec")?;

    let spec1_ = get_peer_by_spec(spec1)?;

    match spec1_ {
        Spec::Server(x) => {
            unimplemented!();
        }
        Spec::Client(p1) => {
            let spec2_ = get_peer_by_spec(spec2)?;

            match spec2_ {
                Spec::Server(x) => {
                    unimplemented!();
                }
                Spec::Client(p2) => {
                    let des = DataExchangeSession {
                        peer1 : p1,
                        peer2 : p2,
                    };

                    des.data_exchange()?;
                }
            }
        }
    }

    debug!("Exited");
    Ok(())
}

fn main() {
    if let Err(x) = try_main() {
        let _ = writeln!(::std::io::stderr(), "{:?}", x);
    }
}

<commit_msg>Before TCP server impl<commit_after>#![recursion_limit = "1024"] // error_chain

extern crate websocket;
extern crate env_logger;
#[macro_use]
extern crate log;
#[macro_use]
extern crate error_chain;
extern crate url;
extern crate clap;

use std::thread;
use std::io::{stdin,stdout};

use websocket::{Message, Sender, Receiver, DataFrame};
use websocket::message::Type;
use websocket::client::request::Url;
use websocket::Client;

use std::borrow::Borrow;
use std::io::{Error as IoError, ErrorKind as IoErrorKind, Write, Read};

error_chain! {
    foreign_links {
        ::std::io::Error, Io;
        log::SetLoggerError, Log;
        ::url::ParseError, Url;
        ::websocket::result::WebSocketError, Ws;
        ::std::env::VarError, Ev;
    }
    errors {
        InvalidSpecifier(t : String) {
            description("invalid specifier")
            display("Invalid client or server specifier `{}`", t)
        }
    }
}

// Initialize logger with default "info" log level:
fn init_logger() -> Result<()> {
    let mut builder = env_logger::LogBuilder::new();
    builder.filter(None, log::LogLevelFilter::Info);
    if ::std::env::var("RUST_LOG").is_ok() {
       builder.parse(&::std::env::var("RUST_LOG")?);
    }
    builder.init()?;
    Ok(())
}

struct SenderWrapper<T: Sender> (T);

impl<T: Sender> ::std::io::Write for SenderWrapper<T> {
    fn write(&mut self, buf: &[u8]) -> ::std::io::Result<usize> {
        let message = Message::binary(buf);
        let ret;
        let len = buf.len();
        if len > 0 {
            debug!("Sending message of {} bytes", len);
            ret = self.0.send_message(&message);
        } else {
            // Interpret zero length buffer is request
            // to close communication

            debug!("Sending the closing message");
            ret = self.0.send_message(&Message::close());
        }
        ret.map_err(|e|IoError::new(IoErrorKind::BrokenPipe, e))?;
        Ok(len)
    }
    fn flush(&mut self) -> ::std::io::Result<()> {
        Ok(())
    }
}

struct ReceiverWrapper<T: Receiver<DataFrame>> (T);

impl<T:Receiver<DataFrame>> ::std::io::Read for ReceiverWrapper<T> {
    fn read(&mut self, buf: &mut [u8]) -> ::std::io::Result<usize> {
        let ret = self.0.recv_message();
        let msg : Message = ret.map_err(|e|IoError::new(IoErrorKind::BrokenPipe, e))?;

        match msg.opcode {
            Type::Close => {
                Ok(0)
            }
            Type::Ping => {
                // Sender used to be in a separate thread with a channel
                // now there's no channel, so trickier to combine ping replies
                // and usual data exchange
                unimplemented!();
            }
            _ => {
                let msgpayload : &[u8] = msg.payload.borrow();
                let len = msgpayload.len();
                debug!("Received message of {} bytes", len);

                assert!(buf.len() >= len);

                buf[0..len].copy_from_slice(msgpayload);

                Ok(len)
            }
        }
    }
}

struct Peer<R, W>
    where R : Read + Send + 'static, W: Write + Send + 'static
{
    reader: R,
    writer: W,
}

type IPeer = Peer<Box<Read+Send>, Box<Write+Send>>;

struct DataExchangeSession<R1, R2, W1, W2>
    where R1 : Read  + Send + 'static,
          R2 : Read  + Send + 'static,
          W1 : Write + Send + 'static,
          W2 : Write + Send + 'static,
{
    peer1: Peer<R1, W1>,
    peer2: Peer<R2, W2>,
}

impl<R1,R2,W1,W2> DataExchangeSession<R1,R2,W1,W2>
    where R1 : Read  + Send + 'static,
          R2 : Read  + Send + 'static,
          W1 : Write + Send + 'static,
          W2 : Write + Send + 'static,
{
    fn data_exchange(self) -> Result<()> {

        let mut reader1 = self.peer1.reader;
        let mut writer1 = self.peer1.writer;
        let mut reader2 = self.peer2.reader;
        let mut writer2 = self.peer2.writer;

        let receive_loop = thread::spawn(move || -> Result<()> {
            // Actual data transfer happens here
            ::std::io::copy(&mut reader1, &mut writer2)?;
            writer2.write(b"")?; // signal close
            Ok(())
        });

        // Actual data transfer happens here
        ::std::io::copy(&mut reader2, &mut writer1)?;
        writer1.write(b"")?; // Signal close

        debug!("Waiting for receiver side to exit");

        receive_loop.join().map_err(|x|format!("{:?}",x))?
    }
}

fn get_websocket_peer(urlstr: &str) -> Result<
        Peer<
            ReceiverWrapper<websocket::client::Receiver<websocket::WebSocketStream>>,
            SenderWrapper<websocket::client::Sender<websocket::WebSocketStream>>>
        > {
    let url = Url::parse(urlstr)?;

    info!("Connecting to {}", url);

    let request = Client::connect(url)?;

    let response = request.send()?; // Send the request and retrieve a response

    info!("Validating response...");

    response.validate()?; // Validate the response

    info!("Successfully connected");

    let (sender, receiver) = response.begin().split();

    let peer = Peer {
        reader : ReceiverWrapper(receiver),
        writer : SenderWrapper(sender),
    };
    Ok(peer)
}

fn get_tcp_peer(addr: &str) -> Result<
        Peer<
            ::std::net::TcpStream,
            ::std::net::TcpStream,
        >> {
    let sock = ::std::net::TcpStream::connect(addr)?;

    let peer = Peer {
        reader : sock.try_clone()?,
        writer : sock.try_clone()?,
    };
    info!("Connected to TCP {}", addr);
    Ok(peer)
}

fn get_stdio_peer() -> Result<Peer<std::io::Stdin, std::io::Stdout>> {
    Ok(
        Peer {
            reader : stdin(),
            writer : stdout(),
        }
    )
}

impl<R,W> Peer<R,W>
    where R : Read + Send + 'static, W: Write + Send + 'static
{
    fn upcast(self) -> IPeer  {
        Peer {
            reader: Box::new(self.reader) as Box<Read +Send>,
            writer: Box::new(self.writer) as Box<Write+Send>,
        }
    }
}

trait Server
{
    fn start_serving(&mut self, spec: &str, once: bool);
    fn first_connected_client(&mut self) -> Result<IPeer>;
    fn stop(&mut self);

    fn upcast(self) -> Box<Server+Send>
        where Self : Sized + Send + 'static
        { Box::new(self) as Box<Server+Send> }
}

enum Spec {
    Server(Box<Server + Send>),
    Client(IPeer)
}

struct TcpServer {

}
impl TcpServer {
    fn new(addr: &str) -> Result<Self> {
        unimplemented!()
    }
}

impl Server for TcpServer {
    fn start_serving(&mut self, spec: &str, once: bool) { unimplemented!() }
    fn first_connected_client(&mut self) -> Result<IPeer> { unimplemented!() }
    fn stop(&mut self) { unimplemented!() }
}

fn get_peer_by_spec(specifier: &str) -> Result<Spec> {
    use Spec::{Server,Client};
    match specifier {
        x if x == "-"               => Ok(Client(get_stdio_peer()?.upcast())),
        x if x.starts_with("ws:")   => Ok(Client(get_websocket_peer(x)?.upcast())),
        x if x.starts_with("wss:")  => Ok(Client(get_websocket_peer(x)?.upcast())),
        x if x.starts_with("tcp:")  => Ok(Client(get_tcp_peer(&x[4..])?.upcast())),
        x if x.starts_with("l-tcp:")  => Ok(Server(TcpServer::new(&x[6..])?.upcast())),
        x => Err(ErrorKind::InvalidSpecifier(x.to_string()).into()),
    }
}

fn try_main() -> Result<()> {
    //env_logger::init()?;
    init_logger()?;

    // setup command line arguments
    let matches = ::clap::App::new("websocat")
        .version("0.1")
        .author("Vitaly \"_Vi\" Shukela <vi0oss@gmail.com>")
        .about("Exchange binary data between binary websocket and something.\nSocat analogue with websockets.")
        .arg(::clap::Arg::with_name("spec1")
             .help("First specifier.")
             .required(true)
             .index(1))
        .arg(::clap::Arg::with_name("spec2")
             .help("Second specifier.")
             .required(true)
             .index(2))
        .after_help(r#"
Specifiers can be:
  ws[s]://<rest of websocket URL>    Connect to websocket
  tcp:<socket address>               Connect to TCP
  l-tcp:<socket address>             Listen TCP connections
  -                                  stdin/stdout
  (more to be implemented)

Examples:
  websocat - wss://myserver/mysocket
    Connect stdin/stdout to secure web socket once.
    Like netcat, but for websocket.
  websocat ws://localhost:1234/ tcp:localhost:1235
    Connect both to websocket and to TCP and exchange data.
  websocat l-tcp::::9559 ws://echo.websocket.org/
    Listen TCPv6 port 9959 on address :: and forward
    all connections to a public loopback websocket

Specify listening part first, unless you want websocat to serve once.
"#)
        .get_matches();

    let spec1  = matches.value_of("spec1") .ok_or("no listener_spec" )?;
    let spec2 = matches.value_of("spec2").ok_or("no connector_spec")?;

    let spec1_ = get_peer_by_spec(spec1)?;

    match spec1_ {
        Spec::Server(mut x) => {
            x.start_serving(spec2, false);
        }
        Spec::Client(p1) => {
            let spec2_ = get_peer_by_spec(spec2)?;

            let otherpeer = match spec2_ {
                Spec::Server(mut x) => {
                    let t = x.first_connected_client()?;
                    x.stop();
                    t
                }
                Spec::Client(p2) => {
                    p2
                }
            };

            let des = DataExchangeSession {
                peer1 : p1,
                peer2 : otherpeer,
            };

            des.data_exchange()?;
        }
    }

    debug!("Exited");
    Ok(())
}

fn main() {
    if let Err(x) = try_main() {
        let _ = writeln!(::std::io::stderr(), "{:?}", x);
    }
}

<|endoftext|>