#!/bin/sh  
# \
exec oagwish "$0" "$@"

#
# $Log: not supported by cvs2svn $
# Revision 1.14  2003/01/23 19:47:07  soliday
# The accelerator subnet changed to accel.ntw0rk
#
# Revision 1.13  1996/06/13 18:51:11  saunders
# Logging enabled only on helios subnet.
#
# Revision 1.12  1996/06/10 19:11:23  saunders
# Changed logMessage cmds to use default logDaemon.
#
# Revision 1.11  1996/06/04 19:29:46  saunders
# Changed serviceId and location of log files.
#
# Revision 1.10  1996/05/16 15:57:13  saunders
# Accidentally left debug directories enabled.
#
# Revision 1.9  1996/05/16 15:48:36  saunders
# Changed sourceId string.
#
# Revision 1.8  1996/05/08 20:57:20  saunders
# Re-enabled net domain check.
#
# Revision 1.7  1996/05/08 20:46:22  saunders
# Heavily revised to list CVS modules, not individual applications.
#
# Revision 1.6  1996/05/08 17:42:44  saunders
# Last stage of 2 arch. approach before changing to use cvs "modules".
#
# Revision 1.5  1996/05/02 16:22:14  saunders
# Altered to track sun4 and solaris architectures separately.
#
# Revision 1.4  1996/04/26 13:53:23  saunders
# Ported to use V2.0 of logDaemon. Some minor interface changes.
#
# Revision 1.3  1996/03/14 21:57:51  saunders
# Intermediate stage save.
#
# Revision 1.2  1996/03/13 23:36:18  saunders
# Saving intermediate progress.
#
# Revision 1.1  1996/03/06 21:26:15  saunders
# Initial work. Not functional yet.
#
#

set auto_path [linsert $auto_path 0  /usr/local/oag/apps/lib/$env(HOST_ARCH)]
set auto_path [linsert $auto_path 0 /usr/local/oag/lib_patch/$env(HOST_ARCH)]
set CVSRevisionAuthor "\$Revision: 1.15 $ \$Author: soliday $"

set CVSRepository NotChosenYet
set CVSRepositoryManager(EPICS) "jba@aps.anl.gov"
set CVSRepositoryManager(OAG) "saunders@aps.anl.gov"
set OAGDir /usr/local/oag/apps
#set OAGDir /home/phebos/SAUNDERS/oag/apps
set EPICSDir /usr/local/epics/extensions

set OAGsrcDir $OAGDir/src
set OAGdocDir $OAGDir/notes
set EPICSsrcDir $EPICSDir/src
set EPICSdocDir $EPICSDir/notes

set logDir /home/helios/oagData/logDaemonData
#set logDir /home/phebos/SAUNDERS/oagData/logDaemonData
set sourceId appBuildAudit
set serviceId oag
set logFile $sourceId.log
set userEmail "$env(USER)@aps.anl.gov"
set userGroups [split [exec groups]]

set networkDomain [exec domainname]

# Vars for New Release Build submit form
set newAppName ""
set newAppChangeCommit 0
set newAppReleaseCommit 0
set newAppTest 0
set newAppStatus 1
set newAppEmail ""

# Vars for Build Acknowledgement form
set buildAckBuilt 0
set buildAckSerial 0
set buildAckTest 0
set buildAckStatus 0
set buildAckEmail ""

#
# Procedure Definitions
#

#
# Load application lists with apps in selected repository
#
proc loadAppList {} {
    global apps 
    loadArchAppList $apps
}

proc loadArchAppList {appWidget} {
    global newAppEmail newAppName lastLogStatus status CVSRepository
    global CVSRepositoryManager

    # Give busy indicator, since this can take some time
    set status "Please wait, loading application list..."
    update idletasks

    # Going to new repository, clear last selection
    set newAppName ""

    $appWidget configure -state normal
    $appWidget delete 1.0 end
    set appList [getAppList 1]
    getAppStatus $appList
    set i 0
    foreach app $appList {
	switch $lastLogStatus($app) {
	    "buildSubmit" {
		set statusTag red
	    }
	    "official" {
		set statusTag normal
	    }
	    default {
		set statusTag normal
	    }	    
	}
	$appWidget insert end $app\n $statusTag
	incr i
    }
    $appWidget configure -state disabled
    set newAppEmail $CVSRepositoryManager($CVSRepository)
    set status "...Done."
}

