# Copyright (C) 1993 by the author(s).
# 
# This software is published in the hope that it will be useful, but
# WITHOUT ANY WARRANTY for any part of this software to work correctly
# or as described in the manuals. See the ShapeTools Public License
# for details.
#
# Permission is granted to use, copy, modify, or distribute any part of
# this software but only under the conditions described in the ShapeTools 
# Public License. A copy of this license is supposed to have been given
# to you along with ShapeTools in a file named LICENSE. Among other
# things, this copyright notice and the Public License must be
# preserved on all copies.

#
# shape_CM environment -- stdconf-mgmt (stdtargets + stdconf)
#
# Authors: Andreas Lampen (Andreas.Lampen@cs.tu-berlin.de)
#          Axel Mahler (Axel.Mahler@cs.tu-berlin.de)
#
# Modified by: Karl-Heinz Koester (Karl-Heinz.Koester@sietec.de)
#
# $__Header$
#
# $__xpoff$

rms: help

info: help

help:
	@echo CPE Release Managemet System; \
	echo Usage: ; \
	echo "  shape [build]   [BINDDEFAULT=<selection_rule>]; \
	echo "                  [variants] [macro settings]"; \
	echo "  make  [build]   [<macro settings>]"; \
	echo "  shape clean"; \
	echo "  make  clean"; \
	echo "  shape cleancache"; \
	echo "  shape depend  [BINDDEFAULT=<selection_rule>] [variants]"; \
	echo "  shape localinstall [BINDDEFAULT=<selection_rule]"; \
	echo "                     [LOCAL=<path>] [variants] [macro settings]"; \ 
	echo "  make  localinstall [LOCAL=<path>] [macro settings]
	echo "  shape install [BINDDEFAULT=<rule>] [INSTALLBASE=<path>]"; \
	echo "                [variants] [macro settings]"; \
	echo "  make  install [INSTALLBASE=<path>] [<macro settings>]"; \
	echo "  shape retrv"; \
	echo "  shape save"; \
	echo "  shape vdiff"; \
	echo "  shape prerelease"; \
	echo "  shape extractprerelease [RELEASENAME=<relId>]";

cleancache: cclean

cclean:
	@echo "Cleaning derived object cache"; \
	atfsrepair -C -q

depend: $(BINDDEFAULT) +$(SYSTEM) +$(MACHINE) +$(CCOMP) \
	$(C_SRC) $(PUBLIC_C_HDR) $(LOCAL_C_HDR)
	@-echo "Generating Dependencies file."; \
	if [ "$(SYSTEM)" ]; \
	then \
	  _hostsystem=$(SYSTEM); \
	else \
	  _hostsystem=_xXxXxX_; \
	fi; \
	if [ "$(BASE)" ]; \
	then \
	  _basepath=$(BASE); \
	else \
	  _basepath=_xXxXxX_; \
	fi; \
	$(CC) $(CFLAGS) -M $(C_SRC) \
	| grep -v "/usr/include" \
	| sort | uniq | \
	sed -e "s:$$_basepath:$$(BASE):" -e "s:$$_hostsystem:$$(SYSTEM):" \
	> CDependencies

cooldepend: $(BINDDEFAULT) +$(SYSTEM) +$(MACHINE) +$(CCOMP) \
	$(PUBLIC_COOL_SPECS) $(LOCAL_COOL_SPECS) $(COOL_IMPLS) $(COOL_MODS)
	@-echo "Generating CooL Dependencies file."; \
	( for i in $(PUBLIC_COOL_SPECS) $(LOCAL_COOL_SPECS) $(COOL_IMPLS) \
	  	   $(COOL_MODS) ; do \
	    $(COOL) $(COOLFLAGS) -M $$i ;\
          done )  > CooLDependencies

#
# Releasing targets
#

prerelease:+
	RELEASENAME=`$(SHAPELIBPATH)/gen_rel_id $(PATCH) prerelease \
		$(NODENAME) $(VERSIONFILE) $(PRERELSEQ) $(PATCHSEQ)`

release:+
	RELEASENAME=`$(SHAPELIBPATH)/gen_rel_id $(PATCH) release \
		$(NODENAME) $(VERSIONFILE) $(PRERELSEQ) $(PATCHSEQ)`

USERATDOMAIN:=`$(SHAPELIBPATH)/user_at`
NOTOPRELEASE=$(NODEPATH)
LASTNODERELEASE:=`$(SHAPELIBPATH)/gen_rel_id release $(NODENAME) \
	$(BASE)/$(NODEPATH)/$(VERSIONFILE) $(BASE)/$(NODEPATH)/$(PRERELSEQ) \
	$(BASE)/$(NODEPATH)/$(PATCHSEQ)`
LASTNODEPRERELEASE:=`$(SHAPELIBPATH)/gen_rel_id prerelease $(NODENAME) \
	$(BASE)/$(NODEPATH)/$(VERSIONFILE) $(BASE)/$(NODEPATH)/$(PRERELSEQ) \
	$(BASE)/$(NODEPATH)/$(PATCHSEQ)`
LASTRELEASE:=`vl -format '$$__lastrelease$$' -lastsaved \
	$(BASE)/$(NODEPATH)/$(VERSIONFILE)`
PRERELSEQ=AtFS/.prerelseq
PATCHSEQ=AtFS/.patchseq
RETRVOPTS=

INDENT=
INDENTINCR="  "

#
# This file defines the targets ``release'' and ``prerelease'' to
# generate a new release of an AtFS application.
# Target ``save'' is useful to make an intermediate save of all components.
#
# You should not use targets beginning with an underscore (`_').

prerelease: +prerelease _start_prerelease _checkseq _check_releasability \
	_newprerel _xprerelease _end_prerelease

_start_prerelease:
	@echo; echo Starting pre-release process for $(NODENAME); echo
	@echo Checking for pre-release preconditions...; echo;

_end_prerelease:
	@echo Construction of pre-release $(RELEASENAME) finished \!; echo

_check_releasability: _checksub _checknode

_check_sub_releasability: _checksub _check_subnode

#
# This predicate checks whether all necessary preconditions for a 
# release of all subsystems are met, i.e. the subrelease must be
# identifyable.
#
_checksub:
	@echo $(INDENT)$(NODENAME)...; \
	if [ -n "$(SUBSYSTEMS)" ] ; \
	then \
	  if [ -n "$(NODEPATH)" ] ; \
	  then \
	    echo $(INDENT)"Checking subsystem(s) $(NODEPATH)/{$(SUBSYSTEMS)} for releasability"; \
	  else \
	    echo $(INDENT)"Checking subsystem(s) {$(SUBSYSTEMS)} for releasability"; \
	  fi; \
	fi; \
	_subsystems="$(SUBSYSTEMS)"; \
	exitcode=0; \
	for i in $$_subsystems; \
	do \
	  (cd $$i; $(SHAPE) INDENT='$(INDENT)$(INDENTINCR)' \
 	           _check_sub_releasability); \
	  if [ $$? -ne 0 ]; then exitcode=1; fi; \
	done; \
	if [ -n "$(SUBSYSTEMS)" ] ; \
	then \
	  echo $(INDENT)$(NODENAME)...; \
	fi; \
	exit $$exitcode
	
#
# This predicate checks whether all preconditions for a local
# release (i.e. of TARGET, COMPONENTS etc.) are met. In particular
# we must be able to lock all components, before we check them
# in. This is intended to prevent interference with programmers
# who might have locked particular COMPONENTS. In the case of a global
# release it is checked whether there are at all subreleases in all
# of the subsystems.
#
# For prereleases, this predicate checks, whether there is a current
# regular release that shall be included into the pre-release.
#

_checknode: _check_unlocked_changes _check_foreign_locks
	@echo $(INDENT)"   ...is releasable"

_check_foreign_locks: check_releasable $(COMPONENTS) $(VERSIONFILE)

_check_unlocked_changes:
	@echo -n $(INDENT)Checking for unsaved changes without lock...; \
	nll=`vfind $(COMPONENTS) -last \! -locked -print | \
	egrep '.*\[.*\..*\]' | sed -e 's/\[.*\]//'`; \
	for i in $$nll; \
	do \
	  if [ ! -f $$i ] || vdiff $$i > /dev/null ; \
	  then : ; \
	  else \
	    ulcl="$$ulcl $$i"; \
	  fi; \
	done; \
	if [ -n "$$ulcl" ] ; \
	then \
	  echo; \
	  echo $(INDENT)The following files have been changed but are not locked: ; \
	  echo $(INDENT)"	$$ulcl"; \
	  echo $(INDENT)...$(NODENAME) is currently not releasable.; \
	  exit 1; \
	fi; \
	echo OK!; \
	exit 0;

_check_subnode: most_recently_prereleased $(COMPONENTS) $(VERSIONFILE)
	@echo $(INDENT)"   ...is releasable"

#
# This action creates a new versionid for our local release which 
# is also used to construct a symbolic name for it.
#

_newprerel: _incseq
	@-if vl -lastsaved $(VERSIONFILE) > /dev/null 2>&1; \
	then :; \
	else \
	  save -fq -lock $(VERSIONFILE); \
	  vadm -q -lastsaved -attr norelease=true -unlock $(VERSIONFILE); \
	fi; \
	echo; echo New pre-release name is $(RELEASENAME); echo

_xprerelease: _subprereleases _node_prerelease
	@echo

_xsubprerelease: _subprereleases _include_prerelease
	@echo

