Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
tag: v780
Fetching contributors…

Cannot retrieve contributors at this time

executable file 1689 lines (1516 sloc) 49.411 kb
#!/usr/bin/env bash
export ROOT=`pwd`
# The name of the application
opatrack='opatrack'
# The location of cgi script for building evolution scripts
CGI_LOCATION='http://kahan/cgi-bin/hudson'
# Conventions over name of files and directories.
# <!> Keep it synchronized with module PassTrack.
passes_list='passes.list'
printers_list='printers.list'
trackers_list='trackers.list'
printers_dir='printers'
trackers_dir='trackers'
internal_dir='internal'
check_dir='check'
time_dir='time'
all_time='all.time'
size_file='size'
# Global variables
dir2_mode=0
entityident='entity'
html_trace="$entityident.html"
raw_trace="$entityident.opatrack"
set_entity_ident() {
local entity="$1"
entityident="$entity"
html_trace="$entityident.html"
raw_trace="$entityident.opatrack"
}
# Command line options.
# <!> Keep alphabetic order for maintenance.
COLOR=1
DEBUG=0
DIR=''
DIR2=''
LOGFILE=/dev/stdout
REPORT_MODE=0
TOOL=meld
TOOL_FLAGS=''
VIEWER=less
VIEWER_FLAGS=''
SUM=0
SUMTARGET=''
menuitem() {
key="$1"
shift
msg="$*"
if [ "$COLOR" -eq 1 ]; then
printf "\t%2s : %s\n" "$key" "$msg"
else
printf "\t%2s : %s\n" "$key" "$msg"
fi
}
title() {
if [ "$COLOR" -eq 1 ]; then
echo "$*"
else
echo "$*"
fi
}
warn() {
if [ "$COLOR" -eq 1 ]; then
echo "$*"
else
echo "$*"
fi
}
# Help messsage
help() {
cat <<EOF
$opatrack: the MLstate pass track analyser
Usage: $opatrack [options] ?directory ?directory2
Options:
-h|--help : displays this help
--no-color : disables colors
-t|--tool : set diff tool. (def is $TOOL)
--tflag <opt> : add to tool options <opt>
-v|--viewer : set diff viewer. (def is $VIEWER)
--vflag <opt> : add to viewer options <opt>
--report : do not start main, but report mode
--entity-ident _ : set the entity ident (def is $entityident)
--html _ : set the name of the html trace (def is entityident.html)
--sum _ <dirs> : set the directory target for suming everyother _tracks directory
--debug : debug mode (more output for reporting, or summing)
--log _ : precise a log for outputing modes (default is /dev/stdout)
See the documentation of module PassTracker for more information.
EOF
}
# Arg.parse
while [ $# -gt 0 ]; do
case $1 in
-h|--help|-help|help)
help
exit 0
;;
--no-color)
COLOR=0
;;
-t|--tool)
if [ -z "$2" ]; then warn "Error: option $1 requires an argument"; exit 1; fi
shift
TOOL="$1"
;;
--tflag)
if [ -z "$2" ]; then warn "Error: option $1 requires an argument"; exit 1; fi
shift
TOOL_FLAGS="$TOOL_FLAGS $1"
;;
-v|--viewer)
if [ -z "$2" ]; then warn "Error: option $1 requires an argument"; exit 1; fi
shift
VIEWER="$1"
;;
--vflag)
if [ -z "$2" ]; then warn "Error: option $1 requires an argument"; exit 1; fi
shift
VIEWER_FLAGS="$VIEWER_FLAGS $1"
;;
--report)
REPORT_MODE=1
;;
--entity-ident)
if [ -z "$2" ]; then warn "Error: option $1 requires an argument"; exit 1; fi
shift
set_entity_ident "$1"
;;
--html)
if [ -z "$2" ]; then warn "Error: option $1 requires an argument"; exit 1; fi
shift
html_trace="$1"
;;
--sum)
if [ -z "$2" ]; then warn "Error: option $1 requires an argument"; exit 1; fi
shift
SUM=1
SUMTARGET="$1"
shift
DIR="$@"
break
;;
--debug)
DEBUG=1
;;
--log)
if [ -z "$2" ]; then warn "Error: option $1 requires an argument"; exit 1; fi
shift
LOGFILE=$1
;;
*)
if [ -z "$DIR" ] ; then
DIR="$1"
else
if [ -z "$DIR2" ] ; then
DIR2="$1"
dir2_mode=1
else
warn "$opatrack: unrecognized option '$1'"
warn "Try '$opatrack --help' for more information."
exit 1
fi
fi
;;
esac
shift
done
sum_size() {
local A=$1
local B=$2
local T=$3
local line
rm -f $T
while read number field ; do
line=$(cat $B | grep $field)
number2=$(echo $line | cut -d' ' -f1)
number=$(echo "$number + $number2" | bc)
if [ -n "$number" ] ; then
echo "$number $field" >> $T
fi
done < $A
}
get_line() {
local file=$1
local line=$2
line=$(head -n $line $file | tail -n 1)
echo $line
}
merge_files() {
local private_FILE_I=$1
local private_FILE_J=$2
local private_I=1
local private_J=1
local private_FILE_I_LEN=$(cat $private_FILE_I | wc -l)
local private_FILE_J_LEN=$(cat $private_FILE_J | wc -l)
local LINES=''
local line_I=''
local line_J=''
local rest_I=0
local rest_J=0
local succ_I=0
local succ_J=0
while [ 1 ] ; do
if (($private_I > $private_FILE_I_LEN)) && (($private_J > $private_FILE_J_LEN)) ; then
break;
fi
if (($private_I > $private_FILE_I_LEN)) ; then
local rest_J=$(($private_FILE_J_LEN - $private_J + 1))
tail -n $rest_J $private_FILE_J
break;
fi
if (($private_J > $private_FILE_J_LEN)) ; then
local rest_I=$(($private_FILE_I_LEN - $private_I + 1))
tail -n $rest_I $private_FILE_I
break;
fi
line_I=$(get_line $private_FILE_I $private_I)
line_J=$(get_line $private_FILE_J $private_J)
if [ "$line_I" = "$line_J" ] ; then
echo "$line_I"
let "private_I=$private_I+1"
let "private_J=$private_J+1"
else
# depending of a simple heuristic, priority to left or to right
local succ_I=$(get_line $private_FILE_I $(($private_I+1)))
local succ_J=$(get_line $private_FILE_J $(($private_J+1)))
if [ "$line_I" = "$succ_J" ] ; then
echo "$line_J"
let "private_J=$private_J+1"
elif [ "$line_J" = "$succ_I" ] ; then
echo "$line_I"
let "private_I=$private_I+1"
else
# warning, will probably skip some lines
echo "$line_I"
let "private_I=$private_I+1"
fi
fi
done
echo $LINES
}
sum2() {
local A=$1
local B=$2
local T=$3
local pass ta tb tc
local PASSES=$(merge_files $A/$passes_list $B/$passes_list)
mkdir -p $T/$time_dir
cp $A/*.list $T/
rm -f $T/$passes_list
if [ -f $A/$time_dir/$all_time ] && [ -f $B/$time_dir/$all_time ] ; then
echo "$(cat $A/$time_dir/$all_time) + $(cat $B/$time_dir/$all_time)" | bc > $T/$time_dir/$all_time
fi
for pass in $PASSES ; do
if [ -f $A/$time_dir/$pass.time ] && [ -f $B/$time_dir/$pass.time ] ; then
echo "$(cat $A/$time_dir/$pass.time) + $(cat $B/$time_dir/$pass.time)" | bc > $T/$time_dir/$pass.time
echo $pass >> $T/$passes_list
else
if [ -f $A/$time_dir/$pass.time ] ; then
# echo "only A for $pass"
cat $A/$time_dir/$pass.time > $T/$time_dir/$pass.time
echo $pass >> $T/$passes_list
elif [ -f $B/$time_dir/$pass.time ] ; then
# echo "only B for $pass"
cat $B/$time_dir/$pass.time > $T/$time_dir/$pass.time
echo $pass >> $T/$passes_list
fi
fi
if [ -f $A/$pass/$printers_dir/size ] && [ -f $B/$pass/$printers_dir/size ] ; then
mkdir -p $T/$pass/$printers_dir
sum_size $A/$pass/$printers_dir/size $B/$pass/$printers_dir/size $T/$pass/$printers_dir/size
fi
if [ -f $A/$pass/$printers_dir/size_client ] && [ -f $B/$pass/$printers_dir/size_client ] ; then
mkdir -p $T/$pass/$printers_dir
sum_size $A/$pass/$printers_dir/size_client $B/$pass/$printers_dir/size_client $T/$pass/$printers_dir/size_client
fi
done
}
sumN() {
local T=$1
shift
local N=$@
local first acc target
local x=$(echo $N | wc -w)
first=$(echo $N | cut -d' ' -f1)
acc=$(mktemp)
rm -rf $acc
mkdir -p $acc
cp -r $first/* $acc/
N=$(echo $N | cut -d' ' -f2-$x)
for d in $N; do
tmp1=$(mktemp)
rm -rf $tmp1
sum2 $acc $d $tmp1
rm -rf $acc
acc=$tmp1
done
mv $tmp1 $T
}
if [ "$SUM" = 1 ] ; then
sumN $SUMTARGET $DIR
exit 0
fi
# Utils
quit() {
warn "Thank you for using $opatrack !"
exit 0
}
if [ "$COLOR" -eq 1 ]; then
TRACKPATH="$opatrackm:\$ "
else
TRACKPATH="$opatrack:\$ "
fi
set_track_path() {
if [ "$COLOR" -eq 1 ]; then
TRACKPATH="$opatrack:/$1\$ "
else
TRACKPATH="$opatrack:/$1\$ "
fi
}
concat_path() {
local p1="$1"
local p2="$2"
if [ -z "$p1" ] ; then
echo "$p2"
else
echo "$p1/$p2"
fi
}
check_dir() {
if [ ! -d "$1" ] ; then
warn "[!] $opatrack: cannot find directory $1"
exit 1
fi
}
check_file() {
if [ ! -f "$1" ] ; then
warn "[!] $opatrack: cannot find file $1"
exit 1
fi
}
length_of_file() {
wc -l $1 | sed -e 's/ *\(.*\)/\1/g' | cut -d' ' -f1
}
assert_eq() {
if [ ! "$1" = "$2" ] ; then
warn "$opatrack: internal error. assertion failure ($1 != $2)"
exit 5
fi
}
eof_check() {
if [ "$1" = 1 ] && [ -z "$REPLY" ] ; then echo ; quit ; fi
if [ "$REPLY" = "q" ] ; then echo ; quit ; fi
}
get_size() {
# %d declarations
# %d nodes
local file="$1"
if [ -e "$file" ] ; then
local declarations=$(cat $file | grep 'declarations' | cut -d' ' -f1)
local nodes=$(cat $file | grep 'nodes' | cut -d' ' -f1)
echo $declarations $nodes
else
echo 0 0
fi
}
# Evolution ratio between a last value, and a current value.
# the value is expressed like this :
# +3.4 means 1 * 3.4
# -2.5 means 1 / 2.5
# @param $1 last
# @param $2 current
evolution_ratio() {
last=$1
this=$2
if [ ! -n "$last" ] || [ ! -n "$this" ] || [ "$last" = 0 ] || [ "$this" = 0 ] ; then
echo 'nan'
return
fi
ratio=$(echo "scale=4; $this / $last" | bc)
if [ $(echo "$ratio < 1" | bc) = 1 ] ; then
ratio=$(echo "scale=4; 1 / $ratio" | bc)
echo "-$ratio"
else
echo "+$ratio"
fi
}
private_fresh=0
fresh_index() {
private_fresh=$(echo "$private_fresh + 1" | bc)
}
evolution_item() {
local CGI_CALL="$1"
shift
local label="$1"
shift
local data="$*"
fresh_index
local this_fresh=$private_fresh
local this_cgi_call=$CGI_CALL"&label=$label"
cat <<EOF
<b>$label</b> : $data
[
<a href='#' onclick='javascript:document.getElementById("evolution_$this_fresh").innerHTML=document.getElementById("evolution_$this_fresh").innerHTML != "" ? "" : "<object width=700px height=500px data=$this_cgi_call></object>"; return false;'>evolution</a>
]
<div id="evolution_$this_fresh"></div>
EOF
}
# avoid to print .54 instead of 0.54
float_escaped() {
local float="$1"
if [ $(echo "$float < 1" | bc) = "1" ] ; then
float="0"$float
fi
echo "$float"
}
# grep_indexed_auto_selection will select between args
# writting in the tempfile, and returning 0 if ok, 1 if KO
auto_selected_file=$(mktemp /tmp/fileXXXXXX)
grep_indexed_auto_selection() {
echo '' > $auto_selected_file
local ALL="$@"
declare -a tab
local loop=1
local FILES="$ALL"
if [ -z "$ALL" ] ; then
return 1
fi
local IS_FILTER=0
while [ "$loop" = 1 ] ; do
loop=0
i=0
tab[1]=''
count=$(echo $FILES | wc -w | sed -e 's/ *\(.*\)/\1/g')
if [ "$count" -gt 150 ] ; then
echo "There are $count elts, please give a <regexp> !"
read -p "$TRACKPATH"
eof_check "$?"
rep="$REPLY"
if [ "$rep" = "!" ] ; then break ; fi
IS_FILTER=1
FILES=$(for file in $FILES; do echo $file ; done | grep $rep)
loop=1
continue
fi
title "Selection:"
for file in $FILES ; do
let "i=$i+1"
menuitem $i "$file"
tab[$i]=$file
done
if [ "$i" = 0 ] ; then
loop=1
FILES="$ALL"
IS_FILTER=0
continue
fi
if [ "$i" = 1 ] ; then
echo "${tab[1]}" > $auto_selected_file
return 0
fi
if [ "$i" -lt 10 ] ; then
echo "Choose an index, (or '!')"
read -p "$TRACKPATH" -en1
eof_check "$?"
else
echo "Choose an index, or '<regexp>' for filtering or '!' for review all"
read -p "$TRACKPATH"
eof_check "$?"
fi
rep=$REPLY
if [ -z "$rep" ] ; then
loop=1
continue
fi
if [ ! "$rep" = "!" ] && [[ "$rep" != [0-9]* ]]; then
IS_FILTER=1
FILES=$(for file in $FILES; do echo $file ; done | grep $rep)
loop=1
continue
else
if [ "$rep" = "!" ] ; then
if [ "$IS_FILTER" = 1 ] ; then
loop=1
FILES="$ALL"
IS_FILTER=0
continue
else
return 1
fi
else
if [[ "$rep" != [0-9]* ]]; then
warn "integer expected : $rep"
loop=1
continue
else
choice="${tab[$rep]}"
if [ -n "$choice" ] ; then
echo "$choice" > $auto_selected_file
return 0
else
warn "[!] $rep : no such index."
loop=1
fi
fi
fi
fi
done
}
# 1 Retrieve informations
# 1.1 Find directory
# Get to the directory if specified
# If the directory ends with .opx, then go $DIR/_tracks instead
# Can be absolute or relative. Try both
case "$DIR" in
*.opx) DIR="$DIR/_tracks";;
esac
if [ ! -d "$ROOT/$DIR" ] ; then
check_dir "$DIR"
else
if [ -n "$DIR" ] ; then
DIR="$ROOT/$DIR"
else
DIR="$ROOT"
fi
fi
if [ "$dir2_mode" = 1 ] ; then
case "$DIR2" in
*.opx) DIR2="$DIR2/_tracks";;
esac
if [ ! -d "$ROOT/$DIR2" ] ; then
check_dir "$DIR2"
else
if [ -n "$DIR2" ] ; then
DIR2="$ROOT/$DIR2"
else
DIR2="$ROOT"
fi
fi
fi
# 1.2 Check for .list conf
passes_list="$DIR/$passes_list"
printers_list="$DIR/$printers_list"
trackers_list="$DIR/$trackers_list"
check_file "$passes_list"
check_file "$printers_list"
check_file "$trackers_list"
passes_len=$(length_of_file $passes_list)
printers_len=$(length_of_file $printers_list)
trackers_len=$(length_of_file $trackers_list)
# 1.3 Build tables for indexed access
declare -a passes_table
declare -a printers_table
declare -a trackers_table
declare -a trackers_tracked_table
declare -a trackers_length_table
ALL_PASSES=''
ALL_PRINTERS=''
ALL_TRACKERS=''
i=0
while read passname ; do
let "i=$i+1"
passes_table[$i]=$passname
done < $passes_list
ALL_PASSES=$(cat $passes_list)
assert_eq "$i" "$passes_len"
i=0
while read printer_id ; do
let "i=$i+1"
printers_table[$i]=$printer_id
done < $printers_list
ALL_PRINTERS=$(cat $printers_list)
assert_eq "$i" "$printers_len"
i=0
while read tracker_id ; do
let "i=$i+1"
trackers_table[$i]=$tracker_id
done < $trackers_list
ALL_TRACKERS=$(cat $trackers_list)
assert_eq "$i" "$trackers_len"
# collect all tracked values for a given tracker_id
for (( i=1; i<=$trackers_len; i++ )); do
tracker_id="${trackers_table[$i]}"
tracked_file="$DIR/$trackers_dir/$tracker_id.list"
length=$(length_of_file $tracked_file)
trackers_length_table[$i]="$length"
trackers_tracked_table[$i]=$(cat $tracked_file)
done
print_tree() {
title "Passes:"
for (( i=1; i<=$passes_len; i++ )); do
menuitem $i "${passes_table[$i]}"
done
title "Printers:"
if [ "$printers_len" -gt 5 ] ; then
echo -e "\t$printers_len printers"
else
for (( i=1; i<=$printers_len; i++ )); do
menuitem $i "${printers_table[$i]}"
done
fi
title "Trackers:"
if [ "$trackers_len" -gt 5 ] ; then
echo -e "\t$trackers_len trackers"
else
for (( i=1; i<=$trackers_len; i++ )); do
menuitem $i "${trackers_table[$i]} (${trackers_length_table[$i]} elts)"
done
fi
}
index_pass() {
local passname="$1"
for (( i=1; i<=$passes_len; i++ )); do
if [ "${passes_table[$i]}" = "$passname" ] ; then
echo $i
return 0
fi
done
return 1
}
index_printer() {
local printer_id="$1"
for (( i=1; i<=$printers_len; i++ )); do
if [ "${printers_table[$i]}" = "$printer_id" ] ; then
echo $i
return 0
fi
done
return 1
}
index_tracker() {
local tracker_id="$1"
for (( i=1; i<=$trackers_len; i++ )); do
if [ "${trackers_table[$i]}" = "$tracker_id" ] ; then
echo $i
return 0
fi
done
return 1
}
# 2 Pre computation is done. Start the main loop
# 2.1 Some common help manual
general_help() {
cat <<EOF
Welcome to opatrack.
This script is meant to speed-up the diffing between expressions
along passes. You can choose between several modes.
Whenever you get request for an answer :
'?' : get some help about the specific local menu
'!' : get back to the backward menu
'q' : quit opatrack.
Have a nice bug tracking with opatrack !
EOF
}
# Add new modes there if you need.
# GUIDELINES ABOUT MODES :
# + should start a loop, and print $opatrack/$mode ~:$ before inviting read
# + they can starts sub-mode, and should not exit when finished (get back to the parent mode) (except if 'q' is read)
# + they should be documented, and provide an introduction, and a short helpfull help messages resuming command
# + they should return and get back to the parent if '!' is pressed.
# + if you add sub modes, the function should be prefixed with the name of the mode
# + read function should prefix request with TRACKPATH value
# + menus should be cool (hahaha)
# tool (meld)
launch_meld() {
local file1="$1"
local file2="$2"
local file3="$3"
local command=''
if [ -n "$file3" ] ; then
command="$TOOL $TOOL_FLAGS $file1 $file2 $file3"
else
command="$TOOL $TOOL_FLAGS $file1 $file2"
fi
echo "$command"
$command
}
# viewer (less)
launch_less() {
local file1="$1"
local command=''
command="$VIEWER $VIEWER_FLAGS $file1"
echo "$command"
$command
}
filtering_passes() {
local file="$1"
local pass
for pass in $ALL_PASSES ; do
if [ -e "$DIR/$pass/$file" ] ; then
echo $pass
fi
done
}
# GENERIC NODE/LEAF management
# generic shema for the an application_node
# copy past it, and change name with a fresh name
application_node_name() {
# dealing with path
local selfpath='name'
# GENERIC =========================================
local parentpath="$1" #
shift #
selfpath=$(concat_path "$parentpath" "$selfpath") #
set_track_path "$selfpath" #
# =================================================
# other args are options of the node.
help_for_name() {
menuitem "a" "blabla"
menuitem "b" "bloblo"
}
# introduction
cat <<EOF
This is a help message which is printed only once, whenever
we enter the node. After that the loop will start.
EOF
while [ 1 ] ; do
title "Node"
help_for_name
# GENERIC ===================
set_track_path "$selfpath" #
read -p "$TRACKPATH" -en1 #
eof_check "$?" #
case $REPLY in #
# ===========================
# insert there call to other node or leaf
a)
application_node_child "$selfpath" # optionnal args
;;
!)
return
;;
*) # will lead to loop, and rewrite the help
;;
esac
done
}
# This node is for comparing _tracks from 2 different branches
# of the compiler (usefull for comparing code after a huge modif)
node_meld_2bran() {
# GENERIC =========================================
local parentpath="$1" #
shift #
# get arguments
local SUBDIR="$1"
local FILE_FOR_MELD=$(concat_path "$SUBDIR" "$2")
# dealing with path
local selfpath='2bran'
selfpath=$(concat_path "$parentpath" "$selfpath") #
set_track_path "$selfpath" #
# =================================================
# other args are options of the node.
help_for_meld_2bran() {
menuitem "!" "quit meld 2bran mode"
menuitem "q" "quit opatrack"
}
if [ "$passes_len" -le 0 ] ; then
warn "No pass: This mode is not available"
return
fi
title "Meld 2bran: $FILE_FOR_MELD"
local FILTERING_PASSES=$(filtering_passes "$FILE_FOR_MELD")
local number_filtering=$(echo $FILTERING_PASSES | wc -w | sed -e 's/ *\(.*\)/\1/g')
while true ; do
set_track_path "$selfpath"
help_for_meld_2bran
echo "Choose the pass:"
grep_indexed_auto_selection "$FILTERING_PASSES"
code=$?
if [ ! "$code" = 0 ] ; then
return
fi
pass=$(cat $auto_selected_file)
index_pass=$(index_pass $pass)
code=$?
if [ ! "$code" = 0 ] ; then
warn "Pass: $pass Not found (i=$index_pass)"
continue
fi
file1="$DIR/$pass/$FILE_FOR_MELD"
file2="$DIR2/$pass/$FILE_FOR_MELD"
# check that the same file also exists in the other branch
if [ ! -f "$file2" ] ; then
warn "File: $file2 Not available"
continue
fi
if diff -q $file1 $file2 >/dev/null; then
warn "The files are identical, not running $TOOL"
warn "run $TOOL anyway (y/*) ?"
read -p '' -n1
eof_check "$?"
echo ''
if [ "$REPLY" = "y" ] ; then
launch_meld "$file1" "$file2"
fi
else
launch_meld "$file1" "$file2"
fi
if [ "$number_filtering" -le 1 ]; then
break
fi
done
}
# find quickly the changes
node_meld_2chan() {
# GENERIC =========================================
local parentpath="$1" #
shift #
# get arguments
local SUBDIR="$1"
local FILE_FOR_MELD=$(concat_path "$SUBDIR" "$2")
local LOG="$3"
# dealing with path
local selfpath='2chan'
selfpath=$(concat_path "$parentpath" "$selfpath") #
set_track_path "$selfpath" #
# =================================================
# other args are options of the node.
help_for_meld_2chan() {
menuitem "!" "quit meld 2chan mode"
menuitem "q" "quit opatrack"
}
if [ "$passes_len" -le 0 ] ; then
warn "No pass: This mode is not available"
return
fi
title "Meld 2chan: $FILE_FOR_MELD"
local FILTERING_PASSES=$(filtering_passes "$FILE_FOR_MELD")
local number_filtering=$(echo $FILTERING_PASSES | wc -w | sed -e 's/ *\(.*\)/\1/g')
set_track_path "$selfpath"
# help_for_meld_2chan
local no_changes=1
local i=0
if [ "$LOG" = 'LOG' ] ; then
echo "list of passes with changes:"
else
# avoid to delete the previous line
echo
fi
local always_meld=0
for pass in $FILTERING_PASSES ; do
let "i=$i+1"
file1="$DIR/$pass/$FILE_FOR_MELD"
file2="$DIR2/$pass/$FILE_FOR_MELD"
# check that the same file also exists in the other branch
if [ ! -f "$file2" ] ; then
warn "File: $file2 Not available"
continue
fi
if [ "$LOG" = 'LOG' ] ; then
if ! diff -q $file1 $file2 >/dev/null; then
no_changes=0
echo "$pass" >> $LOGFILE
fi
else
if diff -q $file1 $file2 >/dev/null; then
printf ""
printf "pass %d/%d (%s) : no changes\n" $i $number_filtering "$pass"
else
no_changes=0
echo "$pass: changes"
if [ "$always_meld" = 1 ] ; then
launch_meld "$file1" "$file2"
else
warn "run $TOOL (y/a/*) ?"
read -p '' -n1
eof_check "$?"
echo ''
case $REPLY in
y)
launch_meld "$file1" "$file2"
;;
a)
always_meld=1
launch_meld "$file1" "$file2"
;;
!)
return
;;
*)
;;
esac
fi
fi
fi
done
if [ "$no_changes" = 1 ] ; then
echo "no changes on $FILE_FOR_MELD"
fi
}
node_2branches() {
# dealing with path
local selfpath='2bran'
# GENERIC =========================================
local parentpath="$1" #
shift #
local printers_dir=$1
local FILE_FOR_MELD=$2
selfpath=$(concat_path "$parentpath" "$selfpath") #
set_track_path "$selfpath" #
# =================================================
# other args are options of the node.
help_for_name() {
menuitem "d" "2-bran sub-mode"
menuitem "c" "2-chan sub-mode"
menuitem "l" "2-log sub-mode"
menuitem "!" "quit printers mode"
menuitem "q" "quit opatrack"
}
while [ 1 ] ; do
title "2branches"
help_for_name
# GENERIC ===================
set_track_path "$selfpath" #
read -p "$TRACKPATH" -en1 #
eof_check "$?" #
case $REPLY in #
# ===========================
# insert there call to other node or leaf
d)
node_meld_2bran "$selfpath" "$printers_dir" "$FILE_FOR_MELD"
;;
c)
node_meld_2chan "$selfpath" "$printers_dir" "$FILE_FOR_MELD"
;;
l)
node_meld_2chan "$selfpath" "$printers_dir" "$FILE_FOR_MELD" 'LOG'
;;
!)
return
;;
*) # will lead to loop, and rewrite the help
;;
esac
done
}
node_meld_2cons() {
# GENERIC =========================================
local parentpath="$1" #
shift #
# get arguments
local SUBDIR="$1"
local FILE_FOR_MELD=$(concat_path "$SUBDIR" "$2")
local FREE="$3"
# dealing with path
local selfpath=''
if [ "$FREE" = 'FREE' ] ; then
selfpath='2free'
else
selfpath='2cons'
fi
selfpath=$(concat_path "$parentpath" "$selfpath") #
set_track_path "$selfpath" #
# =================================================
# other args are options of the node.
help_for_meld_2cons() {
menuitem "!" "quit meld 2cons mode"
menuitem "q" "quit opatrack"
}
if [ "$passes_len" -le 1 ] ; then
warn "Only 1 pass: Melds mode are not available"
return
fi
title "Meld 2cons: $FILE_FOR_MELD"
local FILTERING_PASSES=$(filtering_passes "$FILE_FOR_MELD")
local number_filtering=$(echo $FILTERING_PASSES | wc -w | sed -e 's/ *\(.*\)/\1/g')
while true ; do
set_track_path "$selfpath"
help_for_meld_2cons
echo "Choose the left pass:"
grep_indexed_auto_selection "$FILTERING_PASSES"
code=$?
if [ ! "$code" = 0 ] ; then
return
fi
pass1=$(cat $auto_selected_file)
index_pass1=$(index_pass $pass1)
code=$?
if [ ! "$code" = 0 ] ; then
warn "Pass: $pass1 Not found (i=$index_pass1)"
continue
fi
if [ "$index_pass1" = "$passes_len" ] ; then
warn "[!] 2cons mode cannot be runned from last pass"
continue
fi
if [ "$FREE" = 'FREE' ] ; then
echo "Choose the right pass:"
grep_indexed_auto_selection "$ALL_PASSES"
code=$?
if [ ! "$code" = 0 ] ; then
return
fi
pass2=$(cat $auto_selected_file)
index_pass2=$(index_pass $pass2)
code=$?
if [ ! "$code" = 0 ] ; then
warn "Pass: $pass2 Not found (i=$index_pass2)"
continue
fi
else
index_pass2=$(($index_pass1+1))
pass2=${passes_table[$index_pass2]}
fi
file1="$DIR/$pass1/$FILE_FOR_MELD"
file2="$DIR/$pass2/$FILE_FOR_MELD"
if diff -q $file1 $file2 >/dev/null; then
warn "This pass caused no changes, not running $TOOL"
warn "run $TOOL anyway (y/*) ?"
read -p '' -n1
eof_check "$?"
echo ''
if [ "$REPLY" = "y" ] ; then
launch_meld "$file1" "$file2"
fi
else
launch_meld "$file1" "$file2"
fi
if [ "$number_filtering" -le 2 ]; then
break
fi
done
}
node_meld_3cons() {
# GENERIC =========================================
local parentpath="$1" #
shift #
# get arguments
local SUBDIR="$1"
local FILE_FOR_MELD=$(concat_path "$SUBDIR" "$2")
local FREE="$3"
# dealing with path
local selfpath=''
if [ "$FREE" = 'FREE' ] ; then
selfpath='3free'
else
selfpath='3cons'
fi
selfpath=$(concat_path "$parentpath" "$selfpath") #
set_track_path "$selfpath" #
# =================================================
# other args are options of the node.
help_for_meld_3cons() {
menuitem "!" "quit meld 2cons mode"
menuitem "q" "quit opatrack"
}
if [ "$passes_len" -le 2 ] ; then
warn "Only $passes_len pass(es): 3cons mode is not available"
return
fi
title "Meld 3cons: $FILE_FOR_MELD"
local FILTERING_PASSES=$(filtering_passes "$FILE_FOR_MELD")
local number_filtering=$(echo $FILTERING_PASSES | wc -w | sed -e 's/ *\(.*\)/\1/g')
while true ; do
set_track_path "$selfpath"
help_for_meld_3cons
echo "Choose the first pass:"
grep_indexed_auto_selection "$FILTERING_PASSES"
code=$?
if [ ! "$code" = 0 ] ; then
return
fi
pass1=$(cat $auto_selected_file)
index_pass1=$(index_pass $pass1)
code=$?
if [ ! "$code" = 0 ] ; then
warn "Pass: $pass1 Not found (i=$index_pass1)"
continue
fi
if [ "$index_pass1" -gt $(($passes_len - 2)) ] ; then
warn "[!] 3cons mode cannot be runned from 2 last passes"
continue
fi
if [ "$FREE" = 'FREE' ] ; then
echo "Choose the midle pass:"
grep_indexed_auto_selection "$ALL_PASSES"
code=$?
if [ ! "$code" = 0 ] ; then
return
fi
pass2=$(cat $auto_selected_file)
index_pass2=$(index_pass $pass2)
code=$?
if [ ! "$code" = 0 ] ; then
warn "Pass: $pass2 Not found (i=$index_pass2)"
continue
fi
echo "Choose the right pass:"
grep_indexed_auto_selection "$ALL_PASSES"
code=$?
if [ ! "$code" = 0 ] ; then
return
fi
pass3=$(cat $auto_selected_file)
index_pass3=$(index_pass $pass3)
code=$?
if [ ! "$code" = 0 ] ; then
warn "Pass: $pass3 Not found (i=$index_pass3)"
continue
fi
else
index_pass2=$(($index_pass1+1))
pass2=${passes_table[$index_pass2]}
index_pass3=$(($index_pass1+2))
pass3=${passes_table[$index_pass3]}
fi
launch_meld "$DIR/$pass1/$FILE_FOR_MELD" "$DIR/$pass2/$FILE_FOR_MELD" "$DIR/$pass3/$FILE_FOR_MELD"
if [ "$number_filtering" -le 3 ]; then
break
fi
done
}
node_printers() {
# dealing with path
local selfpath='printers'
# GENERIC =========================================
local parentpath="$1" #
shift #
selfpath=$(concat_path "$parentpath" "$selfpath") #
set_track_path "$selfpath" #
# =================================================
local FILE_FOR_MELD=''
# other args are options of the node.
help_for_printers() {
menuitem "2" "2-cons sub-mode"
menuitem "3" "3-cons sub-mode"
menuitem "f" "2-free sub-mode"
menuitem "g" "3-free sub-mode"
if [ "$dir2_mode" = 1 ] ; then
menuitem "d" "2-branches mode"
fi
menuitem "!" "quit printers mode"
menuitem "q" "quit opatrack"
}
local all_printers_path="$selfpath"
if [ "$printers_len" -le 0 ] ; then
warn "No printer available"
return
fi
while [ 1 ] ; do
set_track_path "$all_printers_path"
# select the file
grep_indexed_auto_selection "$ALL_PRINTERS"
FILE_FOR_MELD=$(cat $auto_selected_file)
if [ -z "$FILE_FOR_MELD" ] ; then
warn "No file to meld."
return
fi
# introduction
selfpath="$all_printers_path/$FILE_FOR_MELD"
while [ 1 ] ; do
title "Printer: $FILE_FOR_MELD"
help_for_printers
# GENERIC ===================
set_track_path "$selfpath" #
read -p "$TRACKPATH" -en1 #
eof_check "$?" #
case $REPLY in #
# ===========================
# insert there call to other node or leaf
2)
node_meld_2cons "$selfpath" "$printers_dir" "$FILE_FOR_MELD" 'CONS'
;;
3)
node_meld_3cons "$selfpath" "$printers_dir" "$FILE_FOR_MELD" 'CONS'
;;
f)
node_meld_2cons "$selfpath" "$printers_dir" "$FILE_FOR_MELD" 'FREE'
;;
g)
node_meld_3cons "$selfpath" "$printers_dir" "$FILE_FOR_MELD" 'FREE'
;;
d)
if [ "$dir2_mode" = 0 ] ; then
echo "2branches mode is not available"
else
node_2branches "$selfpath" "$printers_dir" "$FILE_FOR_MELD"
fi
;;
!)
break
;;
*) # will lead to loop, and rewrite the help
;;
esac
done
done
}
node_trackers_this() {
# GENERIC =========================================
local parentpath="$1" #
shift #
# get arguments
local tracker_id="$1"
# dealing with path
local selfpath=$(concat_path "$parentpath" "$tracker_id") #
set_track_path "$selfpath" #
# =================================================
local FILE_FOR_MELD=''
# select the tracked values
local tracker_id_index=$(index_tracker "$tracker_id")
local code=$?
if [ ! $code = 0 ] ; then
warn "Unknown tracker_id: $tracker_id"
return
fi
local ALL_TRACKED="${trackers_tracked_table[$tracker_id_index]}"
local this_tracker_path="$selfpath"
# other args are options of the node.
help_for_trackers_this() {
menuitem "2" "2-cons sub-mode"
menuitem "3" "3-cons sub-mode"
menuitem "f" "2-free sub-mode"
menuitem "g" "3-free sub-mode"
menuitem "!" "quit printers mode"
menuitem "q" "quit opatrack"
}
while [ 1 ] ; do
set_track_path "$this_tracker_path"
grep_indexed_auto_selection "$ALL_TRACKED"
FILE_FOR_MELD=$(cat $auto_selected_file)
if [ -z "$FILE_FOR_MELD" ] ; then
warn "No file to meld."
return
fi
selfpath=$(concat_path "$this_tracker_path" "$FILE_FOR_MELD") #
# introduction
while [ 1 ] ; do
title "Tracker $tracker_id: Tracked --> '$FILE_FOR_MELD'"
help_for_trackers_this
# GENERIC ===================
set_track_path "$selfpath" #
read -p "$TRACKPATH" -en1 #
eof_check "$?" #
case $REPLY in #
# ===========================
# insert there call to other node or leaf
2)
node_meld_2cons "$selfpath" "$trackers_dir/$tracker_id" "$FILE_FOR_MELD" 'CONS'
;;
3)
node_meld_3cons "$selfpath" "$trackers_dir/$tracker_id" "$FILE_FOR_MELD" 'CONS'
;;
f)
node_meld_2cons "$selfpath" "$trackers_dir/$tracker_id" "$FILE_FOR_MELD" 'FREE'
;;
g)
node_meld_3cons "$selfpath" "$trackers_dir/$tracker_id" "$FILE_FOR_MELD" 'FREE'
;;
!)
break
;;
*) # will lead to loop, and rewrite the help
;;
esac
done
done
}
node_trackers() {
# dealing with path
local selfpath='trackers'
# GENERIC =========================================
local parentpath="$1" #
shift #
selfpath=$(concat_path "$parentpath" "$selfpath") #
set_track_path "$selfpath" #
# =================================================
# select the tracker_id
while [ 1 ] ; do
set_track_path "$selfpath" #
title "Choose a tracker"
grep_indexed_auto_selection "$ALL_TRACKERS"
tracker_id=$(cat $auto_selected_file)
if [ -z "$tracker_id" ] ; then
warn "No such tracker."
return
fi
node_trackers_this "$selfpath" "$tracker_id"
done
}
main() {
local selfpath=''
help_for_main() {
menuitem 'p' "printers"
menuitem 't' "trackers"
menuitem '@' "at pass"
menuitem 'i' "internal errors"
menuitem 'c' "conditions"
menuitem 'x' "print tree"
menuitem 'h' "general help"
menuitem '?' "help"
menuitem 'q' "quit"
}
print_tree
while [ 1 ] ; do
title "Choose a mode to run"
help_for_main
# GENERIC ===================
set_track_path "$selfpath" #
read -p "$TRACKPATH" -en1 #
eof_check "$?" #
case $REPLY in #
# ===========================
p)
node_printers "$selfpath"
;;
t)
node_trackers "$selfpath"
;;
@)
node_passes "$selfpath"
;;
i)
node_internal "$selfpath"
;;
c)
node_check "$selfpath"
;;
x)
print_tree
;;
h)
general_help
read -p "press any key to continue..." -n1
eof_check "$?"
print_tree
;;
!)
return
;;
*) # will lead to loop, and rewrite the help
;;
esac
done
}
# start the main menu
# todo : see in what case we are, add main2 for comparing 2 or 3 directories of compilation
if [ "$REPORT_MODE" = 0 ] ; then
main
exit 0
fi
# ===================================================================================
# ===================================================================================
# ===================================================================================
# this is the report mode
all_time_value=$(cat "$DIR/$time_dir/$all_time")
last_declarations=''
last_nodes=''
noninstant_passes=$(cat $passes_list | wc -l)
mean_time_ratio=$(bc <<<"scale=2; 100. / $noninstant_passes")
echo -n > $html_trace
echo -n > $raw_trace
# starts the raw trace with the global time
cat >> $raw_trace <<EOF
GLOBAL
Time $all_time_value
EOF
time_color () {
local ratio=$1
local value=$(bc -l <<<"256 * a($ratio / $mean_time_ratio) / (2*a(1))") # a() is arc-tangent
local value=$(bc <<<"$value / 1")
printf '#%02x00%02x' $value $((255 - value))
}
global_evolution_item () {
local label=$1;
local OBJECT="<object width=100% data=$CGI_LOCATION/opatrack-global.cgi?entityident=$entityident&label=$label></object>"
cat <<EOF
<a href='#' onclick='javascript:document.getElementById("global_evolution").innerHTML = "$OBJECT"; return false;'>$label</a>
EOF
}
# transforms .12 into 0.12
# input is the standard input, not the command line
add_leading_zero() {
sed -e 's/^\./0./'
}
# making bc output compatible with html
# which means a number before the decimal point
bc() {
command bc "$@" | add_leading_zero
}
# same for the html trace
echo "<h4> date of creation : $(date)</h4>" >> $html_trace
echo "<h4> PassTracker : $entityident</h4>" >> $html_trace
CGI_CALL=$CGI_LOCATION"/opatrack.cgi?entityident=$entityident&passname=GLOBAL"
cat >> $html_trace <<EOF
<!-- GLOBAL -->
Raw log of the execution : <a href="$entityident.log"> there </a><br/>
Raw trace of tracker (e.g. for scripts) : <a href="$raw_trace"> there </a><br/>
<br/>
Show global evolution for [ $(S=""; for label in Time Declarations Nodes; do echo $S; global_evolution_item $label; S=" | "; done) ]<br/>
<div style="margin:auto; width:75%;" id="global_evolution"></div>
<br/>
<table>
<tr>
<td><h4><a class="test" href="#" onclick="toggle_source(0); return false">Global Execution</a></h4></td>
<td width="800px">
<div style="border: 2px solid grey; margin-left: auto; padding: 0;" width="100%">
<table style="border: none;" width="100%">
<tr>
<!-- TODO: the color depends on the historic red: slower than normal, magenta normal, and an other, quicker -->
<td style="background: $(time_color "0.");" width="$mean_time_ratio%" height="10px"></td>
<td style="background: $(time_color "100.");" width="$(bc <<<"scale=2; 100. - $mean_time_ratio")%" height="10px"></td>
</tr>
</table>
<table style="border: none; border-top: 2px solid grey;" width="100%">
<tr>
<td style="background: green;" width="100%" height="10px"></td>
</tr>
</table>
</div>
<div class="test_source" id="test_source_0">
EOF
# This is the part which is toggled
evolution_item "$CGI_CALL" "Time" "$all_time_value" "sec" >> $html_trace
cat >> $html_trace <<EOF
</div>
</td>
</tr>
EOF
# first, going through all the passes to get the maximum
# number of nodes in the code
max_nodes=0
for ((i=1;i<=$passes_len;i++)); do
passname="${passes_table[$i]}"
pass_size_file="$DIR/$passname/$printers_dir/$size_file"
pass_size=$(get_size $pass_size_file)
nodes=$(echo $pass_size | cut -d' ' -f2)
if ((max_nodes < nodes)); then max_nodes=$nodes; fi
done
for ((i=1;i<=$passes_len;i++)); do
passname="${passes_table[$i]}"
if [ -t 1 ]; then # only displaying when stdout is a tty
[ $i -eq 1 ] || printf "" # go one line up, erase the whole line, go to 0th column
printf "pass %d/%d (%s)\n" $i $passes_len "$passname"
fi
# time
# echo "time"
this_time=$(cat "$DIR/$time_dir/$passname.time")
if [ ! -n "$this_time" ] ; then this_time="0" ; fi
this_time_ratio=$(echo "scale=2; $this_time * 100 / $all_time_value" | bc)
this_time_ratio_complement=$(echo "scale=2; 100 - $this_time_ratio" | bc)
this_time_ratio=$(float_escaped "$this_time_ratio")
this_time_ratio_complement=$(float_escaped "$this_time_ratio_complement")
# size
# echo "size"
pass_size_file="$DIR/$passname/$printers_dir/$size_file"
pass_size=$(get_size $pass_size_file)
this_declarations=$(echo $pass_size | cut -d' ' -f1)
this_nodes=$(echo $pass_size | cut -d' ' -f2)
this_declarations_ratio=$(evolution_ratio $last_declarations $this_declarations)
this_nodes_ratio=$(evolution_ratio $last_nodes $this_nodes)
this_max_nodes_ratio=$(bc <<<"scale=2; $this_nodes * 100. / $max_nodes" 2>/dev/null)
this_max_nodes_ratio_complement=$(bc <<<"scale=2; 100. - $this_max_nodes_ratio" 2>/dev/null)
# speed per nodes
# echo "speed"
this_speed_per_node=$(bc <<< "scale=2; $this_nodes / $this_time" 2> /dev/null)
last_declarations="$this_declarations"
last_nodes="$this_nodes"
# Raw trace
# keep synchonized with label given in the html for cgi purpose
cat >> $raw_trace <<EOF
$passname
Time $this_time
TimeRatio $this_time_ratio %
Declarations $this_declarations
DeclarationsRatio $this_declarations_ratio
Nodes $this_nodes
NodesRatio $this_nodes_ratio
MaxNodesRatio $this_max_nodes_ratio
SpeedPerNode $this_speed_per_node
EOF
# Html trace
# echo "html trace"
CGI_CALL=$CGI_LOCATION"/opatrack.cgi?entityident=$entityident&passname=$passname"
cat >> $html_trace <<EOF
<!-- PASS : $passname -->
<tr>
<td><h4><a class="test" href="#" onclick="toggle_source($i); return false">$passname</a></h4></td>
<td width="800px">
<div style="border: 2px solid grey; margin-left: auto; padding: 0;" width="100%">
<table style="border: none;" width="100%">
<tr>
<!-- TODO: the color depends on the historic red: slower than normal, magenta normal, and an other, quicker -->
<td style="background: $(time_color $this_time_ratio);" width="$this_time_ratio%" height="10px"></td>
$(if [ "$this_time_ratio_complement" != "0.0" ]; then
echo "<td width=\"$this_time_ratio_complement%\" height=\"10px\"></td>"; fi)
</tr>
</table>
<table style="border: none; border-top: 2px solid grey" width="100%">
<tr>
<td style="background: green;" width="$this_max_nodes_ratio%" height="10px"></td>
$(if [ "$this_max_nodes_ratio_complement" != "0" ]; then
echo "<td width=\"$this_max_nodes_ratio_complement%\" height=\"10px\"></td>"; fi)
</tr>
</table>
</div>
<div class="test_source" id="test_source_$i">
EOF
# This is the part which is toggled
# echo "evolution item"
evolution_item "$CGI_CALL" "Time" "$this_time" "sec" >> $html_trace
evolution_item "$CGI_CALL" "TimeRatio" "$this_time_ratio" "%" >> $html_trace
evolution_item "$CGI_CALL" "Declarations" "$this_declarations" "decls" >> $html_trace
evolution_item "$CGI_CALL" "DeclarationsRatio" "$this_declarations_ratio" >> $html_trace
evolution_item "$CGI_CALL" "Nodes" "$this_nodes" "nodes" >> $html_trace
evolution_item "$CGI_CALL" "NodesRatio" "$this_nodes_ratio" >> $html_trace
evolution_item "$CGI_CALL" "MaxNodesRatio" "$this_max_nodes_ratio" >> $html_trace
evolution_item "$CGI_CALL" "SpeedPerNode" "$this_speed_per_node" >> $html_trace
cat >> $html_trace <<EOF
</div>
</td>
</tr>
EOF
done
cat >> $html_trace <<EOF
</table>
<br/>
EOF
Jump to Line
Something went wrong with that request. Please try again.