def test_diff_manifest_add_file_last(test_data, testname, monkeypatch): """Diff two fileinfo lists, one having an additional file as last item. The implementation of the corresponding command line tool used to have a flaw in this particular case, ref. #55. """ monkeypatch.chdir(test_data) with Archive().open(Path("archive.tar")) as archive: manifest_ref = archive.manifest base_dir = Path("base") mtime_base = os.stat(base_dir).st_mtime p = base_dir / "zzz.dat" shutil.copy(gettestdata("rnd2.dat"), p) os.utime(base_dir, times=(mtime_base, mtime_base)) fileinfos = get_fileinfos(base_dir) diff = list(filter(non_match, diff_manifest(fileinfos, manifest_ref))) assert len(diff) == 1 status, fi_a, fi_b = diff[0] assert status == DiffStatus.MISSING_B assert fi_a.type == 'f' assert fi_a.path == p assert fi_b is None diff = list(filter(non_match, diff_manifest(manifest_ref, fileinfos))) assert len(diff) == 1 status, fi_a, fi_b = diff[0] assert status == DiffStatus.MISSING_A assert fi_b.type == 'f' assert fi_b.path == p assert fi_a is None
def test_diff_manifest_mult(test_data, testname, monkeypatch): """Diff two fileinfo lists having multiple differences. """ monkeypatch.chdir(test_data) with Archive().open(Path("archive.tar")) as archive: manifest_ref = archive.manifest base_dir = Path("base") mtime_base = os.stat(base_dir).st_mtime mtime_data = os.stat(base_dir / "data").st_mtime pm = base_dir / "data" / "rnd.dat" shutil.copy(gettestdata("rnd2.dat"), pm) p1 = base_dir / "msg.txt" p2 = base_dir / "o.txt" p1.rename(p2) os.utime(base_dir, times=(mtime_base, mtime_base)) os.utime(base_dir / "data", times=(mtime_data, mtime_data)) fileinfos = get_fileinfos(base_dir) diff = list(filter(non_match, diff_manifest(fileinfos, manifest_ref))) assert len(diff) == 3 status, fi_a, fi_b = diff[0] assert status == DiffStatus.CONTENT assert fi_a.type == fi_b.type == 'f' assert fi_a.path == fi_b.path == pm status, fi_a, fi_b = diff[1] assert status == DiffStatus.MISSING_A assert fi_b.type == 'f' assert fi_b.path == p1 assert fi_a is None status, fi_a, fi_b = diff[2] assert status == DiffStatus.MISSING_B assert fi_a.type == 'f' assert fi_a.path == p2 assert fi_b is None
def test_diff_manifest_missing_files(test_data, testname, monkeypatch): """Diff two fileinfo lists having one file's name changed. """ monkeypatch.chdir(test_data) with Archive().open(Path("archive.tar")) as archive: manifest_ref = archive.manifest base_dir = Path("base") mtime_base = os.stat(base_dir).st_mtime p1 = base_dir / "rnd.dat" p2 = base_dir / "a.dat" p1.rename(p2) os.utime(base_dir, times=(mtime_base, mtime_base)) fileinfos = get_fileinfos(base_dir) diff = list(filter(non_match, diff_manifest(fileinfos, manifest_ref))) assert len(diff) == 2 status, fi_a, fi_b = diff[0] assert status == DiffStatus.MISSING_B assert fi_a.type == 'f' assert fi_a.path == p2 assert fi_b is None status, fi_a, fi_b = diff[1] assert status == DiffStatus.MISSING_A assert fi_b.type == 'f' assert fi_b.path == p1 assert fi_a is None
def test_diff_manifest_equal(test_data, testname, monkeypatch): """Diff two fileinfo lists having equal content. """ monkeypatch.chdir(test_data) with Archive().open(Path("archive.tar")) as archive: manifest_ref = archive.manifest base_dir = Path("base") fileinfos = get_fileinfos(base_dir) diff = list(filter(non_match, diff_manifest(fileinfos, manifest_ref))) assert diff == []
def test_diff_manifest_metadata(test_data, testname, monkeypatch): """Diff two fileinfo lists having one file's metadata modified. """ monkeypatch.chdir(test_data) with Archive().open(Path("archive.tar")) as archive: manifest_ref = archive.manifest base_dir = Path("base") p = base_dir / "rnd.dat" p.chmod(0o0444) fileinfos = get_fileinfos(base_dir) diff = list(filter(non_match, diff_manifest(fileinfos, manifest_ref))) assert len(diff) == 1 status, fi_a, fi_b = diff[0] assert status == DiffStatus.META assert fi_a.type == fi_b.type == 'f' assert fi_a.path == fi_b.path == p
def test_diff_manifest_modified_file(test_data, testname, monkeypatch): """Diff two fileinfo lists having one file's content modified. """ monkeypatch.chdir(test_data) with Archive().open(Path("archive.tar")) as archive: manifest_ref = archive.manifest base_dir = Path("base") mtime_base = os.stat(base_dir).st_mtime p = base_dir / "rnd.dat" shutil.copy(gettestdata("rnd2.dat"), p) os.utime(base_dir, times=(mtime_base, mtime_base)) fileinfos = get_fileinfos(base_dir) diff = list(filter(non_match, diff_manifest(fileinfos, manifest_ref))) assert len(diff) == 1 status, fi_a, fi_b = diff[0] assert status == DiffStatus.CONTENT assert fi_a.type == fi_b.type == 'f' assert fi_a.path == fi_b.path == p
def test_diff_manifest_symlink_target(test_data, testname, monkeypatch): """Diff two fileinfo lists having one symlink's target modified. """ monkeypatch.chdir(test_data) with Archive().open(Path("archive.tar")) as archive: manifest_ref = archive.manifest base_dir = Path("base") mtime_base = os.stat(base_dir).st_mtime p = base_dir / "s.dat" p.unlink() p.symlink_to(Path("msg.txt")) os.utime(base_dir, times=(mtime_base, mtime_base)) fileinfos = get_fileinfos(base_dir) diff = list(filter(non_match, diff_manifest(fileinfos, manifest_ref))) assert len(diff) == 1 status, fi_a, fi_b = diff[0] assert status == DiffStatus.SYMLNK_TARGET assert fi_a.type == fi_b.type == 'l' assert fi_a.path == fi_b.path == p
def test_diff_manifest_wrong_type(test_data, testname, monkeypatch): """Diff two fileinfo lists with one entry having a wrong type. """ monkeypatch.chdir(test_data) with Archive().open(Path("archive.tar")) as archive: manifest_ref = archive.manifest base_dir = Path("base") mtime_base = os.stat(base_dir).st_mtime p = base_dir / "rnd.dat" p.unlink() p.symlink_to(Path("data", "rnd.dat")) os.utime(base_dir, times=(mtime_base, mtime_base)) fileinfos = get_fileinfos(base_dir) diff = list(filter(non_match, diff_manifest(fileinfos, manifest_ref))) assert len(diff) == 1 status, fi_a, fi_b = diff[0] assert status == DiffStatus.TYPE assert fi_a.type == 'l' assert fi_b.type == 'f' assert fi_a.path == fi_b.path == p
def test_diff_manifest_dircontent(test_data, testname, monkeypatch): """Diff two fileinfo lists with one subdirectory missing. """ monkeypatch.chdir(test_data) with Archive().open(Path("archive.tar")) as archive: manifest_ref = archive.manifest base_dir = Path("base") mtime_base = os.stat(base_dir).st_mtime pd = base_dir / "data" shutil.rmtree(pd) os.utime(base_dir, times=(mtime_base, mtime_base)) fileinfos = get_fileinfos(base_dir) diff = list(filter(non_match, diff_manifest(fileinfos, manifest_ref))) assert len(diff) == 2 status, fi_a, fi_b = diff[0] assert status == DiffStatus.MISSING_A assert fi_b.type == 'd' assert fi_b.path == pd assert fi_a is None status, fi_a, fi_b = diff[1] assert status == DiffStatus.MISSING_A assert fi_b.type == 'f' assert fi_b.path == pd / "rnd.dat" assert fi_a is None
def diff(args): archive1 = Archive().open(args.archive1) manifest1 = archive1.manifest archive1.close() archive2 = Archive().open(args.archive2) manifest2 = archive2.manifest archive2.close() algorithm = _common_checksum(manifest1, manifest2) diff = diff_manifest(manifest1, manifest2, algorithm) if args.skip_dir_content: diff = _skip_dir_filter(diff) status = 0 for diff_stat, fi1, fi2 in diff: if diff_stat == DiffStatus.MISSING_A: print("Only in %s: %s" % (args.archive2, fi2.path)) status = max(status, 102) elif diff_stat == DiffStatus.MISSING_B: print("Only in %s: %s" % (args.archive1, fi1.path)) status = max(status, 102) elif diff_stat == DiffStatus.TYPE: print("Entries %s:%s and %s:%s have different type" % (args.archive1, fi1.path, args.archive2, fi2.path)) status = max(status, 102) elif diff_stat == DiffStatus.SYMLNK_TARGET: print("Symbol links %s:%s and %s:%s have different target" % (args.archive1, fi1.path, args.archive2, fi2.path)) status = max(status, 101) elif diff_stat == DiffStatus.CONTENT: print("Files %s:%s and %s:%s differ" % (args.archive1, fi1.path, args.archive2, fi2.path)) status = max(status, 101) elif diff_stat == DiffStatus.META and args.report_meta: print("File system metadata for %s:%s and %s:%s differ" % (args.archive1, fi1.path, args.archive2, fi2.path)) status = max(status, 100) return status
def filter_fileinfos(base, fileinfos, algorithm): for stat, fi1, fi2 in diff_manifest(base, fileinfos, algorithm): if stat == DiffStatus.MISSING_B or stat == DiffStatus.MATCH: continue yield fi2