Repository: vamolessa/verco (language: rust)

Issue:
Make it work when not on git/hg root
If git/hg folder is not found in pwd, try find it in parent folders and use that if found


Discussion / hints:

Fix patch:
diff --git a/src/git_actions.rs b/src/git_actions.rs
index ac4b6fa..39a595b 100644
--- a/src/git_actions.rs
+++ b/src/git_actions.rs
@@ -31,7 +31,17 @@ impl GitActions {
 }
 
 impl VersionControlActions for GitActions {
-    fn repository_directory(&self) -> &str {
+    fn set_root(&mut self) -> Result<(), String> {
+        let mut command = self.command();
+        let dir = handle_command(command.args(&["rev-parse", "--show-toplevel"]))?;
+        
+        let dir = dir.lines().next().expect("Root directory is an empty string");
+        self.current_dir = dir.to_owned();
+        
+        Ok(())
+    }
+
+    fn get_root(&self) -> &str {
         &self.current_dir[..]
     }
 
diff --git a/src/hg_actions.rs b/src/hg_actions.rs
index 0489ed5..264cdbd 100644
--- a/src/hg_actions.rs
+++ b/src/hg_actions.rs
@@ -39,7 +39,17 @@ impl HgActions {
 }
 
 impl<'a> VersionControlActions for HgActions {
-    fn repository_directory(&self) -> &str {
+    fn set_root(&mut self) -> Result<(), String> {
+        let mut command = self.command();
+        let dir = handle_command(command.arg("root"))?;
+
+        let dir = dir.lines().next().expect("Root directory is an empty string");
+        self.current_dir = dir.to_owned();
+
+        Ok(())
+    }
+
+    fn get_root(&self) -> &str {
         &self.current_dir[..]
     }
 
diff --git a/src/repositories.rs b/src/repositories.rs
index 2793f2a..fbf5674 100644
--- a/src/repositories.rs
+++ b/src/repositories.rs
@@ -1,4 +1,4 @@
-use std::{env, path::{Path, PathBuf}};
+use std::{env, path::Path};
 
 use crate::git_actions::GitActions;
 use crate::hg_actions::HgActions;
@@ -14,23 +14,31 @@ pub fn get_current_version_control() -> Option<Box<dyn VersionControlActions>> {
 
     let current_dir = env::current_dir().expect("could not get current directory");
 
-    if subdir_exists(&current_dir, ".git") {
-        Some(Box::from(GitActions {
-            current_dir: current_dir.to_str().expect("current directory is not valid utf8").into(),
-            revision_shortcut: Default::default(),
-        }))
-    } else if subdir_exists(&current_dir, ".hg") {
-        Some(Box::from(HgActions {
-            current_dir: current_dir.to_str().expect("current directory is not valid utf8").into(),
-            revision_shortcut: Default::default(),
-        }))
+    // First try Git because it's the most common and also responds the fastest
+    let mut git_actions = Box::from(GitActions {
+        current_dir: current_dir
+            .to_str()
+            .expect("current directory is not valid utf8")
+            .into(),
+        revision_shortcut: Default::default(),
+    });
+
+    if git_actions.set_root().is_ok() {
+        return Some(git_actions)
+    } 
+
+    // Otherwise try Mercurial
+    let mut hg_actions = Box::from(HgActions {
+        current_dir: current_dir
+            .to_str()
+            .expect("current directory is not valid utf8")
+            .into(),
+        revision_shortcut: Default::default(),
+    });
+
+    if hg_actions.set_root().is_ok() {
+        Some(hg_actions)
     } else {
         None
     }
 }
-
-fn subdir_exists(basedir: &PathBuf, subdir: &str) -> bool {
-    let mut path = basedir.clone();
-    path.push(subdir);
-    path.exists()
-}
diff --git a/src/tui.rs b/src/tui.rs
index 4eadebb..08c8d2f 100644
--- a/src/tui.rs
+++ b/src/tui.rs
@@ -87,7 +87,7 @@ where
     {
         let header = Header {
             action_name,
-            directory_name: self.version_control.repository_directory().into(),
+            directory_name: self.version_control.get_root().into(),
         };
         show_header(&mut self.write, &header, HeaderKind::Waiting)?;
         self.write.flush()?;
@@ -441,7 +441,7 @@ where
                             self.write.queue(cursor::MoveToNextLine(2))?;
 
                             let result =
-                                command.execute(self.version_control.repository_directory());
+                                command.execute(self.version_control.get_root());
                             self.handle_result(header, result)?;
                             return Ok(());
                         }
diff --git a/src/version_control_actions.rs b/src/version_control_actions.rs
index 046e55c..0a40c97 100644
--- a/src/version_control_actions.rs
+++ b/src/version_control_actions.rs
@@ -3,7 +3,10 @@ use std::process::Command;
 use crate::select::Entry;
 
 pub trait VersionControlActions {
-    fn repository_directory(&self) -> &str;
+    /// Sets the root of the current repository
+    fn set_root(&mut self) -> Result<(), String>;
+    /// Get the root of the current repository
+    fn get_root(&self) -> &str;
 
     fn get_current_changed_files(&mut self) -> Result<Vec<Entry>, String>;
     fn get_revision_changed_files(&mut self, target: &str) -> Result<Vec<Entry>, String>;


Test patch: