#
# Build darcs
#
## If we are not doing a disttest, clean or config operation, include
## (and therefore make) the autoconf.mk and .depend makefile.  There
## are two includes as the former is needed to build the latter.
ifeq (,$(filter %clean config% disttest,$(MAKECMDGOALS)))
include autoconf.mk
include .depend .depend_p
endif

ifneq (,$(RTSFLAGS))
GHCFLAGS += +RTS $(RTSFLAGS) -RTS
endif

GHCFLAGS += -Wall -I. -I./src -i./src
GHCFLAGS_src__Darcs__Commands__Record.o = $(filter-out -auto-all,$(GHCFLAGS))
GHCFLAGS_src__Darcs__SelectChanges.o = $(filter-out -auto-all,$(GHCFLAGS))
GHCFLAGS_src__SHA1.o = $(GHCFLAGS) -no-auto-all -funfolding-use-threshold20
GHCFLAGS_src__SHA1.p_o = $(GHCFLAGS_src__SHA1.o)

# All the Haskell source files used to build Darcs, but NOT other
# Haskell sources used for e.g. unit testing.  This is done by finding
# ALL Haskell source files, then filtering out the exceptions.  The
# first few entries are hard-coded in because they are generated by
# ./configure and thus might not exist when find runs.
DARCS_FILES = src/Context.hs						\
	$(filter-out src/DateTester.% src/Darcs/Patch/Check.%		\
	  src/Darcs/Patch/Properties.% src/Darcs/Patch/QuickCheck.%	\
	  src/Darcs/Patch/Test.% src/Darcs/Patch/Unit.% src/win32/%,	\
	  $(wildcard src/[A-Z]*.hs src/*/[A-Z]*.hs src/*/*/[A-Z]*.hs))	\
	  $(wildcard src/[A-Z]*.lhs src/*/[A-Z]*.lhs src/*/*/[A-Z]*.lhs)

witnesses: src/Darcs/Patch/Real.hi src/Darcs/Patch/Properties.hi src/Darcs/Patch.hi \
	src/Darcs/Repository/ApplyPatches.hi src/Darcs/Patch/Bundle.hi \
	src/Darcs/Patch/Match.hi src/Darcs/Repository/HashedRepo.hi \
	src/Darcs/Resolution.hi src/Darcs/Patch/Check.hi \
	src/Darcs/Repository/Pristine.hi src/Darcs/Repository/DarcsRepo.hi \
	src/Darcs/Repository/Internal.hi \
	src/Darcs/Commands/Unrevert.hi src/Darcs/Commands/WhatsNew.hi \
	src/Darcs/Commands/Show.o src/Darcs/Commands/Unrecord.o \
	src/Darcs/Commands/Dist.hi src/Darcs/Commands/TransferMode.hi

# If QuickCheck is not available, we cannot even generate a .depend
# that includes the unit testing files.  Therefore make this variable
# empty as a short-term workaround (http://bugs.darcs.net/issue1307).
ifeq (yes,$(HAVE_QUICKCHECK))
UNIT_FILES = $(DARCS_FILES) $(wildcard src/Darcs/Patch/Test.*hs		\
	 src/Darcs/Patch/QuickCheck.*hs src/Darcs/Patch/Unit.*hs	\
	 src/Darcs/Patch/Properties.*hs src/Darcs/Patch/Check.*hs)
endif


C_OBJS = $(patsubst %,src/%.o,c_compat maybe_relink atomic_create fpstring umask Crypt/sha2 hscurl)

ifeq ($(SYS), windows)
GHCFLAGS += -isrc/win32 -Isrc/win32 -DWIN32
DARCS_FILES += src/win32/System/Posix.hs src/win32/System/Posix/Files.hs \
               src/win32/System/Posix/IO.hs src/win32/CtrlC.hs
C_OBJS += src/win32/CtrlC_stub.o src/win32/CtrlC.o
endif

