diff options
author | psyc://loupsycedyglgamf.onion/~lynX <ircs://psyced.org/youbroketheinternet> | 1984-04-04 00:44:06 +0000 |
---|---|---|
committer | psyc://loupsycedyglgamf.onion/~lynX <ircs://psyced.org/youbroketheinternet> | 1984-04-04 00:44:06 +0000 |
commit | 0e47c51575652753615dc508fcd81dc710c6af33 (patch) | |
tree | c726ac95d8d42b0bf687b71bee8d97c85423e9e8 | |
parent | 94619cb1af3a14030c90da9324258a31d40263cd (diff) | |
download | youbroketheinternet-overlay-0e47c51575652753615dc508fcd81dc710c6af33.tar.gz youbroketheinternet-overlay-0e47c51575652753615dc508fcd81dc710c6af33.zip |
recreated Tor patch for git-r3.eclass and applied
-rw-r--r-- | eclass/git-r3.eclass | 35 | ||||
-rw-r--r-- | eclass/git-r3.tor.eclass | 1016 | ||||
-rw-r--r-- | git-r3.eclass.patch | 99 |
3 files changed, 128 insertions, 1022 deletions
diff --git a/eclass/git-r3.eclass b/eclass/git-r3.eclass index a1ad0d2..5e4f57e 100644 --- a/eclass/git-r3.eclass +++ b/eclass/git-r3.eclass | |||
@@ -9,6 +9,15 @@ | |||
9 | # @DESCRIPTION: | 9 | # @DESCRIPTION: |
10 | # Third generation eclass for easing maintenance of live ebuilds using | 10 | # Third generation eclass for easing maintenance of live ebuilds using |
11 | # git as remote repository. | 11 | # git as remote repository. |
12 | # | ||
13 | # Patched by symlynX to allow for gits via Tor. Why Tor? Because | ||
14 | # unlike HTTPS it provides end-to-end authenticity which is not | ||
15 | # susceptible to man-in-the-middle attacks, so all gits should | ||
16 | # migrate to Tor, cjdns or gnunet-vpn. But the latter two do | ||
17 | # not need custom changes to this file to do their job. | ||
18 | # | ||
19 | # @FIXME: Should we automatically define EGIT_SOCKS="torsocks" | ||
20 | # when we see that /etc/tor/torsocks.conf exists? | ||
12 | 21 | ||
13 | case "${EAPI:-0}" in | 22 | case "${EAPI:-0}" in |
14 | 0|1|2|3) | 23 | 0|1|2|3) |
@@ -655,7 +664,18 @@ git-r3_fetch() { | |||
655 | if [[ ! ${EVCS_OFFLINE} ]]; then | 664 | if [[ ! ${EVCS_OFFLINE} ]]; then |
656 | einfo "Fetching \e[1m${r}\e[22m ..." | 665 | einfo "Fetching \e[1m${r}\e[22m ..." |
657 | 666 | ||
658 | local fetch_command=( git fetch "${r}" ) | 667 | if [[ ${r} == https?://* ]]; then |
668 | # if we're not using git protocol, web proxy takes care of things | ||
669 | EGIT_SOCKS = "" | ||
670 | elif [[ ! ${EGIT_SOCKS} ]] && [[ ${r} == git://*.onion/* ]]; then | ||
671 | if ROOT=/ has_version 'net-proxy/torsocks'; then | ||
672 | EGIT_SOCKS="torsocks" | ||
673 | else | ||
674 | die "Properly configured net-proxy/torsocks required to fetch git from onion." | ||
675 | fi | ||
676 | fi | ||
677 | |||
678 | local fetch_command=( ${EGIT_SOCKS} git fetch "${r}" ) | ||
659 | local clone_type=${EGIT_CLONE_TYPE} | 679 | local clone_type=${EGIT_CLONE_TYPE} |
660 | 680 | ||
661 | if [[ ${clone_type} == mirror ]]; then | 681 | if [[ ${clone_type} == mirror ]]; then |
@@ -683,7 +703,7 @@ git-r3_fetch() { | |||
683 | else | 703 | else |
684 | # tag or commit id... | 704 | # tag or commit id... |
685 | # let ls-remote figure it out | 705 | # let ls-remote figure it out |
686 | local tagref=$(git ls-remote "${r}" "refs/tags/${remote_ref}") | 706 | local tagref=$(${EGIT_SOCKS} git ls-remote "${r}" "refs/tags/${remote_ref}") |
687 | 707 | ||
688 | # if it was a tag, ls-remote obtained a hash | 708 | # if it was a tag, ls-remote obtained a hash |
689 | if [[ ${tagref} ]]; then | 709 | if [[ ${tagref} ]]; then |
@@ -770,7 +790,7 @@ git-r3_fetch() { | |||
770 | fi | 790 | fi |
771 | else | 791 | else |
772 | local full_remote_ref=$( | 792 | local full_remote_ref=$( |
773 | git rev-parse --verify --symbolic-full-name "${remote_ref}" | 793 | ${EGIT_SOCKS} git rev-parse --verify --symbolic-full-name "${remote_ref}" |
774 | ) | 794 | ) |
775 | 795 | ||
776 | if [[ ${full_remote_ref} ]]; then | 796 | if [[ ${full_remote_ref} ]]; then |
@@ -805,6 +825,9 @@ git-r3_fetch() { | |||
805 | fi | 825 | fi |
806 | [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI" | 826 | [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI" |
807 | 827 | ||
828 | # consistency check, in case we got man-in-the-middle't --lynX | ||
829 | git fsck | ||
830 | |||
808 | # submodules can reference commits in any branch | 831 | # submodules can reference commits in any branch |
809 | # always use the 'mirror' mode to accomodate that, bug #503332 | 832 | # always use the 'mirror' mode to accomodate that, bug #503332 |
810 | local EGIT_CLONE_TYPE=mirror | 833 | local EGIT_CLONE_TYPE=mirror |
@@ -813,7 +836,7 @@ git-r3_fetch() { | |||
813 | if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then | 836 | if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then |
814 | local submodules | 837 | local submodules |
815 | _git-r3_set_submodules \ | 838 | _git-r3_set_submodules \ |
816 | "$(git cat-file -p "${local_ref}":.gitmodules || die)" | 839 | "$(${EGIT_SOCKS} git cat-file -p "${local_ref}":.gitmodules || die)" |
817 | 840 | ||
818 | while [[ ${submodules[@]} ]]; do | 841 | while [[ ${submodules[@]} ]]; do |
819 | local subname=${submodules[0]} | 842 | local subname=${submodules[0]} |
@@ -825,7 +848,7 @@ git-r3_fetch() { | |||
825 | # note: git cat-file does not work for submodules | 848 | # note: git cat-file does not work for submodules |
826 | if [[ $(git ls-tree -d "${local_ref}" "${path}") ]] | 849 | if [[ $(git ls-tree -d "${local_ref}" "${path}") ]] |
827 | then | 850 | then |
828 | local commit=$(git rev-parse "${local_ref}:${path}" || die) | 851 | local commit=$(${EGIT_SOCKS} git rev-parse "${local_ref}:${path}" || die) |
829 | 852 | ||
830 | if [[ ! ${commit} ]]; then | 853 | if [[ ! ${commit} ]]; then |
831 | die "Unable to get commit id for submodule ${subname}" | 854 | die "Unable to get commit id for submodule ${subname}" |
@@ -1051,7 +1074,7 @@ git-r3_peek_remote_ref() { | |||
1051 | 1074 | ||
1052 | # split on whitespace | 1075 | # split on whitespace |
1053 | local ref=( | 1076 | local ref=( |
1054 | $(git ls-remote "${r}" "${lookup_ref}") | 1077 | $(${EGIT_SOCKS} git ls-remote "${r}" "${lookup_ref}") |
1055 | ) | 1078 | ) |
1056 | 1079 | ||
1057 | if [[ ${ref[0]} ]]; then | 1080 | if [[ ${ref[0]} ]]; then |
diff --git a/eclass/git-r3.tor.eclass b/eclass/git-r3.tor.eclass deleted file mode 100644 index e3e6717..0000000 --- a/eclass/git-r3.tor.eclass +++ /dev/null | |||
@@ -1,1016 +0,0 @@ | |||
1 | # Copyright 1999-2015 Gentoo Authors | ||
2 | # Distributed under the terms of the GNU General Public License v2 | ||
3 | # $Id$ | ||
4 | |||
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 maintenance of live ebuilds using | ||
11 | # git as remote repository. | ||
12 | # | ||
13 | # Patched by symlynX to allow for gits via Tor. Why Tor? Because | ||
14 | # unlike HTTPS it provides end-to-end authenticity which is not | ||
15 | # susceptible to man-in-the-middle attacks, so all gits should | ||
16 | # migrate to Tor, cjdns or gnunet-vpn. But the latter two do | ||
17 | # not need custom changes to this file to do their job. | ||
18 | # | ||
19 | # @FIXME: Should we automatically define EGIT_SOCKS="torsocks" | ||
20 | # when we see that /etc/tor/torsocks.conf exists? | ||
21 | |||
22 | case "${EAPI:-0}" in | ||
23 | 0|1|2|3|4|5|6) | ||
24 | ;; | ||
25 | *) | ||
26 | die "Unsupported EAPI=${EAPI} (unknown) for ${ECLASS}" | ||
27 | ;; | ||
28 | esac | ||
29 | |||
30 | if [[ ! ${_GIT_R3} ]]; then | ||
31 | |||
32 | inherit eutils | ||
33 | |||
34 | fi | ||
35 | |||
36 | EXPORT_FUNCTIONS src_unpack | ||
37 | |||
38 | if [[ ! ${_GIT_R3} ]]; then | ||
39 | |||
40 | if [[ ! ${_INHERITED_BY_GIT_2} ]]; then | ||
41 | DEPEND=">=dev-vcs/git-1.8.2.1" | ||
42 | fi | ||
43 | |||
44 | # @ECLASS-VARIABLE: EGIT_CLONE_TYPE | ||
45 | # @DESCRIPTION: | ||
46 | # Type of clone that should be used against the remote repository. | ||
47 | # This can be either of: 'mirror', 'single', 'shallow'. | ||
48 | # | ||
49 | # This is intended to be set by user in make.conf. Ebuilds are supposed | ||
50 | # to set EGIT_MIN_CLONE_TYPE if necessary instead. | ||
51 | # | ||
52 | # The 'mirror' type clones all remote branches and tags with complete | ||
53 | # history and all notes. EGIT_COMMIT can specify any commit hash. | ||
54 | # Upstream-removed branches and tags are purged from the local clone | ||
55 | # while fetching. This mode is suitable for cloning the local copy | ||
56 | # for development or hosting a local git mirror. However, clones | ||
57 | # of repositories with large diverged branches may quickly grow large. | ||
58 | # | ||
59 | # The 'single+tags' type clones the requested branch and all tags | ||
60 | # in the repository. All notes are fetched as well. EGIT_COMMIT | ||
61 | # can safely specify hashes throughout the current branch and all tags. | ||
62 | # No purging of old references is done (if you often switch branches, | ||
63 | # you may need to remove stale branches yourself). This mode is intended | ||
64 | # mostly for use with broken git servers such as Google Code that fail | ||
65 | # to fetch tags along with the branch in 'single' mode. | ||
66 | # | ||
67 | # The 'single' type clones only the requested branch or tag. Tags | ||
68 | # referencing commits throughout the branch history are fetched as well, | ||
69 | # and all notes. EGIT_COMMIT can safely specify only hashes | ||
70 | # in the current branch. No purging of old references is done (if you | ||
71 | # often switch branches, you may need to remove stale branches | ||
72 | # yourself). This mode is suitable for general use. | ||
73 | # | ||
74 | # The 'shallow' type clones only the newest commit on requested branch | ||
75 | # or tag. EGIT_COMMIT can only specify tags, and since the history is | ||
76 | # unavailable calls like 'git describe' will not reference prior tags. | ||
77 | # No purging of old references is done. This mode is intended mostly for | ||
78 | # embedded systems with limited disk space. | ||
79 | : ${EGIT_CLONE_TYPE:=single} | ||
80 | |||
81 | # @ECLASS-VARIABLE: EGIT_MIN_CLONE_TYPE | ||
82 | # @DESCRIPTION: | ||
83 | # 'Minimum' clone type supported by the ebuild. Takes same values | ||
84 | # as EGIT_CLONE_TYPE. When user sets a type that's 'lower' (that is, | ||
85 | # later on the list) than EGIT_MIN_CLONE_TYPE, the eclass uses | ||
86 | # EGIT_MIN_CLONE_TYPE instead. | ||
87 | # | ||
88 | # This variable is intended to be used by ebuilds only. Users are | ||
89 | # supposed to set EGIT_CLONE_TYPE instead. | ||
90 | # | ||
91 | # A common case is to use 'single' whenever the build system requires | ||
92 | # access to full branch history, or 'single+tags' when Google Code | ||
93 | # or a similar remote is used that does not support shallow clones | ||
94 | # and fetching tags along with commits. Please use sparingly, and to fix | ||
95 | # fatal errors rather than 'non-pretty versions'. | ||
96 | : ${EGIT_MIN_CLONE_TYPE:=shallow} | ||
97 | |||
98 | # @ECLASS-VARIABLE: EGIT3_STORE_DIR | ||
99 | # @DESCRIPTION: | ||
100 | # Storage directory for git sources. | ||
101 | # | ||
102 | # This is intended to be set by user in make.conf. Ebuilds must not set | ||
103 | # it. | ||
104 | # | ||
105 | # EGIT3_STORE_DIR=${DISTDIR}/git3-src | ||
106 | |||
107 | # @ECLASS-VARIABLE: EGIT_MIRROR_URI | ||
108 | # @DEFAULT_UNSET | ||
109 | # @DESCRIPTION: | ||
110 | # 'Top' URI to a local git mirror. If specified, the eclass will try | ||
111 | # to fetch from the local mirror instead of using the remote repository. | ||
112 | # | ||
113 | # The mirror needs to follow EGIT3_STORE_DIR structure. The directory | ||
114 | # created by eclass can be used for that purpose. | ||
115 | # | ||
116 | # Example: | ||
117 | # @CODE | ||
118 | # EGIT_MIRROR_URI="git://mirror.lan/" | ||
119 | # @CODE | ||
120 | |||
121 | # @ECLASS-VARIABLE: EGIT_REPO_URI | ||
122 | # @REQUIRED | ||
123 | # @DESCRIPTION: | ||
124 | # URIs to the repository, e.g. git://foo, https://foo. If multiple URIs | ||
125 | # are provided, the eclass will consider them as fallback URIs to try | ||
126 | # if the first URI does not work. For supported URI syntaxes, read up | ||
127 | # the manpage for git-clone(1). | ||
128 | # | ||
129 | # It can be overriden via env using ${PN}_LIVE_REPO variable. | ||
130 | # | ||
131 | # Can be a whitespace-separated list or an array. | ||
132 | # | ||
133 | # Example: | ||
134 | # @CODE | ||
135 | # EGIT_REPO_URI="git://a/b.git https://c/d.git" | ||
136 | # @CODE | ||
137 | |||
138 | # @ECLASS-VARIABLE: EVCS_OFFLINE | ||
139 | # @DEFAULT_UNSET | ||
140 | # @DESCRIPTION: | ||
141 | # If non-empty, this variable prevents any online operations. | ||
142 | |||
143 | # @ECLASS-VARIABLE: EVCS_UMASK | ||
144 | # @DEFAULT_UNSET | ||
145 | # @DESCRIPTION: | ||
146 | # Set this variable to a custom umask. This is intended to be set by | ||
147 | # users. By setting this to something like 002, it can make life easier | ||
148 | # for people who do development as non-root (but are in the portage | ||
149 | # group), and then switch over to building with FEATURES=userpriv. | ||
150 | # Or vice-versa. Shouldn't be a security issue here as anyone who has | ||
151 | # portage group write access already can screw the system over in more | ||
152 | # creative ways. | ||
153 | |||
154 | # @ECLASS-VARIABLE: EGIT_BRANCH | ||
155 | # @DEFAULT_UNSET | ||
156 | # @DESCRIPTION: | ||
157 | # The branch name to check out. If unset, the upstream default (HEAD) | ||
158 | # will be used. | ||
159 | # | ||
160 | # It can be overriden via env using ${PN}_LIVE_BRANCH variable. | ||
161 | |||
162 | # @ECLASS-VARIABLE: EGIT_COMMIT | ||
163 | # @DEFAULT_UNSET | ||
164 | # @DESCRIPTION: | ||
165 | # The tag name or commit identifier to check out. If unset, newest | ||
166 | # commit from the branch will be used. If set, EGIT_BRANCH will | ||
167 | # be ignored. | ||
168 | # | ||
169 | # It can be overriden via env using ${PN}_LIVE_COMMIT variable. | ||
170 | |||
171 | # @ECLASS-VARIABLE: EGIT_CHECKOUT_DIR | ||
172 | # @DESCRIPTION: | ||
173 | # The directory to check the git sources out to. | ||
174 | # | ||
175 | # EGIT_CHECKOUT_DIR=${WORKDIR}/${P} | ||
176 | |||
177 | # @FUNCTION: _git-r3_env_setup | ||
178 | # @INTERNAL | ||
179 | # @DESCRIPTION: | ||
180 | # Set the eclass variables as necessary for operation. This can involve | ||
181 | # setting EGIT_* to defaults or ${PN}_LIVE_* variables. | ||
182 | _git-r3_env_setup() { | ||
183 | debug-print-function ${FUNCNAME} "$@" | ||
184 | |||
185 | # check the clone type | ||
186 | case "${EGIT_CLONE_TYPE}" in | ||
187 | mirror|single+tags|single|shallow) | ||
188 | ;; | ||
189 | *) | ||
190 | die "Invalid EGIT_CLONE_TYPE=${EGIT_CLONE_TYPE}" | ||
191 | esac | ||
192 | case "${EGIT_MIN_CLONE_TYPE}" in | ||
193 | shallow) | ||
194 | ;; | ||
195 | single) | ||
196 | if [[ ${EGIT_CLONE_TYPE} == shallow ]]; then | ||
197 | einfo "git-r3: ebuild needs to be cloned in '\e[1msingle\e[22m' mode, adjusting" | ||
198 | EGIT_CLONE_TYPE=single | ||
199 | fi | ||
200 | ;; | ||
201 | single+tags) | ||
202 | if [[ ${EGIT_CLONE_TYPE} == shallow || ${EGIT_CLONE_TYPE} == single ]]; then | ||
203 | einfo "git-r3: ebuild needs to be cloned in '\e[1msingle+tags\e[22m' mode, adjusting" | ||
204 | EGIT_CLONE_TYPE=single+tags | ||
205 | fi | ||
206 | ;; | ||
207 | mirror) | ||
208 | if [[ ${EGIT_CLONE_TYPE} != mirror ]]; then | ||
209 | einfo "git-r3: ebuild needs to be cloned in '\e[1mmirror\e[22m' mode, adjusting" | ||
210 | EGIT_CLONE_TYPE=mirror | ||
211 | fi | ||
212 | ;; | ||
213 | *) | ||
214 | die "Invalid EGIT_MIN_CLONE_TYPE=${EGIT_MIN_CLONE_TYPE}" | ||
215 | esac | ||
216 | |||
217 | local esc_pn livevar | ||
218 | esc_pn=${PN//[-+]/_} | ||
219 | |||
220 | livevar=${esc_pn}_LIVE_REPO | ||
221 | EGIT_REPO_URI=${!livevar:-${EGIT_REPO_URI}} | ||
222 | [[ ${!livevar} ]] \ | ||
223 | && ewarn "Using ${livevar}, no support will be provided" | ||
224 | |||
225 | livevar=${esc_pn}_LIVE_BRANCH | ||
226 | EGIT_BRANCH=${!livevar:-${EGIT_BRANCH}} | ||
227 | [[ ${!livevar} ]] \ | ||
228 | && ewarn "Using ${livevar}, no support will be provided" | ||
229 | |||
230 | livevar=${esc_pn}_LIVE_COMMIT | ||
231 | EGIT_COMMIT=${!livevar:-${EGIT_COMMIT}} | ||
232 | [[ ${!livevar} ]] \ | ||
233 | && ewarn "Using ${livevar}, no support will be provided" | ||
234 | |||
235 | # Migration helpers. Remove them when git-2 is removed. | ||
236 | |||
237 | if [[ ${EGIT_SOURCEDIR} ]]; then | ||
238 | eerror "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR. While updating" | ||
239 | eerror "your ebuild, please check whether the variable is necessary at all" | ||
240 | eerror "since the default has been changed from \${S} to \${WORKDIR}/\${P}." | ||
241 | eerror "Therefore, proper setting of S may be sufficient." | ||
242 | die "EGIT_SOURCEDIR has been replaced by EGIT_CHECKOUT_DIR." | ||
243 | fi | ||
244 | |||
245 | if [[ ${EGIT_MASTER} ]]; then | ||
246 | eerror "EGIT_MASTER has been removed. Instead, the upstream default (HEAD)" | ||
247 | eerror "is used by the eclass. Please remove the assignment or use EGIT_BRANCH" | ||
248 | eerror "as necessary." | ||
249 | die "EGIT_MASTER has been removed." | ||
250 | fi | ||
251 | |||
252 | if [[ ${EGIT_HAS_SUBMODULES} ]]; then | ||
253 | eerror "EGIT_HAS_SUBMODULES has been removed. The eclass no longer needs" | ||
254 | eerror "to switch the clone type in order to support submodules and therefore" | ||
255 | eerror "submodules are detected and fetched automatically." | ||
256 | die "EGIT_HAS_SUBMODULES is no longer necessary." | ||
257 | fi | ||
258 | |||
259 | if [[ ${EGIT_PROJECT} ]]; then | ||
260 | eerror "EGIT_PROJECT has been removed. Instead, the eclass determines" | ||
261 | eerror "the local clone path using path in canonical EGIT_REPO_URI." | ||
262 | eerror "If the current algorithm causes issues for you, please report a bug." | ||
263 | die "EGIT_PROJECT is no longer necessary." | ||
264 | fi | ||
265 | |||
266 | if [[ ${EGIT_BOOTSTRAP} ]]; then | ||
267 | eerror "EGIT_BOOTSTRAP has been removed. Please create proper src_prepare()" | ||
268 | eerror "instead." | ||
269 | die "EGIT_BOOTSTRAP has been removed." | ||
270 | fi | ||
271 | |||
272 | if [[ ${EGIT_NOUNPACK} ]]; then | ||
273 | eerror "EGIT_NOUNPACK has been removed. The eclass no longer calls default" | ||
274 | eerror "unpack function. If necessary, please declare proper src_unpack()." | ||
275 | die "EGIT_NOUNPACK has been removed." | ||
276 | fi | ||
277 | } | ||
278 | |||
279 | # @FUNCTION: _git-r3_set_gitdir | ||
280 | # @USAGE: <repo-uri> | ||
281 | # @INTERNAL | ||
282 | # @DESCRIPTION: | ||
283 | # Obtain the local repository path and set it as GIT_DIR. Creates | ||
284 | # a new repository if necessary. | ||
285 | # | ||
286 | # <repo-uri> may be used to compose the path. It should therefore be | ||
287 | # a canonical URI to the repository. | ||
288 | _git-r3_set_gitdir() { | ||
289 | debug-print-function ${FUNCNAME} "$@" | ||
290 | |||
291 | local repo_name=${1#*://*/} | ||
292 | |||
293 | # strip the trailing slash | ||
294 | repo_name=${repo_name%/} | ||
295 | |||
296 | # strip common prefixes to make paths more likely to match | ||
297 | # e.g. git://X/Y.git vs https://X/git/Y.git | ||
298 | # (but just one of the prefixes) | ||
299 | case "${repo_name}" in | ||
300 | # gnome.org... who else? | ||
301 | browse/*) repo_name=${repo_name#browse/};; | ||
302 | # cgit can proxy requests to git | ||
303 | cgit/*) repo_name=${repo_name#cgit/};; | ||
304 | # pretty common | ||
305 | git/*) repo_name=${repo_name#git/};; | ||
306 | # gentoo.org | ||
307 | gitroot/*) repo_name=${repo_name#gitroot/};; | ||
308 | # google code, sourceforge | ||
309 | p/*) repo_name=${repo_name#p/};; | ||
310 | # kernel.org | ||
311 | pub/scm/*) repo_name=${repo_name#pub/scm/};; | ||
312 | esac | ||
313 | # ensure a .git suffix, same reason | ||
314 | repo_name=${repo_name%.git}.git | ||
315 | # now replace all the slashes | ||
316 | repo_name=${repo_name//\//_} | ||
317 | |||
318 | local distdir=${PORTAGE_ACTUAL_DISTDIR:-${DISTDIR}} | ||
319 | : ${EGIT3_STORE_DIR:=${distdir}/git3-src} | ||
320 | |||
321 | GIT_DIR=${EGIT3_STORE_DIR}/${repo_name} | ||
322 | |||
323 | if [[ ! -d ${EGIT3_STORE_DIR} ]]; then | ||
324 | ( | ||
325 | addwrite / | ||
326 | mkdir -p "${EGIT3_STORE_DIR}" | ||
327 | ) || die "Unable to create ${EGIT3_STORE_DIR}" | ||
328 | fi | ||
329 | |||
330 | addwrite "${EGIT3_STORE_DIR}" | ||
331 | if [[ ! -d ${GIT_DIR} ]]; then | ||
332 | local saved_umask | ||
333 | if [[ ${EVCS_UMASK} ]]; then | ||
334 | saved_umask=$(umask) | ||
335 | umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}" | ||
336 | fi | ||
337 | mkdir "${GIT_DIR}" || die | ||
338 | git init --bare || die | ||
339 | if [[ ${saved_umask} ]]; then | ||
340 | umask "${saved_umask}" || die | ||
341 | fi | ||
342 | fi | ||
343 | } | ||
344 | |||
345 | # @FUNCTION: _git-r3_set_submodules | ||
346 | # @USAGE: <file-contents> | ||
347 | # @INTERNAL | ||
348 | # @DESCRIPTION: | ||
349 | # Parse .gitmodules contents passed as <file-contents> | ||
350 | # as in "$(cat .gitmodules)"). Composes a 'submodules' array that | ||
351 | # contains in order (name, URL, path) for each submodule. | ||
352 | _git-r3_set_submodules() { | ||
353 | debug-print-function ${FUNCNAME} "$@" | ||
354 | |||
355 | local data=${1} | ||
356 | |||
357 | # ( name url path ... ) | ||
358 | submodules=() | ||
359 | |||
360 | local l | ||
361 | while read l; do | ||
362 | # submodule.<path>.path=<path> | ||
363 | # submodule.<path>.url=<url> | ||
364 | [[ ${l} == submodule.*.url=* ]] || continue | ||
365 | |||
366 | l=${l#submodule.} | ||
367 | local subname=${l%%.url=*} | ||
368 | |||
369 | # skip modules that have 'update = none', bug #487262. | ||
370 | local upd=$(echo "${data}" | git config -f /dev/fd/0 \ | ||
371 | submodule."${subname}".update) | ||
372 | [[ ${upd} == none ]] && continue | ||
373 | |||
374 | # https://github.com/git/git/blob/master/refs.c#L39 | ||
375 | # for now, we just filter /. because of #572312 | ||
376 | local enc_subname=${subname//\/.//_} | ||
377 | [[ ${enc_subname} == .* ]] && enc_subname=_${enc_subname#.} | ||
378 | |||
379 | submodules+=( | ||
380 | "${enc_subname}" | ||
381 | "$(echo "${data}" | git config -f /dev/fd/0 \ | ||
382 | submodule."${subname}".url || die)" | ||
383 | "$(echo "${data}" | git config -f /dev/fd/0 \ | ||
384 | submodule."${subname}".path || die)" | ||
385 | ) | ||
386 | done < <(echo "${data}" | git config -f /dev/fd/0 -l || die) | ||
387 | } | ||
388 | |||
389 | # @FUNCTION: _git-r3_set_subrepos | ||
390 | # @USAGE: <submodule-uri> <parent-repo-uri>... | ||
391 | # @INTERNAL | ||
392 | # @DESCRIPTION: | ||
393 | # Create 'subrepos' array containing absolute (canonical) submodule URIs | ||
394 | # for the given <submodule-uri>. If the URI is relative, URIs will be | ||
395 | # constructed using all <parent-repo-uri>s. Otherwise, this single URI | ||
396 | # will be placed in the array. | ||
397 | _git-r3_set_subrepos() { | ||
398 | debug-print-function ${FUNCNAME} "$@" | ||
399 | |||
400 | local suburl=${1} | ||
401 | subrepos=( "${@:2}" ) | ||
402 | |||
403 | if [[ ${suburl} == ./* || ${suburl} == ../* ]]; then | ||
404 | # drop all possible trailing slashes for consistency | ||
405 | subrepos=( "${subrepos[@]%%/}" ) | ||
406 | |||
407 | while true; do | ||
408 | if [[ ${suburl} == ./* ]]; then | ||
409 | suburl=${suburl:2} | ||
410 | elif [[ ${suburl} == ../* ]]; then | ||
411 | suburl=${suburl:3} | ||
412 | |||
413 | # XXX: correctness checking | ||
414 | |||
415 | # drop the last path component | ||
416 | subrepos=( "${subrepos[@]%/*}" ) | ||
417 | # and then the trailing slashes, again | ||
418 | subrepos=( "${subrepos[@]%%/}" ) | ||
419 | else | ||
420 | break | ||
421 | fi | ||
422 | done | ||
423 | |||
424 | # append the preprocessed path to the preprocessed URIs | ||
425 | subrepos=( "${subrepos[@]/%//${suburl}}") | ||
426 | else | ||
427 | subrepos=( "${suburl}" ) | ||
428 | fi | ||
429 | } | ||
430 | |||
431 | |||
432 | # @FUNCTION: _git-r3_is_local_repo | ||
433 | # @USAGE: <repo-uri> | ||
434 | # @INTERNAL | ||
435 | # @DESCRIPTION: | ||
436 | # Determine whether the given URI specifies a local (on-disk) | ||
437 | # repository. | ||
438 | _git-r3_is_local_repo() { | ||
439 | debug-print-function ${FUNCNAME} "$@" | ||
440 | |||
441 | local uri=${1} | ||
442 | |||
443 | [[ ${uri} == file://* || ${uri} == /* ]] | ||
444 | } | ||
445 | |||
446 | # @FUNCTION: _git-r3_find_head | ||
447 | # @USAGE: <head-ref> | ||
448 | # @INTERNAL | ||
449 | # @DESCRIPTION: | ||
450 | # Given a ref to which remote HEAD was fetched, try to find | ||
451 | # a branch matching the commit. Expects 'git show-ref' | ||
452 | # or 'git ls-remote' output on stdin. | ||
453 | _git-r3_find_head() { | ||
454 | debug-print-function ${FUNCNAME} "$@" | ||
455 | |||
456 | local head_ref=${1} | ||
457 | local head_hash=$(git rev-parse --verify "${1}" || die) | ||
458 | local matching_ref | ||
459 | |||
460 | # TODO: some transports support peeking at symbolic remote refs | ||
461 | # find a way to use that rather than guessing | ||
462 | |||
463 | # (based on guess_remote_head() in git-1.9.0/remote.c) | ||
464 | local h ref | ||
465 | while read h ref; do | ||
466 | # look for matching head | ||
467 | if [[ ${h} == ${head_hash} ]]; then | ||
468 | # either take the first matching ref, or master if it is there | ||
469 | if [[ ! ${matching_ref} || ${ref} == refs/heads/master ]]; then | ||
470 | matching_ref=${ref} | ||
471 | fi | ||
472 | fi | ||
473 | done | ||
474 | |||
475 | if [[ ! ${matching_ref} ]]; then | ||
476 | die "Unable to find a matching branch for remote HEAD (${head_hash})" | ||
477 | fi | ||
478 | |||
479 | echo "${matching_ref}" | ||
480 | } | ||
481 | |||
482 | # @FUNCTION: git-r3_fetch | ||
483 | # @USAGE: [<repo-uri> [<remote-ref> [<local-id>]]] | ||
484 | # @DESCRIPTION: | ||
485 | # Fetch new commits to the local clone of repository. | ||
486 | # | ||
487 | # <repo-uri> specifies the repository URIs to fetch from, as a space- | ||
488 | # -separated list. The first URI will be used as repository group | ||
489 | # identifier and therefore must be used consistently. When not | ||
490 | # specified, defaults to ${EGIT_REPO_URI}. | ||
491 | # | ||
492 | # <remote-ref> specifies the remote ref or commit id to fetch. | ||
493 | # It is preferred to use 'refs/heads/<branch-name>' for branches | ||
494 | # and 'refs/tags/<tag-name>' for tags. Other options are 'HEAD' | ||
495 | # for upstream default branch and hexadecimal commit SHA1. Defaults | ||
496 | # to the first of EGIT_COMMIT, EGIT_BRANCH or literal 'HEAD' that | ||
497 | # is set to a non-null value. | ||
498 | # | ||
499 | # <local-id> specifies the local branch identifier that will be used to | ||
500 | # locally store the fetch result. It should be unique to multiple | ||
501 | # fetches within the repository that can be performed at the same time | ||
502 | # (including parallel merges). It defaults to ${CATEGORY}/${PN}/${SLOT%/*}. | ||
503 | # This default should be fine unless you are fetching multiple trees | ||
504 | # from the same repository in the same ebuild. | ||
505 | # | ||
506 | # The fetch operation will affect the EGIT_STORE only. It will not touch | ||
507 | # the working copy, nor export any environment variables. | ||
508 | # If the repository contains submodules, they will be fetched | ||
509 | # recursively. | ||
510 | git-r3_fetch() { | ||
511 | debug-print-function ${FUNCNAME} "$@" | ||
512 | |||
513 | [[ ${EVCS_OFFLINE} ]] && return | ||
514 | |||
515 | local repos | ||
516 | if [[ ${1} ]]; then | ||
517 | repos=( ${1} ) | ||
518 | elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then | ||
519 | repos=( "${EGIT_REPO_URI[@]}" ) | ||
520 | else | ||
521 | repos=( ${EGIT_REPO_URI} ) | ||
522 | fi | ||
523 | |||
524 | local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}} | ||
525 | local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}} | ||
526 | local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}} | ||
527 | local local_ref=refs/git-r3/${local_id}/__main__ | ||
528 | |||
529 | [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset" | ||
530 | |||
531 | local -x GIT_DIR | ||
532 | _git-r3_set_gitdir "${repos[0]}" | ||
533 | |||
534 | # prepend the local mirror if applicable | ||
535 | if [[ ${EGIT_MIRROR_URI} ]]; then | ||
536 | repos=( | ||
537 | "${EGIT_MIRROR_URI%/}/${GIT_DIR##*/}" | ||
538 | "${repos[@]}" | ||
539 | ) | ||
540 | fi | ||
541 | |||
542 | # try to fetch from the remote | ||
543 | local r success saved_umask | ||
544 | if [[ ${EVCS_UMASK} ]]; then | ||
545 | saved_umask=$(umask) | ||
546 | umask "${EVCS_UMASK}" || die "Bad options to umask: ${EVCS_UMASK}" | ||
547 | fi | ||
548 | for r in "${repos[@]}"; do | ||
549 | einfo "Fetching \e[1m${r}\e[22m ..." | ||
550 | |||
551 | if [[ ${r} == https?://* ]]; then | ||
552 | # if we're not using git protocol, web proxy takes care of things | ||
553 | EGIT_SOCKS = "" | ||
554 | elif [[ ! ${EGIT_SOCKS} ]] && [[ ${r} == git://*.onion/* ]]; then | ||
555 | if ROOT=/ has_version 'net-proxy/torsocks'; then | ||
556 | EGIT_SOCKS="torsocks" | ||
557 | else | ||
558 | die "Properly configured net-proxy/torsocks required to fetch git from onion." | ||
559 | fi | ||
560 | fi | ||
561 | |||
562 | local fetch_command=( ${EGIT_SOCKS} git fetch "${r}" ) | ||
563 | local clone_type=${EGIT_CLONE_TYPE} | ||
564 | |||
565 | if [[ ${r} == https://* ]] && ! ROOT=/ has_version 'dev-vcs/git[curl]'; then | ||
566 | eerror "git-r3: fetching from https:// requested. In order to support https," | ||
567 | eerror "dev-vcs/git needs to be built with USE=curl. Example solution:" | ||
568 | eerror | ||
569 | eerror " echo dev-vcs/git curl >> /etc/portage/package.use" | ||
570 | eerror " emerge -1v dev-vcs/git" | ||
571 | die "dev-vcs/git built with USE=curl required." | ||
572 | fi | ||
573 | |||
574 | if [[ ${r} == https://code.google.com/* ]]; then | ||
575 | # Google Code has special magic on top of git that: | ||
576 | # 1) can't handle shallow clones at all, | ||
577 | # 2) fetches duplicately when tags are pulled in with branch | ||
578 | # so automatically switch to single+tags mode. | ||
579 | if [[ ${clone_type} == shallow ]]; then | ||
580 | einfo " Google Code does not support shallow clones" | ||
581 | einfo " using \e[1mEGIT_CLONE_TYPE=single+tags\e[22m" | ||
582 | clone_type=single+tags | ||
583 | elif [[ ${clone_type} == single ]]; then | ||
584 | einfo " git-r3: Google Code does not send tags properly in 'single' mode" | ||
585 | einfo " using \e[1mEGIT_CLONE_TYPE=single+tags\e[22m" | ||
586 | clone_type=single+tags | ||
587 | fi | ||
588 | fi | ||
589 | |||
590 | if [[ ${clone_type} == mirror ]]; then | ||
591 | fetch_command+=( | ||
592 | --prune | ||
593 | # mirror the remote branches as local branches | ||
594 | "+refs/heads/*:refs/heads/*" | ||
595 | # pull tags explicitly in order to prune them properly | ||
596 | "+refs/tags/*:refs/tags/*" | ||
597 | # notes in case something needs them | ||
598 | "+refs/notes/*:refs/notes/*" | ||
599 | # and HEAD in case we need the default branch | ||
600 | # (we keep it in refs/git-r3 since otherwise --prune interferes) | ||
601 | "+HEAD:refs/git-r3/HEAD" | ||
602 | ) | ||
603 | else # single or shallow | ||
604 | local fetch_l fetch_r | ||
605 | |||
606 | if [[ ${remote_ref} == HEAD ]]; then | ||
607 | # HEAD | ||
608 | fetch_l=HEAD | ||
609 | elif [[ ${remote_ref} == refs/* ]]; then | ||
610 | # regular branch, tag or some other explicit ref | ||
611 | fetch_l=${remote_ref} | ||
612 | else | ||
613 | # tag or commit id... | ||
614 | # let ls-remote figure it out | ||
615 | local tagref=$(${EGIT_SOCKS} git ls-remote "${r}" "refs/tags/${remote_ref}") | ||
616 | |||
617 | # if it was a tag, ls-remote obtained a hash | ||
618 | if [[ ${tagref} ]]; then | ||
619 | # tag | ||
620 | fetch_l=refs/tags/${remote_ref} | ||
621 | else | ||
622 | # commit id | ||
623 | # so we need to fetch the whole branch | ||
624 | if [[ ${branch} ]]; then | ||
625 | fetch_l=${branch} | ||
626 | else | ||
627 | fetch_l=HEAD | ||
628 | fi | ||
629 | |||
630 | # fetching by commit in shallow mode? can't do. | ||
631 | if [[ ${clone_type} == shallow ]]; then | ||
632 | clone_type=single | ||
633 | fi | ||
634 | fi | ||
635 | fi | ||
636 | |||
637 | if [[ ${fetch_l} == HEAD ]]; then | ||
638 | fetch_r=refs/git-r3/HEAD | ||
639 | else | ||
640 | fetch_r=${fetch_l} | ||
641 | fi | ||
642 | |||
643 | fetch_command+=( | ||
644 | "+${fetch_l}:${fetch_r}" | ||
645 | ) | ||
646 | |||
647 | if [[ ${clone_type} == single+tags ]]; then | ||
648 | fetch_command+=( | ||
649 | # pull tags explicitly as requested | ||
650 | "+refs/tags/*:refs/tags/*" | ||
651 | ) | ||
652 | fi | ||
653 | fi | ||
654 | |||
655 | if [[ ${clone_type} == shallow ]]; then | ||
656 | if _git-r3_is_local_repo; then | ||
657 | # '--depth 1' causes sandbox violations with local repos | ||
658 | # bug #491260 | ||
659 | clone_type=single | ||
660 | elif [[ ! $(git rev-parse --quiet --verify "${fetch_r}") ]] | ||
661 | then | ||
662 | # use '--depth 1' when fetching a new branch | ||
663 | fetch_command+=( --depth 1 ) | ||
664 | fi | ||
665 | else # non-shallow mode | ||
666 | if [[ -f ${GIT_DIR}/shallow ]]; then | ||
667 | fetch_command+=( --unshallow ) | ||
668 | fi | ||
669 | fi | ||
670 | |||
671 | set -- "${fetch_command[@]}" | ||
672 | echo "${@}" >&2 | ||
673 | if "${@}"; then | ||
674 | if [[ ${clone_type} == mirror ]]; then | ||
675 | # find remote HEAD and update our HEAD properly | ||
676 | git symbolic-ref HEAD \ | ||
677 | "$(_git-r3_find_head refs/git-r3/HEAD \ | ||
678 | < <(git show-ref --heads || die))" \ | ||
679 | || die "Unable to update HEAD" | ||
680 | else # single or shallow | ||
681 | if [[ ${fetch_l} == HEAD ]]; then | ||
682 | # find out what branch we fetched as HEAD | ||
683 | local head_branch=$(_git-r3_find_head \ | ||
684 | refs/git-r3/HEAD \ | ||
685 | < <(${EGIT_SOCKS} git ls-remote --heads "${r}" || die)) | ||
686 | |||
687 | # and move it to its regular place | ||
688 | git update-ref --no-deref "${head_branch}" \ | ||
689 | refs/git-r3/HEAD \ | ||
690 | || die "Unable to sync HEAD branch ${head_branch}" | ||
691 | git symbolic-ref HEAD "${head_branch}" \ | ||
692 | || die "Unable to update HEAD" | ||
693 | fi | ||
694 | fi | ||
695 | |||
696 | # now let's see what the user wants from us | ||
697 | local full_remote_ref=$( | ||
698 | ${EGIT_SOCKS} git rev-parse --verify --symbolic-full-name "${remote_ref}" | ||
699 | ) | ||
700 | |||
701 | if [[ ${full_remote_ref} ]]; then | ||
702 | # when we are given a ref, create a symbolic ref | ||
703 | # so that we preserve the actual argument | ||
704 | set -- git symbolic-ref "${local_ref}" "${full_remote_ref}" | ||
705 | else | ||
706 | # otherwise, we were likely given a commit id | ||
707 | set -- git update-ref --no-deref "${local_ref}" "${remote_ref}" | ||
708 | fi | ||
709 | |||
710 | echo "${@}" >&2 | ||
711 | if ! "${@}"; then | ||
712 | die "Referencing ${remote_ref} failed (wrong ref?)." | ||
713 | fi | ||
714 | |||
715 | success=1 | ||
716 | break | ||
717 | fi | ||
718 | done | ||
719 | if [[ ${saved_umask} ]]; then | ||
720 | umask "${saved_umask}" || die | ||
721 | fi | ||
722 | [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI" | ||
723 | |||
724 | # consistency check, in case we got man-in-the-middle't --lynX | ||
725 | git fsck | ||
726 | |||
727 | # submodules can reference commits in any branch | ||
728 | # always use the 'mirror' mode to accomodate that, bug #503332 | ||
729 | local EGIT_CLONE_TYPE=mirror | ||
730 | |||
731 | # recursively fetch submodules | ||
732 | if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then | ||
733 | local submodules | ||
734 | _git-r3_set_submodules \ | ||
735 | "$(${EGIT_SOCKS} git cat-file -p "${local_ref}":.gitmodules || die)" | ||
736 | |||
737 | while [[ ${submodules[@]} ]]; do | ||
738 | local subname=${submodules[0]} | ||
739 | local url=${submodules[1]} | ||
740 | local path=${submodules[2]} | ||
741 | |||
742 | # use only submodules for which path does exist | ||
743 | # (this is in par with 'git submodule'), bug #551100 | ||
744 | # note: git cat-file does not work for submodules | ||
745 | if [[ $(git ls-tree -d "${local_ref}" "${path}") ]] | ||
746 | then | ||
747 | local commit=$(${EGIT_SOCKS} git rev-parse "${local_ref}:${path}" || die) | ||
748 | |||
749 | if [[ ! ${commit} ]]; then | ||
750 | die "Unable to get commit id for submodule ${subname}" | ||
751 | fi | ||
752 | |||
753 | local subrepos | ||
754 | _git-r3_set_subrepos "${url}" "${repos[@]}" | ||
755 | |||
756 | git-r3_fetch "${subrepos[*]}" "${commit}" "${local_id}/${subname}" | ||
757 | fi | ||
758 | |||
759 | submodules=( "${submodules[@]:3}" ) # shift | ||
760 | done | ||
761 | fi | ||
762 | } | ||
763 | |||
764 | # @FUNCTION: git-r3_checkout | ||
765 | # @USAGE: [<repo-uri> [<checkout-path> [<local-id>]]] | ||
766 | # @DESCRIPTION: | ||
767 | # Check the previously fetched tree to the working copy. | ||
768 | # | ||
769 | # <repo-uri> specifies the repository URIs, as a space-separated list. | ||
770 | # The first URI will be used as repository group identifier | ||
771 | # and therefore must be used consistently with git-r3_fetch. | ||
772 | # The remaining URIs are not used and therefore may be omitted. | ||
773 | # When not specified, defaults to ${EGIT_REPO_URI}. | ||
774 | # | ||
775 | # <checkout-path> specifies the path to place the checkout. It defaults | ||
776 | # to ${EGIT_CHECKOUT_DIR} if set, otherwise to ${WORKDIR}/${P}. | ||
777 | # | ||
778 | # <local-id> needs to specify the local identifier that was used | ||
779 | # for respective git-r3_fetch. | ||
780 | # | ||
781 | # The checkout operation will write to the working copy, and export | ||
782 | # the repository state into the environment. If the repository contains | ||
783 | # submodules, they will be checked out recursively. | ||
784 | git-r3_checkout() { | ||
785 | debug-print-function ${FUNCNAME} "$@" | ||
786 | |||
787 | local repos | ||
788 | if [[ ${1} ]]; then | ||
789 | repos=( ${1} ) | ||
790 | elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then | ||
791 | repos=( "${EGIT_REPO_URI[@]}" ) | ||
792 | else | ||
793 | repos=( ${EGIT_REPO_URI} ) | ||
794 | fi | ||
795 | |||
796 | local out_dir=${2:-${EGIT_CHECKOUT_DIR:-${WORKDIR}/${P}}} | ||
797 | local local_id=${3:-${CATEGORY}/${PN}/${SLOT%/*}} | ||
798 | |||
799 | local -x GIT_DIR | ||
800 | _git-r3_set_gitdir "${repos[0]}" | ||
801 | |||
802 | einfo "Checking out \e[1m${repos[0]}\e[22m to \e[1m${out_dir}\e[22m ..." | ||
803 | |||
804 | if ! git cat-file -e refs/git-r3/"${local_id}"/__main__; then | ||
805 | if [[ ${EVCS_OFFLINE} ]]; then | ||
806 | die "No local clone of ${repos[0]}. Unable to work with EVCS_OFFLINE." | ||
807 | else | ||
808 | die "Logic error: no local clone of ${repos[0]}. git-r3_fetch not used?" | ||
809 | fi | ||
810 | fi | ||
811 | local remote_ref=$( | ||
812 | git symbolic-ref --quiet refs/git-r3/"${local_id}"/__main__ | ||
813 | ) | ||
814 | local new_commit_id=$( | ||
815 | git rev-parse --verify refs/git-r3/"${local_id}"/__main__ | ||
816 | ) | ||
817 | |||
818 | git-r3_sub_checkout() { | ||
819 | local orig_repo=${GIT_DIR} | ||
820 | local -x GIT_DIR=${out_dir}/.git | ||
821 | local -x GIT_WORK_TREE=${out_dir} | ||
822 | |||
823 | mkdir -p "${out_dir}" || die | ||
824 | |||
825 | # use git init+fetch instead of clone since the latter doesn't like | ||
826 | # non-empty directories. | ||
827 | |||
828 | git init --quiet || die | ||
829 | # setup 'alternates' to avoid copying objects | ||
830 | echo "${orig_repo}/objects" > "${GIT_DIR}"/objects/info/alternates || die | ||
831 | # now copy the refs | ||
832 | # [htn]* safely catches heads, tags, notes without complaining | ||
833 | # on non-existing ones, and omits internal 'git-r3' ref | ||
834 | cp -R "${orig_repo}"/refs/[htn]* "${GIT_DIR}"/refs/ || die | ||
835 | |||
836 | # (no need to copy HEAD, we will set it via checkout) | ||
837 | |||
838 | if [[ -f ${orig_repo}/shallow ]]; then | ||
839 | cp "${orig_repo}"/shallow "${GIT_DIR}"/ || die | ||
840 | fi | ||
841 | |||
842 | set -- git checkout --quiet | ||
843 | if [[ ${remote_ref} ]]; then | ||
844 | set -- "${@}" "${remote_ref#refs/heads/}" | ||
845 | else | ||
846 | set -- "${@}" "${new_commit_id}" | ||
847 | fi | ||
848 | echo "${@}" >&2 | ||
849 | "${@}" || die "git checkout ${remote_ref:-${new_commit_id}} failed" | ||
850 | } | ||
851 | git-r3_sub_checkout | ||
852 | unset -f git-r3_sub_checkout | ||
853 | |||
854 | local old_commit_id=$( | ||
855 | git rev-parse --quiet --verify refs/git-r3/"${local_id}"/__old__ | ||
856 | ) | ||
857 | if [[ ! ${old_commit_id} ]]; then | ||
858 | echo "GIT NEW branch -->" | ||
859 | echo " repository: ${repos[0]}" | ||
860 | echo " at the commit: ${new_commit_id}" | ||
861 | else | ||
862 | # diff against previous revision | ||
863 | echo "GIT update -->" | ||
864 | echo " repository: ${repos[0]}" | ||
865 | # write out message based on the revisions | ||
866 | if [[ "${old_commit_id}" != "${new_commit_id}" ]]; then | ||
867 | echo " updating from commit: ${old_commit_id}" | ||
868 | echo " to commit: ${new_commit_id}" | ||
869 | |||
870 | git --no-pager diff --stat \ | ||
871 | ${old_commit_id}..${new_commit_id} | ||
872 | else | ||
873 | echo " at the commit: ${new_commit_id}" | ||
874 | fi | ||
875 | fi | ||
876 | git update-ref --no-deref refs/git-r3/"${local_id}"/{__old__,__main__} || die | ||
877 | |||
878 | # recursively checkout submodules | ||
879 | if [[ -f ${out_dir}/.gitmodules ]]; then | ||
880 | local submodules | ||
881 | _git-r3_set_submodules \ | ||
882 | "$(<"${out_dir}"/.gitmodules)" | ||
883 | |||
884 | while [[ ${submodules[@]} ]]; do | ||
885 | local subname=${submodules[0]} | ||
886 | local url=${submodules[1]} | ||
887 | local path=${submodules[2]} | ||
888 | |||
889 | # use only submodules for which path does exist | ||
890 | # (this is in par with 'git submodule'), bug #551100 | ||
891 | if [[ -d ${out_dir}/${path} ]]; then | ||
892 | local subrepos | ||
893 | _git-r3_set_subrepos "${url}" "${repos[@]}" | ||
894 | |||
895 | git-r3_checkout "${subrepos[*]}" "${out_dir}/${path}" \ | ||
896 | "${local_id}/${subname}" | ||
897 | fi | ||
898 | |||
899 | submodules=( "${submodules[@]:3}" ) # shift | ||
900 | done | ||
901 | fi | ||
902 | |||
903 | # keep this *after* submodules | ||
904 | export EGIT_DIR=${GIT_DIR} | ||
905 | export EGIT_VERSION=${new_commit_id} | ||
906 | } | ||
907 | |||
908 | # @FUNCTION: git-r3_peek_remote_ref | ||
909 | # @USAGE: [<repo-uri> [<remote-ref>]] | ||
910 | # @DESCRIPTION: | ||
911 | # Peek the reference in the remote repository and print the matching | ||
912 | # (newest) commit SHA1. | ||
913 | # | ||
914 | # <repo-uri> specifies the repository URIs to fetch from, as a space- | ||
915 | # -separated list. When not specified, defaults to ${EGIT_REPO_URI}. | ||
916 | # | ||
917 | # <remote-ref> specifies the remote ref to peek. It is preferred to use | ||
918 | # 'refs/heads/<branch-name>' for branches and 'refs/tags/<tag-name>' | ||
919 | # for tags. Alternatively, 'HEAD' may be used for upstream default | ||
920 | # branch. Defaults to the first of EGIT_COMMIT, EGIT_BRANCH or literal | ||
921 | # 'HEAD' that is set to a non-null value. | ||
922 | # | ||
923 | # The operation will be done purely on the remote, without using local | ||
924 | # storage. If commit SHA1 is provided as <remote-ref>, the function will | ||
925 | # fail due to limitations of git protocol. | ||
926 | # | ||
927 | # On success, the function returns 0 and writes hexadecimal commit SHA1 | ||
928 | # to stdout. On failure, the function returns 1. | ||
929 | git-r3_peek_remote_ref() { | ||
930 | debug-print-function ${FUNCNAME} "$@" | ||
931 | |||
932 | local repos | ||
933 | if [[ ${1} ]]; then | ||
934 | repos=( ${1} ) | ||
935 | elif [[ $(declare -p EGIT_REPO_URI) == "declare -a"* ]]; then | ||
936 | repos=( "${EGIT_REPO_URI[@]}" ) | ||
937 | else | ||
938 | repos=( ${EGIT_REPO_URI} ) | ||
939 | fi | ||
940 | |||
941 | local branch=${EGIT_BRANCH:+refs/heads/${EGIT_BRANCH}} | ||
942 | local remote_ref=${2:-${EGIT_COMMIT:-${branch:-HEAD}}} | ||
943 | |||
944 | [[ ${repos[@]} ]] || die "No URI provided and EGIT_REPO_URI unset" | ||
945 | |||
946 | local r success | ||
947 | for r in "${repos[@]}"; do | ||
948 | einfo "Peeking \e[1m${remote_ref}\e[22m on \e[1m${r}\e[22m ..." >&2 | ||
949 | |||
950 | local lookup_ref | ||
951 | if [[ ${remote_ref} == refs/* || ${remote_ref} == HEAD ]] | ||
952 | then | ||
953 | lookup_ref=${remote_ref} | ||
954 | else | ||
955 | # ls-remote by commit is going to fail anyway, | ||
956 | # so we may as well pass refs/tags/ABCDEF... | ||
957 | lookup_ref=refs/tags/${remote_ref} | ||
958 | fi | ||
959 | |||
960 | # split on whitespace | ||
961 | local ref=( | ||
962 | $(git ls-remote "${r}" "${lookup_ref}") | ||
963 | ) | ||
964 | |||
965 | if [[ ${ref[0]} ]]; then | ||
966 | echo "${ref[0]}" | ||
967 | return 0 | ||
968 | fi | ||
969 | done | ||
970 | |||
971 | return 1 | ||
972 | } | ||
973 | |||
974 | git-r3_src_fetch() { | ||
975 | debug-print-function ${FUNCNAME} "$@" | ||
976 | |||
977 | if [[ ! ${EGIT3_STORE_DIR} && ${EGIT_STORE_DIR} ]]; then | ||
978 | ewarn "You have set EGIT_STORE_DIR but not EGIT3_STORE_DIR. Please consider" | ||
979 | ewarn "setting EGIT3_STORE_DIR for git-r3.eclass. It is recommended to use" | ||
980 | ewarn "a different directory than EGIT_STORE_DIR to ease removing old clones" | ||
981 | ewarn "when git-2 eclass becomes deprecated." | ||
982 | fi | ||
983 | |||
984 | _git-r3_env_setup | ||
985 | git-r3_fetch | ||
986 | } | ||
987 | |||
988 | git-r3_src_unpack() { | ||
989 | debug-print-function ${FUNCNAME} "$@" | ||
990 | |||
991 | _git-r3_env_setup | ||
992 | git-r3_src_fetch | ||
993 | git-r3_checkout | ||
994 | } | ||
995 | |||
996 | # https://bugs.gentoo.org/show_bug.cgi?id=482666 | ||
997 | git-r3_pkg_needrebuild() { | ||
998 | debug-print-function ${FUNCNAME} "$@" | ||
999 | |||
1000 | local new_commit_id=$(git-r3_peek_remote_ref) | ||
1001 | [[ ${new_commit_id} && ${EGIT_VERSION} ]] || die "Lookup failed" | ||
1002 | |||
1003 | if [[ ${EGIT_VERSION} != ${new_commit_id} ]]; then | ||
1004 | einfo "Update from \e[1m${EGIT_VERSION}\e[22m to \e[1m${new_commit_id}\e[22m" | ||
1005 | else | ||
1006 | einfo "Local and remote at \e[1m${EGIT_VERSION}\e[22m" | ||
1007 | fi | ||
1008 | |||
1009 | [[ ${EGIT_VERSION} != ${new_commit_id} ]] | ||
1010 | } | ||
1011 | |||
1012 | # 'export' locally until this gets into EAPI | ||
1013 | pkg_needrebuild() { git-r3_pkg_needrebuild; } | ||
1014 | |||
1015 | _GIT_R3=1 | ||
1016 | fi | ||
diff --git a/git-r3.eclass.patch b/git-r3.eclass.patch new file mode 100644 index 0000000..92310c2 --- /dev/null +++ b/git-r3.eclass.patch | |||
@@ -0,0 +1,99 @@ | |||
1 | Patch recreated from diff -u with | ||
2 | git co 9dd95690e6f4ff62d66595eb2e0f78c223b32a3e git-r3.eclass | ||
3 | Commit hash obtained by checking date using 'git blame', | ||
4 | then looking up 'git log git-r3.eclass'. | ||
5 | (So now you know how to do this). | ||
6 | |||
7 | --- /portage/eclass/git-r3.eclass 2018-12-17 10:59:00.141710464 +0100 | ||
8 | +++ git-r3.tor.eclass 2018-12-17 10:33:59.554716188 +0100 | ||
9 | @@ -9,6 +9,15 @@ | ||
10 | # @DESCRIPTION: | ||
11 | # Third generation eclass for easing maintenance of live ebuilds using | ||
12 | # git as remote repository. | ||
13 | +# | ||
14 | +# Patched by symlynX to allow for gits via Tor. Why Tor? Because | ||
15 | +# unlike HTTPS it provides end-to-end authenticity which is not | ||
16 | +# susceptible to man-in-the-middle attacks, so all gits should | ||
17 | +# migrate to Tor, cjdns or gnunet-vpn. But the latter two do | ||
18 | +# not need custom changes to this file to do their job. | ||
19 | +# | ||
20 | +# @FIXME: Should we automatically define EGIT_SOCKS="torsocks" | ||
21 | +# when we see that /etc/tor/torsocks.conf exists? | ||
22 | |||
23 | case "${EAPI:-0}" in | ||
24 | 0|1|2|3|4|5|6) | ||
25 | @@ -539,7 +548,18 @@ | ||
26 | for r in "${repos[@]}"; do | ||
27 | einfo "Fetching \e[1m${r}\e[22m ..." | ||
28 | |||
29 | - local fetch_command=( git fetch "${r}" ) | ||
30 | + if [[ ${r} == https?://* ]]; then | ||
31 | + # if we're not using git protocol, web proxy takes care of things | ||
32 | + EGIT_SOCKS = "" | ||
33 | + elif [[ ! ${EGIT_SOCKS} ]] && [[ ${r} == git://*.onion/* ]]; then | ||
34 | + if ROOT=/ has_version 'net-proxy/torsocks'; then | ||
35 | + EGIT_SOCKS="torsocks" | ||
36 | + else | ||
37 | + die "Properly configured net-proxy/torsocks required to fetch git from onion." | ||
38 | + fi | ||
39 | + fi | ||
40 | + | ||
41 | + local fetch_command=( ${EGIT_SOCKS} git fetch "${r}" ) | ||
42 | local clone_type=${EGIT_CLONE_TYPE} | ||
43 | |||
44 | if [[ ${r} == https://* ]] && ! ROOT=/ has_version 'dev-vcs/git[curl]'; then | ||
45 | @@ -592,7 +612,7 @@ | ||
46 | else | ||
47 | # tag or commit id... | ||
48 | # let ls-remote figure it out | ||
49 | - local tagref=$(git ls-remote "${r}" "refs/tags/${remote_ref}") | ||
50 | + local tagref=$(${EGIT_SOCKS} git ls-remote "${r}" "refs/tags/${remote_ref}") | ||
51 | |||
52 | # if it was a tag, ls-remote obtained a hash | ||
53 | if [[ ${tagref} ]]; then | ||
54 | @@ -662,7 +682,7 @@ | ||
55 | # find out what branch we fetched as HEAD | ||
56 | local head_branch=$(_git-r3_find_head \ | ||
57 | refs/git-r3/HEAD \ | ||
58 | - < <(git ls-remote --heads "${r}" || die)) | ||
59 | + < <(${EGIT_SOCKS} git ls-remote --heads "${r}" || die)) | ||
60 | |||
61 | # and move it to its regular place | ||
62 | git update-ref --no-deref "${head_branch}" \ | ||
63 | @@ -675,7 +695,7 @@ | ||
64 | |||
65 | # now let's see what the user wants from us | ||
66 | local full_remote_ref=$( | ||
67 | - git rev-parse --verify --symbolic-full-name "${remote_ref}" | ||
68 | + ${EGIT_SOCKS} git rev-parse --verify --symbolic-full-name "${remote_ref}" | ||
69 | ) | ||
70 | |||
71 | if [[ ${full_remote_ref} ]]; then | ||
72 | @@ -701,6 +721,9 @@ | ||
73 | fi | ||
74 | [[ ${success} ]] || die "Unable to fetch from any of EGIT_REPO_URI" | ||
75 | |||
76 | + # consistency check, in case we got man-in-the-middle't --lynX | ||
77 | + git fsck | ||
78 | + | ||
79 | # submodules can reference commits in any branch | ||
80 | # always use the 'mirror' mode to accomodate that, bug #503332 | ||
81 | local EGIT_CLONE_TYPE=mirror | ||
82 | @@ -709,7 +732,7 @@ | ||
83 | if git cat-file -e "${local_ref}":.gitmodules &>/dev/null; then | ||
84 | local submodules | ||
85 | _git-r3_set_submodules \ | ||
86 | - "$(git cat-file -p "${local_ref}":.gitmodules || die)" | ||
87 | + "$(${EGIT_SOCKS} git cat-file -p "${local_ref}":.gitmodules || die)" | ||
88 | |||
89 | while [[ ${submodules[@]} ]]; do | ||
90 | local subname=${submodules[0]} | ||
91 | @@ -721,7 +744,7 @@ | ||
92 | # note: git cat-file does not work for submodules | ||
93 | if [[ $(git ls-tree -d "${local_ref}" "${path}") ]] | ||
94 | then | ||
95 | - local commit=$(git rev-parse "${local_ref}:${path}" || die) | ||
96 | + local commit=$(${EGIT_SOCKS} git rev-parse "${local_ref}:${path}" || die) | ||
97 | |||
98 | if [[ ! ${commit} ]]; then | ||
99 | die "Unable to get commit id for submodule ${subname}" | ||