1 |
commit: 1e984dab27458e3026163c5690aec5fd3298dd8b |
2 |
Author: Zac Medico <zmedico <AT> gentoo <DOT> org> |
3 |
AuthorDate: Sat May 18 22:24:05 2013 +0000 |
4 |
Commit: Zac Medico <zmedico <AT> gentoo <DOT> org> |
5 |
CommitDate: Sat May 18 22:24:05 2013 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/portage.git;a=commit;h=1e984dab |
7 |
|
8 |
Support PORTAGE_SSH_OPTS, bug #470002. |
9 |
|
10 |
Additional ssh options to be used when portage executes ssh or sftp. |
11 |
This variable supports use of embedded quote characters to quote |
12 |
whitespace or special shell characters within arguments (embedded |
13 |
quotes must be escaped in make.conf settings). |
14 |
|
15 |
--- |
16 |
cnf/make.globals | 6 ++- |
17 |
man/make.conf.5 | 8 +++++ |
18 |
pym/_emerge/BinpkgFetcher.py | 8 ++++- |
19 |
pym/_emerge/actions.py | 6 +++ |
20 |
pym/portage/dbapi/bintree.py | 31 +++++++++++++++--- |
21 |
pym/portage/getbinpkg.py | 33 +++++++++++++++----- |
22 |
.../package/ebuild/_config/special_env_vars.py | 2 +- |
23 |
pym/portage/package/ebuild/fetch.py | 9 ++++- |
24 |
8 files changed, 84 insertions(+), 19 deletions(-) |
25 |
|
26 |
diff --git a/cnf/make.globals b/cnf/make.globals |
27 |
index 5f5098b..1f07df3 100644 |
28 |
--- a/cnf/make.globals |
29 |
+++ b/cnf/make.globals |
30 |
@@ -46,10 +46,12 @@ RESUMECOMMAND="wget -c -t 3 -T 60 --passive-ftp -O \"\${DISTDIR}/\${FILE}\" \"\$ |
31 |
FETCHCOMMAND_RSYNC="rsync -avP \"\${URI}\" \"\${DISTDIR}/\${FILE}\"" |
32 |
RESUMECOMMAND_RSYNC="rsync -avP \"\${URI}\" \"\${DISTDIR}/\${FILE}\"" |
33 |
|
34 |
-FETCHCOMMAND_SSH="bash -c \"x=\\\${2#ssh://} ; host=\\\${x%%/*} ; port=\\\${host##*:} ; host=\\\${host%:*} ; [[ \\\${host} = \\\${port} ]] && port=22 ; exec rsync --rsh=\\\"ssh -p\\\${port}\\\" -avP \\\"\\\${host}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" rsync \"\${DISTDIR}/\${FILE}\" \"\${URI}\"" |
35 |
+# NOTE: rsync will evaluate quotes embedded inside PORTAGE_SSH_OPTS |
36 |
+FETCHCOMMAND_SSH="bash -c \"x=\\\${2#ssh://} ; host=\\\${x%%/*} ; port=\\\${host##*:} ; host=\\\${host%:*} ; [[ \\\${host} = \\\${port} ]] && port=22 ; exec rsync --rsh=\\\"ssh -p\\\${port} \\\${3}\\\" -avP \\\"\\\${host}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" rsync \"\${DISTDIR}/\${FILE}\" \"\${URI}\" \"\${PORTAGE_SSH_OPTS}\"" |
37 |
RESUMECOMMAND_SSH=${FETCHCOMMAND_SSH} |
38 |
|
39 |
-FETCHCOMMAND_SFTP="bash -c \"x=\\\${2#sftp://} ; host=\\\${x%%/*} ; port=\\\${host##*:} ; host=\\\${host%:*} ; [[ \\\${host} = \\\${port} ]] && port=22 ; exec sftp -P \\\${port} \\\"\\\${host}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" sftp \"\${DISTDIR}/\${FILE}\" \"\${URI}\"" |
40 |
+# NOTE: bash eval is used to evaluate quotes embedded inside PORTAGE_SSH_OPTS |
41 |
+FETCHCOMMAND_SFTP="bash -c \"x=\\\${2#sftp://} ; host=\\\${x%%/*} ; port=\\\${host##*:} ; host=\\\${host%:*} ; [[ \\\${host} = \\\${port} ]] && port=22 ; eval \\\"declare -a ssh_opts=(\\\${3})\\\" ; exec sftp -P \\\${port} \\\"\\\${ssh_opts[@]}\\\" \\\"\\\${host}:/\\\${x#*/}\\\" \\\"\\\$1\\\"\" sftp \"\${DISTDIR}/\${FILE}\" \"\${URI}\" \"\${PORTAGE_SSH_OPTS}\"" |
42 |
|
43 |
# Default user options |
44 |
FEATURES="assume-digests binpkg-logs |
45 |
|
46 |
diff --git a/man/make.conf.5 b/man/make.conf.5 |
47 |
index 9b4121c..fed71f5 100644 |
48 |
--- a/man/make.conf.5 |
49 |
+++ b/man/make.conf.5 |
50 |
@@ -854,6 +854,14 @@ addresses are exhausted. |
51 |
.br |
52 |
Defaults to -1. |
53 |
.TP |
54 |
+\fBPORTAGE_SSH_OPTS\fR = \fI[list of ssh options]\fR |
55 |
+Additional ssh options to be used when portage executes ssh or sftp. |
56 |
+This variable supports use of embedded quote characters to quote |
57 |
+whitespace or special shell characters within arguments (embedded |
58 |
+quotes must be escaped in make.conf settings). |
59 |
+.br |
60 |
+Defaults to no value. |
61 |
+.TP |
62 |
\fBPORTAGE_SYNC_STALE\fR = \fI[NUMBER]\fR |
63 |
Defines the number of days after the last `emerge \-\-sync` that a warning |
64 |
message should be produced. A value of 0 will disable warnings. |
65 |
|
66 |
diff --git a/pym/_emerge/BinpkgFetcher.py b/pym/_emerge/BinpkgFetcher.py |
67 |
index 099d3c4..543881e 100644 |
68 |
--- a/pym/_emerge/BinpkgFetcher.py |
69 |
+++ b/pym/_emerge/BinpkgFetcher.py |
70 |
@@ -1,4 +1,4 @@ |
71 |
-# Copyright 1999-2012 Gentoo Foundation |
72 |
+# Copyright 1999-2013 Gentoo Foundation |
73 |
# Distributed under the terms of the GNU General Public License v2 |
74 |
|
75 |
from _emerge.AsynchronousLock import AsynchronousLock |
76 |
@@ -80,6 +80,12 @@ class BinpkgFetcher(SpawnProcess): |
77 |
"FILE" : os.path.basename(pkg_path) |
78 |
} |
79 |
|
80 |
+ for k in ("PORTAGE_SSH_OPTS",): |
81 |
+ try: |
82 |
+ fcmd_vars[k] = settings[k] |
83 |
+ except KeyError: |
84 |
+ pass |
85 |
+ |
86 |
fetch_env = dict(settings.items()) |
87 |
fetch_args = [portage.util.varexpand(x, mydict=fcmd_vars) \ |
88 |
for x in portage.util.shlex_split(fcmd)] |
89 |
|
90 |
diff --git a/pym/_emerge/actions.py b/pym/_emerge/actions.py |
91 |
index 3982eb3..a46f565 100644 |
92 |
--- a/pym/_emerge/actions.py |
93 |
+++ b/pym/_emerge/actions.py |
94 |
@@ -2253,6 +2253,9 @@ def action_sync(settings, trees, mtimedb, myopts, myaction): |
95 |
writemsg_level("!!! SYNC is invalid: %s\n" % syncuri, |
96 |
noiselevel=-1, level=logging.ERROR) |
97 |
return 1 |
98 |
+ |
99 |
+ ssh_opts = settings.get("PORTAGE_SSH_OPTS") |
100 |
+ |
101 |
if port is None: |
102 |
port="" |
103 |
if user_name is None: |
104 |
@@ -2370,6 +2373,9 @@ def action_sync(settings, trees, mtimedb, myopts, myaction): |
105 |
|
106 |
rsynccommand = [rsync_binary] + rsync_opts + extra_rsync_opts |
107 |
|
108 |
+ if proto == 'ssh' and ssh_opts: |
109 |
+ rsynccommand.append("--rsh=ssh " + ssh_opts) |
110 |
+ |
111 |
if "--debug" in myopts: |
112 |
print(rsynccommand) |
113 |
|
114 |
|
115 |
diff --git a/pym/portage/dbapi/bintree.py b/pym/portage/dbapi/bintree.py |
116 |
index 14d05ad..77b2886 100644 |
117 |
--- a/pym/portage/dbapi/bintree.py |
118 |
+++ b/pym/portage/dbapi/bintree.py |
119 |
@@ -915,10 +915,18 @@ class binarytree(object): |
120 |
# Use a pipe so that we can terminate the download |
121 |
# early if we detect that the TIMESTAMP header |
122 |
# matches that of the cached Packages file. |
123 |
+ ssh_args = ['ssh'] |
124 |
if port is not None: |
125 |
- port_args = ['-p', "%s" % (port,)] |
126 |
- proc = subprocess.Popen(['ssh'] + port_args + \ |
127 |
- [user_passwd + host, '--', 'cat', path], |
128 |
+ ssh_args.append("-p%s" % (port,)) |
129 |
+ # NOTE: shlex evaluates embedded quotes |
130 |
+ ssh_args.extend(portage.util.shlex_split( |
131 |
+ self.settings.get("PORTAGE_SSH_OPTS", ""))) |
132 |
+ ssh_args.append(user_passwd + host) |
133 |
+ ssh_args.append('--') |
134 |
+ ssh_args.append('cat') |
135 |
+ ssh_args.append(path) |
136 |
+ |
137 |
+ proc = subprocess.Popen(ssh_args, |
138 |
stdout=subprocess.PIPE) |
139 |
f = proc.stdout |
140 |
else: |
141 |
@@ -932,8 +940,21 @@ class binarytree(object): |
142 |
fd, tmp_filename = tempfile.mkstemp() |
143 |
tmp_dirname, tmp_basename = os.path.split(tmp_filename) |
144 |
os.close(fd) |
145 |
- success = portage.getbinpkg.file_get(url, |
146 |
- tmp_dirname, fcmd=fcmd, filename=tmp_basename) |
147 |
+ |
148 |
+ fcmd_vars = { |
149 |
+ "DISTDIR": tmp_dirname, |
150 |
+ "FILE": tmp_basename, |
151 |
+ "URI": url |
152 |
+ } |
153 |
+ |
154 |
+ for k in ("PORTAGE_SSH_OPTS",): |
155 |
+ try: |
156 |
+ fcmd_vars[k] = self.settings[k] |
157 |
+ except KeyError: |
158 |
+ pass |
159 |
+ |
160 |
+ success = portage.getbinpkg.file_get( |
161 |
+ fcmd=fcmd, fcmd_vars=fcmd_vars) |
162 |
if not success: |
163 |
raise EnvironmentError("%s failed" % (setting,)) |
164 |
f = open(tmp_filename, 'rb') |
165 |
|
166 |
diff --git a/pym/portage/getbinpkg.py b/pym/portage/getbinpkg.py |
167 |
index 77c1c8f..ff656ba 100644 |
168 |
--- a/pym/portage/getbinpkg.py |
169 |
+++ b/pym/portage/getbinpkg.py |
170 |
@@ -477,7 +477,8 @@ def file_get_metadata(baseurl,conn=None, chunk_size=3000): |
171 |
return myid |
172 |
|
173 |
|
174 |
-def file_get(baseurl,dest,conn=None,fcmd=None,filename=None): |
175 |
+def file_get(baseurl=None, dest=None, conn=None, fcmd=None, filename=None, |
176 |
+ fcmd_vars=None): |
177 |
"""(baseurl,dest,fcmd=) -- Takes a base url to connect to and read from. |
178 |
URI should be in the form <proto>://[user[:pass]@]<site>[:port]<path>""" |
179 |
|
180 |
@@ -487,14 +488,30 @@ def file_get(baseurl,dest,conn=None,fcmd=None,filename=None): |
181 |
"parameter is deprecated", DeprecationWarning, stacklevel=2) |
182 |
|
183 |
return file_get_lib(baseurl,dest,conn) |
184 |
- if not filename: |
185 |
- filename = os.path.basename(baseurl) |
186 |
|
187 |
- variables = { |
188 |
- "DISTDIR": dest, |
189 |
- "URI": baseurl, |
190 |
- "FILE": filename |
191 |
- } |
192 |
+ variables = {} |
193 |
+ |
194 |
+ if fcmd_vars is not None: |
195 |
+ variables.update(fcmd_vars) |
196 |
+ |
197 |
+ if "DISTDIR" not in variables: |
198 |
+ if dest is None: |
199 |
+ raise portage.exception.MissingParameter( |
200 |
+ _("%s is missing required '%s' key") % |
201 |
+ ("fcmd_vars", "DISTDIR")) |
202 |
+ variables["DISTDIR"] = dest |
203 |
+ |
204 |
+ if "URI" not in variables: |
205 |
+ if baseurl is None: |
206 |
+ raise portage.exception.MissingParameter( |
207 |
+ _("%s is missing required '%s' key") % |
208 |
+ ("fcmd_vars", "URI")) |
209 |
+ variables["URI"] = baseurl |
210 |
+ |
211 |
+ if "FILE" not in variables: |
212 |
+ if filename is None: |
213 |
+ filename = os.path.basename(variables["URI"]) |
214 |
+ variables["FILE"] = filename |
215 |
|
216 |
from portage.util import varexpand |
217 |
from portage.process import spawn |
218 |
|
219 |
diff --git a/pym/portage/package/ebuild/_config/special_env_vars.py b/pym/portage/package/ebuild/_config/special_env_vars.py |
220 |
index 9662571..8b9cac1 100644 |
221 |
--- a/pym/portage/package/ebuild/_config/special_env_vars.py |
222 |
+++ b/pym/portage/package/ebuild/_config/special_env_vars.py |
223 |
@@ -171,7 +171,7 @@ environ_filter += [ |
224 |
"PORTAGE_REPO_DUPLICATE_WARN", |
225 |
"PORTAGE_RO_DISTDIRS", |
226 |
"PORTAGE_RSYNC_EXTRA_OPTS", "PORTAGE_RSYNC_OPTS", |
227 |
- "PORTAGE_RSYNC_RETRIES", "PORTAGE_SYNC_STALE", |
228 |
+ "PORTAGE_RSYNC_RETRIES", "PORTAGE_SSH_OPTS", "PORTAGE_SYNC_STALE", |
229 |
"PORTAGE_USE", "PORTAGE_XATTR_EXCLUDE", |
230 |
"PORT_LOGDIR", "PORT_LOGDIR_CLEAN", |
231 |
"QUICKPKG_DEFAULT_OPTS", "REPOMAN_DEFAULT_OPTS", |
232 |
|
233 |
diff --git a/pym/portage/package/ebuild/fetch.py b/pym/portage/package/ebuild/fetch.py |
234 |
index 0a7bf10..162c7c2 100644 |
235 |
--- a/pym/portage/package/ebuild/fetch.py |
236 |
+++ b/pym/portage/package/ebuild/fetch.py |
237 |
@@ -1,4 +1,4 @@ |
238 |
-# Copyright 2010-2012 Gentoo Foundation |
239 |
+# Copyright 2010-2013 Gentoo Foundation |
240 |
# Distributed under the terms of the GNU General Public License v2 |
241 |
|
242 |
from __future__ import print_function |
243 |
@@ -964,11 +964,16 @@ def fetch(myuris, mysettings, listonly=0, fetchonly=0, |
244 |
writemsg_stdout(_(">>> Downloading '%s'\n") % \ |
245 |
_hide_url_passwd(loc)) |
246 |
variables = { |
247 |
- "DISTDIR": mysettings["DISTDIR"], |
248 |
"URI": loc, |
249 |
"FILE": myfile |
250 |
} |
251 |
|
252 |
+ for k in ("DISTDIR", "PORTAGE_SSH_OPTS"): |
253 |
+ try: |
254 |
+ variables[k] = mysettings[k] |
255 |
+ except KeyError: |
256 |
+ pass |
257 |
+ |
258 |
myfetch = shlex_split(locfetch) |
259 |
myfetch = [varexpand(x, mydict=variables) for x in myfetch] |
260 |
myret = -1 |