1
0
mirror of https://github.com/openSUSE/osc.git synced 2024-12-26 09:56:13 +01:00

- added new "repairwc" command which tries to repair an inconsistent working copy

This commit is contained in:
Marcus Huewe 2010-09-08 18:56:15 +02:00
parent cb935861c8
commit 9ad14a1d9c
4 changed files with 97 additions and 9 deletions

View File

@ -149,7 +149,7 @@ def run(prg):
print >>sys.stderr, e
return 1
except (oscerr.PackageExists, oscerr.PackageMissing), e:
except (oscerr.PackageExists, oscerr.PackageMissing, oscerr.WorkingCopyInconsistent), e:
print >>sys.stderr, e.msg
return 1

View File

@ -5977,7 +5977,34 @@ Please submit there instead, or use --nodevelproject to force direct submission.
p.todo = p.filenamelist
for f in p.todo:
p.revert(f)
def do_repairwc(self, subcmd, opts, *args):
"""${cmd_name}: try to repair an inconsistent working copy
Examples:
osc repairwc <path>
Note: if <path> is omitted it defaults to '.'
Warning: This command might delete some files in the storedir
(.osc). Please check the state of the wc afterwards (via 'osc status').
${cmd_usage}
${cmd_option_list}
"""
args = parseargs(args)
if len(args) < 1:
raise oscerr.WrongArgs('Too few arguments.')
elif len(args) > 1:
raise oscerr.WrongArgs('Too many arguments.')
try:
p = Package(args[0])
except oscerr.WorkingCopyInconsistent:
p = Package(args[0], wc_check=False)
p.wc_repair()
print 'done. Please check the state of the wc (via \'osc status\').'
else:
print >>sys.stderr, 'osc: working copy is not inconsistent'
# fini!
###############################################################################

View File

@ -773,7 +773,13 @@ class Project:
class Package:
"""represent a package (its directory) and read/keep/write its metadata"""
def __init__(self, workingdir, progress_obj=None, size_limit=None):
# should _meta be a required file?
REQ_STOREFILES = ('_project', '_package', '_apiurl', '_files', '_osclib_version')
OPT_STOREFILES = ('_to_be_added', '_to_be_deleted', '_in_conflict', '_in_update',
'_in_commit', '_meta', '_meta_mode', '_frozen', '_pulled', '_linkrepair', '_size_limit')
def __init__(self, workingdir, progress_obj=None, size_limit=None, wc_check=True):
global store
self.dir = workingdir
@ -791,9 +797,64 @@ class Package:
self.apiurl = store_read_apiurl(self.dir)
self.update_datastructs()
if wc_check and self.wc_check():
msg = 'Your working copy is in an inconsistent state.\n' \
'Please run \'osc repairwc\' (Note this might _remove_\n' \
'files from the .osc/ dir). Please check the state\n' \
'of the working copy afterwards (via \'osc status\')'
raise oscerr.WorkingCopyInconsistent(self.prjname, self.name, msg)
self.todo = []
def wc_check(self):
dirty = False
for fname in self.filenamelist:
if not os.path.exists(os.path.join(self.storedir, fname)) and not fname in self.skipped:
dirty = True
for fname in Package.REQ_STOREFILES:
if not os.path.isfile(os.path.join(self.storedir, fname)):
dirty = True
for fname in os.listdir(self.storedir):
if fname in Package.REQ_STOREFILES or fname in Package.OPT_STOREFILES or \
fname.startswith('_build'):
continue
elif fname in self.filenamelist and fname in self.skipped:
dirty = True
elif not fname in self.filenamelist:
dirty = True
for fname in self.to_be_deleted[:]:
if not fname in self.filenamelist:
dirty = True
for fname in self.in_conflict[:]:
if not fname in self.filenamelist:
dirty = True
return dirty
def wc_repair(self):
# all files which are present in the filelist have to exist in the storedir
for f in self.filelist:
# XXX: should we also check the md5?
if not os.path.exists(os.path.join(self.storedir, f.name)) and not f.name in self.skipped:
# if get_source_file fails we're screwed up...
get_source_file(self.apiurl, self.prjname, self.name, f.name,
targetfilename=os.path.join(self.storedir, f.name), revision=self.rev,
mtime=f.mtime)
for fname in os.listdir(self.storedir):
if fname in Package.REQ_STOREFILES or fname in Package.OPT_STOREFILES or \
fname.startswith('_build'):
continue
elif not fname in self.filenamelist or fname in self.skipped:
# this file does not belong to the storedir so remove it
os.unlink(os.path.join(self.storedir, fname))
for fname in self.to_be_deleted[:]:
if not fname in self.filenamelist:
self.to_be_deleted.remove(fname)
self.write_deletelist()
for fname in self.in_conflict[:]:
if not fname in self.filenamelist:
self.in_conflict.remove(fname)
self.write_conflictlist()
def info(self):
source_url = makeurl(self.apiurl, ['source', self.prjname, self.name])
r = info_templ % (self.prjname, self.name, self.absdir, self.apiurl, source_url, self.srcmd5, self.rev, self.linkinfo)
@ -1242,12 +1303,6 @@ class Package:
except:
# okay, a very old version of _files, which didn't contain any metadata yet...
f = File(node.get('name'), '', 0, 0)
# restore storefile in case it is lost (for whatever reason)
# XXX: this is a bad idea if we do a checkout - will be fixed later
if not os.path.exists(os.path.join(self.storedir, f.name)) and not f.name in self.skipped:
get_source_file(self.apiurl, self.prjname, self.name, f.name,
targetfilename=os.path.join(self.storedir, f.name), revision=files_tree_root.get('rev'),
mtime=f.mtime)
self.filelist.append(f)
self.filenamelist.append(f.name)

View File

@ -82,6 +82,12 @@ class PackageError(OscBaseError):
self.prj = prj
self.pac = pac
class WorkingCopyInconsistent(PackageError):
"""Exception raised when the working copy is in an inconsistent state"""
def __init__(self, prj, pac, msg):
PackageError.__init__(self, prj, pac)
self.msg = msg
class LinkExpandError(PackageError):
"""Exception raised when source link expansion fails"""
def __init__(self, prj, pac, msg):