spec 10.7 KB
Newer Older
1 2 3 4 5
#!/bin/bash
# 2006-2008 Etersoft www.etersoft.ru
# Author: Vitaly Lipatov <lav@etersoft.ru>
# Public domain

6 7
load_mod gear

8 9 10 11 12 13
get_var()
{
	grep -i "^$1:" | head -n 1 | sed -e "s/^[^:]*[ \t]*:[ \t]*//"

}

14
# TODO: create temp spec, not just output: it masks specs problem now
15
# Раскрывает макросы в спеке и выводит на стандартный вывод
16 17 18
eval_spec()
{
	# TODO: use rpm -showrc instead -bE for get main variables?
19 20 21
	local SPECNAME=$1

	# Drop changelog and make spec copy
22
	# see http://bugs.etersoft.ru/show_bug.cgi?id=6588
23 24 25 26 27
	SPECNAMETMP=$(make_temp_file)
	SPECNAMECHANGELOG=$(make_temp_file)
	mark_file_to_remove $SPECNAMETMP $SPECNAMECHANGELOG
	separate_changelog $SPECNAME $SPECNAMETMP $SPECNAMECHANGELOG
	SPEC=$SPECNAMETMP
28 29 30 31 32 33 34 35 36

	USEARCH=
	# FIXME: rpm on 64bit ALT has no macros for ix86 arch
	# use i586 if ExclusiveArch is %{ix86}
	#[ "$SYSARCH" = "x86_64" ] && grep "^ExclusiveArch:" $SPEC | grep -q "ix86" && USEARCH=i586

	# Hack for allow repack on x86_64 packages with ExclusiveArch: %{ix586}
	# See https://bugs.etersoft.ru/show_bug.cgi?id=8394
	[ "$SYSARCH" = "x86_64" ] && subst "s|^ExclusiveArch:.*||g" $SPEC
37 38 39 40

	# Hack: just print spec if -bE failed
	if is_alt ; then
		# on ALT we have to done without errors
41
		$USEARCH $RPMBUILD -bE --with=test --target $SYSARCH $RPMBUILDARG $SPEC | iconv -f utf8 -r || fatal "Check spec's fields"
42
	else
43
		( a= $USEARCH rpmspec -P --target $SYSARCH $RPMBUILDARG $SPEC 2>/dev/null || cat $SPEC ) | iconv -f utf8
44
	fi
45
	# FIXME: hack for koi8-r in spec (grep will not work with it)
46 47
	[ -n "$DEBUG" ] || rm -f $SPECNAMETMP $SPECNAMECHANGELOG
	remove_file_from_remove $SPECNAMETMP $SPECNAMECHANGELOG
48 49 50 51 52 53 54
}

get_release()
{
	eval_spec $1 | get_var "Release"
}

55
# TODO: fix description
Vitaly Lipatov's avatar
Vitaly Lipatov committed
56 57 58
# get 11 from alt11, 12.1 from alt12.1t
get_numpartrelease()
{
59
	echo "$1" | perl -pe "s|([a-zA-Z]+)([0-9]+)[^0-9].*|\2|" || echo "0"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
60 61
}

62 63 64
# get 11 from alt11, 12.1 from alt12.1t
get_numrelease()
{
65
	get_release "$1" | sed -e "s|\([a-zA-Z]*\)\([0-9\.]\)[^0-9\.]*|\2|" || echo "0"
66 67
}

68 69
get_default_txtrelease()
{
70
	# assert GITHOST
Vitaly Lipatov's avatar
Vitaly Lipatov committed
71
	# TODO: check for git.alt in ~/.ssh/config?
72
	[ "$GITHOST" = "gitery" ] && echo "alt" && return
73
	echo ${GITHOST/git./}
74 75
}

76
# get alt from alt11
77 78
# TODO: support alt1.eter2
# TODO: change to use mask gggNNN gggNNN.NNN gggNNN.NNNggg gggNNN.eeee.MMMM.ffff
79 80
get_txtrelease()
{
81
	# TODO: txtrelease is all exclude num part
82
	get_release "$1" | sed -e "s|\([a-zA-Z]*\)\([0-9\.]\).*|\1|" || get_default_txtrelease
83 84
}

85 86
set_var()
{
87
	subst "0,/^$2:/s/^\($2:\)\([[:space:]]*\).*\$/\1\2$3/" $1
88
	#subst "s|^\($2:\).*\$|\1 $3|q" $1
89 90
}

