From fafb69e4b59a5580ed3358b22a852d879510d8cd Mon Sep 17 00:00:00 2001
From: Ryan Brue <ryanbrue.dev@gmail.com>
Date: Sep 29 2024 03:44:19 +0000
Subject: more changes


Signed-off-by: Ryan Brue <ryanbrue.dev@gmail.com>

---

diff --git a/Cargo.lock b/Cargo.lock
index 6deba74..167df1b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -109,21 +109,67 @@ version = "0.1.0"
 dependencies = [
  "anyhow",
  "clap",
+ "dot",
+ "petgraph",
 ]
 
 [[package]]
+name = "dot"
+version = "0.1.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a74b6c4d4a1cff5f454164363c16b72fa12463ca6b31f4b5f2035a65fa3d5906"
+
+[[package]]
+name = "equivalent"
+version = "1.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5"
+
+[[package]]
+name = "fixedbitset"
+version = "0.4.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80"
+
+[[package]]
+name = "hashbrown"
+version = "0.14.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1"
+
+[[package]]
 name = "heck"
 version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
 
 [[package]]
+name = "indexmap"
+version = "2.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5"
+dependencies = [
+ "equivalent",
+ "hashbrown",
+]
+
+[[package]]
 name = "is_terminal_polyfill"
 version = "1.70.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
 
 [[package]]
+name = "petgraph"
+version = "0.6.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db"
+dependencies = [
+ "fixedbitset",
+ "indexmap",
+]
+
+[[package]]
 name = "proc-macro2"
 version = "1.0.86"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/cosmic-packaging-tool/Cargo.toml b/cosmic-packaging-tool/Cargo.toml
index 66c2ab9..d3fe314 100644
--- a/cosmic-packaging-tool/Cargo.toml
+++ b/cosmic-packaging-tool/Cargo.toml
@@ -8,3 +8,5 @@ edition = "2021"
 [dependencies]
 anyhow = "1.0.89"
 clap = { version = "4.5.18", features = ["derive"] }
+dot = "0.1.4"
+petgraph = "0.6.5"
diff --git a/cosmic-packaging-tool/src/main.rs b/cosmic-packaging-tool/src/main.rs
index 134cd70..bdea719 100644
--- a/cosmic-packaging-tool/src/main.rs
+++ b/cosmic-packaging-tool/src/main.rs
@@ -1,5 +1,5 @@
 use std::{
-    collections::HashSet,
+    collections::{HashMap, HashSet},
     env,
     fs::{self, create_dir, File},
     io::{self, BufRead, Write},
@@ -8,6 +8,10 @@ use std::{
 };
 
 use clap::{Parser, Subcommand};
+use petgraph::{
+    dot::{Config, Dot},
+    graph::{DiGraph, NodeIndex},
+};
 
 #[derive(Parser)]
 #[command(version, about)]
@@ -53,6 +57,8 @@ enum Commands {
         /// Version (i.e. 1.0.0~alpha.2)
         version: String,
     },
+    /// Build a dependency graph of the packages
+    DependencyGraph { packaging_dir: PathBuf },
 }
 
 const PACKAGES_ITER: [Packages; 22] = [
@@ -160,7 +166,7 @@ impl Packages {
         }
     }
 