ifeq ($(HAVE_MAPI),True)
C_OBJS += src/win32/send_email.o
CPPFLAGS += -Isrc/win32
GHCFLAGS += -DHAVE_MAPI
endif

DARCS_OBJS	= $(addsuffix .o,$(basename $(DARCS_FILES)))
DARCS_OBJS_P	= $(addsuffix .p_o,$(basename $(DARCS_FILES)))
UNIT_OBJS	= $(addsuffix .o,$(basename $(UNIT_FILES)))


.PHONY:		all clean distclean maintainer-clean dist deb test check install \
		darcs-snapshot\
		disttest slowdisttest \
		installserver windowsinstaller \
		website witnesses\

config: configure autoconf.mk

copy:
	$(MAKE) install prefix=$(destdir)/$(prefix) \
                        bindir=$(destdir)/$(bindir) \
                        libdir=$(destdir)/$(libdir) \
                        datadir=$(destdir)/$(datadir) \
                        libexecdir=$(destdir)/$(libexecdir)

$(DESTDIR)$(bindir) $(DESTDIR)$(docdir)/manual $(DESTDIR)$(docdir)/examples $(DESTDIR)$(sysconfdir)/bash_completion.d $(DESTDIR)$(mandir)/man1:
	$(INSTALL) -d $@
install::	$(DESTDIR)$(bindir) darcs
	$(INSTALL) darcs $<
install::	$(DESTDIR)$(sysconfdir)/bash_completion.d

	$(INSTALL_DATA) contrib/darcs_completion $</darcs
install::	$(DESTDIR)$(mandir)/man1 doc/darcs.1
	$(INSTALL_DATA) doc/darcs.1 $(DESTDIR)$(mandir)/man1/
install-ps:	$(DESTDIR)$(docdir)/manual ps
	$(INSTALL_DATA) doc/manual/darcs.ps $<
install-pdf:	$(DESTDIR)$(docdir)/manual pdf
	$(INSTALL_DATA) doc/manual/darcs.pdf $<
install-html:	$(DESTDIR)$(docdir)/manual html
	$(INSTALL_DATA) doc/manual/*.png $<
	$(INSTALL_DATA) doc/manual/*.html $<
install-examples:	$(DESTDIR)$(docdir)/examples
	$(INSTALL_DATA) contrib/_darcs.zsh $<
.PHONY: install-ps install-pdf install-html install-examples

installserver:	contrib/cgi/darcs.cgi
	test -d $(DESTDIR)$(libexecdir)/cgi-bin || \
		$(INSTALL) -d $(DESTDIR)$(libexecdir)/cgi-bin

	test -d $(DESTDIR)$(sysconfdir)/darcs || \
		$(INSTALL) -d $(DESTDIR)$(sysconfdir)/darcs
	test -f $(DESTDIR)$(sysconfdir)/darcs/cgi.conf || \
	    $(INSTALL_DATA) contrib/cgi/cgi.conf $(DESTDIR)$(sysconfdir)/darcs/cgi.conf
	$(INSTALL) contrib/cgi/darcs.cgi $(DESTDIR)$(libexecdir)/cgi-bin/darcs.cgi
	test -d $(DESTDIR)$(datadir)/darcs || \
		$(INSTALL) -d $(DESTDIR)$(datadir)/darcs
	test -d $(DESTDIR)$(datadir)/darcs/xslt || \
		$(INSTALL) -d $(DESTDIR)$(datadir)/darcs/xslt
	$(INSTALL_DATA) contrib/cgi/xslt/*.xslt $(DESTDIR)$(datadir)/darcs/xslt/
	$(INSTALL_DATA) contrib/cgi/xslt/errors.xml $(DESTDIR)$(datadir)/darcs/xslt/
	$(INSTALL_DATA) contrib/cgi/xslt/styles.css $(DESTDIR)$(datadir)/darcs/xslt/styles.css

# Debian policy doesn't allow symlinks as configuration files.
#	test -e $(DESTDIR)$(sysconfdir)/darcs/styles.css || \
#	    ln -s $(datadir)/darcs/xslt/styles.css \
#		$(DESTDIR)$(sysconfdir)/darcs/styles.css
	$(INSTALL) -m 644 contrib/cgi/xslt/styles.css $(DESTDIR)$(sysconfdir)/darcs/styles.css

PREDIST_COPY_FILES = \
	AUTHORS \
	release/STATE \
	src/Context.hs

DARCS_VERSION_WITH_PATCHES=$(DARCS_VERSION)$(shell sed -n '/patches/ { s/.* \([0-9]\+\) patches.*/+\1/; p }' release/STATE)
darcs-snapshot: darcs release/STATE
	mkdir -p snapshots
	cp darcs "snapshots/darcs-$(DARCS_VERSION_WITH_PATCHES)"

