docs.rs 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. use anyhow::{anyhow, Context as _, Result};
  2. use cargo_metadata::{Metadata, MetadataCommand};
  3. use indoc::{indoc, writedoc};
  4. use std::{ffi::OsString, fs, io::Write as _, process::Command};
  5. pub fn exec(cmd: &mut Command) -> Result<()> {
  6. let status = cmd
  7. .status()
  8. .with_context(|| format!("failed to run {cmd:?}"))?;
  9. match status.code() {
  10. Some(code) => match code {
  11. 0 => Ok(()),
  12. code => Err(anyhow!("{cmd:?} exited with code {code}")),
  13. },
  14. None => Err(anyhow!("{cmd:?} terminated by signal")),
  15. }
  16. }
  17. pub fn docs() -> Result<()> {
  18. const PACKAGE_TO_DESCRIPTION: &[(&str, &str)] = &[
  19. ("aya", "User-space BPF program loading and manipulation"),
  20. ("aya-bpf", "Kernel-space BPF program implementation toolkit"),
  21. ("aya-log-ebpf", "Kernel-space logging from BPF programs"),
  22. (
  23. "aya-log",
  24. "User-space consumption of logs from BPF programs",
  25. ),
  26. ];
  27. let Metadata {
  28. workspace_root,
  29. target_directory,
  30. ..
  31. } = MetadataCommand::new().exec().context("cargo metadata")?;
  32. exec(
  33. Command::new("cargo")
  34. .current_dir(&workspace_root)
  35. .args(["clean", "--doc"]),
  36. )?;
  37. let tmp = tempfile::tempdir().context("create tempdir")?;
  38. let header = tmp.path().join("header.html");
  39. fs::write(&header, r#"<meta name="robots" content="noindex">"#).context("write header.html")?;
  40. let mut rustdocflags = OsString::new();
  41. rustdocflags.push("--cfg docsrs --html-in-header ");
  42. rustdocflags.push(header);
  43. rustdocflags.push(" -D warnings");
  44. exec(
  45. Command::new("cargo")
  46. .current_dir(&workspace_root)
  47. .env("RUSTDOCFLAGS", rustdocflags)
  48. .args(["+nightly", "doc", "--no-deps", "--all-features"])
  49. .args(
  50. PACKAGE_TO_DESCRIPTION
  51. .iter()
  52. .flat_map(|(package, _)| ["--package", package]),
  53. ),
  54. )?;
  55. let site = workspace_root.join("site");
  56. match fs::remove_dir_all(&site) {
  57. Ok(()) => {}
  58. Err(err) => {
  59. if err.kind() != std::io::ErrorKind::NotFound {
  60. return Err(err).context(format!("remove {site:?}"));
  61. }
  62. }
  63. }
  64. let doc = target_directory.join("doc");
  65. fs::rename(&doc, &site).with_context(|| format!("rename {doc:?} to {site:?}"))?;
  66. exec(Command::new("sh").current_dir(&site).args([
  67. "-c",
  68. "grep -FRl crabby.svg | xargs sed -i s/crabby.svg/crabby_dev.svg/g",
  69. ]))?;
  70. fs::write(
  71. site.join("robots.txt"),
  72. indoc! {r#"
  73. User-Agent:*
  74. Disallow: /
  75. "#},
  76. )
  77. .context("can't write robots.txt")?;
  78. let mut index = fs::File::create(site.join("index.html"))
  79. .with_context(|| format!("create {site:?}/index.html"))?;
  80. writedoc! {&mut index, r#"
  81. <html>
  82. <meta name="robots" content="noindex">
  83. <body>
  84. <ul>
  85. "#}
  86. .context("write to index.html")?;
  87. for (package, description) in PACKAGE_TO_DESCRIPTION {
  88. let package = package.replace('-', "_");
  89. writedoc! {&mut index, r#"
  90. <li><a href="{package}/index.html">Aya {description}</a></li>
  91. "#}
  92. .context("write to string")?;
  93. }
  94. writedoc! {&mut index, r#"
  95. </ul>
  96. </body>
  97. </html>
  98. "#}
  99. .context("write to index.html")?;
  100. Ok(())
  101. }