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
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)
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)
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
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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)
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
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)
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)
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)
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)
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)
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)
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
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)
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)
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)
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))
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)
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)