dist: darcs $(PREDIST_COPY_FILES)
	REPO_PATH="$$PWD" ./darcs dist --dist-name darcs-$(DARCS_VERSION)
	ln -sf darcs-$(DARCS_VERSION).tar.gz darcs-latest.tar.gz

darcs-test.tar.gz: darcs $(PREDIST_COPY_FILES)
	REPO_PATH="$$PWD" ./darcs dist --dist-name darcs-test

predist_copy:
	for F in $(PREDIST_COPY_FILES); do \
	    cp "$$REPO_PATH/$$F" "$$F"; \
	done

predist: predist_copy doc/darcs.1 pdf html distclean

windowsinstaller:	darcs html release/darcs.nsi
	echo "!define VERSION $(DARCS_VERSION)" > version.nsi
	"$(MAKENSIS)" version.nsi release/darcs.nsi
clean::
	rm -f version.nsi

# rebuild whenever a module changes, using searchpath
# Requires a patched version: darcs get http://joyful.com/repos/searchpath
SP=sp --no-default-map --no-exts --sp-verbose 1
SPDARCSCMD="--version"
SPLAST=--run $(SPDARCSCMD)
continuous ci:
	@$(SP) $(GHC) --make $(GHCFLAGS) $(OPTLLDFLAGS) -o darcs src/darcs.hs $(C_OBJS) $(OPTLLIBS) $(SPLAST)

ghci: $(DARCS_FILES) $(C_OBJS)
	ghci $(filter-out -Wall,$(GHCFLAGS)) $(OPTLLDFLAGS) src/darcs.hs $(C_OBJS) $(OPTLLIBS)
.PHONY: ghci

darcs: $(DARCS_OBJS) $(C_OBJS)
darcs_p: $(DARCS_OBJS_P) $(C_OBJS)
microbench preproc: $(C_OBJS) $(DARCS_OBJS)
unit: $(C_OBJS) $(UNIT_OBJS)
clean::
	rm -f darcs darcs_p microbench preproc unit

