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

WIP Fix file permissions of package.py on Windows #598

Merged

Conversation

mottosso
Copy link
Contributor

@mottosso mottosso commented Apr 18, 2019

This hasn't been confirmed yet; on some machines, this hasn't been an issue, but on mine (Windows 10, non-privileged user, local disk) it was a showstopper.

The permission bits here aren't supported on Windows which shouldn't be a problem, as they should fall back to the only two bits that are, IWRITE and IREAD. Here however, they result in read-only file permissions that cannot be overwritten and breaks building of variants amongst others

$ rez build --install
== Anima Rez Config ==
16:50:44 INFO     Applying preprocess function package_preprocess_function
16:50:44 INFO     Package attributes were changed in preprocessing:
Added attributes: ['config']
16:50:44 INFO     Applying preprocess function package_preprocess_function
16:50:44 INFO     Package attributes were changed in preprocessing:
Added attributes: ['config']

--------------------------------------------------------------------------------
Building ATC-0.3.15...
--------------------------------------------------------------------------------

--------------------------------------------------------------------------------
Building variant 0 (1/2)...
--------------------------------------------------------------------------------
16:50:44 INFO     Applying preprocess function package_preprocess_function
16:50:44 INFO     Package attributes were changed in preprocessing:
Added attributes: ['config']
Resolving build environment: globals-0.0.5+ core_pipeline-1.2+ maya-2018
resolved by manima@toy.fritz.box, on Thu Apr 18 16:50:44 2019, using Rez v2.29.0

requested packages:
globals-0.0.5+
core_pipeline-1.2+
maya-2018
~platform==windows       (implicit)
~arch==AMD64             (implicit)
~os==windows-10.0.17134  (implicit)

resolved packages:
Qt.py-1.1.0            C:\Users\manima\Dropbox\dev\anima\.cache\packages\ext\Qt.py\1.1.0\platform-windows\arch-AMD64\os-windows-10.0.17134\python-2.7
arch-AMD64             C:\Users\manima\packages\arch\AMD64                                                                                             (local)
core_pipeline-1.2.0    C:\Users\manima\Dropbox\dev\anima\.cache\packages\int\core_pipeline\1.2.0
globals-0.0.6          C:\Users\manima\packages\int\globals\0.0.6
maya-2018.0.0          C:\Users\manima\packages\ext\maya\2018.0.0
maya_base-1.0.7        C:\Users\manima\packages\ext\maya_base\1.0.7
os-windows-10.0.17134  C:\Users\manima\packages\os\windows-10.0.17134                                                                                  (local)
platform-windows       C:\Users\manima\packages\platform\windows                                                                                       (local)
python-2.7.14          C:\Users\manima\packages\python\2.7.14\platform-windows\arch-AMD64\os-windows-10.0.17134                                        (local)
six-1.12.0             C:\Users\manima\Dropbox\dev\anima\.cache\packages\ext\six\1.12.0\platform-windows\arch-AMD64\os-windows-10.0.17134\python-2.7

Invoking custom build system...

--------------------------------------------------------------------------------
Building variant 1 (2/2)...
--------------------------------------------------------------------------------
16:50:44 INFO     Applying preprocess function package_preprocess_function
16:50:44 INFO     Package attributes were changed in preprocessing:
Added attributes: ['config']
Resolving build environment: globals-0.0.5+ core_pipeline-1.2+ nuke-11
resolved by manima@toy.fritz.box, on Thu Apr 18 16:50:44 2019, using Rez v2.29.0

requested packages:
globals-0.0.5+
core_pipeline-1.2+
nuke-11
~platform==windows       (implicit)
~arch==AMD64             (implicit)
~os==windows-10.0.17134  (implicit)

resolved packages:
Qt.py-1.1.0            C:\Users\manima\Dropbox\dev\anima\.cache\packages\ext\Qt.py\1.1.0\platform-windows\arch-AMD64\os-windows-10.0.17134\python-2.7
arch-AMD64             C:\Users\manima\packages\arch\AMD64                                                                                             (local)
core_pipeline-1.2.0    C:\Users\manima\Dropbox\dev\anima\.cache\packages\int\core_pipeline\1.2.0
globals-0.0.6          C:\Users\manima\packages\int\globals\0.0.6
nuke-11.3.2            C:\Users\manima\packages\ext\nuke\11.3.2
os-windows-10.0.17134  C:\Users\manima\packages\os\windows-10.0.17134                                                                                  (local)
platform-windows       C:\Users\manima\packages\platform\windows                                                                                       (local)
python-2.7.14          C:\Users\manima\packages\python\2.7.14\platform-windows\arch-AMD64\os-windows-10.0.17134                                        (local)
six-1.12.0             C:\Users\manima\Dropbox\dev\anima\.cache\packages\ext\six\1.12.0\platform-windows\arch-AMD64\os-windows-10.0.17134\python-2.7