91 92
# Args: spec, new_release
# set release to arg2 or reset numeration if arg2 is empty
93
set_release()
94 95 96 97 98 99 100 101 102
{
	local RELEASE=$2
	[ -n "$RELEASE" ] || RELEASE="$(get_txtrelease $1)1"
	set_var $1 Release $RELEASE
}

# Args: spec, new_release
# Set release to arg2 or to the default start value if arg2 is empty
reset_release()
103 104
{
	local RELEASE=$2
105
	[ -n "$RELEASE" ] || RELEASE="$(get_default_txtrelease)1"
106 107 108
	set_var $1 Release $RELEASE
}

109 110
is_backported_release()
{
111
	echo "$1" | grep -E -q "\.(M[0-9][0-9][CPT])\."
112 113
}

114
# inc 2 release to 3
115
# textMAJOR.middle.MINOR
116 117
inc_release()
{
118
	local BASERELEASE=$(get_numrelease "$1")
119 120 121 122 123 124
	if is_backported_release "$BASERELEASE" ; then
		local MAJOR="$(echo "$BASERELEASE" | sed -e "s|.*\.M[0-9][0-9][CPT]\.||")"
		local m="$(echo "$BASERELEASE" | sed -e "s|$MAJOR$||")"
		set_release "$1" "$(get_txtrelease "$1")$m$(($MAJOR + 1))"
		return
	fi
125
	local MAJOR=`echo "$BASERELEASE" | sed -e "s|\..*||"`
126
	local MINOR=`echo "$BASERELEASE" | sed -e "s|.*\.||"`
127
	local m=$(echo "$BASERELEASE" | sed -e "s|$MAJOR\.\(.*\)\.$MINOR|\1|") #"
128 129 130 131 132 133 134
	[ "$m" = "$BASERELEASE" ] && m=''
	local am=''
	# keep minor part
	[ -z "$m" ] && rhas "$MINOR" "[a-zA-Z]" && am=".$MINOR"
	# keep middle part
	[ -n "$m" ] && am=".$m"
	set_release "$1" "$(get_txtrelease "$1")$(($MAJOR + 1 ))$am"
135 136 137
}

# inc 2.x to 2.(x+1) or 2 to 2.1
138
# textMAJOR.middle.MINOR
139 140
inc_subrelease()
{
141
	#is_backported_release
142 143 144
	local BASERELEASE=$(get_numrelease $1)
	local MAJOR=`echo "$BASERELEASE" | sed -e "s|\..*||"`
	local MINOR=`echo "$BASERELEASE" | sed -e "s|.*\.||"`
145
	[ "$MINOR" = "$BASERELEASE" ] && MINOR="0"
146
	local m=$(echo "$BASERELEASE" | sed -e "s|$MAJOR\.\(.*\)\.$MINOR|\1|") #"
147 148 149 150 151 152
	local am=''
	# keep minor part
	rhas "$MINOR" "[a-zA-Z]" && am=".$MINOR" && MINOR="0"
	# keep middle part
	[ -n "$m" ] && [ "$m" != "$BASERELEASE" ] && am=".$m"
	set_release "$1" "$(get_txtrelease $1)${MAJOR}$am.$(($MINOR + 1 ))"
153 154
}

155 156 157 158 159 160 161 162 163
reset_subrelease()
{
	local BASERELEASE=$(get_numrelease $1)
	local MAJOR=`echo "$BASERELEASE" | sed -e "s|\..*||"`
	local MINOR=`echo "$BASERELEASE" | sed -e "s|.*\.||"`
	MINOR="0"
	set_release "$1" "$(get_txtrelease $1)${MAJOR}.$(($MINOR + 1 ))"
}

164 165 166 167 168
get_name()
{
	eval_spec $1 | get_var "Name"
}

169 170 171 172 173
get_version()
{
	eval_spec $1 | get_var "Version"
}

Vitaly Lipatov's avatar
Vitaly Lipatov committed
174
# Args: specname, source_number
175 176
get_tarballname()
{
Vitaly Lipatov's avatar
Vitaly Lipatov committed
177 178
	local SOURCE=$(eval_spec "$1" | get_var "Source$2")
	[ -n "$SOURCE" ] || SOURCE=$(eval_spec "$1" | get_var "Source0")
179
	[ -n "$SOURCE" ] || fatal "Can't grep Source$2 from spec $1"
Vitaly Lipatov's avatar
Vitaly Lipatov committed
180
	basename $(basename "$SOURCE" | sed -e "s|-$(get_version "$1").*||g") .tar
181 182
}

183

