scc-cmp(1)



NAME


	scc-cmp - compare two SCC-snapshots

RELEASE


	scc	1.23.185

SYNOPSIS


	scc-cmp <prev> <new> <remark> <ignore>

DESCRIPTION


	This program compares the current and new snapshots, ignoring some
	data by means of the sed-expressions <ignore>. The results of the 
	compare are written to stdout.

	Do not signal all changes when new and previous snapshots are less 
	than 20% of each other or when the number of differences execeeds 20.000
	lines. Reduce the differences to the count of all classes of the
	differences.

ARGUMENTS


	<prev>          The snapshot of the previous run. Absence of this file
	                indicates a (re)start.
	<new>          	The snapshot of the current run.
	<remark>       	Remark to be added to logbook.
	<ignore>       	Sed-statements ignoring certain data.

OPTIONS


	None.

DIAGNOSTICS


	This program writes the following messages to stderr:

	Syntax error, use: scc-cmp <prev> <new> <remark> <ignore>
	A syntax error has been detected and reported.

	scc-cmp: cannot access file <new>
	The new snapshot cannot be found.

EXTERNAL INFLUENCES


	This program is part of the SCC client, but is also used by the
	SCC server.

	This program will not work correctly when diff is implemented by busybox.
	The SCC client checks for this dependency before calling this program, the
	SCC server software not.

	Use environment variable SCC_DATA to specify an alternative directory
	for the SCC data files. Should be an absolute path.

RETURN VALUE


	Upon completion, the program returns one of the following values:

		0 successful completion
		1 Syntax error
		2 Runtime error

COPYRIGHT


	scc-cmp is free software under the terms of the GNU General Public 
	License. Copyright (C) 2001-2004 Open Challenge B.V.,
	2004-2005 OpenEyeT Professional Services, 2005-2015 QNH.

SEE ALSO


	scc(1), scc-cmp(1), scc-collect(1), scc-log(1), scc-log2html(1),
	scc-plugin(1), scc-snap2html(1), scc(4), scc(5)

VERSION


	$Revision: 5917 $

)	;;
	echo "${ProgName}: alternative SCC_DATA (${SCC_DATA}) should be an absolute path" >&2
xit 2;;
ac

port TMPDIR=${SCC_TMP}
port TMP=${SCC_TMP}

port SHELL=/bin/sh

-r ${SCC_CONF}/scc-localize ] && . ${SCC_CONF}/scc-localize

${SCC_BIN}/scc_modules/scc_utils

ask 077

[ $# -ne 4 ]
en
cho "Syntax error, use: ${ProgName} <prev> <new> <remark> <ignore>" >&2
xit 1


ndom="$(get_RANDOM)"
port TMP1_FILE=${SCC_TMP}/scc_cmp1_$$_${random}
port TMP2_FILE=${SCC_TMP}/scc_cmp2_$$_${random}
port TMP3_FILE=${SCC_TMP}/scc_cmp3_$$_${random}
ap 'rm -f ${TMP1_FILE} ${TMP2_FILE} ${TMP3_FILE} 2>/dev/null' 0
ap "exit 2" 1 2 3 15

Split a snapshot into files per classification, containing the "fix" data.
Required for context diff.
ap_split()
{
     my_dir="${1}"
     my_snap="${2}"
     rm -rf "${my_dir}"
     mkdir -p "${my_dir}"

     awk '/^fix:/    {
                             file_name = $0;
                             gsub( "::.*", "", file_name );
                             gsub( "/", "_", file_name );		# filename cannot contain "/" 
                             file_name = sprintf( "%s/%s", d, file_name );
                             print >>file_name;
                     }' d="${my_dir}" <"${my_snap}"
}

ev_snapshot="${1}"
w_snapshot="${2}"
mark="${3}"
nore="${4}"

[ ! -f "${new_snapshot}" ]
en
cho "${ProgName}: cannot access file ${new_snapshot}" >&2
xit 2


mestamp="$(head "${new_snapshot}"	|
awk -F:	'/date/		{ d=$NF; next }
	/:start time:/	{ print d ":" $NF }' )";

ntime="$(head "${new_snapshot}" | sed -n -e "s/^var:general::runtime://p")"

[ -f "${prev_snapshot}" ]
en
${TMP1_FILE}

The software system module of scc records the checksums of all modules.

scc-collect "surrounds" the data of a user-module with the following tags:

	var:MoDuLe:start::<module>:<checksum>
	...
	var:MoDuLe:end::<module>:

These tags are used to ignore changes when a user-modules has been changed.


Suppose you run scc daily and the user modules weekly (on sunday).


When you change a user-module on wednesday, the change of the checksum

recorded by the software system module will be reported on the next run of scc.

On the first run of the changed user-module, the changed checksum in the plugin-data

causes that all changes of that user-module are ignored.

The "proper" procedure to change a user-module is:

	- run all system modules and the user-module: scc -e "<user-module>"
	- change the user-module
	- test the user-module: scc-collect -i -e "<user-module>"
	- rerun the system modules and the user-module: scc -e "<user-module>"

The last run will signal the change in the checksum of the user-module,

but ignores all changes in the output of the user-module. On the next,
weekly activation of the user-module, all (regular) changes will be
reported.
rep "^var:MoDuLe:start::scc_[0-9][0-9][0-9][0-9]_u_" ${prev_snapshot} >${TMP2_FILE}
rep "^var:MoDuLe:start::scc_[0-9][0-9][0-9][0-9]_u_" ${new_snapshot} >${TMP3_FILE}
iff ${TMP2_FILE} ${TMP3_FILE}			|
ed -n -e 's/.*var:MoDuLe:start:://p'		|
ed -e 's/:.*//'				|
ort -u						|
hile read module remainder
o
# This module is reported, erase all the data of this module.
echo "/^var:MoDuLe:start::${module}:/,/^var:MoDuLe:end::${module}:/d" >>${TMP1_FILE}
one

