2021-01-22 19:14:51 +00:00
use crate ::shadow ;
2021-07-04 19:32:58 +00:00
use crate ::utils ::{ self , exec_cmd } ;
2022-11-25 16:44:25 +00:00
use nu_ansi_term ::Style ;
2020-03-05 15:53:58 +00:00
2019-12-14 23:40:12 +00:00
use std ::fs ;
use std ::path ::PathBuf ;
2021-02-11 20:34:47 +00:00
use std ::time ::Duration ;
2019-12-14 23:40:12 +00:00
pub fn create ( ) {
2022-03-20 01:01:57 +00:00
println! ( " {} \n " , shadow ::VERSION . trim ( ) ) ;
2019-12-14 23:40:12 +00:00
let os_info = os_info ::get ( ) ;
let environment = Environment {
os_type : os_info . os_type ( ) ,
2021-07-29 18:27:46 +00:00
os_version : os_info . version ( ) . clone ( ) ,
2019-12-14 23:40:12 +00:00
shell_info : get_shell_info ( ) ,
2019-12-17 15:17:04 +00:00
terminal_info : get_terminal_info ( ) ,
2019-12-14 23:40:12 +00:00
starship_config : get_starship_config ( ) ,
} ;
2022-11-25 16:44:25 +00:00
let issue_body = get_github_issue_body ( & environment ) ;
println! (
" {} \n {issue_body} \n \n " ,
Style ::new ( ) . bold ( ) . paint ( " Generated bug report: " )
) ;
println! ( " Forward the pre-filled report above to GitHub in your browser? " ) ;
println! ( " {} To avoid any sensitive data from being exposed, please review the included information before proceeding. Data forwarded to GitHub is subject to GitHub's privacy policy. " , Style ::new ( ) . bold ( ) . paint ( " Warning: " ) ) ;
println! (
" Enter `{}` to accept, or anything else to decline, and `{}` to confirm your choice: \n " ,
Style ::new ( ) . bold ( ) . paint ( " y " ) ,
Style ::new ( ) . bold ( ) . paint ( " Enter key " )
) ;
let mut input = String ::new ( ) ;
let _ = std ::io ::stdin ( ) . read_line ( & mut input ) ;
if input . trim ( ) . to_lowercase ( ) = = " y " {
let link = make_github_issue_link ( & issue_body ) ;
if let Err ( e ) = open ::that ( & link ) {
2022-12-17 17:01:27 +00:00
println! ( " Failed to open issue report in your browser: {e} " ) ;
2022-11-25 16:44:25 +00:00
println! ( " Please copy the above report and open an issue manually, or try opening the following link: \n {link} " ) ;
}
2019-12-14 23:40:12 +00:00
} else {
2022-11-25 16:44:25 +00:00
println! ( " Will not open an issue in your browser! Please copy the above report and open an issue manually. " ) ;
2019-12-14 23:40:12 +00:00
}
2022-11-25 16:44:25 +00:00
println! ( " Thanks for using the Starship bug report tool! " ) ;
2020-03-05 15:53:58 +00:00
}
2019-12-14 23:40:12 +00:00
const UNKNOWN_SHELL : & str = " <unknown shell> " ;
2019-12-17 15:17:04 +00:00
const UNKNOWN_TERMINAL : & str = " <unknown terminal> " ;
2019-12-14 23:40:12 +00:00
const UNKNOWN_VERSION : & str = " <unknown version> " ;
const UNKNOWN_CONFIG : & str = " <unknown config> " ;
2020-01-16 04:47:56 +00:00
const GITHUB_CHAR_LIMIT : usize = 8100 ; // Magic number accepted by Github
2019-12-14 23:40:12 +00:00
struct Environment {
os_type : os_info ::Type ,
os_version : os_info ::Version ,
shell_info : ShellInfo ,
2019-12-17 15:17:04 +00:00
terminal_info : TerminalInfo ,
2019-12-14 23:40:12 +00:00
starship_config : String ,
}
2021-01-22 19:14:51 +00:00
fn get_pkg_branch_tag ( ) -> & 'static str {
if ! shadow ::TAG . is_empty ( ) {
return shadow ::TAG ;
}
shadow ::BRANCH
}
2022-11-25 16:44:25 +00:00
fn get_github_issue_body ( environment : & Environment ) -> String {
2022-01-28 11:17:49 +00:00
let shell_syntax = match environment . shell_info . name . as_ref ( ) {
" powershell " | " pwsh " = > " pwsh " ,
" fish " = > " fish " ,
" cmd " = > " lua " ,
// GitHub does not seem to support elvish syntax highlighting.
" elvish " = > " bash " ,
_ = > " bash " ,
} ;
2022-11-25 16:44:25 +00:00
format! ( " #### Current Behavior
2019-12-14 23:40:12 +00:00
< ! - - A clear and concise description of the behavior . - ->
#### Expected Behavior
< ! - - A clear and concise description of what you expected to happen . - ->
#### Additional context / Screenshots
< ! - - Add any other context about the problem here . If applicable , add screenshots to help explain . - ->
2019-12-16 00:27:23 +00:00
#### Possible Solution
< ! - - - Only if you have suggestions on a fix for the bug - ->
2019-12-14 23:40:12 +00:00
#### Environment
- Starship version : { starship_version }
- { shell_name } version : { shell_version }
- Operating system : { os_name } { os_version }
2019-12-17 15:17:04 +00:00
- Terminal emulator : { terminal_name } { terminal_version }
2021-01-22 19:14:51 +00:00
- Git Commit Hash : { git_commit_hash }
- Branch / Tag : { pkg_branch_tag }
- Rust Version : { rust_version }
- Rust channel : { rust_channel } { build_rust_channel }
- Build Time : { build_time }
2019-12-14 23:40:12 +00:00
#### Relevant Shell Configuration
2022-01-28 11:17:49 +00:00
` ` ` { shell_syntax }
2019-12-14 23:40:12 +00:00
{ shell_config }
` ` `
#### Starship Configuration
` ` ` toml
{ starship_config }
2019-12-16 00:27:23 +00:00
` ` ` " ,
2021-01-22 19:14:51 +00:00
starship_version = shadow ::PKG_VERSION ,
2019-12-16 00:27:23 +00:00
shell_name = environment . shell_info . name ,
shell_version = environment . shell_info . version ,
2019-12-17 15:17:04 +00:00
terminal_name = environment . terminal_info . name ,
terminal_version = environment . terminal_info . version ,
2019-12-16 00:27:23 +00:00
os_name = environment . os_type ,
os_version = environment . os_version ,
shell_config = environment . shell_info . config ,
starship_config = environment . starship_config ,
2021-01-22 19:14:51 +00:00
git_commit_hash = shadow ::SHORT_COMMIT ,
pkg_branch_tag = get_pkg_branch_tag ( ) ,
rust_version = shadow ::RUST_VERSION ,
rust_channel = shadow ::RUST_CHANNEL ,
build_rust_channel = shadow ::BUILD_RUST_CHANNEL ,
build_time = shadow ::BUILD_TIME ,
2022-01-28 11:17:49 +00:00
shell_syntax = shell_syntax ,
2022-11-25 16:44:25 +00:00
)
}
fn make_github_issue_link ( body : & str ) -> String {
let escaped = urlencoding ::encode ( body ) . replace ( " %20 " , " + " ) ;
2019-12-14 23:40:12 +00:00
format! (
2019-12-16 00:27:23 +00:00
" https://github.com/starship/starship/issues/new?template={}&body={} " ,
2020-01-16 04:47:56 +00:00
urlencoding ::encode ( " Bug_report.md " ) ,
2022-11-25 16:44:25 +00:00
escaped
2019-12-14 23:40:12 +00:00
)
2020-01-16 04:47:56 +00:00
. chars ( )
. take ( GITHUB_CHAR_LIMIT )
. collect ( )
2019-12-14 23:40:12 +00:00
}
#[ derive(Debug) ]
struct ShellInfo {
name : String ,
version : String ,
config : String ,
}
fn get_shell_info ( ) -> ShellInfo {
let shell = std ::env ::var ( " STARSHIP_SHELL " ) ;
if shell . is_err ( ) {
return ShellInfo {
name : UNKNOWN_SHELL . to_string ( ) ,
version : UNKNOWN_VERSION . to_string ( ) ,
config : UNKNOWN_CONFIG . to_string ( ) ,
} ;
}
let shell = shell . unwrap ( ) ;
2022-02-03 20:51:39 +00:00
let version = get_shell_version ( & shell ) ;
2019-12-14 23:40:12 +00:00
let config = get_config_path ( & shell )
. and_then ( | config_path | fs ::read_to_string ( config_path ) . ok ( ) )
2021-07-29 18:27:46 +00:00
. map_or_else (
| | UNKNOWN_CONFIG . to_string ( ) ,
| config | config . trim ( ) . to_string ( ) ,
) ;
2019-12-14 23:40:12 +00:00
ShellInfo {
name : shell ,
version ,
config ,
}
}
2019-12-17 15:17:04 +00:00
#[ derive(Debug) ]
struct TerminalInfo {
name : String ,
version : String ,
}
fn get_terminal_info ( ) -> TerminalInfo {
let terminal = std ::env ::var ( " TERM_PROGRAM " )
. or_else ( | _ | std ::env ::var ( " LC_TERMINAL " ) )
. unwrap_or_else ( | _ | UNKNOWN_TERMINAL . to_string ( ) ) ;
let version = std ::env ::var ( " TERM_PROGRAM_VERSION " )
. or_else ( | _ | std ::env ::var ( " LC_TERMINAL_VERSION " ) )
. unwrap_or_else ( | _ | UNKNOWN_VERSION . to_string ( ) ) ;
TerminalInfo {
name : terminal ,
version ,
}
}
2019-12-14 23:40:12 +00:00
fn get_config_path ( shell : & str ) -> Option < PathBuf > {
2021-07-04 19:32:58 +00:00
if shell = = " nu " {
2022-03-24 19:06:24 +00:00
return dirs_next ::config_dir ( )
. map ( | config_dir | config_dir . join ( " nushell " ) . join ( " config.nu " ) ) ;
2021-07-04 19:32:58 +00:00
}
utils ::home_dir ( ) . and_then ( | home_dir | {
2019-12-14 23:40:12 +00:00
match shell {
" bash " = > Some ( " .bashrc " ) ,
" fish " = > Some ( " .config/fish/config.fish " ) ,
2020-10-02 16:45:23 +00:00
" ion " = > Some ( " .config/ion/initrc " ) ,
2022-01-28 11:17:49 +00:00
" powershell " | " pwsh " = > {
2019-12-14 23:40:12 +00:00
if cfg! ( windows ) {
Some ( " Documents/PowerShell/Microsoft.PowerShell_profile.ps1 " )
} else {
Some ( " .config/powershell/Microsoft.PowerShell_profile.ps1 " )
}
}
" zsh " = > Some ( " .zshrc " ) ,
2021-02-02 11:59:55 +00:00
" elvish " = > Some ( " .elvish/rc.elv " ) ,
2021-02-27 18:55:27 +00:00
" tcsh " = > Some ( " .tcshrc " ) ,
2021-07-16 19:25:01 +00:00
" xonsh " = > Some ( " .xonshrc " ) ,
2022-01-10 05:47:53 +00:00
" cmd " = > Some ( " AppData/Local/clink/starship.lua " ) ,
2019-12-14 23:40:12 +00:00
_ = > None ,
}
. map ( | path | home_dir . join ( path ) )
} )
}
fn get_starship_config ( ) -> String {
2020-01-16 04:47:56 +00:00
std ::env ::var ( " STARSHIP_CONFIG " )
. map ( PathBuf ::from )
. ok ( )
. or_else ( | | {
2021-07-04 19:32:58 +00:00
utils ::home_dir ( ) . map ( | mut home_dir | {
2020-01-16 04:47:56 +00:00
home_dir . push ( " .config/starship.toml " ) ;
home_dir
} )
} )
. and_then ( | config_path | fs ::read_to_string ( config_path ) . ok ( ) )
2019-12-14 23:40:12 +00:00
. unwrap_or_else ( | | UNKNOWN_CONFIG . to_string ( ) )
}
2022-02-03 20:51:39 +00:00
fn get_shell_version ( shell : & str ) -> String {
let time_limit = Duration ::from_millis ( 500 ) ;
match shell {
" powershell " = > exec_cmd (
2022-11-05 11:40:46 +00:00
shell ,
2022-02-03 20:51:39 +00:00
& [ " (Get-Host | Select Version | Format-Table -HideTableHeaders | Out-String).trim() " ] ,
time_limit ,
) ,
2022-11-05 11:40:46 +00:00
_ = > exec_cmd ( shell , & [ " --version " ] , time_limit ) ,
2022-02-03 20:51:39 +00:00
}
. map_or_else (
| | UNKNOWN_VERSION . to_string ( ) ,
| output | output . stdout . trim ( ) . to_string ( ) ,
)
}
2019-12-14 23:40:12 +00:00
#[ cfg(test) ]
mod tests {
use super ::* ;
use std ::env ;
#[ test ]
2020-01-16 04:47:56 +00:00
fn test_make_github_link ( ) {
2019-12-14 23:40:12 +00:00
let environment = Environment {
os_type : os_info ::Type ::Linux ,
2020-09-29 21:06:45 +00:00
os_version : os_info ::Version ::Semantic ( 1 , 2 , 3 ) ,
2019-12-14 23:40:12 +00:00
shell_info : ShellInfo {
name : " test_shell " . to_string ( ) ,
version : " 2.3.4 " . to_string ( ) ,
config : " No config " . to_string ( ) ,
} ,
2019-12-17 15:17:04 +00:00
terminal_info : TerminalInfo {
name : " test_terminal " . to_string ( ) ,
version : " 5.6.7 " . to_string ( ) ,
} ,
2019-12-14 23:40:12 +00:00
starship_config : " No Starship config " . to_string ( ) ,
} ;
2022-11-25 16:44:25 +00:00
let body = get_github_issue_body ( & environment ) ;
let link = make_github_issue_link ( & body ) ;
2019-12-14 23:40:12 +00:00
2021-01-22 19:14:51 +00:00
assert! ( link . contains ( clap ::crate_version! ( ) ) ) ;
2019-12-14 23:40:12 +00:00
assert! ( link . contains ( " Linux " ) ) ;
assert! ( link . contains ( " 1.2.3 " ) ) ;
assert! ( link . contains ( " test_shell " ) ) ;
assert! ( link . contains ( " 2.3.4 " ) ) ;
2020-01-16 04:47:56 +00:00
assert! ( link . contains ( " No+config " ) ) ;
assert! ( link . contains ( " No+Starship+config " ) ) ;
2019-12-14 23:40:12 +00:00
}
#[ test ]
#[ cfg(not(windows)) ]
fn test_get_config_path ( ) {
let config_path = get_config_path ( " bash " ) ;
2021-01-19 22:23:27 +00:00
assert_eq! (
2021-07-04 19:32:58 +00:00
utils ::home_dir ( ) . unwrap ( ) . join ( " .bashrc " ) ,
2021-01-19 22:23:27 +00:00
config_path . unwrap ( )
) ;
2019-12-14 23:40:12 +00:00
}
}