#!/bin/sh

# Copyright (C) 1994-2016 Lawrence Livermore National Security, LLC.
# LLNL-CODE-425250.
# All rights reserved.
# 
# This file is part of Silo. For details, see silo.llnl.gov.
# 
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
# 
#    * Redistributions of source code must retain the above copyright
#      notice, this list of conditions and the disclaimer below.
#    * Redistributions in binary form must reproduce the above copyright
#      notice, this list of conditions and the disclaimer (as noted
#      below) in the documentation and/or other materials provided with
#      the distribution.
#    * Neither the name of the LLNS/LLNL nor the names of its
#      contributors may be used to endorse or promote products derived
#      from this software without specific prior written permission.
# 
# THIS SOFTWARE  IS PROVIDED BY  THE COPYRIGHT HOLDERS  AND CONTRIBUTORS
# "AS  IS" AND  ANY EXPRESS  OR IMPLIED  WARRANTIES, INCLUDING,  BUT NOT
# LIMITED TO, THE IMPLIED  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A  PARTICULAR  PURPOSE ARE  DISCLAIMED.  IN  NO  EVENT SHALL  LAWRENCE
# LIVERMORE  NATIONAL SECURITY, LLC,  THE U.S.  DEPARTMENT OF  ENERGY OR
# CONTRIBUTORS BE LIABLE FOR  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
# EXEMPLARY, OR  CONSEQUENTIAL DAMAGES  (INCLUDING, BUT NOT  LIMITED TO,
# PROCUREMENT OF  SUBSTITUTE GOODS  OR SERVICES; LOSS  OF USE,  DATA, OR
# PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
# LIABILITY, WHETHER  IN CONTRACT, STRICT LIABILITY,  OR TORT (INCLUDING
# NEGLIGENCE OR  OTHERWISE) ARISING IN  ANY WAY OUT  OF THE USE  OF THIS
# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# 
# This work was produced at Lawrence Livermore National Laboratory under
# Contract  No.   DE-AC52-07NA27344 with  the  DOE.  Neither the  United
# States Government  nor Lawrence  Livermore National Security,  LLC nor
# any of  their employees,  makes any warranty,  express or  implied, or
# assumes   any   liability   or   responsibility  for   the   accuracy,
# completeness, or usefulness of any information, apparatus, product, or
# process  disclosed, or  represents  that its  use  would not  infringe
# privately-owned   rights.  Any  reference   herein  to   any  specific
# commercial products,  process, or  services by trade  name, trademark,
# manufacturer or otherwise does not necessarily constitute or imply its
# endorsement,  recommendation,   or  favoring  by   the  United  States
# Government or Lawrence Livermore National Security, LLC. The views and
# opinions  of authors  expressed  herein do  not  necessarily state  or
# reflect those  of the United  States Government or  Lawrence Livermore
# National  Security, LLC,  and shall  not  be used  for advertising  or
# product endorsement purposes.

# ----------------------------------------------------------------------------
# Purpose: Difference two silo files and/or directories containing silo files 
#
# Programmer: Mark C. Miller
# Creation:   January 21, 2009
#
# Modifications:
#   Mark C. Miller, Wed Mar 11 10:03:10 PDT 2009
#   Added browserOptsDef and set lowlevel to 0. That is important when
#   diff'ing HDF5 files.
#
#   Mark C. Miller, Wed Dec  2 11:47:31 PST 2009
#   Added logic to use path to browser that is 'next to' silodiff or fall
#   back what a browser in path, but issue a warning if they are somehow
#   different.
#
#   Mark C. Miller, Fri Dec  4 09:58:17 PST 2009
#   Made it possible to override browser path warning
# ----------------------------------------------------------------------------
#

#
# Handle Command Line Arguments
#
tmpDir=$TMPDIR
if test -z "$tmpDir"; then
    if test -d /usr/tmp; then
       tmpDir=/usr/tmp
    elif test -d /tmp; then
       tmpDir=/tmp
    else
       tmpDir=`(cd ~; pwd -P)`
    fi
fi
optError=0
browserOptsDef="-l 0"
browserOpts=""
arg1=
arg2=
recurse=0
verbose=0
override=0
for options
do
   case $1 in
      "")
         # handle empty argument
         ;;
      help|-help|--help)
         optError=1
         shift
         ;;
      -recurse|--recurse)
         recurse=1
         shift
         ;;
      -verbose|--verbose)
         verbose=1
         shift
         ;;
      -override-browser-warning|--override-browser-warning)
         override=1
         shift
         ;;
      *)
         if test -e $1; then
             if test -z "$arg1"; then
                 arg1=$1
             else
                 arg2=$1
             fi
         else
             browserOpts="$browserOpts $1"
         fi
         shift
         ;;
   esac
done

