From 6d0bb1a6677b0028b02c5504023423fc97c11f54 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bastian=20K=C3=B6cher?= <info@kchr.de>
Date: Tue, 13 Sep 2022 12:48:46 +0100
Subject: [PATCH] Make `BasePath::new_temp_dir` return the same path for the
 program lifetime (#12246)

* Make `BasePath::new_temp_dir` return the same path for the program lifetime

Instead of returning always a different path, this now returns the same path for the entire lifetime
of the program. We still ensure that the path is cleared at the end of the program.

* Update client/service/src/config.rs

Co-authored-by: Koute <koute@users.noreply.github.com>

* Update client/service/src/config.rs

Co-authored-by: Nitwit <47109040+nitwit69@users.noreply.github.com>

* FMT

Co-authored-by: Koute <koute@users.noreply.github.com>
Co-authored-by: Nitwit <47109040+nitwit69@users.noreply.github.com>
---
 substrate/Cargo.lock                   | 37 +++++++++++++++++++++++-
 substrate/client/service/Cargo.toml    |  1 +
 substrate/client/service/src/config.rs | 39 ++++++++++++++++----------
 3 files changed, 61 insertions(+), 16 deletions(-)

diff --git a/substrate/Cargo.lock b/substrate/Cargo.lock
index 08915196d53..efc1aa2976c 100644
--- a/substrate/Cargo.lock
+++ b/substrate/Cargo.lock
@@ -873,6 +873,12 @@ version = "1.0.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
 
+[[package]]
+name = "cfg_aliases"
+version = "0.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e"
+
 [[package]]
 name = "chacha20"
 version = "0.8.1"
@@ -8822,6 +8828,7 @@ dependencies = [
  "sp-transaction-storage-proof",
  "sp-trie",
  "sp-version",
+ "static_init",
  "substrate-prometheus-endpoint",
  "substrate-test-runtime",
  "substrate-test-runtime-client",
@@ -10341,6 +10348,34 @@ version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 
+[[package]]
+name = "static_init"
+version = "1.0.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "8a2a1c578e98c1c16fc3b8ec1328f7659a500737d7a0c6d625e73e830ff9c1f6"
+dependencies = [
+ "bitflags",
+ "cfg_aliases",
+ "libc",
+ "parking_lot 0.11.2",
+ "parking_lot_core 0.8.5",
+ "static_init_macro",
+ "winapi",
+]
+
+[[package]]
+name = "static_init_macro"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "70a2595fc3aa78f2d0e45dd425b22282dd863273761cc77780914b2cf3003acf"
+dependencies = [
+ "cfg_aliases",
+ "memchr",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
 [[package]]
 name = "statrs"
 version = "0.15.0"
@@ -11210,7 +11245,7 @@ checksum = "97fee6b57c6a41524a810daee9286c02d7752c4253064d0b05472833a438f675"
 dependencies = [
  "cfg-if 1.0.0",
  "digest 0.10.3",
- "rand 0.7.3",
+ "rand 0.8.5",
  "static_assertions",
 ]
 
diff --git a/substrate/client/service/Cargo.toml b/substrate/client/service/Cargo.toml
index e96421d031d..76c61fe17f0 100644
--- a/substrate/client/service/Cargo.toml
+++ b/substrate/client/service/Cargo.toml
@@ -85,6 +85,7 @@ async-trait = "0.1.57"
 tokio = { version = "1.17.0", features = ["time", "rt-multi-thread", "parking_lot"] }
 tempfile = "3.1.0"
 directories = "4.0.1"
+static_init = "1.0.3"
 
 [dev-dependencies]
 substrate-test-runtime-client = { version = "2.0.0", path = "../../test-utils/runtime/client" }
diff --git a/substrate/client/service/src/config.rs b/substrate/client/service/src/config.rs
index 2fb3f820ebf..44153e3b914 100644
--- a/substrate/client/service/src/config.rs
+++ b/substrate/client/service/src/config.rs
@@ -262,31 +262,43 @@ impl Default for RpcMethods {
 	}
 }
 
-/// The base path that is used for everything that needs to be write on disk to run a node.
+#[static_init::dynamic(drop, lazy)]
+static mut BASE_PATH_TEMP: Option<TempDir> = None;
+
+/// The base path that is used for everything that needs to be written on disk to run a node.
 #[derive(Debug)]
-pub enum BasePath {
-	/// A temporary directory is used as base path and will be deleted when dropped.
-	Temporary(TempDir),
-	/// A path on the disk.
-	Permanenent(PathBuf),
+pub struct BasePath {
+	path: PathBuf,
 }
 
 impl BasePath {
 	/// Create a `BasePath` instance using a temporary directory prefixed with "substrate" and use
 	/// it as base path.
 	///
-	/// Note: the temporary directory will be created automatically and deleted when the `BasePath`
-	/// instance is dropped.
+	/// Note: The temporary directory will be created automatically and deleted when the program
+	/// exits. Every call to this function will return the same path for the lifetime of the
+	/// program.
 	pub fn new_temp_dir() -> io::Result<BasePath> {
-		Ok(BasePath::Temporary(tempfile::Builder::new().prefix("substrate").tempdir()?))
+		let mut temp = BASE_PATH_TEMP.write();
+
+		match &*temp {
+			Some(p) => Ok(Self::new(p.path())),
+			None => {
+				let temp_dir = tempfile::Builder::new().prefix("substrate").tempdir()?;
+				let path = PathBuf::from(temp_dir.path());
+
+				*temp = Some(temp_dir);
+				Ok(Self::new(path))
+			},
+		}
 	}
 
 	/// Create a `BasePath` instance based on an existing path on disk.
 	///
 	/// Note: this function will not ensure that the directory exist nor create the directory. It
 	/// will also not delete the directory when the instance is dropped.
-	pub fn new<P: AsRef<Path>>(path: P) -> BasePath {
-		BasePath::Permanenent(path.as_ref().to_path_buf())
+	pub fn new<P: Into<PathBuf>>(path: P) -> BasePath {
+		Self { path: path.into() }
 	}
 
 	/// Create a base path from values describing the project.
@@ -300,10 +312,7 @@ impl BasePath {
 
 	/// Retrieve the base path.
 	pub fn path(&self) -> &Path {
-		match self {
-			BasePath::Temporary(temp_dir) => temp_dir.path(),
-			BasePath::Permanenent(path) => path.as_path(),
-		}
+		&self.path
 	}
 
 	/// Returns the configuration directory inside this base path.
-- 
GitLab