diff --git a/CREDITS b/CREDITS
new file mode 100644
index 00000000..b3f96fac
--- /dev/null
+++ b/CREDITS
@@ -0,0 +1,5 @@
+There is a number of people who have helped:
+
+Marcus Rueckert - help and countless suggestions
+Christoph Thiel - patch enabling build log following.
+Adrian Schroeter - one-liner showing how to handle an error ;-)
diff --git a/TODO b/TODO
index 3cd58acc..70c60347 100644
--- a/TODO
+++ b/TODO
@@ -2,17 +2,10 @@
- implement 'info' command
- implement 'mv' command
-- editing of user data
-
-
-
-
- editmeta: the API will return a 500 if the xml is broken... the document
could be presented for editing again in that case
- updatepacmetafromspec -- is that useful?
In which form would this be integrated best?
-- clean up the way how a .oscrc template is being added: at the moment, there
- are two places doing this
checkin:
diff --git a/osc/build.py b/osc/build.py
index cfe64b29..4c68d718 100644
--- a/osc/build.py
+++ b/osc/build.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
-# Copyright (C) 2006 Peter Poeml. All rights reserved.
+# Copyright (C) 2006 Peter Poeml / Novell Inc. All rights reserved.
# This program is free software; it may be used, copied, modified
# and distributed under the terms of the GNU General Public Licence,
# either version 2, or (at your option) any later version.
diff --git a/osc/commandline.py b/osc/commandline.py
index 980c52d2..e9147d2e 100755
--- a/osc/commandline.py
+++ b/osc/commandline.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
-# Copyright (C) 2006 Peter Poeml. All rights reserved.
+# Copyright (C) 2006 Peter Poeml / Novell Inc. All rights reserved.
# This program is free software; it may be used, copied, modified
# and distributed under the terms of the GNU General Public Licence,
# either version 2, or (at your option) any later version.
@@ -134,6 +134,20 @@ usage: osc editmeta FooPrj # edit meta of project 'FooPrj'
edit_meta(project, None)
+def edituser(args):
+ """edituser: Edit user meta information
+usage: osc edituser
+
+If the named user id does not exist, it will be created.
+ """
+
+ if not args or len(args) != 1:
+ user = conf.config['user']
+ else:
+ user = args[0]
+ edit_user_meta(user)
+
+
def linkpac(args):
""""Link" a package to another package -- possibly cross-project.
@@ -473,6 +487,8 @@ usage: osc ci # current dir
for filename in p.todo_delete:
p.delete_source_file(filename)
p.to_be_deleted.remove(filename)
+ if conf.config['do_commits'] == '1':
+ p.commit(msg='MESSAGE')
p.update_filesmeta()
p.write_deletelist()
@@ -606,17 +622,17 @@ usage: osc resolved
p.clear_from_conflictlist(filename)
-def userid(args):
- """id: show metadata about user
+def usermeta(args):
+ """usermeta: show metadata about user
-usage: osc id
+usage: osc usermeta
"""
if not args:
print 'this command requires at least one argument'
sys.exit(1)
- r = get_user_id(args[0])
+ r = get_user_meta(args[0])
if r:
print ''.join(r)
@@ -842,6 +858,9 @@ BUILD_ROOT or OSC_BUILD_ROOT overrides the build-root.
import osc.build
+ if not os.path.exists('/usr/lib/build/debsort'):
+ sys.exit('Error: you need build.rpm with version 2006.6.14 or newer.\nSee http://software.opensuse.org/download/openSUSE:/Tools/')
+
builddist = os.getenv('BUILD_DIST')
if builddist:
#sys.argv[4] = sys.argv[1]
@@ -981,7 +1000,8 @@ cmd_dict = {
help: ['help'],
buildhistory: ['buildhistory', 'buildhist'],
linkpac: ['linkpac'],
- userid: ['id'], # <- small difference here
+ usermeta: ['usermeta'],
+ edituser: ['edituser'],
init: ['init'], # depracated
log: ['log'],
ls: ['ls', 'list'],
diff --git a/osc/conf.py b/osc/conf.py
index fd824482..29d49891 100644
--- a/osc/conf.py
+++ b/osc/conf.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
-# Copyright (C) 2006 Peter Poeml. All rights reserved.
+# Copyright (C) 2006 Peter Poeml / Novell Inc. All rights reserved.
# This program is free software; it may be used, copied, modified
# and distributed under the terms of the GNU General Public Licence,
# either version 2, or (at your option) any later version.
@@ -56,6 +56,9 @@ DEFAULTS = { 'apisrv': 'api.opensuse.org',
# direct access to "full" tree
'http://api.opensuse.org/rpm/%(project)s/%(repository)s/_repository/%(buildarch)s/%(name)s',
],
+
+ # switched off for now (testing)
+ 'do_commits': '0',
}
new_conf_template = """
diff --git a/osc/core.py b/osc/core.py
index b3e11a05..2b3c05b9 100755
--- a/osc/core.py
+++ b/osc/core.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
-# Copyright (C) 2006 Peter Poeml. All rights reserved.
+# Copyright (C) 2006 Peter Poeml / Novell Inc. All rights reserved.
# This program is free software; it may be used, copied, modified
# and distributed under the terms of the GNU General Public Licence,
# either version 2, or (at your option) any later version.
@@ -97,6 +97,24 @@ HERE
"""
+new_user_template = """\
+
+ %(user)s
+ PUT_EMAIL_ADDRESS_HERE
+ PUT_REAL_NAME_HERE
+
+
+
+
+
+
+
+
+
+
+
+
+"""
buildstatus_symbols = {'succeeded': '.',
'disabled': ' ',
@@ -271,10 +289,22 @@ class Package:
# escaping '+' in the URL path (note: not in the URL query string) is
# only a workaround for ruby on rails, which swallows it otherwise
u = makeurl(['source', self.prjname, self.name, pathname2url(n)])
+ if conf.config['do_commits'] == '1':
+ u += '?rev=upload'
othermethods.putfile(u, conf.config['user'], conf.config['pass'], file = os.path.join(self.dir, n))
shutil.copy2(os.path.join(self.dir, n), os.path.join(self.storedir, n))
+ def commit(self, msg=''):
+ import othermethods
+
+ u = makeurl(['source', self.prjname, self.name])
+ u += '?cmd=commit&rev=upload'
+ u += '&user=%s' % conf.config['user']
+ u += '&comment=%s' % quote_plus(msg)
+ #print u
+ f = urlopen(u, data='')
+ #print f.read()
def write_conflictlist(self):
if len(self.in_conflict) == 0:
@@ -721,7 +751,7 @@ def edit_meta(prj, pac, template=new_package_templ, change_is_required=True):
m = urllib2.urlopen(u).readlines()
except urllib2.HTTPError, e:
if e.code == 404:
- m = template % (pac, conf.config['username'])
+ m = template % (pac, conf.config['user'])
else:
print 'error getting package meta for project \'%s\' package \'%s\':' % (prj, pac)
print e
@@ -734,7 +764,7 @@ def edit_meta(prj, pac, template=new_package_templ, change_is_required=True):
m = urllib2.urlopen(u).readlines()
except urllib2.HTTPError, e:
if e.code == 404:
- m = new_project_templ % (prj, conf.config['username'])
+ m = new_project_templ % (prj, conf.config['user'])
else:
print 'error getting package meta for project \'%s\':' % prj
print e
@@ -760,6 +790,42 @@ def edit_meta(prj, pac, template=new_package_templ, change_is_required=True):
print 'Done.'
+def edit_user_meta(user, change_is_required=True):
+ import othermethods
+ import tempfile
+
+ u = makeurl(['person', quote_plus(user)])
+
+ try:
+ m = urllib2.urlopen(u).readlines()
+ except urllib2.HTTPError, e:
+ if e.code == 404:
+ m = new_user_template % { 'user': user }
+ else:
+ print 'error getting metadata for user \'%s\':' % user
+ print e
+ sys.exit(1)
+
+ (fd, filename) = tempfile.mkstemp(prefix = 'osc_edituser.', suffix = '.xml', dir = '/tmp')
+ f = os.fdopen(fd, 'w')
+ f.write(''.join(m))
+ f.close()
+ timestamp = os.path.getmtime(filename)
+
+ editor = os.getenv('EDITOR', default='vim')
+ os.system('%s %s' % (editor, filename))
+
+ if change_is_required == True and os.path.getmtime(filename) == timestamp:
+ print 'File unchanged. Not saving.'
+ os.unlink(filename)
+
+ else:
+ print 'Sending meta data...',
+ othermethods.putfile(u, conf.config['user'], conf.config['pass'], file=filename)
+ os.unlink(filename)
+ print 'Done.'
+
+
def show_files_meta(prj, pac):
f = urlopen(makeurl(['source', prj, pac]))
return f.readlines()
@@ -799,7 +865,7 @@ def read_meta_from_spec(specfile):
return name, summary, descr
-def get_user_id(user):
+def get_user_meta(user):
u = makeurl(['person', quote_plus(user)])
try:
f = urllib2.urlopen(u)
@@ -1001,14 +1067,14 @@ def delete_package(prj, pac):
import othermethods
u = makeurl(['source', prj, pac])
- othermethods.delfile(u, pac, conf.config['username'], conf.config['pass'])
+ othermethods.delfile(u, pac, conf.config['user'], conf.config['pass'])
def delete_project(prj):
import othermethods
u = makeurl(['source', prj])
- othermethods.delfile(u, prj, conf.config['username'], conf.config['pass'])
+ othermethods.delfile(u, prj, conf.config['user'], conf.config['pass'])
def get_platforms():
diff --git a/osc/fetch.py b/osc/fetch.py
index db5ab4cb..fd7c0eae 100644
--- a/osc/fetch.py
+++ b/osc/fetch.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
-# Copyright (C) 2006 Peter Poeml. All rights reserved.
+# Copyright (C) 2006 Peter Poeml / Novell Inc. All rights reserved.
# This program is free software; it may be used, copied, modified
# and distributed under the terms of the GNU General Public Licence,
# either version 2, or (at your option) any later version.
diff --git a/osc/othermethods.py b/osc/othermethods.py
index daa0c44b..9759dc6c 100755
--- a/osc/othermethods.py
+++ b/osc/othermethods.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
-# Copyright (C) 2006 Peter Poeml. All rights reserved.
+# Copyright (C) 2006 Peter Poeml / Novell Inc. All rights reserved.
# This program is free software; it may be used, copied, modified
# and distributed under the terms of the GNU General Public Licence,
# either version 2, or (at your option) any later version.
@@ -16,100 +16,81 @@ import httplib
import base64
import os
import urlparse
+from osc.core import __version__
BLOCKSIZE=4096
-def delfile(url, file, username, password):
+def request(method, url, username, password, file=None, strbuf=None):
+ """call with method = (PUT|DELETE)"""
- auth_string = base64.encodestring('%s:%s' % (username, password)).strip()
- u = urlparse.urlparse(url)
- host = u[1]
- path = u[2]
+ if method == 'PUT':
+ if file == None and strbuf == None:
+ print >>sys.stderr, 'putting a file requires either a filename or a string buffer'
+ sys.exit(1)
+ if strbuf:
+ size = len(strbuf)
+ else:
+ size = os.path.getsize(file)
- conn = httplib.HTTP(host)
- conn.putrequest('DELETE', '%s' % path)
+ scheme, host, path, params, query, fragment = urlparse.urlparse(url)
+ if query:
+ path += '?' + query
+
+ if scheme == 'https':
+ conn = httplib.HTTPS(host)
+ elif scheme == 'http':
+ conn = httplib.HTTP(host)
+ else:
+ sys.exit('unknown scheme %s' % scheme)
+
+ # Headers
+ conn.putrequest(method, '%s' % path)
conn.putheader('Host', host)
+ conn.putheader('User-agent', 'osc/%s' % __version__)
+ auth_string = base64.encodestring('%s:%s' % (username, password)).strip()
conn.putheader('Authorization', 'Basic %s' % auth_string)
+ if method == 'PUT':
+ conn.putheader('Content-Type', 'text/plain')
+ conn.putheader('Content-Length', str(size))
conn.endheaders()
+ # Body
+ if method == 'PUT':
+ if strbuf:
+ conn.send(strbuf)
+ else:
+ fp = open(file, 'rb')
+ #n = 0
+ while 1:
+ buf = fp.read(BLOCKSIZE)
+ #n+=1
+ #if n % 10 == 0:
+ # print 'upload-sending blocknum=', n
+ # print '.',
+
+ if not buf: break
+
+ try:
+ conn.send(buf)
+ except:
+ sys.exit('ERROR uploading %s' % file)
+ fp.close()
reply, msg, headers = conn.getreply()
if reply != 200:
- print 'error deleting %s' % file
- print 'upload-DELETE reply=', reply, ' msg=', msg, 'headers=', headers
+ print >>sys.stderr, 'Error: can\'t %s \'%s\'' % (method, url)
+ print >>sys.stderr, 'reply:', reply
+ print >>sys.stderr, '\nDebugging output follows.\nurl:\n%s\nheaders:\n%s\nresponse:\n%s' % (url, headers, msg)
+
+
+
+def delfile(url, file, username, password):
+ return request('DELETE', url, username, password, file=file)
def putfile(url, username, password, file=None, strbuf=None):
-
- if file == None and strbuf == None:
- print >>sys.stderr, 'putfile requires either a filename or a string buffer'
- sys.exit(1)
-
- if strbuf:
- size = len(strbuf)
- else:
- size = os.stat(file)[6]
-
- auth_string = base64.encodestring('%s:%s' % (username, password)).strip()
-
- u = urlparse.urlparse(url)
- host = u[1]
- path = u[2]
-
- conn = httplib.HTTP(host)
- conn.putrequest('PUT', '%s' % path)
- conn.putheader('Host', host)
- conn.putheader('Content-Type', 'text/plain')
- conn.putheader('Content-Length', str(size))
- conn.putheader('Authorization', 'Basic %s' % auth_string)
- conn.endheaders()
-
- if strbuf:
- conn.send(strbuf)
- else:
- fp = open(file, 'rb')
- n = 0
- while 1:
- buf = fp.read(BLOCKSIZE)
- n+=1
- if n % 10 == 0:
- #print 'upload-sending blocknum=', n
- #print '.',
- pass
-
- if not buf: break
-
- try:
- conn.send(buf)
- except:
- print
- print 'ERROR uploading %s' % file
- print
- os._exit(1)
-
- fp.close()
-
- reply, msg, headers = conn.getreply()
-
- if reply != 200:
- print 'error uploading %s' % file
- print 'upload-PUT reply=', reply, ' msg=', msg, 'headers=', headers
+ return request('PUT', url, username, password, file=file, strbuf=strbuf)
-def main():
- import sys
-
- username = 'yourusername'
- password = 'yourpassword'
- file = sys.argv[1]
- url = 'http://api.opensuse.org/source/exim/exim/%s' % os.path.basename(file)
-
- putfile(url, file, username, password)
-
- delfile(url, file, username, password)
-
-
-if __name__ == '__main__':
- main()
diff --git a/tests.py b/tests.py
index df476ebd..755e897c 100755
--- a/tests.py
+++ b/tests.py
@@ -4,7 +4,6 @@ import os, sys, time
import unittest
import shutil
-from osc.core import init_basicauth
from osc import commandline
PRJ = 'home:poeml'
@@ -25,11 +24,11 @@ class TestOsc(unittest.TestCase):
#####################################################################
- def testId(self):
+ def testUsermeta(self):
expect = """
poeml
poeml@suse.de
- Dr. Peter Peoml
+ Dr. Peter Poeml
@@ -50,12 +49,14 @@ class TestOsc(unittest.TestCase):
+
+
"""
- self.out, self.err = runosc('id poeml')
+ self.out, self.err = runosc('usermeta poeml')
self.assertEqual(self.err, '')
self.assertEqual(self.out, expect)
@@ -91,7 +92,7 @@ class TestOsc(unittest.TestCase):
def testMetaPac(self):
self.out, self.err = runosc('meta Apache apache2')
self.assertEqual(self.err, '')
- self.assert_('' in self.out)
+ self.assert_('' in self.out)
#####################################################################
@@ -251,8 +252,6 @@ def touch(filename):
if __name__ == '__main__':
- init_basicauth()
-
#unittest.main()
oldpwd = os.getcwd()
suite = unittest.makeSuite(TestOsc)