public inbox for gentoo-dev@lists.gentoo.org
 help / color / mirror / Atom feed
* [gentoo-dev] git-2.eclass final review
@ 2011-03-22 21:07 Tomáš Chvátal
  2011-03-22 21:26 ` Mike Frysinger
  2011-04-17  8:44 ` [gentoo-dev] " Tomá? Chvátal
  0 siblings, 2 replies; 24+ messages in thread
From: Tomáš Chvátal @ 2011-03-22 21:07 UTC (permalink / raw
  To: gentoo-dev


[-- Attachment #1.1: Type: text/plain, Size: 311 bytes --]

Hi guys,
as there are no more complaints in kde overlay i would like you to test
your git using live ebuild with this new git-2 eclass and tell me how
you like it.

Also usual review of what already is in is welcomed because i would
really really like to move this thing into main tree.

Cheers

Tom

[-- Attachment #1.2: git-2.eclass --]
[-- Type: text/plain, Size: 12516 bytes --]

# Copyright 1999-2011 Gentoo Foundation
# Distributed under the terms of the GNU General Public License v2
# $Header: $

# @ECLASS: git-2.eclass
# @MAINTAINER:
# Tomas Chvatal <scarabeus@gentoo.org>
# @BLURB: This eclass provides functions for fetch and unpack git repositories
# @DESCRIPTION:
# Eclass for easing maitenance of live ebuilds using git as remote repository.
# Eclass support working with git submodules and branching.

# This eclass support all EAPIs
EXPORT_FUNCTIONS src_unpack

DEPEND="dev-vcs/git"

# This static variable is for storing the data in WORKDIR.
# Sometimes we might want to redefine S.
EGIT_SOURCEDIR="${WORKDIR}/${P}"

# @FUNCTION: git-2_init_variables
# @DESCRIPTION:
# Internal function initializing all git variables.
# We define it in function scope so user can define
# all the variables before and after inherit.
git-2_init_variables() {
	debug-print-function ${FUNCNAME} "$@"

	# @ECLASS-VARIABLE: EGIT_STORE_DIR
	# @DESCRIPTION:
	# Storage directory for git sources.
	: ${EGIT_STORE_DIR:="${PORTAGE_ACTUAL_DISTDIR-${DISTDIR}}/egit-src"}

	# @ECLASS-VARIABLE: EGIT_HAS_SUBMODULES
	# @DESCRIPTION:
	# Set this to non-empty value to enable submodule support.
	: ${EGIT_HAS_SUBMODULES:=}

	# @ECLASS-VARIABLE: EGIT_FETCH_CMD
	# @DESCRIPTION:
	# Command for cloning the repository.
	: ${EGIT_FETCH_CMD:="git clone"}

	# @ECLASS-VARIABLE: EGIT_UPDATE_CMD
	# @DESCRIPTION:
	# Git fetch command.
	: ${EGIT_UPDATE_CMD:="git pull -f -u"}

	# @ECLASS-VARIABLE: EGIT_OPTIONS
	# @DESCRIPTION:
	# This variable value is passed to clone and fetch.
	: ${EGIT_OPTIONS:=}

	# @ECLASS-VARIABLE: EGIT_MASTER
	# @DESCRIPTION:
	# Variable for specifying master branch.
	# Usefull when upstream don't have master branch.
	: ${EGIT_MASTER:=master}

	# @ECLASS-VARIABLE: EGIT_REPO_URI
	# @DESCRIPTION:
	# URI for the repository
	# e.g. http://foo, git://bar
	#
	# Support multiple values:
	# EGIT_REPO_URI="git://a/b.git http://c/d.git"
	eval X="\$${PN//[-+]/_}_LIVE_REPO"
	if [[ ${X} = "" ]]; then
		: ${EGIT_REPO_URI:=}
	else
		EGIT_REPO_URI="${X}"
	fi
	[[ -z ${EGIT_REPO_URI} ]] && die "EGIT_REPO_URI must have some value."

	# @ECLASS-VARIABLE: EVCS_OFFLINE
	# @DESCRIPTION:
	# Set this variable to a non-empty value to disable the automatic updating
	# of an GIT source tree. This is intended to be set outside the git source
	# tree by users.
	: ${EVCS_OFFLINE:=}

	# @ECLASS-VARIABLE: EGIT_BRANCH
	# @DESCRIPTION:
	# Specify the branch we want to check out from the repository
	eval X="\$${PN//[-+]/_}_LIVE_BRANCH"
	if [[ "${X}" = "" ]]; then
		: ${EGIT_BRANCH:=${EGIT_MASTER}}
	else
		EGIT_BRANCH="${X}"
	fi

	# @ECLASS-VARIABLE: EGIT_COMMIT
	# @DESCRIPTION:
	# Specify commit we want to check out from the repository.
	eval X="\$${PN//[-+]/_}_LIVE_COMMIT"
	if [[ "${X}" = "" ]]; then
		: ${EGIT_COMMIT:=${EGIT_BRANCH}}
	else
		EGIT_COMMIT="${X}"
	fi

	# @ECLASS-VARIABLE: EGIT_REPACK
	# @DESCRIPTION:
	# Set to non-empty value to repack objects to save disk space. However this
	# can take a REALLY LONG time with VERY big repositories.
	: ${EGIT_REPACK:=}

	# @ECLASS-VARIABLE: EGIT_PRUNE
	# @DESCRIPTION:
	# Set to non-empty value to prune loose objects on each fetch. This is
	# useful if upstream rewinds and rebases branches often.
	: ${EGIT_PRUNE:=}

}

# @FUNCTION: git-2_submodules
# @DESCRIPTION:
# Internal function wrapping the submodule initialisation and update
git-2_submodules() {
	debug-print-function ${FUNCNAME} "$@"

	[[ "$#" -ne 1 ]] && die "${FUNCNAME}: requires 1 argument (path)"

	debug-print "${FUNCNAME}: working in \"${1}\""
	pushd "${1}" &> /dev/null

	# for submodules operations we need to be online
	if [[ -z ${EVCS_OFFLINE} && -n ${EGIT_HAS_SUBMODULES} ]]; then
		export GIT_DIR=${EGIT_DIR}
		debug-print "${FUNCNAME}: git submodule init"
		git submodule init \
			|| die "${FUNCNAME}: git submodule initialisation failed"
		debug-print "${FUNCNAME}: git submodule sync"
		git submodule sync "" die "${FUNCNAME}: git submodule sync failed"
		debug-print "${FUNCNAME}: git submodule update"
		git submodule update || die "${FUNCNAME}: git submodule update failed"
		unset GIT_DIR
	fi

	popd > /dev/null
}

# @FUNCTION: git-2_branch
# @DESCRIPTION:
# Internal function that changes branch for the repo based on EGIT_COMMIT and
# EGIT_BRANCH variables.
git-2_branch() {
	debug-print-function ${FUNCNAME} "$@"

	debug-print "${FUNCNAME}: working in \"${EGIT_SOURCEDIR}\""
	pushd "${EGIT_SOURCEDIR}" &> /dev/null

	local branchname=branch-${EGIT_BRANCH} src=origin/${EGIT_BRANCH}
	if [[ "${EGIT_COMMIT}" != "${EGIT_BRANCH}" ]]; then
		branchname=tree-${EGIT_COMMIT}
		src=${EGIT_COMMIT}
	fi
	debug-print "${FUNCNAME}: git checkout -b ${branchname} ${src}"
	git checkout -b ${branchname} ${src} \
		|| die "${FUNCNAME}: changing the branch failed"

	popd > /dev/null

	unset branchname src
}

# @FUNCTION: git-2_gc
# @DESCRIPTION:
# Internal function running garbage collector on checked out tree.
git-2_gc() {
	debug-print-function ${FUNCNAME} "$@"

	pushd "${EGIT_DIR}" &> /dev/null
	if [[ -n ${EGIT_REPACK} || -n ${EGIT_PRUNE} ]]; then
		ebegin "Garbage collecting the repository"
		local args
		[[ -n ${EGIT_PRUNE} ]] && args='--prune'
		debug-print "${FUNCNAME}: git gc ${args}"
		git gc ${args}
		eend $?
	fi
	popd &> /dev/null
}

# @FUNCTION: git-2_prepare_storedir
# @DESCRIPTION:
# Internal function preparing directory where we are going to store SCM
# repository.
git-2_prepare_storedir() {
	debug-print-function ${FUNCNAME} "$@"

	local clone_dir
	local save_sandbox_write=${SANDBOX_WRITE}

	# initial clone, we have to create master git storage directory and play
	# nicely with sandbox
	if [[ ! -d "${EGIT_STORE_DIR}" ]] ; then
		debug-print "${FUNCNAME}: Creating git main storage directory"
		addwrite /
		mkdir -p "${EGIT_STORE_DIR}" \
			|| die "${FUNCNAME}: can't mkdir \"${EGIT_STORE_DIR}\"."
		SANDBOX_WRITE=${save_sandbox_write}
	fi

	cd -P "${EGIT_STORE_DIR}" \
		|| die "${FUNCNAME}:  can't chdir to \"${EGIT_STORE_DIR}\""
	# allow writing into EGIT_STORE_DIR
	addwrite "${EGIT_STORE_DIR}"
	# calculate the proper store dir for data
	[[ -z ${EGIT_REPO_URI##*/} ]] && EGIT_REPO_URI="${EGIT_REPO_URI%/}"
	clone_dir="${EGIT_REPO_URI##*/}"
	export EGIT_DIR="${EGIT_STORE_DIR}/${clone_dir}"
	debug-print "${FUNCNAME}: Storing the repo into \"${EGIT_DIR}\"."

	# we can not jump between using and not using SUBMODULES so we need to
	# refetch the source when needed
	if [[ -d "${EGIT_DIR}" && ! -d "${EGIT_DIR}"/.git ]]; then
		debug-print "${FUNCNAME}: \"${clone_dir}\" was bare copy moving..."
		mv "${EGIT_DIR}" "${EGIT_DIR}.bare" \
			|| die "${FUNCNAME}: Moving the bare sources failed."

	fi
	# Tell user that he can remove his bare repository. It is not used.
	if [[ -d "${EGIT_DIR}.bare" ]]; then
		einfo "Found GIT bare repository at \"${EGIT_DIR}.bare\"."
		einfo "This folder can be safely removed to save space."
	fi
}

# @FUNCTION: git-2_move_source
# @DESCRIPTION:
# Internal function moving sources from the EGIT_DIR to EGIT_SOURCEDIR dir.
git-2_move_source() {
	debug-print-function ${FUNCNAME} "$@"

	pushd "${EGIT_DIR}" &> /dev/null
	debug-print "${FUNCNAME}: rsync -rlpgo . \"${EGIT_SOURCEDIR}\""
	rsync -rlpgo . "${EGIT_SOURCEDIR}" \
		|| die "${FUNCNAME}: sync to \"${EGIT_SOURCEDIR}\" failed"
	popd &> /dev/null
}

# @FUNCTION: git-2_initial_clone
# @DESCRIPTION:
# Run initial clone on specified repo_uri
git-2_initial_clone() {
	debug-print-function ${FUNCNAME} "$@"

	local repo_uri

	for repo_uri in ${EGIT_REPO_URI}; do
		debug-print "${FUNCNAME}: ${EGIT_FETCH_CMD} ${EGIT_OPTIONS} \"${repo_uri}\" \"${EGIT_DIR}\""
		${EGIT_FETCH_CMD} ${EGIT_OPTIONS} "${repo_uri}" "${EGIT_DIR}"
		if [[ $? -eq 0 ]]; then
			# global variable containing the repo_name we will be using
			debug-print "${FUNCNAME}: EGIT_REPO_URI_SELECTED=\"${repo_uri}\""
			EGIT_REPO_URI_SELECTED="${repo_uri}"
			break
		fi
	done

	if [[ -z ${EGIT_REPO_URI_SELECTED} ]]; then
		die "${FUNCNAME}: can't fetch from ${EGIT_REPO_URI}."
	fi
}

# @FUNCTION: git-2_update_repo
# @DESCRIPTION:
# Run update command on specified repo_uri
git-2_update_repo() {
	debug-print-function ${FUNCNAME} "$@"

	local repo_uri

	# checkout master branch and drop all other local branches
	git checkout ${EGIT_MASTER}
	for x in $(git branch |grep -v "* ${EGIT_MASTER}" |tr '\n' ' '); do
		debug-print "${FUNCNAME}: git branch -D ${x}"
		git branch -D ${x}
	done

	for repo_uri in ${EGIT_REPO_URI}; do
		# git urls might change, so reset it
		git config remote.origin.url "${repo_uri}"

		debug-print "${EGIT_UPDATE_CMD} ${EGIT_OPTIONS}"
		${EGIT_UPDATE_CMD} ${EGIT_OPTIONS}

		if [[ $? -eq 0 ]]; then
			# global variable containing the repo_name we will be using
			debug-print "${FUNCNAME}: EGIT_REPO_URI_SELECTED=\"${repo_uri}\""
			EGIT_REPO_URI_SELECTED="${repo_uri}"
			break
		fi
	done

	if [[ -z ${EGIT_REPO_URI_SELECTED} ]]; then
		die "${FUNCNAME}: can't update from ${EGIT_REPO_URI_SELECTED}."
	fi
}

# @FUNCTION: git-2_fetch
# @DESCRIPTION:
# Internal function fetching repository from EGIT_REPO_URI and storing it in
# specified EGIT_STORE_DIR.
git-2_fetch() {
	debug-print-function ${FUNCNAME} "$@"

	local oldsha cursha upstream_branch

	upstream_branch=origin/${EGIT_BRANCH}

	if [[ ! -d ${EGIT_DIR} ]] ; then
		git-2_initial_clone
		pushd "${EGIT_DIR}" &> /dev/null
		cursha=$(git rev-parse ${upstream_branch})
		einfo "GIT NEW clone -->"
		einfo "   repository:               ${EGIT_REPO_URI_SELECTED}"
		einfo "   at the commit:            ${cursha}"

		git-2_submodules "${EGIT_DIR}"
		popd &> /dev/null
	elif [[ -n ${EVCS_OFFLINE} ]] ; then
		pushd "${EGIT_DIR}" &> /dev/null
		cursha=$(git rev-parse ${upstream_branch})
		einfo "GIT offline update -->"
		einfo "   repository:               $(git config remote.origin.url)"
		einfo "   at the commit:            ${cursha}"
		popd &> /dev/null
	else
		pushd "${EGIT_DIR}" &> /dev/null
		oldsha=$(git rev-parse ${upstream_branch})
		git-2_update_repo
		cursha=$(git rev-parse ${upstream_branch})

		# fetch updates
		einfo "GIT update -->"
		einfo "   repository:               ${EGIT_REPO_URI_SELECTED}"
		# write out message based on the revisions
		if [[ "${oldsha1}" != "${cursha1}" ]]; then
			einfo "   updating from commit:     ${oldsha}"
			einfo "   to commit:                ${cursha}"
		else
			einfo "   at the commit:            ${cursha}"
		fi

		git-2_submodules "${EGIT_DIR}"

		# print nice statistic of what was changed
		git --no-pager diff --stat ${oldsha}..${upstream_branch}
		popd &> /dev/null
	fi
	# export the version the repository is at
	export EGIT_VERSION="${cursha1}"
	# log the repo state
	[[ "${EGIT_COMMIT}" != "${EGIT_BRANCH}" ]] \
		&& einfo "   commit:                   ${EGIT_COMMIT}"
	einfo "   branch:                   ${EGIT_BRANCH}"
	einfo "   storage directory:        \"${EGIT_DIR}\""
}

# @FUNCTION: git_bootstrap
# @DESCRIPTION:
# Internal function that runs bootstrap command on unpacked source.
git-2_bootstrap() {
	debug-print-function ${FUNCNAME} "$@"

	# @ECLASS_VARIABLE: EGIT_BOOTSTRAP
	# @DESCRIPTION:
	# Command to be executed after checkout and clone of the specified
	# repository.
	# enviroment the package will fail if there is no update, thus in
	# combination with --keep-going it would lead in not-updating
	# pakcages that are up-to-date.
	if [[ -n ${EGIT_BOOTSTRAP} ]] ; then
		pushd "${EGIT_SOURCEDIR}" &> /dev/null
		einfo "Starting bootstrap"

		if [[ -f ${EGIT_BOOTSTRAP} ]]; then
			# we have file in the repo which we should execute
			debug-print "${FUNCNAME}: bootstraping with file \"${EGIT_BOOTSTRAP}\""

			if [[ -x ${EGIT_BOOTSTRAP} ]]; then
				eval "./${EGIT_BOOTSTRAP}" \
					|| die "${FUNCNAME}: bootstrap script failed"
			else
				eerror "\"${EGIT_BOOTSTRAP}\" is not executable."
				eerror "Report upstream, or bug ebuild maintainer to remove bootstrap command."
				die "\"${EGIT_BOOTSTRAP}\" is not executable."
			fi
		else
			# we execute some system command
			debug-print "${FUNCNAME}: bootstraping with commands \"${EGIT_BOOTSTRAP}\""

			eval "${EGIT_BOOTSTRAP}" \
				|| die "${FUNCNAME}: bootstrap commands failed."
		fi

		einfo "Bootstrap finished"
		popd > /dev/null
	fi
}

# @FUNCTION: git-2_src_unpack
# @DESCRIPTION:
# src_upack function
git-2_src_unpack() {
	debug-print-function ${FUNCNAME} "$@"

	git-2_init_variables
	git-2_prepare_storedir
	git-2_fetch $@
	git-2_gc
	git-2_move_source
	git-2_branch
	git-2_submodules "${EGIT_SOURCEDIR}"
	git-2_bootstrap
	echo ">>> Unpacked to ${EGIT_SOURCEDIR}"
}

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 262 bytes --]

^ permalink raw reply	[flat|nested] 24+ messages in thread

end of thread, other threads:[~2011-04-18 17:57 UTC | newest]

Thread overview: 24+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2011-03-22 21:07 [gentoo-dev] git-2.eclass final review Tomáš Chvátal
2011-03-22 21:26 ` Mike Frysinger
2011-03-22 22:38   ` Tomáš Chvátal
2011-03-22 23:08     ` Mike Frysinger
2011-03-22 23:41       ` [gentoo-dev] " Ryan Hill
2011-03-22 23:45         ` Ryan Hill
2011-03-22 23:55         ` Mike Frysinger
2011-03-23 12:28           ` James Cloos
2011-03-23 13:01             ` Tomáš Chvátal
2011-03-23 14:44               ` James Cloos
2011-03-24 12:54                 ` Donnie Berkholz
2011-03-23 16:29             ` Donnie Berkholz
2011-03-24 10:52               ` James Cloos
2011-03-23  0:42       ` [gentoo-dev] " Tomáš Chvátal
2011-03-31  4:55         ` Jeroen Roovers
2011-03-31  6:32           ` Tomáš Chvátal
2011-03-31  7:29             ` Fabian Groffen
2011-03-31 16:00             ` Matt Turner
2011-03-31 21:23               ` Aaron W. Swenson
2011-04-05 15:18       ` Marc Schiffbauer
2011-04-17  8:44 ` [gentoo-dev] " Tomá? Chvátal
2011-04-17 18:31   ` James Cloos
2011-04-18  9:45     ` Tomáš Chvátal
2011-04-18 17:55       ` James Cloos

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox