~sircmpwn/shit

ref: 308ffecc89bce90960bdbbdd2f4cfd4fce8a7367 shit/ls-files -rwxr-xr-x 1.4 KiB
308ffeccDrew DeVault Initial commit 8 months ago
                                                                                
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
#!/bin/sh -eu
SHIT_PATH=$(dirname "$0")
. $SHIT_PATH/common.sh

index="$GIT_DIR"/index

magic=$(od -An -tc -N4 "$index" | tr -d ' ')
version=$(read_int32 "$index" 4)
nentries=$(read_int32 "$index" 8)

if [ "$magic" != "DIRC" ]
then
	printf "Invalid git index format\n" >&2
	exit
fi

if [ $version -ne 2 ]
then
	printf "Only git index version %d is supported, %d was found\n" \
		"$INDEX_VERSION" "$version" >&2
	exit 1
fi

offs=12
while [ $nentries -gt 0 ]
do
	# mode  @ 24 bytes
	# sha   @ 40 bytes
	# flags @ 60 bytes
	# name  @ 62 bytes
	mode=$(read_int32 "$index" $((offs+24)))
	sha=$(read_hex "$index" $((offs+40)) 20)
	flags=$(read_int16 "$index" $((offs+60)))

	# 0bNNNNxxxMMMMMMMMM
	# NNNN -> object type
	# MMMMMMMMM -> unix file mode (644 or 755)
	case $(printf "%X" $((mode & 0xF000))) in
		8000)
			objtype=file
			;;
		A000)
			objtype=link
			;;
		E000)
			objtype=gitlink
			;;
		*)
			printf "Invalid object type %x\n" $(((mode & 0xF000) >> 12)) >&2
			exit 1
			;;
	esac
	mode=$((mode & 0x1FF))
	if [ $mode -ne $((0644)) ] && [ $mode -ne $((0755)) ] && [ $mode -ne 0 ]
	then
		printf "Invalid file mode %o\n" $mode >&2
		exit 1
	fi

	pathlen=$((flags & 0xFFF))
	path="$(read_text "$index" $((offs+62)) $pathlen)"

	printf "%s %o %s %s\n" "$objtype" "$mode" "$sha" "$path"

	padding=$((${#path} + 1 + 62))
	padding=$((padding % 8))
	padding=$(((8 - padding) % 8))
	offs=$((offs+62+${#path}+1+padding))

	nentries=$((nentries-1))
done