Example #1
0
    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]))