diff --git a/behave/features/repairwc.feature b/behave/features/repairwc.feature new file mode 100644 index 000000000..251429df1 --- /dev/null +++ b/behave/features/repairwc.feature @@ -0,0 +1,47 @@ +Feature: `osc repairwc` command + + +Scenario: Run `osc repairwc` on a project + Given I set working directory to "{context.osc.temp}" + And I execute osc with args "checkout test:factory" + And I set working directory to "{context.osc.temp}/test:factory" + When I execute osc with args "repairwc" + Then the exit code is 0 + When I execute osc with args "status" + Then the exit code is 0 + + +Scenario: Run `osc repairwc` on a project without .osc/_osclib_version + Given I set working directory to "{context.osc.temp}" + And I execute osc with args "checkout test:factory" + And I set working directory to "{context.osc.temp}/test:factory" + And I remove file "{context.osc.temp}/test:factory/.osc/_osclib_version" + When I execute osc with args "status" + Then the exit code is 1 + When I execute osc with args "repairwc" + Then the exit code is 0 + When I execute osc with args "status" + Then the exit code is 0 + + +Scenario: Run `osc repairwc` on a package + Given I set working directory to "{context.osc.temp}" + And I execute osc with args "checkout test:factory/test-pkgA" + And I set working directory to "{context.osc.temp}/test:factory/test-pkgA" + When I execute osc with args "repairwc" + Then the exit code is 0 + When I execute osc with args "status" + Then the exit code is 0 + + +Scenario: Run `osc repairwc` on a package without .osc/_osclib_version + Given I set working directory to "{context.osc.temp}" + And I execute osc with args "checkout test:factory/test-pkgA" + And I set working directory to "{context.osc.temp}/test:factory/test-pkgA" + And I remove file "{context.osc.temp}/test:factory/test-pkgA/.osc/_osclib_version" + When I execute osc with args "status" + Then the exit code is 1 + When I execute osc with args "repairwc" + Then the exit code is 0 + When I execute osc with args "status" + Then the exit code is 0 diff --git a/behave/features/steps/common.py b/behave/features/steps/common.py index ed1e37ff0..871ba31d3 100644 --- a/behave/features/steps/common.py +++ b/behave/features/steps/common.py @@ -194,6 +194,13 @@ def step_impl(context, source, destination): shutil.copyfile(source, destination) +@behave.step('I remove file "{path}"') +def step_impl(context, path): + # substitutions + path = path.format(context=context) + os.remove(path) + + @behave.step('file "{path}" exists') def step_impl(context, path): path = path.format(context=context) diff --git a/osc/commandline.py b/osc/commandline.py index 3a336a1d3..aa04934c7 100644 --- a/osc/commandline.py +++ b/osc/commandline.py @@ -10102,8 +10102,9 @@ def get_apiurl(apiurls): if is_project_dir(i): try: prj = Project(i, getPackageList=False) - except oscerr.WorkingCopyInconsistent as e: - if '_apiurl' in e.dirty_files and (not apiurl or not opts.force_apiurl): + except (oscerr.WorkingCopyInconsistent, oscerr.NoWorkingCopy) as e: + dirty_files = getattr(e, "dirty_files", []) + if '_apiurl' in dirty_files and (not apiurl or not opts.force_apiurl): apiurl = get_apiurl(apiurls) prj = Project(i, getPackageList=False, wc_check=False) prj.wc_repair(apiurl) @@ -10122,8 +10123,9 @@ def get_apiurl(apiurls): for pdir in pacs: try: p = Package(pdir) - except oscerr.WorkingCopyInconsistent as e: - if '_apiurl' in e.dirty_files and (not apiurl or not opts.force_apiurl): + except (oscerr.WorkingCopyInconsistent, oscerr.NoWorkingCopy) as e: + dirty_files = getattr(e, "dirty_files", []) + if '_apiurl' in dirty_files and (not apiurl or not opts.force_apiurl): apiurl = get_apiurl(apiurls) p = Package(pdir, wc_check=False) p.wc_repair(apiurl) diff --git a/osc/obs_scm/package.py b/osc/obs_scm/package.py index e72880f59..557296151 100644 --- a/osc/obs_scm/package.py +++ b/osc/obs_scm/package.py @@ -51,7 +51,7 @@ def __init__(self, workingdir, progress_obj=None, size_limit=None, wc_check=True self.dir = workingdir or "." self.absdir = os.path.abspath(self.dir) - self.store = osc_store.get_store(self.dir) + self.store = osc_store.get_store(self.dir, check=wc_check) self.store.assert_is_package() self.storedir = os.path.join(self.absdir, store) self.progress_obj = progress_obj @@ -178,8 +178,13 @@ def wc_check(self): def wc_repair(self, apiurl: Optional[str] = None): from ..core import get_source_file - store = Store(self.dir) + store = Store(self.dir, check=False) store.assert_is_package() + + # there was a time when osc did not write _osclib_version file; let's assume these checkouts have version 1.0 + if not store.exists("_osclib_version"): + store.write_string("_osclib_version", "1.0") + if not store.exists("_apiurl") or apiurl: if apiurl is None: msg = 'cannot repair wc: the \'_apiurl\' file is missing but ' \ diff --git a/osc/obs_scm/project.py b/osc/obs_scm/project.py index 60c712ff5..5a4b221c9 100644 --- a/osc/obs_scm/project.py +++ b/osc/obs_scm/project.py @@ -87,7 +87,7 @@ def __init__(self, dir, getPackageList=True, progress_obj=None, wc_check=True): self.dir = Path(dir) self.absdir = os.path.abspath(dir) - self.store = Store(dir) + self.store = Store(dir, check=wc_check) self.progress_obj = progress_obj self.name = store_read_project(self.dir) @@ -140,8 +140,13 @@ def wc_check(self): return dirty_files def wc_repair(self, apiurl: Optional[str] = None): - store = Store(self.dir) + store = Store(self.dir, check=False) store.assert_is_project() + + # there was a time when osc did not write _osclib_version file; let's assume these checkouts have version 1.0 + if not store.exists("_osclib_version"): + store.write_string("_osclib_version", "1.0") + if not store.exists("_apiurl") or apiurl: if apiurl is None: msg = 'cannot repair wc: the \'_apiurl\' file is missing but ' \ diff --git a/osc/obs_scm/store.py b/osc/obs_scm/store.py index 695d8e35b..4e008d4d2 100644 --- a/osc/obs_scm/store.py +++ b/osc/obs_scm/store.py @@ -345,7 +345,7 @@ def check_store_version(dir): v = '' if v == '': - msg = f'Error: "{os.path.abspath(dir)}" is not an osc package working copy.' + msg = f'Error: "{os.path.abspath(dir)}" is not an osc working copy.' if os.path.exists(os.path.join(dir, '.svn')): msg = msg + '\nTry svn instead of osc.' raise oscerr.NoWorkingCopy(msg)