From 202f3e48a96b38d32b11d28449358c7d1f3546ff Mon Sep 17 00:00:00 2001
From: Jiahao XU <Jiahao_XU@outlook.com>
Date: Mon, 27 May 2024 20:57:14 +1000
Subject: [PATCH 1/4] Refactor: Make it easier to compile gitoxide as dynlib

And also optimize compilation time: By making `plumbing` and `porcelain`
as modules the `lib.rs`, they can be compiled after the rmeta for the
dependencies are generated.

For the `uni.rs` which uses both `plumbing` and `porcelain`, this would avoid
compiling these two modules twice.

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
---
 src/ein.rs                   |  4 +---
 src/gix.rs                   |  8 ++------
 src/lib.rs                   |  2 ++
 src/plumbing/main.rs         |  2 +-
 src/plumbing/options/free.rs |  2 +-
 src/plumbing/options/mod.rs  | 30 +++++++++++++++---------------
 src/porcelain/main.rs        | 12 ++++++------
 src/porcelain/options.rs     |  4 ++--
 src/uni.rs                   |  7 ++-----
 9 files changed, 32 insertions(+), 39 deletions(-)

diff --git a/src/ein.rs b/src/ein.rs
index ebcfa5a9965..371a68690dc 100644
--- a/src/ein.rs
+++ b/src/ein.rs
@@ -1,9 +1,7 @@
 #![deny(rust_2018_idioms, unsafe_code)]
 
-mod porcelain;
-
 fn main() -> anyhow::Result<()> {
-    porcelain::main()
+    crate::porcelain::main()
 }
 
 #[cfg(not(feature = "pretty-cli"))]
diff --git a/src/gix.rs b/src/gix.rs
index 8527e57926a..1d010e6e344 100644
--- a/src/gix.rs
+++ b/src/gix.rs
@@ -1,12 +1,8 @@
 #![deny(unsafe_code, rust_2018_idioms)]
 
-mod plumbing;
-
-use anyhow::Result;
-
 #[cfg(feature = "pretty-cli")]
-fn main() -> Result<()> {
-    plumbing::main()
+fn main() -> anyhow::Result<()> {
+    crate::plumbing::main()
 }
 
 #[cfg(not(feature = "pretty-cli"))]
diff --git a/src/lib.rs b/src/lib.rs
index 64313c03533..74da768da12 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -24,5 +24,7 @@
 #![allow(missing_docs)]
 #![forbid(unsafe_code)]
 
+pub mod plumbing;
+pub mod porcelain;
 /// everything in common between the `gix` and `ein` binaries.
 pub mod shared;
diff --git a/src/plumbing/main.rs b/src/plumbing/main.rs
index 49b2c50fe9e..b139264955e 100644
--- a/src/plumbing/main.rs
+++ b/src/plumbing/main.rs
@@ -7,9 +7,9 @@ use std::{
     },
 };
 
+use crate::shared::pretty::prepare_and_run;
 use anyhow::{anyhow, Context, Result};
 use clap::{CommandFactory, Parser};
-use gitoxide::shared::pretty::prepare_and_run;
 use gitoxide_core as core;
 use gitoxide_core::{pack::verify, repository::PathsOrPatterns};
 use gix::bstr::{io::BufReadExt, BString};
