mirror of
https://github.com/openSUSE/osc.git
synced 2024-12-27 02:16:12 +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
|
print >>sys.stderr, e
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
except (oscerr.PackageExists, oscerr.PackageMissing), e:
|
except (oscerr.PackageExists, oscerr.PackageMissing, oscerr.WorkingCopyInconsistent), e:
|
||||||
print >>sys.stderr, e.msg
|
print >>sys.stderr, e.msg
|
||||||
return 1
|
return 1
|
||||||
|
|
||||||
|
@ -5978,6 +5978,33 @@ Please submit there instead, or use --nodevelproject to force direct submission.
|
|||||||
for f in p.todo:
|
for f in p.todo:
|
||||||
p.revert(f)
|
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!
|
# fini!
|
||||||
###############################################################################
|
###############################################################################
|
||||||
|
|
||||||
|
69
osc/core.py
69
osc/core.py
@ -773,7 +773,13 @@ class Project:
|
|||||||
|
|
||||||
class Package:
|
class Package:
|
||||||
"""represent a package (its directory) and read/keep/write its metadata"""
|
"""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
|
global store
|
||||||
|
|
||||||
self.dir = workingdir
|
self.dir = workingdir
|
||||||
@ -791,9 +797,64 @@ class Package:
|
|||||||
self.apiurl = store_read_apiurl(self.dir)
|
self.apiurl = store_read_apiurl(self.dir)
|
||||||
|
|
||||||
self.update_datastructs()
|
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 = []
|
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):
|
def info(self):
|
||||||
source_url = makeurl(self.apiurl, ['source', self.prjname, self.name])
|
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)
|
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:
|
except:
|
||||||
# okay, a very old version of _files, which didn't contain any metadata yet...
|
# okay, a very old version of _files, which didn't contain any metadata yet...
|
||||||
f = File(node.get('name'), '', 0, 0)
|
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.filelist.append(f)
|
||||||
self.filenamelist.append(f.name)
|
self.filenamelist.append(f.name)
|
||||||
|
|
||||||
|
@ -82,6 +82,12 @@ class PackageError(OscBaseError):
|
|||||||
self.prj = prj
|
self.prj = prj
|
||||||
self.pac = pac
|
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):
|
class LinkExpandError(PackageError):
|
||||||
"""Exception raised when source link expansion fails"""
|
"""Exception raised when source link expansion fails"""
|
||||||
def __init__(self, prj, pac, msg):
|
def __init__(self, prj, pac, msg):
|
||||||
|
Loading…
Reference in New Issue
Block a user