Repository: mkdocs/mkdocs

Issue:
Existing favicon gets overwritten
Apart from what the documentation says, any existing favicon gets overwritten when building or serving. This seems to have changed with 1.0.0 - the theme favicon always overwrites the favicon. I'm not using any plugins, and am using the default theme.

```
DEBUG   -  Loading configuration file: /workdir/mkdocs/mkdocs.yml
DEBUG   -  Loaded theme configuration for 'mkdocs' from '/usr/lib/python2.7/site-packages/mkdocs/themes/mkdocs/mkdocs_theme.yml': {u'hljs_languages': [], u'highlightjs': True, u'search_index_only': False, u'shortcuts': {u'search': 83, u'next': 78, u'help': 191, u'previous': 80}, u'hljs_style': u'github', u'static_templates': [u'404.html'], u'include_search_page': False}
DEBUG   -  Config value: 'site_name' = u'Documentation'
DEBUG   -  Config value: 'extra' = <mkdocs.config.config_options.SubConfig object at 0x7f64dcd77b50>
DEBUG   -  Config value: 'extra_javascript' = []
DEBUG   -  Config value: 'plugins' = PluginCollection([(u'search', <mkdocs.contrib.search.SearchPlugin object at 0x7f64dc792990>)])
DEBUG   -  Config value: 'extra_css' = []
DEBUG   -  Config value: 'config_file_path' = u'/workdir/mkdocs/mkdocs.yml'
DEBUG   -  Config value: 'copyright' = None
DEBUG   -  Config value: 'remote_branch' = u'gh-pages'
DEBUG   -  Config value: 'site_url' = u''
DEBUG   -  Config value: 'use_directory_urls' = True
DEBUG   -  Config value: 'strict' = False
DEBUG   -  Config value: 'theme' = Theme(name='mkdocs', dirs=['/usr/lib/python2.7/site-packages/mkdocs/themes/mkdocs', u'/usr/lib/python2.7/site-packages/mkdocs/templates'], static_templates=[u'404.html',u'ap.xml'], hljs_languages=[], highlightjs=True, search_index_only=False, shortcuts={u'search': 83, u'next': 78, u'help': 191, u'previous': 80}, hljs_style=u'github', include_search_page=False)
DEBUG   -  Config value: 'nav' = [{u'Home': u'index.md'}]
DEBUG   -  Config value: 'docs_dir' = u'/workdir/mkdocs/docs'
DEBUG   -  Config value: 'repo_name' = u''
DEBUG   -  Config value: 'site_dir' = u'/workdir/mkdocs/site'
DEBUG   -  Config value: 'dev_addr' = Address(host=u'127.0.0.1', port=8000)
DEBUG   -  Config value: 'repo_url' = u''
DEBUG   -  Config value: 'remote_name' = u'origin'
DEBUG   -  Config value: 'pages' = None
DEBUG   -  Config value: 'markdown_extensions' = [u'toc', u'tables', u'fenced_code']
DEBUG   -  Config value: 'site_description' = None
DEBUG   -  Config value: 'extra_templates' = []
DEBUG   -  Config value: 'site_author' = None
DEBUG   -  Config value: 'google_analytics' = None
DEBUG   -  Config value: 'mdx_configs' = {}
DEBUG   -  Config value: 'edit_uri' = u''
INFO    -  Cleaning site directory
INFO    -  Building documentation to directory: /workdir/mkdocs/site
DEBUG   -  Reading markdown pages.
DEBUG   -  Copying static assets.
DEBUG   -  Copying media file: 'img/burger.png'
DEBUG   -  Copying media file: 'img/edit-button.png'
DEBUG   -  Copying media file: 'img/favicon.ico'
DEBUG   -  Copying media file: 'img/invitations-tab.png'
DEBUG   -  Copying media file: 'css/base.css'
DEBUG   -  Copying media file: 'css/bootstrap-custom.min.css'
DEBUG   -  Copying media file: 'css/font-awesome.min.css'
DEBUG   -  Copying media file: 'fonts/fontawesome-webfont.eot'
DEBUG   -  Copying media file: 'fonts/fontawesome-webfont.svg'
DEBUG   -  Copying media file: 'fonts/fontawesome-webfont.ttf'
DEBUG   -  Copying media file: 'fonts/fontawesome-webfont.woff'
DEBUG   -  Copying media file: 'fonts/fontawesome-webfont.woff2'
DEBUG   -  Copying media file: 'fonts/glyphicons-halflings-regular.eot'
DEBUG   -  Copying media file: 'fonts/glyphicons-halflings-regular.svg'
DEBUG   -  Copying media file: 'fonts/glyphicons-halflings-regular.ttf'
DEBUG   -  Copying media file: 'fonts/glyphicons-halflings-regular.woff'
DEBUG   -  Copying media file: 'fonts/glyphicons-halflings-regular.woff2'
DEBUG   -  Copying media file: 'img/favicon.ico'
DEBUG   -  Copying media file: 'img/grid.png'
DEBUG   -  Copying media file: 'js/base.js'
DEBUG   -  Copying media file: 'js/bootstrap-3.0.3.min.js'
DEBUG   -  Copying media file: 'js/jquery-1.10.2.min.js'
DEBUG   -  Copying media file: 'search/lunr.js'
DEBUG   -  Copying media file: 'search/main.js'
DEBUG   -  Copying media file: 'search/worker.js'
DEBUG   -  Building theme template: 404.html
DEBUG   -  Building theme template: sitemap.xml
DEBUG   -  Gzipping template: sitemap.xml
DEBUG   -  Building markdown pages.
DEBUG   -  Building page index.md
```


