Example #1
0
def write_tree(gitdir: pathlib.Path,
               index: tp.List[GitIndexEntry],
               dirname: str = "") -> str:
    # PUT YOUR CODE HERE
    content = b""
    for entry in index:
        if "/" in entry.name:
            content += b"40000 "
            ford = entry.name[:entry.name.find("/")]
            content += ford.encode() + b"\0"
            sha_of = b""
            sha_of += oct(entry.mode)[2:].encode() + b" "
            ford1 = entry.name[entry.name.find("/") + 1:]
            sha_of += ford1.encode() + b"\0"
            sha_of += entry.sha1
            sha_of_end = hash_object(sha_of, "tree", True)
            print("sha_of_end is " + sha_of_end)
            content += bytes.fromhex(sha_of_end)
        else:
            content += oct(entry.mode)[2:].encode() + b" "
            content += entry.name.encode() + b"\0"
            content += entry.sha1
            print(entry.sha1)
    tree = hash_object(content, "tree", True)
    return tree
Example #2
0
def write_tree(gitdir: pathlib.Path, index: tp.List[GitIndexEntry], dirname: str = "") -> str:
    tree_entries = []
    for entry in index:
        _, name = os.path.split(entry.name)
        if dirname:
            names = dirname.split(os.sep)
        else:
            names = entry.name.split(os.sep)
        if len(names) != 1:
            prefix = names[0]
            name = f"{os.sep}".join(names[1:])
            rights = "40000"
            tree_entry = f"{rights} {prefix}\0".encode()
            tree_entry += bytes.fromhex(write_tree(gitdir, index, name))
            tree_entries.append(tree_entry)
        else:
            if dirname and entry.name.find(dirname) == -1:
                continue
            with open(entry.name, "rb") as content:
                data = content.read()
            rights = str(oct(entry.mode))[2:]
            tree_entry = f"{rights} {name}\0".encode()
            tree_entry += bytes.fromhex(hash_object(data, "blob", write=True))
            tree_entries.append(tree_entry)

    tree_binary = b"".join(tree_entries)
    return hash_object(tree_binary, "tree", write=True)
Example #3
0
def write_tree(gitdir: pathlib.Path,
               index: tp.List[GitIndexEntry],
               dirname: str = "") -> str:
    tree_inputs = []
    for entry in index:
        _, title = os.path.split(entry.name)
        if dirname:
            titles = dirname.split("/")
        else:
            titles = entry.name.split("/")
        if len(titles) != 1:
            prefix = titles[0]
            title = f"/".join(titles[1:])
            mode = "40000"
            tree_input = f"{mode} {prefix}\0".encode()
            tree_input += bytes.fromhex(write_tree(gitdir, index, title))
            tree_inputs.append(tree_input)
        else:
            if dirname and entry.name.find(dirname) == -1:
                continue
            with open(entry.name, "rb") as file:
                info = file.read()
            mode = str(oct(entry.mode))[2:]
            tree_input = f"{mode} {title}\0".encode()
            tree_input += bytes.fromhex(hash_object(info, "blob", write=True))
            tree_inputs.append(tree_input)

    tree_binary = b"".join(tree_inputs)
    return hash_object(tree_binary, "tree", write=True)
Example #4
0
def write_tree(gitdir: pathlib.Path,
               index: tp.List[GitIndexEntry],
               current_path: str = "") -> str:
    full_tree = b''
    for entry in index:
        if current_path and entry.name.find(current_path) == -1:
            continue
        current_path_elements = current_path.split(
            '/') if current_path else entry.name.split('/')

        if len(current_path_elements) > 1:
            current_dir_name = current_path_elements[0]
            mode = '40000'
            tree_element = f'{mode} {current_dir_name}\0'.encode()
            one_level_deeper_path = '/'.join(current_path_elements[1:])
            deeper_tree_hash = bytes.fromhex(
                write_tree(gitdir, index, one_level_deeper_path))
            tree_element += deeper_tree_hash
        else:
            with open(entry.name, "rb") as entry_file:
                entry_data = entry_file.read()
                sha = bytes.fromhex(hash_object(entry_data, "blob",
                                                write=True))
            mode = str(oct(entry.mode))[2:]
            name = current_path_elements[0]
            tree_element = f"{mode} {name}\0".encode()
            tree_element += sha
        full_tree += tree_element

    full_tree_hash = hash_object(full_tree, 'tree', True)
    return full_tree_hash