-    fn package_dir<'a>(&self, packaging_dir: &Path) -> PathBuf {
+    fn spec_file<'a>(&self, packaging_dir: &Path) -> PathBuf {
         packaging_dir.join(&format!(
             "rpms/{}/{}.spec",
             self.package_name(),
@@ -188,7 +194,61 @@ fn main() -> anyhow::Result<()> {
             srpm_url,
             version,
         } => setup_build_command(&workdir, &package_name, &srpm_url, &version),
+        Commands::DependencyGraph { packaging_dir } => dependency_graph_command(&packaging_dir),
+    }
+}
+
+fn dependency_graph_command(packaging_dir: &Path) -> anyhow::Result<()> {
+    // Create a directed graph
+    let mut graph = DiGraph::new();
+    let mut nodes: HashMap<String, NodeIndex> = HashMap::new();
+
+    for package in PACKAGES_ITER {
+        if !nodes.contains_key(package.package_name()) {
+            nodes.insert(
+                package.package_name().to_string(),
+                graph.add_node(package.package_name().to_string()),
+            );
+        }
+        // Open the file in read-only mode
+        let file = File::open(&package.spec_file(packaging_dir))?;
+        let reader = io::BufReader::new(file);
+
+        // Iterate over each line in the file
+        for line in reader.lines() {
+            let line = line?;
+            // Check if the line starts with "Requires:"
+            if line.starts_with("Requires:") {
+                let dep = line.split(" ").last().unwrap().to_string();
+                // println!("Dep: '{}'", &dep);
+                if !nodes.contains_key(&dep) {
+                    // println!("Dep not found in nodes: {}", &dep);
+                    nodes.insert(dep.to_string(), graph.add_node(dep.clone()));
+                }
+                graph.add_edge(
+                    *nodes.get(package.package_name()).unwrap(),
+                    *nodes.get(&dep).unwrap(),
+                    (),
+                );
+            }
+        }
     }
+
+    // Convert the graph to DOT format
+    let dot = Dot::with_config(&graph, &[Config::EdgeNoLabel]);
+
+    // Write the DOT file
+    let mut file = File::create("graph.dot").expect("Unable to create file");
+    write!(file, "{:?}", dot).expect("Unable to write to file");
+
+    println!("Graph saved to graph.dot. Attempting to convert to image (make sure graphviz is installed)...");
+    let _ = Command::new("dot")
+        .arg("-Tpng")
+        .arg(Path::new("graph.dot"))
+        .arg("-o")
+        .arg(Path::new("dep_graph.png"))
+        .status();
+    Ok(())
 }
 
 fn setup_build_command(
@@ -274,7 +334,7 @@ fn setup_build_command(
 fn autobump_releases_command(packaging_dir: &Path, release: &str) -> anyhow::Result<()> {
     for package in PACKAGES_ITER {
         homebrew_sed(
-            &package.package_dir(packaging_dir),
+            &package.spec_file(packaging_dir),
             "Release: ",
             &format!("Release:        {}", release),
         )?;
@@ -343,7 +403,7 @@ fn update_licenses_command(
             if let Some(packaging_dir) = packaging_dir.as_deref() {
                 if !license_result.is_empty() && license_validate(&license_result)? {
                     homebrew_sed(
-                        &package.package_dir(packaging_dir),
+                        &package.spec_file(packaging_dir),
                         "License: ",
                         &format!("License:        {}", &license_result),
                     )?;
diff --git a/docs/src/SUMMARY.md b/docs/src/SUMMARY.md
index ed685dc..30db5f3 100644
--- a/docs/src/SUMMARY.md
+++ b/docs/src/SUMMARY.md
@@ -3,3 +3,4 @@
 - [Welcome](./index.md)
 - [Building for Rawhide](./building-for-rawhide.md)
 - [Generating license](./generating-license.md)
+- [Dependency Graph](./dependency-graph.md)
diff --git a/rpms/cosmic-applets/cosmic-applets.spec b/rpms/cosmic-applets/cosmic-applets.spec
index de23c91..1b432b6 100644
--- a/rpms/cosmic-applets/cosmic-applets.spec
+++ b/rpms/cosmic-applets/cosmic-applets.spec
@@ -45,7 +45,7 @@ BuildRequires:  libxkbcommon-devel
 BuildRequires:  just
 BuildRequires:  desktop-file-utils
 
-Requires:       cosmic-icons
+Requires:       cosmic-icon-theme
 Requires:       cosmic-panel
 Requires:       hicolor-icon-theme
 

