#
# 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)
ifeq ($(HAVE_CURSES),True)
GHCFLAGS_src__Darcs__External.o = $(GHCFLAGS)
ifeq ($(HAVE_TERMIO_H),True)
# This termio bit is a grim hack for Solaris 10 (at least).
# Without it, SGTTY isn't declared.  Something in the ghc C headers
# which get included before term.h in the generated C is clobbering
# it.  (If you edit that C and put the curses.h and term.h first, the
# error goes away.)
GHCFLAGS_src__Darcs__External.o += '-\#include <termio.h>'
endif
GHCFLAGS_src__Darcs__External.o += '-\#include <curses.h>' '-\#include <term.h>'
endif

# 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/Autoconf.hs src/Context.hs src/ThisVersion.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 hslibwww)

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\
		api-doc-dir

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) tools/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/*.ps $<
install-pdf:	$(DESTDIR)$(docdir)/manual pdf
	$(INSTALL_DATA) doc/manual/*.pdf $<
install-html:	$(DESTDIR)$(docdir)/manual html
	$(INSTALL_DATA) doc/manual/*.png $<
	$(INSTALL_DATA) doc/manual/*.html $<
install-examples:	$(DESTDIR)$(docdir)/examples
	$(INSTALL_DATA) tools/zsh_completion_new $<
	$(INSTALL_DATA) tools/zsh_completion_old $<
.PHONY: install-ps install-pdf install-html install-examples

installserver:	tools/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) tools/cgi/cgi.conf $(DESTDIR)$(sysconfdir)/darcs/cgi.conf
	$(INSTALL) tools/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) tools/cgi/xslt/*.xslt $(DESTDIR)$(datadir)/darcs/xslt/
	$(INSTALL_DATA) tools/cgi/xslt/errors.xml $(DESTDIR)$(datadir)/darcs/xslt/
	$(INSTALL_DATA) tools/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 tools/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

#ensure the directory exists for api documentation
api-doc-dir:
	mkdir -p api-doc

#generate the api documentation
api-doc: api-doc-dir $(DARCS_FILES)
	@test $(HADDOCK_VERSION) -ge 2 || { echo "You need haddock 2.0.0 or later to build the API documentation"; false; }
	haddock --ignore-all-exports $(patsubst %,--optghc=%,$(GHCFLAGS)) -B `$(GHC) --print-libdir` -o api-doc -h $(filter %.hs %.lhs,$^)
	cp api-doc/index.html api-doc/modules-index.html

#generate the api documentation with links to colourised source code
api-doc-with-source: api-doc-dir colourised-source $(DARCS_FILES) src/darcs.hs
	@test $(HADDOCK_VERSION) -ge 2 || { echo "You need haddock 2.0.0 or later to build the API documentation"; false; }
	haddock --no-warnings --ignore-all-exports $(patsubst %,--optghc=%,$(GHCFLAGS)) -B `$(GHC) --print-libdir` -o api-doc -h --source-module=src-%{MODULE/./-}.html $(filter %.hs %.lhs,$^)
	cp api-doc/index.html api-doc/modules-index.html
# --source-entity=src-%{MODULE/./-}.html#%N # awaiting http://code.google.com/p/ndmitchell/issues/detail?id=95

# munge haddock and hoogle into a rough but useful framed layout
# ensure that the hoogle cgi is built with base target "main"
api-doc-frames: api-doc-with-source hoogleweb
	sed -i -e 's%^></head%><base target="main"></head%i' api-doc/modules-index.html
	cp doc/misc/api-doc-frames.html api-doc/index.html
	cp doc/misc/hoogle-small.html hoogle

colourised-source: api-doc-dir $(DARCS_FILES) src/darcs.hs
	for f in $(DARCS_FILES) src/darcs.hs; do \
		HsColour -css -anchor $$f -oapi-doc/`echo $$f | sed -e's%/%-%g' | sed -e's%\.l\?hs$$%.html%'` ; \
	done
	mv api-doc/src-darcs.html api-doc/src-Main.html
	HsColour -print-css >api-doc/hscolour.css

#generate a hoogle index
#currently (2008/10) you should use the darcs version of hoogle
hoogleindex: $(DARCS_FILES) src/darcs.hs
	mkdir -p hoogle
	haddock --no-warnings --ignore-all-exports $(patsubst %,--optghc=%,$(GHCFLAGS)) -B `$(GHC) --print-libdir` -o hoogle --hoogle $^
	cd hoogle && hoogle --convert=main.txt --output=default.hoo

#set up the hoogle web interface
#uses a hoogle source tree configured with --datadir=. and patched to fix haddock urls
HOOGLESRC=/usr/local/src/hoogle
HOOGLE=$(HOOGLESRC)/dist/build/hoogle/hoogle
HOOGLEVER=`$(HOOGLE) --version |tail -n 1 | sed -e 's/Version /hoogle-/'`
hoogleweb: hoogleindex
	mkdir -p hoogle
	rm -f hoogle/$(HOOGLEVER)
	ln -s . hoogle/$(HOOGLEVER)
	cp -r $(HOOGLESRC)/deploy/res/ hoogle/
	cp -p $(HOOGLE) hoogle/index.cgi
	touch log.txt
	chmod 666 log.txt

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)
darcsman list_authors microbench preproc: $(C_OBJS) $(DARCS_OBJS)
unit: $(C_OBJS) $(UNIT_OBJS)

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: darcs 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:	darcsman
	./$< > $@

AUTHORS:	list_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 unit diff darcs darcs_cgi
	rm -f stringify
	rm -f $(addprefix doc/manual/*.,tex aux dvi log toc)
	rm -f preproc darcsman 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 -f list_authors
	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)
	rm -f src/ThisVersion.lhs src/Autoconf.lhs

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 src/Autoconf.hs darcs.idv
	rm -f src/ThisVersion.hs tools/cgi/README tools/cgi/darcs.cgi tools/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 src/Autoconf.hs tools/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