Example #5
0
    def test_hash_object_twice(self):
        _ = repo.repo_create(".")

        contents = "that's what she said"
        data = contents.encode()
        expected_sha = "7e774cf533c51803125d4659f3488bd9dffc41a6"
        sha = objects.hash_object(data, fmt="blob", write=True)
        self.assertEqual(expected_sha, sha)
        sha = objects.hash_object(data, fmt="blob", write=True)
        self.assertEqual(expected_sha, sha)
Example #6
0
def write_tree(gitdir: pathlib.Path,
               index: tp.List[GitIndexEntry],
               dirname: str = "") -> str:
    tree_content: tp.List[tp.Tuple[int, pathlib.Path, bytes]] = []
    subtrees: tp.Dict[str, tp.List[GitIndexEntry]] = dict()
    files = [str(x) for x in (gitdir.parent / dirname).glob("*")]
    for entry in index:
        if entry.name in files:
            tree_content.append(
                (entry.mode, (gitdir.parent / entry.name), entry.sha1))
        else:
            dirs_name = entry.name.lstrip(dirname).split("/", 1)[0]
            if not dirs_name in subtrees:
                subtrees[dirs_name] = []
            subtrees[dirs_name].append(entry)
    for name in subtrees:
        stat = (gitdir.parent / dirname / name).stat()
        tree_content.append((
            0o40000,
            gitdir.parent / dirname / name,
            bytes.fromhex(
                write_tree(
                    gitdir,
                    subtrees[name],
                    dirname + "/" + name if dirname != "" else name,
                )),
        ))
    tree_content.sort(key=lambda x: x[1])
    data = b"".join(f"{elem[0]:o} {elem[1].name}".encode() + b"\00" + elem[2]
                    for elem in tree_content)
    return hash_object(data, "tree", write=True)
Example #7
0
def commit_tree(
    gitdir: pathlib.Path,
    tree: str,
    message: str,
    parent: tp.Optional[str] = None,
    author: tp.Optional[str] = None,
) -> str:
    if author is None and "GIT_AUTHOR_NAME" in os.environ and "GIT_AUTHOR_EMAIL" in os.environ:
        author = (
            os.getenv("GIT_AUTHOR_NAME", None)  # type:ignore
            + " "  # type:ignore
            + f'<{os.getenv("GIT_AUTHOR_EMAIL", None)}>'  # type:ignore
        )  # type:ignore
    if time.timezone > 0:
        timezone = "-"
    else:
        timezone = "+"
    timezone += f"{abs(time.timezone) // 60 // 60:02}{abs(time.timezone) // 60 % 60:02}"
    data = [f"tree {tree}"]
    if parent is not None:
        data.append(f"parent {parent}")
    data.append(
        f"author {author} {int(time.mktime(time.localtime()))} {timezone}")
    data.append(
        f"committer {author} {int(time.mktime(time.localtime()))} {timezone}")
    data.append(f"\n{message}\n")
    return hash_object("\n".join(data).encode(), "commit", write=True)
