| 
					
				 | 
			
			
				@@ -3,7 +3,6 @@ import io 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import json 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import os 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import shutil 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-import socket 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import stat 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import subprocess 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 import sys 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -39,13 +38,7 @@ from ...remote import RemoteRepository, PathNotAllowed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from ...repository import Repository 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from .. import has_lchflags, llfuse 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 from .. import BaseTestCase, changedir, environment_variable 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-from .. import ( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    are_symlinks_supported, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    are_hardlinks_supported, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    are_fifos_supported, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    is_utime_fully_supported, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    is_birthtime_fully_supported, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+from .. import are_symlinks_supported, are_hardlinks_supported, are_fifos_supported 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 RK_ENCRYPTION = "--encryption=repokey-aes-ocb" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 KF_ENCRYPTION = "--encryption=keyfile-chacha20-poly1305" 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -376,90 +369,6 @@ class ArchiverTestCase(ArchiverTestCaseBase): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         repository_id = bin_to_hex(self._extract_repository_id(self.repository_path)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         return get_security_dir(repository_id) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_basic_functionality(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        have_root = self.create_test_files() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # fork required to test show-rc output 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION, "--show-version", "--show-rc", fork=True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("borgbackup version", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("terminating with success status, rc 0", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "--exclude-nodump", "test", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", "create", "--exclude-nodump", "--stats", "test.2", "input" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("Archive name: test.2", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with changedir("output"): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd(f"--repo={self.repository_location}", "extract", "test") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        list_output = self.cmd(f"--repo={self.repository_location}", "rlist", "--short") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("test", list_output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("test.2", list_output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        expected = [ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input/bdev", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input/cdev", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input/dir2", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input/dir2/file2", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input/empty", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input/file1", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input/flagfile", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if are_fifos_supported(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            expected.append("input/fifo1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if are_symlinks_supported(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            expected.append("input/link1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if are_hardlinks_supported(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            expected.append("input/hardlink") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if not have_root: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            # we could not create these device files without (fake)root 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            expected.remove("input/bdev") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            expected.remove("input/cdev") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if has_lchflags: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            # remove the file we did not backup, so input and output become equal 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            expected.remove("input/flagfile")  # this file is UF_NODUMP 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            os.remove(os.path.join("input", "flagfile")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        list_output = self.cmd(f"--repo={self.repository_location}", "list", "test", "--short") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for name in expected: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.assert_in(name, list_output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_dirs_equal("input", "output/input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        info_output = self.cmd(f"--repo={self.repository_location}", "info", "-a", "test") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        item_count = 5 if has_lchflags else 6  # one file is UF_NODUMP 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("Number of files: %d" % item_count, info_output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        shutil.rmtree(self.cache_path) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        info_output2 = self.cmd(f"--repo={self.repository_location}", "info", "-a", "test") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        def filter(output): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            # filter for interesting "info" output, ignore cache rebuilding related stuff 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            prefixes = ["Name:", "Fingerprint:", "Number of files:", "This archive:", "All archives:", "Chunk index:"] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            result = [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            for line in output.splitlines(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                for prefix in prefixes: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                    if line.startswith(prefix): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                        result.append(line) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return "\n".join(result) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # the interesting parts of info_output2 and info_output should be same 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_equal(filter(info_output), filter(info_output2)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @requires_hardlinks 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_duplicate_root(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # setup for #5603 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        path_a = os.path.join(self.input_path, "a") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        path_b = os.path.join(self.input_path, "b") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        os.mkdir(path_a) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        os.mkdir(path_b) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        hl_a = os.path.join(path_a, "hardlink") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        hl_b = os.path.join(path_b, "hardlink") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file(hl_a, contents=b"123456") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        os.link(hl_a, hl_b) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", "--encryption=none") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "test", "input", "input")  # give input twice! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # test if created archive has 'input' contents twice: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        archive_list = self.cmd(f"--repo={self.repository_location}", "list", "test", "--json-lines") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        paths = [json.loads(line)["path"] for line in archive_list.split("\n") if line] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # we have all fs items exactly once! 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert sorted(paths) == ["input", "input/a", "input/a/hardlink", "input/b", "input/b/hardlink"] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     def test_init_parent_dirs(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         parent_path = os.path.join(self.tmpdir, "parent1", "parent2") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         repository_path = os.path.join(parent_path, "repository") 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -471,41 +380,6 @@ class ArchiverTestCase(ArchiverTestCaseBase): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.cmd(f"--repo={repository_location}", "rcreate", "--encryption=none", "--make-parent-dirs") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         assert os.path.exists(parent_path) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_unix_socket(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            sock = socket.socket(socket.AF_UNIX, socket.SOCK_STREAM) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            sock.bind(os.path.join(self.input_path, "unix-socket")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        except PermissionError as err: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            if err.errno == errno.EPERM: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                pytest.skip("unix sockets disabled or not supported") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            elif err.errno == errno.EACCES: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                pytest.skip("permission denied to create unix sockets") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "test", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        sock.close() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with changedir("output"): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd(f"--repo={self.repository_location}", "extract", "test") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            assert not os.path.exists("input/unix-socket") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @pytest.mark.skipif(not is_utime_fully_supported(), reason="cannot properly setup and execute test without utime") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @pytest.mark.skipif( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        not is_birthtime_fully_supported(), reason="cannot properly setup and execute test without birthtime" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_nobirthtime(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_test_files() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        birthtime, mtime, atime = 946598400, 946684800, 946771200 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        os.utime("input/file1", (atime, birthtime)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        os.utime("input/file1", (atime, mtime)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "test", "input", "--nobirthtime") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with changedir("output"): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd(f"--repo={self.repository_location}", "extract", "test") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        sti = os.stat("input/file1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        sto = os.stat("output/input/file1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert int(sti.st_birthtime * 1e9) == birthtime * 1e9 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert int(sto.st_birthtime * 1e9) == mtime * 1e9 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert sti.st_mtime_ns == sto.st_mtime_ns == mtime * 1e9 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     def test_repository_swap_detection(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.create_test_files() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         os.environ["BORG_PASSPHRASE"] = "passphrase" 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -638,351 +512,6 @@ class ArchiverTestCase(ArchiverTestCaseBase): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         with environment_variable(BORG_UNKNOWN_UNENCRYPTED_REPO_ACCESS_IS_OK="yes"): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             self.cmd(f"--repo={self.repository_location}", "rinfo") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_stdin(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        input_data = b"\x00foo\n\nbar\n   \n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "test", "-", input=input_data) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        item = json.loads(self.cmd(f"--repo={self.repository_location}", "list", "test", "--json-lines")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert item["uid"] == 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert item["gid"] == 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert item["size"] == len(input_data) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert item["path"] == "stdin" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        extracted_data = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", "extract", "test", "--stdout", binary_output=True 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert extracted_data == input_data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_content_from_command(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        input_data = "some test content" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        name = "a/b/c" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "create", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--stdin-name", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            name, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--content-from-command", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "test", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "echo", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            input_data, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        item = json.loads(self.cmd(f"--repo={self.repository_location}", "list", "test", "--json-lines")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert item["uid"] == 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert item["gid"] == 0 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert item["size"] == len(input_data) + 1  # `echo` adds newline 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert item["path"] == name 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        extracted_data = self.cmd(f"--repo={self.repository_location}", "extract", "test", "--stdout") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert extracted_data == input_data + "\n" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_content_from_command_with_failed_command(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "create", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--content-from-command", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "test", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "sh", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "-c", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "exit 73;", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            exit_code=2, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert output.endswith("Command 'sh' exited with status 73\n") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        archive_list = json.loads(self.cmd(f"--repo={self.repository_location}", "rlist", "--json")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert archive_list["archives"] == [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_content_from_command_missing_command(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "test", "--content-from-command", exit_code=2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert output.endswith("No command given.\n") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_paths_from_stdin(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("dir1/file2", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("dir1/file3", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file4", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        input_data = b"input/file1\0input/dir1\0input/file4" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "create", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "test", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--paths-from-stdin", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--paths-delimiter", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "\\0", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            input=input_data, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        archive_list = self.cmd(f"--repo={self.repository_location}", "list", "test", "--json-lines") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        paths = [json.loads(line)["path"] for line in archive_list.split("\n") if line] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert paths == ["input/file1", "input/dir1", "input/file4"] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_paths_from_command(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file2", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file3", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file4", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        input_data = "input/file1\ninput/file2\ninput/file3" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", "create", "--paths-from-command", "test", "--", "echo", input_data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        archive_list = self.cmd(f"--repo={self.repository_location}", "list", "test", "--json-lines") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        paths = [json.loads(line)["path"] for line in archive_list.split("\n") if line] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert paths == ["input/file1", "input/file2", "input/file3"] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_paths_from_command_with_failed_command(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "create", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--paths-from-command", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "test", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "sh", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "-c", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "exit 73;", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            exit_code=2, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert output.endswith("Command 'sh' exited with status 73\n") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        archive_list = json.loads(self.cmd(f"--repo={self.repository_location}", "rlist", "--json")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert archive_list["archives"] == [] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_paths_from_command_missing_command(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "test", "--paths-from-command", exit_code=2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert output.endswith("No command given.\n") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_without_root(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """test create without a root""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "test", exit_code=2) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_pattern_root(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """test create with only a root pattern""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file2", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "test", "-v", "--list", "--pattern=R input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/file2", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_pattern(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """test file patterns during create""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file2", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file_important", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "create", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "-v", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--list", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--pattern=+input/file_important", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--pattern=-input/file*", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "test", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/file_important", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("x input/file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("x input/file2", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_pattern_file(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """test file patterns during create""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file2", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("otherfile", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file_important", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "create", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "-v", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--list", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--pattern=-input/otherfile", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--patterns-from=" + self.patterns_file_path, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "test", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/file_important", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("x input/file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("x input/file2", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("x input/otherfile", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_pattern_exclude_folder_but_recurse(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """test when patterns exclude a parent folder, but include a child""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.patterns_file_path2 = os.path.join(self.tmpdir, "patterns2") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with open(self.patterns_file_path2, "wb") as fd: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            fd.write(b"+ input/x/b\n- input/x*\n") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("x/a/foo_a", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("x/b/foo_b", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("y/foo_y", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "create", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "-v", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--list", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--patterns-from=" + self.patterns_file_path2, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "test", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("x input/x/a/foo_a", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/x/b/foo_b", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/y/foo_y", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_pattern_exclude_folder_no_recurse(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """test when patterns exclude a parent folder and, but include a child""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.patterns_file_path2 = os.path.join(self.tmpdir, "patterns2") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with open(self.patterns_file_path2, "wb") as fd: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            fd.write(b"+ input/x/b\n! input/x*\n") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("x/a/foo_a", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("x/b/foo_b", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("y/foo_y", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "create", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "-v", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--list", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--patterns-from=" + self.patterns_file_path2, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "test", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_not_in("input/x/a/foo_a", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_not_in("input/x/a", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/y/foo_y", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_pattern_intermediate_folders_first(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """test that intermediate folders appear first when patterns exclude a parent folder but include a child""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.patterns_file_path2 = os.path.join(self.tmpdir, "patterns2") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with open(self.patterns_file_path2, "wb") as fd: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            fd.write(b"+ input/x/a\n+ input/x/b\n- input/x*\n") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("x/a/foo_a", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("x/b/foo_b", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with changedir("input"): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                f"--repo={self.repository_location}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "create", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "--patterns-from=" + self.patterns_file_path2, 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                "test", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                ".", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # list the archive and verify that the "intermediate" folders appear before 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # their contents 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        out = self.cmd(f"--repo={self.repository_location}", "list", "test", "--format", "{type} {path}{NL}") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        out_list = out.splitlines() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("d x/a", out_list) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("d x/b", out_list) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert out_list.index("d x/a") < out_list.index("- x/a/foo_a") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert out_list.index("d x/b") < out_list.index("- x/b/foo_b") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_no_cache_sync(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_test_files() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rdelete", "--cache-only") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        create_json = json.loads( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                f"--repo={self.repository_location}", "create", "--no-cache-sync", "--json", "--error", "test", "input" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        )  # ignore experimental warning 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        info_json = json.loads(self.cmd(f"--repo={self.repository_location}", "info", "-a", "test", "--json")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        create_stats = create_json["cache"]["stats"] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        info_stats = info_json["cache"]["stats"] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert create_stats == info_stats 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rdelete", "--cache-only") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "--no-cache-sync", "test2", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rinfo") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "check") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_archivename_with_placeholder(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_test_files() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ts = "1999-12-31T23:59:59" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        name_given = "test-{now}"  # placeholder in archive name gets replaced by borg 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        name_expected = f"test-{ts}"  # placeholder in f-string gets replaced by python 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", f"--timestamp={ts}", name_given, "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        list_output = self.cmd(f"--repo={self.repository_location}", "rlist", "--short") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert name_expected in list_output 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_exclude_caches(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self._create_test_caches() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "test", "input", "--exclude-caches") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self._assert_test_caches() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_exclude_tagged(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self._create_test_tagged() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "create", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "test", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--exclude-if-present", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ".NOBACKUP", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--exclude-if-present", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "00-NOBACKUP", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self._assert_test_tagged() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_exclude_keep_tagged(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self._create_test_keep_tagged() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "create", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "test", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--exclude-if-present", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ".NOBACKUP1", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--exclude-if-present", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            ".NOBACKUP2", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--exclude-caches", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--keep-exclude-tags", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self._assert_test_keep_tagged() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_path_normalization(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("dir1/dir2/file", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with changedir("input/dir1/dir2"): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd(f"--repo={self.repository_location}", "create", "test", "../../../input/dir1/../dir1/dir2/..") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "list", "test") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_not_in("..", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in(" input/dir1/dir2/file", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_exclude_normalization(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file2", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with changedir("input"): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd(f"--repo={self.repository_location}", "create", "test1", ".", "--exclude=file1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with changedir("output"): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd(f"--repo={self.repository_location}", "extract", "test1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_equal(sorted(os.listdir("output")), ["file2"]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with changedir("input"): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd(f"--repo={self.repository_location}", "create", "test2", ".", "--exclude=./file1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with changedir("output"): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd(f"--repo={self.repository_location}", "extract", "test2") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_equal(sorted(os.listdir("output")), ["file2"]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "test3", "input", "--exclude=input/./file1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with changedir("output"): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd(f"--repo={self.repository_location}", "extract", "test3") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_equal(sorted(os.listdir("output/input")), ["file2"]) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_repeated_files(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "test", "input", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     def test_corrupted_repository(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.create_src_archive("test") 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -998,22 +527,6 @@ class ArchiverTestCase(ArchiverTestCaseBase): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         output = self.cmd(f"--repo={self.repository_location}", "check", "--info", exit_code=1) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         self.assert_in("Starting repository check", output)  # --info given for root logger 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @pytest.mark.skipif("BORG_TESTS_IGNORE_MODES" in os.environ, reason="modes unreliable") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_umask(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "test", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        mode = os.stat(self.repository_path).st_mode 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assertEqual(stat.S_IMODE(mode), 0o700) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_dry_run(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "--dry-run", "test", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # Make sure no archive has been created 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with Repository(self.repository_path) as repository: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            manifest = Manifest.load(repository, Manifest.NO_OPERATION_CHECK) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_equal(len(manifest.archives), 0) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     def add_unknown_feature(self, operation): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         with Repository(self.repository_path, exclusive=True) as repository: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             manifest = Manifest.load(repository, Manifest.NO_OPERATION_CHECK) 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -1122,231 +635,6 @@ class ArchiverTestCase(ArchiverTestCaseBase): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             with Cache(repository, manifest) as cache: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				                 assert cache.cache_config.mandatory_features == set() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_progress_on(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "test4", "input", "--progress") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("\r", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_progress_off(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "test5", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_not_in("\r", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_file_status(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """test that various file status show expected results 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        clearly incomplete: only tests for the weird "unchanged" status for now""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        time.sleep(1)  # file2 must have newer timestamps than file1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file2", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "--list", "test", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/file2", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # should find first file as unmodified 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "--list", "test2", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("U input/file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # this is expected, although surprising, for why, see: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # https://borgbackup.readthedocs.org/en/latest/faq.html#i-am-seeing-a-added-status-for-a-unchanged-file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/file2", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_file_status_cs_cache_mode(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """test that a changed file with faked "previous" mtime still gets backed up in ctime,size cache_mode""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", contents=b"123") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        time.sleep(1)  # file2 must have newer timestamps than file1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file2", size=10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", "create", "test1", "input", "--list", "--files-cache=ctime,size" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # modify file1, but cheat with the mtime (and atime) and also keep same size: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        st = os.stat("input/file1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", contents=b"321") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        os.utime("input/file1", ns=(st.st_atime_ns, st.st_mtime_ns)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # this mode uses ctime for change detection, so it should find file1 as modified 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", "create", "test2", "input", "--list", "--files-cache=ctime,size" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("M input/file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_file_status_ms_cache_mode(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """test that a chmod'ed file with no content changes does not get chunked again in mtime,size cache_mode""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        time.sleep(1)  # file2 must have newer timestamps than file1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file2", size=10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", "create", "--list", "--files-cache=mtime,size", "test1", "input" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # change mode of file1, no content change: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        st = os.stat("input/file1") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        os.chmod("input/file1", st.st_mode ^ stat.S_IRWXO)  # this triggers a ctime change, but mtime is unchanged 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # this mode uses mtime for change detection, so it should find file1 as unmodified 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", "create", "--list", "--files-cache=mtime,size", "test2", "input" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("U input/file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_file_status_rc_cache_mode(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """test that files get rechunked unconditionally in rechunk,ctime cache mode""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        time.sleep(1)  # file2 must have newer timestamps than file1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file2", size=10) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", "create", "--list", "--files-cache=rechunk,ctime", "test1", "input" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # no changes here, but this mode rechunks unconditionally 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", "create", "--list", "--files-cache=rechunk,ctime", "test2", "input" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_file_status_excluded(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        """test that excluded paths are listed""" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        time.sleep(1)  # file2 must have newer timestamps than file1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file2", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if has_lchflags: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.create_regular_file("file3", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            platform.set_flags(os.path.join(self.input_path, "file3"), stat.UF_NODUMP) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "--list", "--exclude-nodump", "test", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("A input/file2", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if has_lchflags: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.assert_in("x input/file3", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # should find second file as excluded 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "create", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "test1", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "input", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--list", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--exclude-nodump", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "--exclude", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            "*/file2", 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("U input/file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("x input/file2", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if has_lchflags: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.assert_in("x input/file3", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_json(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        create_info = json.loads(self.cmd(f"--repo={self.repository_location}", "create", "--json", "test", "input")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # The usual keys 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert "encryption" in create_info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert "repository" in create_info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert "cache" in create_info 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert "last_modified" in create_info["repository"] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        archive = create_info["archive"] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert archive["name"] == "test" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert isinstance(archive["command_line"], list) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert isinstance(archive["duration"], float) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert len(archive["id"]) == 64 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert "stats" in archive 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_topical(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        time.sleep(1)  # file2 must have newer timestamps than file1 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file2", size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # no listing by default 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "test", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_not_in("file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # shouldn't be listed even if unchanged 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "test0", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_not_in("file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # should list the file as unchanged 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "test1", "input", "--list", "--filter=U") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # should *not* list the file as changed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "test2", "input", "--list", "--filter=AM") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_not_in("file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # change the file 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_regular_file("file1", size=1024 * 100) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        # should list the file as changed 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "create", "test3", "input", "--list", "--filter=AM") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.assert_in("file1", output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    @pytest.mark.skipif(not are_fifos_supported(), reason="FIFOs not supported") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_read_special_symlink(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        from threading import Thread 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        def fifo_feeder(fifo_fn, data): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            fd = os.open(fifo_fn, os.O_WRONLY) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                os.write(fd, data) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            finally: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                os.close(fd) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        data = b"foobar" * 1000 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        fifo_fn = os.path.join(self.input_path, "fifo") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        link_fn = os.path.join(self.input_path, "link_fifo") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        os.mkfifo(fifo_fn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        os.symlink(fifo_fn, link_fn) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        t = Thread(target=fifo_feeder, args=(fifo_fn, data)) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        t.start() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        try: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd(f"--repo={self.repository_location}", "create", "--read-special", "test", "input/link_fifo") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        finally: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            t.join() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        with changedir("output"): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            self.cmd(f"--repo={self.repository_location}", "extract", "test") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            fifo_fn = "input/link_fifo" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            with open(fifo_fn, "rb") as f: 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-                extracted_data = f.read() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert extracted_data == data 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_create_read_special_broken_symlink(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        os.symlink("somewhere does not exist", os.path.join(self.input_path, "link")) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "create", "--read-special", "test", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        output = self.cmd(f"--repo={self.repository_location}", "list", "test") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert "input/link -> somewhere does not exist" in output 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    # def test_cmdline_compatibility(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    #    self.create_regular_file('file1', size=1024 * 80) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    #    self.cmd(f'--repo={self.repository_location}', 'rcreate', RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    #    self.cmd(f'--repo={self.repository_location}', 'create', 'test', 'input') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    #    output = self.cmd('foo', self.repository_location, '--old') 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    #    self.assert_in('"--old" has been deprecated. Use "--new" instead', output) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_log_json(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_test_files() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        log = self.cmd( 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            f"--repo={self.repository_location}", "create", "test", "input", "--log-json", "--list", "--debug" 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        ) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        messages = {}  # type -> message, one of each kind 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        for line in log.splitlines(): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            msg = json.loads(line) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            messages[msg["type"]] = msg 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        file_status = messages["file_status"] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert "status" in file_status 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert file_status["path"].startswith("input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        log_message = messages["log_message"] 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert isinstance(log_message["time"], float) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert log_message["levelname"] == "DEBUG"  # there should only be DEBUG messages 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert isinstance(log_message["message"], str) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    def test_common_options(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.create_test_files() 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        self.cmd(f"--repo={self.repository_location}", "rcreate", RK_ENCRYPTION) 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        log = self.cmd(f"--repo={self.repository_location}", "--debug", "create", "test", "input") 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        assert "security: read previous location" in log 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     def test_init_interrupt(self): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         def raise_eof(*args, **kwargs): 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             raise EOFError 
			 |