#!/usr/bin/env python
import os
import sys
import argparse
import subprocess
import globals
import toolconfig
import multi_facility_process_helper_client
from globals import UserParamsException

def pushRelease(freshen):
	"""Submits a release to the build and release process. 
	This is largely a process of rsync'ing the contents of this folder to the correct places.
	We identify this package and use the tool configuration to determine rsync dest locations.
	You have to run cram push from the folder containing the release.
	We also honor rsync include and exclude files that are present in the .cram folder.
	Global include and exclude files are .cram/push_include and .cram/push_exclude.
	Facility_specific include and exclude files are .cram/<facility>_push_include and .cram/<facility>_push_exclude.
	"""
	packageInfo = toolconfig.readPackageConfig(autoDescribeRelease=True)
	appType = packageInfo['type']
	currentVersionNum = os.path.basename(os.getcwd())		
	facilitiesConfig = toolconfig.getFacilityConfig()
	for facilityConfig in facilitiesConfig:
		commandsAndArgs = []
		packageReleaseFolder = os.path.join(facilityConfig[appType]['releaseFolder'], packageInfo['name'])
		releaseFolder = os.path.join(packageReleaseFolder, currentVersionNum)
		commandsAndArgs.append(('fileinfo', [packageReleaseFolder]))
		commandsAndArgs.append(('fileinfo', [releaseFolder]))
		results = multi_facility_process_helper_client.executeCommandsOnFacility(facilityConfig['name'], commandsAndArgs)
		packageTopInfo = results[0]
		if not packageTopInfo:
			print "Skipping pushing release to ", facilityConfig['name'], " as the top level folder is missing"
			continue;
		fileinforet = results[1]
		if releaseFolder in fileinforet:
			if not freshen:
				print "Release ", currentVersionNum, " already exists on facility ", facilityConfig['name'], "Use --freshen to update a release that has previously been pushed."
				continue
		
		rsyncDestPath = facilityConfig['ssh'] + ":" + os.path.join(facilityConfig[appType]['releaseFolder'], packageInfo['name'], currentVersionNum)
		if globals.verbose:
			print "RSyncing to ", rsyncDestPath
		
		rsync_manifest_args = []
		includePath = os.path.join(".cram", "push_include")
		if os.path.exists(includePath):
			rsync_manifest_args.extend(["--include-from", includePath])
		includePath = os.path.join(".cram", facilityConfig['name'] + "_push_include")
		if os.path.exists(includePath):
			rsync_manifest_args.extend(["--include-from", includePath])
		excludePath = os.path.join(".cram", "push_exclude")
		if os.path.exists(excludePath):
			rsync_manifest_args.extend(["--exclude-from", excludePath])
		excludePath = os.path.join(".cram", facilityConfig['name'] + "_push_exclude")
		if os.path.exists(excludePath):
			rsync_manifest_args.extend(["--exclude-from", excludePath])
		if globals.verbose:
			print "Manifest args", rsync_manifest_args
		rsyncextraargs = "-a"
		if globals.verbose:
			rsyncextraargs = "-av"
		subprocess.check_call(['rsync', rsyncextraargs] + rsync_manifest_args + ['-e', 'ssh ' + globals.dmzmachine + ' ssh', '.', rsyncDestPath])
		if appType in ['SIOC', 'HIOC']:
			if globals.verbose:
				print "Fixing up envPaths on ", facilityConfig['name']
			commandsAndArgs = []
			arg = {}
			arg['name'] = packageInfo['name']
			arg['type'] = appType
			arg['facility'] = facilityConfig['name']
			arg['releaseFolder'] = facilityConfig[appType]['releaseFolder']
			arg['linkFolder'] = facilityConfig[appType]['linkFolder']
			arg['release'] = currentVersionNum
			commandsAndArgs.append(('fixEnvPathsForAllIOCs', arg))
			results = multi_facility_process_helper_client.executeCommandsOnFacility(facilityConfig['name'], commandsAndArgs)
			
		print "Pushed release", currentVersionNum, "to", facilityConfig['name']

def execute(args):
	parser = argparse.ArgumentParser(prog="cram push", description="Pushes a release (the contents of the current folder) to all the facilities. This is largely a process of rsync'ing the contents of the current folder " + os.getcwd() + " to the releaseFolder's in all the facilities for this software package. You must run cram push from the folder containing the release. The folder name must match the version.")
	parser.add_argument('-v', '--verbose', action='store_true', help='Enable verbose logging')
	parser.add_argument('-f', '--freshen', action='store_true', help='Freshen/updates an existing release')
	args = parser.parse_args(args)
	globals.verbose = args.verbose

	try:
		pushRelease(args.freshen)
	except UserParamsException as upe:
		if not globals.verbose and not globals.isunittests:
			print upe
			sys.exit(-1)
		else:
			raise

if __name__ == "__main__":
	execute(sys.argv[1:])