mirror of
https://github.com/openSUSE/osc.git
synced 2024-12-26 01:46:13 +01:00
- added new "repairwc" command which tries to repair an inconsistent working copy
This commit is contained in:
parent
cb935861c8
commit
9ad14a1d9c
@ -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
|
||||
|
||||
|
@ -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!
|
||||
###############################################################################
|
||||
|
||||
|
69
osc/core.py
69
osc/core.py
@ -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)
|
||||
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user