Example #8
0
def commit_tree(
        gitdir: pathlib.Path,
        tree: str,
        message: str,
        parent: tp.Optional[str] = None,
        author: tp.Optional[str] = "Dementiy <*****@*****.**>",
) -> str:
    """
    :version: 0.6.0

    """
    if (
            author is None
            and "GIT_AUTHOR_NAME" in os.environ
            and "GIT_AUTHOR_EMAIL" in os.environ
    ):
        get_name = os.getenv("GIT_AUTHOR_NAME")
        get_email = os.getenv("GIT_AUTHOR_EMAIL")
        author = f"""{get_name} <{get_email}>"""

    absolute = abs(time.timezone) // 60
    localtime = int(time.mktime(time.localtime()))
    sign = '-' if time.timezone > 0 else '+'
    times = f"{absolute // 60:02}{absolute % 60:02}"
    timezone = sign + times
    data = [
        f"tree {tree}",
        f"parent {parent}" if parent is not None else "",
        f"author {author} {localtime} {timezone}",
        f"committer {author} {localtime} {timezone}",
        f"\n{message}\n"
    ]
    data = '\n'.join([x for x in data if x != ""])

    return hash_object(data.encode(), "commit", write=True)
Example #9
0
def write_tree(gitdir: pathlib.Path, index: tp.List[GitIndexEntry], dirname: str = "") -> str:
    tree_content = b''
    for entry in index:
        if '/' in entry.name:
            tree_content += b"40000 "
            dir_name = entry.name[:entry.name.find('/')]
            tree_content += dir_name.encode() + b'\0'
            subdir_file = str(entry.mode).encode() + b" "
            subdir_file += entry.name[entry.name.find("/") + 1:].encode() + b"\0"
            subdir_file += entry.sha1
            file_hash = hash_object(subdir_file, fmt="tree", write=True)
            tree_content += bytes.fromhex(file_hash)
        else:
            record = f'{entry.mode} {entry.name}\0'.encode() + entry.sha1
            tree_content += record
    return hash_object(tree_content, 'tree', True)
Example #10
0
def update_index(gitdir: pathlib.Path,
                 paths: tp.List[pathlib.Path],
                 write: bool = True) -> None:
    entries = []
    for el in paths:
        try:
            f = el.open()
            file_content = f.read()
        except:
            raise Exception("Wrong path")

        sha1 = hash_object(file_content.encode(), "blob", True)
        stat = os.stat(el)

        entries.append(
            GitIndexEntry(ctime_s=int(stat.st_ctime),
                          ctime_n=0,
                          mtime_s=int(stat.st_mtime),
                          mtime_n=0,
                          dev=stat.st_dev,
                          ino=stat.st_ino,
                          mode=stat.st_mode,
                          uid=stat.st_uid,
                          gid=stat.st_gid,
                          size=stat.st_size,
                          sha1=bytes.fromhex(sha1),
                          flags=7,
                          name=str(el)))
    entries = sorted(entries, key=lambda x: x.name)
    if not (gitdir / "index").exists():
        write_index(gitdir, entries)
    else:
        index = read_index(gitdir)
        index += entries
        write_index(gitdir, index)
Example #11
0
def update_index(gitdir: pathlib.Path,
                 paths: tp.List[pathlib.Path],
                 write: bool = True) -> None:
    entries = read_index(gitdir)

    for path in paths:
        stat = path.stat()
        with open(path, "rb") as f:
            entry = GitIndexEntry(
                ctime_s=int(stat.st_ctime),
                ctime_n=0,
                mtime_s=int(stat.st_mtime),
                mtime_n=0,
                dev=stat.st_dev,
                ino=stat.st_ino,
                mode=stat.st_mode,
                uid=stat.st_uid,
                gid=stat.st_uid,
                size=stat.st_size,
                sha1=bytes.fromhex(hash_object(f.read(), "blob", write=write)),
                flags=len(str(path)),
                name=str(path),
            )
        entries.append(entry)
    write_index(gitdir, entries)
Example #12
0
def commit_tree(
    gitdir: pathlib.Path,
    tree: str,
    message: str,
    parent: tp.Optional[str] = None,
    author: tp.Optional[str] = None,
) -> str:
    if not author:
        author = (
            os.getenv("GIT_AUTHOR_NAME") + " " +
            f"<{os.getenv('GIT_AUTHOR_EMAIL')}>"  # type: ignore
        )
    if time.timezone > 0:
        timezone = "-"
    else:
        timezone = "+"
    timezone += f"{abs(time.timezone) // 60 // 60:02}{abs(time.timezone) // 60 % 60:02}"
    info = [f"tree {tree}"]
    if parent is not None:
        info.append(f"parent{parent}")
    info.append(
        f"author {author} {int(time.mktime(time.localtime()))} {timezone}")
    info.append(
        f"committer {author} {int(time.mktime(time.localtime()))} {timezone}")
    info.append(f"\n{message}\n")
    return hash_object("\n".join(info).encode(), "commit", write=True)
