1#!/usr/bin/env python 2 3from __future__ import print_function 4 5import os 6import os.path 7import subprocess 8 9import util 10 11# 12# Utility Functions 13# 14 15def _assert_same_inodes(path1, path2): 16 assert os.path.exists(path1), "missing hard-linked-file {p}".format(p=path1) 17 assert os.path.exists(path1), "missing hard-linked-file {p}".format(p=path2) 18 stat1 = os.lstat(path1) 19 stat2 = os.lstat(path2) 20 assert stat1.st_ino == stat2.st_ino, "inodes do not match for hard-linked files \"{p1}\" and \"{p2}\"".format(p1=path1, p2=path2) 21 22 23# 24# Test Cases 25# 26 27def hard_link_in_directory(filename): 28 with util.directory_created("hardlink_scratch") as directory: 29 util.touch(os.path.join(directory, "a")) 30 os.link(os.path.join(directory, "a"), os.path.join(directory, "b")) 31 32 with util.archive_created("hardlink_archive.xar", "hardlink_scratch") as path: 33 with util.directory_created("hardlink_extracted") as extracted: 34 subprocess.check_call(["xar", "-x", "-C", extracted, "-f", path]) 35 _assert_same_inodes(os.path.join(extracted, "hardlink_scratch", "a"), os.path.join(extracted, "hardlink_scratch", "b")) 36 37def hard_link_in_cwd(filename): 38 with util.directory_created("hardlink_scratch") as directory: 39 with util.chdir(directory): 40 util.touch("a") 41 os.link("a", "b") 42 with util.archive_created(os.path.join("..", "hardlink_archive.xar"), ".") as path: 43 with util.directory_created(os.path.join("..", "hardlink_extracted")) as extracted: 44 subprocess.check_call(["xar", "-x", "-C", extracted, "-f", path]) 45 _assert_same_inodes(os.path.join(extracted, "a"), os.path.join(extracted, "b")) 46 47def hard_link_identical_files(filename): 48 with util.directory_created("hardlink_scratch") as directory: 49 with open(os.path.join(directory, "a"), "w") as f: 50 f.write("1234samecontent") 51 with open(os.path.join(directory, "b"), "w") as f: 52 f.write("1234samecontent") 53 with util.archive_created("hardlink_archive.xar", "hardlink_scratch", "--link-same") as path: 54 with util.directory_created("hardlink_extracted") as extracted: 55 subprocess.check_call(["xar", "-x", "-C", extracted, "-f", path]) 56 _assert_same_inodes(os.path.join(extracted, "hardlink_scratch", "a"), os.path.join(extracted, "hardlink_scratch", "b")) 57 58TEST_CASES = (hard_link_in_directory, hard_link_in_cwd, hard_link_identical_files) 59 60if __name__ == "__main__": 61 for case in TEST_CASES: 62 try: 63 case("{f}.xar".format(f=case.func_name)) 64 print("PASSED: {f}".format(f=case.func_name)) 65 except (AssertionError, IOError, subprocess.CalledProcessError): 66 import sys, os 67 print("FAILED: {f}".format(f=case.func_name)) 68 sys.excepthook(*sys.exc_info()) 69 print("") 70