Index: vc/darcs.py
===================================================================
--- vc/darcs.py	(revision 1182)
+++ vc/darcs.py	(working copy)
@@ -37,17 +37,13 @@
 
     CMD = "darcs"
     NAME = "Darcs"
+    VC_DIR = "_darcs"
     PATCH_STRIP_NUM = 1
     PATCH_INDEX_RE = "--- old.+?/(.+?)\\t+.*[0-9]{4}$"
 
     def __init__(self, location):
+        _vc.Vc.__init__(self, location)
         self._cachetime = None
-        while location != "/":
-            if os.path.isdir( "%s/_darcs" % location):
-                self.root = location
-                return
-            location = os.path.dirname(location)
-        raise ValueError()
 
     def commit_command(self, message):
         return [self.CMD, "record",
Index: vc/bzr.py
===================================================================
--- vc/bzr.py	(revision 1182)
+++ vc/bzr.py	(working copy)
@@ -30,17 +30,13 @@
 
     CMD = "bzr"
     NAME = "Bazaar-NG"
+    VC_DIR = ".bzr"
     PATCH_STRIP_NUM = 0
     PATCH_INDEX_RE = "^=== modified file '(.*)'$"
 
     def __init__(self, location):
+        _vc.Vc.__init__(self, location)
         self._tree_cache = None
-        while location != "/":
-            if os.path.isdir( "%s/.bzr" % location):
-                self.root = location
-                return
-            location = os.path.dirname(location)
-        raise ValueError()
 
     def commit_command(self, message):
         return [self.CMD,"commit","-m",message]
Index: vc/monotone.py
===================================================================
--- vc/monotone.py	(revision 1182)
+++ vc/monotone.py	(working copy)
@@ -36,15 +36,8 @@
         self._tree_cache = None
         location = os.path.normpath(location)
 
-        def find_folder(where, tofind):
-            while where != "/":
-                cur = os.path.join(where,tofind)
-                if os.path.isdir(cur):
-                    return where
-                where = os.path.dirname(where)
-
         # for monotone >= 0.26
-        mtn = find_folder(location,"_MTN")
+        mtn = self.find_repo_root(location, "_MTN", raiseError = False)
         if mtn:
             self.root = mtn
 
@@ -55,7 +48,7 @@
             return
 
         # for monotone <= 0.25 (different metadata directory, different executable)
-        mt = find_folder(location,"MT")
+        mt = self.find_repo_root(location, "MT", raiseError = False)
         if mt:
             self.root = mt
             self.CMD = "monotone"
Index: vc/tla.py
===================================================================
--- vc/tla.py	(revision 1182)
+++ vc/tla.py	(working copy)
@@ -61,18 +61,14 @@
 
     CMD = "tla"
     NAME = "Arch"
+    VC_DIR = "{arch}"
     PATCH_STRIP_NUM = 1
     PATCH_INDEX_RE = "--- orig/(.*)"
 
     def __init__(self, location):
+        _vc.Vc.__init__(self, location)
         self._cachetime = None
         self._cached_statuses = None
-        while location != "/":
-            if os.path.isdir( "%s/{arch}" % location):
-                self.root = location
-                return
-            location = os.path.dirname(location)
-        raise ValueError()
 
     def commit_command(self, message):
         return [self.CMD, "commit",
Index: vc/git.py
===================================================================
--- vc/git.py	(revision 1182)
+++ vc/git.py	(working copy)
@@ -35,21 +35,20 @@
 
     CMD = "git"
     NAME = "Git"
+    VC_DIR = ".git"
     PATCH_STRIP_NUM = 1
     PATCH_INDEX_RE = "^diff --git a/(.*) b/.*$"
 
     def __init__(self, location):
         self._tree_cache = None
-        while location != "/":
-            if os.path.isdir( "%s/.git" % location):
-                self.root = location
+        try:
+            _vc.Vc.__init__(self, location)
+        except ValueError:
+            gitdir = os.environ.get("GIT_DIR")
+            if gitdir and os.path.isdir(gitdir):
+                self.root = gitdir
                 return
-            location = os.path.dirname(location)
-        gitdir = os.environ.get("GIT_DIR")
-        if gitdir and os.path.isdir(gitdir):
-            self.root = gitdir
-            return
-        raise ValueError()
+            raise ValueError()
 
     def commit_command(self, message):
         return [self.CMD,"commit","-m",message]
Index: vc/mercurial.py
===================================================================
--- vc/mercurial.py	(revision 1182)
+++ vc/mercurial.py	(working copy)
@@ -29,17 +29,10 @@
 
     CMD = "hg"
     NAME = "Mercurial"
+    VC_DIR = ".hg"
     PATCH_STRIP_NUM = 1
     PATCH_INDEX_RE = "^diff -r \w+ (.*)$"
 
-    def __init__(self, location):
-        while location != "/":
-            if os.path.isdir( "%s/.hg" % location):
-                self.root = location
-                return
-            location = os.path.dirname(location)
-        raise ValueError()
-
     def commit_command(self, message):
         return [self.CMD,"commit","-m",message]
     def diff_command(self):
Index: vc/_vc.py
===================================================================
--- vc/_vc.py	(revision 1182)
+++ vc/_vc.py	(working copy)
@@ -70,7 +70,11 @@
 class Vc(object):
 
     PATCH_STRIP_NUM = 0
+    VC_DIR = None
 
+    def __init__(self, location):
+        self.root = self.find_repo_root(location, self.VC_DIR)
+
     def commit_command(self, message):
         raise NotImplementedError()
     def diff_command(self):
@@ -86,6 +90,15 @@
     def patch_command(self, workdir):
         return ["patch","--strip=%i"%self.PATCH_STRIP_NUM,"--reverse","--directory=%s" % workdir]
 
+    def find_repo_root(self, start, subdir, raiseError = True):
+        while start != "/":
+            if os.path.isdir(os.path.join(start, subdir)):
+                return start
+            start = os.path.dirname(start)
+        if raiseError:
+            raise ValueError()
+        return None
+
     def get_working_directory(self, workdir):
         return workdir
 
