Hello community, here is the log from the commit of package osc checked in at Fri Nov 30 02:28:10 CET 2007. -------- --- osc/osc.changes 2007-09-03 14:32:12.000000000 +0200 +++ /mounts/work_src_done/STABLE/osc/osc.changes 2007-11-30 02:02:16.000000000 +0100 @@ -1,0 +2,40 @@ +Fri Nov 30 01:50:24 CET 2007 - poeml@suse.de + +- update to r2685: + - rdiff: new command for server-side diffs between arbitrary + packages + - cat: new command to print a file on the standard output + - diff: reworked functionality to show newly added files, and + behaving more like svn when doing diff against a certain + revision + - bugfix in {link,aggregate,copy}_pac (<person> elements). Patch + from Michal Marek. + - checkout an empty project instead of doing nothing + - fix prjresults for newly added packages, where build status is + missing + - internal changes: + - copied init_project_dir() method from the + osc-package-tracking branch (just removed the + do_package_tracking stuff) + - changed the storedir attribut of the Package() class to an + absolute filename - normally this shouldn't have any impact + on existing methods, functionality etc. + +------------------------------------------------------------------- +Tue Oct 30 12:47:13 CET 2007 - poeml@suse.de + +- update to r2467. Most work done by Marcus Huewe. + - version 0.99 + - aggregatepac: new command, similar to linkpac. Patch from Pavol + Rusnak. + - wipebinaries: added --build-failed and --broken [#335498] + - deleteprj: enabled this command, as the backend now supports it + - maintainer: + - added --verbose option + - added functionality to add/remove users from a project/package + - print the list of URL to try, when in HTTP debug mode + - build: allow to use lbuild, a compatible replacement for build + - do not create dirs for non-existing packages during checkout + [#259711] + +------------------------------------------------------------------- Old: ---- osc-0.98.tar.gz New: ---- osc-0.99.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ osc.spec ++++++ --- /var/tmp/diff_new_pack.DA5603/_old 2007-11-30 02:27:28.000000000 +0100 +++ /var/tmp/diff_new_pack.DA5603/_new 2007-11-30 02:27:28.000000000 +0100 @@ -1,5 +1,5 @@ # -# spec file for package osc (Version 0.98) +# spec file for package osc (Version 0.99) # # Copyright (c) 2007 SUSE LINUX Products GmbH, Nuernberg, Germany. # This file and all modifications and additions to the pristine @@ -12,13 +12,13 @@ Name: osc BuildRequires: python-devel -Version: 0.98 +Version: 0.99 Release: 1 Group: Development/Tools/Other License: GPL v2 or later BuildRoot: %{_tmppath}/%{name}-%{version}-build -URL: https://forgesvn1.novell.com/svn/opensuse/trunk/buildservice/src/clientlib/p... -# v=0.98; svn export https://forgesvn1.novell.com/svn/opensuse/trunk/buildservice/src/clientlib/p... osc-$v; tar czf osc-$v.tar.gz osc-$v +Url: https://forgesvn1.novell.com/svn/opensuse/trunk/buildservice/src/clientlib/p... +# v=0.99; svn export https://forgesvn1.novell.com/svn/opensuse/trunk/buildservice/src/clientlib/p... osc-$v; tar czf osc-$v.tar.gz osc-$v Source: osc-%{version}.tar.gz Summary: openSUSE (build service) commander Requires: python-urlgrabber @@ -78,6 +78,40 @@ %doc README TODO NEWS %changelog +* Fri Nov 30 2007 - poeml@suse.de +- update to r2685: + - rdiff: new command for server-side diffs between arbitrary + packages + - cat: new command to print a file on the standard output + - diff: reworked functionality to show newly added files, and + behaving more like svn when doing diff against a certain + revision + - bugfix in {link,aggregate,copy}_pac (<person> elements). Patch + from Michal Marek. + - checkout an empty project instead of doing nothing + - fix prjresults for newly added packages, where build status is + missing + - internal changes: + - copied init_project_dir() method from the + osc-package-tracking branch (just removed the + do_package_tracking stuff) + - changed the storedir attribut of the Package() class to an + absolute filename - normally this shouldn't have any impact + on existing methods, functionality etc. +* Tue Oct 30 2007 - poeml@suse.de +- update to r2467. Most work done by Marcus Huewe. + - version 0.99 + - aggregatepac: new command, similar to linkpac. Patch from Pavol + Rusnak. + - wipebinaries: added --build-failed and --broken [#335498] + - deleteprj: enabled this command, as the backend now supports it + - maintainer: + - added --verbose option + - added functionality to add/remove users from a project/package + - print the list of URL to try, when in HTTP debug mode + - build: allow to use lbuild, a compatible replacement for build + - do not create dirs for non-existing packages during checkout + [#259711] * Mon Sep 03 2007 - poeml@suse.de - update to r2075: - new 'maintainer' command, to list the maintainers of a project ++++++ debian.changelog ++++++ --- osc/debian.changelog 2007-09-03 12:50:23.000000000 +0200 +++ /mounts/work_src_done/STABLE/osc/debian.changelog 2007-11-30 02:03:02.000000000 +0100 @@ -1,3 +1,43 @@ +osc (0.99-2) unstable; urgency=high + + - update to r2685: + - rdiff: new command for server-side diffs between arbitrary + packages + - cat: new command to print a file on the standard output + - diff: reworked functionality to show newly added files, and + behaving more like svn when doing diff against a certain + revision + - bugfix in {link,aggregate,copy}_pac (<person> elements). Patch + from Michal Marek. + - checkout an empty project instead of doing nothing + - fix prjresults for newly added packages, where build status is + missing + - internal changes: + - copied init_project_dir() method from the + osc-package-tracking branch (just removed the + do_package_tracking stuff) + - changed the storedir attribut of the Package() class to an + absolute filename - normally this shouldn't have any impact + on existing methods, functionality etc. + + -- Peter Poeml <poeml@suse.de> Fri, 30 Nov 2007 00:00:00 +0200 + +osc (0.99-1) unstable; urgency=high + + - update to r2467. Most work done by Marcus Huewe. + - version 0.99 + - wipebinaries: added --build-failed and --broken [#335498] + - deleteprj: enabled this command, as the backend now supports it + - maintainer: + - added --verbose option + - added functionality to add/remove users from a project/package + - print the list of URL to try, when in HTTP debug mode + - build: allow to use lbuild, a compatible replacement for build + - do not create dirs for non-existing packages during checkout + [#259711] + + -- Peter Poeml <poeml@suse.de> Tue, 30 Oct 2007 00:00:00 +0200 + osc (0.98-3) unstable; urgency=high - update to r2075: ++++++ osc-0.98.tar.gz -> osc-0.99.tar.gz ++++++ diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/osc-0.98/NEWS new/osc-0.99/NEWS --- old/osc-0.98/NEWS 2007-09-03 12:50:02.000000000 +0200 +++ new/osc-0.99/NEWS 2007-11-30 02:00:14.000000000 +0100 @@ -1,3 +1,27 @@ +since 0.99: + +- rdiff: new command for server-side diffs between arbitrary packages +- cat: new command to print a file on the standard output +- diff: reworked functionality to show newly added files, and behaving more + like svn when doing diff against a certain revision +- bugfix in {link,aggregate,copy}_pac (<person> elements) +- checkout an empty project instead of doing nothing +- fix prjresults for newly added packages, where build status is missing + + +0.99: + +- aggregatepac: new command, similar to linkpac. Patch from Pavol Rusnak. +- wipebinaries: added --build-failed and --broken [#335498] +- deleteprj: enabled this command, as the backend now supports it +- maintainer: + - added --verbose option + - added functionality to add/remove users from a project/package +- print the list of URL to try, when in HTTP debug mode +- build: allow to use lbuild, a compatible replacement for build +- do not create dirs for non-existing packages during checkout [#259711] + + 0.98: - new maintainer command, to list the maintainers of a project or package diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/osc-0.98/osc/build.py new/osc-0.99/osc/build.py --- old/osc-0.98/osc/build.py 2007-09-03 12:25:18.000000000 +0200 +++ new/osc-0.99/osc/build.py 2007-09-10 14:22:13.000000000 +0200 @@ -281,7 +281,8 @@ print 'Updating cache of required packages' fetcher = Fetcher(cachedir = config['packagecachedir'], urllist = config['urllist'], - auth_dict = config['auth_dict']) + auth_dict = config['auth_dict'], + http_debug = config['http_debug']) # now update the package cache fetcher.run(bi) diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/osc-0.98/osc/commandline.py new/osc-0.99/osc/commandline.py --- old/osc-0.98/osc/commandline.py 2007-09-03 12:25:18.000000000 +0200 +++ new/osc-0.99/osc/commandline.py 2007-11-29 18:32:52.000000000 +0100 @@ -436,6 +436,36 @@ return 1 link_pac(src_project, src_package, dst_project, dst_package) + def do_aggregatepac(self, subcmd, opts, *args): + """${cmd_name}: "Aggregate" a package to another package + + The DESTPAC name is optional; the source packages' name will be used if + DESTPAC is omitted. + + usage: + osc aggregatepac SOURCEPRJ SOURCEPAC DESTPRJ [DESTPAC] + ${cmd_option_list} + """ + + args = slash_split(args) + + if not args or len(args) < 3: + print >>sys.stderr, 'Incorrect number of argument.' + self.do_help([None, 'aggregatepac']) + return 2 + + src_project = args[0] + src_package = args[1] + dst_project = args[2] + if len(args) > 3: + dst_package = args[3] + else: + dst_package = src_package + + if src_project == dst_project and src_package == dst_package: + print >>sys.stderr, 'Error: source and destination are the same.' + return 1 + aggregate_pac(src_project, src_package, dst_project, dst_package) @cmdln.option('-t', '--to-apiurl', metavar='URL', help='URL of destination api server. Default is the source api server.') @@ -493,27 +523,27 @@ delete_package(conf.config['apiurl'], project, package) + @cmdln.option('-f', '--force', action='store_true', + help='deletes a project and its packages') def do_deleteprj(self, subcmd, opts, project): """${cmd_name}: Delete a project on the repository server - As a safety measure, project must be empty (i.e., you first need to delete all - packages first). + As a safety measure, project must be empty (i.e., you need to delete all + packages first). If you are sure that you want to remove this project and all + its packages use '--force' switch. - NOTE: This command is not implemented yet. Please mail - admin@opensuse.org in order to get projects deleted. ${cmd_usage} ${cmd_option_list} """ - if meta_get_packagelist(conf.config['apiurl'], project) != []: - print >>sys.stderr, 'Project contains packages. It must be empty before deleting it.' - return 1 - - #delete_project(conf.config['apiurl'], project) - print >>sys.stderr, 'Deleting projects is not yet implemented.' - print >>sys.stderr, 'Please send a request to opensuse-buildservice@opensuse.org' - print >>sys.stderr, 'or admin@opensuse.org.' + if len(meta_get_packagelist(conf.config['apiurl'], project)) >= 1 and not opts.force: + print >>sys.stderr, 'Project contains packages. It must be empty before deleting it. ' \ + 'If you are sure that you want to remove this project and all its ' \ + 'packages use the '--force' switch' + sys.exit(1) + else: + delete_project(conf.config['apiurl'], project) @cmdln.option('', '--specfile', metavar='FILE', @@ -561,98 +591,47 @@ args = parseargs(args) pacs = findpacs(args) - difference_found = False - d = [] - rev1, rev2 = parseRevisionOption(opts.revision) - pac = pacs[0] - - if rev1 and rev2 and (len(pacs) == 1): - # this is currently not implemented - print >>sys.stderr, 'this feature isn't implemented yet' - sys.exit(1) - elif rev1 and (pac.rev != rev1) and (len(pacs) == 1): - if not checkRevision(pac.prjname, pac.name, rev1): - print >>sys.stderr, 'Revision '%s' does not exist' % rev1 - sys.exit(1) - # make a temp dir for checking out the project - import tempfile - tmpdir = tempfile.mkdtemp(rev1, pac.name, '/tmp') - curdir = os.getcwd() - os.chdir(tmpdir) - init_package_dir(conf.config['apiurl'], pac.prjname, pac.name, tmpdir, rev1) - os.chdir(curdir) - tmppac = Package(tmpdir) - - changed_files = [] - added_files = [] - removed_files = [] - if pac.todo: - for file in pac.todo: - if file in tmppac.filenamelist: - if dgst(os.path.join(pac.dir, file)) != tmppac.findfilebyname(file).md5: - changed_files.append(file) - else: - added_files.append(file) - else: - changed_files, added_files, removed_files = pac.comparePac(tmppac) - - for file in changed_files: - tmppac.updatefile(file, rev1) - d.append('Index: %s\n' % file) - d.append('===================================================================\n') - d.append(get_source_file_diff(pac.dir, file, rev1, file, tmppac.dir)) - tmppac.delete_localfile(file) - tmppac.delete_storefile(file) - - # this tempfile is used as a dummy file for difflib - (fd, filename) = tempfile.mkstemp(dir=tmppac.storedir) - - for file in added_files: - d.append('Index: %s\n' % file) - d.append('===================================================================\n') - d.append(get_source_file_diff(pac.dir, file, rev1, \ - os.path.basename(filename), \ - tmppac.storedir, file)) - - for file in removed_files: - tmppac.updatefile(file, rev1) - d.append('Index: %s\n' % file) - d.append('===================================================================\n') - d.append(get_source_file_diff(tmppac.storedir, \ - os.path.basename(filename), \ - rev1, file, tmppac.dir, file)) - tmppac.delete_localfile(file) - tmppac.delete_storefile(file) + diff = '' + for pac in pacs: + diff += ''.join(make_diff(pac, rev1)) + if len(diff) > 0: + print diff - # clean up - os.unlink(filename) - for dir, dirnames, files in os.walk(tmppac.storedir): - for file in files: - os.unlink(os.path.join(dir, file)) - os.rmdir(tmppac.storedir) - os.rmdir(tmppac.dir) - else: - for p in pacs: - if p.todo == []: - for i in p.filenamelist: - s = p.status(i) - if s == 'M' or s == 'C': - p.todo.append(i) - - for filename in p.todo: - d.append('Index: %s\n' % filename) - d.append('===================================================================\n') - d.append(get_source_file_diff(p.dir, filename, p.rev)) - - if d: - print ''.join(d) - difference_found = True + @cmdln.option('--oldprj', metavar='OLDPRJ', + help='project to compare against') + @cmdln.option('--oldpkg', metavar='OLDPKG', + help='package to compare against') + @cmdln.option('-r', '--revision', metavar='N[:M]', + help='revision id, where N = old revision and M = new revision') + def do_rdiff(self, subcmd, opts, new_project, new_package): + """${cmd_name}: server-side "pretty" diff of two packages + + If neither OLDPRJ nor OLDPKG are specified, the diff is against the + last revision, thus showing the latest change. + + Note that this command doesn't reply a "normal" diff which can be + applied as patch, but a pretty diff, which also compares the content of + tarballs. + + + ${cmd_usage} + ${cmd_option_list} + """ + + old_revision = None + new_revision = None + if opts.revision: + old_revision, new_revision = parseRevisionOption(opts.revision) + + rdiff = pretty_diff(conf.config['apiurl'], + opts.oldprj, opts.oldpkg, old_revision, + new_project, new_package, new_revision) + + print rdiff + - if difference_found: - return 1 - def do_repourls(self, subcmd, opts, *args): """${cmd_name}: shows URLs of .repo files @@ -719,6 +698,12 @@ checkout_package(conf.config['apiurl'], project, package, rev) elif project: + if not os.path.exists(project): + init_project_dir(conf.config['apiurl'], project, project) + print statfrmt('A', project) + else: + print >>sys.stderr, 'osc: project '%s' already exists' % project + sys.exit(1) # all packages for package in meta_get_packagelist(conf.config['apiurl'], project): checkout_package(conf.config['apiurl'], project, package) @@ -1363,7 +1348,8 @@ import osc.build - if not os.path.exists('/usr/lib/build/debtransform'): + if not os.path.exists('/usr/lib/build/debtransform') \ + and not os.path.exists('/usr/lib/lbuild/debtransform'): sys.stderr.write('Error: you need build.rpm with version 2007.3.12 or newer.\n') sys.stderr.write('See http://download.opensuse.org/repositories/openSUSE:/Tools/\n') return 1 @@ -1557,6 +1543,10 @@ help='Delete all binary packages for a specific repository') @cmdln.option('--build-disabled', action='store_true', help='Delete all binaries of packages for which the build is disabled') + @cmdln.option('--build-failed', action='store_true', + help='Delete all binaries of packages for which the build failed') + @cmdln.option('--broken', action='store_true', + help='Delete all binaries of packages for which the package source is bad') def do_wipebinaries(self, subcmd, opts, *args): """${cmd_name}: Delete all binary packages of a certain project/package @@ -1578,8 +1568,21 @@ package = args[1] else: package = None - - print wipebinaries(conf.config['apiurl'], args[0], package, opts.arch, opts.repo, opts.build_disabled) + + codes = [] + if opts.build_disabled: + codes.append('disabled') + if opts.build_failed: + codes.append('failed') + if opts.broken: + codes.append('broken') + + if len(codes) == 0: + codes.append(None) + + # make a new request for each code= parameter + for code in codes: + print wipebinaries(conf.config['apiurl'], args[0], package, opts.arch, opts.repo, code) @cmdln.option('--repos-baseurl', action='store_true', @@ -1832,23 +1835,33 @@ @cmdln.option('-e', '--email', action='store_true', help='show email addresses instead of user names') + @cmdln.option('-v', '--verbose', action='store_true', + help='show more information') + @cmdln.option('-a', '--add', metavar='user', + help='add a new maintainer') + @cmdln.option('-d', '--delete', metavar='user', + help='delete a maintainer from a project or package') def do_maintainer(self, subcmd, opts, *args): """${cmd_name}: Show maintainers of a project/package To be used like this: - osc maintainer PRJ + osc maintainer PRJ <options> or - osc maintainer PRJ PKG + osc maintainer PRJ PKG <options> ${cmd_usage} ${cmd_option_list} """ + pac = None if len(args) == 1: m = show_project_meta(conf.config['apiurl'], args[0]) + prj = args[0] elif len(args) == 2: m = show_package_meta(conf.config['apiurl'], args[0], args[1]) + prj = args[0] + pac = args[1] else: sys.exit('wrong argument count') @@ -1858,16 +1871,64 @@ for person in tree.findall('person'): maintainers.append(person.get('userid')) - if not opts.email: - print ', '.join(maintainers) - else: + if opts.email: emails = [] for maintainer in maintainers: - emails.append(get_user_email(conf.config['apiurl'], maintainer)) + user = get_user_data(conf.config['apiurl'], maintainer, 'email') + if user != None: + emails.append(''.join(user)) print ', '.join(emails) + elif opts.verbose: + userdata = [] + for maintainer in maintainers: + user = get_user_data(conf.config['apiurl'], maintainer, 'realname', 'login', 'email') + if user != None: + for itm in user: + userdata.append(itm) + for row in build_table(3, userdata, ['realname', 'userid', 'email\n']): + print row + elif opts.add: + addMaintainer(conf.config['apiurl'], prj, pac, opts.add) + elif opts.delete: + delMaintainer(conf.config['apiurl'], prj, pac, opts.delete) + else: + print ', '.join(maintainers) + + + def do_cat(self, subcmd, opts, *args): + """${cmd_name}: print file on the standard output + Examples: + osc cat project package file + osc cat project/package/file + ${cmd_usage} + ${cmd_option_list} + """ + args = slash_split(args) + if len(args) != 3: + print >>sys.stderr, 'error - incorrect number of arguments' + sys.exit(1) + import tempfile + (fd, filename) = tempfile.mkstemp(prefix = 'osc_%s.' % args[2], dir = '/tmp') + get_source_file(conf.config['apiurl'], args[0], args[1], args[2], targetfilename=filename) + if binary(os.read(fd, 4098)): + print >>sys.stderr, 'error - cannot display binary file '%s'' % args[2] + else: + print '### Beginning of file: '%s' ###' % filename + while True: + buf = os.read(fd, BUFSIZE) + if not buf: + break + else: + print buf + print '### End of file ###' + try: + os.close(fd) + os.unlink(filename) + except: + pass # fini! ############################################################################### diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/osc-0.98/osc/core.py new/osc-0.99/osc/core.py --- old/osc-0.98/osc/core.py 2007-09-03 12:17:04.000000000 +0200 +++ new/osc-0.99/osc/core.py 2007-11-29 18:22:57.000000000 +0100 @@ -5,7 +5,7 @@ # and distributed under the terms of the GNU General Public Licence, # either version 2, or (at your option) any later version. -__version__ = '0.98' +__version__ = '0.99' import os import sys @@ -201,7 +201,7 @@ def __init__(self, workingdir): self.dir = workingdir self.absdir = os.path.abspath(self.dir) - self.storedir = os.path.join(self.dir, store) + self.storedir = os.path.join(self.absdir, store) check_store_version(self.dir) @@ -498,7 +498,7 @@ exists_in_store = False if n in self.filenamelist: known_by_meta = True - if os.path.exists(os.path.join(self.dir, n)): + if os.path.exists(os.path.join(self.absdir, n)): exists = True if os.path.exists(os.path.join(self.storedir, n)): exists_in_store = True @@ -512,7 +512,7 @@ state = 'C' elif exists and exists_in_store and known_by_meta: #print self.findfilebyname(n) - if dgst(os.path.join(self.dir, n)) != self.findfilebyname(n).md5: + if dgst(os.path.join(self.absdir, n)) != self.findfilebyname(n).md5: state = 'M' else: state = ' ' @@ -829,6 +829,13 @@ return fd +def init_project_dir(apiurl, dir, project): + if not os.path.exists(dir): + os.mkdir(dir) + os.mkdir(os.path.join(dir, store)) + + store_write_project(dir, project) + store_write_apiurl(dir, apiurl) def init_package_dir(apiurl, project, package, dir, revision=None): if not os.path.isdir(store): @@ -867,7 +874,7 @@ sys.exit(1) if v != __version__: - if v in ['0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '0.95', '0.96', '0.97']: + if v in ['0.2', '0.3', '0.4', '0.5', '0.6', '0.7', '0.8', '0.9', '0.95', '0.96', '0.97', '0.98']: # version is fine, no migration needed f = open(versionfile, 'w') f.write(__version__ + '\n') @@ -1182,14 +1189,25 @@ return None -def get_user_email(apiurl, user): - u = makeurl(apiurl, ['person', quote_plus(user)]) - try: - f = http_GET(u) - root = ET.parse(f).getroot() - return root.find('email').text - except urllib2.HTTPError: - print 'user '%s' not found' % user +def get_user_data(apiurl, user, *tags): + """get specified tags from the user meta""" + meta = get_user_meta(apiurl, user) + data = [] + if meta != None: + root = ET.fromstring(meta) + for tag in tags: + try: + if root.find(tag).text != None: + data.append(root.find(tag).text) + else: + # tag is empty + data.append('-') + except AttributeError: + # this part is reached if the tags tuple contains an invalid tag + print 'The xml file for user '%s' seems to be broken' % user + return None + return data + else: return None @@ -1295,7 +1313,7 @@ if not origfilename: origfilename = filename - + file1 = os.path.join(olddir, oldfilename) # old/stored original file2 = os.path.join(dir, filename) # working copy @@ -1327,16 +1345,128 @@ return ''.join(d) +def make_diff(wc, revision): + import tempfile + changed_files = [] + added_files = [] + removed_files = [] + cmp_pac = None + diff_hdr = 'Index: %s\n' + diff_hdr += '===================================================================\n' + if not revision: + # normal diff + for file in wc.filenamelist+wc.filenamelist_unvers: + state = wc.status(file) + if state == 'M' or state == 'C': + changed_files.append(file) + elif state == 'A': + added_files.append(file) + elif state == 'D': + removed_files.append(file) + else: + olddir = os.getcwd() + tmpdir = tempfile.mkdtemp(revision, wc.name, '/tmp') + os.chdir(tmpdir) + init_package_dir(conf.config['apiurl'], wc.prjname, wc.name, tmpdir, revision) + cmp_pac = Package(tmpdir) + if wc.todo: + for file in wc.todo: + if file in cmp_pac.filenamelist: + changed_files.append(file) + # behave like svn + #else: + # added_files.append(file) + else: + for file in wc.filenamelist+wc.filenamelist_unvers: + state = wc.status(file) + if wc.status(file) == 'A' and (not file in cmp_pac.filenamelist): + added_files.append(file) + elif file in cmp_pac.filenamelist and wc.status(file) == 'D': + removed_files.append(file) + elif wc.status(file) == ' ' and not file in cmp_pac.filenamelist: + added_files.append(file) + elif file in cmp_pac.filenamelist and state != 'A' and state != '?': + if dgst(os.path.join(wc.absdir, file)) != cmp_pac.findfilebyname(file).md5: + changed_files.append(file) + for file in cmp_pac.filenamelist: + if not file in wc.filenamelist: + removed_files.append(file) + + diff = [] + for file in changed_files: + diff.append(diff_hdr % file) + if cmp_pac == None: + diff.append(get_source_file_diff(wc.absdir, file, wc.rev)) + else: + cmp_pac.updatefile(file, revision) + diff.append(get_source_file_diff(wc.absdir, file, revision, file, + cmp_pac.absdir, file)) + (fd, tmpfile) = tempfile.mkstemp(dir='/tmp') + for file in added_files: + diff.append(diff_hdr % file) + if cmp_pac == None: + diff.append(get_source_file_diff(wc.absdir, file, wc.rev, os.path.basename(tmpfile), + os.path.dirname(tmpfile), file)) + else: + diff.append(get_source_file_diff(wc.absdir, file, revision, os.path.basename(tmpfile), + os.path.dirname(tmpfile), file)) + + # FIXME: this is ugly but it cannot be avoided atm + # if a file is deleted via "osc rm file" we should keep the storefile. + tmp_pac = None + if cmp_pac == None: + olddir = os.getcwd() + tmpdir = tempfile.mkdtemp(dir='/tmp') + os.chdir(tmpdir) + init_package_dir(conf.config['apiurl'], wc.prjname, wc.name, tmpdir, wc.rev) + tmp_pac = Package(tmpdir) + os.chdir(olddir) + + for file in removed_files: + diff.append(diff_hdr % file) + if cmp_pac == None: + tmp_pac.updatefile(file, tmp_pac.rev) + diff.append(get_source_file_diff(os.path.dirname(tmpfile), os.path.basename(tmpfile), + wc.rev, file, tmp_pac.storedir, file)) + else: + cmp_pac.updatefile(file, revision) + diff.append(get_source_file_diff(os.path.dirname(tmpfile), os.path.basename(tmpfile), + revision, file, cmp_pac.storedir, file)) + + os.chdir(olddir) + if cmp_pac != None: + delete_tmpdir(cmp_pac.absdir) + if tmp_pac != None: + delete_tmpdir(tmp_pac.absdir) + return diff + + +def pretty_diff(apiurl, + old_project, old_package, old_revision, + new_project, new_package, new_revision): + + query = [] + query.append('cmd=diff') + if old_project: + query.append('oproject=%s' % quote_plus(old_project)) + if old_package: + query.append('opackage=%s' % quote_plus(old_package)) + if old_revision: + query.append('orev=%s' % quote_plus(old_revision)) + if new_revision: + query.append('rev=%s' % quote_plus(new_revision)) + + u = makeurl(apiurl, ['source', new_project, new_package], query=query) + + f = http_POST(u) + return f.read() + def make_dir(apiurl, project, package): #print "creating directory '%s'" % project if not os.path.exists(project): print statfrmt('A', project) - os.mkdir(project) - os.mkdir(os.path.join(project, store)) - - store_write_project(project, project) - store_write_apiurl(project, apiurl) + init_project_dir(apiurl, project, project) #print "creating directory '%s/%s'" % (project, package) if not os.path.exists(os.path.join(project, package)): @@ -1350,6 +1480,11 @@ def checkout_package(apiurl, project, package, revision=None): olddir = os.getcwd() + path = (quote_plus(project), quote_plus(package)) + if meta_exists(metatype='pkg', path_args=path, create_new=False) == None: + print >>sys.stderr, 'error 404 - package or package does not exist' + sys.exit(1) + os.chdir(make_dir(apiurl, project, package)) init_package_dir(apiurl, project, package, store, revision) p = Package(os.curdir) @@ -1361,6 +1496,20 @@ os.chdir(olddir) +def replace_pkg_meta(pkgmeta, new_name, new_prj): + """ + update pkgmeta with new new_name and new_prj and set calling user as the + only maintainer + """ + root = ET.fromstring(''.join(pkgmeta)) + root.set('name', new_name) + root.set('project', new_prj) + for person in root.findall('person'): + root.remove(person) + ET.SubElement(root, 'person', + userid = conf.config['user'], role = 'maintainer') + return ET.tostring(root) + def link_pac(src_project, src_package, dst_project, dst_package): """ create a linked package @@ -1369,18 +1518,7 @@ """ src_meta = show_package_meta(conf.config['apiurl'], src_project, src_package) - - # replace package name and username - # using a string buffer - # and create the package - tree = ET.parse(StringIO(''.join(src_meta))) - root = tree.getroot() - root.set('name', dst_package) - root.set('project', dst_project) - tree.find('person').set('userid', conf.config['user']) - buf = StringIO() - tree.write(buf) - src_meta = buf.getvalue() + src_meta = replace_pkg_meta(src_meta, dst_package, dst_project) edit_meta('pkg', path_args=(dst_project, dst_package), @@ -1407,6 +1545,39 @@ http_PUT(u, data=link_template) print 'Done.' +def aggregate_pac(src_project, src_package, dst_project, dst_package): + """ + aggregate package + - "src" is the original package + - "dst" is the "aggregate" package that we are creating here + """ + + src_meta = show_package_meta(conf.config['apiurl'], src_project, src_package) + src_meta = replace_pkg_meta(src_meta, dst_package, dst_project) + + edit_meta('pkg', + path_args=(dst_project, dst_package), + data=src_meta) + + # create the _aggregate file + # but first, make sure not to overwrite an existing one + if '_aggregate' in meta_get_filelist(conf.config['apiurl'], dst_project, dst_package): + print >>sys.stderr + print >>sys.stderr, '_aggregate file already exists...! Aborting' + sys.exit(1) + + print 'Creating _aggregate...', + aggregate_template = """\ +<aggregatelist> + <aggregate project="%s"> + <package>%s</package> + </aggregate> +</aggregatelist> +""" % (src_project, src_package) + + u = makeurl(conf.config['apiurl'], ['source', dst_project, dst_package, '_aggregate']) + http_PUT(u, data=aggregate_template) + print 'Done.' def copy_pac(src_apiurl, src_project, src_package, dst_apiurl, dst_project, dst_package): @@ -1417,17 +1588,7 @@ import tempfile src_meta = show_package_meta(src_apiurl, src_project, src_package) - - # replace project and package name - # using a string buffer - # and create the package - tree = ET.parse(StringIO(''.join(src_meta))) - root = tree.getroot() - root.set('name', dst_package) - root.set('project', dst_project) - buf = StringIO() - tree.write(buf) - src_meta = buf.getvalue() + src_meta = replace_pkg_meta(src_meta, dst_package, dst_project) print 'Sending meta data...' u = makeurl(dst_apiurl, ['source', dst_project, dst_package, '_meta']) @@ -1609,6 +1770,8 @@ line = [] line.append(' ') for pac in pacs[startpac:startpac+max_pacs]: + if not status.has_key(pac): # for newly added packages, status may be missing + status[pac] = '?' line.append(status[pac]) line.append(' ') line.append(' %s %s' % (target['repo'], target['arch'])) @@ -1804,7 +1967,7 @@ return root.get('code') -def wipebinaries(apiurl, project, package=None, arch=None, repo=None, build_disabled=None): +def wipebinaries(apiurl, project, package=None, arch=None, repo=None, code=None): query = [] query.append('cmd=wipe') if package: @@ -1813,8 +1976,8 @@ query.append('arch=%s' % quote_plus(arch)) if repo: query.append('repository=%s' % quote_plus(repo)) - if build_disabled: - query.append('code=disabled') + if code: + query.append('code=%s' % quote_plus(code)) u = makeurl(apiurl, ['build', project], query) try: @@ -1827,8 +1990,8 @@ err_str += ' arch %s' % arch if repo: err_str += ' repository %s' % repo - if build_disabled: - err_str += ' code=disabled' + if code: + err_str += ' code=%s' % code print >> sys.stderr, err_str print >> sys.stderr, u print >> sys.stderr, e @@ -2118,3 +2281,61 @@ # see bug #280034 print >>sys.stderr, 'error while deleting file '%s'' % file sys.exit(1) + +def addMaintainer(apiurl, prj, pac, user): + """ add a new maintainer to a package or project """ + path = quote_plus(prj), + kind = 'prj' + if pac: + path = path + (quote_plus(pac),) + kind = 'pkg' + data = meta_exists(metatype=kind, + path_args=path, + template_args=None, + create_new=False) + + if data and get_user_meta(apiurl, user) != None: + tree = ET.fromstring(''.join(data)) + found = False + for person in tree.getiterator('person'): + if person.get('userid') == user: + found = True + print "user already exists" + break + if not found: + # the xml has a fixed structure + tree.insert(2, ET.Element('person', role='maintainer', userid=user)) + print 'user '%s' added to '%s'' % (user, pac or prj) + edit_meta(metatype=kind, + path_args=path, + data=ET.tostring(tree)) + else: + print "osc: an error occured" + +def delMaintainer(apiurl, prj, pac, user): + """ delete a maintainer from a package or project """ + path = quote_plus(prj), + kind = 'prj' + if pac: + path = path + (quote_plus(pac), ) + kind = 'pkg' + data = meta_exists(metatype=kind, + path_args=path, + template_args=None, + create_new=False) + if data: + tree = ET.fromstring(''.join(data)) + found = False + for person in tree.getiterator('person'): + if person.get('userid') == user: + tree.remove(person) + found = True + print "user '%s' removed" % user + if found: + edit_meta(metatype=kind, + path_args=path, + data=ET.tostring(tree)) + else: + print "user '%s' not found in '%s'" % (user, pac or prj) + else: + print "an error occured" diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/osc-0.98/osc/fetch.py new/osc-0.99/osc/fetch.py --- old/osc-0.98/osc/fetch.py 2007-06-26 13:19:41.000000000 +0200 +++ new/osc-0.99/osc/fetch.py 2007-09-10 14:22:13.000000000 +0200 @@ -23,7 +23,7 @@ class Fetcher: - def __init__(self, cachedir = '/tmp', auth_dict = {}, urllist = []): + def __init__(self, cachedir = '/tmp', auth_dict = {}, urllist = [], http_debug = False): __version__ = '0.1' __user_agent__ = 'osbuild/%s' % __version__ @@ -37,6 +37,7 @@ self.cachedir = cachedir self.urllist = urllist + self.http_debug = http_debug passmgr = urllib2.HTTPPasswordMgrWithDefaultRealm() for host in auth_dict.keys(): @@ -67,6 +68,12 @@ MirrorGroup._join_url = join_url mg = MirrorGroup(self.gr, pac.urllist) + if self.http_debug: + print + print 'URLs to try for package '%s':' % pac + print '\n'.join(pac.urllist) + print + try: # it returns the filename ret = mg.urlgrab(pac.filename, diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/osc-0.98/TODO new/osc-0.99/TODO --- old/osc-0.98/TODO 2007-09-03 12:49:44.000000000 +0200 +++ new/osc-0.99/TODO 2007-10-25 15:53:46.000000000 +0200 @@ -8,6 +8,7 @@ - think about how to locally build "linked" packages http://lists4.opensuse.org/opensuse-buildservice/2007-07/msg00043.html https://bugzilla.novell.com/show_bug.cgi?id=212565 + draft on source code branching: http://en.opensuse.org/Build_Service/Concepts NORMAL: @@ -26,6 +27,8 @@ - use urllib.urlencode for parameter encoding (or check if this is the case already?) - _real_ SSL support, with certificate verification - copypac: put the current release number into the spec file before sending it + - for this, it is required to scan all current binaries, pick the highest release number + and put it into the spec file... otherwise clients won't regard the copied package as newer - commit: check if errors during PUT are handled sensibly, so the change is not committed to localmeta - store password base64 hashed, so it is not directly visible in plaintext @@ -152,3 +155,34 @@ + + % osc importsrcpkg -n apache2-mod_memcache /tmp/apache-mod_memcache-0.1.0-2mdv2008.0.src.rpm +warning: rpmts_HdrFromFdno: Header V3 DSA signature: NOKEY, key ID 26752624 +Traceback (most recent call last): + File "/suse/poeml/bin/osc", line 10, in ? + sys.exit( osc.main() ) + File "/suse/poeml/osc/osc/cmdln.py", line 256, in main + return self.cmd(args) + File "/suse/poeml/osc/osc/cmdln.py", line 279, in cmd + retval = self.onecmd(argv) + File "/suse/poeml/osc/osc/cmdln.py", line 395, in onecmd + return self._dispatch_cmd(handler, argv) + File "/suse/poeml/osc/osc/cmdln.py", line 1070, in _dispatch_cmd + return handler(argv[0], opts, *args) + File "/suse/poeml/osc/osc/commandline.py", line 1714, in do_importsrcpkg + rpm_data = data_from_rpm(srpm, 'Name:', 'Summary:', '%description') + File "/suse/poeml/osc/osc/core.py", line 2128, in data_from_rpm + header = ts.hdrFromFdno(file.fileno()) +_rpm.error: public key not available + + +15:16 < DuDE> mt: Projekte anlegen geht nur, wenn es ein Subprojekt ist von einem Projekt wo Du Schreibrechte hast +15:16 < mt> DuDE: wofür? +15:16 < DuDE> mt: dass jeder einfach so top-level-Projekte anlegen kann, war einmal. Chaos-Reduzierung +15:17 < DuDE> mt: ueblich ist heutzutage ein Request auf opensuse-buildservice@ +15:18 < DuDE> mt: kannst Du das gleiche mal eben mit osc -H probieren? Mich wuerde mal interessieren, ob da eine sinnvollere Meldung im Body mitkommt +15:19 < DuDE> mt: mit -H muesste osc den Response-Body anzeigen. Meist ist der unerwuenscht, weil er typischerweise dank iChain hauptsaechlich Javascript-Schlonz enthaelt. +15:19 < mt> DuDE: reply: 'HTTP/1.1 403 Forbidden\r\n' +15:20 < DuDE> mt: das ist gut, dann sollte osc kein "try again" anbieten, sondern die Meldung rueberbringen + + ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Remember to have fun... --------------------------------------------------------------------- To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org For additional commands, e-mail: opensuse-commit+help@opensuse.org