Sometimes "fixed" lines between "variable" lines are also reported.


Avoid this by limiting the comparison to "fixed" lines.

f [ -s ${TMP1_FILE} ]
hen
sed -f ${TMP1_FILE} ${prev_snapshot}		|
grep "^fix:" >${TMP2_FILE}

sed -f ${TMP1_FILE} ${new_snapshot}		|
grep "^fix:" >${TMP3_FILE}

if [ -z "${remark}" ]		# Do not change remark supplied with -c option.
then
	remark="changes in modules $(awk -F: '{ printf( "%s ", $(NF - 1) ) }' ${TMP1_FILE}), differences ignored"
fi
>${TMP1_FILE}
lse
grep "^fix:" ${prev_snapshot} >${TMP2_FILE}
grep "^fix:" ${new_snapshot} >${TMP3_FILE}
i

iff -u /dev/null /dev/null >/dev/null 2>/dev/null		# Check for support of context diff?
f [ $? -eq 0 -a "${SCC_CONTEXT_DIFF:-}" = "yes" ]
hen
# Context diff: contributed by Erik-Jan Taal:
snap_split ${SCC_DATA}/new ${TMP3_FILE}
snap_split ${SCC_DATA}/old ${TMP2_FILE}

diff -u -NP ${SCC_DATA}/old ${SCC_DATA}/new	|
sed     -e '/^diff /d'  	\
	-e '/^--- /d'   	\
	-e '/^+++ /d'   	\
	-e '/^@@ /d'		\
	-e 's/^+fix:/new::/'	\
	-e 's/^-fix:/old::/'	\
	-e 's/^ fix:/ctx::/'	\
		${ignore} >${TMP1_FILE}

dif_cnt=$(grep -c "^[no][el][wd]:" ${TMP1_FILE})	# Count the "new" and "old" lines.

rm -rf ${SCC_DATA}/new ${SCC_DATA}/old
lse
# Compare     old          new
diff ${TMP2_FILE} ${TMP3_FILE}		|
sed 	-e "/^[0-9]/d"		\
	-e "/^--/d"		\
	-e "s/^< fix:/old::/"	\
	-e "s/^> fix:/new::/"	\
		${ignore} >${TMP1_FILE}

dif_cnt="$(wc -l <${TMP1_FILE} | sed -e 's/^ *//')"
i

f [ -s ${TMP1_FILE} ]
hen
old_cnt="$(wc -l <${TMP2_FILE})"
new_cnt="$(wc -l <${TMP3_FILE})"
# Require a minimal size of the snapshots.
if [ "${old_cnt}" -gt 1000 -o "${new_cnt}" -gt 1000 ]
then
	# Do not signal all changes when new and previous are less 
	# than 20% of each other or when the number of differences execeeds 20.000
	if [	${new_cnt} -lt $(( old_cnt / 5 ))	-o	\
		${old_cnt} -lt $(( new_cnt / 5 ))	-o	\
		${dif_cnt} -gt 20000					]
	then
		# Old and new differ too much or there are too many changes.
		# Reduce the differences to the count of all classes of the differences.
		# Ignore the context files with context diff.
		remark="Too many changes; reduced to # of lines per classification"

		awk	'/^old::/	{
						sub( "^old::", "" );
						sub( "::.*", "" );
						old[ $0 ] += 1;
					}
			/^new::/	{
						sub( "^new::", "" );
						sub( "::.*", "" );
						new[ $0 ] += 1;
					}
					{
						if ( ! id[ $0 ] )
						{
							id[ $0 ] = NR;
						}
					}
			END	{
					for ( o in old )
					{
						printf( "%d %d old::%s::%d\n",
							old[ o ] + new[ o ], id[ o ],
							o, old[ o ] );
					}
					for ( n in new )
					{
						printf( "%d %d new::%s::%d\n",
							new[ n ] + old[ n ], id[ n ],
							n, new[ n ] );
					}
				}' ${TMP1_FILE}		|
		sort -k 1nr -k 2n -k 3			|
		sed -e 's/^[0-9 ]*//' >${TMP2_FILE}
		mv ${TMP2_FILE} ${TMP1_FILE}
	fi	# Too many differences.
fi	# if [ "${old_cnt}" -gt 1000 -o "${new_cnt}" -gt 1000 ]

# Get the date and time of the old (current) snapshot.
d_o=$(head ${prev_snapshot} | sed -n -e "s/.*::date://p")
t_o=$(head ${prev_snapshot} | sed -n -e "s/.*::start time://p" | sed -e 's/:/./g')

echo "${timestamp}:result::different"
echo "${timestamp}:remark::${remark}"
echo "${timestamp}:runtime::${runtime}"
echo "${timestamp}:count::${dif_cnt}"
echo "${timestamp}:previous date::${d_o}"
echo "${timestamp}:previous time::${t_o}"

sed -e "s/^/${timestamp}:data::/" ${TMP1_FILE}
lse
# File with differences is empty. No differences.
echo "${timestamp}:result::identical"
echo "${timestamp}:remark::${remark}"
echo "${timestamp}:runtime::${runtime}"
i	# if [ -s ${TMP1_FILE} ]
se	# if [ -f "${prev_snapshot}" ]

No previous snapshot. This means that scc has been (re)started.

cho "${timestamp}:result::(re)start"
cho "${timestamp}:remark::${remark}"
cho "${timestamp}:runtime::${runtime}"
	

it 0