Skip to content

Commit

Permalink
Fix: conan config install - overwrite read-only files / don't copy …
Browse files Browse the repository at this point in the history
…file permissions (#7004)

* `conan config install` - overwrite read-only files

* `conan config install` - shouldn't copy file permission

* use `conans.util.files.remove()` to remove file

* use `conans.util.files` to make file read only
  • Loading branch information
e-i-n-s committed May 13, 2020
1 parent 90e6d64 commit 364e2ce
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 9 deletions.
7 changes: 4 additions & 3 deletions conans/client/conf/config_installer.py
@@ -1,6 +1,7 @@
import json
import os
import shutil
import stat
from datetime import datetime
from dateutil.tz import gettz

Expand All @@ -14,7 +15,7 @@
from conans.client.tools import Git
from conans.client.tools.files import unzip
from conans.errors import ConanException
from conans.util.files import mkdir, rmdir, walk, save, touch
from conans.util.files import mkdir, rmdir, walk, save, touch, remove
from conans.client.cache.cache import ClientCache


Expand Down Expand Up @@ -80,8 +81,8 @@ def _filecopy(src, filename, dst):
src = os.path.join(src, filename)
dst = os.path.join(dst, filename)
if os.path.exists(dst):
os.remove(dst)
shutil.copy(src, dst)
remove(dst)
shutil.copyfile(src, dst)


def _process_folder(config, folder, cache, output):
Expand Down
22 changes: 20 additions & 2 deletions conans/test/functional/command/config_install_test.py
Expand Up @@ -16,8 +16,7 @@
from conans.errors import ConanException
from conans.test.utils.test_files import temp_folder
from conans.test.utils.tools import TestClient, StoppableThreadBottle
from conans.util.files import load, mkdir, save, save_files

from conans.util.files import load, mkdir, save, save_files, make_file_read_only

win_profile = """[settings]
os: Windows
Expand Down Expand Up @@ -528,6 +527,25 @@ def get_zip():
self.assertIn("Unzipping", self.client.out)
http_server.stop()

def test_overwrite_read_only_file(self):
source_folder = self._create_profile_folder()
self.client.run('config install "%s"' % source_folder)
# make existing settings.yml read-only
make_file_read_only(self.client.cache.settings_path)
self.assertFalse(os.access(self.client.cache.settings_path, os.W_OK))

# config install should overwrite the existing read-only file
self.client.run('config install "%s"' % source_folder)
self.assertTrue(os.access(self.client.cache.settings_path, os.W_OK))

def test_dont_copy_file_permissions(self):
source_folder = self._create_profile_folder()
# make source settings.yml read-only
make_file_read_only(os.path.join(source_folder, 'remotes.txt'))

self.client.run('config install "%s"' % source_folder)
self.assertTrue(os.access(self.client.cache.settings_path, os.W_OK))


class ConfigInstallSchedTest(unittest.TestCase):

Expand Down
12 changes: 8 additions & 4 deletions conans/util/files.py
Expand Up @@ -31,12 +31,16 @@ def walk(top, **kwargs):
return os.walk(top, **kwargs)


def make_read_only(path):
for root, _, files in walk(path):
def make_read_only(folder_path):
for root, _, files in walk(folder_path):
for f in files:
full_path = os.path.join(root, f)
mode = os.stat(full_path).st_mode
os.chmod(full_path, mode & ~ stat.S_IWRITE)
make_file_read_only(full_path)


def make_file_read_only(file_path):
mode = os.stat(file_path).st_mode
os.chmod(file_path, mode & ~ stat.S_IWRITE)


_DIRTY_FOLDER = ".dirty"
Expand Down

0 comments on commit 364e2ce

Please sign in to comment.