diff --git a/DESIGN.md b/DESIGN.md index c5063d6..104fe0c 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -37,9 +37,11 @@ invocation it documents **one package installed in the current switch**: - The switch is discovered by shelling out to `opam switch show` / `opam var prefix` (both read-only operations). - `--odoc-dir`, `--odocl-dir` and `--html-dir` all default to - `/doc`. Intermediate `.odoc`/`.odocl` files and HTML + `/odoc`. Intermediate `.odoc`/`.odocl` files and HTML share that tree, with each package's output directly under - `doc//` (flat layout, same as plain `odoc_driver`). + `odoc//` (flat layout, same as plain `odoc_driver`). This is a + switchdocs-owned tree, kept separate from opam's own `/doc`, where + packages install their own documentation. - Previously built dependencies are discovered by scanning `--odoc-dir` for the `.odoc_pkg_marker` / `.odoc_lib_marker` files written on earlier runs — this is what makes incremental, package-at-a-time building work. @@ -97,15 +99,15 @@ handling). var/cache/switchdocs/ pending # set of stale/removed packages, appended by `record` log # sync output, since hooks must stay quiet -doc/ +odoc/ /... # per-package odoc, odocl and HTML (driver defaults) index.html # switch-wide landing page (ours) odoc-search/... # driver support files, search assets ``` -The driver's defaults are taken as-is: one `doc/` tree per switch holding -both intermediates and HTML. Our own state is just the pending file and a -log. +The driver's defaults are taken as-is: one `odoc/` tree per switch holding +both intermediates and HTML, separate from opam's own `/doc`. Our own +state is just the pending file and a log. ### 3. The `sync` step @@ -121,7 +123,7 @@ with the lock the surrounding session holds. `removed : (pkg, ver) set`. A package appearing in both (upgrade = remove old + install new) counts as stale. 2. **Erase**: for removed-and-not-reinstalled packages, delete - `doc//` outright. For stale packages, also delete `doc//` + `odoc//` outright. For stale packages, also delete `odoc//` before rebuilding — the flat layout has no version in the path, so an upgrade overwrites in place, and pre-deleting prevents files from modules that no longer exist surviving from the old version. @@ -132,7 +134,7 @@ with the lock the surrounding session holds. remove the package's lines from the pending file (rewrite-and-rename). On failure, leave them: the next session retries automatically. 5. **Regenerate the top-level index**: a landing page listing all packages - with built docs (directory listing of `doc/`, filtered to package + with built docs (directory listing of `odoc/`, filtered to package dirs). The per-package pages and redirects are the driver's job; only this one page is ours. diff --git a/DESIGN_SHOW.md b/DESIGN_SHOW.md index a9af5bd..205a519 100644 --- a/DESIGN_SHOW.md +++ b/DESIGN_SHOW.md @@ -61,12 +61,13 @@ derived, not configured. `Resolver.create`'s `Accessible_paths` looks up units by capitalised base name, scanning the directories it is given for `*.odoc` files. In a switch the driver -writes these under `$OPAM_SWITCH_PREFIX/doc///.odoc` (verified -on the dev switch: e.g. `doc/astring/astring/astring.odoc`). So: +writes these under `$OPAM_SWITCH_PREFIX/odoc///.odoc` (verified +on the dev switch: e.g. `odoc/astring/astring/astring.odoc`). (This is the +switchdocs-owned tree, separate from opam's own `/doc`.) So: - discover the switch prefix exactly as the existing commands do (`Switchdocs.Switch.detect`, `--prefix`); -- recursively collect every directory under `/doc` that contains a +- recursively collect every directory under `/odoc` that contains a `.odoc` file, and pass them all as `directories` (`Show.scan`). Only *top-level unit* files need to be reachable by name; sub-modules @@ -83,8 +84,8 @@ references** (`{!/pkg/Module.value}`, `{!/pkg/page}`) resolve through *named roots*, which `~roots:None` doesn't provide. So `show` also reconstructs the `-L`/`-P` roots the driver links with (`landing_pages.ml`, `odoc_unit.ml`): -- `-P :/doc/` (page roots) — every top-level dir under `doc/`; -- `-L :/doc//` (lib roots) — their immediate +- `-P :/odoc/` (page roots) — every top-level dir under `odoc/`; +- `-L :/odoc//` (lib roots) — their immediate subdirectories. These are passed via `Resolver.create`'s `~roots`, with `current_lib` / diff --git a/README.md b/README.md index 7fc1c86..51005f8 100644 --- a/README.md +++ b/README.md @@ -6,8 +6,10 @@ Keep an opam switch's HTML documentation continuously up to date. and `post-session-commands` hooks to `odoc_driver_opam` so that after every successful `opam install` / `opam upgrade` / `opam remove`, the docs for exactly the packages that changed are regenerated, in dependency order. -Docs are written to `$OPAM_SWITCH_PREFIX/doc//`, with a landing -page at `$OPAM_SWITCH_PREFIX/doc/index.html`. +Docs are written to `$OPAM_SWITCH_PREFIX/odoc//`, with a landing +page at `$OPAM_SWITCH_PREFIX/odoc/index.html`. (This is switchdocs' own tree, +kept separate from opam's `$OPAM_SWITCH_PREFIX/doc`, where packages install +their own documentation.) See [DESIGN.md](DESIGN.md) for the full design. diff --git a/bin/main.ml b/bin/main.ml index 8dc82cc..aeb529d 100644 --- a/bin/main.ml +++ b/bin/main.ml @@ -291,7 +291,7 @@ let search_cmd = `S Manpage.s_description; `P "Searches the per-package sherlodoc databases under \ - $(b,\\$OPAM_SWITCH_PREFIX/doc) that the driver writes alongside the \ + $(b,\\$OPAM_SWITCH_PREFIX/odoc) that the driver writes alongside the \ HTML, querying them together so a single query covers every \ documented package in the switch. A database that cannot be loaded \ (for instance one written by an incompatible sherlodoc version) is \ @@ -401,8 +401,8 @@ let main_cmd = its installed packages. opam hooks record which packages each opam \ invocation touched; at the end of the session the worker rebuilds \ exactly those packages' docs, in dependency order, using an odoc \ - driver. Output goes to $(b,\\$OPAM_SWITCH_PREFIX/doc), with a landing \ - page at $(b,doc/index.html)."; + driver. Output goes to $(b,\\$OPAM_SWITCH_PREFIX/odoc), with a landing \ + page at $(b,odoc/index.html)."; `P "Run $(b,switchdocs setup) to configure the hooks."; ] in diff --git a/lib/index_page.ml b/lib/index_page.ml index 385824c..0b8ac18 100644 --- a/lib/index_page.ml +++ b/lib/index_page.ml @@ -1,5 +1,5 @@ let has_docs sw name = - Bos.OS.File.exists Fpath.(Switch.doc_dir sw / name / "index.html") + Bos.OS.File.exists Fpath.(Switch.odoc_dir sw / name / "index.html") |> Result.value ~default:false let page entries = @@ -35,6 +35,6 @@ let write sw = let entries = List.filter (fun (name, _) -> has_docs sw name) (Switch.installed sw) in - Result.bind (Bos.OS.Dir.create ~path:true (Switch.doc_dir sw)) + Result.bind (Bos.OS.Dir.create ~path:true (Switch.odoc_dir sw)) @@ fun (_ : bool) -> - Bos.OS.File.write Fpath.(Switch.doc_dir sw / "index.html") (page entries) + Bos.OS.File.write Fpath.(Switch.odoc_dir sw / "index.html") (page entries) diff --git a/lib/index_page.mli b/lib/index_page.mli index e79a423..cfb6c63 100644 --- a/lib/index_page.mli +++ b/lib/index_page.mli @@ -1,4 +1,4 @@ -(** The switch-wide landing page, [/doc/index.html]: a list of every +(** The switch-wide landing page, [/odoc/index.html]: a list of every installed package that has documentation. The per-package pages are the driver's job; this one page is ours. *) diff --git a/lib/search.ml b/lib/search.ml index a61719f..c37299d 100644 --- a/lib/search.ml +++ b/lib/search.ml @@ -68,10 +68,10 @@ let result_of_entry (e : Db.Entry.t) = url = e.url; } -(* The per-package marshal databases under /doc/, as (package, file). *) +(* The per-package marshal databases under /odoc/, as (package, file). *) let marshal_dbs sw = - let doc = Switch.doc_dir sw in - match Bos.OS.Dir.contents doc with + let odoc = Switch.odoc_dir sw in + match Bos.OS.Dir.contents odoc with | Error _ -> [] | Ok entries -> List.filter_map diff --git a/lib/search.mli b/lib/search.mli index bb1d5a7..77fc74c 100644 --- a/lib/search.mli +++ b/lib/search.mli @@ -1,7 +1,7 @@ (** Search across the switch's per-package sherlodoc databases. The driver writes a [sherlodoc_db.marshal] into each - [/doc//]. This module loads them all and queries them as a + [/odoc//]. This module loads them all and queries them as a single corpus — sherlodoc searches a list of databases and unions the results — so one query covers every documented package in the switch. @@ -25,7 +25,7 @@ val search : string -> result list (** [search sw query] queries every [sherlodoc_db.marshal] under the switch's - doc directory. [?packages] restricts the search to the named packages' + odoc directory. [?packages] restricts the search to the named packages' databases (default: all installed). [?limit] caps the number of results (default 25). [?warn] reports databases that could not be loaded. *) diff --git a/lib/show.ml b/lib/show.ml index 69ef7c8..81f528a 100644 --- a/lib/show.ml +++ b/lib/show.ml @@ -5,7 +5,7 @@ the whole switch, followed by fetching and rendering the resolved item's doc comment. Three stages: - 1. Scan the switch's [doc/] tree once for the include directories (dirs + 1. Scan the switch's [odoc/] tree once for the include directories (dirs holding [.odoc] files) and an index of linked units ([.odocl] by name). 2. Resolve the reference string to a canonical identifier with [Odoc_xref2.Ref_tools.resolve_reference], exactly as odoc does. @@ -46,24 +46,24 @@ let subdirs dir = entries type scan = { - doc : Fpath.t; (** the switch's [doc/] root *) + odoc : Fpath.t; (** the switch's [odoc/] root *) directories : Fpath.t list; (** every dir holding a [.odoc] (the [-I] set) *) odocl : (string, Fpath.t) Hashtbl.t; (** capitalised unit name -> [.odocl] *) - page_roots : (string * Fpath.t) list; (** package name -> [doc/] ([-P]) *) + page_roots : (string * Fpath.t) list; (** package name -> [odoc/] ([-P]) *) lib_roots : (string * Fpath.t) list; - (** library name -> [doc//] ([-L]) *) + (** library name -> [odoc//] ([-L]) *) } -(* The driver links each package with [-P :doc/] for every package and - [-L :doc//] for every library (see [landing_pages.ml] and +(* The driver links each package with [-P :odoc/] for every package + and [-L :odoc//] for every library (see [landing_pages.ml] and [odoc_unit.ml] in the driver). To resolve the package-qualified path references those produce ([{!/pkg/...}]), we reconstruct the same named roots - for the whole switch: packages are the top-level dirs under [doc/], libraries + for the whole switch: packages are the top-level dirs under [odoc/], libraries their immediate subdirectories. (Name lookups for ordinary dotted references still go through the flat [-I] set; the roots only add path references.) *) let scan sw = - let doc = Switch.doc_dir sw in - let files = all_files doc in + let odoc = Switch.odoc_dir sw in + let files = all_files odoc in let dirs = Hashtbl.create 256 in let odocl = Hashtbl.create 256 in List.iter @@ -80,13 +80,13 @@ let scan sw = | _ -> ()) files; let directories = Hashtbl.fold (fun _ d acc -> d :: acc) dirs [] in - let page_roots = subdirs doc in + let page_roots = subdirs odoc in let lib_roots = List.concat_map (fun (_pkg, dir) -> subdirs dir) page_roots in - { doc; directories; odocl; page_roots; lib_roots } + { odoc; directories; odocl; page_roots; lib_roots } (* {1 Stage 2: resolve the reference} *) -let resolve_to_id { doc; directories; page_roots; lib_roots; _ } ref_str = +let resolve_to_id { odoc; directories; page_roots; lib_roots; _ } ref_str = let dir = Odoc_odoc.Fs.Directory.of_string in let directories = List.map (fun d -> dir (Fpath.to_string d)) directories in let named = List.map (fun (n, d) -> (n, dir (Fpath.to_string d))) in @@ -100,8 +100,8 @@ let resolve_to_id { doc; directories; page_roots; lib_roots; _ } ref_str = (* No "current" unit: [show] resolves a reference from nowhere, so relative/current-package path references don't apply. current_dir is required but only feeds the include set and the (here unused) - hierarchy, so the doc root is a harmless value. *) - current_dir = dir (Fpath.to_string doc); + hierarchy, so the odoc root is a harmless value. *) + current_dir = dir (Fpath.to_string odoc); } in let resolver = diff --git a/lib/switch.ml b/lib/switch.ml index 971ac01..e94094c 100644 --- a/lib/switch.ml +++ b/lib/switch.ml @@ -33,7 +33,7 @@ let pending_file t = Fpath.(state_dir t / "pending") let log_file t = Fpath.(state_dir t / "log") let lock_file t = Fpath.(state_dir t / "lock") let work_dir t = Fpath.(state_dir t / "work") -let doc_dir t = Fpath.(t.prefix / "doc") +let odoc_dir t = Fpath.(t.prefix / "odoc") let packages_dir t = Fpath.(t.prefix / ".opam-switch" / "packages") (* Directory entries are .; package names cannot contain diff --git a/lib/switch.mli b/lib/switch.mli index 6975bf9..4ec46bf 100644 --- a/lib/switch.mli +++ b/lib/switch.mli @@ -22,8 +22,10 @@ val work_dir : t -> Fpath.t (** Scratch directory the driver is run from (it creates [_index]/[_mld] relative to its cwd). *) -val doc_dir : t -> Fpath.t -(** [/doc] — the driver's default odoc/odocl/html output tree. *) +val odoc_dir : t -> Fpath.t +(** [/odoc] — the driver's default odoc/odocl/html output tree. (Kept + separate from opam's own [/doc], where packages install their + documentation.) *) val packages_dir : t -> Fpath.t (** [/.opam-switch/packages] — opam's record of installed package diff --git a/lib/sync.ml b/lib/sync.ml index 9adf999..e394304 100644 --- a/lib/sync.ml +++ b/lib/sync.ml @@ -62,7 +62,7 @@ let valid_pkg_name n = let erase_doc sw name = if valid_pkg_name name then - ignore (Bos.OS.Dir.delete ~recurse:true Fpath.(Switch.doc_dir sw / name)) + ignore (Bos.OS.Dir.delete ~recurse:true Fpath.(Switch.odoc_dir sw / name)) (* The driver locates the switch by running `opam switch show`; make sure that resolves to ours even when sync is invoked with an explicit diff --git a/test/sync.t b/test/sync.t index 15963d1..866b1a2 100644 --- a/test/sync.t +++ b/test/sync.t @@ -15,8 +15,8 @@ package's doc directory. > pkg="$1" > [ "$pkg" = "bad" ] && { echo "boom" >&2; exit 1; } > echo "$pkg" >> "$OPAM_SWITCH_PREFIX/build-order" - > mkdir -p "$OPAM_SWITCH_PREFIX/doc/$pkg" - > echo ok > "$OPAM_SWITCH_PREFIX/doc/$pkg/index.html" + > mkdir -p "$OPAM_SWITCH_PREFIX/odoc/$pkg" + > echo ok > "$OPAM_SWITCH_PREFIX/odoc/$pkg/index.html" > EOF $ chmod +x driver.sh @@ -40,7 +40,7 @@ packages: $ test -e prefix/var/cache/switchdocs/pending || echo consumed consumed - $ grep -o '
  • .*
  • ' prefix/doc/index.html | sed 's/<[^>]*>//g' + $ grep -o '
  • .*
  • ' prefix/odoc/index.html | sed 's/<[^>]*>//g' a 1 b 1 @@ -62,16 +62,16 @@ landing-page entry. Note that bad, still pending from the previous run, is retried (and fails again) — that is the designed retry-on-next-session behaviour: - $ test -d prefix/doc/b && echo present + $ test -d prefix/odoc/b && echo present present $ rm -r prefix/.opam-switch/packages/b.1 $ switchdocs record remove --prefix prefix b 1 $ switchdocs sync --prefix prefix --driver ./driver.sh switchdocs: 0 built, 1 failed, 1 removed switchdocs: see $TESTCASE_ROOT/prefix/var/cache/switchdocs/log - $ test -d prefix/doc/b || echo gone + $ test -d prefix/odoc/b || echo gone gone - $ grep -o '
  • .*
  • ' prefix/doc/index.html | sed 's/<[^>]*>//g' + $ grep -o '
  • .*
  • ' prefix/odoc/index.html | sed 's/<[^>]*>//g' a 1 A missing driver leaves everything pending and is reported via the summary