* new module credentials.py which contains classes
and methods to set and get passwords for different
backends:
- python-keyring
- gnomekeyring
- ConfigFile based storage
The new code should be backward compatible except a minor
change in add_section (pass and passx are not removed from
the config parser). This affects only callers that do not pass
a creds_mgr_descriptor.
On initial osc call or initial osc call on new API Url
the user now can decide where to store the password (based
on the backends available on his system)
The upcoming credentials manager abstraction supersedes the old
plaintext_passwd behavior. This commits "breaks" the old behavior:
Passwords are not rewritten anymore (plaintext <-> obfuscated)
Move logic to conf module in new function interactive_config_setup
for new config file and missing apiurl section.
Dropped keyring code, because it was never used in write_initial_config()
python3 "workaround" for the quite fragile code in
RawCmdln._help_preprocess: It depends on the "non-deterministic" order
of preprocessor.items(). Hence, the results may differ on python2 and
python3. The real fix is probably to enforce a fixed iteration order.
See also the discussion in [1].
[1] https://github.com/openSUSE/osc/pull/604
prevent call of preprocessor if ${cmd_name} marker is accidentaly set,
but cmdname is None.
Also for cmd_option_list and cmd_usage
overwrite _help_preprocess_* functions in Osc class
After (successfully) running an 'osc vc' the following exception trace
comes up, when no rpm python module is available:
```
no changes made
Traceback (most recent call last):
File "/home/mgerstner/.local/lib64/python3.6/site-packages/osc/babysitter.py", line 62, in run
return prg.main(argv)
File "/home/mgerstner/.local/lib64/python3.6/site-packages/osc/cmdln.py", line 344, in main
return self.cmd(args)
File "/home/mgerstner/.local/lib64/python3.6/site-packages/osc/cmdln.py", line 367, in cmd
retval = self.onecmd(argv)
File "/home/mgerstner/.local/lib64/python3.6/site-packages/osc/cmdln.py", line 501, in onecmd
return self._dispatch_cmd(handler, argv)
File "/home/mgerstner/.local/lib64/python3.6/site-packages/osc/cmdln.py", line 1232, in _dispatch_cmd
return handler(argv[0], opts, *args)
File "/home/mgerstner/.local/lib64/python3.6/site-packages/osc/commandline.py", line 8924, in do_vc
sys.exit(vc.returncode)
SystemExit: 0
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/mgerstner/bin/osc", line 41, in <module>
r = babysitter.run(osccli)
File "/home/mgerstner/.local/lib64/python3.6/site-packages/osc/babysitter.py", line 172, in run
except RPMError as e:
TypeError: catching classes that do not inherit from BaseException is not allowed
```
To fix this change the fallback RPMError from None to an actual
Exception-derived type.
Since we do not know the files' encoding, the diff functions/methods
have to return bytes. Note: decoding the diff result is wrong in
general (see the discussion in [1]).
[1] https://github.com/openSUSE/osc/pull/554
The files are now opened as rb for diffing. In python2 nothing changes.
In python3 the returned diff is bytes now.
The following changes were made:
* commandline.py: The returned diff is now bytes
* get_diff now returs the diff as a bytes-like object
* run_pager writes with sys.stdout.buffer.write if message
is not a string
* for the commit message the returned diff needs to be decoded
now. Otherwise it will just producce garbage. For the commit
message the diff on decoded bytes-objects is ok. (nothing harmfull
can happen here)
* fixed submit_action_diff
* fixed request_interactive_review
use own implementation of HTTPSConnection (myHTTPSConnection)
instead the one provided by M2Crypto (httpslib.HTTPConnection)
And in proxy case use myProxyHTTPSConnection.
all credits go to wfrisch
Do not guess the decoding of the returned output on osc api calls.
This could lead to unexptected behavior. Just use sys.stdout.buffer.write()
to print the bytes-like object in python3.
if prjconfig meta is empty the class metafile init
fails with
if isinstance(input[0], str):
IndexError: list index out of range
This is because input is an empty list and has no
[0] index.
This can be fixed by changing this line to:
if input and isinstance(input[0], str):
simplified and fixed the __init__ method of the metafile class.
input can be string, bytes-like object, list of strings or list
of bytes-like objects now.
Based on the input now always a list is generated and joined to
a string for writing in the fd. (This is ugly but needed for
compat reasons)
this makes sure not to mix objects to prevent a TypeError
TypeError: Can't mix strings and bytes in path components
Fixes#567
Signed-off-by: Maximilian Meister <mmeister@suse.de>
The offline mode does not really work offline since
parse_repoarchdescr() uses get_buildconfig to store the
buildconfig in a temporary file.
Solution:
Use the same logic as in build.py. If in offline mode(noinit = True)
try to use the local _buildconfig file. If not in offline mode just
download the buildconfig from the server via get_buildconfig
On osc meta attribute --attribue <name> --delete the returned
data is encoded. Therefore the sys.stdout.write(data) call fails.
Solution: Decode data
--> sys.stdout.write(decode_it(data))
opts.quiet is passed to get_binary_file which is False by default.
So the following if progress_meter is always False unless -q is given.
So it needs to be if not progress_meter.
When running osc triggerreason on newly created (empty) packages
the command failes with AttributeError: 'NoneType' object has no attribute 'text'
because root.find('explain') is NoneType.
Solution:
Check if root.find('explain') is None and print "No triggerreaseon found".
In this case also do not try to get the triggertime. It will result in the same error.
The content in the todo dict are strings. In python3 the communicate
method expects a bytes-like object not a string.
Solution: Encode every element in todo to a new dict (enc_todo) and
pass this instead of todo
osc se did not sort the output anymore. The logic
in the existing results.sort(key=...) was wrong. Now it is using
key=itemgetter(0,1) has two columns and key=itemgetter(0) if there
is only one column.
When adding attribute with osc meta attribute <prj> -a <attr> -s '<val>'
the api call gets executed successfull but the return value needs to be
decoded to print it correctly.
In some rare cases the chardet encoding detection detects
a wrong encoding standard. Then we switch to latin-1 which
covers most if utf-8 does not work.
* use cmp_to_key from functools for python 2.7 and higer
* use self written cmp_to_key for python 2.6
* new functions compare und cmp (used in python2 and python3)
* a lot of bytestring handling and decoding
* fix slow rbl based on f.readline(bufsize)
In that case, the packages to setup the build environment are
taken from the repositories defined in the kiwi file. Osc did
not take into account that the build config must match this
path. So it cannot just get the build config like with normal
builds, but must use a different path.
This led to build errors on some projects like CentOS 7 which
rely on 'Order' statements from the project config.
The OBS backend already had support for this: the 'path' parameter
can be used to overwrite the project path in the _buildconfig
query. We now use this to provide the correct path if we
detect this case. (The detection is currently a heuristic
because OBS does not provide us with a clear indicator.)
Always error out if the source services execution failed (the old
code only errored out if the local_service_run config option was
set (this behavior was probably unintentionally introduced in commit
d3dd8539d9 ('- fallback to "build
--local-package" if it does not exist instead of complaining'))).
Also, do not suppress all exceptions (if something failed in the
services execution code path, the user should be informed).
The bug was reported by darix.
The vc_export_env call was introduced in commit
37ca5535ce ("Export vc env vars when
running a source service") and broke the testsuite. The potential
http request is useless if there are no services. Hence, avoid it.
Thanks to Marco Strigl for catching the testsuite error!
Some services (like the obs_scm) will use them. Note: if realname
or email is not set in the oscrc, an additional http request will
be performed.
This change was requested by darix.
No functional changes. Note that we cannot simply decode the control's
fields as ascii/utf-8 because a field is not necessarily a valid
ascii/utf-8 encoding (it is possible to register _arbitrary_ custom
fields via a 'register-custom-fields' hook when building a deb
package).
Note: DebQuery.debvercmp really deserves a cleanup:/
cmp(a, b) returns
-1 if a < b
0 if a == 0
1 if a > b
This is needed since python3 has no cmp function anymore.
All credits for this go to Marco Strigl <mstrigl@suse.com> (see
PR#483 [1]).
[1] https://github.com/openSUSE/osc/pull/483
The None argument is always <= than the other argument. We need this
in case of a broken/pathological package where version() or release()
return None (see vercmp (which calls rpmvercmp)).
Returning None breaks ArchQuery.vercmp. Returning b'0' is ok because
an epoch, if present, is always supposed to be an integer (at least
in a "valid" arch package (see scripts/libmakepkg/lint_pkgbuild/epoch.sh.in
in the pacman sources)). Hence, if we compare the epoch of a package,
which has no explicit epoch set, with the epoch of a package, which
has an explicit epoch set, we always have a <= relation.
If size is 0, using pb.Percentage will result in a
ZeroDivisionException. Note: the output in case of
size == 0 looks a bit "strange" - for a consistent
output we should probably subclass pb.Percentage.
* new function create_text_meter with fallback selection
* NoPBTextMeter.start() will print the basename (if not stated otherise with
basename = None)
* The callers that should use an alternare TextMeter class now call create_text_meter()
* The callers that should not use and alternate TextMeter (because of different handling,
like build.py) call create_text_meter(use_pb_fallback=False)
* the warning 'Please install the progressbar module' is now only shown once
improvements
Now, CpioWrite provides a bytes-only API. It would be also possible
that the API accepts bytes and str (we would need to explicitly
encode the latter) but this would be a bit inconsistent wrt.
cpio.CpioRead (which is bytes-only).
Also, by using a bytesarray instead of a [] we avoid several
intermediate ''.join(...)s.
This is a bytes only API because a filename in a cpio archive can
contain, for instance, illegal utf-8 sequences. A user can decode
the filename/content as she wishes.
A ValueError is more appropriate because there is no issue with the
ar archive itself. Also, the old codepath never worked because the
fn parameter was missing.
Since an ar archive can contain arbitary filenames (that is a
filename can be an invalid utf-8 encoding (for instance,
"foo\xff\xffbar")), the ar module provides a bytes only API. A
user can decode filenames as she wishes.
Note: if a "fn" parameter is passed to Ar.__init__ it should be a
bytes (a str is also ok, but then be aware that an ArError's file
attribute might be a str or a bytes).
There is no need to unpack a single byte because it is not
affected by (byte) endianness (and that's what struct.unpack is
about). Moreover, rpmquery.unpack_string now supports an optional
encoding parameter, which could be used by the python3 port to
decode a string. Note: in general we cannot assume that all strings
in a rpm are utf-8 encoded (it is possible to build a rpm that
contains illegal utf-8 sequences).
With the NoPBTextMeter class the build view gets broken.
Old view:
1/11 (repo) filename
new view:
Please install the progressbar module...
Please install the progressbar module...
Please install the progressbar module...
With this commit the old behavior is restored.
The getbinaries call now lists the file he downloads instead of just
stating "Please install the progressbar module..." several times.
(but only if not called with the option quiet)
Since commit 8a6abe3a6c ("warn user
if python-progressbar is not installed") it is always safe to import
the meter module (even if the progressbar module is not installed).
On ImportError have_pb_module is false and the class NoPBTextMeter gets
returned which prints "Please install progressbar module..." on TextMeter.start()
This functions are used in the whole code and are
mandatory for the python3 support to work. In python2
case nothing is touched.
* cmp_to_key:
converts a cmp= into a key= function
* decode_list:
decodes each element of a list. This is needed if
we have a mixed list with strings and bytes.
* decode_it:
Takes the input and checks if it is not a string.
Then it uses chardet to get the encoding.
If urlgrab returns a URLError (for example if the Network is unreachable)
the for loop did not continue and the osc build aborts.
Now we also catch the URLError and try the next mirror and return False
correctly if no mirror could be reached. And then try to download it from
api
Get rid of the urlgrabber dependency. The current implementation of the
progress bar is quite "noisy" if the line length exceeds the size of
the terminal window, but that's something we could fix later. (The
superfluous error message will be fixed in a subsequent commit.)
This is useful so one can wait with a following osc prjresult until
everything done. Without this one can not know if a release job hasn't
started yet or is already finished.
* altered command do_checkout
new option -D | --deleted. Can only be used with PACKAGE and needs
-o to work
* what happens:
core function checkout_deleted_package fetches the file list of the deleted
package and saves it to given destdir. If destdir is not existent it
creates the destination directory. Otherwise the files will be written
in the existing directory.
Print error and exit if osc -A <apiurl> sr is issued on a
package with a different apiurl in its working copy. This leads
to unexpected behavior, because the SR is created for the package
apiurl, not the apiurl given by the -A command line option.
The old code could potentially yield to a use-after-free situation,
which results in UB. For this, consider the following scenario, where
osc performs several HTTPS requests (assumption: the server supports
ssl session resumption):
- HTTPS Request 1:
* a new SSL *s connection is established, which also creates a new
SSL_SESSION *ss => ss->references == 1
* once the handshake is done, the ss is put into the session cache
(see ssl_update_cache) => ss->references == 2
- osc saves the session ss in a class variable
- s is SSL_free()d, which calls SSL_SESSION_free => ss->references == 1
- HTTPS Request 2:
* setup a new SSL *s connection that reuses the saved session ss
=> ss->references == 2
* once the handshake is done, ssl_update_cache is called, which is a
NOP, because s->hit == 1 (that is, the session was resumed)
* osc saves the session ss in a class variable
* s is SSL_free()d, which calls SSL_SESSION_free => ss->references == 1
...
> 2 hours later (see tls1_default_timeout)
...
- HTTPS Request 256:
* setup a new SSL *s connection that reuses the saved session ss
=> ss->references == 2
* once the handshake is done, ssl_update_cache is called, but is
_no_ NOP anymore
* ssl_update_cache flushes the session cache (this is done every
255/256 (depending on the way we count) connections) => ss is
SSL_SESSION_free()d => ss->references == 1
* osc saves the session ss in a class variable
* s is SSL_free()d, which calls SSL_SESSION_free:
since ss->references == 1, ss is eventually free()d
- HTTPS Request 257:
* setup a new SSL *s connection that reuses the saved session ss
Since ss does not exist anymore, the remaining program execution is UB.
(Note: SSL_free(...) is _NOT_ called, if M2Crypto 0.29 is used.
M2Crypto 0.30 calls SSL_free(...) again.)
Due to a bug in OpenSSL_1_1_0h (see openssl commit 8e405776858) the
scenario from above can be triggered with exactly 2 HTTPS requests (the
SSL_SESSION is not cached, because we configured SSL_VERIFY_PEER, but
no sid_ctx was set). This is fixed in openssl commit c4fa1f7fc01.
In order to reliably reuse a session, we probably need to listen to the
session cache changes. Such callbacks could be registered via
SSL_CTX_sess_set_new_cb and/or SSL_CTX_sess_set_remove_cb, but both
functions are not provided by M2Crypto. Another idea is to directly utilize
the session cache, but this also has to be implemented in M2Crypto first.
Yet another approach is to retrieve the session via SSL_get1_session, which
increases the session's refcnt, but this also needs to be implemented in
M2Crypto first (if we choose to use this approach, we also have to make
sure that we eventually free the session manually...).
Fixes: #398 ("SIGSEGV on \"osc commit\"")
Always pass the "--statistics" option to the build script (only affects
a vm build). It is not implemented as an option, because we already have
so many of them... (see also https://github.com/openSUSE/osc/pull/412).
yet another option, but
* only very old build scripts don't know it, we should just require a recent one
* build script is ignoring it for chroot case
so why bother with another option?
Note that the diff is only shown, if it was requested before (that is
the "i" command was issued). The new behavior is consistent with the
other commands like "a", "d" etc.
Storing the error encoding in an "encoding" attribute "breaks" the
python3 "input" function: In essence, builtin_input_impl does a
getattr(sys.stdout, 'encoding'), which returns our error encoding
instead of the "real" stdout encoding. In order to avoid this, we
store the error encoding in an "_encoding" attribute.
Making SafeWriter a new-style class simplifies the code a lot.
This is a fix for issue #385. osc commit breaks due to
the use of sfilelist.findall('.//entry[@hash]')
I now will iterate through the sfilelist and use
for entry in sfilelist.findall('entry'):
if entry.get('hash'):
... execute hash code ...
This is a little bit slower, but should not break
on SLE11 anymore
Without this change, using "--alternative-project <prj>" in combination
with "--multibuild-package <flavor>" yields to unexpected results (from
a user's point of view). Note that this may break existing (artificial)
workflows (e.g., using --alternative-project to ignore the package
meta's debuginfo flag), but these workflows should be rare and there
are options to achieve the same.
Fixes: #376 ("osc build -M something does not work with
--alternative-project")
Only include a tag if it "has" text in get_request_issues. Note
that the code in get_formatted_issues always assumes the presence
of the "label" tag.
Fixes: #369 ("crash trying to view diff of a request")
The retrun at this point breaks the call, because in most
cases <prj> is not a binary. And the code always checks for the
binary first and then returns if no binary with the name <prj>
is found.
The following abstract methods are added to the PackageQueryResult
class: recommends(), suggests(), supplements(), and enhances().
Note that not all package/metadata formats have a notion of these
weak dependencies.
rpm rpmmd deb arch
recommends x x x
suggests x x x x
supplements x x
enhances x x x
(where "x" represents "supported"). In case of an unsupported weak
dependency, the implementation returns an empty list.
We need the weak dependency support in order to fix#363 ("osc build
-p ../rpms/tw doesnt send recommends to the server which makes client
side build behave differently to server side build").
There is no good reason why "--revision <rev>" and "--expand-link" or
"--revision <rev>" and "--unexpand-link" should be mutually exclusive
during an "osc up" of a package wc.
Introduce the new "--linkrev <rev>" option to specify a rev of the link
target that is used during link expansion.
In case of a pulled/linkrepair wc, it is possible that the backend
requests a hash for a tracked file, which is neither added, restored,
nor modified. For instance, this can happen if a new file was added
to the link target. Hence, for a pulled/linkrepair wc always send
the sha256 hashes of the tracked files.
This is needed for a new validation of the source server.
The source server will 'ask' for the sha256 sum of files which are new or
modified and osc calculates the sha256 sums for those files and sends them
back to the server.
The server checks the sha256 sums and if dies if something is wrong.