Skip to content

Commit

Permalink
[refactor] add class Metadata to handle file metadata
Browse files Browse the repository at this point in the history
  • Loading branch information
smd1121 committed Jan 7, 2024
1 parent 4af50b9 commit 9918b9c
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 63 deletions.
4 changes: 2 additions & 2 deletions xgit/commands/cat_file.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from typing_extensions import Annotated

from xgit.types.types import Factory
from xgit.utils.utils import check_exist, get_file_path
from xgit.utils.utils import get_object, check_exist


def cat_file(
Expand Down Expand Up @@ -57,7 +57,7 @@ def cat_file(
typer.echo(f"fatal: Not a valid obj name {obj}", err=True)
sys.exit(128)

with get_file_path(obj=obj).open("rb") as f:
with get_object(obj=obj).open("rb") as f:
data = zlib.decompress(f.read())

hdr, data = data.split(b"\x00", maxsplit=1)
Expand Down
14 changes: 5 additions & 9 deletions xgit/commands/update_index.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def update_index(
"""
# 如果没有 git repo,会报错
index = get_index()

# === 检查参数正确性 ===
# add, remove, force_remove, refresh 互斥
if add + remove + force_remove + refresh > 1:
Expand All @@ -46,10 +46,10 @@ def update_index(
repo = find_repo().resolve()
files = files or []
update_files = []

for f in files:
file_path = Path(f).resolve()

if not file_path.is_relative_to(repo):
typer.echo(f"fatal: '{f}' is outside repository at '{repo}'", err=True)
sys.exit(128)
Expand All @@ -58,21 +58,17 @@ def update_index(
else:
update_files.append(f)


# === 执行操作 ===
# refresh:刷新 index 中的 metadata,报告需要 update 的文件
# 我们暂时忽略 merge 相关的状态
if refresh:
# 对于 index 中的每个 entry,检查其 metadata 是否与本地一致
# 如果不一致,检查文件 sha 是否一致:如果一致,更新 metadata;否则报告 needs update
# 如果不一致,检查文件 sha 是否一致:如果一致,更新 metadata;否则报告 needs update
pass

# 如果没有 add, remove, force_remove
if not (add or remove or force_remove):
# 对于 files 中的每一项
# 如果本地或 index 不存在,报错
# 如果都存在,更新其状态
pass



78 changes: 28 additions & 50 deletions xgit/types/index.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import hashlib
from typing import Optional

from xgit.utils.utils import find_repo, timestamp_to_str
from xgit.utils.utils import find_repo, get_repo_file, timestamp_to_str
from xgit.types.metadata import Metadata
from xgit.utils.constants import GIT_DIR


Expand Down Expand Up @@ -65,16 +66,7 @@ def __rich_repr__(self):
yield "stage", self.stage
yield "name_length", self.name_length

ctime_s: int
ctime_ns: int
mtime_s: int
mtime_ns: int
dev: int
inode: int
mode: int
uid: int
gid: int
file_size: int
metadata: Metadata
sha: str
flags: Flag
extended_flags: Optional[bytes]
Expand All @@ -97,16 +89,9 @@ def __init__(
extended_flags,
file_name,
):
self.ctime_s = ctime_s
self.ctime_ns = ctime_ns
self.mtime_s = mtime_s
self.mtime_ns = mtime_ns
self.dev = dev
self.inode = inode
self.mode = mode
self.uid = uid
self.gid = gid
self.file_size = file_size
self.metadata = Metadata(
get_repo_file(file_name), ctime_s, ctime_ns, mtime_s, mtime_ns, dev, inode, mode, uid, gid, file_size
)
self.sha = sha
self.flags = flags
self.extended_flags = extended_flags
Expand Down Expand Up @@ -169,16 +154,16 @@ def parse(data: bytes) -> tuple["IndexEntry", bytes]:
)

def to_bytes(self) -> bytes:
entry = self.ctime_s.to_bytes(4, "big")
entry += self.ctime_ns.to_bytes(4, "big")
entry += self.mtime_s.to_bytes(4, "big")
entry += self.mtime_ns.to_bytes(4, "big")
entry += self.dev.to_bytes(4, "big")
entry += self.inode.to_bytes(4, "big")
entry += self.mode.to_bytes(4, "big")
entry += self.uid.to_bytes(4, "big")
entry += self.gid.to_bytes(4, "big")
entry += self.file_size.to_bytes(4, "big")
entry = self.metadata.ctime_s.to_bytes(4, "big")
entry += self.metadata.ctime_ns.to_bytes(4, "big")
entry += self.metadata.mtime_s.to_bytes(4, "big")
entry += self.metadata.mtime_ns.to_bytes(4, "big")
entry += self.metadata.dev.to_bytes(4, "big")
entry += self.metadata.inode.to_bytes(4, "big")
entry += self.metadata.mode.to_bytes(4, "big")
entry += self.metadata.uid.to_bytes(4, "big")
entry += self.metadata.gid.to_bytes(4, "big")
entry += self.metadata.file_size.to_bytes(4, "big")
entry += bytes.fromhex(self.sha)
entry += self.flags.to_bytes()
if self.extended_flags is not None:
Expand All @@ -199,20 +184,20 @@ def to_bytes(self) -> bytes:
def __rich_repr__(self):
if not self.verbose:
yield "file_name", self.file_name
yield "ctime", timestamp_to_str(self.ctime_s, self.ctime_ns)
yield "mtime", timestamp_to_str(self.mtime_s, self.mtime_ns)
yield "ctime", timestamp_to_str(self.metadata.ctime_s, self.metadata.ctime_ns)
yield "mtime", timestamp_to_str(self.metadata.mtime_s, self.metadata.mtime_ns)
yield "sha", self.sha
else:
yield "ctime_s", self.ctime_s
yield "ctime_ns", self.ctime_ns
yield "mtime_s", self.mtime_s
yield "mtime_ns", self.mtime_ns
yield "dev", self.dev
yield "inode", self.inode
yield "mode", oct(self.mode)
yield "uid", self.uid
yield "gid", self.gid
yield "file_size", self.file_size
yield "ctime_s", self.metadata.ctime_s
yield "ctime_ns", self.metadata.ctime_ns
yield "mtime_s", self.metadata.mtime_s
yield "mtime_ns", self.metadata.mtime_ns
yield "dev", self.metadata.dev
yield "inode", self.metadata.inode
yield "mode", oct(self.metadata.mode)
yield "uid", self.metadata.uid
yield "gid", self.metadata.gid
yield "file_size", self.metadata.file_size
yield "sha", self.sha
yield "flags", self.flags
yield "extended_flags", self.extended_flags
Expand Down Expand Up @@ -256,13 +241,6 @@ def __rich_repr__(self):
yield "entries", self.entries
yield "extensions", self.extensions

def update_or_add(self, entry: IndexEntry):
for i, e in enumerate(self.entries):
if e.file_name == entry.file_name:
self.entries[i] = entry
return
self.entries.append(entry)


def get_index() -> Index:
"""
Expand Down
42 changes: 42 additions & 0 deletions xgit/types/metadata.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
from pathlib import Path


class Metadata:
path: Path

ctime_s: int
ctime_ns: int
mtime_s: int
mtime_ns: int
dev: int
inode: int
mode: int
uid: int
gid: int
file_size: int

def __init__(
self,
path: Path,
ctime_s: int,
ctime_ns: int,
mtime_s: int,
mtime_ns: int,
dev: int,
inode: int,
mode: int,
uid: int,
gid: int,
file_size: int,
):
self.path = path
self.ctime_s = ctime_s
self.ctime_ns = ctime_ns
self.mtime_s = mtime_s
self.mtime_ns = mtime_ns
self.dev = dev
self.inode = inode
self.mode = mode
self.uid = uid
self.gid = gid
self.file_size = file_size
14 changes: 12 additions & 2 deletions xgit/utils/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,23 @@ def find_repo() -> Path:
sys.exit(128)


def get_file_path(obj: str):
def get_repo_file(f: str) -> Path:
"""
`f` 是相对于 repo 的路径,返回在本地的实际路径
"""
return (find_repo() / f).resolve()


def get_object(obj: str):
"""
给定一个 object 的 ID (sha),返回它在 objects 中的路径
"""
repo_dir = find_repo()
return repo_dir / GIT_DIR / "objects" / obj[:2] / obj[2:]


def check_exist(obj: str) -> bool:
object_file = get_file_path(obj)
object_file = get_object(obj)
return object_file.exists()


Expand Down

0 comments on commit 9918b9c

Please sign in to comment.