From 28cb9d52afaf7a9a8939e86d16ac8991e8176ceb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Cl=C3=A9ment=20P=C3=A9au?= Date: Fri, 26 Oct 2018 11:56:23 -0400 Subject: [PATCH 1/3] Modified the solutioner.update to make sure that only the needed files are deleted during update. --- quail/constants.py | 1 + quail/solution/solutioner.py | 21 +++++++++++++++++++-- tests/test_ignore_file.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 tests/test_ignore_file.py diff --git a/quail/constants.py b/quail/constants.py index 56d542c..d02db6b 100644 --- a/quail/constants.py +++ b/quail/constants.py @@ -5,4 +5,5 @@ class Constants: ARGUMENT_RM = "--quail_rm" CHECKSUMS_FILE = ".integrity.json" INTEGRITY_IGNORE_FILE = ".integrity_ignore" + UPDATE_IGNORE_FILE = ".quailignore" diff --git a/quail/solution/solutioner.py b/quail/solution/solutioner.py index e41a136..0d705ef 100644 --- a/quail/solution/solutioner.py +++ b/quail/solution/solutioner.py @@ -1,5 +1,8 @@ import shutil import os +import glob +from quail.helper.file_ignore import FileIgnore +from quail.constants import Constants class Solutioner: @@ -35,9 +38,23 @@ def install(self): def installed(self): return os.path.exists(self.dest()) + """ + This function makes sure that all the files defined in Constants.UPDATE_IGNORE_FILE + are not deleted when the software is updating + + First parameter is the root path for the solution. We could have used self.dest() but is not + an acceptable solution for tests. + """ + def _clear_non_ignored_files(self, path): + fi = FileIgnore(path + "\\" + Constants.UPDATE_IGNORE_FILE) + result = [os.path.join(dp, f) for dp, dn, filenames in os.walk(path) for f in filenames] + files_to_remove = [item for item in result if fi.accept(item) and not item.endswith(Constants.UPDATE_IGNORE_FILE)] + for file in files_to_remove: + if os.path.exists(file): + os.remove(file) + def update(self): - # TODO: uninstall will be a waste of time on future solution types - self.uninstall() + self._clear_non_ignored_files(self.dest()) self.install() def uninstall(self): diff --git a/tests/test_ignore_file.py b/tests/test_ignore_file.py new file mode 100644 index 0000000..b8db948 --- /dev/null +++ b/tests/test_ignore_file.py @@ -0,0 +1,28 @@ +import os +import quail +from .base_test_case import BaseTestCase +from quail.constants import Constants +from quail.solution.solutioner import Solutioner + + +class TestUpdateFileIgnore(BaseTestCase): + + def setUp(self): + super().setUp() + self.solutioner = Solutioner(None, os.path.curdir) + + def test_basic_ignore(self): + os.mkdir(self.tmp("test")) + with open(self.tmp("test", "1.txt"), "a+"): + pass + with open(self.tmp("test", "2.txt"), "a+"): + pass + with open(self.tmp("test", Constants.UPDATE_IGNORE_FILE), "a+") as f: + f.write("*1.txt") + self.solutioner._clear_non_ignored_files(self.tmp("test")) + + assert os.path.exists(self.tmp("test", Constants.UPDATE_IGNORE_FILE)) + assert not os.path.exists(self.tmp("test", "2.txt")) + + +#TODO: Add multiple test with edge case From 731f1d51c96b0b4426c9e17b310a2291ad7dfdcc Mon Sep 17 00:00:00 2001 From: PEAU Clement Date: Thu, 20 Dec 2018 18:45:15 +0100 Subject: [PATCH 2/3] Have a working copy of the feature --- quail/solution/solutioner.py | 21 ++++++++++++++++++--- tests/test_ignore_file.py | 1 - 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/quail/solution/solutioner.py b/quail/solution/solutioner.py index 0d705ef..5f2b869 100644 --- a/quail/solution/solutioner.py +++ b/quail/solution/solutioner.py @@ -39,23 +39,38 @@ def installed(self): return os.path.exists(self.dest()) """ - This function makes sure that all the files defined in Constants.UPDATE_IGNORE_FILE + This function makes sure that all the files defined in the file with path=Constants.UPDATE_IGNORE_FILE are not deleted when the software is updating First parameter is the root path for the solution. We could have used self.dest() but is not an acceptable solution for tests. + TODO: Make sure that we set up the solution properly during the test, this problem should'nt happen """ def _clear_non_ignored_files(self, path): - fi = FileIgnore(path + "\\" + Constants.UPDATE_IGNORE_FILE) + fi = FileIgnore(os.path.join(path, Constants.UPDATE_IGNORE_FILE)) result = [os.path.join(dp, f) for dp, dn, filenames in os.walk(path) for f in filenames] files_to_remove = [item for item in result if fi.accept(item) and not item.endswith(Constants.UPDATE_IGNORE_FILE)] for file in files_to_remove: if os.path.exists(file): os.remove(file) + def __update_solution_files(self): + self._solution.open() + try: + if not os.path.exists(self.dest()): + os.makedirs(self.dest(), 0o777, True) + for root, dirs, files in self._solution.walk(): + for dir in dirs: + if not os.path.exists(dir): + os.makedirs(self.dest(root, dir), 0o777, True) + for file in files: + self._retrieve_file(os.path.join(root, file)) + finally: + self._solution.close() + def update(self): self._clear_non_ignored_files(self.dest()) - self.install() + self.__update_solution_files() def uninstall(self): if self.installed(): diff --git a/tests/test_ignore_file.py b/tests/test_ignore_file.py index b8db948..4035b63 100644 --- a/tests/test_ignore_file.py +++ b/tests/test_ignore_file.py @@ -1,5 +1,4 @@ import os -import quail from .base_test_case import BaseTestCase from quail.constants import Constants from quail.solution.solutioner import Solutioner From c8ae759db593000e0f662dfb43c6ddac3082cdd6 Mon Sep 17 00:00:00 2001 From: Clement Peau Date: Wed, 22 May 2019 17:35:56 -0400 Subject: [PATCH 3/3] Fixed the update method, during the update, files specified in the quailignore file will not get overwritten. --- quail/helper/file_ignore.py | 2 +- quail/solution/solutioner.py | 27 ++++++--------------------- tests/test_ignore_file.py | 17 +---------------- tests/test_solution_local.py | 1 - 4 files changed, 8 insertions(+), 39 deletions(-) diff --git a/quail/helper/file_ignore.py b/quail/helper/file_ignore.py index c3af954..5dbed54 100644 --- a/quail/helper/file_ignore.py +++ b/quail/helper/file_ignore.py @@ -31,5 +31,5 @@ def __init__(self, file_path): except FileNotFoundError: self._ignore_list = [] - def accept(self, path): + def is_file_ignored(self, path): return accept_path(path, self._ignore_list) diff --git a/quail/solution/solutioner.py b/quail/solution/solutioner.py index 5f2b869..d982e3c 100644 --- a/quail/solution/solutioner.py +++ b/quail/solution/solutioner.py @@ -38,38 +38,23 @@ def install(self): def installed(self): return os.path.exists(self.dest()) - """ - This function makes sure that all the files defined in the file with path=Constants.UPDATE_IGNORE_FILE - are not deleted when the software is updating - - First parameter is the root path for the solution. We could have used self.dest() but is not - an acceptable solution for tests. - TODO: Make sure that we set up the solution properly during the test, this problem should'nt happen - """ - def _clear_non_ignored_files(self, path): - fi = FileIgnore(os.path.join(path, Constants.UPDATE_IGNORE_FILE)) - result = [os.path.join(dp, f) for dp, dn, filenames in os.walk(path) for f in filenames] - files_to_remove = [item for item in result if fi.accept(item) and not item.endswith(Constants.UPDATE_IGNORE_FILE)] - for file in files_to_remove: - if os.path.exists(file): - os.remove(file) - def __update_solution_files(self): self._solution.open() + fi = FileIgnore(os.path.join(self.dest(), Constants.UPDATE_IGNORE_FILE)) try: if not os.path.exists(self.dest()): os.makedirs(self.dest(), 0o777, True) for root, dirs, files in self._solution.walk(): - for dir in dirs: - if not os.path.exists(dir): - os.makedirs(self.dest(root, dir), 0o777, True) + for d in dirs: + if not os.path.exists(d): + os.makedirs(self.dest(root, d), 0o777, True) for file in files: - self._retrieve_file(os.path.join(root, file)) + if not fi.is_file_ignored(file): + self._retrieve_file(os.path.join(root, file)) finally: self._solution.close() def update(self): - self._clear_non_ignored_files(self.dest()) self.__update_solution_files() def uninstall(self): diff --git a/tests/test_ignore_file.py b/tests/test_ignore_file.py index 4035b63..a93fb73 100644 --- a/tests/test_ignore_file.py +++ b/tests/test_ignore_file.py @@ -1,6 +1,7 @@ import os from .base_test_case import BaseTestCase from quail.constants import Constants +import quail from quail.solution.solutioner import Solutioner @@ -9,19 +10,3 @@ class TestUpdateFileIgnore(BaseTestCase): def setUp(self): super().setUp() self.solutioner = Solutioner(None, os.path.curdir) - - def test_basic_ignore(self): - os.mkdir(self.tmp("test")) - with open(self.tmp("test", "1.txt"), "a+"): - pass - with open(self.tmp("test", "2.txt"), "a+"): - pass - with open(self.tmp("test", Constants.UPDATE_IGNORE_FILE), "a+") as f: - f.write("*1.txt") - self.solutioner._clear_non_ignored_files(self.tmp("test")) - - assert os.path.exists(self.tmp("test", Constants.UPDATE_IGNORE_FILE)) - assert not os.path.exists(self.tmp("test", "2.txt")) - - -#TODO: Add multiple test with edge case diff --git a/tests/test_solution_local.py b/tests/test_solution_local.py index 02c86cd..9ff4f6d 100644 --- a/tests/test_solution_local.py +++ b/tests/test_solution_local.py @@ -1,4 +1,3 @@ - import os import quail from .base_test_solution import BaseTestSolution