about summary refs log tree commit diff stats
path: root/sys/nixpkgs/pkgs/lf-make-map/src/generator
diff options
context:
space:
mode:
authorBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-05-05 12:59:36 +0200
committerBenedikt Peetz <benedikt.peetz@b-peetz.de>2024-05-05 12:59:36 +0200
commit023b7cd0ada0cb153769bdcc931ef04512d125c4 (patch)
tree584315a010a9eccdd182e48801496ea4e226bfcb /sys/nixpkgs/pkgs/lf-make-map/src/generator
parentbuild(treewide): Update (diff)
downloadnixos-config-023b7cd0ada0cb153769bdcc931ef04512d125c4.tar.gz
nixos-config-023b7cd0ada0cb153769bdcc931ef04512d125c4.zip
feat(pkgs/lf-make-map): Init
Diffstat (limited to 'sys/nixpkgs/pkgs/lf-make-map/src/generator')
-rw-r--r--sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs45
-rw-r--r--sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs.old165
2 files changed, 210 insertions, 0 deletions
diff --git a/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs b/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs
new file mode 100644
index 00000000..48df027f
--- /dev/null
+++ b/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs
@@ -0,0 +1,45 @@
+use std::path::PathBuf;
+
+use anyhow::{Context, Result};
+use log::{debug, info, trace};
+use walkdir::{DirEntry, WalkDir};
+
+use crate::mapping::{map_tree::MappingTree, Mapping};
+
+pub struct MappingsGenerator {
+    mappings: MappingTree,
+    paths_to_process: Vec<PathBuf>,
+}
+
+fn is_dir(entry: &DirEntry) -> bool {
+    entry.file_type().is_dir()
+}
+
+impl MappingsGenerator {
+    pub async fn new(
+        directories_to_scan: Vec<PathBuf>,
+        max_depth: usize,
+        home_path: PathBuf,
+    ) -> Result<Self> {
+        let mut mappings = MappingTree::new();
+
+        for dir in directories_to_scan {
+            for dir2 in WalkDir::new(&dir)
+                .max_depth(max_depth)
+                .into_iter()
+                .filter_entry(|e| is_dir(e))
+            {
+                let directory =
+                    dir2.with_context(|| format!("Failed to read dir ('{}')", &dir.display()))?;
+
+                trace!("Processed '{}'..", directory.path().display());
+
+                let mapping = Mapping::new(&home_path, directory.path().to_path_buf());
+                mappings
+                    .insert(&mapping.key.clone(), mapping)
+                    .context("Failed to insert a key")?;
+            }
+        }
+        todo!()
+    }
+}
diff --git a/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs.old b/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs.old
new file mode 100644
index 00000000..406b1996
--- /dev/null
+++ b/sys/nixpkgs/pkgs/lf-make-map/src/generator/mod.rs.old
@@ -0,0 +1,165 @@
+use std::{
+    collections::HashMap,
+    path::{Path, PathBuf},
+};
+
+use anyhow::{bail, Context, Result};
+use futures::{Stream, StreamExt, TryStreamExt};
+use log::info;
+use tokio::{
+    fs::{self, DirEntry},
+    io,
+    sync::mpsc::{self, Receiver, Sender},
+    task::JoinHandle,
+};
+use tokio_stream::wrappers::{ReadDirStream, ReceiverStream};
+
+pub struct MappingGenerator {
+    current_mappings: HashMap<String, PathBuf>,
+    paths_to_process: Vec<PathBuf>,
+}
+
+pub struct MappingGeneratorHelper {
+    tx: Sender<(PathBuf, oneshotSender<PathBuf>)>,
+    handle: JoinHandle<()>,
+    done: Vec<PathBuf>,
+}
+
+impl MappingGeneratorHelper {
+    pub fn new() -> Self {
+        let (rx, tx) = mpsc::channel(100);
+
+        let handle = tokio::spawn(async move {
+            while let Some(dir) = rx.recv().await {
+                info!("processing '{}'..", dir.display());
+                get_dir(dir);
+            }
+        });
+
+        Self { tx, handle }
+    }
+
+    pub async fn process(&self, dir: PathBuf) -> Result<()> {
+        let (tx, rx) =
+        self.tx.send(dir).await?;
+        Ok(())
+    }
+}
+
+impl MappingGenerator {
+    pub async fn new(directories_to_scan: Vec<PathBuf>, depth: usize) -> Result<Self> {
+        let cleaned_directories: Vec<PathBuf> = directories_to_scan
+            .into_iter()
+            .map(check_dir)
+            .collect::<Result<_>>()?;
+
+        let helper = MappingGeneratorHelper::new();
+
+        cleaned_directories
+            .into_iter()
+            .for_each(|dir| helper.process(dir));
+
+        info!(
+            "Will process:\n  {}",
+            all_directories
+                .iter()
+                .map(|pat| pat.display().to_string())
+                .collect::<Vec<_>>()
+                .join("\n  ")
+        );
+        Ok(Self {
+            current_mappings: HashMap::new(),
+            paths_to_process: all_directories,
+        })
+    }
+}
+
+fn check_dir(dir: PathBuf) -> Result<PathBuf> {
+    match dir.metadata() {
+        Ok(_) => Ok(dir),
+        Err(e) => bail!(
+            "'{}' is not a valid path; Error was: '{}'",
+            dir.display(),
+            e
+        ),
+    }
+}
+
+pub async fn get_dir(dir: PathBuf, current_depth: usize, max_depth: usize) -> Result<Vec<PathBuf>> {
+    let (tx, rx) = mpsc::channel(100);
+
+    let handle = tokio::spawn(async move { get_dir_recursive(dir, current_depth, max_depth, tx) });
+
+    let out = ReceiverStream::new(rx).collect::<Vec<PathBuf>>().await;
+    handle.await?;
+    Ok(out)
+}
+
+async fn get_dir_recursive(
+    dir: PathBuf,
+    current_depth: usize,
+    max_depth: usize,
+    tx: Sender<PathBuf>,
+) -> Result<()> {
+    if dir.is_dir() && current_depth != max_depth {
+        tx.send(dir).await?;
+
+        match fs::read_dir(&dir).await {
+            Ok(directories) => {
+                let mut handles: Vec<JoinHandle<Result<(), anyhow::Error>>> = vec![];
+                while let Some(entry) = directories
+                    .next_entry()
+                    .await
+                    .with_context(|| format!("Failed to read directory: '{}'", dir.display()))?
+                {
+                    let tx_new = tx.clone();
+                    handles.push(tokio::spawn(async move {
+                        get_dir_recursive(entry.path(), current_depth + 1, max_depth, tx_new)
+                            .await
+                            .with_context(|| {
+                                format!("Failed to get child directories to '{}'", dir.display())
+                            })?;
+
+                        Ok(())
+                    }));
+                }
+
+                let out: Vec<_> = tokio_stream::iter(handles)
+                    .then(|handle| async move { handle.await })
+                    .collect()
+                    .await;
+
+                // I have no idea what happened here to the type system
+                for i in out {
+                    i??
+                }
+
+                Ok(())
+            }
+
+            Err(e) => {
+                bail!(
+                    "Unable to read directory {}, skipping; error: {}",
+                    dir.display(),
+                    e
+                );
+            }
+        }
+    } else {
+        return Ok(());
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use std::path::PathBuf;
+
+    use super::get_dir;
+
+    #[test]
+    fn test_get_dir() {
+        let dirs = get_dir(PathBuf::from("~/repos"));
+        let expected_dirs = vec![PathBuf::from("~/repos/rust")];
+        assert_eq!(dirs, expected_dirs);
+    }
+}