2 # make-srpm: srpm builder, helps build srpm out of rcs sources
4 # Copyright (C) 2008-2010 Sam Liddicott <sam@liddicott.com>
6 # This program is free software; you can redistribute it and/or modify
7 # it under the terms of the GNU General Public License as published by
8 # the Free Software Foundation; either version 3 of the License, or
9 # (at your option) any later version.
11 # This program is distributed in the hope that it will be useful,
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 # GNU General Public License for more details.
16 # You should have received a copy of the GNU General Public License
17 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 # make-srpm will export from git or subversion and produce a src.rpm
21 # It will try and pick a recent tagged release for the "pristine source" and
22 # then produce patches up to the selected release as part of the rpm.
24 # It requires a .spec or .spec.in specfile template, from which it can also
25 # read some configuration, but this can be overridden on the command line
27 # arguments can be specified in the template spec file, or in the environment
28 # or as name=value pairs on the command line. (Once a non name=value argument
29 # is found, others are not looked for).
31 # $1 should be a spec file template
34 # ORIGIN - an rcs reference to the revision that should be tar'd
35 # ORIGIN_PATTERN - a glob or regex used to look for rcs tags to guess ORIGIN
36 # RELEASE - an rcs reference to the revision you want to build. Patches
37 # are generated from ORIGIN to RELEASE. RELEASE can be:
38 # - HEAD whatever os checked out
39 # - LOCAL means whatever is checked out + local changes
41 #include svn and git helpers
43 export PATH
="$PATH:/usr/local/lib/make-srpm:/usr/lib/make-srpm"
44 PATH
="$PATH:`dirname $0`:`dirname $0`/../lib" . make-srpm_git
45 PATH
="$PATH:`dirname $0`:`dirname $0`/../lib" . make-srpm_svn
56 # try to find a checked-out project src dir
58 # stop when we find the git folder or the top level svn folder
61 echo "Checking for top level source directory in $PWD" >&2
62 git_toplevel
&& break # found top level git
63 svn_toplevel
&& break # found top level svn
65 if ! cd .. ||
test "$PWD" = "/"
67 report
"Can't find top level repository directory, using $BASED"
75 # read a config item from a file and set environment variables.
77 # to match 2.4 from Version: 2.4
80 # to match /bin:/usr/bin from PATH=/bin:/usr/bin
81 # sep="=" get_config PATH
83 # to match 2.4alpha from #mksrpm-RELEASE: 2.4alpha
84 # prefix="#mksrpm-" get_config RELEASE
89 then export $g="`sed "/^
$prefix$g *${sep:-:} */!d;s/^[^${sep:-:}]*${sep:-:} *//;" "$SPEC_SRC"`"
94 # generate the $SPEC spec file from $SPEC template which MAY be $SPEC.in
96 _SPEC
="$SRC_EXPORT/`basename "$SPECIN" .in`"
98 cat "$SPEC_SRC" > "$_SPEC" || die
"Can't copy $SPECIN to $_SPEC"
100 report
"Updating $_SPEC"
101 # insert some macros which may be useful
102 # as well as define versions etc
103 sed -i -e "1i%define makesrpm_tarname $TAR_NAME" \
104 -e "1i%define makesrpm_tarprefix $TAR_PREFIX" \
105 -e "s/^\(Version: *\).*/\1$SPEC_VERSION/" \
106 -e "s/^\(Release: *\).*/\1${SPEC_RELEASE:-0}/" \
107 -e "s/^\(Source: *\).*/\1$TAR_NAME/" \
108 -e "/^Source: */r$SRC_EXPORT/patches.list" \
109 -e "/^%setup/r$SRC_EXPORT/patches.apply" \
111 # insert/replace any macro defines that were passed on the command line
112 for define
in "${defines[@]}"
114 if grep "^%define ${define%%=*} " 2>/dev
/null
"$_SPEC"
115 then sed -i -e "/^%define[ \t][ \t]*${define%%=*}[ \t]/c%define ${define%%=*} ${define#*=}" "$_SPEC"
116 else sed -i -e "1i%define ${define%%=*} ${define#*=}" "$_SPEC"
119 # _defines are like defines except subject to variable interpolation so
120 # that inner values calculated during execution, like TAR_NAME can be accessed
121 for define
in "${_defines[@]}"
123 eval "define=$define"
124 if grep "^%define ${define%%=*} " 2>/dev
/null
"$_SPEC"
125 then sed -i -e "/^%define[ \t][ \t]*${define%%=*}[ \t]/c%define ${define%%=*} ${define#*=}" "$_SPEC"
126 else sed -i -e "1i%define ${define%%=*} ${define#*=}" "$_SPEC"
131 # export current checked out source to file "$2" with tar path prefix of $1
132 # normally a git or svn helper is used to do a repo-export, but this will
133 # try to do a poor-mans equivalent
136 # we want to specify the top-level folder name so we use a ghastly
137 # cpio hard-link trick to avoid copying the whole tree before tar-ing it
138 find ${SOURCE_PATHS:-.} '(' -wholename "$SRC_EXPORT*" -o -wholename "./.git*" -o -name '*.o' \
139 -o -name '*.a' -o -name '*.so' -o -name '.svn' \
140 -o -name "$Name-*gz" -o -name "$Name-*src.rpm" \
141 ')' -prune -o -print |\
142 cpio -p -d -l "$1" >/dev
/null
145 source_export
"$SRC_EXPORT/$1" &&
146 ( cd "$SRC_EXPORT" && tar -czf - "1"; rm -fr "$1") > "$2"
149 # export_archive exports some "clean" source tree to $TAR_NAME
151 report
"Writing $SOURCE_TYPE to $TAR_NAME"
152 case "$SOURCE_TYPE" in
153 git
) git_archive
"$DIRNAME" "$TAR_NAME" ;;
154 svn
) svn_archive
"$DIRNAME" "$TAR_NAME" ;;
155 source) source_archive
"$DIRNAME" "$TAR_NAME" ;;
156 *) die
"Can't export from unknown source type $SOURCE_TYPE";;
160 # export_src exports some "clean" source tree to $SRC_EXPORT
162 report
"Exporting $SOURCE_TYPE to $1"
163 case "$SOURCE_TYPE" in
164 git
) git_export
"$1" ;;
165 svn
) svn_export
"$1" ;;
166 source) source_export
"$1";;
167 *) die
"Can't export from unknown source type $SOURCE_TYPE";;
171 # $1 is a simple glob like v*-release
172 # $2 is a simple value like v2.3-release
173 # outputs 2.3 by splitting on the * and then removing the LHS and RHS from $2
175 local R
="${2#${1/\**}}"
180 test -n "$TOPDIR" || TOPDIR
="`find_topdir`"
181 cd "$TOPDIR" || die
"Can't cd to $TOPDIR from $BASED"
183 if [ "$SOURCE_TYPE" = "" ]
187 test -d .svn
&& SOURCE_TYPE
="svn"
188 test -d .git
&& SOURCE_TYPE
="git"
191 echo "Source type: $SOURCE_TYPE"
193 SRC_EXPORT
="./dist_export"
200 echo "Cleaning temp dir" >&2
201 # delete the git tmpdir unless asked to keep it
202 if test -z "$KEEP_GIT"
204 # this is safer than rm -fr $GIT_TMP if $HOME is accidentally used!
205 rm -fr $GIT_TMP/git-tmp
212 mkdir
-p "$SRC_EXPORT"
214 # copy any local sources
215 test -n "$EXTRA_SOURCE" && cp `dirname "$SPEC_SRC"`/$EXTRA_SOURCE "$SRC_EXPORT"
217 # what number should our patches start at? Check what patches are already listed
218 START_PATCH_NO
=$
(( 1 + 0`sed -n 's/^\(%\|\)\(patch\)//i;T;s/[: ].*//;T;p' "$SPEC_SRC" | sort -nr | head -1` ))
220 # get patches ready according to rebase, origin etc
221 case "$SOURCE_TYPE" in
222 git
) prepare_git_src
;;
223 svn
) prepare_svn_src
;;
227 # make spec file and calculate START_PATCH_NO
228 TAR_NAME
="`basename "$TAR_NAME"`" make_spec
230 # nodeps tip from proyvind at #rpm on 5 Feb 2009
231 # nodeps because we are building src.rpm and we don't need build-time dependancies to be satisfied
232 rpmbuild
--nodeps --define "_sourcedir $SRC_EXPORT" --define "_srcrpmdir ." -bs "$SRC_EXPORT/`basename "$SPEC"`" >&2 ||
"Failed to build src.rpm"
235 # set environment from args of style var=value
239 # -c means make tmp checkout here and delete afterwards
240 -c) KEEP_GIT
= ; GIT_TMP
="$2"; shift 2;;
241 # -C means make tmp checkout here and don't delete afterwards
242 -C) KEEP_GIT
=1; GIT_TMP
="$2"; shift 2;;
243 define_
*=*) defines
[${#defines[@]}]="${1#define_}"; shift;;
244 _define_
*=*) _defines
[${#_defines[@]}]="${1#_define_}"; shift;;
245 *=*) export "${1%%=*}"="${1#*=}"; shift;;
250 if test -z "$GIT_TMP"
252 GIT_TMP
="${TMP:-${TEMP:-/tmp}}/make-srpm.$$.git"
256 VERSION
=${VERSION%%-*}
258 # Check if we need to do git checkout
260 # get to the top level project folder
267 # fixup relative paths to what PWD was when we launched
270 *) spec
="$BASED/$spec";;
274 *.spec.
in) test -z "$SPECIN" && SPECIN
="$spec";;
275 *.spec
) test -z "$SPEC" && SPEC
="$spec";;
278 test -z "$SPECIN" -a -n "$SPEC" && SPECIN
="$SPEC.in"
279 test -z "$SPECIN" && SPECIN
="`set -- *spec.in && echo $spec`"
280 test -z "$SPEC" && SPEC
="`dirname "$SPECIN"`/`basename "$SPECIN" .in`"
281 test -r "$SPECIN" -o -r "$SPEC" || die
"Can't find spec file to work with"
282 # find the project parameters
283 test -r "$SPECIN" && SPEC_SRC
="$SPECIN" || SPEC_SRC
="$SPEC"
285 CASE
="i" get_config Name Version
286 prefix
="#makes\(-\|\)rpm-" get_config SOURCE_PATHS ORIGIN ORIGIN_PATTERN RELEASE PATCH_LEVEL VERSION_PATTERN GIT_CLONE GIT_CHECKOUT
288 test -z "$PATCH_LEVEL" && export PATCH_LEVEL
=0
290 if test -n "$GIT_CLONE"
292 GIT_BASENAME
=`git_basename "$GIT_CLONE"`
293 mkdir
-p "$GIT_TMP/git-tmp" || die
"Can't make git dir $GIT_TMP/git-tmp"
294 cd "$GIT_TMP/git-tmp" || die
"Can't cd to git dir $GIT_TMP/git-tmp"
295 git clone
-n "$GIT_CLONE" "$GIT_BASENAME" || die
"Can't clone $GIT_CLONE to $PWD/$GIT_BASENAME"
297 git checkout
"$GIT_CHECKOUT"