New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Permission denied when copying a template from a read-only path #1292

Closed
kirelagin opened this Issue Sep 26, 2017 · 3 comments

Comments

Projects
None yet
2 participants
@kirelagin

kirelagin commented Sep 26, 2017

There are two things uncommon about my setup that cause the error.

  1. I have installed mkdocs using Nix. Long story short, all the mkdocs files (the ones in lib/python2.7/site-packages/mkdocs) have mode 0444 (that is, read-only).
  2. I have theme_dir set in mkdocs.yml and I use it to overwrite one of the theme files, namely js/highlight.pack.js.

This is what I get:

$ mkdocs build
WARNING -  Config value: 'extra_javascript'. Warning: The following files have been automatically included in the documentation build and will be added to the HTML: highlight/theme/js/highlight.pack.js. This behavior is deprecated. In version 1.0 and later they will need to be explicitly listed in the 'extra_javascript' config setting.
INFO    -  Cleaning site directory
INFO    -  Building documentation to directory: <project path>/build/site
Traceback (most recent call last):
  File "/nix/store/2zkwsgan90gl63pqnq01vrdrpf11fm1m-mkdocs-0.16.3/bin/.mkdocs-wrapped", line 12, in <module>
    sys.exit(cli())
  File "/nix/store/cjhms7xja78pbh5gnh9ii7hlxizq2iy7-python2.7-click-6.7/lib/python2.7/site-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/nix/store/cjhms7xja78pbh5gnh9ii7hlxizq2iy7-python2.7-click-6.7/lib/python2.7/site-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/nix/store/cjhms7xja78pbh5gnh9ii7hlxizq2iy7-python2.7-click-6.7/lib/python2.7/site-packages/click/core.py", line 1066, in invoke
    return _process_result(sub_ctx.command.invoke(sub_ctx))
  File "/nix/store/cjhms7xja78pbh5gnh9ii7hlxizq2iy7-python2.7-click-6.7/lib/python2.7/site-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/nix/store/cjhms7xja78pbh5gnh9ii7hlxizq2iy7-python2.7-click-6.7/lib/python2.7/site-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/nix/store/2zkwsgan90gl63pqnq01vrdrpf11fm1m-mkdocs-0.16.3/lib/python2.7/site-packages/mkdocs/__main__.py", line 156, in build_command
    ), dirty=not clean)
  File "/nix/store/2zkwsgan90gl63pqnq01vrdrpf11fm1m-mkdocs-0.16.3/lib/python2.7/site-packages/mkdocs/commands/build.py", line 373, in build
    theme_dir, config['site_dir'], exclude=['*.py', '*.pyc', '*.html'], dirty=dirty
  File "/nix/store/2zkwsgan90gl63pqnq01vrdrpf11fm1m-mkdocs-0.16.3/lib/python2.7/site-packages/mkdocs/utils/__init__.py", line 175, in copy_media_files
    copy_file(source_path, output_path)
  File "/nix/store/2zkwsgan90gl63pqnq01vrdrpf11fm1m-mkdocs-0.16.3/lib/python2.7/site-packages/mkdocs/utils/__init__.py", line 110, in copy_file
    shutil.copy(source_path, output_path)
  File "/nix/store/w8zld7z4gq4b36z0szgrh6yv5zi30915-python-2.7.13/lib/python2.7/shutil.py", line 119, in copy
    copyfile(src, dst)
  File "/nix/store/w8zld7z4gq4b36z0szgrh6yv5zi30915-python-2.7.13/lib/python2.7/shutil.py", line 83, in copyfile
    with open(dst, 'wb') as fdst:
IOError: [Errno 13] Permission denied: u'<project path>/build/site/js/highlight.pack.js'

$ ls -l build/site/js/
total 396
-r--r--r-- 1 kirelagin staff 300764 Sep 26 16:03 highlight.pack.js
-r--r--r-- 1 kirelagin staff  84245 Sep 26 16:03 jquery-2.1.1.min.js
-r--r--r-- 1 kirelagin staff  11084 Sep 26 16:03 modernizr-2.8.3.min.js
-r--r--r-- 1 kirelagin staff   2676 Sep 26 16:03 theme.js

$ ls -ld build/site/js/
drwxr-xr-x 6 kirelagin staff 204 Sep 26 16:03 build/site/js/

What happens is, the built-in theme files get copied with their permissions preserved, so site/js/highlight.pack.js ends up having mode 0444. Next mkdocs tries to overwrite this file with the one from the theme_dir and at this point shutil.copyfile fails, because that’s how it works.

I’m not really sure what to do with that. Probably, catching the exception and adjusting the permissions would make sense.

@waylan

This comment has been minimized.

Member

waylan commented Sep 26, 2017

Hmm, I'm not sure how we should deal with this either. That said, it is reasonable to expect that a user could have read-only permissions to any files in site-packages. For example, on a system with multiple users, only the root user might have write access to site-packages and therefore permission to install/update Python libs. Just because the user running MkDocs isn't the root user shouldn't mean they can't have access to all of MkDocs' features. So, yeah, this is a bug.

As a workaround, you could create a virtualenv with your user account and install MkDocs in there. Then you would have full access. You just need to remember to "activate" the venv before running MkDocs. Actually, I always run MkDocs from a venv; I don't even have it installed as a system Python lib.

@waylan waylan added the Bug label Sep 26, 2017

@waylan waylan added this to the 1.0.0 milestone Sep 26, 2017

@waylan

This comment has been minimized.

Member

waylan commented Sep 26, 2017

So, it appears that the problem is that we use shutil.copy rather than shutil.copyfile. The difference is that shutil.copy also copyies permissions. However, if we used shutil.copyfile, then a new file would be created (with permissions for the current user) and only the contents would be copied. As, shutil.copy just calls shutil.copyfile under the hood (followed by shutil.copymode which we don't want), there is no reason why we can't just use shutil.copyfile. We might also need to add a line or two to check for directories, which shutil.copy includes.

@kirelagin

This comment has been minimized.

kirelagin commented Sep 26, 2017

Yes, looks like you are right. 👍

waylan added a commit to waylan/mkdocs that referenced this issue Sep 27, 2017

Do not copy permissions with files.
In various stages of a build, a new file may overwrite a previously written
file (for example to override a theme). If a source file is read-only, the
copied file cannot remain read-only. Therefore, permissions must not be
copied with a file. `shutil.copyfile` only copies a file's contents and is
now being used to copy all files.

Fixes mkdocs#1292.

waylan added a commit to waylan/mkdocs that referenced this issue Sep 27, 2017

Do not copy permissions with files.
In various stages of a build, a new file may overwrite a previously written
file (for example to override a theme). If a source file is read-only, the
copied file cannot remain read-only. Therefore, permissions must not be
copied with a file. `shutil.copyfile` only copies a file's contents and is
now being used to copy all files.

Fixes mkdocs#1292.

@waylan waylan closed this in #1294 Sep 27, 2017

waylan added a commit that referenced this issue Sep 27, 2017

Do not copy permissions with files.
In various stages of a build, a new file may overwrite a previously written
file (for example to override a theme). If a source file is read-only, the
copied file cannot remain read-only. Therefore, permissions must not be
copied with a file. `shutil.copyfile` only copies a file's contents and is
now being used to copy all files.

Fixes #1292.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment