Skip to content

Commit

Permalink
[chore][command] implements show-index for reading index easily
Browse files Browse the repository at this point in the history
  • Loading branch information
smd1121 committed Jan 7, 2024
1 parent 37b776c commit 8c80c80
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 3 deletions.
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
setuptools.setup(
name="xgit",
packages=setuptools.find_packages(),
install_requires=["typer>=0.9.0"],
install_requires=["typer>=0.9.0", "rich", "typing_extensions"],
entry_points={"console_scripts": ["xgit = xgit.cli:main"]},
)
3 changes: 2 additions & 1 deletion xgit/cli.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import typer

from xgit.commands import init, cat_file, ls_files, hash_object
from xgit.commands import init, cat_file, ls_files, show_index, hash_object

app = typer.Typer(add_completion=False, rich_markup_mode="markdown")

Expand All @@ -9,6 +9,7 @@
app.command()(init.init)
app.command()(cat_file.cat_file)
app.command()(ls_files.ls_files)
app.command(hidden=True)(show_index.show_index)


def main():
Expand Down
37 changes: 37 additions & 0 deletions xgit/commands/show_index.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
from typing import Optional
from pathlib import Path

from typer import Option, Argument
from rich.pretty import pprint
from typing_extensions import Annotated

from xgit.types.index import get_index
from xgit.utils.utils import find_repo


def show_index(
files: Annotated[Optional[list[str]], Argument(help="要展示的 entry,默认展示全部")] = None,
verbose: Annotated[bool, Option("-v", "--verbose", help="以详细模式展示 entry")] = False,
):
"""
以可读的方式输出 index。只打印当前目录和子目录下在的 index 中的 entry,不打印父目录中的其他 entry。
这并非 git 本身支持的功能,只是为了方便调试和展示结果。
"""
index = get_index()

cwd = Path.cwd().resolve()
repo = find_repo().resolve()

# 如果指定了 files,则只打印这些文件的 entry
if files:
file_paths = [Path(cwd / f).resolve() for f in files]
index.entries = [e for e in index.entries if repo / e.file_name in file_paths]

# 只打印当前目录和子目录下在的 index 中的 entry
index.entries = [e for e in index.entries if Path(repo / e.file_name).is_relative_to(cwd)]

if verbose:
for entry in index.entries:
entry.verbose = True

pprint(index)
40 changes: 39 additions & 1 deletion xgit/types/index.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import hashlib
from typing import Optional

from xgit.utils.utils import find_repo, get_repo_file
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 @@ -60,6 +60,12 @@ def to_bytes(self) -> bytes:
data |= self.name_length
return data.to_bytes(2, "big")

def __rich_repr__(self):
yield "assume_valid", self.assume_valid
yield "extended", self.extended
yield "stage", self.stage
yield "name_length", self.name_length

metadata: Metadata
sha: str
flags: Flag
Expand Down Expand Up @@ -171,6 +177,32 @@ def to_bytes(self) -> bytes:

return entry

# 以下用于 show-index 输出

verbose: bool = False

def __rich_repr__(self):
if not self.verbose:
yield "file_name", self.file_name
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.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
yield "file_name", self.file_name


class Index:
version: int
Expand Down Expand Up @@ -203,6 +235,12 @@ def to_bytes(self) -> bytes:
index += hashlib.sha1(index).digest()
return index

def __rich_repr__(self):
yield "version", self.version
yield "entry_count", self.entry_count
yield "entries", self.entries
yield "extensions", self.extensions


def get_index() -> Index:
"""
Expand Down
8 changes: 8 additions & 0 deletions xgit/utils/utils.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import sys
import datetime
from pathlib import Path

import typer
Expand Down Expand Up @@ -39,3 +40,10 @@ def get_object(obj: str):
def check_exist(obj: str) -> bool:
object_file = get_object(obj)
return object_file.exists()


def timestamp_to_str(time_s, time_ns):
dt = datetime.datetime.fromtimestamp(time_s)
microseconds = time_ns // 1000
dt = dt + datetime.timedelta(microseconds=microseconds)
return dt.strftime("%Y-%m-%d %H:%M:%S.%f")

0 comments on commit 8c80c80

Please sign in to comment.