Example #13
0
def commit_tree(
    gitdir: pathlib.Path,
    tree: str,
    message: str,
    parent: tp.Optional[str] = None,
    author: tp.Optional[str] = None,
) -> str:
    if "GIT_AUTHOR_NAME" in os.environ and "GIT_AUTHOR_EMAIL" in os.environ and author is None:
        author = author = f"{os.getenv('GIT_AUTHOR_NAME')} <{os.getenv('GIT_AUTHOR_EMAIL')}>"
    now = int(time.mktime(time.localtime()))
    timezone = time.timezone
    if timezone > 0:
        format_time = "-"
    else:
        format_time = "+"
    format_time += f"{abs(timezone) // 3600:02}{abs(timezone) // 60 % 60:02}"
    data_commit = []
    data_commit.append(f"tree {tree}")
    if parent is not None:
        data_commit.append(f"parent {parent}")
    data_commit.append(f"author {author} {now} {format_time}")
    data_commit.append(f"committer {author} {now} {format_time}")
    data_commit.append(f"\n{message}\n")
    data = "\n".join(data_commit).encode()
    return hash_object(data, "commit", write=True)
Example #14
0
def commit_tree(
    gitdir: pathlib.Path,
    tree: str,
    message: str,
    parent: tp.Optional[str] = None,
    author: tp.Optional[str] = None,
) -> str:

    data = [f"tree {tree}"]
    if parent:
        data.append(f"parent {parent}")
    if not author:
        name, email = os.getenv("GIT_AUTHOR_NAME"), os.getenv(
            "GIT_AUTHOR_EMAIL")
        author = "{} <{}>".format(name, email)

    zone = time.timezone
    offset = "+" if zone < 0 else "-"
    zone = abs(zone)
    zone = zone // 60
    offset += f"{zone // 60:02}"
    offset += f"{zone % 60:02}"

    local = time.localtime()
    sec = time.mktime(local)
    sec = int(sec)

    data.append(f"author {author} {sec} {offset}")
    data.append(f"committer {author} {sec} {offset}")
    data.append(f"\n{message}\n")
    encData = "\n".join(data)
    encData = encData.encode()

    return hash_object(encData, "commit", write=True)
Example #15
0
def update_index(gitdir: pathlib.Path,
                 paths: tp.List[pathlib.Path],
                 write: bool = True) -> None:
    entries = []
    for el in paths:
        f = el.open()
        str_file = f.read()
        sha1 = hash_object(str_file.encode(), "blob", write=True)
        """to_pack = bytearray.fromhex(hashlib.sha1(f.read().encode()).hexdigest())
        sha = struct.pack(">" + str(len(to_pack)) + "s", to_pack)"""
        stat = os.stat(el)
        entries.append(
            GitIndexEntry(ctime_s=int(stat.st_ctime),
                          ctime_n=0,
                          mtime_s=int(stat.st_mtime),
                          mtime_n=0,
                          dev=stat.st_dev,
                          ino=stat.st_ino,
                          mode=stat.st_mode,
                          uid=stat.st_uid,
                          gid=stat.st_gid,
                          size=stat.st_size,
                          sha1=bytes.fromhex(sha1),
                          flags=7,
                          name=str(el)))
    entries = sorted(entries, key=lambda x: x.name)
    if not (gitdir / "index").exists():
        write_index(gitdir, entries)
    else:
        index = read_index(gitdir)
        index += entries
        write_index(gitdir, index)
