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