# HG changeset patch
# User Simon Sapin <simon.sapin@octobus.net>
# Date 1636047750 -3600
#      Thu Nov 04 18:42:30 2021 +0100
# Node ID a5a4311d5148c64d19a5ad9e1e41d880c68734a8
# Parent  60d53e09b2acc52d6d760d85dd35596edcd01822
Find and create a `tmp` directory in the source repo

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -1,1 +1,2 @@
 ^target/
+^tmp/
diff --git a/src/main.rs b/src/main.rs
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,5 +1,6 @@
 use dialoguer::console::style;
 use dialoguer::Confirm;
+use std::path::PathBuf;
 use structopt::StructOpt;
 
 #[derive(StructOpt)]
@@ -7,32 +8,68 @@
     NewDataset { directory: String },
 }
 
+struct Megafine {
+    tmp_dir: PathBuf,
+}
+
 type Result<T> = std::result::Result<T, Box<dyn std::error::Error>>;
 
-fn new_dataset(directory: String) -> Result<()> {
-    println!(
-        "Creating a dataset from directory {}",
-        style(&directory).bold()
-    );
-    if !std::fs::metadata(&directory)?.is_dir() {
-        Err("Not a directory")?
+impl Megafine {
+    fn new_dataset(&self, directory: String) -> Result<()> {
+        println!(
+            "Creating a dataset from directory {}",
+            style(&directory).bold()
+        );
+        if !std::fs::metadata(&directory)?.is_dir() {
+            Err("Not a directory")?
+        }
+        let proceed = Confirm::new()
+            .with_prompt("Continue?")
+            .default(false)
+            .interact()?;
+        if !proceed {
+            Err("")?
+        }
+        // TODO
+        Ok(())
     }
-    let proceed = Confirm::new()
-        .with_prompt("Continue?")
-        .default(false)
-        .interact()?;
-    if !proceed {
-        Err("")?
+
+    fn new() -> Result<Self> {
+        let exe = std::fs::canonicalize(std::env::current_exe()?)?;
+
+        // TODO: use a `try` block when available
+        // https://github.com/rust-lang/rust/issues/31436
+        let find_repo = || {
+            let parent_1 = exe.parent()?;
+            let parent_2 = parent_1.parent()?;
+            let parent_3 = parent_2.parent()?;
+            let name_1 = parent_1.file_name()?;
+            let name_2 = parent_2.file_name()?;
+            (name_2 == "target" && (name_1 == "debug" || name_1 == "release")).then(|| parent_3)
+        };
+
+        let repo = find_repo().ok_or_else(|| {
+            format!(
+                "Couldn’t find megafine repository, executable is '{}' \
+                 instead of the expected target/{{debug,target}}/megafine",
+                exe.display()
+            )
+        })?;
+        let tmp_dir = repo.join("tmp");
+        std::fs::create_dir_all(&tmp_dir)?;
+        Ok(Self { tmp_dir })
     }
-    // TODO
-    Ok(())
+
+    fn main() -> Result<()> {
+        let megafine = Megafine::new()?;
+        match Args::from_args() {
+            Args::NewDataset { directory } => megafine.new_dataset(directory),
+        }
+    }
 }
 
 fn main() {
-    let result = match Args::from_args() {
-        Args::NewDataset { directory } => new_dataset(directory),
-    };
-    match result {
+    match Megafine::main() {
         Ok(()) => {}
         Err(error) => {
             let message = error.to_string();