Example #16
0
def commit_tree(
        gitdir: pathlib.Path,
        tree: str,
        message: str,
        parent: tp.Optional[str] = None,
        author: tp.Optional[str] = None,
) -> str:
    if author is None and "GIT_AUTHOR_NAME" in os.environ and "GIT_AUTHOR_EMAIL" in os.environ:
        author = os.environ["GIT_AUTHOR_NAME"] + " " + os.environ["GIT_AUTHOR_EMAIL"]
    if author is None:
        author = "Aleksandr Piliakin [email protected]"
    time_of_commit = (
            str(int(time.mktime(time.localtime()))) + " " + str(time.strftime("%z", time.gmtime()))
    )
    store = (
            "tree "
            + tree
            + "\nauthor "
            + author
            + " "
            + time_of_commit
            + "\ncommitter "
            + author
            + " "
            + time_of_commit
            + "\n\n"
            + message
            + "\n"
    )
    return hash_object(store.encode(), "commit", True)
Example #17
0
def commit_tree(
        gitdir: pathlib.Path,
        tree: str,
        message: str,
        parent: tp.Optional[str] = None,
        author: tp.Optional[str] = None,
) -> str:
    if "GIT_DIR" not in os.environ:
        os.environ["GIT_DIR"] = ".git"
    if not author:
        author = f"{os.environ['GIT_AUTHOR_NAME']} <{os.environ['GIT_AUTHOR_EMAIL']}>"
    timestamp = int(time.mktime(time.localtime()))
    utc_offset = -time.timezone
    author_time = "{} {}{:02}{:02}".format(
        timestamp,
        "+" if utc_offset > 0 else "-",
        abs(utc_offset) // 3600,
        (abs(utc_offset) // 60) % 60,
    )
    content = f"tree {tree}\n"
    if parent:
        content += f"parent {parent}\n"
    content += f"author {author} {author_time}\ncommitter {author} {author_time}\n\n{message}\n"
    sha = hash_object(content.encode("ascii"), "commit", True)
    return sha
Example #18
0
def update_index(gitdir: pathlib.Path,
                 paths: tp.List[pathlib.Path],
                 write: bool = True) -> None:
    index = []
    for i in paths:
        with i.open("rb") as f:
            data = f.read()
        entry = GitIndexEntry(
            ctime_s=int(os.stat(i).st_ctime),
            ctime_n=0,
            mtime_s=int(os.stat(i).st_mtime),
            mtime_n=0,
            dev=os.stat(i).st_dev,
            ino=os.stat(i).st_ino,
            mode=os.stat(i).st_mode,
            uid=os.stat(i).st_uid,
            gid=os.stat(i).st_gid,
            size=os.stat(i).st_size,
            sha1=bytes.fromhex(hash_object(data, "blob", write=True)),
            flags=len(i.name),
            name=str(i),
        )
        index.append(entry)
    if write:
        index_s = sorted(index, key=lambda x: x.name)
        write_index(gitdir, index_s)
Example #19
0
def commit_tree(
        gitdir: pathlib.Path,
        tree: str,
        message: str,
        parent: tp.Optional[str] = None,
        author: tp.Optional[str] = None,
) -> str:
    content = f'tree {tree}\n'
    if parent:
        content += f'parent {parent}\n'

    _time = int(time.mktime(time.localtime()))
    timezone = "{:+}00".format(int(time.timezone / -3600)).zfill(5)

    for value in ['author', 'committer']:
        content += f'{value} '
        if author:
            content += f'{author} '
        else:
            content += f'{os.environ["GIT_AUTHOR_NAME"]} {os.environ["GIT_AUTHOR_EMAIL"]} '
        content += f'{_time} {timezone}\n'

    content += '\n'
    content += message + '\n'

    return hash_object(content.encode(), 'commit', write=True)
Example #20
0
def commit_tree(
    gitdir: pathlib.Path,
    tree: str,
    message: str,
    parent: tp.Optional[str] = None,
    author: tp.Optional[str] = None,
) -> str:
    # PUT YOUR CODE HERE
    now_bad_format = time.localtime()
    now = int(
        datetime.datetime(
            year=now_bad_format.tm_year,
            day=now_bad_format.tm_mday,
            month=now_bad_format.tm_mon,
            hour=now_bad_format.tm_hour,
            minute=now_bad_format.tm_min,
            second=now_bad_format.tm_sec,
        ).timestamp())
    tz = time.timezone
    tz_str = ("-" if tz > 0 else
              "+") + f"{abs(tz) // 3600:02}{abs(tz) // 60 % 60:02}"
    content = []
    content.append(f"tree {tree}")
    if parent is not None:
        content.append(f"parent {parent}")
    content.append(f"author {author} {now} {tz_str}")
    content.append(f"committer {author} {now} {tz_str}")
    content.append(f"\n{message}\n")
    data = "\n".join(content).encode()
    return hash_object(data, "commit", write=True)
Example #21
0
def commit_tree(
    gitdir: pathlib.Path,
    tree: str,
    message: str,
    parent: tp.Optional[str] = None,
    author: tp.Optional[str] = None,
) -> str:
    if author is None and "GIT_AUTHOR_NAME" in os.environ and "GIT_AUTHOR_EMAIL" in os.environ:
        author = (str(
            os.getenv("GIT_AUTHOR_NAME", None) + " " +
            f'<{os.getenv("GIT_AUTHOR_EMAIL", None)}>'))  # type:ignore
    now = int(time.mktime(time.localtime()))
    tz = time.timezone
    if tz > 0:
        tz_str = "-"
    else:
        tz_str = "+"
    tz_str += f"{abs(tz) // 60 // 60:02}{abs(tz) // 60 % 60:02}"
    cont = [f"tree {tree}"]
    if parent is not None:
        cont.append(f"parent {parent}")
    cont.append(f"author {author} {now} {tz_str}")
    cont.append(f"committer {author} {now} {tz_str}")
    cont.append(f"\n{message}\n")
    return hash_object("\n".join(cont).encode(), "commit", write=True)
Example #22
0
def write_tree(gitdir: pathlib.Path,
               index: tp.List[GitIndexEntry],
               dirname: str = "") -> str:

    files = []
    content: tp.List[tp.Tuple[int, str, bytes]] = []
    subtrees: tp.Dict[str, tp.List[GitIndexEntry]] = dict()
    for i in (gitdir.parent / dirname).glob("*"):
        files.append(str(i))
    for i in index:
        if i.name in files:
            content.append((i.mode, str(gitdir.parent / i.name), i.sha1))
        else:
            name = i.name.lstrip(dirname).split("/", 1)[0]
            if not name in subtrees:
                subtrees[name] = []
            subtrees[name].append(i)
    for i in subtrees:
        if dirname != "":
            content.append((
                0o40000,
                str(gitdir.parent / dirname / i),
                bytes.fromhex(
                    write_tree(gitdir, subtrees[i], dirname + "/" + i)),
            ))
        else:
            content.append((
                0o40000,
                str(gitdir.parent / dirname / i),
                bytes.fromhex(write_tree(gitdir, subtrees[i], i)),
            ))
    content.sort(key=lambda x: x[1])
    data = b"".join(f"{elem[0]:o} {elem[1].split('/')[-1]}".encode() + b"\00" +
                    elem[2] for elem in content)
    return hash_object(data, "tree", True)
Example #23
0
def update_index(gitdir: pathlib.Path, paths: tp.List[pathlib.Path], write: bool = True) -> None:
    entries = {entry.name: entry for entry in read_index(gitdir)}
    for path in paths:
        if str(path) in entries:
            del entries[str(path)]
        with path.open("rb") as f:
            data = f.read()
        stat = os.stat(path)
        sha1 = hash_object(data, "blob", write=True)
        entries.update(
            {
                str(path): GitIndexEntry(
                    ctime_s=int(stat.st_ctime),
                    ctime_n=stat.st_ctime_ns % len(str(int(stat.st_ctime))),
                    mtime_s=int(stat.st_mtime),
                    mtime_n=stat.st_mtime_ns % len(str(int(stat.st_mtime))),
                    dev=stat.st_dev,
                    ino=stat.st_ino,
                    mode=stat.st_mode,
                    uid=stat.st_uid,
                    gid=stat.st_gid,
                    size=stat.st_size,
                    sha1=bytes.fromhex(sha1),
                    flags=7,
                    name=str(path),
                )
            }
        )
    if write:
        entries_list = []
        for name in sorted(entries.keys()):
            entries_list.append(entries[name])
        write_index(gitdir, entries_list)
Example #24
0
def write_tree(gitdir: pathlib.Path, index: tp.List[GitIndexEntry], dirname: str = "") -> str:
    # PUT YOUR CODE HERE
    if "GIT_DIR" not in os.environ:
        os.environ["GIT_DIR"] = ".git"    
    last_dir = None
    current_dir = dirname
    content = b""  
    for entry in index:             
        current_name = os.path.relpath(entry.name, dirname)        
        if "/" in current_name:            
            left_slash = current_name.find("/")
            last_dir = current_dir
            current_dir = os.path.join(dirname, current_name[:left_slash])
            if last_dir != current_dir:
                entries_to_tree = []
                for possible_entry in index:
                    if possible_entry.name.startswith(current_dir):
                        entries_to_tree.append(possible_entry)
                inner_tree = write_tree(gitdir, entries_to_tree, current_dir)
                content += f"40000 {current_dir}\x00".encode("ascii")
                content += binascii.unhexlify(inner_tree)
        else:
            content += f"100644 {current_name}\x00".encode("ascii")  
            content += entry.sha1 
    tree = hash_object(content ,"tree", True)      
    return tree
Example #25
0
def update_index(gitdir: pathlib.Path,
                 paths: tp.List[pathlib.Path],
                 write: bool = True) -> None:
    # PUT YOUR CODE HERE
    entries = read_index(gitdir)
    for path in paths:
        with path.open("rb") as f:
            data = f.read()
        stat = path.stat()
        name_found = [
            x for x in range(len(entries)) if entries[x].name == str(path)
        ]
        if name_found:
            del entries[name_found[0]]
        sha1_hash = hash_object(data, "blob", write=True)
        entries.append(
            GitIndexEntry(
                ctime_s=int(stat.st_ctime),
                ctime_n=0,
                mtime_s=int(stat.st_mtime),
                mtime_n=0,
                dev=stat.st_dev,
                ino=stat.st_ino,
                mode=stat.st_mode,
                uid=stat.st_uid,
                gid=stat.st_gid,
                size=stat.st_size,
                sha1=bytes.fromhex(sha1_hash),
                flags=len(path.name),
                name=str(path),
            ))
    if write:
        entries.sort(key=lambda x: x.name)
        write_index(gitdir, entries)
Example #26
0
def update_index(gitdir: pathlib.Path,
                 paths: tp.List[pathlib.Path],
                 write: bool = True) -> None:
    index_entries = []

    gitdir_relative_paths = convert_to_relative_for_gitdir(gitdir, paths)
    gitdir_relative_paths = sorted(gitdir_relative_paths)

    for path in gitdir_relative_paths:
        with open(path, 'rb') as file:
            file_data = file.read()
        file_hash = bytes.fromhex(hash_object(file_data, 'blob', True))
        file_stats = os.stat(path)
        flags = len(str(path))
        os_file_inf = os.stat(path)
        index_class_args = (
            int(os_file_inf.st_ctime),
            0,
            int(os_file_inf.st_mtime),
            0,
            os_file_inf.st_dev,
            os_file_inf.st_ino,
            os_file_inf.st_mode,
            os_file_inf.st_uid,
            os_file_inf.st_gid,
            os_file_inf.st_size,
            file_hash,
            flags,
            str(path),
        )
        index_entry = GitIndexEntry(*index_class_args)
        index_entries.append(index_entry)

    if write:
        write_index(gitdir, index_entries)
Example #27
0
def commit_tree(
    gitdir: pathlib.Path,
    tree: str,
    message: str,
    parent: tp.Optional[str] = None,
    author: tp.Optional[str] = None,
) -> str:
    timestamp = int(time.mktime(time.localtime()))
    timezone = time.timezone if (time.localtime().tm_isdst == 0) else time.altzone
    timezone = int(timezone / 60 / 60 * -1)
    if timezone > 0:
        tz_offset = f"+0{timezone}00"
    elif timezone < 0:
        tz_offset = f"-0{timezone}00"
    else:
        tz_offset = "0000"
    author_name = os.getenv("GIT_AUTHOR_NAME")
    email = os.getenv("GIT_AUTHOR_EMAIL")
    if email or author_name:
        author = f"{author_name} <{email}>"
    data = f"tree {tree}\n"
    if parent:
        data += f"parent {parent}\n"
    data += f"author {author} {timestamp} {tz_offset}\ncommitter {author} {timestamp} {tz_offset}\n\n{message}\n"
    return hash_object(data.encode(), "commit", write=True)
Example #28
0
def update_index(gitdir: pathlib.Path,
                 paths: tp.List[pathlib.Path],
                 write: bool = True) -> None:
    entries = read_index(gitdir)
    for path in paths:
        with path.open("rb") as f:
            data = f.read()
        stat = os.stat(path)
        entries.append(
            GitIndexEntry(
                ctime_s=int(stat.st_ctime),
                ctime_n=0,
                mtime_s=int(stat.st_mtime),
                mtime_n=0,
                dev=stat.st_dev,
                ino=stat.st_ino,
                mode=stat.st_mode,
                uid=stat.st_uid,
                gid=stat.st_gid,
                size=stat.st_size,
                sha1=bytes.fromhex(hash_object(data, "blob", write=True)),
                flags=7,
                name=str(path),
            ))
    if write:
        write_index(gitdir, sorted(entries, key=lambda x: x.name))
Example #29
0
def update_index(gitdir: pathlib.Path,
                 paths: tp.List[pathlib.Path],
                 write: bool = True) -> None:
    entries = []
    for path in paths:
        with open(path, "r") as f:
            content = f.read()
        sha1 = hash_object(content.encode(), "blob", write=True)
        file = os.stat(path)
        entries.append(
            GitIndexEntry(
                ctime_s=round(file.st_ctime),
                ctime_n=0,
                mtime_s=round(file.st_mtime),
                mtime_n=0,
                dev=file.st_dev,
                ino=file.st_ino,
                mode=file.st_mode,
                uid=file.st_uid,
                gid=file.st_gid,
                size=file.st_size,
                sha1=bytes.fromhex(sha1),
                flags=len(path.name),
                name=str(path),
            ))

    if not (gitdir / "index").exists():
        write_index(gitdir, entries)
    else:
        index = read_index(gitdir)
        index += entries
        write_index(gitdir, index)
Example #30
0
def update_index(gitdir: pathlib.Path, paths: tp.List[pathlib.Path], write: bool = True) -> None:
    idx_entries: tp.List[GitIndexEntry] = []
    absolute_paths = [i.absolute() for i in paths]
    absolute_paths.sort()
    relative_paths = [i.relative_to(os.getcwd()) for i in absolute_paths]
    relative_paths.reverse()
    for path in relative_paths:
        with open(path, "rb") as f_name:
            data = f_name.read()
        obj_hash = bytes.fromhex(hash_object(data, "blob", True))
        os_stats = os.stat(path, follow_symlinks=False)
        name_len = len(str(path))
        if name_len > 0xFFF:
            name_len = 0xFFF
        flags = name_len
        idx_entry = GitIndexEntry(
            int(os_stats.st_ctime),
            0,
            int(os_stats.st_mtime),
            0,
            os_stats.st_dev,
            os_stats.st_ino,
            os_stats.st_mode,
            os_stats.st_uid,
            os_stats.st_gid,
            os_stats.st_size,
            obj_hash,
            flags,
            str(path),
        )
        if idx_entry not in idx_entries:
            idx_entries.insert(0, idx_entry)

    if write:
        write_index(gitdir, idx_entries)