#
# This action visits all subsystems and triggers global releases for
# them. Subsystems of subsystems are globally released recursively.
# The maintarget is globally released after the subsystems.
#
_subprereleases:
	@-_subsystems="$(SUBSYSTEMS)"; \
	for i in $$_subsystems; \
	do \
	  (symName=$(RELEASENAME); cd $$i; \
		$(SHAPE) INDENT='$(INDENT)$(INDENTINCR)' \
		RELEASENAME=$$symName \
		NOTOPRELEASE=$(NOTOPRELEASE) \
		DELIVERYBASE=$(DELIVERYBASE) \
		_xsubprerelease); \
	done

#
# This action takes care that all yet unsubmitted work results are
# deposited in the version object base and assigned the status "proposed".
# The new, locally generated releasename is attached to all COMPONENTS.
#

_node_prerelease:
	@-symName=$(RELEASENAME); \
	echo Pre-releasing $$symName...; \
	save -q $(COMPONENTS); \
	vadm -q -lastsaved -attr nodename=$(NODENAME) \
		-attr lastrelease=$(RELEASENAME) \
		-alias $(RELEASENAME) $(VERSIONFILE); \
	vadm -q -lastsaved -alias $$symName -attr lastrelease=$$symName \
		$(COMPONENTS); \
	retrv -xpoff -fq $(VERSIONFILE); \
	touch -c -f $(VERSIONFILE); \
	sbmt -q -bind $$symName $(COMPONENTS) $(VERSIONFILE)

#
# This action is triggered by an incoming global release process, i.e.
# when we are in the role of a subtarget. It retrieves the most recent
# local release of TARGET (see selection rule) and marks its COMPONENTS
# with the global releasename which is passed down to us in the macro
# RELEASENAME. If this is an intermediate global release, i.e. the release
# was initiated by a non-toplevel subsystem of the overall system, no 
# status-change of the involved COMPONENTS takes place. If this is a "real"
# TOPLEVEL release of the entire system, all COMPONENTS are set to status 
# "frozen". 
#

_include_prerelease:
	@-last_node_prerelease=$(LASTNODEPRERELEASE); \
	if vl -bind $$last_node_prerelease $(VERSIONFILE) > /dev/null 2>&1; \
	then :; \
	else \
	  last_node_prerelease=$(LASTNODERELEASE); \
	fi; \
	echo $(INDENT)Including $$last_node_prerelease into $(RELEASENAME); \
	vadm -q -bind $$last_node_prerelease -alias $(RELEASENAME) \
		$(COMPONENTS) $(VERSIONFILE); \
        echo $(INDENT)Accessing $(NODENAME) components; \
	accs -q -bind $$last_node_prerelease $(COMPONENTS) $(VERSIONFILE); \

#
# make sure that prerelase sequence number is present and initialized
#

_checkseq: $(PRERELSEQ)

_resetseq: $(PRERELSEQ)
	@rm -f $(PRERELSEQ) 2> /dev/null; \
	echo 0 > $(PRERELSEQ); \
	chmod 664 $(PRERELSEQ)

_incseq: $(PRERELSEQ)
	@awk < $(PRERELSEQ) '{ print $$1+1; }' > AtFS/.prereltmp; \
	mv AtFS/.prereltmp $(PRERELSEQ);\
	chmod 664 $(PRERELSEQ)

$(PRERELSEQ):
	@-if [ ! -f $(PRERELSEQ) ]; \
	then \
		echo 0 > $(PRERELSEQ); \
		chmod 664 $(PRERELSEQ); \
	fi


extractprerelease: _extract_subprereleases _partial_extractprerelease

# extractrelease: _extract_subreleases _partial_extractrelease

_extract_subprereleases:
	@-_subsystems="$(SUBSYSTEMS)"; \
	if [ -n "$(RELEASENAME)" ]; \
	then \
	  symname=$(RELEASENAME); \
	else \
	  symname=$(LASTNODEPRERELEASE); \
	fi; \
	echo $(INDENT)Extracting release $$symname of $(NODENAME).; \
	for i in $$_subsystems; \
	do \
	  (cd $$i; $(MAKE) RELEASENAME=$$symname \
	  INDENT='$(INDENT)$(INDENTINCR)' \
	  NOTOPRELEASE=$(NOTOPRELEASE) \
	  DELIVERYBASE=$(DELIVERYBASE) \
	  RETRVOPTS="$(RETRVOPTS)" \
	  extractprerelease); \
	done