Invoking custom build system...
Traceback (most recent call last):
  File "c:\Python27\Lib\runpy.py", line 174, in _run_module_as_main
    "__main__", fname, loader, pkg_name)
  File "c:\Python27\Lib\runpy.py", line 72, in _run_code
    exec code in run_globals
  File "C:\Users\manima\Dropbox\dev\anima\rez2\Scripts\rez\rez.exe\__main__.py", line 2, in <module>
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rez\cli\_main.py", line 144, in run
    returncode = run_cmd()
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rez\cli\_main.py", line 136, in run_cmd
    return opts.func(opts, opts.parser, extra_arg_groups)
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rez\cli\build.py", line 155, in command
    variants=opts.variants)
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rezplugins\build_process\local.py", line 41, in build
    install=install)
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rez\build_process_.py", line 197, in visit_variants
    result = func(variant, **kwargs)
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rezplugins\build_process\local.py", line 280, in _build_variant
    variant.install(install_path)
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rez\packages_.py", line 401, in install
    overrides=overrides)
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rezplugins\package_repository\filesystem.py", line 608, in install_variant
    variant = _create_variant()
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rezplugins\package_repository\filesystem.py", line 601, in _create_variant
    overrides=overrides
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rezplugins\package_repository\filesystem.py", line 1056, in _create_variant
    dump_package_data(package_data, buf=f, format_=package_format)
  File "c:\Python27\Lib\contextlib.py", line 24, in __exit__
    self.gen.next()
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rez\serialise.py", line 68, in open_file_for_write
    f.write(content)
  File "c:\Python27\Lib\contextlib.py", line 24, in __exit__
    self.gen.next()
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rez\vendor\atomicwrites\__init__.py", line 154, in _open
    self.commit(f)
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rez\vendor\atomicwrites\__init__.py", line 185, in commit
    replace_atomic(f.name, self._path)
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rez\vendor\atomicwrites\__init__.py", line 92, in replace_atomic
    return _replace_atomic(src, dst)
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rez\vendor\atomicwrites\__init__.py", line 75, in _replace_atomic
    _windows_default_flags | _MOVEFILE_REPLACE_EXISTING
  File "c:\users\manima\dropbox\dev\anima\rez2\lib\site-packages\rez-2.29.0-py2.7.egg\rez\vendor\atomicwrites\__init__.py", line 70, in _handle_errors
    raise WinError()
WindowsError: [Error 5] Access is denied.

Confirmed with this minimal reproducible.

$ rez python
Python 2.7.14 (v2.7.14:84471935ed, Sep 16 2017, 20:25:58) [MSC v.1500 64 bit (AMD64)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>> import os
>>> import stat
>>> package_file_mode = (stat.S_IRUSR | stat.S_IRGRP | stat.S_IROTH)
>>> with open("test.txt", "w") as f:
...   f.write("Test")
...
>>> os.chmod("test.txt", package_file_mode)
>>> with open("test.txt", "w") as f:
...   pass
...
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
IOError: [Errno 13] Permission denied: 'test.txt'

They aren't supported on Windows, and result in read-only file permissions which cannot be overwritten and breaks building of variants amongst others, see https://docs.python.org/2/library/os.html#os.chmod
Cosmetics
@mottosso
Copy link
Contributor Author

This also fixes the issue on Windows whereby you cannot rez build --install the same version twice, as you can on Linux.

Before

$ rez build --install
$ rez build --install
WindowsError: [Error 5] Access is denied.

After

$ rez build --install
$ rez build --install
$ rez build --install

@instinct-vfx
Copy link
Contributor

instinct-vfx commented Apr 23, 2019

I can confirm this being an issue and also being a regression. It was introduced in this commit: 3c861b4#diff-104ec3e25911699423194e63a835d25d

But it seems that this was intenionally added to explicitly set the file to read only. So i wonder if the fix must happen elsewhere to be really consistent?

@instinct-vfx
Copy link
Contributor

So after thinking a bit about this i think the general idea is to handle setting it readable before modifications. There seem to be one or more decorators that do that (one is @make_path_writeable).

Hence i am wondering if maybe the solution should be to fix the functions that make the path writeable again instead of not making the path read-only in the first place. Personally i don't care about the path or files being read-only as we enforce permissions on the share level already, but i think this is still worth evaluating. @nerdvegas could you give some insight on the idea behind these changes? They are kind of recent.

@mottosso
Copy link
Contributor Author

Hence i am wondering if maybe the solution should be to fix the functions that make the path writeable again instead of not making the path read-only in the first place.

Agreed.

Since making this PR, despite the permissions being set to writable on Windows, I've still had issues with package.py files becoming read-only from somewhere else. I'm unsure of whether it's Rez, or even Git or some Windows indexing service. It happens sporadically, and my workaround has been this.

    for attempt in range(2):
        try:
            with atomic_write(filepath, overwrite=True) as f:
                f.write(content)

        except WindowsError as e:
            if attempt == 0:
                # `overwrite=True` of atomic_write doesn't restore
                # writability to the file being written to.
                os.chmod(filepath, stat.S_IWRITE | stat.S_IREAD)

            else:
                # Under Windows, atomic_write doesn't tell you about
                # which file actually failed.
                raise WindowsError("%s: '%s'" % (e, filepath))

Which has worked so far, but is a little backwards.. The system fighting itself.

@nerdvegas
Copy link
Contributor

nerdvegas commented Apr 26, 2019 via email

@mottosso
Copy link
Contributor Author

@nerdvegas That's actually what I found myself doing which has worked well so far. I pushed an update with this now, let me know if you'd like anything changed.

@mottosso
Copy link
Contributor Author

Didn't work having just that in place, not entirely sure why.

This was referenced May 27, 2019
@nerdvegas nerdvegas added the os:windows Windows-specific label Jun 2, 2019
@nerdvegas nerdvegas merged commit f91f029 into AcademySoftwareFoundation:master Jun 3, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
os:windows Windows-specific
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants