The latter needs implementation, but the API seems nice.
Showing the changes to git-credentials/src/program (3 of 8 files). Show all
Unified · Split
| @@ -8,6 +8,7 @@ impl Default for Cascade { · 7 unmodified lines | ||
| 8 | 8 | Cascade { |
| 9 | 9 | programs: Vec::new(), |
| 10 | 10 | stderr: true, |
| 11 | + #[cfg(feature = "prompt")] | |
| 11 | 12 | prompt: true, |
| 12 | 13 | } |
| 13 | 14 | } |
| @@ -127,10 +128,10 @@ impl Cascade { · 113 unmodified lines | ||
| 127 | 128 | if self.prompt { |
| 128 | 129 | if let Some(ctx) = action.context_mut() { |
| 129 | 130 | if let username @ None = &mut ctx.username { |
| 130 | − *username = crate::program::prompt::openly("Username: ")?.into(); | |
| 131 | + *username = git_prompt::openly("Username: ")?.into(); | |
| 131 | 132 | } |
| 132 | 133 | if let password @ None = &mut ctx.password { |
| 133 | − *password = crate::program::prompt::securely("Password: ")?.into(); | |
| 134 | + *password = git_prompt::securely("Password: ")?.into(); | |
| 134 | 135 | } |
| 135 | 136 | } |
| 136 | 137 | } |
| @@ -16,9 +16,6 @@ pub struct Cascade { · 15 unmodified lines | ||
| 16 | 16 | } |
| 17 | 17 | |
| 18 | 18 | mod cascade; |
| 19 | −#[cfg(feature = "prompt")] | |
| 20 | −/// | |
| 21 | −pub mod prompt; | |
| 22 | 19 | |
| 23 | 20 | /// The kind of helper program to use. |
| 24 | 21 | #[derive(Debug, Clone, Eq, PartialEq)] |
| @@ -1,52 +0,0 @@ | ||
| 1 | −use std::borrow::Cow; | |
| 2 | − | |
| 3 | −use rustyline::config::Configurer; | |
| 4 | −use rustyline::highlight::Highlighter; | |
| 5 | −use rustyline::{ColorMode, Editor, Result}; | |
| 6 | −use rustyline_derive::{Completer, Helper, Hinter, Validator}; | |
| 7 | − | |
| 8 | −#[derive(Completer, Helper, Hinter, Validator)] | |
| 9 | −struct Mask { | |
| 10 | − apply: bool, | |
| 11 | −} | |
| 12 | − | |
| 13 | −impl Highlighter for Mask { | |
| 14 | − fn highlight<'l>(&self, line: &'l str, _pos: usize) -> Cow<'l, str> { | |
| 15 | − use unicode_width::UnicodeWidthStr; | |
| 16 | − if self.apply { | |
| 17 | − Cow::Owned("*".repeat(line.width())) | |
| 18 | − } else { | |
| 19 | − Cow::Borrowed(line) | |
| 20 | − } | |
| 21 | − } | |
| 22 | − | |
| 23 | − fn highlight_char(&self, _line: &str, _pos: usize) -> bool { | |
| 24 | − self.apply | |
| 25 | − } | |
| 26 | −} | |
| 27 | − | |
| 28 | −/// Ask for information typed by the user after showing the prompt`, like `"Username: `. | |
| 29 | −pub fn openly(prompt: &str) -> Result<String> { | |
| 30 | − editor(false)?.readline(prompt) | |
| 31 | −} | |
| 32 | − | |
| 33 | −/// Ask for information _securely_ after showing the `prompt` (like `"password: "`) by not showing what's typed. | |
| 34 | −/// | |
| 35 | −/// # Security | |
| 36 | −/// | |
| 37 | −/// The current implementation does only mask the typed characters, they could still be read by an attacker. | |
| 38 | −/// To do this correctly, echoing has to be disabled entirely. See [this issue](https://github.com/kkawakam/rustyline/issues/58) | |
| 39 | −/// for progress on this. | |
| 40 | −pub fn securely(prompt: &str) -> Result<String> { | |
| 41 | − let mut ed = editor(true)?; | |
| 42 | − ed.set_color_mode(ColorMode::Forced); // force masking, otherwise disabling color won't trigger the highlighter. | |
| 43 | − ed.set_auto_add_history(false); | |
| 44 | − ed.readline(prompt) | |
| 45 | −} | |
| 46 | − | |
| 47 | −fn editor(masked: bool) -> Result<Editor<Mask>> { | |
| 48 | − let h = Mask { apply: masked }; | |
| 49 | − let mut ed = Editor::new()?; | |
| 50 | − ed.set_helper(Some(h)); | |
| 51 | − Ok(ed) | |
| 52 | −} | |