TEXSOURCES = preproc src/darcs.tex $(wildcard src/*.tex) $(filter %.lhs,$(DARCS_FILES))
doc/manual/darcs.tex: $(TEXSOURCES)
	./preproc darcs.tex $(PREPROCHTML) >$@
doc/manual/darcs_print.tex: $(TEXSOURCES)
	./preproc darcs.tex >$@
doc/manual/patch-theory.tex: $(TEXSOURCES) $(UNIT_FILES)
	./preproc Darcs/Patch/Properties.lhs >$@

.PHONY: ps pdf html
ps pdf: %: doc/manual/darcs.% doc/manual/patch-theory.%
html: doc/manual/index.html
website: ps pdf html doc/manual/bigpage.html doc/index.html

doc/manual/index.html: doc/manual/darcs.tex src/gpl.tex doc/darcs.css
	$(MAKEMANUAL)
	cp -f doc/darcs.css doc/manual/darcs.css

doc/manual/bigpage.html: doc/manual/darcs.tex src/gpl.tex doc/darcs.css
	ln -sf darcs.tex doc/manual/bigpage.tex
	latex2html -split 0 -external_file darcs -prefix big \
		-no_auto_link -dir doc/manual doc/manual/bigpage.tex
	cp -f doc/darcs.css doc/manual/bigpage.css
clean::
	rm -f doc/manual/bigpage.tex

doc/manual/darcs.ps: doc/manual/darcs_print.ps
	cp $< $@
doc/manual/darcs.pdf: doc/manual/darcs_print.pdf
	cp $< $@

doc/darcs.1:	darcs
	./$< help manpage > $@

AUTHORS: darcs
	./$< show authors > $@

disttest:
	@echo '**********************************************************************'
	@echo Note: to prevent darcs from running tests by default, you can put
	@echo the following entries in _darcs/prefs/defaults
	@echo
	@echo record no-test
	@echo amend-record no-test
	@echo
	@echo It would be helpful if you ran the tests sometime before sending in
	@echo your patches.  You can do so by running darcs check.
	@echo
	@echo To run a faster subset of the tests, just run make check.
	@echo '**********************************************************************'
	@printf %s 'Checking for QuickCheck 2... '
	@if ghc-pkg list QuickCheck | grep 'QuickCheck-2\..' >/dev/null 2>&1; \
	 then echo yes; \
	 else echo no; \
	      echo "You need QuickCheck 2 to run the tests! Try"; \
	      echo "darcs get http://darcs.haskell.org/QuickCheck"; \
	      false; \
	 fi
	autoconf
	./configure --with-type-witnesses
	$(MAKE) witnesses
	$(MAKE) clean
	./configure
	$(MAKE) all unit
	$(MAKE) check test-network

slowdisttest: disttest test_unit

hspwd: tests/hspwd.hs
	$(ANNOUNCE_GHC) --make -o $@ $<

shell_harness: tests/shell_harness.hs
	$(ANNOUNCE_GHC) --make -o $@ $<

TEST_FILTER_FILE = tests_to_run
SHELL_HARNESS = ../shell_harness
FORMATS = darcs-2 hashed old-fashioned-inventory
$(addprefix test-,$(FORMATS)): test-%: darcs hspwd shell_harness
	@echo Applying functional tests to $* repositories...
	test ! -d $@ || chmod -R u+rwx $@
	rm -rf $@
	cp -R tests $@
	mkdir -p $@/.darcs
	echo >>$@/.darcs/defaults ALL --$*
	cd $@ && \
	  if test -r $(TEST_FILTER_FILE); \
	  then grep -v ^# $(TEST_FILTER_FILE) | xargs $(SHELL_HARNESS); \
	  else $(SHELL_HARNESS) *.sh; \
	  fi
$(addprefix bugs-,$(FORMATS)): bugs-%: darcs hspwd shell_harness
	@echo Applying known bugs to $* repositories...
	test ! -d $@ || chmod -R u+rwx $@
	rm -rf $@
	cp -R bugs $@
	mkdir -p $@/.darcs
	echo >>$@/.darcs/defaults ALL --$*
	cd $@ && \
	  if test -r $(TEST_FILTER_FILE); \
	  then grep -v ^# $(TEST_FILTER_FILE) | xargs $(SHELL_HARNESS) || true; \
	  else $(SHELL_HARNESS) *.sh || true; \
	  fi
# The other test targets check tests/*.sh.  test-network tests
# test/network/*.sh -- DIFFERENT tests.
test-network: darcs hspwd shell_harness
	@echo Applying tests that require network...
	test ! -d $@ || chmod -R u+rwx $@
	rm -rf $@
	cp -R tests/network $@
	mkdir -p $@/.darcs
	cd $@ && \
	  if test -r $(TEST_FILTER_FILE); \
	  then grep -v ^# $(TEST_FILTER_FILE) | xargs $(SHELL_HARNESS); \
	  else $(SHELL_HARNESS) *.sh; \
	  fi
.PHONY: $(addprefix test-,$(FORMATS)) $(addprefix bugs-,$(FORMATS))
.PHONY: test-network
clean::
	rm -rf test-network $(addprefix test-,$(FORMATS)) $(addprefix bugs-,$(FORMATS))

# Legacy names for the targets above.
test-format2 bugs-format2: %-format2: %-darcs-2
test-old bugs-old: %-old: %-old-fashioned-inventory
test_network: test-network
.PHONY: test-format2 bugs-format2 test-old bugs-old test_network
# Targets for all tests/bugs.
test tests check: $(addprefix test-,$(FORMATS))
bugs: $(addprefix bugs-,$(FORMATS))
.PHONY: test tests check bugs

test_unit:     darcs unit
	./unit

clean::
	find src \( -name \*.o -o -name \*.hi \) -exec rm -f {} \;
	find src \( -name \*.p_o -o -name \*.p_hi \) -exec rm -f {} \;
	rm -f Distribution/*.o Distribution/*.hi tests/*.o tests/*.hi
	rm -f diff darcs_cgi
	rm -f stringify
	rm -f $(addprefix doc/manual/*.,tex aux dvi log toc)
	rm -f hspwd shell_harness
	rm -rf tests/temp* darcs.log darcs.toc
	rm -f conftest* .depend.bak
	rm -f src/win32/System/Posix/IO.hs src/win32/System/Posix/Files.hs
	rm -f version.nsi
	rm -rf api-doc
	rm -rf hoogle
	#only remove src/Context.hs if we have a darcs inventory to rebuild it from
	if test -f _darcs/inventory; then rm -f src/Context.hs; fi
	# these files might be around from before they were renamed to .hs (Nov 2008)

distclean::	clean
	rm -rf config.status config.log autoconf.mk config.cache autom4te.cache
	rm -f doc/manual/darcs.ps doc/manual/darcs.pdf doc/manual/patch-theory.pdf darcs.idv
	rm -f contrib/cgi/README contrib/cgi/darcs.cgi contrib/cgi/cgi.conf
	rm -f config.command
	rm -rf snapshots

# This command is intended for maintainers to use; it
# deletes files that may need special tools to rebuild.
maintainer-clean:: distclean
	rm -f configure doc/darcs.1 .depend .depend_p AUTHORS
	rm -f src/Context.hs
	rm -f doc/manual/*.html doc/manual/darcs*.??? doc/manual/darcs.lg
	rm -f doc/manual/darcs.xref c_context.c doc/darcs_print.ps
	rm -rf tests/test_output

configure:		configure.ac aclocal.m4
	autoconf

autoconf.mk contrib/cgi/darcs.cgi : % : %.in config.status
	./config.status

config.status:	configure
	@if test -x config.status; then					\
	  ./config.status --recheck;					\
	else								\
	  echo >&2 "Please run ./configure to setup the build system.";	\
	  exit 1;							\
	fi

.depend:	autoconf.mk $(DARCS_FILES) $(UNIT_FILES)
	$(ANNOUNCE_GHC) $(GHCFLAGS) -M -optdep-f -optdep$@ $(filter %.lhs %.hs,$^)
.depend_p: .depend
	sed 's/\.\(hi\|o\)/.p_\1/g' $< >$@

# Fixme: Generate correct list of .c files.

# Always generate both tags and TAGS when the user asks for either,
# because lispy doesn't like using the shift key.
tags TAGS: $(DARCS_FILES) src/*.c
	hasktags -b $(filter %.lhs %.hs,$^)
	ctags -a $(filter %.c,$^)
# The test part tells make not to care if etags isn't installed, while
# still caring about etags crashing.  This is a Good Thing because you
# probably won't have etags installed unless you're an Emacs user.
	etags -a $(filter %.c,$^) || test $$? -eq 126 -o $$? -eq 127
distclean::
	rm -f TAGS tags
