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

Merge pull request #1234 from dmach/mv-fix-regression

mv: Fix regression
This commit is contained in:
Daniel Mach 2023-01-26 10:34:20 +01:00 committed by GitHub
commit faf1223ed9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 34 deletions

View File

@ -0,0 +1,21 @@
Feature: `osc mv` command
# common steps for all scenarios
Background:
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"
Scenario: Run `osc mv <file> <new-name>` in a package checkout
When I execute osc with args "mv test-pkgA.changes new-name.changes"
Then the exit code is 0
And I execute osc with args "status"
And stdout is
"""
A new-name.changes
D test-pkgA.changes
"""
And file "{context.osc.temp}/test:factory/test-pkgA/test-pkgA.changes" does not exist
And file "{context.osc.temp}/test:factory/test-pkgA/new-name.changes" exists

View File

@ -9159,11 +9159,11 @@ Please submit there instead, or use --nodevelproject to force direct submission.
os.rename(source, dest) os.rename(source, dest)
try: try:
tgt_pkg[0].addfile(os.path.basename(dest)) tgt_pkg.addfile(os.path.basename(dest))
except oscerr.PackageFileConflict: except oscerr.PackageFileConflict:
# file is already tracked # file is already tracked
pass pass
src_pkg[0].delete_file(os.path.basename(source), force=opts.force) src_pkg.delete_file(os.path.basename(source), force=opts.force)
@cmdln.option('-d', '--delete', action='store_true', @cmdln.option('-d', '--delete', action='store_true',
help='delete option from config or reset option to the default)') help='delete option from config or reset option to the default)')

View File

@ -1224,7 +1224,14 @@ class Package:
def __init__(self, workingdir, progress_obj=None, size_limit=None, wc_check=True): def __init__(self, workingdir, progress_obj=None, size_limit=None, wc_check=True):
global store global store
self.dir = workingdir self.todo = []
if os.path.isfile(workingdir) or not os.path.exists(workingdir):
# workingdir is a file
# workingdir doesn't exist -> it points to a non-existing file in a working dir (e.g. during mv)
workingdir, todo_entry = os.path.split(workingdir)
self.todo.append(todo_entry)
self.dir = workingdir or "."
self.absdir = os.path.abspath(self.dir) self.absdir = os.path.abspath(self.dir)
self.store = Store(self.dir) self.store = Store(self.dir)
self.storedir = os.path.join(self.absdir, store) self.storedir = os.path.join(self.absdir, store)
@ -1251,8 +1258,6 @@ class Package:
'of the working copy afterwards (via \'osc status %s\')' % (self.dir, self.dir, self.dir) 'of the working copy afterwards (via \'osc status %s\')' % (self.dir, self.dir, self.dir)
raise oscerr.WorkingCopyInconsistent(self.prjname, self.name, dirty_files, msg) raise oscerr.WorkingCopyInconsistent(self.prjname, self.name, dirty_files, msg)
self.todo = []
def __repr__(self): def __repr__(self):
return super().__repr__() + f"({self.prjname}/{self.name})" return super().__repr__() + f"({self.prjname}/{self.name})"
@ -1272,28 +1277,23 @@ class Package:
""" """
packages = [] packages = []
for path in paths: for path in paths:
# TODO: match only dirs, remove the code for resolving files into Package objects
orig_path = path
path_is_file = os.path.isfile(path)
if path_is_file:
path = os.path.dirname(path) or "."
package = cls(path, progress_obj) package = cls(path, progress_obj)
seen_package = None
try: try:
# re-use an existing package # re-use an existing package
seen_package_index = packages.index(package) seen_package_index = packages.index(package)
package = packages[seen_package_index] seen_package = packages[seen_package_index]
if os.path.abspath(path) != package.absdir:
raise oscerr.PackageExists(package.prjname, package.name, "Duplicate package")
except ValueError: except ValueError:
# use a new package instance pass
packages.append(package)
if path_is_file: if seen_package:
# XXX: modifying 'todo' is an unexpected side-effect # merge package into seen_package
todo_entry = os.path.basename(orig_path) if seen_package.absdir != package.absdir:
if todo_entry not in package.todo: raise oscerr.PackageExists(package.prjname, package.name, "Duplicate package")
package.todo.append(todo_entry) seen_package.merge(package)
else:
# use the new package instance
packages.append(package)
return packages return packages
@ -1306,21 +1306,30 @@ class Package:
packages = [] packages = []
failed_to_load = [] failed_to_load = []
for path in paths: for path in paths:
# TODO: match only dirs, remove the code for resolving files into Package objects
orig_path = path
path_is_file = os.path.isfile(path)
if path_is_file:
path = os.path.dirname(path) or "."
try: try:
package = cls(path, progress_obj) package = cls(path, progress_obj)
if path_is_file:
# XXX: modifying 'todo' is an unexpected side-effect
package.todo = [os.path.basename(orig_path)]
if package in packages:
raise oscerr.PackageExists(package.prjname, package.name, "Duplicate package")
packages.append(package)
except oscerr.NoWorkingCopy: except oscerr.NoWorkingCopy:
failed_to_load.append(orig_path) failed_to_load.append(path)
continue
# the following code is identical to from_paths()
seen_package = None
try:
# re-use an existing package
seen_package_index = packages.index(package)
seen_package = packages[seen_package_index]
except ValueError:
pass
if seen_package:
# merge package into seen_package
if seen_package.absdir != package.absdir:
raise oscerr.PackageExists(package.prjname, package.name, "Duplicate package")
seen_package.merge(package)
else:
# use the new package instance
packages.append(package)
return packages, failed_to_load return packages, failed_to_load
def wc_check(self): def wc_check(self):
@ -2260,7 +2269,9 @@ class Package:
yield diff_add_delete(f, False, revision) yield diff_add_delete(f, False, revision)
def merge(self, otherpac): def merge(self, otherpac):
self.todo += otherpac.todo for todo_entry in otherpac.todo:
if todo_entry not in self.todo:
self.todo.append(todo_entry)
def __str__(self): def __str__(self):
r = """ r = """

