Hello community,
here is the log from the commit of package osc
checked in at Thu Aug 9 20:43:11 CEST 2007.
--------
--- osc/osc.changes 2007-07-18 15:22:59.000000000 +0200
+++ /mounts/work_src_done/STABLE/osc/osc.changes 2007-08-09 00:55:04.000000000 +0200
@@ -1,0 +2,45 @@
+Thu Aug 9 00:54:21 CEST 2007 - poeml@suse.de
+
+- update to r1947:
+ - commit: fixed possible "UnboundLocalError" with -m. Thanks to
+ judas_iscariote for spotting this issue, and Marcus for fixing
+ it.
+
+-------------------------------------------------------------------
+Wed Aug 8 20:49:24 CEST 2007 - poeml@suse.de
+
+- update to r1946:
+ - avoid warning/error with unsupported HTTPS_PROXY [#214983][#298378]
+ - importsrcpkg:
+ * changed default behaviour - the files will not be committed by
+ default. To commit them use the --commit switch.
+ * added --delete-old-files option switch to delete old files from
+ the server.
+ * allow to import source rpms by specifying an URL
+ * use rpm-python
+ - fix for "osc prjconf <project> -e".
+ - add Recommends: rpm-python
+
+-------------------------------------------------------------------
+Wed Jul 25 13:04:37 CEST 2007 - poeml@suse.de
+
+- update to r1884:
+ - added new importfromsrcpkg command, to import a package src.rpm
+ (we owe this to Marcus)
+ - added new req command, to issue arbitrary requests to the API
+ - append missing newline if do_commits=False [#293672]
+ - make delete_package() and delete_project() more userfriendly
+ (added trivial exception handling..)
+ - expand ~ to users home for packagecachedir in .oscrc [#293675]
+
+-------------------------------------------------------------------
+Thu Jul 19 14:28:51 CEST 2007 - poeml@suse.de
+
+- update to r1871:
+ - meta: allow for editing patterns
+ - small fixes:
+ - fix error message which osc issues if build package is too old
+ - results: result code can be empty when package has just been created
+ - fix name of 10.2 product in the template for new projects
+
+-------------------------------------------------------------------
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ osc.spec ++++++
--- /var/tmp/diff_new_pack.p25263/_old 2007-08-09 20:42:15.000000000 +0200
+++ /var/tmp/diff_new_pack.p25263/_new 2007-08-09 20:42:15.000000000 +0200
@@ -13,7 +13,7 @@
Name: osc
BuildRequires: python-devel
Version: 0.97
-Release: 4
+Release: 13
Group: Development/Tools/Other
License: GPL v2 or later
BuildRoot: %{_tmppath}/%{name}-%{version}-build
@@ -29,6 +29,9 @@
%else
Requires: python-xml
%endif
+%if %suse_version > 1000
+Recommends: rpm-python
+%endif
%endif
#
%if 0%{?fedora_version}
@@ -75,6 +78,39 @@
%doc README TODO NEWS
%changelog
+* Thu Aug 09 2007 - poeml@suse.de
+- update to r1947:
+ - commit: fixed possible "UnboundLocalError" with -m. Thanks to
+ judas_iscariote for spotting this issue, and Marcus for fixing
+ it.
+* Wed Aug 08 2007 - poeml@suse.de
+- update to r1946:
+ - avoid warning/error with unsupported HTTPS_PROXY [#214983][#298378]
+ - importsrcpkg:
+ * changed default behaviour - the files will not be committed by
+ default. To commit them use the --commit switch.
+ * added --delete-old-files option switch to delete old files from
+ the server.
+ * allow to import source rpms by specifying an URL
+ * use rpm-python
+ - fix for "osc prjconf <project> -e".
+ - add Recommends: rpm-python
+* Wed Jul 25 2007 - poeml@suse.de
+- update to r1884:
+ - added new importfromsrcpkg command, to import a package src.rpm
+ (we owe this to Marcus)
+ - added new req command, to issue arbitrary requests to the API
+ - append missing newline if do_commits=False [#293672]
+ - make delete_package() and delete_project() more userfriendly
+ (added trivial exception handling..)
+ - expand ~ to users home for packagecachedir in .oscrc [#293675]
+* Thu Jul 19 2007 - poeml@suse.de
+- update to r1871:
+ - meta: allow for editing patterns
+ - small fixes:
+ - fix error message which osc issues if build package is too old
+ - results: result code can be empty when package has just been created
+ - fix name of 10.2 product in the template for new projects
* Wed Jul 18 2007 - poeml@suse.de
- update to r1861:
- commit (using the currently documented way):
++++++ debian.changelog ++++++
--- osc/debian.changelog 2007-07-18 15:24:27.000000000 +0200
+++ /mounts/work_src_done/STABLE/osc/debian.changelog 2007-08-09 00:55:39.000000000 +0200
@@ -1,3 +1,51 @@
+osc (0.97-7) unstable; urgency=high
+
+ * update to r1947:
+ - commit: fixed possible "UnboundLocalError" with -m. Thanks to
+ judas_iscariote for spotting this issue, and Marcus for fixing
+ it.
+
+ -- Peter Poeml Thu, 9 Aug 2007 00:00:00 +0200
+
+osc (0.97-6) unstable; urgency=high
+
+ * update to r1946:
+ - avoid warning/error with unsupported HTTPS_PROXY [#214983][#298378]
+ - importsrcpkg:
+ * changed default behaviour - the files will not be committed by
+ default. To commit them use the --commit switch.
+ * added --delete-old-files option switch to delete old files from
+ the server.
+ * allow to import source rpms by specifying an URL
+ * use rpm-python
+ - fix for "osc prjconf <project> -e".
+
+ -- Peter Poeml Wed, 8 Aug 2007 00:00:00 +0200
+
+osc (0.97-5) unstable; urgency=high
+
+ * update to r1884:
+ - added new importfromsrcpkg command, to import a package src.rpm
+ (we owe this to Marcus)
+ - added new req command, to issue arbitrary requests to the API
+ - append missing newline if do_commits=False [#293672]
+ - make delete_package() and delete_project() more userfriendly
+ (added trivial exception handling..)
+ - expand ~ to users home for packagecachedir in .oscrc [#293675]
+
+ -- Peter Poeml Wed, 25 Jul 2007 00:00:00 +0200
+
+osc (0.97-4) unstable; urgency=high
+
+ * update to r1811:
+ - meta: allow for editing patterns
+ - small fixes:
+ - fix error message which osc issues if build package is too old
+ - results: result code can be empty when package has just been created
+ - fix name of 10.2 product in the template for new projects
+
+ -- Peter Poeml Thu, 19 Jul 2007 00:00:00 +0200
+
osc (0.97-3) unstable; urgency=high
* update to r1861:
++++++ osc-0.97.tar.gz ++++++
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/osc-0.97/NEWS new/osc-0.97/NEWS
--- old/osc-0.97/NEWS 2007-07-16 19:30:48.000000000 +0200
+++ new/osc-0.97/NEWS 2007-07-23 11:28:15.000000000 +0200
@@ -3,6 +3,7 @@
- added initial search support
- new meta command, replacing editmeta, editprj, createprj,
editpac, createpac, edituser
+- allow editing patterns (osc meta pattern -e)
- show helpful xml error messages if broken metadata is uploaded
- implementing a log command to review the commit log
- renamed previous "log" command to "buildlog" (short: bl)
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/osc-0.97/osc/commandline.py new/osc-0.97/osc/commandline.py
--- old/osc-0.97/osc/commandline.py 2007-07-18 15:20:59.000000000 +0200
+++ new/osc-0.97/osc/commandline.py 2007-08-08 21:48:38.000000000 +0200
@@ -137,10 +137,12 @@
'\'-\' denotes standard input. ')
@cmdln.option('-e', '--edit', action='store_true',
help='edit metadata')
+ @cmdln.option('--delete', action='store_true',
+ help='delete a pattern file')
def do_meta(self, subcmd, opts, *args):
"""${cmd_name}: Show meta information, or edit it
- Show or edit build service metadata of type .
+ Show or edit build service metadata of type .
This command displays metadata on buildservice objects like projects,
packages, or users. The type of metadata is specified by the word after
@@ -150,6 +152,10 @@
prjconf denotes the (build) configuration of a project.
pkg denotes metadata of a buildservice package.
user denotes the metadata of a user.
+ pattern denotes installation patterns defined for a project.
+
+ To list patterns, use 'osc meta pattern PRJ'. An additional argument
+ will be the pattern file to view or edit.
With the --edit switch, the metadata can be edited. Per default, osc
opens the program specified by the environmental variable EDITOR with a
@@ -162,9 +168,10 @@
while it is edited.
usage:
- osc meta ARGS...
- osc meta -e|--edit [-c|--create] ARGS...
- osc meta -F|--file ARGS...
+ osc meta ARGS...
+ osc meta -e|--edit [-c|--create] ARGS...
+ osc meta -F|--file ARGS...
+ osc meta pattern --delete PRJ PATTERN
${cmd_option_list}
"""
@@ -177,14 +184,16 @@
cmd = args[0]
del args[0]
- if cmd == 'pkg':
- required_args = 2
+ if cmd in ['pkg']:
+ min_args, max_args = 2, 2
+ elif cmd in ['pattern']:
+ min_args, max_args = 1, 2
else:
- required_args = 1
- if len(args) < required_args:
+ min_args, max_args = 1, 1
+ if len(args) < min_args:
print >>sys.stderr, 'Too few arguments.'
return 2
- if len(args) > required_args:
+ if len(args) > max_args:
print >>sys.stderr, 'Too many arguments.'
return 2
@@ -197,9 +206,18 @@
project = args[0]
elif cmd == 'user':
user = args[0]
+ elif cmd == 'pattern':
+ project = args[0]
+ if len(args) > 1:
+ pattern = args[1]
+ else:
+ pattern = None
+ # enforce pattern argument if needed
+ if opts.edit or opts.file:
+ sys.exit('a pattern file argument is required.')
# show
- if not opts.edit:
+ if not opts.edit and not opts.file and not opts.delete:
if cmd == 'prj':
sys.stdout.write(''.join(show_project_meta(conf.config['apiurl'], project)))
elif cmd == 'pkg':
@@ -210,6 +228,15 @@
r = get_user_meta(conf.config['apiurl'], user)
if r:
sys.stdout.write(''.join(r))
+ elif cmd == 'pattern':
+ if pattern:
+ r = show_pattern_meta(conf.config['apiurl'], project, pattern)
+ if r:
+ sys.stdout.write(''.join(r))
+ else:
+ r = show_pattern_metalist(conf.config['apiurl'], project)
+ if r:
+ sys.stdout.write('\n'.join(r) + '\n')
# edit
if opts.edit and not opts.file:
@@ -233,6 +260,11 @@
edit=True,
path_args=(quote_plus(user)),
template_args=(user, user))
+ elif cmd == 'pattern':
+ edit_meta(metatype='pattern',
+ edit=True,
+ path_args=(project, pattern),
+ template_args=None)
# upload file
if opts.file:
@@ -265,6 +297,21 @@
data=f,
edit=opts.edit,
path_args=(quote_plus(user)))
+ elif cmd == 'pattern':
+ edit_meta(metatype='pattern',
+ data=f,
+ edit=opts.edit,
+ path_args=(project, pattern))
+
+
+ # delete
+ if opts.delete:
+ path = metatypes[cmd]['path']
+ if cmd == 'pattern':
+ path = path % (project, pattern)
+ u = makeurl(conf.config['apiurl'], [path])
+ else:
+ sys.exit('The --delete switch is only for pattern metadata.')
@@ -404,7 +451,7 @@
def do_deletepac(self, subcmd, opts, project, package):
- """${cmd_name}: Delete a packge on the repository server
+ """${cmd_name}: Delete a package on the repository server
${cmd_usage}
${cmd_option_list}
@@ -729,7 +776,6 @@
osc add FILE [FILE...]
${cmd_option_list}
"""
-
if not args:
print >>sys.stderr, 'Missing argument.'
self.do_help([None, 'add'])
@@ -822,7 +868,7 @@
conf.config['do_commits'] = True
for p in pacs:
-
+ msg = ''
if conf.config['do_commits']:
if opts.message:
msg = opts.message
@@ -831,48 +877,7 @@
msg = open(opts.file).read()
except:
sys.exit('could not open file \'%s\'.' % opts.file)
- else:
- msg = ''
-
- # commit only if the upstream revision is the same as the working copy's
- upstream_rev = show_upstream_rev(p.apiurl, p.prjname, p.name)
- if p.rev != upstream_rev:
- print >>sys.stderr, 'Working copy \'%s\' is out of date (rev %s vs rev %s).' \
- % (p.absdir, p.rev, upstream_rev)
- print >>sys.stderr, 'Looks as if you need to update it first.'
- return 1
-
- if not p.todo:
- p.todo = p.filenamelist_unvers + p.filenamelist
-
- for filename in p.todo:
- st = p.status(filename)
- if st == 'A' or st == 'M':
- p.todo_send.append(filename)
- print 'Sending %s' % filename
- elif st == 'D':
- p.todo_delete.append(filename)
- print 'Deleting %s' % filename
-
- if not p.todo_send and not p.todo_delete:
- print 'nothing to do for package %s' % p.name
- continue
-
- print 'Transmitting file data ',
- for filename in p.todo_delete:
- p.delete_source_file(filename)
- p.to_be_deleted.remove(filename)
- for filename in p.todo_send:
- sys.stdout.write('.')
- sys.stdout.flush()
- p.put_source_file(filename)
- if conf.config['do_commits']:
- p.rev = p.commit(msg=msg)
- print
- print 'Committed revision %s.' % p.rev
-
- p.update_local_filesmeta()
- p.write_deletelist()
+ p.commit(msg)
@cmdln.option('-r', '--revision', metavar='rev',
@@ -1331,7 +1336,7 @@
import osc.build
if not os.path.exists('/usr/lib/build/debtransform'):
- sys.stderr.write('Error: you need build.rpm with version 2006.6.14 or newer.\n')
+ 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
@@ -1609,6 +1614,189 @@
else:
print 'No matches found for \'%s\' in %ss' % (args[0], kind)
+
+ @cmdln.option('-p', '--project', metavar='project',
+ help='specify a project name')
+ @cmdln.option('-n', '--name', metavar='name',
+ help='specify a package name')
+ @cmdln.option('-t', '--title', metavar='title',
+ help='set a title')
+ @cmdln.option('-d', '--description', metavar='description',
+ help='set the description of the package')
+ @cmdln.option('', '--delete-old-files', action='store_true',
+ help='delete existing files from the server')
+ @cmdln.option('-c', '--commit', action='store_true',
+ help='commit the new files')
+ def do_importsrcpkg(self, subcmd, opts, srpm):
+ """${cmd_name}: import a new package from a src.rpm
+
+ A new package dir will be created inside the project dir
+ (if no project is specified and the current working dir is a
+ project dir the package will be created in this project). If
+ the package does not exist on the server it will be created
+ too otherwise the meta data of the existing package will be
+ updated (<title /> and <description />).
+ The src.rpm will be extracted into the package dir. If the
+ --disable-commit switch is not used all changes will be
+ committed.
+
+ SRPM is the path of the src.rpm in the local filesystem,
+ or an URL.
+
+ ${cmd_usage}
+ ${cmd_option_list}
+ """
+ import glob
+
+ if '://' in srpm:
+ print 'trying to fetch', srpm
+ import urlgrabber
+ urlgrabber.urlgrab(srpm)
+ srpm = os.path.basename(srpm)
+
+ srpm = os.path.abspath(srpm)
+
+ if opts.project:
+ project_dir = opts.project
+ else:
+ project_dir = os.getcwd()
+
+ if not is_project_dir(project_dir):
+ print >>sys.stderr, 'project dir \'%s\' does not exist' % project
+ sys.exit(1)
+ else:
+ project = store_read_project(project_dir)
+
+ rpm_data = data_from_rpm(srpm, 'Name:', 'Summary:', '%description')
+ if rpm_data:
+ title, pac, descr = ( v for k, v in rpm_data.iteritems() )
+ else:
+ title = pac = descr = ''
+
+ if opts.title:
+ title = opts.title
+ if opts.name:
+ pac = opts.name
+ if opts.description:
+ descr = opts.description
+
+ # title and description can be empty
+ if not pac:
+ print >>sys.stderr, 'please specify a package name with the \'--name\' option. ' \
+ 'The automatic detection failed'
+ sys.exit(1)
+
+ if not os.path.exists(os.path.join(project_dir, pac)):
+ os.mkdir(os.path.join(project_dir, pac))
+ os.chdir(os.path.join(project_dir, pac))
+ data = meta_exists(metatype='pkg',
+ path_args=(quote_plus(project), quote_plus(pac)),
+ template_args=(pac, conf.config['user']))
+ if data:
+ data = ET.fromstring(''.join(data))
+ data.find('title').text = title
+ data.find('description').text = ''.join(descr)
+ data = ET.tostring(data)
+ else:
+ print >>sys.stderr, 'error - cannot get meta data'
+ sys.exit(1)
+ edit_meta(metatype='pkg',
+ path_args=(quote_plus(project), quote_plus(pac)),
+ data = data)
+ init_package_dir(conf.config['apiurl'], project, pac, os.path.join(project, pac))
+ unpack_srcrpm(srpm, os.getcwd())
+ p = Package(os.getcwd())
+ if len(p.filenamelist) == 0 and opts.commit:
+ # TODO: moving this into the Package class
+ print 'Adding files to working copy...'
+ self.do_add(None, None, *glob.glob('*'))
+ p.commit()
+ elif opts.commit and opts.delete_old_files:
+ delete_server_files(conf.config['apiurl'], project, pac, p.filenamelist)
+ p.update_local_filesmeta()
+ # TODO: moving this into the Package class
+ print 'Adding files to working copy...'
+ self.do_add(None, None, *glob.glob('*'))
+ p.update_datastructs()
+ p.commit()
+ else:
+ print 'No files were committed to the server. Please ' \
+ 'commit them manually.'
+ print 'Package \'%s\' only imported locally' % pac
+ sys.exit(1)
+ else:
+ print >>sys.stderr, 'error - local package already exists'
+ sys.exit(1)
+
+ print 'Package \'%s\' imported successfully' % pac
+
+
+ @cmdln.option('-m', '--method', default='GET', metavar='HTTP_METHOD',
+ help='specify HTTP method to use (GET|PUT|DELETE|POST)')
+ @cmdln.option('-d', '--data', default=None, metavar='STRING',
+ help='specify string data for e.g. POST')
+ @cmdln.option('-f', '--file', default=None, metavar='FILE',
+ help='specify filename for e.g. PUT or DELETE')
+ def do_req(self, subcmd, opts, url):
+ """${cmd_name}: Issue an arbitrary request to the API
+
+ Useful for testing.
+
+ URL can be specified either partially (only the path component), or fully
+ with URL scheme and hostname ('http://...').
+
+ Note the global -A and -H options (see osc help).
+
+ Examples:
+ osc req /source/home:poeml
+ osc req -m PUT -f /etc/fstab source/home:poeml/test5/myfstab
+
+ ${cmd_usage}
+ ${cmd_option_list}
+ """
+
+ if not opts.method in ['GET', 'PUT', 'POST', 'DELETE']:
+ sys.exit('unknown method %s' % opts.method)
+
+ if not url.startswith('http'):
+ if not url.startswith('/'):
+ url = '/' + url
+ url = conf.config['apiurl'] + url
+
+ try:
+ r = http_request(opts.method,
+ url,
+ data=opts.data,
+ file=opts.file)
+
+ except urllib2.HTTPError, e:
+ if e.code == 400:
+ print >>sys.stderr, e
+ print >>sys.stderr, e.read()
+ sys.exit(1)
+ if e.code == 500:
+ print >>sys.stderr, e
+ # this may be unhelpful... because it may just print a big blob of uninteresting
+ # ichain html and javascript... however it could potentially be useful if the orign
+ # server returns an information body
+ if conf.config['http_debug']:
+ print >>sys.stderr, e.read()
+ sys.exit(1)
+ else:
+ sys.exit('unexpected error')
+
+ try:
+ out = r.read()
+ except:
+ sys.exit('failed to read from file object')
+
+ sys.stdout.write(out)
+
+
+
+# fini!
+###############################################################################
+
# load subcommands plugged-in locally
plugin_dirs = ['/var/lib/osc-plugins', os.path.expanduser('~/.osc-plugins')]
for plugin_dir in plugin_dirs:
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/osc-0.97/osc/conf.py new/osc-0.97/osc/conf.py
--- old/osc-0.97/osc/conf.py 2007-07-16 11:45:17.000000000 +0200
+++ new/osc-0.97/osc/conf.py 2007-08-08 15:24:52.000000000 +0200
@@ -122,6 +122,15 @@
global cookiejar
+ # HTTPS proxy is not supported by urllib2. It only leads to an error
+ # or, at best, a warning.
+ # https://bugzilla.novell.com/show_bug.cgi?id=214983
+ # https://bugzilla.novell.com/show_bug.cgi?id=298378
+ if 'https_proxy' in os.environ:
+ del os.environ['https_proxy']
+ if 'HTTPS_PROXY' in os.environ:
+ del os.environ['HTTPS_PROXY']
+
if config['http_debug']:
# brute force
def urllib2_debug_init(self, debuglevel=0):
@@ -225,6 +234,8 @@
except:
sys.exit('option %s requires an integer value' % i)
+ packagecachedir = os.path.expanduser(config['packagecachedir'])
+
# transform 'url1, url2, url3' form into a list
if type(config['urllist']) == str:
config['urllist'] = [ i.strip() for i in config['urllist'].split(',') ]
diff -urN --exclude=CVS --exclude=.cvsignore --exclude=.svn --exclude=.svnignore old/osc-0.97/osc/core.py new/osc-0.97/osc/core.py
--- old/osc-0.97/osc/core.py 2007-07-16 19:06:06.000000000 +0200
+++ new/osc-0.97/osc/core.py 2007-08-04 23:11:31.000000000 +0200
@@ -57,8 +57,8 @@
<arch>x86_64</arch>
<arch>i586</arch>
</repository>
- <repository name="SUSE_Linux_10.2">
- <path project="SUSE:SL-10.2" repository="standard" />
+ <repository name="openSUSE_10.2">
+ <path project="openSUSE:10.2" repository="standard"/>
<arch>x86_64</arch>
<arch>i586</arch>
</repository>
@@ -132,6 +132,13 @@
Revision: %s
"""
+new_pattern_template = """\
+<!-- See http://svn.opensuse.org/svn/zypp/trunk/libzypp/zypp/parser/yum/schema/patterns.rng -->
+
+<pattern>
+</pattern>
+"""
+
buildstatus_symbols = {'succeeded': '.',
'disabled': ' ',
'expansion error': 'E',
@@ -192,7 +199,6 @@
class Package:
"""represent a package (its directory) and read/keep/write its metadata"""
def __init__(self, workingdir):
- import fnmatch
self.dir = workingdir
self.absdir = os.path.abspath(self.dir)
self.storedir = os.path.join(self.dir, store)
@@ -203,41 +209,12 @@
self.name = store_read_package(self.dir)
self.apiurl = store_read_apiurl(self.dir)
- files_tree = read_filemeta(self.dir)
- files_tree_root = files_tree.getroot()
-
- self.rev = files_tree_root.get('rev')
- self.srcmd5 = files_tree_root.get('srcmd5')
-
- self.filenamelist = []
- self.filelist = []
- for node in files_tree_root.findall('entry'):
- try:
- f = File(node.get('name'),
- node.get('md5'),
- int(node.get('size')),
- int(node.get('mtime')))
- except:
- # okay, a very old version of _files, which didn't contain any metadata yet...
- f = File(node.get('name'), '', 0, 0)
- self.filelist.append(f)
- self.filenamelist.append(f.name)
-
- self.to_be_deleted = read_tobedeleted(self.dir)
- self.in_conflict = read_inconflict(self.dir)
+ self.update_datastructs()
self.todo = []
self.todo_send = []
self.todo_delete = []
- # gather unversioned files, but ignore some stuff
- self.excluded = [ i for i in os.listdir(self.dir)
- for j in exclude_stuff
- if fnmatch.fnmatch(i, j) ]
- self.filenamelist_unvers = [ i for i in os.listdir(self.dir)
- if i not in self.excluded
- if i not in self.filenamelist ]
-
def info(self):
return info_templ % (self.dir, self.apiurl, self.srcmd5, self.rev)
@@ -320,18 +297,57 @@
shutil.copy2(os.path.join(self.dir, n), os.path.join(self.storedir, n))
def commit(self, msg=''):
-
- query = []
- query.append('cmd=commit')
- query.append('rev=upload')
- query.append('user=%s' % conf.config['user'])
- query.append('comment=%s' % quote_plus(msg))
- u = makeurl(self.apiurl, ['source', self.prjname, self.name], query=query)
- #print u
- f = http_POST(u)
- root = ET.parse(f).getroot()
- rev = int(root.get('rev'))
- return rev
+ # commit only if the upstream revision is the same as the working copy's
+ upstream_rev = show_upstream_rev(self.apiurl, self.prjname, self.name)
+ if self.rev != upstream_rev:
+ print >>sys.stderr, 'Working copy \'%s\' is out of date (rev %s vs rev %s).' \
+ % (self.absdir, self.rev, upstream_rev)
+ print >>sys.stderr, 'Looks as if you need to update it first.'
+ sys.exit(1)
+
+ if not self.todo:
+ self.todo = self.filenamelist_unvers + self.filenamelist
+
+ for filename in self.todo:
+ st = self.status(filename)
+ if st == 'A' or st == 'M':
+ self.todo_send.append(filename)
+ print 'Sending %s' % filename
+ elif st == 'D':
+ self.todo_delete.append(filename)
+ print 'Deleting %s' % filename
+
+ if not self.todo_send and not self.todo_delete:
+ print 'nothing to do for package %s' % self.name
+ sys.exit(1)
+
+ print 'Transmitting file data ',
+ for filename in self.todo_delete:
+ self.delete_source_file(filename)
+ self.to_be_deleted.remove(filename)
+ for filename in self.todo_send:
+ sys.stdout.write('.')
+ sys.stdout.flush()
+ self.put_source_file(filename)
+ # all source files are committed - now comes the log
+ if conf.config['do_commits']:
+ query = []
+ query.append('cmd=commit')
+ query.append('rev=upload')
+ query.append('user=%s' % conf.config['user'])
+ query.append('comment=%s' % quote_plus(msg))
+ u = makeurl(self.apiurl, ['source', self.prjname, self.name], query=query)
+ #print u
+ f = http_POST(u)
+ root = ET.parse(f).getroot()
+ self.rev = int(root.get('rev'))
+ print
+ print 'Committed revision %s.' % self.rev
+ else:
+ print
+
+ self.update_local_filesmeta()
+ self.write_deletelist()
def write_conflictlist(self):
if len(self.in_conflict) == 0:
@@ -409,7 +425,45 @@
f = open(os.path.join(self.storedir, '_files'), 'w')
f.write(meta)
f.close()
-
+
+ def update_datastructs(self):
+ """
+ Update the internal data structures if the local _files
+ file has changed (e.g. update_local_filesmeta() has been
+ called).
+ """
+ import fnmatch
+ files_tree = read_filemeta(self.dir)
+ files_tree_root = files_tree.getroot()
+
+ self.rev = files_tree_root.get('rev')
+ self.srcmd5 = files_tree_root.get('srcmd5')
+
+ self.filenamelist = []
+ self.filelist = []
+ for node in files_tree_root.findall('entry'):
+ try:
+ f = File(node.get('name'),
+ node.get('md5'),
+ int(node.get('size')),
+ int(node.get('mtime')))
+ except:
+ # okay, a very old version of _files, which didn't contain any metadata yet...
+ f = File(node.get('name'), '', 0, 0)
+ self.filelist.append(f)
+ self.filenamelist.append(f.name)
+
+ self.to_be_deleted = read_tobedeleted(self.dir)
+ self.in_conflict = read_inconflict(self.dir)
+
+ # gather unversioned files, but ignore some stuff
+ self.excluded = [ i for i in os.listdir(self.dir)
+ for j in exclude_stuff
+ if fnmatch.fnmatch(i, j) ]
+ self.filenamelist_unvers = [ i for i in os.listdir(self.dir)
+ if i not in self.excluded
+ if i not in self.filenamelist ]
+
def update_local_pacmeta(self):
"""
Update the local _meta file in the store.
@@ -550,14 +604,9 @@
'with --specfile'
sys.exit(1)
- summary, descr = read_meta_from_spec(specfile)
-
- if not summary and not descr:
- print >>sys.stderr, 'aborting'
- sys.exit(1)
- else:
- self.summary = summary
- self.descr = descr
+ data = read_meta_from_spec(specfile, 'Summary:', '%description')
+ self.summary = data['Summary:']
+ self.descr = data['%description']
def update_package_meta(self):
@@ -902,6 +951,26 @@
return f.readlines()
+def show_pattern_metalist(apiurl, prj):
+ url = makeurl(apiurl, ['source', prj, '_pattern'])
+ f = http_GET(url)
+ tree = ET.parse(f)
+ r = [ node.get('name') for node in tree.getroot() ]
+ r.sort()
+ return r
+
+
+def show_pattern_meta(apiurl, prj, pattern):
+ url = makeurl(apiurl, ['source', prj, '_pattern', pattern])
+ try:
+ f = http_GET(url)
+ except urllib2.HTTPError, e:
+ print >>sys.stderr, 'error getting pattern \'%s\' for project \'%s\'' % (pattern, prj)
+ print >>sys.stderr, e
+ sys.exit(1)
+ return f.readlines()
+
+
class metafile:
"""metafile that can be manipulated and is stored back after manipulation."""
def __init__(self, url, input, change_is_required=False):
@@ -965,41 +1034,59 @@
'user': { 'path': 'person/%s',
'template': new_user_template,
},
+ 'pattern': { 'path': 'source/%s/_pattern/%s',
+ 'template': new_pattern_template,
+ },
}
-def edit_meta(metatype,
- path_args=None,
- data=None,
- template_args=None,
- edit=False,
- change_is_required=False):
+def meta_exists(metatype,
+ path_args=None,
+ template_args=None,
+ create_new=True):
+ data = None
+ url = make_meta_url(metatype, path_args)
+ try:
+ data = http_GET(url).readlines()
+ except urllib2.HTTPError, e:
+ if e.code == 404:
+ if create_new:
+ data = metatypes[metatype]['template']
+ if template_args:
+ data = data % template_args
+ else:
+ print >>sys.stderr, 'error getting metadata for type \'%s\' at URL \'%s\':' \
+ % (metatype, url)
+ return data
+
+def make_meta_url(metatype, path_args=None):
if metatype not in metatypes.keys():
sys.exit('unknown metatype %s' % metatype)
-
path = metatypes[metatype]['path']
+
if path_args:
path = path % path_args
- url = makeurl(conf.config['apiurl'], [path])
+ return makeurl(conf.config['apiurl'], [path])
+
+
+def edit_meta(metatype,
+ path_args=None,
+ data=None,
+ template_args=None,
+ edit=False,
+ change_is_required=False):
if not data:
- try:
- data = http_GET(url).readlines()
- except urllib2.HTTPError, e:
- if e.code == 404:
- data = metatypes[metatype]['template']
- if template_args:
- data = data % template_args
- else:
- print >>sys.stderr, 'error getting metadata for type \'%s\' at URL \'%s\':' \
- % (metatype, url)
- print >>sys.stderr, e
- sys.exit(1)
+ data = meta_exists(metatype,
+ path_args,
+ template_args,
+ create_new=True)
if edit:
change_is_required = True
+ url = make_meta_url(metatype, path_args)
f=metafile(url, data, change_is_required)
if edit:
@@ -1033,45 +1120,62 @@
return ET.parse(StringIO(''.join(m))).getroot().get('rev')
-def read_meta_from_spec(specfile):
+def read_meta_from_spec(specfile, *args):
import codecs, locale
- """read Name, Summary and %description from spec file"""
+ """
+ Read tags and sections from spec file. To read out
+ a tag the passed argument must end with a colon. To
+ read out a section the passed argument must start with
+ a '%'.
+ This method returns a dictionary which contains the
+ requested data.
+ """
if not os.path.isfile(specfile):
print 'file \'%s\' is not a readable file' % specfile
- return (None, None)
+ sys.exit(1)
try:
lines = codecs.open(specfile, 'r', locale.getpreferredencoding()).readlines()
except UnicodeDecodeError:
lines = open(specfile).readlines()
- for line in lines:
- if line.startswith('Name:'):
- name = line.split(':')[1].strip()
- break
-
- summary = None
- for line in lines:
- if line.startswith('Summary:'):
- summary = line.split(':')[1].strip()
- break
- if summary == None:
- print 'cannot find \'Summary:\' tag'
- return (None, None)
+ tags = []
+ sections = []
+ spec_data = {}
+
+ for itm in args:
+ if itm.endswith(':'):
+ tags.append(itm)
+ elif itm.startswith('%'):
+ sections.append(itm)
+ else:
+ print >>sys.stderr, 'error - \'%s\' is not a tag nor a section' % itm
+ sys.exit(1)
- descr = []
- try:
- start = lines.index('%description\n') + 1
- except ValueError:
- print 'cannot find %description'
- return (None, None)
- for line in lines[start:]:
- if line.startswith('%'):
- break
- descr.append(line)
-
- return (summary, descr)
+ for tag in tags:
+ for line in lines:
+ if line.startswith(tag):
+ spec_data[tag] = line.split(':')[1].strip()
+ break
+ if not spec_data.has_key(tag):
+ print >>sys.stderr, 'error - tag \'%s\' does not exist' % tag
+ sys.exit(1)
+
+ for section in sections:
+ try:
+ start = lines.index(section + '\n') + 1
+ except ValueError:
+ print >>sys.stderr, 'error - section \'%s\' does not exist' % section
+ sys.exit(1)
+ data = []
+ for line in lines[start:]:
+ if line.startswith('%'):
+ break
+ data.append(line)
+ spec_data[section] = data
+
+ return spec_data
def get_user_meta(apiurl, user):
@@ -1300,15 +1404,31 @@
def delete_package(apiurl, prj, pac):
-
u = makeurl(apiurl, ['source', prj, pac])
- http_DELETE(u)
+ try:
+ http_DELETE(u)
+ except urllib2.HTTPError, e:
+ if e.code == 404:
+ print >>sys.stderr, 'Package \'%s\' does not exist' % pac
+ sys.exit(1)
+ else:
+ print >>sys.stderr, 'an unexpected error occured while deleting ' \
+ '\'%s\'' % pac
+ sys.exit(1)
def delete_project(apiurl, prj):
-
u = makeurl(apiurl, ['source', prj])
- http_DELETE(u)
+ try:
+ http_DELETE(u)
+ except urllib2.HTTPError, e:
+ if e.code == 404:
+ print >>sys.stderr, 'Package \'%s\' does not exist' % pac
+ sys.exit(1)
+ else:
+ print >>sys.stderr, 'an unexpected error occured while deleting ' \
+ '\'%s\'' % pac
+ sys.exit(1)
def get_platforms(apiurl):
@@ -1367,7 +1487,11 @@
rmap['arch'] = node.get('arch')
statusnode = node.find('status')
- rmap['status'] = statusnode.get('code')
+ try:
+ rmap['status'] = statusnode.get('code')
+ except:
+ # code can be missing when package is too new:
+ return {}
if rmap['status'] in ['expansion error', 'broken']:
rmap['status'] += ': ' + statusnode.find('details').text
@@ -1780,3 +1904,151 @@
return result
else:
return None
+
+def delete_tmpdir(tmpdir):
+ """
+ This method deletes a tempdir. This tempdir
+ must be located under /tmp/$DIR. If "tmpdir" is not
+ a valid tempdir it'll return False. If os.unlink() / os.rmdir()
+ throws an exception we will return False too - otherwise
+ True.
+ """
+
+ # small security checks
+ if os.path.islink(tmpdir):
+ return False
+ elif os.path.abspath(tmpdir) == '/':
+ return False
+
+ head, tail = os.path.split(tmpdir)
+ if not head.startswith('/tmp') or not tail:
+ return False
+
+ if not os.path.isdir(tmpdir):
+ return False
+
+ for dirpath, dirnames, filenames in os.walk(tmpdir, topdown=False):
+ for file in filenames:
+ try:
+ os.unlink(os.path.join(dirpath, file))
+ except:
+ return False
+ for dirname in dirnames:
+ try:
+ os.rmdir(os.path.join(dirpath, dirname))
+ except:
+ return False
+ try:
+ os.rmdir(tmpdir)
+ except:
+ return False
+ return True
+
+def unpack_srcrpm(srpm, dir, *files):
+ """
+ This method unpacks the passed srpm into the
+ passed dir. If arguments are passed to the \'files\' tuple
+ only this files will be unpacked.
+ """
+ if not is_srcrpm(srpm):
+ print >>sys.stderr, 'error - \'%s\' is not a source rpm.' % srpm
+ sys.exit(1)
+ curdir = os.getcwd()
+ if not os.path.isdir(dir):
+ dir = curdir
+ else:
+ os.chdir(dir)
+ cmd = 'rpm2cpio %s | cpio -i %s &> /dev/null' % (srpm, ' '.join(files))
+ ret = os.system(cmd)
+ if ret != 0:
+ print >>sys.stderr, 'error \'%s\' - cannot extract \'%s\'' % (ret, srpm)
+ sys.exit(1)
+ os.chdir(curdir)
+
+def tag_to_rpmpy(tag):
+ """
+ maps a spec file tag/section to a valid
+ rpm-python RPMTAG
+ """
+
+ try:
+ import rpm
+ tags = { 'Name:' : rpm.RPMTAG_NAME,
+ 'Summary:' : rpm.RPMTAG_SUMMARY,
+ '%description' : rpm.RPMTAG_DESCRIPTION
+ }
+ if tag in tags.keys():
+ return tags[tag]
+ else:
+ return None
+ except ImportError:
+ return None
+
+def data_from_rpm(rpm_file, *rpmdata):
+ """
+ This method reads the given rpmdata
+ from a rpm.
+ """
+
+ try:
+ import rpm
+ ts = rpm.TransactionSet()
+ file = open(rpm_file, 'r')
+ header = ts.hdrFromFdno(file.fileno())
+ file.close()
+ data = {}
+ for itm in rpmdata:
+ rpmpy = tag_to_rpmpy(itm)
+ if rpmpy:
+ data[itm] = header[rpmpy]
+ else:
+ print >>sys.stderr, 'invalid data \'%s\'' % itm
+ sys.exit(1)
+ return data
+ except ImportError:
+ print >>sys.stderr, 'warning: rpm-python not found'
+ return None
+
+def is_rpm(f):
+ """check if the named file is an RPM package"""
+ try:
+ h = open(f).read(4)
+ except:
+ return False
+
+ if h == '\xed\xab\xee\xdb':
+ return True
+ else:
+ return False
+
+def is_srcrpm(f):
+ """check if the named file is a source RPM"""
+
+ if not is_rpm(f):
+ return False
+
+ try:
+ h = open(f).read(8)
+ except:
+ return False
+
+ if h[7] == '\x01':
+ return True
+ else:
+ return False
+
+def delete_server_files(apiurl, prj, pac, files):
+ """
+ This method deletes the given filelist on the
+ server. No local data will be touched.
+ """
+
+ for file in files:
+ try:
+ u = makeurl(apiurl, ['source', prj, pac, file])
+ http_DELETE(u)
+ except:
+ # we do not handle all exceptions here - we need another solution
+ # see bug #280034
+ print >>sys.stderr, 'error while deleting file \'%s\'' % file
+ sys.exit(1)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Remember to have fun...
---------------------------------------------------------------------
To unsubscribe, e-mail: opensuse-commit+unsubscribe@opensuse.org
For additional commands, e-mail: opensuse-commit+help@opensuse.org