Federated blogging application, thanks to ActivityPub https://joinplu.me
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

119 lines
4.0 KiB

  1. use clap::{App, Arg, ArgMatches, SubCommand};
  2. use plume_models::{db_conn::DbPool, search::Searcher, CONFIG};
  3. use std::fs::{read_dir, remove_file};
  4. use std::io::ErrorKind;
  5. use std::path::Path;
  6. pub fn command<'a, 'b>() -> App<'a, 'b> {
  7. SubCommand::with_name("search")
  8. .about("Manage search index")
  9. .subcommand(
  10. SubCommand::with_name("init")
  11. .arg(
  12. Arg::with_name("path")
  13. .short("p")
  14. .long("path")
  15. .takes_value(true)
  16. .required(false)
  17. .help("Path to Plume's working directory"),
  18. )
  19. .arg(
  20. Arg::with_name("force")
  21. .short("f")
  22. .long("force")
  23. .help("Ignore already using directory"),
  24. )
  25. .about("Initialize Plume's internal search engine"),
  26. )
  27. .subcommand(
  28. SubCommand::with_name("refill")
  29. .arg(
  30. Arg::with_name("path")
  31. .short("p")
  32. .long("path")
  33. .takes_value(true)
  34. .required(false)
  35. .help("Path to Plume's working directory"),
  36. )
  37. .about("Regenerate Plume's search index"),
  38. )
  39. .subcommand(
  40. SubCommand::with_name("unlock")
  41. .arg(
  42. Arg::with_name("path")
  43. .short("p")
  44. .long("path")
  45. .takes_value(true)
  46. .required(false)
  47. .help("Path to Plume's working directory"),
  48. )
  49. .about("Release lock on search directory"),
  50. )
  51. }
  52. pub fn run<'a>(args: &ArgMatches<'a>, conn: DbPool) {
  53. let conn = conn;
  54. match args.subcommand() {
  55. ("init", Some(x)) => init(x, conn),
  56. ("refill", Some(x)) => refill(x, conn, None),
  57. ("unlock", Some(x)) => unlock(x),
  58. ("", None) => command().print_help().unwrap(),
  59. _ => println!("Unknown subcommand"),
  60. }
  61. }
  62. fn init<'a>(args: &ArgMatches<'a>, db_pool: DbPool) {
  63. let path = args
  64. .value_of("path")
  65. .map(|p| Path::new(p).join("search_index"))
  66. .unwrap_or_else(|| Path::new(&CONFIG.search_index).to_path_buf());
  67. let force = args.is_present("force");
  68. let can_do = match read_dir(path.clone()) {
  69. // try to read the directory specified
  70. Ok(mut contents) => contents.next().is_none(),
  71. Err(e) => {
  72. if e.kind() == ErrorKind::NotFound {
  73. true
  74. } else {
  75. panic!("Error while initialising search index : {}", e);
  76. }
  77. }
  78. };
  79. if can_do || force {
  80. let searcher = Searcher::create(&path, db_pool.clone(), &CONFIG.search_tokenizers).unwrap();
  81. refill(args, db_pool, Some(searcher));
  82. } else {
  83. eprintln!(
  84. "Can't create new index, {} exist and is not empty",
  85. path.to_str().unwrap()
  86. );
  87. }
  88. }
  89. fn refill<'a>(args: &ArgMatches<'a>, db_pool: DbPool, searcher: Option<Searcher>) {
  90. let path = args.value_of("path");
  91. let path = match path {
  92. Some(path) => Path::new(path).join("search_index"),
  93. None => Path::new(&CONFIG.search_index).to_path_buf(),
  94. };
  95. let searcher = searcher
  96. .unwrap_or_else(|| Searcher::open(&path, db_pool, &CONFIG.search_tokenizers).unwrap());
  97. searcher.fill().expect("Couldn't import post");
  98. println!("Commiting result");
  99. searcher.commit();
  100. }
  101. fn unlock<'a>(args: &ArgMatches<'a>) {
  102. let path = match args.value_of("path") {
  103. None => Path::new(&CONFIG.search_index),
  104. Some(x) => Path::new(x),
  105. };
  106. let meta = Path::new(path).join(".tantivy-meta.lock");
  107. remove_file(meta).unwrap();
  108. let writer = Path::new(path).join(".tantivy-writer.lock");
  109. remove_file(writer).unwrap();
  110. }