Repository: mkdocs/mkdocs

Issue:
Theme files override docs_dir files on Windows
As investigated and discussed in https://github.com/squidfunk/mkdocs-material/issues/1282, custom files in docs_dir are overriden by theme files. 

For example, if you use the default MkDocs theme and create a custom `favicon.ico` in `docs/img`, the custom icon does not appear in the output. It is overwritten by the theme's own favicon.

The issue was already brought up in https://github.com/mkdocs/mkdocs/issues/1671 and fixed by https://github.com/mkdocs/mkdocs/pull/1672.

However, the fix (https://github.com/mkdocs/mkdocs/pull/1672) **only works on Unix systems (including Mac). It does not work on Windows.**

Windows handles path names differently, so I suppose the issue must be caused by that. See especially the use of `os.path` in `files.py` (https://github.com/mkdocs/mkdocs/commit/f8ac3c7ee).

I had a similar issue in mkdocs-exclude, see here: https://github.com/apenwarr/mkdocs-exclude/issues/2



Discussion:
At first I was confused by this because we have a [test][0] (added in f8ac3c7) which passes on all supported systems (including Windows). But then I realized that the test does not include any nested directories. All paths tested do not include any slashes (for example, `favicon.ico` is the complete path tested). However, the failing example in squidfunk/mkdocs-material#1282 is using a nested path (`assets/images/favicon.png`). Therefore, if [line 77][1] is comparing `assets/images/favicon.png` to `assets\images\favicon.png`, the comparison will fail and the file will be overwritten. Normally, this is not a problem as MkDocs uses the same methods for creating all of its paths internally, which ensures that they all use the same format. However, in this instance, one of the paths being compared is provided by the Jinja template environment and we cannot assume that that path is normalized in the same manner,

This is my best guess without a way to test it. To make matters worse, our Windows CI tests are broken for reasons I don't understand, so I can't rely on them for testing.

[0]: https://github.com/mkdocs/mkdocs/commit/f8ac3c7ee#diff-f7c5abbb8f89d4893bea2dbc26f6e5e4
[1]: https://github.com/mkdocs/mkdocs/blob/f8ac3c7ee0d5839273c3dd3a6a9890a8fe3346e0/mkdocs/structure/files.py#L77 
Normalizing the path before checking the files in `files.py` fixes it:

```python
for path in env.list_templates(filter_func=filter):
    # Theme files do not override docs_dir files
    path = os.path.normpath(path)
    if path not in self:
        for dir in config['theme'].dirs:
            # Find the first theme dir which contains path                   
            if os.path.isfile(os.path.join(dir, path)):
                self.append(File(path, dir, config['site_dir'], config['use_directory_urls']))
                break
```

(Line 3 was added.)

Didn't test it on Unix, but should work there as well.
That is exactly what I suspected the fix would be. Thanks for testing it. Feel free to create a PR.

Resolving patch:
diff --git a/mkdocs/structure/files.py b/mkdocs/structure/files.py
--- a/mkdocs/structure/files.py
+++ b/mkdocs/structure/files.py
@@ -75,6 +75,7 @@ def filter(name):
             return True
         for path in env.list_templates(filter_func=filter):
             # Theme files do not override docs_dir files
+            path = os.path.normpath(path)
             if path not in self:
                 for dir in config['theme'].dirs:
                     # Find the first theme dir which contains path


Test patch: