From d6bdc3712fcf34f38f5f48ee0a21895f9eae7d26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcus=20H=C3=BCwe?= Date: Mon, 30 Jul 2007 11:12:42 +0000 Subject: [PATCH] - some more work on importsrcpkg(): * by default the new files will be comitted (if it is a new package or if there are no source files on the server) * added --disable-commit option switch to import the package only locally * added --delete-old-files option switch to delete old files from the server. - some changes in the Package class: * extended existing commit() method to do all the commit work (before it was done in the do_commit() method). * moved stuff from the constructor into a new method (update_datastructs()). --- osc/commandline.py | 75 +++++++++------------- osc/core.py | 151 ++++++++++++++++++++++++++++++++------------- 2 files changed, 136 insertions(+), 90 deletions(-) diff --git a/osc/commandline.py b/osc/commandline.py index e69f0600..da0633fd 100755 --- a/osc/commandline.py +++ b/osc/commandline.py @@ -868,7 +868,6 @@ class Osc(cmdln.Cmdln): conf.config['do_commits'] = True for p in pacs: - if conf.config['do_commits']: if opts.message: msg = opts.message @@ -879,48 +878,7 @@ class Osc(cmdln.Cmdln): 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 - else: - print - - p.update_local_filesmeta() - p.write_deletelist() + p.commit(msg) @cmdln.option('-r', '--revision', metavar='rev', @@ -1666,6 +1624,10 @@ class Osc(cmdln.Cmdln): 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('', '--disable-commit', action='store_true', + help='do not commit the new files') def do_importsrcpkg(self, subcmd, opts, srpm): """${cmd_name}: import a new package from a src.rpm @@ -1675,7 +1637,9 @@ class Osc(cmdln.Cmdln): the package does not exist on the server it will be created too otherwise the meta data of the existing package will be updated ( and <description />). - The src.rpm will be extracted into the package dir. + 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. @@ -1742,8 +1706,27 @@ class Osc(cmdln.Cmdln): data = data) init_package_dir(conf.config['apiurl'], project, pac, os.path.join(project, pac)) unpack_srcrpm(srpm, os.getcwd()) - print 'Adding files to working copy...' - self.do_add(None, {}, *glob.glob('*')) + p = Package(os.getcwd()) + if len(p.filenamelist) == 0 and not opts.disable_commit: + # TODO: moving this into the Package class + print 'Adding files to working copy...' + self.do_add(None, None, *glob.glob('*')) + p.commit() + elif not opts.disable_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 'The package \'%s\' already exists on the server or the ' \ + '\'--disable-commit\' switch was used. Please commit ' \ + 'this working copy manually or use the ' \ + '\'--delete-old-files\' option.' % pac + print 'Package \'%s\' only imported locally' % pac + sys.exit(1) else: print >>sys.stderr, 'error - package already exists' sys.exit(1) diff --git a/osc/core.py b/osc/core.py index ab58b98d..408eb64c 100755 --- a/osc/core.py +++ b/osc/core.py @@ -199,7 +199,6 @@ class Project: 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) @@ -210,41 +209,12 @@ class Package: 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) @@ -327,18 +297,57 @@ class Package: 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: @@ -416,7 +425,45 @@ class Package: 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. @@ -1992,3 +2039,19 @@ def is_srcrpm(f): 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)