184 185
# Set version for spec (args: spec version), f.i. test.spec 1.2.3)
# Supports %major and %ver_major macros in spec
186
# версия может быть указана как 2.6.1 (полная), 2.6 (major) или .1 (minor)
187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205
set_version()
{
	local SPEC=$1
	local VER=$2

	if [ -z "$SPEC" ] ; then
		return 1
	fi

	if [ -z "$VER" ] ; then
		return 2
	fi

	VERMAJOR=`echo $VER | sed -e "s|\([0-9]*\.[0-9]*\)\..*|\1|"`
	VERMINOR=`echo $VER | sed -e "s|^[0-9]*\.[0-9]*||;s|^\.||"`
	if [ -z ${VER/.*/} ] ; then
		VERMAJOR=
	fi

206
	MAJORMACROS=`grep "%define[[:space:]]\(\|ver_\)major[[:space:]]" $SPEC | sed -e "s|.*[[:space:]]\(.*major\).*|\1|"`
207 208
	if [ -n "${MAJORMACROS}" ] ; then
		# Change major define
209
		test -n "$VERMAJOR" && subst "s|\(%define[[:space:]]$MAJORMACROS[[:space:]]\).*|\1$VERMAJOR|" $SPEC
210 211 212 213 214 215 216 217 218 219 220
		# Change version if VERMINOR is defined
		if [ -n "$VERMINOR" ] ; then
			set_var $SPEC Version %$MAJORMACROS.$VERMINOR || fatal "Error 1 with set version to spec"
		else
			set_var $SPEC Version %$MAJORMACROS || fatal "Error 2 with set version to spec"
		fi
	else
		set_var $SPEC Version $VER || fatal "Error 3 with set version to spec"
	fi
}

221 222 223 224 225 226 227 228 229 230 231
inc_version()
{
	local VER=$(get_version "$1")
	# fixme: more general and use in other functions (see increment_release test)
	local MAJOR=`echo "$VER" | sed -e "s|\.[0-9]*$||"`
	local MINOR=`echo "$VER" | sed -e "s|.*\.||"`
	[ "$MINOR" = "$VER" ] && MINOR="0"
	VER="${MAJOR}.$(($MINOR + 1 ))"
	set_version "$1" $VER
}

232 233 234 235 236
# decrement release with workaround about non textual release
decrement_release()
{
	local NUMPART=$(echo $1 | sed -e "s|[^0-9].*||g")
	[ -n "$NUMPART" ] || NUMPART=1
Vitaly Lipatov's avatar
Vitaly Lipatov committed
237
	[ "$NUMPART" = "0" ] && NUMPART=1
238 239
	echo $(($NUMPART - 1))
}
240 241 242 243 244

subst_namever()
{
	sed -e "s|%{name}|$BASENAME|g
			s|%{version}|$VERSION|g
245 246
			s|%name|$BASENAME|g
			s|%version|$VERSION|g"
247
}
248 249


250
# args: "desc text" <spec(s)>
251 252
add_changelog_helper()
{
253
	# it is permitted to run with "" DESC
254 255 256 257
	local DESC="$1"
	shift
	local SPECS="$*"
	if ! tty -s && [ -z "$DESC" ] ; then
258
		echo "skip changelog fixing without tty and without desc"
259 260
		return 1
	fi
261
	[ -z "$SPECS" ] && fatal "run add_changelog without spec(s)"
262
	LANG=C add_changelog -e "$DESC" $SPECS
263
	R=$?
264 265

	[ -n "$QUIET" ] && return
266
	[ -z "$EDITOR" ] && { echo "skip changelog editing without EDITOR var"; return 0 ; }
267 268

	# If changelog sucessfully added, let us to edit
269
	if [ "$R" = "0" ]; then
270 271
		local SPEC
		for SPEC in $SPECS ; do
Vitaly Lipatov's avatar
Vitaly Lipatov committed
272
			N=`grep --text -n '^%changelog' $SPEC | head -n 1 | sed s!:.*!!g`
273 274 275 276 277 278 279 280 281
			# +1 -- comment with date and packager name
			# +2 -- place for edit comments
			# +N works for mcedit and vi
			${EDITOR} +$(($N + 2)) $SPEC
		done
	fi
	return $R
}

282 283 284 285

# set specdir by spec (run with full path to spec only or in spec dir)
set_specdir()
{
286 287 288 289 290 291
	# support for use git dir instead spec
	if [ -d "$1" ] ; then
		SPECDIR="$1"
		return 0
	fi

292 293 294 295 296 297 298 299 300
	SPECDIR=.
	# get dir from the first spec
	if [ -r "$1" ] ; then
		SPECDIR=`dirname $1`
	fi
	# if spec has no full path, guess from pwd
	if [ "$SPECDIR" = "." ] ; then
		SPECDIR=`pwd`
	fi
301
	[ -d "$SPECDIR" ]
302
}
303

