1 |
mgorny |
1.24 |
# Copyright 1999-2014 Gentoo Foundation |
2 |
mgorny |
1.1 |
# Distributed under the terms of the GNU General Public License v2 |
3 |
mgorny |
1.25 |
# $Header: /var/cvsroot/gentoo-x86/eclass/git-r3.eclass,v 1.24 2014/02/23 22:05:55 mgorny Exp $ |
4 |
mgorny |
1.1 |
|
5 |
|
|
# @ECLASS: git-r3.eclass |
6 |
|
|
# @MAINTAINER: |
7 |
|
|
# Michał Górny <mgorny@gentoo.org> |
8 |
|
|
# @BLURB: Eclass for fetching and unpacking git repositories. |
9 |
|
|
# @DESCRIPTION: |
10 |
|
|
# Third generation eclass for easing maitenance of live ebuilds using |
11 |
mgorny |
1.24 |
# git as remote repository. |
12 |
mgorny |
1.1 |
|
13 |
|
|
case "${EAPI:-0}" in |
14 |
|
|
0|1|2|3|4|5) |
15 |
|
|
;; |
16 |
|
|
*) |
17 |
|
|
die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" |
18 |
|
|
;; |
19 |
|
|
esac |
20 |
|
|
|
21 |
|
|
if [[ ! ${_GIT_R3} ]]; then |
22 |
|
|
|
23 |
|
|
inherit eutils |
24 |
|
|
|
25 |
|
|
fi |
26 |
|
|
|
27 |
|
|
EXPORT_FUNCTIONS src_unpack |
28 |
|
|
|
29 |
|
|
if [[ ! ${_GIT_R3} ]]; then |
30 |
|
|
|
31 |
mgorny |
1.14 |
if [[ ! ${_INHERITED_BY_GIT_2} ]]; then |
32 |
mgorny |
1.24 |
DEPEND="dev-vcs/git" |
33 |
mgorny |
1.14 |
fi |
34 |
mgorny |
1.13 |
|
35 |
mgorny |
1.1 |
# @ECLASS-VARIABLE: EGIT3_STORE_DIR |
36 |
|
|
# @DESCRIPTION: |
37 |
|
|
# Storage directory for git sources. |
38 |
|
|
# |
39 |
|
|
# EGIT3_STORE_DIR=${DISTDIR}/git3-src |
40 |
|
|
|
41 |
|
|
# @ECLASS-VARIABLE: EGIT_REPO_URI |
42 |
|
|
# @REQUIRED |
43 |
|
|
# @DESCRIPTION: |
44 |
|
|
# URIs to the repository, e.g. git://foo, https://foo. If multiple URIs |
45 |
|
|
# are provided, the eclass will consider them as fallback URIs to try |
46 |
|
|
# if the first URI does not work. |
47 |
|
|
# |
48 |
|
|
# It can be overriden via env using ${PN}_LIVE_REPO variable. |
49 |
|
|
# |
50 |
mgorny |
1.9 |
# Can be a whitespace-separated list or an array. |
51 |
|
|
# |
52 |
mgorny |
1.1 |
# Example: |
53 |
|
|
# @CODE |
54 |
|
|
# EGIT_REPO_URI="git://a/b.git https://c/d.git" |
55 |
|
|
# @CODE |
56 |
|
|
|
57 |
|
|
# @ECLASS-VARIABLE: EVCS_OFFLINE |
58 |
|
|
# @DEFAULT_UNSET |
59 |
|
|
# @DESCRIPTION: |
60 |
|
|
# If non-empty, this variable prevents any online operations. |
61 |
|
|
|
62 |
|
|
# @ECLASS-VARIABLE: EGIT_BRANCH |
63 |
|
|
# @DEFAULT_UNSET |
64 |
|
|
# @DESCRIPTION: |
65 |
|
|
# The branch name to check out. If unset, the upstream default (HEAD) |
66 |
|
|
# will be used. |
67 |
|
|
# |
68 |
|
|
# It can be overriden via env using ${PN}_LIVE_BRANCH variable. |
69 |
|
|
|
70 |
|
|
# @ECLASS-VARIABLE: EGIT_COMMIT |
71 |
|
|
# @DEFAULT_UNSET |
72 |
|
|
# @DESCRIPTION: |
73 |
|
|
# The tag name or commit identifier to check out. If unset, newest |
74 |
|
|
# commit from the branch will be used. If set, EGIT_BRANCH will |
75 |
|
|
# be ignored. |
76 |
|
|
# |
77 |
|
|
# It can be overriden via env using ${PN}_LIVE_COMMIT variable. |
78 |
|
|
|
79 |
|
|
# @ECLASS-VARIABLE: EGIT_CHECKOUT_DIR |
80 |
|
|
# @DESCRIPTION: |
81 |
|
|
# The directory to check the git sources out to. |
82 |
|
|
# |
83 |
|
|
# EGIT_CHECKOUT_DIR=${WORKDIR}/${P} |
84 |
|
|
|
85 |
|
|
# @FUNCTION: _git-r3_env_setup |
86 |
|
|
# @INTERNAL |
87 |
|
|
# @DESCRIPTION: |
88 |
|
|
# Set the eclass variables as necessary for operation. This can involve |
89 |
|
|
# setting EGIT_* to defaults or ${PN}_LIVE_* variables. |
90 |
|
|
_git-r3_env_setup() { |
91 |
|
|
debug-print-function ${FUNCNAME} "$@" |
92 |
|
|
|
93 |
|
|
local esc_pn livevar |
94 |
|
|
esc_pn=${PN//[-+]/_} |
95 |
|
|
|
96 |
|
|
livevar=${esc_pn}_LIVE_REPO |
97 |
|
|
EGIT_REPO_URI=${!livevar:-${EGIT_REPO_URI}} |
98 |
|
|
[[ ${!livevar} ]] \ |
99 |
|
|
&& ewarn "Using ${livevar}, no support will be provided" |
100 |
|
|
|
101 |
|
|
livevar=${esc_pn}_LIVE_BRANCH |
102 |
|
|
EGIT_BRANCH=${!livevar:-${EGIT_BRANCH}} |
103 |
|
|
[[ ${!livevar} ]] \ |
104 |
|
|
&& ewarn "Using ${livevar}, no support will be provided" |
105 |
|
|
|
106 |
|
|
livevar=${esc_pn}_LIVE_COMMIT |
107 |
|
|
EGIT_COMMIT=${!livevar:-${EGIT_COMMIT}} |
108 |
|
|
[[ ${!livevar} ]] \ |
109 |
|
|
&& ewarn "Using ${livevar}, no support will be provided" |
110 |
|
|
|
111 |
|
|
# Migration helpers. Remove them when git-2 is removed. |
112 |
|
|
|
113 |
|
|
if [[ ${EGIT_SOURCEDIR} ]]; then |
114 |
|
|
eerror "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR. While updating" |
115 |
|
|
eerror "your ebuild, please check whether the variable is necessary at all" |
116 |
|
|
eerror "since the default has been changed from \${S} to \${WORKDIR}/\${P}." |
117 |
|
|
eerror "Therefore, proper setting of S may be sufficient." |
118 |
|
|
die "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR." |
119 |
|
|
fi |
120 |
|
|
|
121 |
|
|
if [[ ${EGIT_MASTER} ]]; then |
122 |
|
|
eerror "EGIT_MASTER has been removed. Instead, the upstream default (HEAD)" |
123 |
|
|
eerror "is used by the eclass. Please remove the assignment or use EGIT_BRANCH" |
124 |
|
|
eerror "as necessary." |
125 |
|
|
die "EGIT_MASTER has been removed." |
126 |
|
|
fi |
127 |
|
|
|
128 |
|
|
if [[ ${EGIT_HAS_SUBMODULES} ]]; then |
129 |
|
|
eerror "EGIT_HAS_SUBMODULES has been removed. The eclass no longer needs" |
130 |
|
|
eerror "to switch the clone type in order to support submodules and therefore" |
131 |
|
|
eerror "submodules are detected and fetched automatically." |
132 |
|
|
die "EGIT_HAS_SUBMODULES is no longer necessary." |
133 |
|
|
fi |
134 |
|
|
|
135 |
|
|
if [[ ${EGIT_PROJECT} ]]; then |
136 |
|
|
eerror "EGIT_PROJECT has been removed. Instead, the eclass determines" |
137 |
|
|
eerror "the local clone path using path in canonical EGIT_REPO_URI." |
138 |
|
|
eerror "If the current algorithm causes issues for you, please report a bug." |
139 |
|
|
die "EGIT_PROJECT is no longer necessary." |
140 |
|
|
fi |
141 |
|
|
|
142 |
|
|
if [[ ${EGIT_BOOTSTRAP} ]]; then |
143 |
|
|
eerror "EGIT_BOOTSTRAP has been removed. Please create proper src_prepare()" |
144 |
|
|
eerror "instead." |
145 |
|
|
die "EGIT_BOOTSTRAP has been removed." |
146 |
|
|
fi |
147 |
|
|
|
148 |
|
|
if [[ ${EGIT_NOUNPACK} ]]; then |
149 |
|
|
eerror "EGIT_NOUNPACK has been removed. The eclass no longer calls default" |
150 |
|
|
eerror "unpack function. If necessary, please declare proper src_unpack()." |
151 |
|
|
die "EGIT_NOUNPACK has been removed." |
152 |
|
|
fi |
153 |
|
|
} |
154 |
|
|
|
155 |
|
|
# @FUNCTION: _git-r3_set_gitdir |
156 |
|
|
# @USAGE: <repo-uri> |
157 |
|
|
# @INTERNAL |
158 |
|
|
# @DESCRIPTION: |
159 |
|
|
# Obtain the local repository path and set it as GIT_DIR. Creates |
160 |
|
|
# a new repository if necessary. |
161 |
|
|
# |
162 |
|
|
# <repo-uri> may be used to compose the path. It should therefore be |
163 |
|
|
# a canonical URI to the repository. |
164 |
|
|
_git-r3_set_gitdir() { |
165 |
|
|
debug-print-function ${FUNCNAME} "$@" |
166 |
|
|
|
167 |
|
|
local repo_name=${1#*://*/} |
168 |
|
|
|
169 |
mgorny |
1.7 |
# strip the trailing slash |
170 |
|
|
repo_name=${repo_name%/} |
171 |
|
|
|
172 |
mgorny |
1.1 |
# strip common prefixes to make paths more likely to match |
173 |
|
|
# e.g. git://X/Y.git vs https://X/git/Y.git |
174 |
|
|
# (but just one of the prefixes) |
175 |
|
|
case "${repo_name}" in |
176 |
mgorny |
1.8 |
# gnome.org... who else? |
177 |
|
|
browse/*) repo_name=${repo_name#browse/};; |
178 |
mgorny |
1.1 |
# cgit can proxy requests to git |
179 |
|
|
cgit/*) repo_name=${repo_name#cgit/};; |
180 |
|
|
# pretty common |
181 |
|
|
git/*) repo_name=${repo_name#git/};; |
182 |
|
|
# gentoo.org |
183 |
|
|
gitroot/*) repo_name=${repo_name#gitroot/};; |
184 |
|
|
# google code, sourceforge |
185 |
|
|
p/*) repo_name=${repo_name#p/};; |
186 |
|
|
# kernel.org |
187 |
|
|
pub/scm/*) repo_name=${repo_name#pub/scm/};; |
188 |
|
|
esac |
189 |
|
|
# ensure a .git suffix, same reason |
190 |
|
|
repo_name=${repo_name%.git}.git |
191 |
|
|
# now replace all the slashes |
192 |
|
|
repo_name=${repo_name//\//_} |
193 |
|
|
|
194 |
|
|
local distdir=${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}} |
195 |
|
|
: ${EGIT3_STORE_DIR:=${distdir}/git3-src} |
196 |
|
|
|
197 |
|
|
GIT_DIR=${EGIT3_STORE_DIR}/${repo_name} |
198 |
|
|
|
199 |
|
|
if [[ ! -d ${EGIT3_STORE_DIR} ]]; then |
200 |
|
|
( |
201 |
|
|
addwrite / |
202 |
mgorny |
1.17 |
mkdir -m0755 -p "${EGIT3_STORE_DIR}" || die |
203 |
mgorny |
1.1 |
) || die "Unable to create ${EGIT3_STORE_DIR}" |
204 |
|
|
fi |
205 |
|
|
|
206 |
|
|
addwrite "${EGIT3_STORE_DIR}" |
207 |
mgorny |
1.24 |
if [[ -e ${GIT_DIR}/shallow ]]; then |
208 |
|
|
einfo "${GIT_DIR} was a shallow clone, recreating..." |
209 |
|
|
rm -r "${GIT_DIR}" || die |
210 |
|
|
fi |
211 |
mgorny |
1.1 |
if [[ ! -d ${GIT_DIR} ]]; then |
212 |
|
|
mkdir "${GIT_DIR}" || die |
213 |
|
|
git init --bare || die |
214 |
|
|
fi |
215 |
|
|
} |
216 |
|
|
|
217 |
|
|
# @FUNCTION: _git-r3_set_submodules |
218 |
|
|
# @USAGE: <file-contents> |
219 |
|
|
# @INTERNAL |
220 |
|
|
# @DESCRIPTION: |
221 |
|
|
# Parse .gitmodules contents passed as <file-contents> |
222 |
|
|
# as in "$(cat .gitmodules)"). Composes a 'submodules' array that |
223 |
|
|
# contains in order (name, URL, path) for each submodule. |
224 |
|
|
_git-r3_set_submodules() { |
225 |
|
|
debug-print-function ${FUNCNAME} "$@" |
226 |
|
|
|
227 |
|
|
local data=${1} |
228 |
|
|
|
229 |
|
|
# ( name url path ... ) |
230 |
|
|
submodules=() |
231 |
|
|
|
232 |
|
|
local l |
233 |
|
|
while read l; do |
234 |
|
|
# submodule.<path>.path=<path> |
235 |
|
|
# submodule.<path>.url=<url> |
236 |
|
|
[[ ${l} == submodule.*.url=* ]] || continue |
237 |
|
|
|
238 |
|
|
l=${l#submodule.} |
239 |
|
|
local subname=${l%%.url=*} |
240 |
|
|
|
241 |
mgorny |
1.15 |
# skip modules that have 'update = none', bug #487262. |
242 |
|
|
local upd=$(echo "${data}" | git config -f /dev/fd/0 \ |
243 |
mgorny |
1.18 |
submodule."${subname}".update) |
244 |
mgorny |
1.15 |
[[ ${upd} == none ]] && continue |
245 |
|
|
|
246 |
mgorny |
1.1 |
submodules+=( |
247 |
|
|
"${subname}" |
248 |
|
|
"$(echo "${data}" | git config -f /dev/fd/0 \ |
249 |
mgorny |
1.17 |
submodule."${subname}".url || die)" |
250 |
mgorny |
1.1 |
"$(echo "${data}" | git config -f /dev/fd/0 \ |
251 |
mgorny |
1.17 |
submodule."${subname}".path || die)" |
252 |
mgorny |
1.1 |
) |
253 |
mgorny |
1.17 |
done < <(echo "${data}" | git config -f /dev/fd/0 -l || die) |
254 |
mgorny |
1.1 |
} |
255 |
|
|
|
256 |
mgorny |
1.23 |
# @FUNCTION: _git-r3_is_local_repo |
257 |
|
|
# @USAGE: <repo-uri> |
258 |
|
|
# @INTERNAL |
259 |
|
|
# @DESCRIPTION: |
260 |
|
|
# Determine whether the given URI specifies a local (on-disk) |
261 |
|
|
# repository. |
262 |
|
|
_git-r3_is_local_repo() { |
263 |
|
|
debug-print-function ${FUNCNAME} "$@" |
264 |
|
|
|
265 |
|
|
local uri=${1} |
266 |
|
|
|
267 |
|
|
[[ ${uri} == file://* || ${uri} == /* ]] |
268 |
|
|
} |
269 |
|
|
|
270 |
mgorny |
1.1 |
# @FUNCTION: git-r3_fetch |
271 |
|
|
# @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]] |
272 |
|
|
# @DESCRIPTION: |
273 |
|
|
# Fetch new commits to the local clone of repository. |
274 |
|
|
# |
275 |
|
|
# <repo-uri> specifies the repository URIs to fetch from, as a space- |
276 |
|
|
# -separated list. The first URI will be used as repository group |
277 |
|
|
# identifier and therefore must be used consistently. When not |
278 |
|
|
# specified, defaults to ${EGIT_REPO_URI}. |
279 |
|
|
# |
280 |
|
|
# <remote-ref> specifies the remote ref or commit id to fetch. |
281 |
|
|
# It is preferred to use 'refs/heads/<branch-name>' for branches |
282 |
|
|
# and 'refs/tags/<tag-name>' for tags. Other options are 'HEAD' |
283 |
|
|
# for upstream default branch and hexadecimal commit SHA1. Defaults |
284 |
|
|
# to the first of EGIT_COMMIT, EGIT_BRANCH or literal 'HEAD' that |
285 |
|
|
# is set to a non-null value. |
286 |
|
|
# |
287 |
|
|
# <local-id> specifies the local branch identifier that will be used to |
288 |
|
|
# locally store the fetch result. It should be unique to multiple |
289 |
|
|
# fetches within the repository that can be performed at the same time |
290 |
mgorny |
1.20 |
# (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT%/*}. |
291 |
mgorny |
1.1 |
# This default should be fine unless you are fetching multiple trees |
292 |
|
|
# from the same repository in the same ebuild. |
293 |
|
|
# |
294 |
|
|
# The fetch operation will affect the EGIT_STORE only. It will not touch |
295 |
|
|
# the working copy, nor export any environment variables. |
296 |
|
|
# If the repository contains submodules, they will be fetched |
297 |
|
|
# recursively. |
298 |
|
|
git-r3_fetch() { |
299 |
|
|
debug-print-function ${FUNCNAME} "$@" |
300 |
|
|
|
301 |
mgorny |
1.16 |
[[ ${EVCS_OFFLINE} ]] && return |
302 |
|
|
|
303 |
mgorny |
1.11 |
local repos |
304 |
|
|
if [[ ${1} ]]; then |
305 |
|
|
repos=( ${1} ) |
306 |
|
|
elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then |
307 |
|
|
repos=( "${EGIT_REPO_URI[@]}" ) |
308 |
|
|
else |
309 |
|
|
repos=( ${EGIT_REPO_URI} ) |
310 |
mgorny |
1.9 |
fi |
311 |
|
|
|
312 |
mgorny |
1.1 |
local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}} |
313 |
|
|
local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}} |
314 |
mgorny |
1.20 |
local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}} |
315 |
mgorny |
1.24 |
local local_ref=refs/git-r3/${local_id}/__main__ |
316 |
mgorny |
1.1 |
|
317 |
|
|
[[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset" |
318 |
|
|
|
319 |
|
|
local -x GIT_DIR |
320 |
mgorny |
1.9 |
_git-r3_set_gitdir "${repos[0]}" |
321 |
mgorny |
1.1 |
|
322 |
|
|
# try to fetch from the remote |
323 |
|
|
local r success |
324 |
mgorny |
1.9 |
for r in "${repos[@]}"; do |
325 |
mgorny |
1.24 |
einfo "Fetching ${r} ..." |
326 |
mgorny |
1.1 |
|
327 |
mgorny |
1.24 |
local fetch_command=( |
328 |
|
|
git fetch --prune "${r}" |
329 |
|
|
# mirror the remote branches as local branches |
330 |
|
|
"refs/heads/*:refs/heads/*" |
331 |
|
|
# pull tags explicitly in order to prune them properly |
332 |
|
|
"refs/tags/*:refs/tags/*" |
333 |
mgorny |
1.25 |
# notes in case something needs them |
334 |
|
|
"refs/notes/*:refs/notes/*" |
335 |
mgorny |
1.1 |
) |
336 |
|
|
|
337 |
mgorny |
1.24 |
set -- "${fetch_command[@]}" |
338 |
|
|
echo "${@}" >&2 |
339 |
|
|
if "${@}"; then |
340 |
|
|
# now let's see what the user wants from us |
341 |
|
|
local full_remote_ref=$( |
342 |
|
|
git rev-parse --verify --symbolic-full-name "${remote_ref}" |
343 |
|
|
) |
344 |
|
|
|
345 |
|
|
if [[ ${full_remote_ref} ]]; then |
346 |
|
|
# when we are given a ref, create a symbolic ref |
347 |
|
|
# so that we preserve the actual argument |
348 |
|
|
set -- git symbolic-ref "${local_ref}" "${full_remote_ref}" |
349 |
mgorny |
1.3 |
else |
350 |
mgorny |
1.24 |
# otherwise, we were likely given a commit id |
351 |
|
|
set -- git update-ref --no-deref "${local_ref}" "${remote_ref}" |
352 |
mgorny |
1.2 |
fi |
353 |
|
|
|
354 |
mgorny |
1.24 |
echo "${@}" >&2 |
355 |
|
|
if ! "${@}"; then |
356 |
|
|
die "Referencing ${remote_ref} failed (wrong ref?)." |
357 |
mgorny |
1.1 |
fi |
358 |
|
|
|
359 |
|
|
success=1 |
360 |
|
|
break |
361 |
|
|
fi |
362 |
|
|
done |
363 |
|
|
[[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI" |
364 |
|
|
|
365 |
|
|
# recursively fetch submodules |
366 |
|
|
if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then |
367 |
|
|
local submodules |
368 |
|
|
_git-r3_set_submodules \ |
369 |
|
|
"$(git cat-file -p "${local_ref}":.gitmodules || die)" |
370 |
|
|
|
371 |
|
|
while [[ ${submodules[@]} ]]; do |
372 |
|
|
local subname=${submodules[0]} |
373 |
|
|
local url=${submodules[1]} |
374 |
|
|
local path=${submodules[2]} |
375 |
|
|
local commit=$(git rev-parse "${local_ref}:${path}") |
376 |
|
|
|
377 |
|
|
if [[ ! ${commit} ]]; then |
378 |
|
|
die "Unable to get commit id for submodule ${subname}" |
379 |
|
|
fi |
380 |
mgorny |
1.19 |
if [[ ${url} == ./* || ${url} == ../* ]]; then |
381 |
|
|
local subrepos=( "${repos[@]/%//${url}}" ) |
382 |
|
|
else |
383 |
|
|
local subrepos=( "${url}" ) |
384 |
|
|
fi |
385 |
mgorny |
1.1 |
|
386 |
mgorny |
1.19 |
git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}" |
387 |
mgorny |
1.1 |
|
388 |
|
|
submodules=( "${submodules[@]:3}" ) # shift |
389 |
|
|
done |
390 |
|
|
fi |
391 |
|
|
} |
392 |
|
|
|
393 |
|
|
# @FUNCTION: git-r3_checkout |
394 |
|
|
# @USAGE: [<repo-uri> [<checkout-path> [<local-id>]]] |
395 |
|
|
# @DESCRIPTION: |
396 |
|
|
# Check the previously fetched tree to the working copy. |
397 |
|
|
# |
398 |
|
|
# <repo-uri> specifies the repository URIs, as a space-separated list. |
399 |
|
|
# The first URI will be used as repository group identifier |
400 |
|
|
# and therefore must be used consistently with git-r3_fetch. |
401 |
|
|
# The remaining URIs are not used and therefore may be omitted. |
402 |
|
|
# When not specified, defaults to ${EGIT_REPO_URI}. |
403 |
|
|
# |
404 |
|
|
# <checkout-path> specifies the path to place the checkout. It defaults |
405 |
|
|
# to ${EGIT_CHECKOUT_DIR} if set, otherwise to ${WORKDIR}/${P}. |
406 |
|
|
# |
407 |
|
|
# <local-id> needs to specify the local identifier that was used |
408 |
|
|
# for respective git-r3_fetch. |
409 |
|
|
# |
410 |
|
|
# The checkout operation will write to the working copy, and export |
411 |
|
|
# the repository state into the environment. If the repository contains |
412 |
|
|
# submodules, they will be checked out recursively. |
413 |
|
|
git-r3_checkout() { |
414 |
|
|
debug-print-function ${FUNCNAME} "$@" |
415 |
|
|
|
416 |
mgorny |
1.11 |
local repos |
417 |
|
|
if [[ ${1} ]]; then |
418 |
|
|
repos=( ${1} ) |
419 |
|
|
elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then |
420 |
|
|
repos=( "${EGIT_REPO_URI[@]}" ) |
421 |
|
|
else |
422 |
|
|
repos=( ${EGIT_REPO_URI} ) |
423 |
mgorny |
1.9 |
fi |
424 |
|
|
|
425 |
mgorny |
1.1 |
local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}} |
426 |
mgorny |
1.20 |
local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}} |
427 |
mgorny |
1.1 |
|
428 |
mgorny |
1.24 |
local -x GIT_DIR |
429 |
mgorny |
1.9 |
_git-r3_set_gitdir "${repos[0]}" |
430 |
mgorny |
1.1 |
|
431 |
|
|
einfo "Checking out ${repos[0]} to ${out_dir} ..." |
432 |
|
|
|
433 |
mgorny |
1.24 |
if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then |
434 |
mgorny |
1.1 |
if [[ ${EVCS_OFFLINE} ]]; then |
435 |
|
|
die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE." |
436 |
|
|
else |
437 |
|
|
die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?" |
438 |
|
|
fi |
439 |
|
|
fi |
440 |
mgorny |
1.24 |
local remote_ref=$( |
441 |
|
|
git symbolic-ref --quiet refs/git-r3/"${local_id}"/__main__ |
442 |
|
|
) |
443 |
|
|
local new_commit_id=$( |
444 |
|
|
git rev-parse --verify refs/git-r3/"${local_id}"/__main__ |
445 |
|
|
) |
446 |
mgorny |
1.1 |
|
447 |
mgorny |
1.24 |
set -- git clone --quiet --shared --no-checkout "${GIT_DIR}" "${out_dir}"/ |
448 |
mgorny |
1.1 |
echo "${@}" >&2 |
449 |
mgorny |
1.24 |
"${@}" || die "git clone (for checkout) failed" |
450 |
mgorny |
1.22 |
|
451 |
mgorny |
1.24 |
git-r3_sub_checkout() { |
452 |
mgorny |
1.25 |
local orig_repo=${GIT_DIR} |
453 |
mgorny |
1.24 |
local -x GIT_DIR=${out_dir}/.git |
454 |
|
|
local -x GIT_WORK_TREE=${out_dir} |
455 |
|
|
|
456 |
mgorny |
1.25 |
# pull notes |
457 |
|
|
git fetch "${orig_repo}" "refs/notes/*:refs/notes/*" || die |
458 |
|
|
|
459 |
mgorny |
1.24 |
set -- git checkout --quiet |
460 |
|
|
if [[ ${remote_ref} ]]; then |
461 |
|
|
set -- "${@}" "${remote_ref#refs/heads/}" |
462 |
|
|
else |
463 |
|
|
set -- "${@}" "${new_commit_id}" |
464 |
|
|
fi |
465 |
|
|
echo "${@}" >&2 |
466 |
|
|
"${@}" || die "git checkout ${remote_ref:-${new_commit_id}} failed" |
467 |
|
|
} |
468 |
|
|
git-r3_sub_checkout |
469 |
mgorny |
1.22 |
|
470 |
mgorny |
1.1 |
local old_commit_id=$( |
471 |
mgorny |
1.24 |
git rev-parse --quiet --verify refs/git-r3/"${local_id}"/__old__ |
472 |
mgorny |
1.1 |
) |
473 |
|
|
if [[ ! ${old_commit_id} ]]; then |
474 |
|
|
echo "GIT NEW branch -->" |
475 |
|
|
echo " repository: ${repos[0]}" |
476 |
|
|
echo " at the commit: ${new_commit_id}" |
477 |
|
|
else |
478 |
mgorny |
1.24 |
# diff against previous revision |
479 |
mgorny |
1.1 |
echo "GIT update -->" |
480 |
|
|
echo " repository: ${repos[0]}" |
481 |
|
|
# write out message based on the revisions |
482 |
|
|
if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then |
483 |
|
|
echo " updating from commit: ${old_commit_id}" |
484 |
|
|
echo " to commit: ${new_commit_id}" |
485 |
|
|
|
486 |
|
|
git --no-pager diff --stat \ |
487 |
|
|
${old_commit_id}..${new_commit_id} |
488 |
|
|
else |
489 |
|
|
echo " at the commit: ${new_commit_id}" |
490 |
|
|
fi |
491 |
|
|
fi |
492 |
mgorny |
1.24 |
git update-ref --no-deref refs/git-r3/"${local_id}"/{__old__,__main__} || die |
493 |
mgorny |
1.1 |
|
494 |
|
|
# recursively checkout submodules |
495 |
mgorny |
1.24 |
if [[ -f ${out_dir}/.gitmodules ]]; then |
496 |
mgorny |
1.1 |
local submodules |
497 |
|
|
_git-r3_set_submodules \ |
498 |
mgorny |
1.24 |
"$(<"${out_dir}"/.gitmodules)" |
499 |
mgorny |
1.1 |
|
500 |
|
|
while [[ ${submodules[@]} ]]; do |
501 |
|
|
local subname=${submodules[0]} |
502 |
|
|
local url=${submodules[1]} |
503 |
|
|
local path=${submodules[2]} |
504 |
|
|
|
505 |
mgorny |
1.19 |
if [[ ${url} == ./* || ${url} == ../* ]]; then |
506 |
|
|
url=${repos[0]%%/}/${url} |
507 |
|
|
fi |
508 |
|
|
|
509 |
mgorny |
1.24 |
git-r3_checkout "${url}" "${out_dir}/${path}" \ |
510 |
mgorny |
1.1 |
"${local_id}/${subname}" |
511 |
|
|
|
512 |
|
|
submodules=( "${submodules[@]:3}" ) # shift |
513 |
|
|
done |
514 |
|
|
fi |
515 |
|
|
|
516 |
|
|
# keep this *after* submodules |
517 |
|
|
export EGIT_DIR=${GIT_DIR} |
518 |
|
|
export EGIT_VERSION=${new_commit_id} |
519 |
|
|
} |
520 |
|
|
|
521 |
|
|
# @FUNCTION: git-r3_peek_remote_ref |
522 |
|
|
# @USAGE: [<repo-uri> [<remote-ref>]] |
523 |
|
|
# @DESCRIPTION: |
524 |
|
|
# Peek the reference in the remote repository and print the matching |
525 |
|
|
# (newest) commit SHA1. |
526 |
|
|
# |
527 |
|
|
# <repo-uri> specifies the repository URIs to fetch from, as a space- |
528 |
|
|
# -separated list. When not specified, defaults to ${EGIT_REPO_URI}. |
529 |
|
|
# |
530 |
|
|
# <remote-ref> specifies the remote ref to peek. It is preferred to use |
531 |
|
|
# 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>' |
532 |
|
|
# for tags. Alternatively, 'HEAD' may be used for upstream default |
533 |
|
|
# branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal |
534 |
|
|
# 'HEAD' that is set to a non-null value. |
535 |
|
|
# |
536 |
|
|
# The operation will be done purely on the remote, without using local |
537 |
|
|
# storage. If commit SHA1 is provided as <remote-ref>, the function will |
538 |
|
|
# fail due to limitations of git protocol. |
539 |
|
|
# |
540 |
|
|
# On success, the function returns 0 and writes hexadecimal commit SHA1 |
541 |
|
|
# to stdout. On failure, the function returns 1. |
542 |
|
|
git-r3_peek_remote_ref() { |
543 |
|
|
debug-print-function ${FUNCNAME} "$@" |
544 |
|
|
|
545 |
mgorny |
1.11 |
local repos |
546 |
|
|
if [[ ${1} ]]; then |
547 |
|
|
repos=( ${1} ) |
548 |
|
|
elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then |
549 |
|
|
repos=( "${EGIT_REPO_URI[@]}" ) |
550 |
|
|
else |
551 |
|
|
repos=( ${EGIT_REPO_URI} ) |
552 |
mgorny |
1.9 |
fi |
553 |
|
|
|
554 |
mgorny |
1.1 |
local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}} |
555 |
|
|
local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}} |
556 |
|
|
|
557 |
|
|
[[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset" |
558 |
|
|
|
559 |
|
|
local r success |
560 |
mgorny |
1.9 |
for r in "${repos[@]}"; do |
561 |
mgorny |
1.1 |
einfo "Peeking ${remote_ref} on ${r} ..." >&2 |
562 |
|
|
|
563 |
|
|
local is_branch lookup_ref |
564 |
|
|
if [[ ${remote_ref} == refs/heads/* || ${remote_ref} == HEAD ]] |
565 |
|
|
then |
566 |
|
|
is_branch=1 |
567 |
|
|
lookup_ref=${remote_ref} |
568 |
|
|
else |
569 |
|
|
# ls-remote by commit is going to fail anyway, |
570 |
|
|
# so we may as well pass refs/tags/ABCDEF... |
571 |
|
|
lookup_ref=refs/tags/${remote_ref} |
572 |
|
|
fi |
573 |
|
|
|
574 |
|
|
# split on whitespace |
575 |
|
|
local ref=( |
576 |
|
|
$(git ls-remote "${r}" "${lookup_ref}") |
577 |
|
|
) |
578 |
|
|
|
579 |
|
|
if [[ ${ref[0]} ]]; then |
580 |
|
|
echo "${ref[0]}" |
581 |
|
|
return 0 |
582 |
|
|
fi |
583 |
|
|
done |
584 |
|
|
|
585 |
|
|
return 1 |
586 |
|
|
} |
587 |
|
|
|
588 |
|
|
git-r3_src_fetch() { |
589 |
|
|
debug-print-function ${FUNCNAME} "$@" |
590 |
|
|
|
591 |
|
|
if [[ ! ${EGIT3_STORE_DIR} && ${EGIT_STORE_DIR} ]]; then |
592 |
|
|
ewarn "You have set EGIT_STORE_DIR but not EGIT3_STORE_DIR. Please consider" |
593 |
|
|
ewarn "setting EGIT3_STORE_DIR for git-r3.eclass. It is recommended to use" |
594 |
|
|
ewarn "a different directory than EGIT_STORE_DIR to ease removing old clones" |
595 |
|
|
ewarn "when git-2 eclass becomes deprecated." |
596 |
|
|
fi |
597 |
|
|
|
598 |
|
|
_git-r3_env_setup |
599 |
|
|
git-r3_fetch |
600 |
|
|
} |
601 |
|
|
|
602 |
|
|
git-r3_src_unpack() { |
603 |
|
|
debug-print-function ${FUNCNAME} "$@" |
604 |
|
|
|
605 |
|
|
_git-r3_env_setup |
606 |
|
|
git-r3_src_fetch |
607 |
|
|
git-r3_checkout |
608 |
|
|
} |
609 |
|
|
|
610 |
|
|
# https://bugs.gentoo.org/show_bug.cgi?id=482666 |
611 |
|
|
git-r3_pkg_outofdate() { |
612 |
|
|
debug-print-function ${FUNCNAME} "$@" |
613 |
|
|
|
614 |
|
|
local new_commit_id=$(git-r3_peek_remote_ref) |
615 |
|
|
ewarn "old: ${EGIT_VERSION}" |
616 |
|
|
ewarn "new: ${new_commit_id}" |
617 |
|
|
[[ ${new_commit_id} && ${old_commit_id} ]] || return 2 |
618 |
|
|
|
619 |
|
|
[[ ${EGIT_VERSION} != ${new_commit_id} ]] |
620 |
|
|
} |
621 |
|
|
|
622 |
|
|
_GIT_R3=1 |
623 |
|
|
fi |