Skip to content

Commit 8a13acd

Browse files
committed
chore(git-voyage): docs
1 parent 7f144c3 commit 8a13acd

3 files changed

Lines changed: 87 additions & 23 deletions

File tree

src/dev/dir-structure/src/dir_children.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,8 @@ impl<P: PathType + ?Sized> Filter<P> for NoFilter {
176176
/// ```
177177
#[macro_export]
178178
macro_rules! ext_filter {
179-
($vis:vis $name:ident, $Ext:literal) => {
179+
($(#[$attrs:meta])* $vis:vis $name:ident, $Ext:literal) => {
180+
$(#[$attrs])*
180181
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
181182
$vis struct $name;
182183

@@ -206,7 +207,8 @@ macro_rules! ext_filter {
206207
/// ```
207208
#[macro_export]
208209
macro_rules! stem_filter {
209-
($vis:vis $name:ident, $base_name:literal) => {
210+
($(#[$attrs:meta])* $vis:vis $name:ident, $base_name:literal) => {
211+
$(#[$attrs])*
210212
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
211213
$vis struct $name;
212214

@@ -238,7 +240,8 @@ macro_rules! stem_filter {
238240
/// ```
239241
#[macro_export]
240242
macro_rules! file_prefix_filter {
241-
($vis:vis $name:ident, $file_prefix:literal) => {
243+
($(#[$attrs:meta])* $vis:vis $name:ident, $file_prefix:literal) => {
244+
$(#[$attrs])*
242245
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
243246
$vis struct $name;
244247

src/dev/git-voyage/src/lib.rs

Lines changed: 80 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,9 @@
1+
//! A library for managing programming guides.
2+
//!
3+
//! See the docs for more information: https://nrx.dnbln.dev/docs/dx/git-voyage/
4+
5+
#![deny(missing_docs)]
6+
17
pub extern crate git2;
28

39
use std::collections::BTreeMap;
@@ -32,22 +38,27 @@ use git2::build::CheckoutBuilder;
3238
use serde::Deserialize;
3339
use serde::Serialize;
3440

41+
/// The error type for this library.
3542
#[derive(Debug, thiserror::Error)]
3643
pub enum Error {
37-
#[error("Failed to read steps: {0}")]
38-
ReadStepsError(#[from] serde_json::Error),
44+
/// Git error.
3945
#[error("git error: {0}")]
4046
GitError(#[from] git2::Error),
47+
/// Dir-structure error.
4148
#[error("dir-structure error: {0}")]
4249
DirStructureError(#[from] DirStructureError<PathBuf>),
50+
/// IO error.
4351
#[error("IO error: {0}")]
4452
IO(#[from] io::Error),
53+
/// Failed to parse step reference.
4554
#[error("Failed to parse step reference: {0}")]
4655
ParseStepReferenceError(String),
4756
}
4857

58+
/// A specialized `Result` type for this library.
4959
pub type Result<T> = result::Result<T, Error>;
5060

61+
/// The main structure representing a guide.
5162
#[derive(DirStructure, HasField)]
5263
pub struct Guide<Vfs: VfsCore<Path = Path>> {
5364
#[dir_structure(path = "steps.json")]
@@ -63,6 +74,7 @@ pub struct Guide<Vfs: VfsCore<Path = Path>> {
6374
}
6475

6576
impl Guide<FsVfs> {
77+
/// Create a new guide with default values.
6678
pub fn new_default(dir: PathBuf, template_extension: &str) -> Self {
6779
Self {
6880
steps: Versioned::new_dirty(
@@ -106,9 +118,10 @@ End of the guide.
106118
}
107119
}
108120

121+
/// Add a new step to the guide.
109122
pub fn add_step(
110123
&mut self,
111-
step: &StepRef,
124+
step: StepRef,
112125
after_step: Option<&StepRef>,
113126
code_extension: Option<Extension>,
114127
before_after_extension: Option<Extension>,
@@ -215,25 +228,30 @@ End of the guide.
215228
code_footer: None,
216229
self_path: resolve_path!([Guide<FsVfs> @ self.self_path.clone()].step_dirs.${&step.0}),
217230
};
218-
self.step_dirs.push(step.0.clone(), step_dir);
231+
self.step_dirs.push(step.0, step_dir);
219232
}
220233

234+
/// Get a step directory by its reference.
221235
pub fn get_step_dir(&self, step: &StepRef) -> Option<&StepDir<FsVfs>> {
222236
self.step_dirs.get_value_by_name(&step.0)
223237
}
224238

239+
/// Get an iterator over the steps and their directories.
225240
pub fn steps_iter(&self) -> StepsIter<'_> {
226241
StepsIter(self.steps.steps.iter(), &self.step_dirs)
227242
}
228243

244+
/// Get the template content.
229245
pub fn template(&self) -> &String {
230246
self.template.value()
231247
}
232248

249+
/// Render the template with the given steps content.
233250
pub fn render_template(&self, steps: String) -> String {
234251
self.template().replace("<__GitVoyageSteps />", &steps)
235252
}
236253

254+
/// Render the entire guide as a string.
237255
pub fn render_guide(&self) -> String {
238256
let mut steps = String::new();
239257
for (_step, step_dir) in self.steps_iter() {
@@ -243,6 +261,7 @@ End of the guide.
243261
}
244262
}
245263

264+
/// A file extension, including the leading dot if any.
246265
#[derive(Debug)]
247266
pub struct Extension(String);
248267

@@ -253,18 +272,24 @@ impl fmt::Display for Extension {
253272
}
254273

255274
impl Extension {
275+
/// Create a new extension from a string.
276+
///
277+
/// The string should include the leading dot if any, or be empty if not.
256278
pub const fn new(ext: String) -> Self {
257279
Self(ext)
258280
}
259281

282+
/// Default code extension is empty (no extension).
260283
pub fn default_code_extension() -> Self {
261284
Self::new(String::new())
262285
}
263286

287+
/// Default before/after extension is `.mdx`.
264288
pub fn default_before_after_extension() -> Self {
265289
Self::new(String::from(".mdx"))
266290
}
267291

292+
/// Get the value of the extension.
268293
pub fn value(&self) -> &str {
269294
&self.0
270295
}
@@ -283,6 +308,7 @@ impl Extension {
283308
}
284309
}
285310

311+
/// Iterator over steps and their directories.
286312
pub struct StepsIter<'a>(slice::Iter<'a, StepRef>, &'a DirChildren<StepDir<FsVfs>>);
287313

288314
impl<'a> Iterator for StepsIter<'a> {
@@ -313,25 +339,33 @@ impl<'a> DoubleEndedIterator for StepsIter<'a> {
313339
}
314340
}
315341

342+
/// A directory representing a single step in the guide.
316343
#[derive(DirStructure, HasField)]
317344
pub struct StepDir<Vfs: VfsCore<Path = Path>> {
345+
/// The "before" file, optional.
318346
#[dir_structure(path = self)]
319-
before: DirChildSingleOpt<Versioned<String, Vfs::Path>, BeforeFilter, Vfs::Path>,
347+
pub before: DirChildSingleOpt<Versioned<String, Vfs::Path>, BeforeFilter, Vfs::Path>,
348+
/// The "after" file, optional.
320349
#[dir_structure(path = self)]
321-
after: DirChildSingleOpt<Versioned<String, Vfs::Path>, AfterFilter, Vfs::Path>,
350+
pub after: DirChildSingleOpt<Versioned<String, Vfs::Path>, AfterFilter, Vfs::Path>,
351+
/// The "code" file, required.
322352
#[dir_structure(path = self)]
323353
pub code: DirChildSingle<Versioned<String, Vfs::Path>, CodeFilter, Vfs::Path>,
324354

325-
code_header: Option<Versioned<String, Vfs::Path>>,
326-
code_footer: Option<Versioned<String, Vfs::Path>>,
355+
/// Optional code header, if not present, the guide's code header is used if any.
356+
pub code_header: Option<Versioned<String, Vfs::Path>>,
357+
/// Optional code footer, if not present, the guide's code footer is used if any.
358+
pub code_footer: Option<Versioned<String, Vfs::Path>>,
327359
self_path: PathBuf,
328360
}
329361

330362
impl StepDir<FsVfs> {
363+
/// Get the path to the code file.
331364
pub fn code_path(&self) -> PathBuf {
332365
self.self_path.join(self.code.file_name())
333366
}
334367

368+
/// Render the step as a string. This uses the guide's code header and footer if any, if the step's code_header/footer are not present.
335369
pub fn render_step(&self, guide: &Guide<FsVfs>) -> String {
336370
let mut output = String::new();
337371
if let DirChildSingleOpt::Some(before) = &self.before {
@@ -351,6 +385,7 @@ impl StepDir<FsVfs> {
351385
output
352386
}
353387

388+
/// Guess the extension for the before/after files, if any.
354389
pub fn before_after_extension(&self) -> Option<Extension> {
355390
self.before
356391
.as_ref()
@@ -363,30 +398,43 @@ impl StepDir<FsVfs> {
363398
.map(|dir| Extension::guess_from(&dir))
364399
}
365400

401+
/// Guess the extension for the code file.
366402
pub fn code_extension(&self) -> Extension {
367403
Extension::guess_from(&self.code)
368404
}
369405
}
370406

371-
file_prefix_filter!(pub TemplateFilter, "template");
372-
file_prefix_filter!(pub BeforeFilter, "before");
373-
file_prefix_filter!(pub AfterFilter, "after");
374-
file_prefix_filter!(pub CodeFilter, "code");
375-
407+
file_prefix_filter!(
408+
/// Filter for the template file.
409+
pub TemplateFilter, "template");
410+
file_prefix_filter!(
411+
/// Filter for the before file.
412+
pub BeforeFilter, "before");
413+
file_prefix_filter!(
414+
/// Filter for the after file.
415+
pub AfterFilter, "after");
416+
file_prefix_filter!(
417+
/// Filter for the code file.
418+
pub CodeFilter, "code");
419+
420+
/// The steps structure, containing a list of step references.
376421
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)]
377422
pub struct Steps {
378423
steps: Vec<StepRef>,
379424
}
380425

426+
/// A reference to a step.
381427
#[derive(Deserialize, Serialize, Debug, Clone, PartialEq, Eq)]
382428
#[repr(transparent)]
383429
pub struct StepRef(String);
384430

385431
impl StepRef {
432+
/// Create a new step reference from a string.
386433
pub fn new(path: String) -> Self {
387434
Self(path)
388435
}
389436

437+
/// Get the path (name) of the step.
390438
pub fn path(&self) -> &str {
391439
&self.0
392440
}
@@ -411,8 +459,8 @@ impl<T> DbgGitErr for result::Result<T, git2::Error> {
411459
}
412460
}
413461

414-
fn perform_patchup(
415-
guide: &Guide<FsVfs>,
462+
fn perform_patchup<V: VfsCore<Path = Path>>(
463+
guide: &Guide<V>,
416464
step: &StepRef,
417465
new_code: &str,
418466
repo_root: &Path,
@@ -570,8 +618,21 @@ fn perform_patchup(
570618
Ok(empty_steps)
571619
}
572620

573-
pub fn patchup(
574-
guide: &mut Guide<FsVfs>,
621+
/// Perform a patchup of a step in the guide, updating the guide's step identified by `step` with the new code provided in `new_code`.
622+
///
623+
/// This function will then rebase all subsequent steps to ensure they are applied on top of the updated step.
624+
///
625+
/// If any conflicts arise during the rebase, the provided `resolve_conflict` function will be called with the path to the code file,
626+
/// allowing the user to manually resolve the conflict. This function should open an editor or perform any necessary actions to resolve the conflict,
627+
/// and return `Ok(())` if successful, or an `Err` if the conflict could not be resolved.
628+
///
629+
/// After resolve_conflict returns, this function will add the resolved code file to the index and continue the rebase process.
630+
///
631+
/// After everything is done, the guide's steps will be updated to reflect the new code state, but this will not be automatically saved to disk.
632+
///
633+
/// `dir` is a temporary directory where a temporary git repository will be created. You should ensure this directory exists and is writable.
634+
pub fn patchup<V: VfsCore<Path = Path>>(
635+
guide: &mut Guide<V>,
575636
dir: &Path,
576637
step: &StepRef,
577638
new_code: &str,
@@ -596,8 +657,8 @@ pub fn patchup(
596657
Ok(())
597658
}
598659

599-
pub fn repatch(
600-
guide: &mut Guide<FsVfs>,
660+
fn repatch<V: VfsCore<Path = Path>>(
661+
guide: &mut Guide<V>,
601662
dir: &Path,
602663
empty_commits: &BTreeMap<String, String>,
603664
) -> Result<()> {

src/dev/git-voyage/src/main.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ fn main() {
146146
let before_after_extension = before_after_extension.map(Extension::new);
147147

148148
guide.add_step(
149-
&step,
149+
step.clone(),
150150
after_step.as_ref(),
151151
code_extension,
152152
before_after_extension,

0 commit comments

Comments
 (0)