304
# internal func
305 306
get_gear_rule_spec()
{
307
	local rules=$(get_gear_rules $@)
308
	[ -r "$rules" ] || return
Vitaly Lipatov's avatar
Vitaly Lipatov committed
309
	local SPEC="$(grep "^spec:" $rules 2>/dev/null | sed -e "s/spec:[ 	]*//g")"
310
	test -r "$(get_root_git_dir $@)/$SPEC" && echo $(get_root_git_dir $@)/$SPEC
311 312
}

313 314 315
# search for gear spec
get_gear_spec()
{
316
        local trySpec
317
        trySpec=$(get_gear_rule_spec $@)
318
        # check spec in git root dir (by default)
319
        [ -f "$trySpec" ] || trySpec=`echo $(get_root_git_dir $@)/*.spec` || return
320 321
        # check locally only if in gear repo
        #is_gear && trySpec=$(echo *.spec)
322
        # printout nothing if can't get spec
323 324 325 326
        [ -f "$trySpec" ] || trySpec=""
        echo $trySpec
        test -f "$trySpec"
}
327

328 329 330 331 332 333 334 335 336 337 338 339
# transform dir to spec if it is dir
repodirs_to_specs()
{
        local i
        for i in "$@" ; do
            if [ -d "$i" ] ; then
                i=$(get_gear_spec "$i") || continue
            fi
            echo "$i"
        done
}

340 341 342 343 344 345 346 347
separate_changelog()
{
	local SPEC="$1"
	[ "$SPEC" != "$2" ] && [ "$SPEC" != "$3" ] || fatal "separate_changelog: cannot write to itself"
	cat $SPEC | awk 'BEGIN{desk=0}{if (desk==0) {print}; if(/^%changelog/&&desk==0){desk++}}' > "$2"
	cat $SPEC | awk 'BEGIN{desk=0}{if (desk==1) {print}; if(/^%changelog/&&desk==0){desk++}}' > "$3"
}

348
# TODO: do standalone command, see ~/Projects/git-eter/fixbashisms
349
# for rpm + (d)ash
350
# http://mywiki.wooledge.org/Bashism
351 352 353 354 355
remove_bashism()
{
	local SPECNAME="$1"
	test -w "$SPECNAME" || fatal "File '$SPECNAME' is missed or read only"

356 357 358 359
	local SPECNAMETMP=$(make_temp_file)
	local SPECNAMEMAIN=$(make_temp_file)
	local SPECNAMECHANGELOG=$(make_temp_file)
	separate_changelog $SPECNAME $SPECNAMEMAIN $SPECNAMECHANGELOG
360

361 362 363
	subst "s|^pushd \(.*\)|cd \1 >/dev/null|g" $SPECNAMEMAIN
	subst "s|^popd|cd - >/dev/null|g" $SPECNAMEMAIN
	subst "s|^echo -e '\\\n'|echo ''|g" $SPECNAMEMAIN
364 365 366 367

	# {1,2} translation
	# FIXME: miss first spaces
	while read -r n ; do
368
		echo "$n" | grep -v "{.*,.*}" && continue
369 370 371
		rs="$(echo "$n" | perl -pe "s|.*\s(.*?{.*?}.*?)\s.*|\1|g" )"
		res=$(eval echo "$rs")
		echo "$n" | perl -pe "s|$rs|$res|g"
372 373
	done < $SPECNAMEMAIN >$SPECNAMETMP
	[ -s "$SPECNAMETMP" ] && mv -f $SPECNAMETMP $SPECNAME
374
	$EPMCMD assure checkbashisms && docmd checkbashisms $SPECNAME
375 376
	cat $SPECNAMECHANGELOG >>$SPECNAME
	rm -f $SPECNAMEMAIN $SPECNAMECHANGELOG
377 378
}

379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403
get_last_changelog()
{
	local SPEC="$1"
	
	local beg=
	local wait_end=
	while read line ; do
	      
		if echo $line | grep -q '%changelog'; then
		    beg=1
		    continue
		fi
		
		[ -z "$beg" ] && continue

		# check end of changelog (skip last changelog line)
		if echo "$line" | grep '*' | grep -E '[<>]+' | grep -q -E "[0-9.]+.[0-9]+"; then
		    [ -n "$wait_end" ] && return
		    wait_end=1
		fi
		
		echo "$line"
		
	done < $SPEC
}