Repository: mkdocs/mkdocs

Issue:
Don't allow the `site_dir` to be within the `docs_dir`
This leads to the output being copied into the output during a build.

Discussion:

Patch:
diff --git a/.travis.sh b/.travis.sh
index ab95ebbc..de43ce8e 100755
--- a/.travis.sh
+++ b/.travis.sh
@@ -3,7 +3,7 @@ set -xe
 if [ $TOX_ENV == "coverage" ]
 then
   pip install coveralls
-  tox -e py27
+  tox -e py27-unittests
   coveralls
 else
   tox -e $TOX_ENV
diff --git a/mkdocs/config.py b/mkdocs/config.py
index aeaad94e..2b6dcebe 100644
--- a/mkdocs/config.py
+++ b/mkdocs/config.py
@@ -97,6 +97,18 @@ def validate_config(user_config):
     if not config['site_name']:
         raise ConfigurationError("Config must contain 'site_name' setting.")
 
+    # Validate that the docs_dir and site_dir don't contain the
+    # other as this will lead to copying back and forth on each
+    # and eventually make a deep nested mess.
+    abs_site_dir = os.path.abspath(config['site_dir'])
+    abs_docs_dir = os.path.abspath(config['docs_dir'])
+    if abs_docs_dir.startswith(abs_site_dir):
+        raise ConfigurationError(
+            "The 'docs_dir' can't be within the 'site_dir'.")
+    elif abs_site_dir.startswith(abs_docs_dir):
+        raise ConfigurationError(
+            "The 'site_dir' can't be within the 'docs_dir'.")
+
     # If not specified, then the 'pages' config simply includes all
     # markdown files in the docs dir, without generating any header items
     # for them.


Test patch:
diff --git a/mkdocs/tests/config_tests.py b/mkdocs/tests/config_tests.py
index b28d9465..4c27ec9a 100644
--- a/mkdocs/tests/config_tests.py
+++ b/mkdocs/tests/config_tests.py
@@ -111,3 +111,27 @@ class ConfigTests(unittest.TestCase):
             self.assertEqual(conf['pages'], ['index.md', 'about.md'])
         finally:
             shutil.rmtree(tmp_dir)
+
+    def test_doc_dir_in_site_dir(self):
+
+        test_configs = (
+            {'docs_dir': 'docs', 'site_dir': 'docs/site'},
+            {'docs_dir': 'site/docs', 'site_dir': 'site'},
+            {'docs_dir': 'docs', 'site_dir': '.'},
+            {'docs_dir': '.', 'site_dir': 'site'},
+            {'docs_dir': '.', 'site_dir': '.'},
+            {'docs_dir': 'docs', 'site_dir': ''},
+            {'docs_dir': '', 'site_dir': 'site'},
+            {'docs_dir': '', 'site_dir': ''},
+            {'docs_dir': '../mkdocs/docs', 'site_dir': 'docs'},
+        )
+
+        conf = {
+            'site_name': 'Example',
+        }
+
+        for test_config in test_configs:
+
+            c = conf.copy()
+            c.update(test_config)
+            self.assertRaises(ConfigurationError, config.validate_config, c)