#
# Check path to browser and issue error/warning if necessary
#
brexe=browser
sddir=$(dirname $0)
if test -x ${sddir}/browser; then
    brexe=${sddir}/browser
else
    brdir=$(dirname $(which browser))
    if test $brdir != $sddir; then
        leader="*WARNING*"
        if test $override -eq 0; then
            leader="*ERROR*"
        fi
        echo "$leader"
        echo "$leader Using browser at \"$brdir\"."
        echo "$leader and silodiff at \"$sddir\"."
        echo "$leader"
        if test $override -eq 0; then
            echo "$leader Override with \"--override-browser-warning\" option."
            exit 1
        fi
    fi
fi
sfexe=silofile
if test -x ${sddir}/silofile; then
    sfexe=${sddir}/silofile
fi
if test $optError = 1 -o -z "$arg1" -o -z "$arg2"; then
    echo "Usage:  $0 <file|dir> <file|dir> <options>"
    echo ""
    echo "Options:"
    echo "    -help:            print this help message"
    echo "    -recurse:         recurse on directories"
    echo "    -verbose:         report names of file(s) as they are processed."
    echo ""
    echo "If both arguments are files, $0 will attempt to diff the files."
    echo ""
    echo "If one argument is a file and the other a directory, then $0 will attempt"
    echo "to diff the given file with a file by the same name in the given directory."
    echo ""
    echo "If both arguments are directories, $0 will descend into each directory"
    echo "(and will do so recursively if '-recurse' is specified)  finding files"
    echo "whose names differ ONLY in the first component of their paths and attempt"
    echo "to diff them."
    echo ""
    echo "$0 uses Silo's browser tool to do its work. In turn, browser supports a"
    echo "number of additional options. Thus, any arguments to $0 which are neither"
    echo "files nor directories are treated as arguments to browser itself. For some"
    echo "options to browser like the '-f FILE' option, use the '--file=<FILE>'"
    echo "variant instead. By default, $0 will invoke browser with args"
    echo "'$browserOptsDef'. The available options to browser are..."
    echo ""
    $brexe --help 2>&1 | grep -v SWITCHES
    exit 1
fi

if test -d $arg1 -a -d $arg2; then # both are dirs
    if test $recurse -eq 1 -a $verbose -eq 1; then
        echo "Recursively diffing directories..."
    fi
    # Iterate through all members of dir $arg1 finding
    # those in or not in common with dir $arg2
    arg1_files_tmp=`ls -1rt $arg1`
    common_members=""
    not_common_members=""
    for f in $arg1_files_tmp; do
        if test -d $arg1/$f -a -d $arg2/$f -a $recurse -eq 1; then
            common_members="$f $common_members"
        elif test -f $arg1/$f -a -f $arg2/$f; then
            if test -n "$($sfexe $arg1/$f | grep PDB\\\|HDF)"; then
                common_members="$f $common_members"
            else
                not_common_members="$arg1/$f $not_common_members"
            fi
        else
            if test $verbose -eq 1; then
                not_common_members="$arg1/$f $not_common_members"
            fi
        fi
    done
    # If in verbose mode, continue to iterate through dir $arg2
    # finding everything else not in common with dir $arg1
    if test $verbose -eq 1; then
        arg2_files_tmp=`ls -1rt $arg2`
        for f in $arg2_files_tmp; do
            if test -d $arg1/$f -a -d $arg2/$f -a $recurse -eq 1; then
               true
            elif test -f $arg1/$f -a -f $arg2/$f; then
               true
            else
                not_common_members="$arg2/$f $not_common_members"
            fi
        done
        for f in $not_common_members; do
            echo "    Skipping \"$f\"."
        done
    fi
    for f in $common_members; do
        if test -d $arg1/$f -a -d $arg2/$f -a $recurse -eq 1; then
            if test $verbose -eq 1; then
                echo "Recusively diffing directories \"$arg1/$f\" and \"$arg2/$f\"..."
                $0 -recurse -verbose $browserOpts $arg1/$f $arg2/$f
            else
                $0 -recurse $browserOpts $arg1/$f $arg2/$f
            fi
        elif test -f $arg1/$f -a -f $arg2/$f; then
            test $verbose -eq 1 && echo "Diffing files \"$arg1/$f\" and \"$arg2/$f\"..."
            $brexe $browserOptsDef $browserOpts -e diff $arg1/$f $arg2/$f
        else
            true
        fi
    done
elif test -d $arg1 -o -d $arg2; then # one is dir
    if test -d $arg1; then
        $brexe $browserOptsDef $browserOpts -e diff $arg1/$arg2 $arg2
    else
        $brexe $browserOptsDef $browserOpts -e diff $arg1 $arg2/$arg1
    fi
else # neither are dirs
    $brexe $browserOptsDef $browserOpts -e diff $arg1 $arg2
fi
