def link(conf, args): '''Link all files in the repo directory to their configured locations.''' # load our machine id so we know which files to link machine_id = config.get_machine_id() # map all file paths to their destination configs for this machine links = {} for path in os.listdir(constants.REPO_DIR): path = util.normalize_to_root(path, constants.REPO_DIR) is_hidden = util.is_hidden(path) is_ignored = path in conf['ignore'] if not is_hidden and not is_ignored: # load the config for the given path file_config = config.get_file_config(path, conf['destination']) # if the file belongs on this machine, store its config if config.machine_matches(machine_id, file_config['machines']): links[path] = file_config # find the longest link basename for pretty output formatting max_src_width = 0 if len(links) > 0: max_src_width = max(len(os.path.basename(k)) for k in links.keys()) # link the files to their destination(s) link_symbol = ' -> ' for src, info in links.iteritems(): msg = os.path.basename(src).rjust(max_src_width) msg += color.grey(link_symbol) for i, dest in enumerate(info['paths']): # the color of the link destination, different when we're creating a new # link, overwriting a link, and overwriting a normal file. dest_color = 'green' if os.path.lexists(dest): dest_color = 'cyan' if not os.path.islink(dest): dest_color = 'yellow' # do the symlink unless we're doing a dry run if not args.test: # overwrite links only by default, everything if forcing overwrite = True if args.force else None util.symlink(dest, src, overwrite=overwrite) # pad the left space if we're not the first item, since items with # multiple destinations are all under the same link name and symbol. if i > 0: msg += os.linesep msg += ' ' * (max_src_width + len(link_symbol)) msg += color.colored(dest, dest_color) print(msg) # return the created links for good measure return links
def get_file_config(path, dest): ''' Return a normalized config for the given path. If a config file exists for the given path, returns its contents instead and skips parsing. ''' # normalize our path to the destination directory first path = util.normalize_to_root(path, dest) # immediately return the config as written if one exists config = load_file_config_file(path, dest) if config is not None: return config # otherwise, parse and return the file name itself return parse_file_config(path, dest)
def normalize_file_config(config, dest): '''Turn a file config into a normalized variant.''' # an empty config with all the expected keys result = { 'paths': [], 'machines': [], } if 'paths' in config: # normalize all paths names to our destination directory paths = [util.normalize_to_root(p, dest) for p in set(config['paths'])] result['paths'] = sorted(paths) if 'machines' in config: result['machines'] = sorted(frozenset(config['machines'])) return result