Merge branch 'master' of git://git.xonotic.org/xonotic/xonotic
[xonotic/xonotic.git] / misc / tools / git-pk3-import
1 #!/bin/sh
2
3 # git-pk3-import: Import a PK3 into a branch of a bare Git repo.
4
5 set -x
6
7 # Helpers
8
9 die()
10 {
11     echo "$(basename "$0"): error: $*" >&2
12     exit 1
13 }
14
15 usage()
16 {
17     cat <<EOF
18 Usage:
19
20   # mandatory
21   export GIT_DIR=/path/to/xonotic-maps.pk3dir.git # absolute path
22   export GIT_WORK_TREE=/tmp/worktree # pk3 is extracted here
23   # optional
24   export GIT_AUTHOR_NAME="Some Guy"
25   export GIT_AUTHOR_EMAIL="someguy@example.com"
26
27   $(basename $0) nick branch map.pk3 [changes.txt]
28
29 EOF
30 }
31
32 # Check usage
33
34 [ $# -ge 3 -a $# -le 4 ] || {
35     usage
36     die "wrong number of arguments"
37 }
38
39 [ -z "$GIT_DIR" ] && {
40     usage
41     die "GIT_DIR not set"
42 }
43
44 [ -z "$GIT_WORK_TREE" ] && {
45     usage
46     die "GIT_WORK_TREE not set"
47 }
48
49 [ -z "$(ls -A "$GIT_WORK_TREE")" ] ||
50 die "GIT_WORK_TREE is not empty"
51
52 nick="$1"
53 branch=$(git check-ref-format --print "$nick/$2") ||
54 die "malformed branch name '$nick/$2'"
55 pk3path="$3"
56 pk3name="$(basename "$pk3path")"
57 changes="$4"
58
59 # Set up commit info
60
61 [ -z "$GIT_AUTHOR_NAME" ] && export GIT_AUTHOR_NAME="$nick"
62 [ -z "$GIT_AUTHOR_EMAIL" ] && export GIT_AUTHOR_EMAIL="${nick}@example.com"
63
64 message()
65 {
66     echo -e "Import $pk3name\n" | cat - "$changes" 2> /dev/null
67 }
68
69 # Clean up on exit
70
71 cleanup_index=
72 cleanup_worktree=
73
74 cleanup()
75 {
76     [ "$cleanup_index" ] && rm -f "$GIT_INDEX_FILE"
77     [ "$cleanup_worktree" ] && find "$GIT_WORK_TREE" -mindepth 1 -delete
78 }
79
80 trap cleanup EXIT
81
82 # Set up index file, makes testing easier
83 [ -z "$GIT_INDEX_FILE" ] && {
84     export GIT_INDEX_FILE="$GIT_DIR/pk3-import-index"
85     cleanup_index=t
86 }
87
88 # Extract the PK3 (the -n suppresses prompting in an edge case)
89 unzip -n -qq "$pk3path" -d "$GIT_WORK_TREE" ||
90 die "couldn't extract PK3 contents"
91 cleanup_worktree=t
92
93 # Note the refs and the common ancestor
94 master=refs/heads/master
95 ref=refs/heads/$branch
96 base=$(git merge-base $master $ref 2> /dev/null) ||
97 base=$master
98
99 # Figure out the parent commit
100 parent=\
101 $(git rev-parse --verify -q $ref || git rev-parse --verify -q $base) ||
102 die "couldn't determine parent commit"
103
104 # Read the tree at base into index
105 git read-tree $base ||
106 die "couldn't initialize index"
107
108 # Reject any modified files, the mapper should create a branch instead
109 [ -z "$(git diff-files --diff-filter=M)" ] ||
110 die "found changes to files in master"
111
112 # Force reading of .gitignore files from cache, not the work tree
113 git ls-files --cached -z |
114 grep -z '\.gitignore$' |
115 git update-index --skip-worktree -z --stdin ||
116 die "couldn't set up exclude patterns from index"
117
118 # Add untracked files; to filter out generated files such as BSP, add
119 # them to .gitignore and push, --exclude-standard (and the above hack)
120 # takes care of the rest
121 git ls-files --exclude-standard -o -z |
122 git update-index --add -z --stdin ||
123 die "couldn't add files to index"
124
125 # Check if the index contains changes against parent
126 git diff-index --cached --quiet $parent &&
127 die "found no changes to commit"
128
129 # Commit the index and point the ref to the new commit
130 tree=$(git write-tree) &&
131 commit=$(message | git commit-tree $tree -p $parent) &&
132 git update-ref -m "pk3-import: $pk3name" $ref $commit ||
133 die "couldn't commit changes"