Skip to content
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 · 4 comments
Closed

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

kirelagin opened this issue Sep 26, 2017 · 4 comments
Labels
Bug
Milestone

Comments

@kirelagin
Copy link

@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
Copy link
Member

@waylan 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
Copy link
Member

@waylan 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
Copy link
Author

@kirelagin 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
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
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
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.
@Hassanzadeh-sd
Copy link

@Hassanzadeh-sd Hassanzadeh-sd commented Dec 22, 2018

you should be the complete target file name for destination

destination = pathdirectory + filename.*

I use this code fir copy wav file with shutil :

    # open file with QFileDialog

    browse_file = QFileDialog.getOpenFileName(None, 'Open file', 'c:', "wav files (*.wav)")

    # get file name 

    base = os.path.basename(browse_file[0])
    os.path.splitext(base)
    print(os.path.splitext(base)[1])

    # make destination path with file name

    destination= "test/" + os.path.splitext(base)[0] + os.path.splitext(base)[1]
    shutil.copyfile(browse_file[0], destination)
nyraghu added a commit to nyraghu/plastex that referenced this issue May 20, 2020
* plasTeX/Renderers/PageTemplate/__init__.py (copytree): Do not copy
  permissions of directories when copying CSS and JavaScript files,
  and templates, from the plasTeX renderer directory to the output
  directory.  If a source directory is not writable, and its
  permissions are copied to the target directory, then the files in the
  source directory cannot be copied to the target directory because
  the latter directory is not writable.  This raises an error when
  rendering.

  The above problem occurs when using plastex in a Nix environment
  created with nix-build.  Then the plasTeX renderer directory is in
  the Nix store, where all files are unwritable.

  See also <mkdocs/mkdocs#1292>.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
3 participants