def test_no_change(tmp_path) -> None: """ Test that `State.has_changed` returns `False` if the content has not changed. """ path = tmp_path.joinpath("content") path.write_text("Initial content") state = calculate_state(path) updated_state = calculate_state(path) assert state.has_changed(updated_state) == False
def test_changed_different_content(tmp_path) -> None: """ Test that `State.has_changed` returns `True` if the content has changed. """ path = tmp_path.joinpath("content") path.write_text("Initial content") state = calculate_state(path) path.write_text("New content") updated_state = calculate_state(path) assert state.has_changed(updated_state) == True
def test_changed_content_same_length(tmp_path) -> None: """ Test that `State.has_changed` is able to detect changes when the new content is of the same length as the original content. """ path = tmp_path.joinpath("content") path.write_text("abcdef") state = calculate_state(path) path.write_text("abcdeg") updated_state = calculate_state(path) assert state.has_changed(updated_state) == True
def test_changed_content_rewritten(tmp_path) -> None: """ Test that `State.has_changed` returns `False` if the file has been modified, even when the actual contents has not (e.g it has been re-written with the exact same content). """ path = tmp_path.joinpath("content") content = "This is the content of this file." path.write_text(content) state = calculate_state(path) # Write the same content to the file. path.write_text(content) updated_state = calculate_state(path) assert state.has_changed(updated_state) == False
def changes(self) -> Change: """ Finds items that have changed in the repository. Yields ----- A `Change` in the repository. """ for entry in self.content_paths(): logging.debug(f"Checking path: {entry}") relativized = entry.relative_to(self.__root_path) stored_state = self.__state_store.get_state(relativized) state_on_system = calculate_state(path=entry) if stored_state is None: # The entry has not yet been stored in the state. logging.debug(f"No state available for path. {entry} is new.") yield Change(repository_root=self.__root_path, item=relativized, previous_state=None, new_state=state_on_system, state_store=self.__state_store) else: if stored_state.has_changed(other=state_on_system): logging.debug(f"State of file {entry} has changed") item_state = calculate_state(entry) yield Change(repository_root=self.__root_path, item=relativized, previous_state=stored_state, new_state=item_state, state_store=self.__state_store) # Search for items in the store that have been deleted. Since the above # loop has handled the case where the item still exists but has been # modified, this only has to handle the case where items have been # deleted from the repository. for entry in self.__state_store.stored_items(): item_path = self.__root_path.joinpath(entry) if not item_path.exists(): stored_state = self.__state_store.get_state(entry) yield Change(repository_root=self.__root_path, item=entry, previous_state=stored_state, new_state=None, state_store=self.__state_store)
def test_calculate_state(sample) -> None: calculated = state.calculate_state(path=sample["path"]) # We can only safely verify the size and hash values. expected = {"size": sample["size"], "hash": sample["hash"]} actual = {"size": calculated.size, "hash": calculated.content_hash} assert actual == expected