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