Discussion:
Yep, that's a bug. It appears that the files collection contains two `File` objects with the same path, one which points to `img/favicon.ico` in the `docs_dir` and one which points to `img/favicon.ico` in a theme dir. We should not be adding the one from the theme dir ([here][1]) if such a path already exists in the collection.

[1]: https://github.com/mkdocs/mkdocs/blob/master/mkdocs/structure/files.py#L66

Resolving patch:
diff --git a/mkdocs/structure/files.py b/mkdocs/structure/files.py
--- a/mkdocs/structure/files.py
+++ b/mkdocs/structure/files.py
@@ -73,11 +73,13 @@ def filter(name):
                     return False
             return True
         for path in env.list_templates(filter_func=filter):
-            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
+            # Theme files do not override docs_dir files
+            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
 
 
 class File(object):


Test patch:
diff --git a/mkdocs/tests/structure/file_tests.py b/mkdocs/tests/structure/file_tests.py
--- a/mkdocs/tests/structure/file_tests.py
+++ b/mkdocs/tests/structure/file_tests.py
@@ -306,6 +306,34 @@ def test_files(self):
         self.assertTrue(extra_file.src_path in files)
         self.assertEqual(files.documentation_pages(), [fs[0], fs[1], extra_file])
 
+    @tempdir(files=[
+        'favicon.ico',
+        'index.md'
+    ])
+    @tempdir(files=[
+        'base.html',
+        'favicon.ico',
+        'style.css'
+    ])
+    def test_add_files_from_theme(self, tdir, ddir):
+        config = load_config(docs_dir=ddir, theme={'name': None, 'custom_dir': tdir})
+        env = config['theme'].get_env()
+        files = get_files(config)
+        self.assertEqual(
+            [file.src_path for file in files],
+            ['index.md', 'favicon.ico']
+        )
+        files.add_files_from_theme(env, config)
+        self.assertEqual(
+            [file.src_path for file in files],
+            ['index.md', 'favicon.ico', 'style.css']
+        )
+        # Ensure theme file does not override docs_dir file
+        self.assertEqual(
+            files.get_file_from_path('favicon.ico').abs_src_path,
+            os.path.normpath(os.path.join(ddir, 'favicon.ico'))
+        )
+
     def test_filter_paths(self):
         # Root level file
         self.assertFalse(_filter_paths('foo.md', 'foo.md', False, ['bar.md']))