05e39fd383ad5f68226c4c3054e895c7cd51dd60
[dcp.git] / dcp-init
1 #!/bin/bash
2
3 set -e
4
5 usage() {
6     echo "usage: dcp-init [-sh] [-C key=val] [-d REPODIR] PACKAGE [PATCH...]"
7     echo "       PATCH ::= [-p LEVEL] [-bB BRANCH] FILE"
8     echo "       -b creates a new branch at the current patch"
9     echo "       -B creates a new branch at the upstream sources"
10 }
11
12 rungit() {
13     (
14         cd "$td"
15         git "$@"
16     ) || false
17 }
18
19 getaptsrc() {
20     mkdir "$td/apt-tmp"
21     (cd "$td/apt-tmp"; apt-get source "$1") || false
22     
23     sdir=
24     for f in "$td/apt-tmp"/*; do
25         if [ -d "$f" ]; then
26             if [ -z "$sdir" ]; then
27                 sdir="$f"
28             else
29                 echo "dcp-init: got more than one directory from apt-get; cannot continue" >&2
30                 exit 1
31             fi
32         fi
33     done
34     if [ -z "$sdir" ]; then
35         echo "dcp-init: could not find any source directory" >&2
36         exit 1
37     fi
38     mv "$sdir" "$td/src"
39     rm -rf "$td/apt-tmp"
40
41     rungit add src
42 }
43
44 initrepo() {
45     rungit init -q --shared
46     mkdir "$td/control"
47     touch "$td/control/conf"
48     rungit add control
49     rungit commit -q -m "Initial repo"
50     rungit tag empty
51 }
52
53 initbase() {
54     mkdir "$td/control/build.d"
55     mkdir "$td/control/update.d"
56     cat >"$td/control/functions" <<EOF
57 readconf() {
58     while read key val; do
59         export "CONF_\$key"="\$val"
60     done <control/conf
61 }
62
63 rungit() {
64     (cd repo; git "\$@") || false
65 }
66 EOF
67     cat >"$td/control/build" <<EOF
68 #!/bin/sh
69
70 set -e
71
72 . control/functions
73 readconf
74
75 for file in control/build.d/*; do
76     if [ -x "\$file" ]; then "\$file"; fi
77 done
78 EOF
79     chmod 755 "$td/control/build"
80     cat >"$td/control/update" <<EOF
81 #!/bin/sh
82
83 set -e
84
85 . control/functions
86 readconf
87
88 for branch in repo/.git/refs/heads/*; do
89     branch="\${branch##*/}"
90     if [ -x "control/update.d/\$branch" ]; then
91         rungit checkout "\$branch"
92         lastrev="\$(rungit rev-parse HEAD)"
93         "control/update.d/\$branch"
94         newrev="\$(rungit rev-parse HEAD)"
95         rungit checkout master
96         if [ "\$newrev" != "\$lastrev" ]; then
97             rungit merge -n "\$branch"
98         fi
99     fi
100 done
101 EOF
102     chmod 755 "$td/control/update"
103     rungit add control
104 }
105
106 initapt() {
107     cat >"$td/control/build.d/99dpkg" <<EOF
108 #!/bin/bash
109
110 set -e
111
112 cmd=(dpkg-buildpackage -b)
113 if [ -n "\$CONF_MAINTAINER" ]; then
114     cmd=("\${cmd[@]}" "-m\$CONF_MAINTAINER")
115 fi
116 if [ -n "\$CONF_GPGKEY" ]; then
117     cmd=("\${cmd[@]}" "-k\$CONF_GPGKEY")
118 fi
119 (cd repo/src; "\${cmd[@]}") || false
120 mv repo/*.deb output/
121 EOF
122     chmod 755 "$td/control/build.d/99dpkg"
123     rungit add control/build.d/99dpkg
124     cat >"$td/control/update.d/upstream" <<EOF
125 #!/bin/sh
126
127 set -e
128
129 cd repo
130 dcp-update-apt "\$CONF_APTPKG"
131
132 EOF
133     chmod 755 "$td/control/update.d/upstream"
134     rungit add control/update.d/upstream
135     echo "APTPKG $pkg" >>"$td/control/conf"
136     rungit add control/conf
137 }
138
139 defdir=/srv/dcp
140 repodir=
141 confopts=()
142 shared=n
143
144 while [ "${1:0:1}" = - ]; do
145     opt="${1:1}"
146     shift
147     if [ "$opt" = d ]; then
148         repodir="$1"
149         shift
150     elif [ "$opt" = h ]; then
151         usage
152         exit 0
153     elif [ "$opt" = s ]; then
154         shared=y
155     elif [ "$opt" = C ]; then
156         confopts=("${confopts[@]}" "$1")
157         shift
158     else
159         echo "dcp-init: unknown option '$opt'" >&2
160         exit 1
161     fi
162 done
163
164 if [ $# -lt 1 ]; then
165     usage >&2
166     exit 1
167 fi
168 pkg="$1"
169 shift
170 if [ -z "$repodir" ]; then repodir="$pkg"; fi
171 if [[ "$repodir" != */* ]]; then
172     repodir="$defdir/${repodir}.git"
173 fi
174
175 td="$(mktemp -d "/tmp/dcp-XXXXXX")"
176 initrepo
177
178 initbase
179 rungit commit -q -m "Base control files"
180
181 if [ "${#confopts[@]}" -gt 0 ]; then
182     for opt in "${confopts[@]}"; do
183         key="${opt%%=*}"
184         val="${opt#*=}"
185         echo "$key $val" >>"$td/control/conf"
186     done
187     rungit add control/conf
188     rungit commit -q -m "Custom configuration file"
189 fi
190
191 rungit checkout -q -b upstream empty
192 getaptsrc "$pkg"
193 rungit commit -q -m "Initial upstream import"
194 rungit checkout master
195 rungit merge -n upstream
196
197 initapt
198 rungit commit -q -m "APT control files"
199
200 initvals() {
201     level=0
202 }
203 initvals
204 while [ $# -gt 0 ]; do
205     arg="$1"
206     shift
207     if [ "${arg:0:1}" = - ]; then
208         if [ "$arg" = -p ]; then
209             level="$1"
210             shift
211         elif [ "$arg" = -b ]; then
212             rungit checkout -q -b "$1"
213             shift
214         elif [ "$arg" = -B ]; then
215             rungit checkout -q -b "$1" upstream
216         else
217             echo "dcp-init: unknown patch option '$arg'" >&2
218             exit 1
219         fi
220     else
221         (
222             if [[ "$arg" == *.gz ]]; then
223                 zcat "$arg"
224             else
225                 cat "$arg"
226             fi
227         ) | patch -d "$td/src" -p"$level"
228         rungit add src
229         rungit commit -q -m "Applied $(basename "$arg")"
230         initvals
231     fi
232 done
233
234 git clone -q --bare "$td" "$repodir"
235 if [ "$shared" = y ]; then
236     chmod -R g+w "$repodir"
237     td="$repodir" rungit config core.sharedrepository 1
238 fi
239
240 rm -rf "$td"