Показаны сообщения с ярлыком unicode. Показать все сообщения
Показаны сообщения с ярлыком unicode. Показать все сообщения

понедельник, 7 мая 2012 г.

Кроссплатформная проблема длинных имен файлов (Crossplatform long file name problem)


Хотя я демонстрирую ошибку на примере работы с системами контроля версий для MacOsX и Windows - это проблема более глобальная и поймать её вы можете в любой другой комбинации софта (да хоть в той же Samba).
Используемый подход решения проблемы наверняка не единственный, но, при этом, довольно универсален.

Различные файловые системы по разному хранят информацию об имени файла.
Из-за чего возникают коллизии если разработка ведётся многими людьми и у всех разные ОС.
В моём случае получилось так, что другой разработчик закоммитил в репозиторий файл длиной 180 русских букв.

$ echo "яяяяяяяяя яя яяяя яя яяяяяяяяяя яяяяяяяяя я яяяяяя я яяя яяяяяяяяя яяяяяяяяяяяяя яяяяяяяя я яяяяяяяяяяяяяяяяяя яяяяяя яя яяяяяя яяяяяяяяяяяяя яяяяяяяя яяяяя яяяяяя я яяя яяяяя яяя" | wc -m

180


Но

$ echo "яяяяяяяяя яя яяяя яя яяяяяяяяяя яяяяяяяяя я яяяяяя я яяя яяяяяяяяя яяяяяяяяяяяяя яяяяяяяя я яяяяяяяяяяяяяяяяяя яяяяяя яя яяяяяя яяяяяяяяяяяяя яяяяяяяя яяяяя яяяяяя я яяя яяяяя яяя" | wc -c

334

Русские буквы занимают два байта вместо одного.
При попытке создать такой файл под MacOsX на диске со стандартной файловой системой HFS+

$ touch "яяяяяяяяя яя яяяя яя яяяяяяяяяя яяяяяяяяя я яяяяяя я яяя яяяяяяяяя яяяяяяяяяяяяя яяяяяяяя я яяяяяяяяяяяяяяяяяя яяяяяя яя яяяяяя яяяяяяяяяяяяя яяяяяяяя яяяяя яяяяяя я яяя яяяяя яяя"

Получим странное

$ ls я*

яяяяяяяяя яя яяяя яя яяяяяяяяяя яяяяяяяяя я яяяяяя я яяя яяяяяяяяя яяяяяяяяяяяяя яяяяяяяя я яяяяяяяяяяяяяяяяяя яяяяяя яя яяяяяя яяяя#299CD031

Несмотря на заявляемые 255 знаков в кодировке UTF-16 (точно также в NTFS).
А если такой файл попробовать отредактировать, например с помощью vim, то после сохранения и выхода
:wq
файл исчезает.

Кстати, несмотря на то, что некоторые ФС поддерживают ещё более длинные имена, штатные утилиты linux, по всей вероятности, всё равно оперируют байтами и поэтому комманда touch мне стабильно выдавала ошибку: “File name too long”
Я, например, пробовал ReiserfFS под Ubuntu 12.04 LTS.

Возвращаясь к MacOs. Именно эту ошибку я поймал при попытке получить последние изменения из репозитория.
$ git svn rebase
First, rewinding head to replay your work on top of it...
error: cannot stat '$73_chars_4_deep_levels_path_with_spaces/$180_chars_file_name_with_spaces_too': File name too long
error: cannot stat '$73_chars_4_deep_levels_path_with_spaces/$180_chars_file_name_with_spaces_too': File name too long
error: cannot stat '$73_chars_4_deep_levels_path_with_spaces/$180_chars_file_name_with_spaces_too': File name too long
could not detach HEAD
rebase refs/remotes/git-svn: command returned error: 1

