Use the distro module (if available) for guessing the linux distribution.
In case of python < 3.8, use the platform.linux_distribution() fallback if
no distro module is available.
Rationale: platform.linux_distribution() was dropped in python3.8
Existing passx enries resulted in a stacktrace because
the cp.get() call for the passx entries was missing.
Also added a delete_password function for ObfuscatedPasswordManager
to delete passx entries
If a python-keyring based backend is configured, but
python-keyring is not installed osc fails without giving
the user the opportunity to continue.
This introduces a new class method `create` for the AbstractCredentialsManager.
The CredentialsManagers for the backends that use a 3rd party software can
now check if the software is present in its own create method.
The error message if the call of _commit is just:
"ERROR: service run failed"
One option why this can fail is that the user Editor in env('EDITOR')
is not present.
We check now if e.msg gives a hint about "not found file" and then
error out with a better error message
building with alternative project (pac='_repository')
and multibuild did not work correctly, because the buildflavor
was not submitted to the src server.
With commit 2390823d649a3b0b6bf3b7bd07713c4426932bed in open-build-service
it is now possible to submit the build flavor like this: _repository:<flavor>
The obs commit also enables osc buildinfo --alternative-prject -M <flavor>
to show the correct buildinfo for the flavor.
There is a config option 'include_request_from_project' which
can be set to 0 to exclude all requests originating from the
project in osc [rq|review] list.
To force this behaviour just once (without always editing oscrc
the '--incoming' option can be used.
Make "osc buildinfo --alternative-project <project> ..." consistent with
"osc build --alternative-project <project> ...". This change breaks some
invocations where a build_descr is omitted (but in this case, simply
use "osc buildinfo <project> <package> <repo> <arch>).
Pass the filename to the vc script instead of passing its content via
the "-m" parameter. If "osc vc --file <fname>" is issued, it might be
possible that $EDITOR is still opened (if the "vc" script is too old),
which contradicts the --file option's help text. This "break" is acceptable
(just update osc in tandem with the vc script).
In case diff3 returns something except 0 or 1, osc errors out because the
variable merge_cmd is not defined. It used to exist, but got removed in the
past and is reintroduced via this commit.
Simplify the project sr handling in do_submitrequest a bit. It also fixes
a bug in case a target project and --separate-request is specified.
Other bugs are retained for now (for instance, --update-link is ignored).
Most of the stuff is now done in the API.
For just submitting all in one request the following is sufficient:
<action type="submit"> <source project="%s" /> %s </action>
If a target project is given it looks like this:
<action type="submit"> <source project="%s" /> <target project="%s"> %s </action>
We don't need package name or source package and targets anymore.
This is all handled by the API now.
For the --seperate-requests case the check for the entries in the linkinfo
is not working on most cases. So we handle this in the do_submitrequest
and skip the package if X-Opensuse-Errorcode is missing_action which means
basically nothing to do for this package
redesign target_project handling
* Adapt do_config to use the new credentials manager implementation
and add a --change-password option which can be used to change the
password.
* Adapt config_set_option to follow the change in do_config.
* Split selection of the credentials manager descriptor to reuse it
in do_config and interactive_config_setup.
* Introduce new ConfigMissingCredentialsError which is raised in case
of missing credentials (user or password). In this case the user will
be asked to enter the new credentials.
* 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)
Handle multiple revisions the same as a single revision in terms of what
is allowed (digit, or 32 character string [md5]). Additionally, support
either blank or "latest" to mean latest revision (None).
This allows for new revision to be specified without old revision like the
following example:
osc rdiff ... -r :17
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.