diff --git a/src/plumbing/options/free.rs b/src/plumbing/options/free.rs
index 8da1a6fffa3..743b2e39d2d 100644
--- a/src/plumbing/options/free.rs
+++ b/src/plumbing/options/free.rs
@@ -42,7 +42,7 @@ pub mod index {
     #[derive(Debug, clap::Parser)]
     pub struct Platform {
         /// The object format to assume when reading files that don't inherently know about it, or when writing files.
-        #[clap(long, default_value_t = gix::hash::Kind::default(), value_parser = gitoxide::shared::AsHashKind)]
+        #[clap(long, default_value_t = gix::hash::Kind::default(), value_parser = crate::shared::AsHashKind)]
         pub object_hash: gix::hash::Kind,
 
         /// The path to the index file.
diff --git a/src/plumbing/options/mod.rs b/src/plumbing/options/mod.rs
index 10d0312bc7b..229afc4ed13 100644
--- a/src/plumbing/options/mod.rs
+++ b/src/plumbing/options/mod.rs
@@ -17,7 +17,7 @@ pub struct Args {
     ///
     /// For example, if `key` is `core.abbrev`, set configuration like `[core] abbrev = key`,
     /// or `remote.origin.url = foo` to set `[remote "origin"] url = foo`.
-    #[clap(long, short = 'c', value_parser = gitoxide::shared::AsBString)]
+    #[clap(long, short = 'c', value_parser = crate::shared::AsBString)]
     pub config: Vec<BString>,
 
     #[clap(long, short = 't')]
@@ -64,12 +64,12 @@ pub struct Args {
         long,
         short = 'f',
         default_value = "human",
-        value_parser = gitoxide::shared::AsOutputFormat
+        value_parser = crate::shared::AsOutputFormat
     )]
     pub format: core::OutputFormat,
 
     /// The object format to assume when reading files that don't inherently know about it, or when writing files.
-    #[clap(long, default_value_t = gix::hash::Kind::default(), value_parser = gitoxide::shared::AsHashKind)]
+    #[clap(long, default_value_t = gix::hash::Kind::default(), value_parser = crate::shared::AsHashKind)]
     pub object_hash: gix::hash::Kind,
 
     #[clap(subcommand)]
@@ -201,7 +201,7 @@ pub mod archive {
 }
 
 pub mod status {
-    use gitoxide::shared::{CheckPathSpec, ParseRenameFraction};
+    use crate::shared::{CheckPathSpec, ParseRenameFraction};
     use gix::bstr::BString;
 
     #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)]
@@ -320,7 +320,7 @@ pub mod config {
         ///
         /// Typical filters are `branch` or `remote.origin` or `remote.or*` - git-style globs are supported
         /// and comparisons are case-insensitive.
-        #[clap(value_parser = gitoxide::shared::AsBString)]
+        #[clap(value_parser = crate::shared::AsBString)]
         pub filter: Vec<BString>,
     }
 }
@@ -359,7 +359,7 @@ pub mod fetch {
         pub remote: Option<String>,
 
         /// Override the built-in and configured ref-specs with one or more of the given ones.
-        #[clap(value_parser = gitoxide::shared::AsBString)]
+        #[clap(value_parser = crate::shared::AsBString)]
         pub ref_spec: Vec<gix::bstr::BString>,
     }
 
@@ -374,11 +374,11 @@ pub mod fetch {
         pub deepen: Option<u32>,
 
         /// Cutoff all history past the given date. Can be combined with shallow-exclude.
-        #[clap(long, help_heading = Some("SHALLOW"), value_parser = gitoxide::shared::AsTime, value_name = "DATE", conflicts_with_all = ["depth", "deepen", "unshallow"])]
+        #[clap(long, help_heading = Some("SHALLOW"), value_parser = crate::shared::AsTime, value_name = "DATE", conflicts_with_all = ["depth", "deepen", "unshallow"])]
         pub shallow_since: Option<gix::date::Time>,
 
         /// Cutoff all history past the tag-name or ref-name. Can be combined with shallow-since.
-        #[clap(long, help_heading = Some("SHALLOW"), value_parser = gitoxide::shared::AsPartialRefName, value_name = "REF_NAME", conflicts_with_all = ["depth", "deepen", "unshallow"])]
+        #[clap(long, help_heading = Some("SHALLOW"), value_parser = crate::shared::AsPartialRefName, value_name = "REF_NAME", conflicts_with_all = ["depth", "deepen", "unshallow"])]
         pub shallow_exclude: Vec<gix::refs::PartialName>,
 
         /// Remove the shallow boundary and fetch the entire history available on the remote.
@@ -445,11 +445,11 @@ pub mod clone {
         pub depth: Option<NonZeroU32>,
 
         /// Cutoff all history past the given date. Can be combined with shallow-exclude.
-        #[clap(long, help_heading = Some("SHALLOW"), value_parser = gitoxide::shared::AsTime, value_name = "DATE")]
+        #[clap(long, help_heading = Some("SHALLOW"), value_parser = crate::shared::AsTime, value_name = "DATE")]
         pub shallow_since: Option<gix::date::Time>,
 
         /// Cutoff all history past the tag-name or ref-name. Can be combined with shallow-since.
-        #[clap(long, help_heading = Some("SHALLOW"), value_parser = gitoxide::shared::AsPartialRefName, value_name = "REF_NAME")]
+        #[clap(long, help_heading = Some("SHALLOW"), value_parser = crate::shared::AsPartialRefName, value_name = "REF_NAME")]
         pub shallow_exclude: Vec<gix::refs::PartialName>,
     }
 
@@ -501,7 +501,7 @@ pub mod remote {
             #[clap(long, short = 'u')]
             show_unmapped_remote_refs: bool,
             /// Override the built-in and configured ref-specs with one or more of the given ones.
-            #[clap(value_parser = gitoxide::shared::AsBString)]
+            #[clap(value_parser = crate::shared::AsBString)]
             ref_spec: Vec<gix::bstr::BString>,
         },
     }
@@ -517,7 +517,7 @@ pub mod mailmap {
 
 #[cfg(feature = "gitoxide-core-tools-clean")]
 pub mod clean {
-    use gitoxide::shared::CheckPathSpec;
+    use crate::shared::CheckPathSpec;
     use gix::bstr::BString;
 
     #[derive(Default, Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, clap::ValueEnum)]
@@ -787,7 +787,7 @@ pub mod revision {
 }
 
 pub mod attributes {
-    use gitoxide::shared::CheckPathSpec;
+    use crate::shared::CheckPathSpec;
     use gix::bstr::BString;
 
     #[derive(Debug, clap::Subcommand)]
@@ -817,7 +817,7 @@ pub mod attributes {
 pub mod exclude {
     use std::ffi::OsString;
 
-    use gitoxide::shared::CheckPathSpec;
+    use crate::shared::CheckPathSpec;
     use gix::bstr::BString;
 
     #[derive(Debug, clap::Subcommand)]
@@ -847,7 +847,7 @@ pub mod exclude {
 pub mod index {
     use std::path::PathBuf;
 
-    use gitoxide::shared::CheckPathSpec;
+    use crate::shared::CheckPathSpec;
     use gix::bstr::BString;
 
     pub mod entries {
diff --git a/src/porcelain/main.rs b/src/porcelain/main.rs
index a622571485e..9024c193775 100644
--- a/src/porcelain/main.rs
+++ b/src/porcelain/main.rs
@@ -3,9 +3,9 @@ use std::sync::{
     Arc,
 };
 
+use crate::shared::pretty::prepare_and_run;
 use anyhow::{anyhow, Result};
 use clap::{CommandFactory, Parser};
-use gitoxide::shared::pretty::prepare_and_run;
 use gitoxide_core as core;
 
 use crate::porcelain::options::{Args, Subcommands};
@@ -41,7 +41,7 @@ pub fn main() -> Result<()> {
             verbose,
             progress,
             progress_keep_open,
-            gitoxide::shared::STANDARD_RANGE,
+            crate::shared::STANDARD_RANGE,
             move |_progress, _out, _err| panic!("something went very wrong"),
         ),
         Subcommands::Init { directory } => core::repository::init(directory).map(|_| ()),
@@ -61,7 +61,7 @@ pub fn main() -> Result<()> {
                     verbose,
                     progress,
                     progress_keep_open,
-                    gitoxide::shared::STANDARD_RANGE,
+                    crate::shared::STANDARD_RANGE,
                     move |mut progress, out, mut err| {
                         let engine = query::prepare(
                             &repo_dir,
@@ -101,7 +101,7 @@ pub fn main() -> Result<()> {
                     verbose,
                     progress,
                     progress_keep_open,
-                    gitoxide::shared::STANDARD_RANGE,
+                    crate::shared::STANDARD_RANGE,
                     move |progress, out, _err| {
                         hours::estimate(
                             &working_dir,
@@ -128,7 +128,7 @@ pub fn main() -> Result<()> {
                     verbose,
                     progress,
                     progress_keep_open,
-                    gitoxide::shared::STANDARD_RANGE,
+                    crate::shared::STANDARD_RANGE,
                     move |progress, out, _err| {
                         organize::discover(
                             root.unwrap_or_else(|| [std::path::Component::CurDir].iter().collect()),
@@ -152,7 +152,7 @@ pub fn main() -> Result<()> {
                     verbose,
                     progress,
                     progress_keep_open,
-                    gitoxide::shared::STANDARD_RANGE,
+                    crate::shared::STANDARD_RANGE,
                     move |progress, _out, _err| {
                         organize::run(
                             if execute {
diff --git a/src/porcelain/options.rs b/src/porcelain/options.rs
index 708ffdd1417..6fee59f0332 100644
--- a/src/porcelain/options.rs
+++ b/src/porcelain/options.rs
@@ -126,7 +126,7 @@ pub mod tools {
 
     #[cfg(feature = "gitoxide-core-tools-query")]
     pub mod query {
-        use gitoxide::shared::AsPathSpec;
+        use crate::shared::AsPathSpec;
 
         #[derive(Debug, clap::Subcommand)]
         pub enum Command {
@@ -153,7 +153,7 @@ pub mod tools {
         #[clap(default_value = ".")]
         pub working_dir: PathBuf,
         /// The name of the revision as spec, like 'HEAD' or 'main' at which to start iterating the commit graph.
-        #[clap(default_value("HEAD"), value_parser = gitoxide::shared::AsBString)]
+        #[clap(default_value("HEAD"), value_parser = crate::shared::AsBString)]
         pub rev_spec: BString,
         /// Ignore github bots which match the `[bot]` search string.
         #[clap(short = 'b', long)]
diff --git a/src/uni.rs b/src/uni.rs
index b4a76ad6846..af8a5f97d30 100644
--- a/src/uni.rs
+++ b/src/uni.rs
@@ -8,9 +8,6 @@
 
 use anyhow::{bail, Result};
 
-mod plumbing;
-mod porcelain;
-
 #[cfg(feature = "pretty-cli")]
 fn main() -> Result<()> {
     match std::env::current_exe()?
@@ -18,8 +15,8 @@ fn main() -> Result<()> {
         .and_then(|stem| stem.to_str())
         .unwrap_or("gix")
     {
-        "gix" => plumbing::main(),
-        "ein" => porcelain::main(),
+        "gix" => crate::plumbing::main(),
+        "ein" => crate::porcelain::main(),
         unknown => bail!("Executable named '{unknown}' cannot be launched. Exe must be named either `gix` or `ein`."),
     }
 }

From 0b5dc744b951a2ff49ddc4d2c10aaeaf10da2c4b Mon Sep 17 00:00:00 2001
From: Jiahao XU <Jiahao_XU@outlook.com>
Date: Mon, 27 May 2024 22:58:19 +1000
Subject: [PATCH 2/4] Fix compilation errors

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
---
 src/ein.rs | 2 +-
 src/gix.rs | 2 +-
 src/lib.rs | 2 +-
 3 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/ein.rs b/src/ein.rs
index 371a68690dc..07a0fe314e7 100644
--- a/src/ein.rs
+++ b/src/ein.rs
@@ -1,7 +1,7 @@
 #![deny(rust_2018_idioms, unsafe_code)]
 
 fn main() -> anyhow::Result<()> {
-    crate::porcelain::main()
+    gitoxide::porcelain::main()
 }
 
 #[cfg(not(feature = "pretty-cli"))]
diff --git a/src/gix.rs b/src/gix.rs
index 1d010e6e344..2fd02b14e32 100644
--- a/src/gix.rs
+++ b/src/gix.rs
@@ -2,7 +2,7 @@
 
 #[cfg(feature = "pretty-cli")]
 fn main() -> anyhow::Result<()> {
-    crate::plumbing::main()
+    gitoxide::plumbing::main()
 }
 
 #[cfg(not(feature = "pretty-cli"))]
diff --git a/src/lib.rs b/src/lib.rs
index 74da768da12..a512433c3ac 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -22,7 +22,7 @@
 #![cfg_attr(all(doc, feature = "document-features"), feature(doc_cfg, doc_auto_cfg))]
 #![deny(rust_2018_idioms)]
 #![allow(missing_docs)]
-#![forbid(unsafe_code)]
+#![deny(unsafe_code)]
 
 pub mod plumbing;
 pub mod porcelain;

From 4596a3949cdeb7c6953c2a9b8ac1e51609e1b160 Mon Sep 17 00:00:00 2001
From: Jiahao XU <Jiahao_XU@outlook.com>
Date: Mon, 27 May 2024 23:11:42 +1000
Subject: [PATCH 3/4] Fix compilation error in `src/plumbing/main.rs`

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
---
 src/plumbing/main.rs | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/plumbing/main.rs b/src/plumbing/main.rs
index b139264955e..6c8b219d3bf 100644
--- a/src/plumbing/main.rs
+++ b/src/plumbing/main.rs
@@ -24,7 +24,7 @@ use crate::plumbing::{
 
 #[cfg(feature = "gitoxide-core-async-client")]
 pub mod async_util {
-    use gitoxide::shared::ProgressRange;
+    use crate::shared::ProgressRange;
 
     #[cfg(not(feature = "prodash-render-line"))]
     compile_error!("BUG: Need at least a line renderer in async mode");
@@ -38,7 +38,7 @@ pub mod async_util {
         Option<prodash::render::line::JoinHandle>,
         gix_features::progress::DoOrDiscard<prodash::tree::Item>,
     ) {
-        use gitoxide::shared::{self, STANDARD_RANGE};
+        use crate::shared::{self, STANDARD_RANGE};
         shared::init_env_logger();
 
         if verbose {

From bf5a1112245b6d60ceaf5591acf15acd0c8c6363 Mon Sep 17 00:00:00 2001
From: Jiahao XU <Jiahao_XU@outlook.com>
Date: Mon, 27 May 2024 23:23:00 +1000
Subject: [PATCH 4/4] Fix clippy warning

Signed-off-by: Jiahao XU <Jiahao_XU@outlook.com>
---
 src/plumbing/main.rs | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/plumbing/main.rs b/src/plumbing/main.rs
index 6c8b219d3bf..de177127e44 100644
--- a/src/plumbing/main.rs
+++ b/src/plumbing/main.rs
@@ -732,7 +732,7 @@ pub fn main() -> Result<()> {
                         &url,
                         directory,
                         refs_directory,
-                        refs.into_iter().map(|s| s.into()).collect(),
+                        refs.into_iter().map(Into::into).collect(),
                         progress,
                         core::pack::receive::Context {
                             thread_limit,