#
# 
# Copyright (c) 2002 Sebastien J. Gross <seb@sjgross.org>
# Version 0.0.1 ($Id: Makefile,v 1.1.1.1 2002/04/04 16:46:51 sjg Exp $)
#
#

PATCH=patch
DIFF=diff
GREP=grep
CUT=cut
CVS=cvs -q
STAT=stat
STDERR=/dev/stderr
DEFAULT_RIGHTS=`umask -S`
DEFAULT_OWNER=`id -u`.`id -g`
CONFDIR=.conf

###################################################################
#
#           You shouldn't modify anything under this line
#
###################################################################

# This is the destination directory used when installing files
# this variable should be set to /.
# change its value if you want to install files somewhere else (for
# testing purposes for example).
ifeq ($(DESTDIR),)
	DESTDIR:=
endif

# This is the name of the host (the subdirectory where files are
# stored.
ifeq ($(HOSTNAME),)
	HOSTNAME:=`hostname -f`
endif

# Value of the item to treat.
# generaly use like this:
# make install ITEM=etc/resolv.conf
# if you want to install the new /etc/resolv.conf
ifeq ($(ITEM),)
	ITEM:=$(HOSTNAME)
endif

AWK_SCRIPT=/^\.\.?\/?$$|\/CVS|^\.\/\$(CONFDIR)/ { sub(/^\.\//, ""); print}
DIRS=`find ./$$ITEM -type d | awk '! $(AWK_SCRIPT)'`
FILES=`find ./$$ITEM -type f | awk '! $(AWK_SCRIPT)'`
ALL:=$(DIRS) $(FILES)

# The patchfile used for make revert
ifeq ($(PATCH_FILE),)
	PATCH_FILE:=`ls -t *.patch | head -1`
endif

# hide all action?
ifeq ($(DEBUG),)
	DEBUG=@
else
	DEBUG=
endif

all:
	$(DEBUG)\
	cat USAGE; \

# Install new files in production directories
install: patch
	$(DEBUG) \
	cd $(HOSTNAME); \
	(for f in $(ALL); do \
		line=`$(GREP) "^$$f:" $(CONFDIR)/rights`; \
		rights=`echo $$line | $(CUT) -d: -f2`;\
		owner=`echo $$line | $(CUT) -d: -f3`;\
		if [ -d "$$f" ]; then \
			if [ ! -d "$(DESTDIR)/$$f" ]; then \
				echo "Creating: $(DESTDIR)/$$f" > $(STDERR);\
				mkdir -p $(DESTDIR)/$$f ;\
				echo "Setting perms for $(DESTDIR)/$$f"\
					 > $(STDERR);\
				chown $$owner $(DESTDIR)/$$f; \
				chmod $$rights $(DESTDIR)/$$f; \
			fi; \
		else\
			if [ ! -f "$(DESTDIR)/$$f" -o ! -z "`$(DIFF) $(DESTDIR)/$$f $$f`" ]; then\
				echo "Installing: $(DESTDIR)/$$f" > $(STDERR);\
				cp $$f $(DESTDIR)/$$f; \
				echo "Setting perms for $(DESTDIR)/$$f"\
					 > $(STDERR);\
				chown $$owner $(DESTDIR)/$$f; \
				chmod $$rights $(DESTDIR)/$$f; \
			fi; \
		fi;\
	done);\

# Undo changes using PATCH_FILE as patch
revert:
	$(DEBUG) \
	cat $(PATCH_FILE) | $(PATCH) -d $(DESTDIR)/ -R -p0 \

# Create a patch when installing a new version
patch:
	$(DEBUG) \
	tmpfile=$(HOSTNAME)-`date +"%Y-%m-%d-%H-%M-%S"`.patch; \
	cd $(HOSTNAME); \
	(for f in $(FILES); do \
		$(DIFF) -Nu $(DESTDIR)/$$f $$f >> ../$$tmpfile ;\
	done) || true; \
	cd ..; \
	(if [ ! -z "`file $$tmpfile | grep empty`" ] ; then \
		rm -f $$tmpfile ;\
		echo "Production is up to date" > $(STDERR); \
	else \
		echo "Patch saved to `pwd`/$$tmpfile" > $(STDERR); \
	fi); \

# Create a diff of the file/directory given in ITEM between
# development and CVS version.
# Usefull to create a patch.
cvs-diff:
	$(DEBUG) \
	cd $(HOSTNAME); \
	(for f in $(FILES); do \
		$(CVS) diff $$f; \
	done); 

# Similar to cvs annotate.
cvs-annotate:
	$(DEBUG) \
	cd $(HOSTNAME); \
	(for f in $(FILES); do \
		$(CVS) annotate $$f; \
	done); 

# Create a diff of the file/directory given in ITEM between production
# and development version.
# Usefull to create a patch.
diff:
	$(DEBUG) \
	cd $(HOSTNAME); \
	(for f in $(FILES); do \
		$(DIFF) -Nu $(DESTDIR)/$$f $$f; \
	done) || true; 

# Create the host's subdirectory in the CVS
init:
	$(DEBUG) \
	(for f in $(HOSTNAME) $(HOSTNAME)/$(CONFDIR); do \
		mkdir $$f; \
		$(CVS) add $$f;\
		$(CVS) ci -m '' $$f;\
	done);\
	touch $(HOSTNAME)/$(CONFDIR)/rights; \
	$(CVS) add $(HOSTNAME)/$(CONFDIR)/rights; \
	$(CVS) ci -m '' $(HOSTNAME)/$(CONFDIR)/rights; \

# Add recursivelly a directory (or a file)
# defined by ITEM on the command line in the CVS
# You can add a message in the CVS logs using the MESSAGE variable.
add:
	$(DEBUG) \
	cd $(HOSTNAME); \
	echo "add: $$ITEM"; \
	(if [ -d "$$ITEM" ]; then \
		echo $(DIRS) | xargs $(CVS) -q add -m "$$MESSAGE"; \
	fi); \
	(if [ ! -d "`dirname $$ITEM`/CVS" ]; then \
		cd ..; \
		make add ITEM=`dirname $$ITEM`; \
		make rights ITEM=`dirname $$ITEM`; \
		cd $(HOSTNAME); \
	fi); \
	echo $(FILES) | xargs $(CVS) add -m "$$MESSAGE"; \
	echo $(FILES) | xargs $(CVS) ci -m "$$MESSAGE"; \

# Import a file/directory from production to development directory.
# This import is done recursivelly.
import:
	$(DEBUG) \
	(if [ ! -z "$$ITEM" ]; then \
		item=`echo $$ITEM | sed 's/^\///'`; \
		echo "import: $(item)"; \
		(if [ -d "$$ITEM" ]; then \
			mkdir -p $(HOSTNAME)/`dirname $$item`; \
			cp -fr $$ITEM $(HOSTNAME)/`dirname $$item`; \
		fi);\
		(if [ -f "$$ITEM" ] ; then \
			mkdir -p $(HOSTNAME)/`dirname $$item`;\
			cp -f $$ITEM $(HOSTNAME)/$$item; \
		fi);\
		make add ITEM=$$item; \
		make rights ITEM=$$item; \
	fi); \

# Remove a FILE
remove:
	$(DEBUG) \
	cd $(HOSTNAME); \
	(if [ -f "$$ITEM" ]; then \
		grep -v "^$$ITEM:" $(CONFDIR)/rights | xargs -0 echo | \
			grep -v "^$$" > $(CONFDIR)/rights ;\
		rm -f $$ITEM; \
		$(CVS) remove $$ITEM; \
		$(CVS) ci -m "$$MESSAGE" $$ITEM;\
		$(CVS) ci -m '' $(CONFDIR)/rights; \
	fi);\

# Commit files into the CVS repository
commit:
	$(DEBUG) \
	cd $(HOSTNAME); \
	echo $(FILES) | xargs $(CVS) ci -m "$$MESSAGE"; \

# Update local repository
update:
	$(DEBUG) \
	cd $(HOSTNAME); \
	$(CVS) -q up -d; \

# Remove all patch files
clean-patch:
	$(DEBUG) \
	rm -f *.patch; \

# Remove unwanted files
clean: clean-patch
	$(DEBUG) \
	find -name "*~" -exec rm -f {} \; ; \

rights:
	$(DEBUG) \
	cd $(HOSTNAME); \
	(for f in $(ALL); do \
		f=`echo $$f | sed 's/\/$$//'`; \
		(if [ -z "`grep \"^$$f:\" $(CONFDIR)/$@`" ]; then \
			if [ -e $(DESTDIR)/$$f ]; then \
				echo "Getting perms for $$f" > $(STDERR); \
				rights=`$(STAT) -c "%a" $(DESTDIR)/$$f`;\
				owner=`$(STAT) -c "%u.%g" $(DESTDIR)/$$f` ;\
			else \
				rights=$(DEFAULT_RIGHTS); \
				owner=$(DEFAULT_OWNER); \
			fi ;\
			echo "$$f:$$rights:$$owner" >> $(CONFDIR)/$@; \
		fi);\
	done); \
	$(CVS) ci -m '' $(CONFDIR)/rights; \