#
# Get list of applications from selected repository
#
proc getAppList {{stripped 0}} {
    global CVSRepository OAGsrcDir EPICSsrcDir 
    switch $CVSRepository {
	"EPICS" {
	    set dirList [glob -nocomplain $EPICSsrcDir/* ]
	}
	"OAG" {
	    set dirList [glob -nocomplain $OAGsrcDir/* ]
	}
    }
    set appList {}
    foreach file $dirList {
	set fname [file tail $file]
	if {[file isdirectory $file] && \
	      [string compare $fname "CVS"]} {
	    lappend appList $fname
	}
    }
    set appList [lsort $appList]
    return $appList
}

#
# Take application list, and return state from log file submissions
#
proc getAppStatus {appList} {
    global logDir logFile lastLogStatus lastLogMessage lastLogTime
    if [file exists $logDir/$logFile] {
	set appNameEntries \
	  [APSGetSDDSColumn -fileName $logDir/$logFile -column applicationName]
	set appStatusEntries \
	  [APSGetSDDSColumn -fileName $logDir/$logFile \
	     -column applicationState]
	set appMessageEntries \
	  [APSGetSDDSColumn -fileName $logDir/$logFile \
	     -column applicationMessage]
    } else {
	set appNameEntries {}
    }
    
    foreach app $appList {
	set lastLogStatus($app) "official"
	set lastLogMessage($app) ""
	set lastLogTime($app) ""
	set i 0
	foreach appNameEntry $appNameEntries {
	    if {![string compare $appNameEntry $app]} {
		set lastLogStatus($app) \
		  [lindex $appStatusEntries $i]
		set lastLogMessage($app) \
		  [lindex $appMessageEntries $i]
	    }
	    incr i
	}
    }
}

#
# Configure application appropriately when an application is selected
#
proc appListSelect {item dc} {
    global newAppName
    global buildAckEmail buildAckStatus
    global lastLogStatus lastLogMessage
    if {$dc == 0} {
	set newAppName $item
	if [string compare $item ""] {
	    if {[info exists lastLogStatus($item)]} {
		switch $lastLogStatus($item) {
		    "buildSubmit" {
			set buildAckEmail $lastLogMessage($item)
			set buildAckStatus 1
		    }
		    "official" {
			set buildAckStatus 0
		    }
		    default {
		    }	    
		}
	    } 
	}
    }
}

#
# Change graphical (color) status of application in application list
#
proc updateGraphicalStatus {newStatus} {
    global selectionFirst selectionLast apps

    switch $newStatus {
	"buildSubmit" {
	    set statusTag red
	}
	"official" {
	    set statusTag normal
	}
	default {
	    set statusTag normal
	}	    
    }
    $apps tag remove red $selectionFirst $selectionLast
    $apps tag add $statusTag $selectionFirst $selectionLast
}

#
# New Release Build Request Enable
#
proc enableNewAppSubmit {} {
    global newAppName newAppChangeCommit newAppReleaseCommit newAppTest
    global newAppStatus
    
    if {$newAppName != "" && $newAppChangeCommit && \
	  $newAppReleaseCommit && $newAppTest && $newAppStatus} {
	return 1
    } else {
	return 0
    }
}

#
# New Release Build Request
#
proc newAppSubmit {appName userEmail} {
    global status newAppEmail lastLogStatus lastLogMessage
    global CVSRepository sourceId serviceId networkDomain

    if {![enableNewAppSubmit]} {
	bell
	APSAlertBox .illegalOp -errorMessage "You cannot submit a build request at this time. Have you completed the checklist??"
	return
    }
    # Start up email process
    set mailCmd "/bin/mail $newAppEmail"
    if [catch {open "|$mailCmd" w} res] {
	bell
	set status "Unable to send email: $res"
	return
    } else {
	set mfp $res
    }
    
    # Log message to logDaemon
    set logCmd "logMessage -sourceId=$sourceId -tag=applicationName $appName -tag=applicationState buildSubmit -tag=applicationMessage $userEmail"
    if [catch "exec $logCmd" res] {
	bell
	set status "Unable to log $appName submission: $res"
	close $mfp
	return
    } else {
	set status "New release of $appName logged."
    }
    # Update vars which maintain application status
    set lastLogStatus($appName) buildSubmit
    set lastLogMessage($appName) $userEmail
    
    # Change graphical status of selected application
    updateGraphicalStatus buildSubmit
    
    # Send email
    set mailMessage "\n**************************************************************\nThis is an application build request from $userEmail\n\nApplication: $appName\n\nCVS Repository: $CVSRepository\n\nPlease build this and acknowledge ASAP.\n**************************************************************\n"
    puts $mfp $mailMessage
    close $mfp
    set status "Build request for $appName sent to $newAppEmail"
}

#
# Build Acknowledgement Enable
#
proc enableBuildAckSubmit {} {
    global newAppName buildAckBuilt buildAckSerial 
    global buildAckTest buildAckStatus
    
    if {$newAppName != "" && $buildAckBuilt && \
	  $buildAckSerial && $buildAckStatus} {
	return 1
    } else {
	return 0
    }
}

#
# Build Acknowledgement 
#
proc buildAckSubmit {appName userEmail} {
    global status buildAckEmail lastLogStatus lastLogMessage
    global CVSRepository sourceId serviceId

    if {![enableBuildAckSubmit]} {
	bell
	APSAlertBox .illegalOp -errorMessage "You cannot acknowlege a build request at this time. Either you haven't completed the checklist, or nobody has submitted a build request for this application."
	return
    }
    # Start up email process
    set mailCmd "/bin/mail $buildAckEmail"
    if [catch {open "|$mailCmd" w} res] {
	bell
	set status "Unable to send email: $res"
	return
    } else {
	set mfp $res
    }

    # Log message to logDaemon
    set logCmd "logMessage -sourceId=$sourceId -tag=applicationName $appName -tag=applicationState official -tag=applicationMessage $userEmail"
    if [catch "exec $logCmd" res] {
	bell
	set status "Unable to log $appName build acknowledgement: $res"
	close $mfp
	return
    } else {
	set status "Build of $appName logged."
    }
    # Update vars which maintain application status
    set lastLogStatus($appName) official
    set lastLogMessage($appName) $userEmail
    
    # Change graphical status of selected application
    updateGraphicalStatus official

    # Send email
    set mailMessage "\n**************************************************************\nThis is an application build acknowledgement from $userEmail\n\nApplication: $appName\n\nCVS Repository: $CVSRepository\n\nApplication is now installed with new serial number.\n**************************************************************\n"
    puts $mfp $mailMessage
    close $mfp
    set status "Build acknowledgement for $appName sent to $buildAckEmail"
}

#
# Given full path to executable, search for next free serial number,
# and return new path to next serial numbered executable. If file is
# new, return $path.00001.
#
proc nextSerialNumber {path} {
    set dir [file dirname $path]
    set file [file tail $path]
    set fileList [glob -nocomplain ${path}.0*]

    set maxSerial 00000
    foreach f $fileList {
	set serialNo -1
	regexp {[.]([0-9]+)} $f match serialNo
	if {$serialNo > $maxSerial} {
	    set maxSerial $serialNo
	}
    }
    set nextSerial [format "%05d" [expr $maxSerial + 1]]
    return ${path}.$nextSerial
}

#
# Build up Graphical Interface
#

APSApplication . -name applicationSubmit -version $CVSRevisionAuthor \
  -overview "This utility allows you to submit or acknowledge a build request for any code module in the EPICS or OAG CVS repositories. You select the code module of interest, and then either:\n1. Submit a build request.\n2. Acknowledge a build request.\n\nThe status of the application is logged. An associated script entitled applicationBrowse allows you to view the current list of applications and their status, as well as select which release you want as the official one."

#
# Scrolled Status
#
set status "Please select the appropriate Repository."
APSScrolledStatus .ss -parent .userFrame -textVariable status -contextHelp \
  "Provides hints and execution status."
APSRepack .userFrame.ss -fill x

set status "Then select an application from list."

#
# Build up top frame (below status)
#
APSFrame .appChoice -parent .userFrame -label "Application Selection" \
  -contextHelp "Indicates which application (module) has been selected and permits selection of the desired CVS repository. A color key is also provided so you know what state an application is in."

APSFrameGrid .key -parent .userFrame.appChoice.frame -xList {color msg} \
  -yList {select grey red}

# Selected Application
APSLabeledOutput .appname -parent .userFrame.appChoice.frame.key.color.select \
  -label "Selected Application:" -textVariable newAppName -width 25 \
  -contextHelp "Reflects listbox selection."

# CVS Repository selection
APSRadioButtonFrame .repository -parent \
  .userFrame.appChoice.frame.key.msg.select \
  -buttonList {OAG EPICS} -valueList {OAG EPICS} -variable CVSRepository \
  -label "Repository" -commandList {loadAppList loadAppList} \
  -orientation horizontal -packOption "-side left" -contextHelp \
  "Selects which CVS repository to use. Selecting will cause listbox to fill with applications from that repository."

set greyMeaning "Normal."
set redMeaning "Build Request Submitted."

# Build up color key
label .userFrame.appChoice.frame.key.color.grey.left \
  -text "Grey Application" -width 18 -highlightthickness 1 \
  -highlightbackground black
pack .userFrame.appChoice.frame.key.color.grey.left -side left
label .userFrame.appChoice.frame.key.color.grey.right -text $greyMeaning
pack .userFrame.appChoice.frame.key.color.grey.right -side left

label .userFrame.appChoice.frame.key.color.red.left \
  -text "Red Application" -bg red -width 18 -highlightthickness 1 \
  -highlightbackground black
pack .userFrame.appChoice.frame.key.color.red.left -side left
label .userFrame.appChoice.frame.key.color.red.right -text $redMeaning
pack .userFrame.appChoice.frame.key.color.red.right -side left


#
# Build up middle frame
#
APSFrameGrid .fg -parent .userFrame -xList {left right}

# CVS module list
APSFrame .sl -parent .userFrame.fg.left -label "Applications (modules)" \
  -contextHelp "List of applications (cvs modules). Select one and then submit a build request or acknowlege a build request."
APSScrolledText .apps -parent .userFrame.fg.left.sl.frame -height 25 -width 38
set apps .userFrame.fg.left.sl.frame.apps.text
$apps configure -state disabled -cursor left_ptr

# Design color and selection tags for application list widget
proc tagColors {textWidget} {
    $textWidget tag configure selected -relief raised
    $textWidget tag configure red -background red \
      -borderwidth 2 -spacing1 1 -spacing3 1
    $textWidget tag raise red selected
    $textWidget tag configure normal -background Gray85 \
      -borderwidth 2 -spacing1 1 -spacing3 1
    $textWidget tag raise normal selected
}

tagColors $apps

# Remove all default Text class bindings
bindtags $apps [list $apps . all]

bind $apps <Button-1> {
    set cur [$apps index @%x,%y]
    set first [$apps index "$cur linestart"]
    set last [$apps index "$cur lineend + 1 chars"]

    $apps tag remove selected 0.0 $first
    $apps tag add selected $first $last
    $apps tag remove selected $last end
    set selection [$apps get $first "@%x,%y lineend"]

    set selectionFirst $first
    set selectionLast $last
    appListSelect $selection 0
}

#
# Submit New Release for Build Form
#
APSFrame .newRelease -parent .userFrame.fg.right -label \
  "Submit Build Request" -packOption "-side top -fill x" -contextHelp \
  "Submits a build request to the shown email address, and logs the request. You may alter the email address, although it should be preset correctly. Application will remain in a \"build requested\" state until acknowleged."
set newRelease .userFrame.fg.right.newRelease.frame

APSCheckButtonFrame .newAppChecklist -parent $newRelease -label \
  "Complete the Checklist" -buttonList {
      "committed all changes"
      "entered release notes"
      "tested application locally"
  } -contextHelp "You must check all these before pressing Submit." \
  -variableList {newAppChangeCommit newAppReleaseCommit newAppTest}

APSLabeledEntryFrame .newAppEmail -parent $newRelease -label \
  "Build Request To:" -variableList {newAppEmail} -width 30

APSButton .newAppSubmit -parent $newRelease -text "Submit" -highlight 1 \
  -command {newAppSubmit $newAppName $userEmail} -contextHelp \
  "Submit build request."

set newAppSubmitButton $newRelease.newAppSubmit.button


#
# Build acknowledgement form
#
APSFrame .buildAck -parent .userFrame.fg.right -label \
  "Acknowledge Build" -packOption "-side top -fill x" -contextHelp \
  "Acknowleges a pending build request. Email is sent back to the user who last submitted the request."
set buildAck .userFrame.fg.right.buildAck.frame

APSCheckButtonFrame .buildAckChecklist -parent $buildAck -label \
  "Complete the Checklist" -buttonList {
      "built application"
      "installed"
  } -contextHelp "You must check these before pressing Submit." \
  -variableList {buildAckBuilt buildAckSerial}

APSLabeledEntryFrame .buildAckEmail -parent $buildAck -label \
  "Acknowledge Build To:" -variableList {buildAckEmail} -width 30

APSButton .buildAckSubmit -parent $buildAck -text "Submit" -highlight 1 \
  -command {buildAckSubmit $newAppName $userEmail} -contextHelp \
  "Acknowlege pending build request."
set buildAckSubmitButton $buildAck.buildAckSubmit.button

tkwait visibility $buildAckSubmitButton

# Do not allow this to be run from other than the helios subnet. Unless
#  the -test command line arg has been given.

if {[string compare $networkDomain "accel.ntw0rk"] && \
      [string compare $networkDomain "aps4.anl.gov"] && \
      [string compare [lindex $argv 0] "-test"]} {
    bell
    bell
    APSAlertBox .domain -errorMessage "You are only allowed to run this application from the helios subnet. Please log onto a machine there and try again."
    exit
}

