From: shuai.fu Date: Wed, 25 May 2016 07:06:41 +0000 (+0800) Subject: Update version to 0.153 (equel to github version is 0.152) X-Git-Tag: upstream/0.153.0 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=1e53d47fe9188215e3d067e171515a82437cd662;p=tools%2Fosc.git Update version to 0.153 (equel to github version is 0.152) Change-Id: I5bc643eaf2c3e4fa897ba5d2c6ec4e486232d106 Signed-off-by: shuai.fu --- diff --git a/NEWS b/NEWS index 312f290..72b941a 100644 --- a/NEWS +++ b/NEWS @@ -1,3 +1,24 @@ +0.152 + - add support searching for groups via "group:" prefix + - show possible used incident projects on "maintained" command + OBS 2.7 only: + - support buildtime source services + - support maintenance_incident requests with acceptinfo data + - support maintenance_release requests with acceptinfo data + +0.151 + - fixed shell command injection via crafted _service files (CVE-2015-0778) + - fix times when data comes from OBS backend + - support updateing the link in target package for submit requests + - various minor bugfixes + +0.150 + - support local builds using builenv (for same build environment as a former build) + - add "osc api --edit" option to be able to edit some meta files directly + - follow the request order of the api (sorting according to priorization) + - add mr --release-project option for kgraft updates + - add support for makeoriginolder in request + 0.149 - removed "--diff" option from the "createrequest" command - introduced new "vc-cmd" config option, which is used to specify the path diff --git a/README b/README index 3ea39b4..65c9951 100644 --- a/README +++ b/README @@ -1,6 +1,7 @@ osc -- opensuse-commander with svn like handling + Patches can be submitted via * mail to opensuse-buildservice@opensuse.org * Bugzilla: https://bugzilla.novell.com/enter_bug.cgi?product=openSUSE.org&component=BuildService @@ -13,7 +14,7 @@ INSTALLATION: RPM packages are here (rpm-md repository): http://download.opensuse.org/repositories/openSUSE:/Tools/ -To install from svn, do +To install from git, do python setup.py build python setup.py install diff --git a/debian/changelog b/debian/changelog index 8345d62..cd3e62d 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,12 +1,12 @@ osc (0.153.0-2) unstable; urgency=low - Update to 0.153.0 - -- shuai fu Fri, 20 May 2016 10:00:00 +0200 + -- Adrian Schroeter Wed, 18 May 2016 10:00:00 +0200 osc (0.151.0-2) unstable; urgency=low - Update to 0.151.0 - -- shuai fu Wed, 28 Feb 2016 10:00:00 +0200 + -- Adrian Schroeter Wed, 28 Jun 2012 10:00:00 +0200 osc (0.139.0-1) unstable; urgency=low - Update to 0.139.0 diff --git a/dist/complete.sh b/dist/complete.sh index 77156ad..6148b40 100644 --- a/dist/complete.sh +++ b/dist/complete.sh @@ -1,7 +1,6 @@ test -z "$BASH_VERSION" && return complete -o default _nullcommand >/dev/null 2>&1 || return complete -r _nullcommand >/dev/null 2>&1 || return -COMP_WORDBREAKS="${COMP_WORDBREAKS//:}" test -s /usr/share/osc/complete && complete -o default -C /usr/share/osc/complete osc test -s /usr/lib64/osc/complete && complete -o default -C /usr/lib64/osc/complete osc test -s /usr/lib/osc/complete && complete -o default -C /usr/lib/osc/complete osc diff --git a/dist/osc.complete b/dist/osc.complete index 173699f..903d7c5 100644 --- a/dist/osc.complete +++ b/dist/osc.complete @@ -6,7 +6,6 @@ # # usage with bash # -# COMP_WORDBREAKS="${COMP_WORDBREAKS//:}" # complete -C osc.complete osc # # Author: Werner Fink @@ -35,14 +34,19 @@ if test "/proc/$PPID/exe" -ef /bin/tcsh ; then let colon=0 else COMMAND_LINE="${COMP_LINE:0:$COMP_POINT}" -# let colon=1 let colon=0 + case "$COMP_WORDBREAKS" in + *:*) let colon=1 + esac [[ $COMMAND_LINE =~ \\: ]] && COMMAND_LINE="${COMMAND_LINE//\\:/:}" fi IFS="${IFS}=" cmdline=($COMMAND_LINE) IFS="$OIFS" -test "${cmdline[0]}" != "osc" && exit 1 +case "${cmdline[0]}" in +iosc|isc|osc) ;; +*) exit 1 +esac let last=${#COMMAND_LINE} let last-- @@ -79,24 +83,64 @@ oscprj="" oscpkg="" lnkprj="" lnkpkg="" +apiurl="" +alias="" test -s ${PWD}/.osc/_project && read -t 1 oscprj < ${PWD}/.osc/_project test -s ${PWD}/.osc/_package && read -t 1 oscpkg < ${PWD}/.osc/_package if test -s ${PWD}/.osc/_files ; then lnkprj=$(command sed -rn '/ /dev/null) +fi +if test "${cmdline[0]}" = isc ; then + alias=internal +fi + +projects=~/.osc.projects +command=osc -if test -s ~/.osc.projects ; then - typeset -i ctime=$(command date -d "$(command stat -c '%z' ~/.osc.projects)" +'%s') +case "${cmdline[1]}" in +-A|--apiurl) + if test -n "${cmdline[2]}" -a -s ~/.oscrc ; then + hints=($(sed -rn '/^(aliases=|\[http)/{s/,/ /g;s/(aliases=|\[|\])//gp}' < ~/.oscrc 2> /dev/null)) + for h in ${hints[@]} ; do + case "$h" in + http*) + tmp=$(sed -rn '\@^\['${h}'@,\@=@{\@^aliases=@{s@[^=]+=([^,]+),.*@\1@p};}' < ~/.oscrc 2> /dev/null) + if test "${cmdline[2]}" = "$h" ; then + alias=$tmp + break + fi + ;; + *) + if test "${cmdline[2]}" = "$h" ; then + alias=$h + break + fi + esac + done + fi +esac + +if test -n "$alias" ; then + projects="${projects}.${alias}" + command="$command -A $alias" +fi + +if test -s "${projects}" ; then + typeset -i ctime=$(command date -d "$(command stat -c '%z' ${projects})" +'%s') typeset -i now=$(command date -d now +'%s') if ((now - ctime > 86400)) ; then - if tmp=$(mktemp ~/.osc.projects.XXXXXX) ; then - command osc ls / >| $tmp - mv -uf $tmp ~/.osc.projects + if tmp=$(mktemp ${projects}.XXXXXX) ; then + command ${command} ls / >| $tmp + mv -uf $tmp ${projects} fi fi else - command osc ls / >| ~/.osc.projects + command ${command} ls / >| "${projects}" fi projects () @@ -104,7 +148,7 @@ projects () local -a list local -a argv local -i argc=0 - local arg + local arg cur for arg; do if test $arg == "--" ; then let argc++ @@ -113,15 +157,18 @@ projects () argv[argc++]=$arg done shift $argc - if test -n "$1" ; then - list=($(command grep -E "^$1" ~/.osc.projects)) + cur="$1" + if test -n "${cur}" ; then + list=($(command grep -E "^${cur}" ${projects})) else - list=($(command cat ~/.osc.projects)) + list=($(command cat ${projects})) fi if ((colon)) ; then - builtin compgen -W "${list[*]}" "$1"|sed -r 's@([^\\]):@\1\\:@g' + local colon_word + colon_word=${cur%${cur##*:}} + builtin compgen -W "${list[*]}" -- "${cur}" | sed -r "s@^${colon_word}@@g" else - builtin compgen -W "${list[*]}" -- ${1+"$@"} + builtin compgen -W "${list[*]}" -- "${cur}" fi } @@ -130,7 +177,7 @@ packages () local -a list local -a argv local -i argc=0 - local arg + local arg cur for arg; do if test $arg == "--" ; then let argc++ @@ -139,12 +186,13 @@ packages () argv[argc++]=$arg done shift $argc - if test -n "$1" ; then - list=($(command osc ls ${argv[@]}|command grep -E "^$1")) + cur="$1" + if test -n "${cur}" ; then + list=($(command ${command} ls ${argv[@]}|command grep -E "^${cur}")) else - list=($(command osc ls ${argv[@]})) + list=($(command ${command} ls ${argv[@]})) fi - builtin compgen -W "${list[*]}" -- ${1+"$@"} + builtin compgen -W "${list[*]}" -- "${cur}" } repositories () @@ -162,11 +210,11 @@ repositories () done shift $argc if test -n "$1" ; then - list=($(command osc meta prj ${argv[@]}|\ + list=($(command ${command} meta prj ${argv[@]}|\ command sed -rn '//{s@^\s*(.*)@\1@p}'|\ command sort -u|command grep -E "^$1")) else - list=($(command osc meta prj ${argv[@]}|\ + list=($(command ${command} meta prj ${argv[@]}|\ command sed -rn '//{s@^\s*(.*)@\1@p}'|\ command sort -u)) fi @@ -223,8 +271,8 @@ targets () users () { - if test -s ~/.osc.projects ; then - command sed -rn "/^home:$1/{ s/^home:([^:]*):.*/\1/p}" ~/.osc.projects|command sort -u + if test -s ${projects} ; then + command sed -rn "/^home:$1/{ s/^home:([^:]*):.*/\1/p}" ${projects}|command sort -u elif test -s ~/.oscrc; then command sed -rn '/^(user=)/{s/(user=)//p}' ~/.oscrc|command sort -u else @@ -350,7 +398,7 @@ add|addremove|ar) fi ;; build) - opts=(--help --oldpackages --disable-cpio-bulk-download --download-api-only --release --baselibs + opts=(--help --oldpackages --disable-cpio-bulk-download --release --baselibs --disable-debuginfo --debuginfo --alternative-project --vm-type --linksources --local-package --build-uid --userootforbuild --define --without --with --ccache --icecream --jobs --root --extra-pkgs --keep-pkgs --prefer-pkgs @@ -437,9 +485,8 @@ build) done fi if ((count == 2)) ; then - specs=($(command ls *.spec 2>/dev/null)) - images=($(command ls *.kiwi 2>/dev/null)) - builtin compgen -W "${opts[*]} ${specs[*]} ${images[*]}" -- "${cmdline[count]}" + specs=($(command ls *.spec)) + builtin compgen -W "${opts[*]} ${specs[*]}" -- "${cmdline[count]}" fi ;; branch|getpac|bco|branchco) diff --git a/osc-wrapper.py b/osc-wrapper.py index 820473f..833729e 100755 --- a/osc-wrapper.py +++ b/osc-wrapper.py @@ -5,6 +5,7 @@ import locale import sys +import os from osc import commandline, babysitter @@ -21,6 +22,20 @@ except NameError: #reload, neither setdefaultencoding are in python3 pass +# avoid buffering output on pipes (bnc#930137) +# Basically, a "print('foo')" call is translated to a corresponding +# fwrite call that writes to the stdout stream (cf. string_print +# (Objects/stringobject.c) and builtin_print (Python/bltinmodule.c)); +# If no pipe is used, stdout is a tty/refers to a terminal => +# the stream is line buffered (see _IO_file_doallocate (libio/filedoalloc.c)). +# If a pipe is used, stdout does not refer to a terminal anymore => +# the stream is fully buffered by default (see _IO_file_doallocate). +# The following fdopen call makes stdout line buffered again (at least on +# systems that support setvbuf - if setvbuf is not supported, the stream +# remains fully buffered (see PyFile_SetBufSize (Objects/fileobject.c))). +if not os.isatty(sys.stdout.fileno()): + sys.stdout = os.fdopen(sys.stdout.fileno(), sys.stdout.mode, 1) + osccli = commandline.Osc() r = babysitter.run(osccli) diff --git a/osc.fish b/osc.fish new file mode 100644 index 0000000..09dac9d --- /dev/null +++ b/osc.fish @@ -0,0 +1,116 @@ +# fish completion for git +# vim: smartindent:expandtab:ts=2:sw=2 + +function __fish_osc_needs_command + set cmd (commandline -opc) + if contains "$cmd" 'osc' 'osc help' + return 0 + end + return 1 +end + +function __fish_osc_using_command + set cmd (commandline -opc) + if [ (count $cmd) -gt 1 ] + for arg in $argv + if [ $arg = $cmd[2] ] + return 0 + end + end + end + return 1 +end + +# general options +complete -f -c osc -n 'not __fish_osc_needs_command' -s A -l apiurl -d 'specify URL to access API server at or an alias' +complete -f -c osc -n 'not __fish_osc_needs_command' -s c -l config -d 'specify alternate configuration file' +complete -f -c osc -n 'not __fish_osc_needs_command' -s d -l debug -d 'print info useful for debugging' +complete -f -c osc -n 'not __fish_osc_needs_command' -l debugger -d 'jump into the debugger before executing anything' +complete -f -c osc -n 'not __fish_osc_needs_command' -s h -l help -d 'show this help message and exit' +complete -f -c osc -n 'not __fish_osc_needs_command' -s H -l http-debug -d 'debug HTTP traffic (filters some headers)' +complete -f -c osc -n 'not __fish_osc_needs_command' -l http-full-debug -d 'debug HTTP traffic (filters no headers)' +complete -f -c osc -n 'not __fish_osc_needs_command' -l no-gnome-keyring -d 'disable usage of GNOME Keyring' +complete -f -c osc -n 'not __fish_osc_needs_command' -l no-keyring -d 'disable usage of desktop keyring system' +complete -f -c osc -n 'not __fish_osc_needs_command' -l post-mortem -d 'jump into the debugger in case of errors' +complete -f -c osc -n 'not __fish_osc_needs_command' -s q -l quiet -d 'be quiet, not verbose' +complete -f -c osc -n 'not __fish_osc_needs_command' -s t -l traceback -d 'print call trace in case of errors' +complete -f -c osc -n 'not __fish_osc_needs_command' -s v -l verbose -d 'increase verbosity' +complete -f -c osc -n 'not __fish_osc_needs_command' -l version -d 'show program\'s version number and exit' + +# osc commands +complete -f -c osc -n '__fish_osc_needs_command' -a 'add' -d 'Mark files to be added upon the next commit' +complete -f -c osc -n '__fish_osc_needs_command' -a 'addremove ar' -d 'Adds new files, removes disappeared files' +complete -f -c osc -n '__fish_osc_needs_command' -a 'aggregatepac' -d '"Aggregate" a package to another package' +complete -f -c osc -n '__fish_osc_needs_command' -a 'api' -d 'Issue an arbitrary request to the API' +complete -f -c osc -n '__fish_osc_needs_command' -a 'branch bco branchco getpac' -d 'Branch a package' +complete -f -c osc -n '__fish_osc_needs_command' -a 'chroot' -d 'into the buildchroot' +complete -f -c osc -n '__fish_osc_needs_command' -a 'clean' -d 'removes all untracked files from the package working ...' +complete -f -c osc -n '__fish_osc_needs_command' -a 'commit checkin ci' -d 'Upload content to the repository server' +complete -f -c osc -n '__fish_osc_needs_command' -a 'config' -d 'get/set a config option' +complete -f -c osc -n '__fish_osc_needs_command' -a 'copypac' -d 'Copy a package' +complete -f -c osc -n '__fish_osc_needs_command' -a 'createincident' -d 'Create a maintenance incident' +complete -f -c osc -n '__fish_osc_needs_command' -a 'createrequest creq' -d 'create multiple requests with a single command' +complete -f -c osc -n '__fish_osc_needs_command' -a 'delete del remove rm' -d 'Mark files or package directories to be deleted upon ...' +complete -f -c osc -n '__fish_osc_needs_command' -a 'deleterequest deletereq dr dropreq droprequest' -d 'Request to delete (or "drop") a package or project' +complete -f -c osc -n '__fish_osc_needs_command' -a 'dependson whatdependson' -d 'Show the build dependencies' +complete -f -c osc -n '__fish_osc_needs_command' -a 'detachbranch' -d 'replace a link with its expanded sources' +complete -f -c osc -n '__fish_osc_needs_command' -a 'develproject bsdevelproject dp' -d 'print the devel project / package of a package' +complete -f -c osc -n '__fish_osc_needs_command' -a 'diff di ldiff linkdiff' -d 'Generates a diff' +complete -f -c osc -n '__fish_osc_needs_command' -a 'distributions dists' -d 'Shows all available distributions' +complete -f -c osc -n '__fish_osc_needs_command' -a 'getbinaries' -d 'Download binaries to a local directory' +complete -f -c osc -n '__fish_osc_needs_command' -a 'help ? h' -d 'give detailed help on a specific sub-command' +complete -f -c osc -n '__fish_osc_needs_command' -a 'importsrcpkg' -d 'Import a new package from a src.rpm' +complete -f -c osc -n '__fish_osc_needs_command' -a 'info' -d 'Print information about a working copy' +complete -f -c osc -n '__fish_osc_needs_command' -a 'init' -d 'Initialize a directory as working copy' +complete -f -c osc -n '__fish_osc_needs_command' -a 'jobhistory jobhist' -d 'Shows the job history of a project' +complete -f -c osc -n '__fish_osc_needs_command' -a 'linkpac' -d '"Link" a package to another package' +complete -f -c osc -n '__fish_osc_needs_command' -a 'linktobranch' -d 'Convert a package containing a classic link with patc...' +complete -f -c osc -n '__fish_osc_needs_command' -a 'list LL lL ll ls' -d 'List sources or binaries on the server' +complete -f -c osc -n '__fish_osc_needs_command' -a 'localbuildlog lbl' -d 'Shows the build log of a local buildchroot' +complete -f -c osc -n '__fish_osc_needs_command' -a 'log' -d 'Shows the commit log of a package' +complete -f -c osc -n '__fish_osc_needs_command' -a 'maintainer bugowner' -d 'Show maintainers according to server side configuration' +complete -f -c osc -n '__fish_osc_needs_command' -a 'maintenancerequest mr' -d 'Create a request for starting a maintenance incident.' +complete -f -c osc -n '__fish_osc_needs_command' -a 'man' -d 'generates a man page' +complete -f -c osc -n '__fish_osc_needs_command' -a 'mbranch maintained sm' -d 'Search or banch multiple instances of a package' +complete -f -c osc -n '__fish_osc_needs_command' -a 'meta' -d 'Show meta information, or edit it' +complete -f -c osc -n '__fish_osc_needs_command' -a 'mkpac' -d 'Create a new package under version control' +complete -f -c osc -n '__fish_osc_needs_command' -a 'mv' -d 'Move SOURCE file to DEST and keep it under version co...' +complete -f -c osc -n '__fish_osc_needs_command' -a 'my' -d 'show waiting work, packages, projects or requests inv...' +complete -f -c osc -n '__fish_osc_needs_command' -a 'patchinfo' -d 'Generate and edit a patchinfo file.' +complete -f -c osc -n '__fish_osc_needs_command' -a 'pdiff' -d 'Quick alias to diff the content of a package with its...' +complete -f -c osc -n '__fish_osc_needs_command' -a 'prdiff projdiff projectdiff' -d 'Server-side diff of two projects' +complete -f -c osc -n '__fish_osc_needs_command' -a 'prjresults pr' -d 'Shows project-wide build results' +complete -f -c osc -n '__fish_osc_needs_command' -a 'pull' -d 'merge the changes of the link target into your workin...' +complete -f -c osc -n '__fish_osc_needs_command' -a 'rdelete' -d 'Delete a project or packages on the server.' +complete -f -c osc -n '__fish_osc_needs_command' -a 'rdiff' -d 'Server-side "pretty" diff of two packages' +complete -f -c osc -n '__fish_osc_needs_command' -a 'rebuild rebuildpac' -d 'Trigger package rebuilds' +complete -f -c osc -n '__fish_osc_needs_command' -a 'release' -d 'Release sources and binaries' +complete -f -c osc -n '__fish_osc_needs_command' -a 'releaserequest' -d 'Create a request for releasing a maintenance update.' +complete -f -c osc -n '__fish_osc_needs_command' -a 'remotebuildlog rbl rblt rbuildlog rbuildlogtail remotebuildlogtail' -d 'Shows the build log of a package' +complete -f -c osc -n '__fish_osc_needs_command' -a 'repairlink' -d 'Repair a broken source link' +complete -f -c osc -n '__fish_osc_needs_command' -a 'repairwc' -d 'try to repair an inconsistent working copy' +complete -f -c osc -n '__fish_osc_needs_command' -a 'repositories platforms repos' -d 'shows repositories configured for a project. It skips...' +complete -f -c osc -n '__fish_osc_needs_command' -a 'repourls' -d 'Shows URLs of .repo files' +complete -f -c osc -n '__fish_osc_needs_command' -a 'request review rq' -d 'Show or modify requests and reviews' +complete -f -c osc -n '__fish_osc_needs_command' -a 'requestmaintainership reqbs reqbugownership reqmaintainership reqms requestbugownership' -d 'requests to add user as maintainer or bugowner' +complete -f -c osc -n '__fish_osc_needs_command' -a 'resolved' -d 'Remove "conflicted" state on working copy files' +complete -f -c osc -n '__fish_osc_needs_command' -a 'restartbuild abortbuild' -d 'Restart the build of a certain project or package' +complete -f -c osc -n '__fish_osc_needs_command' -a 'results r' -d 'Shows the build results of a package or project' +complete -f -c osc -n '__fish_osc_needs_command' -a 'revert' -d 'Restore changed files or the entire working copy.' +complete -f -c osc -n '__fish_osc_needs_command' -a 'rremove' -d 'Remove source files from selected package' +complete -f -c osc -n '__fish_osc_needs_command' -a 'search bse se' -d 'Search for a project and/or package.' +complete -f -c osc -n '__fish_osc_needs_command' -a 'service' -d 'Handle source services' +complete -f -c osc -n '__fish_osc_needs_command' -a 'setdevelproject sdp' -d 'Set the devel project / package of a package' +complete -f -c osc -n '__fish_osc_needs_command' -a 'setlinkrev' -d 'Updates a revision number in a source link.' +complete -f -c osc -n '__fish_osc_needs_command' -a 'signkey' -d 'Manage Project Signing Key' +complete -f -c osc -n '__fish_osc_needs_command' -a 'status st' -d 'Show status of files in working copy' +complete -f -c osc -n '__fish_osc_needs_command' -a 'submitrequest sr submitpac submitreq' -d 'Create request to submit source into another Project' +complete -f -c osc -n '__fish_osc_needs_command' -a 'token' -d 'Show and manage authentication token' +complete -f -c osc -n '__fish_osc_needs_command' -a 'triggerreason tr' -d 'Show reason why a package got triggered to build' +complete -f -c osc -n '__fish_osc_needs_command' -a 'undelete' -d 'Restores a deleted project or package on the server.' +complete -f -c osc -n '__fish_osc_needs_command' -a 'unlock' -d 'Unlocks a project or package' +complete -f -c osc -n '__fish_osc_needs_command' -a 'update up' -d 'Update a working copy' +complete -f -c osc -n '__fish_osc_needs_command' -a 'updatepacmetafromspec metafromspec updatepkgmetafromspec' -d 'Update package meta information from a specfile' +complete -f -c osc -n '__fish_osc_needs_command' -a 'vc' -d 'Edit the changes file' +complete -f -c osc -n '__fish_osc_needs_command' -a 'whois user who' -d 'Show fullname and email of a buildservice user' +complete -f -c osc -n '__fish_osc_needs_command' -a 'wipebinaries' -d 'Delete all binary packages of a certain project/package' diff --git a/osc/build.py b/osc/build.py index 994b1b9..b2fe44c 100644 --- a/osc/build.py +++ b/osc/build.py @@ -66,7 +66,7 @@ can_also_build = { 'armv5tel': [ 'armv4l', 'armv5el', 'armv5tel' ], 's390x': ['s390' ], 'ppc64': [ 'ppc', 'ppc64', 'ppc64p7', 'ppc64le' ], - 'ppc64le': [ 'ppc64le' ], + 'ppc64le': [ 'ppc64le', 'ppc64' ], 'i586': [ 'i386' ], 'i686': [ 'i586', 'i386' ], 'x86_64': ['i686', 'i586', 'i386' ], @@ -179,7 +179,7 @@ class Pac: self.mp = {} for i in ['binary', 'package', - 'epoch', 'version', 'release', + 'epoch', 'version', 'release', 'hdrmd5', 'project', 'repository', 'preinstall', 'vminstall', 'noinstall', 'installonly', 'runscripts', ]: @@ -211,13 +211,15 @@ class Pac: self.mp['apiurl'] = apiurl if pacsuffix == 'deb': - filename = debquery.DebQuery.filename(self.mp['name'], self.mp['epoch'], self.mp['version'], self.mp['release'], self.mp['arch']) + canonname = debquery.DebQuery.filename(self.mp['name'], self.mp['epoch'], self.mp['version'], self.mp['release'], self.mp['arch']) elif pacsuffix == 'arch': - filename = archquery.ArchQuery.filename(self.mp['name'], self.mp['epoch'], self.mp['version'], self.mp['release'], self.mp['arch']) + canonname = archquery.ArchQuery.filename(self.mp['name'], self.mp['epoch'], self.mp['version'], self.mp['release'], self.mp['arch']) else: - filename = rpmquery.RpmQuery.filename(self.mp['name'], self.mp['epoch'], self.mp['version'], self.mp['release'], self.mp['arch']) + canonname = rpmquery.RpmQuery.filename(self.mp['name'], self.mp['epoch'], self.mp['version'], self.mp['release'], self.mp['arch']) - self.mp['filename'] = node.get('binary') or filename + self.mp['canonname'] = canonname + # maybe we should rename filename key to binary + self.mp['filename'] = node.get('binary') or canonname if self.mp['repopackage'] == '_repository': self.mp['repofilename'] = self.mp['name'] else: @@ -238,7 +240,7 @@ class Pac: # or if-modified-since, so the caching is simply name-based (on the assumption # that the filename is suitable as identifier) self.localdir = '%s/%s/%s/%s' % (cachedir, self.project, self.repository, self.arch) - self.fullfilename = os.path.join(self.localdir, self.filename) + self.fullfilename = os.path.join(self.localdir, self.canonname) self.url_local = 'file://%s' % self.fullfilename # first, add the local URL @@ -317,9 +319,9 @@ def get_repo(path): return repositoryDirectory -def get_prefer_pkgs(dirs, wanted_arch, type): +def get_prefer_pkgs(dirs, wanted_arch, type, cpio): import glob - from .util import repodata, packagequery, cpio + from .util import repodata, packagequery paths = [] repositories = [] @@ -346,7 +348,9 @@ def get_prefer_pkgs(dirs, wanted_arch, type): packageQueries.add(packageQuery) for path in paths: - if path.endswith('src.rpm'): + if path.endswith('.src.rpm') or path.endswith('.nosrc.rpm'): + continue + if path.endswith('.patch.rpm') or path.endswith('.delta.rpm'): continue if path.find('-debuginfo-') > 0: continue @@ -357,21 +361,27 @@ def get_prefer_pkgs(dirs, wanted_arch, type): for name, packageQuery in packageQueries.items()) depfile = create_deps(packageQueries.values()) - cpio = cpio.CpioWrite() cpio.add('deps', '\n'.join(depfile)) - return prefer_pkgs, cpio + return prefer_pkgs def create_deps(pkgqs): """ - creates a list of requires/provides which corresponds to build's internal + creates a list of dependencies which corresponds to build's internal dependency file format """ depfile = [] for p in pkgqs: id = '%s.%s-0/0/0: ' % (p.name(), p.arch()) - depfile.append('R:%s%s' % (id, ' '.join(p.requires()))) depfile.append('P:%s%s' % (id, ' '.join(p.provides()))) + depfile.append('R:%s%s' % (id, ' '.join(p.requires()))) + d = p.conflicts() + if d: + depfile.append('C:%s%s' % (id, ' '.join(d))) + d = p.obsoletes() + if d: + depfile.append('O:%s%s' % (id, ' '.join(d))) + depfile.append('I:%s%s-%s 0-%s' % (id, p.name(), p.evr(), p.arch())) return depfile @@ -436,6 +446,8 @@ def main(apiurl, opts, argv): build_root = opts.root if opts.target: buildargs.append('--target=%s' % opts.target) + if opts.threads: + buildargs.append('--threads=%s' % opts.threads) if opts.jobs: buildargs.append('--jobs=%s' % opts.jobs) elif config['build-jobs'] > 1: @@ -558,11 +570,41 @@ def main(apiurl, opts, argv): s += "%%define %s\n" % i build_descr_data = s + build_descr_data + cpiodata = None + servicefile = os.path.join(os.path.dirname(build_descr), "_service") + if not os.path.isfile(servicefile): + servicefile = os.path.join(os.path.dirname(build_descr), "_service") + if not os.path.isfile(servicefile): + servicefile = None + else: + print('Using local _service file') + buildenvfile = os.path.join(os.path.dirname(build_descr), "_buildenv." + repo + "." + arch) + if not os.path.isfile(buildenvfile): + buildenvfile = os.path.join(os.path.dirname(build_descr), "_buildenv") + if not os.path.isfile(buildenvfile): + buildenvfile = None + else: + print('Using local buildenv file: %s' % os.path.basename(buildenvfile)) + if buildenvfile or servicefile: + from .util import cpio + if not cpiodata: + cpiodata = cpio.CpioWrite() + if opts.prefer_pkgs: print('Scanning the following dirs for local packages: %s' % ', '.join(opts.prefer_pkgs)) - prefer_pkgs, cpio = get_prefer_pkgs(opts.prefer_pkgs, arch, build_type) - cpio.add(os.path.basename(build_descr), build_descr_data) - build_descr_data = cpio.get() + from .util import cpio + if not cpiodata: + cpiodata = cpio.CpioWrite() + prefer_pkgs = get_prefer_pkgs(opts.prefer_pkgs, arch, build_type, cpiodata) + + if cpiodata: + cpiodata.add(os.path.basename(build_descr), build_descr_data) + # buildenv must come last for compatibility reasons... + if buildenvfile: + cpiodata.add("buildenv", open(buildenvfile).read()) + if servicefile: + cpiodata.add("_service", open(servicefile).read()) + build_descr_data = cpiodata.get() # special handling for overlay and rsync-src/dest specialcmdopts = [] @@ -725,8 +767,9 @@ def main(apiurl, opts, argv): enable_cpio = not opts.disable_cpio_bulk_download, cookiejar=cookiejar) - # implicitly trust the project we are building for - check_trusted_projects(apiurl, [ i for i in bi.projects.keys() if not i == prj ]) + if not opts.trust_all_projects: + # implicitly trust the project we are building for + check_trusted_projects(apiurl, [ i for i in bi.projects.keys() if not i == prj ]) # now update the package cache fetcher.run(bi) @@ -765,8 +808,9 @@ def main(apiurl, opts, argv): """ temporary directory that removes itself""" def __init__(self, *args, **kwargs): self.name = mkdtemp(*args, **kwargs) + _rmtree = staticmethod(shutil.rmtree) def cleanup(self): - shutil.rmtree(self.name) + self._rmtree(self.name) def __del__(self): self.cleanup() def __exit__(self): @@ -910,6 +954,17 @@ def main(apiurl, opts, argv): else: print('WARNING: unknown packages get not verified, they can compromise your system !') + for i in bi.deps: + if i.hdrmd5: + from .util import packagequery + hdrmd5 = packagequery.PackageQuery.queryhdrmd5(i.fullfilename) + if not hdrmd5: + print("Error: cannot get hdrmd5 for %s" % i.fullfilename) + sys.exit(1) + if hdrmd5 != i.hdrmd5: + print("Error: hdrmd5 mismatch for %s: %s != %s" % (i.fullfilename, hdrmd5, i.hdrmd5)) + sys.exit(1) + print('Writing build configuration') if build_type == 'kiwi': @@ -951,7 +1006,7 @@ def main(apiurl, opts, argv): my_build_swap = build_root + '/swap' vm_options = [ '--vm-type=%s' % vm_type ] - if vm_type != 'lxc' and vm_type != 'emulator': + if vm_type != 'lxc': vm_options += [ '--vm-disk=' + my_build_device ] vm_options += [ '--vm-swap=' + my_build_swap ] vm_options += [ '--logfile=%s/.build.log' % build_root ] @@ -959,6 +1014,11 @@ def main(apiurl, opts, argv): if os.access(build_root, os.W_OK) and os.access('/dev/kvm', os.W_OK): # so let's hope there's also an fstab entry need_root = False + if config['build-kernel']: + vm_options += [ '--vm-kernel=' + config['build-kernel'] ] + if config['build-initrd']: + vm_options += [ '--vm-initrd=' + config['build-initrd'] ] + build_root += '/.mount' if config['build-memory']: diff --git a/osc/cmdln.py b/osc/cmdln.py index d9abf64..da49ce6 100644 --- a/osc/cmdln.py +++ b/osc/cmdln.py @@ -393,47 +393,63 @@ class RawCmdln(cmd.Cmd): """ self.cmdlooping = True self.preloop() - if intro is None: - intro = self.intro - if intro: - intro_str = self._str(intro) - self.stdout.write(intro_str+'\n') - self.stop = False - retval = None - while not self.stop: - if self.cmdqueue: - argv = self.cmdqueue.pop(0) - assert isinstance(argv, (list, tuple)), \ - "item on 'cmdqueue' is not a sequence: %r" % argv - else: - if self.use_rawinput: - try: - try: - #python 2.x - line = raw_input(self._prompt_str) - except NameError: - line = input(self._prompt_str) - except EOFError: - line = 'EOF' + if self.use_rawinput and self.completekey: + try: + import readline + self.old_completer = readline.get_completer() + readline.set_completer(self.complete) + readline.parse_and_bind(self.completekey+": complete") + except ImportError: + pass + try: + if intro is None: + intro = self.intro + if intro: + intro_str = self._str(intro) + self.stdout.write(intro_str+'\n') + self.stop = False + retval = None + while not self.stop: + if self.cmdqueue: + argv = self.cmdqueue.pop(0) + assert isinstance(argv, (list, tuple)), \ + "item on 'cmdqueue' is not a sequence: %r" % argv else: - self.stdout.write(self._prompt_str) - self.stdout.flush() - line = self.stdin.readline() - if not len(line): - line = 'EOF' + if self.use_rawinput: + try: + try: + #python 2.x + line = raw_input(self._prompt_str) + except NameError: + line = input(self._prompt_str) + except EOFError: + line = 'EOF' else: - line = line[:-1] # chop '\n' - argv = line2argv(line) - try: - argv = self.precmd(argv) - retval = self.onecmd(argv) - self.postcmd(argv) - except: - if not self.cmdexc(argv): - raise - retval = 1 - self.lastretval = retval - self.postloop() + self.stdout.write(self._prompt_str) + self.stdout.flush() + line = self.stdin.readline() + if not len(line): + line = 'EOF' + else: + line = line[:-1] # chop '\n' + argv = line2argv(line) + try: + argv = self.precmd(argv) + retval = self.onecmd(argv) + self.postcmd(argv) + except: + if not self.cmdexc(argv): + raise + retval = 1 + self.lastretval = retval + self.postloop() + finally: + if self.use_rawinput and self.completekey: + try: + import readline + readline.set_completer(self.old_completer) + except ImportError: + pass self.cmdlooping = False return retval diff --git a/osc/commandline.py b/osc/commandline.py index 607b494..281d0eb 100644 --- a/osc/commandline.py +++ b/osc/commandline.py @@ -47,7 +47,7 @@ For additional information, see * http://en.opensuse.org/openSUSE:Build_Service_Tutorial * http://en.opensuse.org/openSUSE:OSC .PP -You can modify osc commands, or roll you own, via the plugin API: +You can modify osc commands, or roll your own, via the plugin API: * http://en.opensuse.org/openSUSE:OSC_plugins .SH AUTHOR osc was written by several authors. This man page is automatically generated. @@ -67,7 +67,7 @@ class Osc(cmdln.Cmdln): * http://en.opensuse.org/openSUSE:Build_Service_Tutorial * http://en.opensuse.org/openSUSE:OSC - You can modify osc commands, or roll you own, via the plugin API: + You can modify osc commands, or roll your own, via the plugin API: * http://en.opensuse.org/openSUSE:OSC_plugins """ name = 'osc' @@ -693,13 +693,13 @@ class Osc(cmdln.Cmdln): osc meta prj PRJ osc meta pkg PRJ PKG osc meta pkg PRJ PKG -e - osc meta attribute PRJ [PKG [SUBPACKAGE]] [--attribute ATTRIBUTE] [--create|--delete|--set [value_list]] Usage: - osc meta ARGS... - osc meta -e|--edit ARGS... - osc meta -F|--file ARGS... + osc meta ARGS... + osc meta -e|--edit ARGS... + osc meta -F|--file ARGS... osc meta pattern --delete PRJ PATTERN + osc meta attribute PRJ [PKG [SUBPACKAGE]] [--attribute ATTRIBUTE] [--create|--delete|--set [value_list]] ${cmd_option_list} """ @@ -948,6 +948,8 @@ class Osc(cmdln.Cmdln): help='never remove source package on accept, but update its content') @cmdln.option('--no-update', action='store_true', help='never touch source package on accept (will break source links)') + @cmdln.option('--update-link', action='store_true', + help='This transfers the source including the _link file.') @cmdln.option('-d', '--diff', action='store_true', help='show diff only instead of creating the actual request') @cmdln.option('--yes', action='store_true', @@ -1026,9 +1028,12 @@ class Osc(cmdln.Cmdln): sr_ids = [] # for single request actionxml = "" - options_block = "" + options_block = "" if src_update: - options_block = """%s """ % (src_update) + options_block += """%s""" % (src_update) + if opts.update_link: + options_block + """true """ + options_block += "" # loop via all packages for checking their state for p in meta_get_packagelist(apiurl, project): @@ -1242,7 +1247,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. result = create_submit_request(apiurl, src_project, src_package, dst_project, dst_package, - opts.message, orev=rev, src_update=src_update) + opts.message, orev=rev, + src_update=src_update, dst_updatelink=opts.update_link) if supersede_existing: for req in reqs: change_request_state(apiurl, req.reqid, 'superseded', @@ -1742,10 +1748,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-m', '--message', metavar='TEXT', help='specify message TEXT') - @cmdln.option('-r', '--repository', metavar='TEXT', - help='specify message TEXT') - @cmdln.option('--accept-in-hours', metavar='TEXT', - help='specify message time when request shall get accepted automatically. Only works with write permissions in target.') + @cmdln.option('-r', '--repository', metavar='REPOSITORY', + help='specify repository') + @cmdln.option('--accept-in-hours', metavar='HOURS', + help='specify time when request shall get accepted automatically. Only works with write permissions in target.') @cmdln.alias("dr") @cmdln.alias("dropreq") @cmdln.alias("droprequest") @@ -2150,7 +2156,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. print('No results') return - results.sort(reverse=True) + # we must not sort the results here, since the api is doing it already "the right way" days = opts.days or conf.config['request_list_days'] since = '' try: @@ -2230,8 +2236,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. except HTTPError as e: # for OBS 2.0 and before sr_actions = r.get_actions('submit') - if not sr_actions: - raise oscerr.WrongOptions('\'--diff\' not possible (request has no \'submit\' actions)') + if not r.get_actions('submit') and not r.get_actions('maintenance_incident') and not r.get_actions('maintenance_release'): + raise oscerr.WrongOptions('\'--diff\' not possible (request has no supported actions)') for action in sr_actions: diff += 'old: %s/%s\nnew: %s/%s\n' % (action.src_project, action.src_package, action.tgt_project, action.tgt_package) @@ -2910,6 +2916,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. help='Use this attribute to find default maintenance project (default is OBS:MaintenanceProject)') @cmdln.option('-m', '--message', metavar='TEXT', help='specify message TEXT') + @cmdln.option('--release-project', metavar='RELEASEPROJECT', + help='Specify the release project') @cmdln.option('--no-cleanup', action='store_true', help='do not remove source project on accept') @cmdln.option('--cleanup', action='store_true', @@ -2933,6 +2941,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. osc maintenancerequest [ SOURCEPROJECT [ SOURCEPACKAGES RELEASEPROJECT ] ] ${cmd_option_list} """ + #FIXME: the follow syntax would make more sense and would obsolete the --release-project parameter + # but is incompatible with the current one + # osc maintenancerequest [ SOURCEPROJECT [ RELEASEPROJECT [ SOURCEPACKAGES ] ] args = slash_split(args) apiurl = self.get_api_url() @@ -2961,6 +2972,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. if source_project.startswith(default_branch): opt_sourceupdate = 'cleanup' + if opts.release_project: + release_project = opts.release_project + if opts.incident_project: target_project = opts.incident_project else: @@ -3048,7 +3062,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. if opts.dryrun: for r in result.findall('package'): - print("%s/%s"%(r.get('project'), r.get('package'))) + line="%s/%s"%(r.get('project'), r.get('package')) + for d in r.findall('devel'): + line+=" using sources from %s/%s"%(d.get('project'), d.get('package')) + print(line) return apiopt = '' @@ -3304,6 +3321,33 @@ Please submit there instead, or use --nodevelproject to force direct submission. delete_project(apiurl, prj, opts.force, msg) + def do_lock(self, subcmd, opts, project, package=None): + """${cmd_name}: Locks a project or package. + + usage: + osc lock PROJECT [PACKAGE] + + ${cmd_option_list} + """ + apiurl = self.get_api_url() + kind = 'prj' + path_args = (project,) + if package is not None: + kind = 'pkg' + path_args = (project, package) + meta = meta_exists(kind, path_args, create_new=False, apiurl=apiurl) + root = ET.fromstring(''.join(meta)) + if root.find('lock') is not None: + print('Already locked', file=sys.stderr) + sys.exit(1) + # alternatively, we could also use the set_flag api call + # instead of manually manipulating the xml + lock = ET.SubElement(root, 'lock') + ET.SubElement(lock, 'enable') + meta = ET.tostring(root) + edit_meta(kind, path_args=path_args, data=meta) + + @cmdln.option('-m', '--message', metavar='TEXT', help='specify log message TEXT') def do_unlock(self, subcmd, opts, *args): @@ -3937,8 +3981,12 @@ Please submit there instead, or use --nodevelproject to force direct submission. else: raise oscerr.WrongArgs('Wrong number of arguments') - # XXX: API should somehow tell that - url_tmpl = 'http://download.opensuse.org/repositories/%s/%s/%s.repo' + root = ET.fromstring(''.join(show_configuration(apiurl))) + elm = root.find('download_url') + if elm is None or not elm.text: + raise oscerr.APIError('download_url configuration element expected') + + url_tmpl = elm.text + '/%s/%s/%s.repo' repos = get_repositories_of_project(apiurl, project) for repo in repos: print(url_tmpl % (project.replace(':', ':/'), repo, project)) @@ -4131,6 +4179,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. 'M' Modified '?' item is not under version control '!' item is missing (removed by non-osc command) or incomplete + 'S' item is skipped (item exceeds a file size limit or is _service:* file) + 'F' Frozen (use "osc pull" to merge conflicts) (package-only state) examples: osc st @@ -4164,7 +4214,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. # state is != ' ' lines.append(statfrmt(st, os.path.normpath(os.path.join(prj.dir, pac)))) continue - if st == ' ' and opts.verbose or st != ' ': + if p.isfrozen(): + lines.append(statfrmt('F', os.path.normpath(os.path.join(prj.dir, pac)))) + elif st == ' ' and opts.verbose or st != ' ': lines.append(statfrmt(st, os.path.normpath(os.path.join(prj.dir, pac)))) states = p.get_status(opts.show_excluded, *excl_states) for st, filename in sorted(states, lambda x, y: cmp(x[1], y[1])): @@ -4269,9 +4321,10 @@ Please submit there instead, or use --nodevelproject to force direct submission. pacs = findpacs(args) for p in pacs: - p.todo = list(set(p.filenamelist + p.filenamelist_unvers + p.to_be_added)) - for filename in p.todo: - if os.path.isdir(filename): + todo = list(set(p.filenamelist + p.filenamelist_unvers + p.to_be_added)) + for filename in todo: + abs_filename = os.path.join(p.absdir, filename) + if os.path.isdir(abs_filename): continue # ignore foo.rXX, foo.mine for files which are in 'C' state if os.path.splitext(filename)[0] in p.in_conflict: @@ -4280,6 +4333,9 @@ Please submit there instead, or use --nodevelproject to force direct submission. if state == '?': # TODO: should ignore typical backup files suffix ~ or .orig p.addfile(filename) + elif state == 'D' and os.path.isfile(abs_filename): + # if the "deleted" file exists in the wc, track it again + p.addfile(filename) elif state == '!': p.delete_file(filename) print(statfrmt('D', getTransActPath(os.path.join(p.dir, filename)))) @@ -5413,10 +5469,11 @@ Please submit there instead, or use --nodevelproject to force direct submission. repo_names = sorted(set([r.name for r in repositories])) if not arg_repository and repositories: + # XXX: we should avoid hardcoding repository names # Use a default value from config, but just even if it's available - # unless try standard, or openSUSE_Factory + # unless try standard, or openSUSE_Factory, or openSUSE_Tumbleweed arg_repository = repositories[-1].name - for repository in (conf.config['build_repository'], 'standard', 'openSUSE_Factory'): + for repository in (conf.config['build_repository'], 'standard', 'openSUSE_Factory', 'openSUSE_Tumbleweed'): if repository in repo_names: arg_repository = repository break @@ -5504,6 +5561,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. help='Build in specified directory') @cmdln.option('-j', '--jobs', metavar='N', help='Compile with N jobs') + @cmdln.option('-t', '--threads', metavar='N', + help='Compile with N threads') @cmdln.option('--icecream', metavar='N', help='use N parallel build jobs with icecream') @cmdln.option('--ccache', action='store_true', @@ -5551,6 +5610,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. help=SUPPRESS_HELP) @cmdln.option('--host', metavar='HOST', help='perform the build on a remote server - user@server:~/remote/directory') + @cmdln.option('--trust-all-projects', action='store_true', + help='trust packages from all projects') def do_build(self, subcmd, opts, *args): """${cmd_name}: Build a package on your local machine @@ -5641,9 +5702,6 @@ Please submit there instead, or use --nodevelproject to force direct submission. if not os.path.isdir(d): raise oscerr.WrongOptions('Preferred package location \'%s\' is not a directory' % d) - if opts.noinit and opts.offline: - raise oscerr.WrongOptions('--noinit and --offline are mutually exclusive') - if opts.offline and opts.preload: raise oscerr.WrongOptions('--offline and --preload are mutually exclusive') @@ -5794,15 +5852,17 @@ Please submit there instead, or use --nodevelproject to force direct submission. help='specify the used build target project') @cmdln.option('--noinit', '--no-init', action='store_true', help='do not guess/verify specified repository') - @cmdln.option('-r', '--root', action='store_true', + @cmdln.option('-r', '--login-as-root', action='store_true', help='login as root instead of abuild') + @cmdln.option('--root', metavar='ROOT', + help='Path to the buildroot') @cmdln.option('-o', '--offline', action='store_true', help='Use cached data without contacting the api server') def do_chroot(self, subcmd, opts, *args): - """${cmd_name}: chroot into the buildchroot + """${cmd_name}: opens a shell inside of the build root - chroot into the buildchroot for the given repository, arch and build description - (NOTE: this command does not work if "build-type" is set in the config) + chroot into the build root for the given repository, arch and build description + (NOTE: this command does not work if a VM is used) usage: osc chroot [OPTS] REPOSITORY ARCH BUILD_DESCR @@ -5814,22 +5874,25 @@ Please submit there instead, or use --nodevelproject to force direct submission. """ if len(args) > 3: raise oscerr.WrongArgs('Too many arguments') - if conf.config['build-type']: + if conf.config['build-type'] and conf.config['build-type'] != "lxc": print('Not implemented for VMs', file=sys.stderr) sys.exit(1) user = 'abuild' - if opts.root: + if opts.login_as_root: user = 'root' - repository, arch, descr = self.parse_repoarchdescr(args, opts.noinit or opts.offline, opts.alternative_project) - project = opts.alternative_project or store_read_project('.') - if opts.local_package: - package = os.path.splitext(descr)[0] - else: - package = store_read_package('.') - apihost = urlsplit(self.get_api_url())[1] - buildroot = os.environ.get('OSC_BUILD_ROOT', conf.config['build-root']) \ - % {'repo': repository, 'arch': arch, 'project': project, 'package': package, 'apihost': apihost} + buildroot = opts.root + if buildroot is None: + repository, arch, descr = self.parse_repoarchdescr(args, opts.noinit or opts.offline, opts.alternative_project) + project = opts.alternative_project or store_read_project('.') + if opts.local_package: + package = os.path.splitext(descr)[0] + else: + package = store_read_package('.') + apihost = urlsplit(self.get_api_url())[1] + if buildroot is None: + buildroot = os.environ.get('OSC_BUILD_ROOT', conf.config['build-root']) \ + % {'repo': repository, 'arch': arch, 'project': project, 'package': package, 'apihost': apihost} if not os.path.isdir(buildroot): raise oscerr.OscIOError(None, '\'%s\' is not a directory' % buildroot) @@ -5861,6 +5924,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. ${cmd_option_list} """ + args = slash_split(args) + if len(args) < 2 and is_package_dir('.'): self.print_repos() @@ -6626,7 +6691,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-V', '--version', action='store_true', help='show package version, revision, and srcmd5. CAUTION: This is slow and unreliable') @cmdln.option('-i', '--involved', action='store_true', - help='show projects/packages where given person (or myself) is involved as bugowner or maintainer') + help='show projects/packages where given person (or myself) is involved as bugowner or maintainer [[{group|person}/]] default: person') @cmdln.option('-b', '--bugowner', action='store_true', help='as -i, but only bugowner') @cmdln.option('-m', '--maintainer', action='store_true', @@ -6717,14 +6782,25 @@ Please submit there instead, or use --nodevelproject to force direct submission. # role filter role_filter = '' if opts.bugowner or opts.maintainer or opts.involved: - xpath = xpath_join(xpath, 'person/@userid = \'%s\'' % search_term, inner=True) - role_filter = '%s (%s)' % (search_term, 'person') + tmp = search_term.split(':') + if len(tmp) > 1: + search_type, search_term = [tmp[0], tmp[1]] + else: + search_type = 'person' + search_dict = { 'person' : 'userid', + 'group' : 'groupid' } + try: + search_id = search_dict[ search_type ] + except KeyError: + search_type, search_id = [ 'person', 'userid' ] + xpath = xpath_join(xpath, '%s/@%s = \'%s\'' % (search_type, search_id, search_term), inner=True) + role_filter = '%s (%s)' % (search_term, search_type) role_filter_xpath = xpath if opts.bugowner and not opts.maintainer: - xpath = xpath_join(xpath, 'person/@role=\'bugowner\'', op='and') + xpath = xpath_join(xpath, '%s/@role=\'bugowner\'' % search_type, op='and') role_filter = 'bugowner' elif not opts.bugowner and opts.maintainer: - xpath = xpath_join(xpath, 'person/@role=\'maintainer\'', op='and') + xpath = xpath_join(xpath, '%s/@role=\'maintainer\'' % search_type, op='and') role_filter = 'maintainer' if opts.limit_to_attribute: xpath = xpath_join(xpath, 'attribute/@name=\'%s\'' % opts.limit_to_attribute, op='and') @@ -6981,6 +7057,8 @@ Please submit there instead, or use --nodevelproject to force direct submission. @cmdln.option('-X', '-m', '--method', default='GET', metavar='HTTP_METHOD', help='specify HTTP method to use (GET|PUT|DELETE|POST)') + @cmdln.option('-e', '--edit', default=None, action='store_true', + help='GET, edit and PUT the location') @cmdln.option('-d', '--data', default=None, metavar='STRING', help='specify string data for e.g. POST') @cmdln.option('-T', '-f', '--file', default=None, metavar='FILE', @@ -7001,6 +7079,7 @@ Please submit there instead, or use --nodevelproject to force direct submission. Examples: osc api /source/home:user osc api -X PUT -T /etc/fstab source/home:user/test5/myfstab + osc api -e /configuration ${cmd_usage} ${cmd_option_list} @@ -7028,10 +7107,17 @@ Please submit there instead, or use --nodevelproject to force direct submission. data=opts.data, file=opts.file, headers=opts.headers) - out = r.read() - sys.stdout.write(out) + if opts.edit: + text = edit_text(out) + r = http_request("PUT", + url, + data=text, + headers=opts.headers) + out = r.read() + + sys.stdout.write(out) @cmdln.option('-b', '--bugowner-only', action='store_true', diff --git a/osc/conf.py b/osc/conf.py index 67f1c97..3239cd8 100644 --- a/osc/conf.py +++ b/osc/conf.py @@ -112,6 +112,8 @@ DEFAULTS = {'apiurl': 'https://api.opensuse.org', 'build-vmdisk-rootsize': '', # optional for VM builds 'build-vmdisk-swapsize': '', # optional for VM builds 'build-vmdisk-filesystem': '', # optional for VM builds + 'build-kernel': '', # optional for VM builds + 'build-initrd': '', # optional for VM builds 'build-jobs': _get_processors(), 'builtin_signature_check': '1', # by default use builtin check for verify pkgs @@ -227,6 +229,12 @@ apiurl = %(apiurl)s # e.g. /var/tmp/FILE.swap #build-swap = /var/tmp/FILE.swap +# build-kernel is the boot kernel used for VM builds +#build-kernel = /boot/vmlinuz + +# build-initrd is the boot initrd used for VM builds +#build-initrd = /boot/initrd + # build-memory is the amount of memory used in the VM # value in MB - e.g. 512 #build-memory = 512 @@ -452,7 +460,7 @@ def _build_opener(url): # workaround for http://bugs.python.org/issue9639 authhandler_class = HTTPBasicAuthHandler - if sys.version_info >= (2, 6, 6) and sys.version_info < (2, 7, 99) \ + if sys.version_info >= (2, 6, 6) and sys.version_info < (2, 7, 1) \ and not 'reset_retry_count' in dir(HTTPBasicAuthHandler): print('warning: your urllib2 version seems to be broken. ' \ 'Using a workaround for http://bugs.python.org/issue9639', file=sys.stderr) @@ -468,7 +476,7 @@ def _build_opener(url): return None authhandler_class = OscHTTPBasicAuthHandler - elif sys.version_info >= (2, 6, 6) and sys.version_info < (2, 7, 99): + elif sys.version_info >= (2, 6, 6) and sys.version_info < (2, 7, 1): class OscHTTPBasicAuthHandler(HTTPBasicAuthHandler): def http_error_404(self, *args): self.reset_retry_count() diff --git a/osc/core.py b/osc/core.py index 095c33f..c569337 100644 --- a/osc/core.py +++ b/osc/core.py @@ -81,7 +81,7 @@ new_project_templ = """\ - +