1# Copyright 2017 The Chromium Authors 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""Recursively create hardlink to target named output.""" 6 7 8import argparse 9import os 10import shutil 11 12 13def CreateHardlinkHelper(target, output): 14 """Recursively create a hardlink named output pointing to target. 15 16 Args: 17 target: path to an existing file or directory 18 output: path to the newly created hardlink 19 20 This function assumes that output does not exists but that the parent 21 directory containing output does. If those conditions are false, then 22 the function will fails with an exception corresponding to an OS error. 23 """ 24 if os.path.islink(target): 25 os.symlink(os.readlink(target), output) 26 elif not os.path.isdir(target): 27 try: 28 os.link(target, output) 29 except: 30 shutil.copy(target, output) 31 else: 32 os.mkdir(output) 33 for name in os.listdir(target): 34 CreateHardlinkHelper( 35 os.path.join(target, name), 36 os.path.join(output, name)) 37 38 39def CreateHardlink(target, output): 40 """Recursively create a hardlink named output pointing to target. 41 42 Args: 43 target: path to an existing file or directory 44 output: path to the newly created hardlink 45 46 If output already exists, it is first removed. In all cases, the 47 parent directory containing output is created. 48 """ 49 if os.path.isdir(output): 50 shutil.rmtree(output) 51 elif os.path.exists(output): 52 os.unlink(output) 53 54 parent_dir = os.path.dirname(os.path.abspath(output)) 55 if not os.path.isdir(parent_dir): 56 os.makedirs(parent_dir) 57 58 CreateHardlinkHelper(target, output) 59 60 61def Main(): 62 parser = argparse.ArgumentParser() 63 parser.add_argument('target', help='path to the file or directory to link to') 64 parser.add_argument('output', help='name of the hardlink to create') 65 args = parser.parse_args() 66 67 CreateHardlink(args.target, args.output) 68 69 70if __name__ == '__main__': 71 Main() 72