Первой моей идеей стало установить Windows внутри VirtualBox и там настроить Cygwin, т.к. в этой экосистеме файлы с длинными именами чувствуют себя вольготно.
Но, всё-таки, ОС внутри виртуальной машины - это довольно тяжелая штука в плане потребления ресурсов.
К тому же, Cygwin/MSysGit имеют и другие проблемы, с которыми приходится периодически бороться.

И, вот, после неудачи с Windows и Ubuntu, ко мне пришла идея попробовать создать образ диска с подходящей ФС средствами MacOS.

Хотя Linux и позволяет создавать и монтировать образы дисков даже более гибко, но надо что-то в нём докручивать, либо чтобы ядро поддерживало длинные уникодные имена, либо выставлять однобайтную локаль и на лету конвертировать файлы с помощью чего-то вроде iconv или средствами самого гита.

В комплекте с макосью идёт инструмент DiskUtility.
Где я для начала попробовал создать DMG-образы с NTFS.
Но, вероятно, имеющиеся у меня драйверы NTFS-3G и Tuxero, содержат ошибку.
В обоих случаях я получал до боли знакомый “File name too long”.

Удача меня ждала с ФС ExFat.



$ touch "яяяяяяяяя яя яяяя яя яяяяяяяяяя яяяяяяяяя я яяяяяя я яяя яяяяяяяяя яяяяяяяяяяяяя яяяяяяяя я яяяяяяяяяяяяяяяяяя яяяяяя яя яяяяяя яяяяяяяяяяяяя яяяяяяяя яяяяя яяяяяя я яяя яяяяя яяя"

И, ву-а-ля

$ ls я*

яяяяяяяяя яя яяяя яя яяяяяяяяяя яяяяяяяяя я яяяяяя я яяя яяяяяяяяя яяяяяяяяяяяяя яяяяяяяя я яяяяяяяяяяяяяяяяяя яяяяяя яя яяяяяя яяяяяяяяяяяяя яяяяяяяя яяяяя яяяяяя я яяя яяяяя яяя


После перемещения своего проекта в новый раздел, вся остальная операция прошла как по-маслу.

Далее, можно почитать про Unicode в названиях файлов в HFS.

четверг, 12 января 2012 г.

MacOSX: Unicode в названиях файлов в HFS


Недавно, я столкнулся с тем что Git на свежевыкачанном репозитории SVN упорно считает, что некоторые файлы находятся в состоянии Untracked.
Небольшое расследование вывело на следующее.

Unicode позволяет, если не совсем избавиться, то минимизировать проблемы национальных кодировок.
Большое число символов задаётся одним единственным кодом.
Но также имеется немаленькое количество знаков, которые составляются из пар кодов.
Наглядный пример, азиатские языки или различные служебные модификаторы вроде признака направления письма справа-налоево или знака ударения.

Кириллица не стала исключением.

При создании файлов, содержащих в наименовании композитные буквы, HFS сохраняет эти названия в виде двух отдельных знаков.

Для меня это стало сюрпризом, т.к. хотя по спецификации всё верно: буква "Й" является композицией следующих двух:

Тем не менее, буква имеет и единичный код

Аналогично и для "Ё".

Если невооружённым взглядом такое поведение или сложно или невозможно, то оно прекрасно наблюдается во время SSH-сессии.

Локально из терминала проблему можно воспроизвести если создать какой-либо файл, например:
$ touch Ё-моё.txt
И попровать затем выполнить автодополение клавишей [TAB].
$ ./Ё[TAB]
не срабатывает.

Но если ввести
$ ./Е[TAB]
то мы увидим нашу многострадальную "Ё".

Некоторые программы (в моём случае GIT и SVN) не могут корректно обработать такую ситуацию.
Файл, по-мнению алгоритмов, просто не существует.
То есть один и тот же файл в репозитории (попавший туда из других файловых систем) и хранящийся локально (в HFS) считается двумя разными файлами.

Пока мне не попалось подходящего решения или обходного пути.
И, похоже, что необходимо заводить тикет с багой.


Далее, можно почитать про проблему длинных имён в HFS+