diff --git a/osc/commandline.py b/osc/commandline.py index 7975fecc..33130f43 100755 --- a/osc/commandline.py +++ b/osc/commandline.py @@ -103,6 +103,39 @@ usage: osc editmeta FooPrj # edit meta of project 'FooPrj' edit_meta(project, None) +def linkpac(args): + """"Link" a package to another package -- possibly cross-project. + +usage: osc linkpac SOURCEPRJ SOURCEPAC DESTPRJ [DESTPAC] + +The DESTPAC name is optional; the source packages' name will be used if +DESTPAC is omitted. + +Afterwards, you will want to 'co DESTPRJ DESTPAC' and edit _link and/or add patches. + + """ + + if not args or len(args) < 3: + print 'missing argument' + print + print linkpac.func_doc + sys.exit(1) + + + 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 'error: source and destination are the same' + sys.exit(1) + link_pac(src_project, src_package, dst_project, dst_package) + + def updatepacmetafromspec(args): """Update package meta information from a specfile @@ -727,6 +760,7 @@ cmd_dict = { editmeta: ['editmeta'], help: ['help'], history: ['history', 'hist'], + linkpac: ['linkpac'], userid: ['id'], # <- small difference here init: ['init'], # depracated log: ['log'], diff --git a/osc/core.py b/osc/core.py index b2d1e1e1..f919ae15 100755 --- a/osc/core.py +++ b/osc/core.py @@ -258,7 +258,7 @@ 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)]) - othermethods.putfile(u, os.path.join(self.dir, n), username, password) + othermethods.putfile(u, username, password, file = os.path.join(self.dir, n)) shutil.copy2(os.path.join(self.dir, n), os.path.join(self.storedir, n)) @@ -427,7 +427,7 @@ rev: %s self.descr = descr - def update_pac_meta(self): + def update_pac_meta(self, template=new_package_templ): import othermethods import tempfile @@ -439,7 +439,7 @@ rev: %s except urllib2.HTTPError, e: if e.code == 404: print 'package does not exist yet... creating it' - m = new_package_templ % (pac, username) + m = template % (pac, username) else: print 'error getting package meta for project \'%s\' package \'%s\':' % (prj, pac) print e @@ -467,7 +467,7 @@ rev: %s if repl == 'y': print 'Sending meta data...', u = makeurl(['source', self.prjname, self.name, '_meta']) - othermethods.putfile(u, filename, username, password) + othermethods.putfile(u, username, password, file=filename) print 'Done.' else: print 'discarding', filename @@ -732,7 +732,7 @@ def check_store_version(dir): def meta_get_packagelist(prj): - u = makeurl(['source', prj, '_meta']) + u = makeurl(['source', prj]) try: f = urllib2.urlopen(u) @@ -748,7 +748,7 @@ def meta_get_packagelist(prj): tree = ET.parse(f) root = tree.getroot() - return [ node.get('name') for node in root.findall('package') ] + return [ node.get('name') for node in root.findall('entry') ] def meta_get_filelist(prj, package): @@ -800,7 +800,7 @@ def show_package_meta(prj, pac): return f.readlines() -def edit_meta(prj, pac): +def edit_meta(prj, pac, template=new_package_templ, change_is_required=True): import othermethods import tempfile @@ -813,7 +813,7 @@ def edit_meta(prj, pac): m = urllib2.urlopen(u).readlines() except urllib2.HTTPError, e: if e.code == 404: - m = new_package_templ % (pac, username) + m = template % (pac, username) else: print 'error getting package meta for project \'%s\' package \'%s\':' % (prj, pac) print e @@ -841,13 +841,13 @@ def edit_meta(prj, pac): editor = os.getenv('EDITOR', default='vim') os.system('%s %s' % (editor, filename)) - if os.path.getmtime(filename) == timestamp: + 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, filename, username, password) + othermethods.putfile(u, username, password, file=filename) os.unlink(filename) print 'Done.' @@ -1001,6 +1001,55 @@ def checkout_package(project, package): os.chdir(olddir) +def link_pac(src_project, src_package, dst_project, dst_package): + """ + create a linked package + - "src" is the original package + - "dst" is the "link" package that we are creating here + """ + + import othermethods + import tempfile + + + src_meta = show_package_meta(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', '%s') + tree.find('person').set('userid', '%s') + buf = StringIO() + tree.write(buf) + src_meta = buf.getvalue() + + + edit_meta(dst_project, dst_package, template=src_meta, change_is_required=False) + + # create the _link file + # but first, make sure not to overwrite an existing one + if '_link' in meta_get_filelist(dst_project, dst_package): + print + print '_link file already exists...! Aborting' + sys.exit(1) + + print 'Creating _link...', + link_template = """\ + + + + + + +""" % (src_project, src_package) + + u = makeurl(['source', dst_project, dst_package, '_link']) + othermethods.putfile(u, username, password, strbuf = link_template) + print 'Done.' + + def get_platforms(): f = urlopen(makeurl(['platform'])) tree = ET.parse(f) diff --git a/osc/othermethods.py b/osc/othermethods.py index 2e670c32..99610ed5 100755 --- a/osc/othermethods.py +++ b/osc/othermethods.py @@ -17,7 +17,7 @@ import base64 import os import urlparse -BLOCKSIZE=1024 +BLOCKSIZE=4096 def delfile(url, file, username, password): @@ -36,16 +36,21 @@ def delfile(url, file, username, password): reply, msg, headers = conn.getreply() - if reply == 200: - #print 'done' - pass - else: + if reply != 200: print 'error deleting %s' % file print 'upload-DELETE reply=', reply, ' msg=', msg, 'headers=', headers -def putfile(url, file, username, password): - size = os.stat(file)[6] +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() @@ -61,26 +66,26 @@ def putfile(url, file, username, password): conn.putheader('Authorization', 'Basic %s' % auth_string) conn.endheaders() - 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 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 - conn.send(buf) - fp.close() + if not buf: break + conn.send(buf) + fp.close() reply, msg, headers = conn.getreply() - if reply == 200: - pass - #print 'done' - else: + if reply != 200: print 'error uploading %s' % file print 'upload-PUT reply=', reply, ' msg=', msg, 'headers=', headers