1 use failure::Fallible;
2 use log::*;
3 use rga::adapters::spawning::map_exe_error;
4 use rga::adapters::*;
5 use rga::args::*;
6 use rga::matching::*;
7 use ripgrep_all as rga;
8 use structopt::StructOpt;
9 
10 use std::process::Command;
11 
main() -> Result<(), exitfailure::ExitFailure>12 fn main() -> Result<(), exitfailure::ExitFailure> {
13     env_logger::init();
14 
15     let (args, passthrough_args) = split_args()?;
16 
17     if args.list_adapters {
18         let (enabled_adapters, disabled_adapters) = get_all_adapters();
19 
20         println!("Adapters:\n");
21         let print = |adapter: std::rc::Rc<dyn FileAdapter>| {
22             let meta = adapter.metadata();
23             let matchers = meta
24                 .fast_matchers
25                 .iter()
26                 .map(|m| match m {
27                     FastMatcher::FileExtension(ext) => format!(".{}", ext),
28                 })
29                 .collect::<Vec<_>>()
30                 .join(", ");
31             let slow_matchers = meta
32                 .slow_matchers
33                 .as_ref()
34                 .unwrap_or(&vec![])
35                 .iter()
36                 .filter_map(|m| match m {
37                     SlowMatcher::MimeType(x) => Some(format!("{}", x)),
38                     SlowMatcher::Fast(_) => None,
39                 })
40                 .collect::<Vec<_>>()
41                 .join(", ");
42             let mime_text = if slow_matchers.is_empty() {
43                 "".to_owned()
44             } else {
45                 format!("Mime Types: {}", slow_matchers)
46             };
47             print!(
48                 " - {name}\n     {desc}\n     Extensions: {matchers}\n     {mime}\n",
49                 name = meta.name,
50                 desc = meta.description,
51                 matchers = matchers,
52                 mime = mime_text
53             );
54             println!("");
55         };
56         for adapter in enabled_adapters {
57             print(adapter)
58         }
59         println!("The following adapters are disabled by default, and can be enabled using '--rga-adapters=+pdfpages,tesseract':\n");
60         for adapter in disabled_adapters {
61             print(adapter)
62         }
63         return Ok(());
64     }
65 
66     if passthrough_args.len() == 0 {
67         // rg would show help. Show own help instead.
68         RgaArgs::clap().print_help()?;
69         println!("");
70         return Ok(());
71     }
72 
73     let adapters = get_adapters_filtered(&args.adapters)?;
74 
75     let pre_glob = if !args.accurate {
76         let extensions = adapters
77             .iter()
78             .flat_map(|a| &a.metadata().fast_matchers)
79             .flat_map(|m| match m {
80                 FastMatcher::FileExtension(ext) => vec![ext.clone(), ext.to_ascii_uppercase()],
81             })
82             .collect::<Vec<_>>()
83             .join(",");
84         format!("*.{{{}}}", extensions)
85     } else {
86         "*".to_owned()
87     };
88 
89     add_exe_to_path()?;
90 
91     let rg_args = vec![
92         "--no-line-number",
93         // smart case by default because within weird files
94         // we probably can't really trust casing anyways
95         "--smart-case",
96     ];
97 
98     let exe = std::env::current_exe().expect("Could not get executable location");
99     let preproc_exe = exe.with_file_name("rga-preproc");
100 
101     let mut child = Command::new("rg")
102         .args(rg_args)
103         .arg("--pre")
104         .arg(preproc_exe)
105         .arg("--pre-glob")
106         .arg(pre_glob)
107         .args(passthrough_args)
108         .spawn()
109         .map_err(|e| map_exe_error(e, "rg", "Please make sure you have ripgrep installed."))?;
110 
111     child.wait()?;
112     Ok(())
113 }
114 
115 /// add the directory that contains `rga` to PATH, so rga-preproc can find pandoc etc (if we are on Windows where we include dependent binaries)
add_exe_to_path() -> Fallible<()>116 fn add_exe_to_path() -> Fallible<()> {
117     use std::env;
118     let mut exe = env::current_exe().expect("Could not get executable location");
119     // let preproc_exe = exe.with_file_name("rga-preproc");
120     exe.pop(); // dirname
121 
122     let path = env::var_os("PATH").unwrap_or("".into());
123     let paths = env::split_paths(&path).collect::<Vec<_>>();
124     // prepend: prefer bundled versions to system-installed versions of binaries
125     // solves https://github.com/phiresky/ripgrep-all/issues/32
126     // may be somewhat of a security issue if rga binary is in installed in unprivileged locations
127     let paths = [&[exe.to_owned(), exe.join("lib")], &paths[..]].concat();
128     let new_path = env::join_paths(paths)?;
129     env::set_var("PATH", &new_path);
130     Ok(())
131 }
132