Пример #1
0
def make_commit(repo: RepositoryContractWrapper, commit_message: str):
    ipfs = ipfshttpclient.connect()

    filepaths = []
    ipfs_hashes = []

    for root, dirs, files in os.walk("./"):
        for name in files:
            filepath = os.path.join(root, name)

            if filepath == "./.repodata.json":
                continue

            print(filepath)

            filepaths.append(filepath)
            ipfs_hashes.append(ipfs.add(filepath)["Hash"])

    print(f"filepaths = {filepaths}")
    print(f"ipfs_hashes = {ipfs_hashes}")
    print(f"current_branch = {current_branch}")

    repo.make_commit(filepaths, ipfs_hashes, current_branch, current_commit, comment=commit_message)
    commit_id = repo.most_recent_commit(current_branch)

    with open("./.repodata.json", "r") as infile:
        repodata = json.load(infile)

    repodata["current_commit_id"] = commit_id

    with open("./.repodata.json", "w") as outfile:
        json.dump(repodata, outfile)
Пример #2
0
def checkout(repo: RepositoryContractWrapper, branch_id: int):
    with open("./.repodata.json", "r") as infile:
        repodata = json.load(infile)

    commit_id = repo.most_recent_commit(branch_id)

    fetch(repo, commit_id)

    repodata["current_branch_id"] = branch_id
    repodata["current_commit_id"] = commit_id

    with open("./.repodata.json", "w") as outfile:
        json.dump(repodata, outfile)
Пример #3
0
def three_way_merge(repo: RepositoryContractWrapper, child_branch, comment):

    # Get the list of commits on the parent branch
    parent_head_commit = repo.most_recent_commit(current_branch)
    parent_head_history = get_history(repo, parent_head_commit)

    # Get the list of commits on the child branch
    child_head_commit = repo.most_recent_commit(child_branch)
    child_head_history = get_history(repo, child_head_commit)

    # Find the common ancestor
    common_ancestor_commit = max(set(parent_head_history) & set(child_head_history))

    # Get the list of file hashes/file paths
    parent_head_files = get_all_files_from_commit(repo, parent_head_commit)
    child_head_files = get_all_files_from_commit(repo, child_head_commit)
    common_ancestor_files = get_all_files_from_commit(repo, common_ancestor_commit)

    # Convert into dictionaries of file_path:ipfs_hash
    parent_head_files = dict(map(lambda x: x[:2], parent_head_files))
    child_head_files = dict(map(lambda x: x[:2], child_head_files))
    common_ancestor_files = dict(map(lambda x: x[:2], common_ancestor_files))

    # list which is going to contain the resulting merge of both commits
    resulting_files = {}

    merge_conflict = False

    for file in parent_head_files.keys() | child_head_files.keys():
        parent_hash = parent_head_files.get(file, None)
        child_hash = child_head_files.get(file, None)
        ancestor_hash = common_ancestor_files.get(file, None)

        if parent_hash == child_hash:
            # Both branches are equal here
            if parent_hash != None:
                resulting_files[file] = parent_hash
        elif parent_hash == ancestor_hash and parent_hash != child_hash:
            # the file has been updated on the child branch but not on the parent branch
            # we take the updates on the child branch
            resulting_files[file] = child_hash
        elif child_hash == ancestor_hash and parent_hash != child_hash:
            # the file has been updated on the parent branch but not on the child branch
            # we take the updates on the parent branch
            resulting_files[file] = parent_hash
        elif parent_hash != child_hash and parent_hash != ancestor_hash and ancestor_hash != child_hash:
            # the same file in both parent and child have been updated independantly causing a merge conflict

            ipfs = ipfshttpclient.connect()

            # write the 3 different copies into temp so that the diff3 program can read them
            with open("/tmp/PARENT", "wb") as outfile:
                outfile.write(ipfs.cat(parent_hash))
            with open("/tmp/CHILD", "wb") as outfile:
                outfile.write(ipfs.cat(child_hash))
            with open("/tmp/BASE", "wb") as outfile:
                outfile.write(ipfs.cat(ancestor_hash))

            process = Popen(["diff3", "-m", "/tmp/PARENT", "/tmp/BASE", "/tmp/CHILD"], stdout=PIPE)
            (output, err) = process.communicate()
            exit_code = process.wait()

            if exit_code == 0:
                #diff3 successfully merged the files together

                # upload the merged file to ipfs
                filehash = ipfs.add_bytes(output)

                # use the merged file hash
                resulting_files[file] = filehash

                pass
            elif exit_code == 1:
                #diff3 could not merge the files together
                print(f"WARNING: could not resolve conflict in file {file}")
                merge_conflict=True
        else:
            # I've missed something here
            raise Exception

    # Return early if there has been a merge conflict
    if merge_conflict == True:
        print("ERROR: Merge Conflicts Detected. Merge Aborted")
        return

    # Convert dictionary into 2 lists
    resulting_files = list(zip(*resulting_files.items()))

    # Create a multi parent commit
    repo.make_commit_multiparent(resulting_files[0], resulting_files[1], current_branch, parent_head_commit, child_head_commit, comment)

    # Update the directory
    fetch(repo, repo.most_recent_commit(current_branch))

    print("Merge Completed")
Пример #4
0
def squash_merge(repo: RepositoryContractWrapper, child_branch, comment):
    if comment is None:
        comment = f"Squash Merge From Branch ID {child_branch}"
    repo.squash_merge(current_branch, child_branch, comment)
    current_commit = repo.most_recent_commit(current_branch)