View File

@ -69,6 +69,36 @@ class TestPackageFromPaths(OscTestCase):
def _get_fixtures_dir(self): def _get_fixtures_dir(self):
return FIXTURES_DIR return FIXTURES_DIR
def test_package_object_dir(self):
path = "projectA/pkgA"
path = os.path.join(self.tmpdir, 'osctest', path)
pac = osc.core.Package(path)
self.assertEqual(pac.name, "pkgA")
self.assertEqual(pac.prjname, "projectA")
self.assertEqual(pac.apiurl, "http://localhost")
self.assertEqual(pac.todo, [])
def test_package_object_file(self):
path = "projectA/pkgA/pkgA.spec"
path = os.path.join(self.tmpdir, 'osctest', path)
pac = osc.core.Package(path)
self.assertEqual(pac.name, "pkgA")
self.assertEqual(pac.prjname, "projectA")
self.assertEqual(pac.apiurl, "http://localhost")
self.assertEqual(pac.todo, ["pkgA.spec"])
def test_package_object_file_missing(self):
path = "projectA/pkgA/missing-file"
path = os.path.join(self.tmpdir, 'osctest', path)
pac = osc.core.Package(path)
self.assertEqual(pac.name, "pkgA")
self.assertEqual(pac.prjname, "projectA")
self.assertEqual(pac.apiurl, "http://localhost")
self.assertEqual(pac.todo, ["missing-file"])
def test_single_package(self): def test_single_package(self):
paths = ["projectA/pkgA"] paths = ["projectA/pkgA"]
paths = [os.path.join(self.tmpdir, 'osctest', i) for i in paths] paths = [os.path.join(self.tmpdir, 'osctest', i) for i in paths]