#!/bin/sh

fossildir=/var/fossil
# Cannot be a bare directory for git as we cannot write to the host directly.
# So we have a staging directory instead.
# This requires a bit of hand-holding to track all the branches.
gitdir=/var/git-staging

marksdir=/var/scm-marks

# Respect default naming at either end
fossil_export_opts="--rename-trunk master"
fossil_import_opts="--rename-master trunk"

# Only used when creating a git bare bones repo from Fossil.
export_fossil_to_git_new()
{

	rm -f "$fossilmarks" "$gitmarks"
	git init
	fossil export --git \
		--export-marks "$fossilmarks" \
		$fossil_export_opts "$fossildir/$fossilrepo" | \
		git fast-import \
		--export-marks="$gitmarks"
	# Force a gc to reduce size
	git gc --prune=now --aggressive
}

export_fossil_to_git()
{

	fossil export --git \
		--import-marks "$fossilmarks" --export-marks "$fossilmarks" \
		$fossil_export_opts "$fossildir/$fossilrepo" | \
		git fast-import \
		--import-marks="$gitmarks" --export-marks="$gitmarks"
}

export_git_to_fossil()
{

	git fast-export --all \
		--import-marks="$gitmarks" --export-marks="$gitmarks" | \
		fossil import --git --incremental \
		--import-marks "$fossilmarks" --export-marks "$fossilmarks" \
		$fossil_import_opts "$fossildir/$fossilrepo"
}

pull_git()
{
	local remote

	git fetch --all
	# Track all remote branches
	git branch -r | grep -v '\->' | while read remote; do
		if [ -z "$(git branch --list "${remote#origin/}")" ]; then		
			git branch --track "${remote#origin/}" "$remote"
		fi
	done
	git branch --list | sed -e 's/^\* //' | while read branch; do
		git checkout "$branch"
		git merge --ff-only
	done
}

push_git()
{

	git push --all
	git push --tags
	# Reset the current branch checkout.
	# If we don't, the next run will complain about unstashed changes.
	# This maybe a bug in git, but maybe not because the live checkout
	# *is* behind at this point as we just fast-imported.
	git reset --hard
}

echo "Syncing git and fossil."
for repo in "$fossildir"/*.fossil; do
	fossilrepo=${repo#${fossildir}/*}
	repo=${fossilrepo%.fossil}
	gitrepo="$repo"
	fossilmarks="$marksdir/$repo.fossil.marks"
	gitmarks="$marksdir/$repo.git.marks"

	# We just sync fossil repos to existing git ones
	if [ -d "$gitdir/$gitrepo" ]; then
		cd "$gitdir/$gitrepo"
		pull_git # staging only
		export_git_to_fossil
		export_fossil_to_git
		push_git # staging only
# Enable the below if pusing to a bare git repo from fossil
#	else
#		export_fossil_to_git_new
	fi
done
