Edit Book: When using the arrange into folders tool do not change the case of already existing folders in the book. Fixes #1633875 [Editor:Arrange Folders problem on Windows](https://bugs.launchpad.net/calibre/+bug/1633875)

This commit is contained in:
Kovid Goyal 2016-10-16 22:38:19 +05:30
parent c080a08b16
commit 9c7f9e5786
3 changed files with 26 additions and 2 deletions

View File

@ -484,7 +484,7 @@ class Container(ContainerBase): # {{{
return name_to_abspath(name, self.root) return name_to_abspath(name, self.root)
def exists(self, name): def exists(self, name):
''' True iff a file corresponding to the canonical name exists. Note ''' True iff a file/directory corresponding to the canonical name exists. Note
that this function suffers from the limitations of the underlying OS that this function suffers from the limitations of the underlying OS
filesystem, in particular case (in)sensitivity. So on a case filesystem, in particular case (in)sensitivity. So on a case
insensitive filesystem this will return True even if the case of name insensitive filesystem this will return True even if the case of name

View File

@ -267,10 +267,25 @@ def get_recommended_folders(container, names):
return {n:recommendations.get(mt_to_category(container, guess_type(os.path.basename(n))), opf_folder) for n in names} return {n:recommendations.get(mt_to_category(container, guess_type(os.path.basename(n))), opf_folder) for n in names}
def normalize_case(container, val):
parts = val.split('/')
ans = []
for i in range(len(parts)):
q = '/'.join(parts[:i+1])
x = container.name_to_abspath(q)
xl = parts[i].lower()
candidates = [c for c in os.listdir(os.path.dirname(x)) if c != parts[i] and c.lower() == xl]
ans.append(candidates[0] if candidates else parts[i])
return '/'.join(ans)
def rationalize_folders(container, folder_type_map): def rationalize_folders(container, folder_type_map):
all_names = set(container.mime_map) all_names = set(container.mime_map)
new_names = set() new_names = set()
name_map = {} name_map = {}
for key in tuple(folder_type_map):
val = folder_type_map[key]
folder_type_map[key] = normalize_case(container, val)
for name in all_names: for name in all_names:
if name.startswith('META-INF/'): if name.startswith('META-INF/'):
continue continue

View File

@ -12,7 +12,7 @@ from zipfile import ZipFile
from calibre import CurrentDir from calibre import CurrentDir
from calibre.ebooks.oeb.polish.tests.base import BaseTest, get_simple_book, get_split_book from calibre.ebooks.oeb.polish.tests.base import BaseTest, get_simple_book, get_split_book
from calibre.ebooks.oeb.polish.container import get_container as _gc, clone_container, OCF_NS from calibre.ebooks.oeb.polish.container import get_container as _gc, clone_container, OCF_NS
from calibre.ebooks.oeb.polish.replace import rename_files from calibre.ebooks.oeb.polish.replace import rename_files, rationalize_folders
from calibre.ebooks.oeb.polish.split import split, merge from calibre.ebooks.oeb.polish.split import split, merge
from calibre.utils.filenames import nlinks_file from calibre.utils.filenames import nlinks_file
from calibre.ptempfile import TemporaryFile, TemporaryDirectory from calibre.ptempfile import TemporaryFile, TemporaryDirectory
@ -264,3 +264,12 @@ class ContainerTests(BaseTest):
self.assertTrue(os.path.exists('.git/xxx')) self.assertTrue(os.path.exists('.git/xxx'))
self.assertTrue(os.path.exists('images/test-container.xyz')) self.assertTrue(os.path.exists('images/test-container.xyz'))
self.assertFalse(os.path.exists('images/cover.jpg')) self.assertFalse(os.path.exists('images/cover.jpg'))
def test_folder_type_map_case(self):
book = get_simple_book()
c = get_container(book)
c.add_file('Image/testcase.png', b'xxx')
rationalize_folders(c, {'image':'image'})
self.assertTrue(c.has_name('Image/testcase.png'))
self.assertTrue(c.exists('Image/testcase.png'))
self.assertFalse(c.has_name('image/testcase.png'))