_partial_extractprerelease:
	@-if [ -n "$(RELEASENAME)" ]; \
	then \
	  symname=$(RELEASENAME); \
	else \
	  symname=$(LASTNODEPRERELEASE); \
	fi; \
	relarea=$(DELIVERYBASE); \
	if [ -n "$$relarea" ]; \
	then \
	  $(SHAPELIBPATH)/mkpdir -m 775 $$relarea/$(NODEPATH); \
	  echo $(INDENT)Copying COMPONENTS to $$relarea/$(NODEPATH); \
	  retrv -fq $(RETRVOPTS) -xpoff -dest $$relarea/$(NODEPATH) \
                -bind $$symname $(COMPONENTS); \
	  retrv -fq $(RETRVOPTS) -dest $$relarea/$(NODEPATH) \
                -bind $$symname $(VERSIONFILE); \
	  cd $$relarea/$(NODEPATH); \
	  make $(MAKEPARAMS) preinstall ;\
	else \
	  echo $(INDENT)"Copying to delivery area skipped ! (no path specified)"; \
	fi

_extract_subreleases:
	@-_subsystems="$(SUBSYSTEMS)"; \
	if [ -n "$(RELEASENAME)" ]; \
	then \
	  symname=$(RELEASENAME); \
	else \
	  symname=$(LASTNODERELEASE); \
	fi; \
	echo $(INDENT)Extracting release $$symname of $(NODENAME).; \
	for i in $$_subsystems; \
	do \
	  (cd $$i; $(MAKE) RELEASENAME=$$symname \
	  INDENT='$(INDENT)$(INDENTINCR)' \
	  NOTOPRELEASE=$(NOTOPRELEASE) \
	  DELIVERYBASE=$(DELIVERYBASE) \
	  RETRVOPTS="$(RETRVOPTS)" \
	  extractrelease); \
	done

_partial_extractrelease:
	@-if [ -n "$(RELEASENAME)" ]; \
	then \
	  symname=$(RELEASENAME); \
	else \
	  symname=$(LASTNODERELEASE); \
	fi; \
	relarea=$(DELIVERYBASE); \
	if [ -n "$$relarea" ]; \
	then \
	  $(SHAPELIBPATH)/mkpdir -m 775 $$relarea/$(NODEPATH); \
	  echo $(INDENT)Copying COMPONENTS to $$relarea/$(NODEPATH); \
	  retrv -fq $(RETRVOPTS) -xpoff -dest $$relarea/$(NODEPATH) \
                -bind $$symname $(COMPONENTS); \
	  retrv -fq $(RETRVOPTS) -dest $$relarea/$(NODEPATH) \
                -bind $$symname $(VERSIONFILE); \
	  cd $$relarea/$(NODEPATH); \
	  make $(MAKEPARAMS) preinstall ;\
	else \
	  echo $(INDENT)"Copying to delivery area skipped ! (no path specified)"; \
	fi

#
# retrieving and saving
#

retrv:+
	ACTION=Retrieving
	SUBNODE=retrv

save:+
	ACTION=Saving
	SUBNODE=save

retrv: +retrv _start _local_retrv _sub _end

save: +save _start _check_unlocked_changes _local_save _sub _end

_local_retrv:
	@list=`$(SHELL) -cf 'vl -1 -last $(COMPONENTS) $(VERSIONFILE) | \
	                     egrep "\[.*\..*\]"'` ;\
	if [ -n "$$list" ] ; then \
	  retrv $$list ;\
	fi

_local_save:
	@for i in $(COMPONENTS) ; do \
	   if [ ! -f $$i ] || vdiff $$i > /dev/null ; then \
	     : ;\
	   else \
	     save $$i ;\
	   fi ;\
	 done
	 
_start:
	@echo $(INDENT)"$(ACTION) $(NODENAME)..."

_end:
	@echo $(INDENT)"$(ACTION) $(NODENAME) finished"

_sub:
	@if [ -n "$(SUBSYSTEMS)" ] ; \
	then \
	  if [ -n "$(NODEPATH)" ] ; \
	  then \
	    echo $(INDENT)"$(ACTION) subsystem(s) $(NODEPATH)/{$(SUBSYSTEMS)}"; \
	  else \
	    echo $(INDENT)"$(ACTION) subsystem(s) {$(SUBSYSTEMS)}"; \
	  fi; \
	fi; \
	_subsystems="$(SUBSYSTEMS)"; \
	for i in $$_subsystems; \
	do \
	  (cd $$i; $(SHAPE) INDENT='$(INDENT)$(INDENTINCR)' $(SUBNODE)); \
	done

#
# checks all busy version (OF $COMPONENETS),
# if they are identical to the last saved version
#

vdiff:
	@for i in $(COMPONENTS) ; do \
	  if [ ! -f $$i ] ; then \
	    echo "$$i:\t no busy version" ;\
	  elif vdiff $$i > /dev/null ; then \
	    echo "$$i:\t not changed" ;\
	  else \
	    echo "$$i:\t changed" ;\
	  fi ;\
	done
