def _merge(self, cc_dir): md5_hashes = {} if HASH_FILE.exists(): for line in [l.strip() for l in HASH_FILE.read_text().split("\n")]: if line: values = line.rsplit(":", maxsplit=1) if len(values) == 2 and values[0] and values[1]: md5_hashes[values[0]] = values[1] try: p = subprocess.run( "git -C \"{cc_dir}\" status --porcelain -uall".format( **locals()), shell=True, stdout=subprocess.PIPE, check=True) merge_files = [] status = str(p.stdout, "utf-8").strip() for line in [s.strip() for s in status.split("\n")]: if line: merge_files.append(tuple(line.split())) except subprocess.CalledProcessError as err: raise nicfit.CommandError(str(err)) for st, file in merge_files + self.args.extra_merge: dst = Path(file) src = cc_dir / dst hasher = md5() try: hasher.update(src.read_bytes()) except FileNotFoundError as notfound: perr(notfound) continue md5sum = hasher.hexdigest() merge_file = (self.args.ignore_md5s or file not in md5_hashes or md5sum != md5_hashes[file]) pout("Comparing {} hash({}): {}".format( file, md5sum, Fg.blue("new") if merge_file else Fg.green("merged"))) md5_hashes[file] = md5sum if merge_file: tmp_dst = None if not dst.exists(): tmp_dst = NamedTemporaryFile("w", suffix=dst.suffix, delete=False) # Write the file to exist on disk for diff and merge tmp_dst.close() tmp_dst = Path(tmp_dst.name) dst_file = str(dst if tmp_dst is None else tmp_dst) diffs = subprocess.run("diff '{src}' '{dst_file}' >/dev/null" .format(**locals()), shell=True)\ .returncode != 0 pout("Differences: {}".format(diffs)) if diffs: merge_cmd = self.args.merge_cmd if merge_cmd is None: for cmd, opts in MERGE_TOOLS.items(): if shutil.which(cmd): merge_cmd = " ".join([cmd, opts or ""]) break if merge_cmd is not None: subprocess.run( "{merge_cmd} '{src}' '{dst_file}'".format( **locals()), shell=True, check=True) else: perr("Merge disabled, no merge command found. Install " "a merge tool such as: {tools}.\nOr use " "--merge-cmd to specify your own.".format( tools=", ".join(MERGE_TOOLS.keys()))) if tmp_dst and tmp_dst.stat().st_size == 0: tmp_dst.unlink() elif tmp_dst: # Move tmp file into place and create parent dirs if not dst.parent.exists(): dst.parent.mkdir(0o755, parents=True) shutil.move(str(tmp_dst), str(dst)) with HASH_FILE.open("w") as hash_file: for f in sorted(md5_hashes.keys()): hash_file.write("{}:{}\n".format(f, md5_hashes[f]))