Глава 7. Имена файлов и шаблоны совпадений

Содержание

7.1. Простое именование файлов
7.2. Запуск команд без указания имен файлов
7.3. Информация о том что произошло;
7.4. Использование шаблонов для указания файлов
7.4.1. glob-шаблоны в стиле shell
7.4.2. Шаблоны регулярных выражений
7.5. Фильтрация файлов
7.6. Постоянное игнорирование ненужных файлов и директорий
7.7. Регистрозависимость
7.7.1. Безопасное и переносимое хранилище
7.7.2. Определение конфликтов регистра символов
7.7.3. Исправление конфликта регистра символов

Mercurial предоставляет механизмы, которые позволят вам работать с именами файлов единообразным и выразительным образом.

7.1. Простое именование файлов

Mercurial использует единообразную технику «скрытую под капотом» для обработки имен файлов. Каждая команда ведет себе одинаково относительно имен файлов. Путь по которому команды работают с именами файламов следующий.

Если вы явно указываете имена реальных файлов, Mercurial работает именно с теми файлами, которые вы ожидаете.

$ hg add COPYING README examples/simple.py

Когда вы указываете имя директории, Mercurial интерпретирует это как «сделай что либо со всеми файлами в этой директории и во вложенных директориях». Mercurial обрабатывает файлы и поддиректории в указанной директории в алфавитном порядке. Когда Mercurial дойдет до каталога, то он рекурсивно спустится в него и произведет теже действия что и выше, перед продолжением обработки в текущем каталоге.

$ hg status src
? src/main.py
? src/watcher/_watcher.c
? src/watcher/watcher.py
? src/xyzzy.txt

7.2. Запуск команд без указания имен файлов

Команды Mercurial, которые работают с именами файлов имеют полезные, заданные по умолчанию поведения, когда вы вызываете их без параметров имен файлов или шаблонов имен. Ожидаемое поведение зависит от того, что делает команда. Вот несколько небольших правил которые вы можете использовать, чтобы предсказать то, что вероятно сделает команда, если вы не укажите имена с которой ей работать.

  • Большинство команд работают со всей рабочей директорией. Так например работает команда hg add.

  • Если результат команды нельзя или очень сложно отменить, то она вынудит вас указать как минимум одно имя или шаблон (см. ниже). Например, это защитит вас от случайного удаления файлов запуском команды hg remove без аргументов.

Легко обойти стандартное поведение если оно вас не устраивает. Если команда как правило работает с целым рабочим каталогом, вы можете ссылаться на него только в текущем каталоге или его подкаталогах, давая ему имя «.».

$ cd src
$ hg add -n
adding ../MANIFEST.in
adding ../examples/performant.py
adding ../setup.py
adding main.py
adding watcher/_watcher.c
adding watcher/watcher.py
adding xyzzy.txt
$ hg add -n .
adding main.py
adding watcher/_watcher.c
adding watcher/watcher.py
adding xyzzy.txt

Как видно выше, некоторые команды обычно выводят относительные имена от корня репозитория, даже если вы выполняете их в подкаталоге. Этаже команда напечатает имена файлов относительно вашего подкаталога, если вы дадите ей явные имена. Давайте выполним hg status из подкаталога и заставим ее работать со всем рабочим каталогом, печатая имена файлов относительно нашего подкаталога, передав ей вывод команды hg root.

$ hg status
A COPYING
A README
A examples/simple.py
? MANIFEST.in
? examples/performant.py
? setup.py
? src/main.py
? src/watcher/_watcher.c
? src/watcher/watcher.py
? src/xyzzy.txt
$ hg status `hg root`
A ../COPYING
A ../README
A ../examples/simple.py
? ../MANIFEST.in
? ../examples/performant.py
? ../setup.py
? main.py
? watcher/_watcher.c
? watcher/watcher.py
? xyzzy.txt

7.3. Информация о том что произошло;

К примеру команда hg add, использованная в предыдущем разделе илюстрирует нечто большее, чем просто помощь по командам Mercurial. Если команда воздействует на файл, который вы явно не задали в командной строке, она обычно выведет имя файла, чтобы вас не удивляли изменения.

Это правило наименьшего удивления — если вы явно именуете файл в командной строке, нет никакого смысла в повторении его снова вам. Если же Mercurial работает с файлом неявно, потому что вы не указали имени, или директории, или шаблона (см. ниже), безопаснее сказать вам что произошло.

Для команд, которые ведут себя так есть простой способ заставить их замочать, используя опцию -q. Вы также можете заставить их печатать имена файлов, даже если они явно заданы вами, используя опцию -v.

7.4. Использование шаблонов для указания файлов

В дополнение к работе с именами файлов и директорий, Mercurial предоставляет вам возможность использования шаблонов. Шаблоны Mercurial достаточно выразительны.

В Unix-подобных системах (Linux, MaxOS, и т.д.), работу по сопоставлению имен файлов шаблонам обычно выполняет интерпретатор (shell). В этих системах вы должны явно указать Mercurial, что указанное имя является шаблоном. В системе Windows, интерпретатор не раскрывает шаблоны, так что Mercurial автоматически идентифицирует имена как шаблоны, и раскрывает их для вас.

Для указания шаблона вместо обычного имени в командной строке используется следующий синтаксис:

syntax:patternbody

Таким образом, шаблон идентифицируется короткой строкой, указывающей тип шаблона, с последующим двоеточием, и содержимым шаблона за ним.

Mercurial поддерживает два типа синтаксиса шаблонов. Наиболее часто употребляется синтаксис glob. Это тот же самый вид сопоставления, используемый интерпретатором Unix и также должен быть знаком пользователям командной строки Windows.

Когда Mercurial выполняет автоматическое сопоставление с шаблоном в Windows, она использует glob синтаксис. Вы также можете опустить префикс «glob:» в Windows, но более безопасно явно указать его.

Синтаксис re более могущественный. Он предполагает что вы указали регулярное выражение (regexps) как шаблон.

Между прочим, в примерах далее обратите внимание что я делаю все возможное обрамляя все мои шаблоны в кавычки, чтобы они не раскрывались интерпретатором командной строки прежде чем их обработает Mercurial.

7.4.1. glob-шаблоны в стиле shell

Этот раздел посвящен краткому обзору видов шаблонов, которые вы можете использовать в glob шаблонах.

Символ «*» (звездочка) соотвествует любой строке в пределах одного каталога.

$ hg add 'glob:*.py'
adding main.py

Шаблон «**» (две звездочки) соответствует любой строке включая подкаталоги. Это не стандартный шаблон Unix, но он используется в некоторых популярных интерпретаторах командной строки и очень полезен.

$ cd ..
$ hg status 'glob:**.py'
A examples/simple.py
A src/main.py
? examples/performant.py
? setup.py
? src/watcher/watcher.py

Шаблон «?» соотвествует любому одиночному символу.

$ hg status 'glob:**.?'
? src/watcher/_watcher.c

Символ «[» открывает класс символов. Этот шаблон соотвествует любому одиночному символу в указанном классе. Класс оканчивается символом «]». Класс может содержать диапазоны в форме «a-f», которые раскрываются в «abcdef».

$ hg status 'glob:**[nr-t]'
? MANIFEST.in
? src/xyzzy.txt

Если первый символ после «[» в классе символов является «!», это инвертирует класс, делая его соотвествующим любому символу не из класса.

Символ «{» начинает группу подшаблонов, где вся группа соответствует если любой из шаблонов в ней совпадает. Символ «,» разделяет подшаблоны, а символ «}» закрывает группу.

$ hg status 'glob:*.{in,py}'
? MANIFEST.in
? setup.py

7.4.1.1. Внимание!

Не забывайте что если вы хотите соответствия в каком-либо каталоге вы не должны использовать «*<любой токен>», т.к. «*» работает только с одной директорией. Вместо него используйте «**» (две звездочки). Ниже пример иллюстрирующий различия.

$ hg status 'glob:*.py'
? setup.py
$ hg status 'glob:**.py'
A examples/simple.py
A src/main.py
? examples/performant.py
? setup.py
? src/watcher/watcher.py

7.4.2. Шаблоны регулярных выражений

Mercurial поддерживает теже регулярные выражения, что и язык программирования Python (используется движок regexp из Python-а). Синтаксис базируется на регулярных выражениях Perl, которые являются наиболее популярных диалектом (например он используется в Java).

Я не стану обсуждать диалект regexp в Mercurial т.к. он не часто используется. В любом случае регулярные выражения Perl хорошо документированы на множестве веб сайтов и в большом количестве книг. Вместо этого я сфокусируюсь на некоторых вещах, которые вы должны знать если хотите использовать регулярные выражения в Mercurial.

Регулярные выражения применяются к полному пути файла, относительно корня репозитория. Другими словами, даже если вы уже в поддиректории foo и хотите работать с файлами в поддиректории вы должны начать паттерн с «foo/».

Стоит отметить одну вещь: если вы знакомы с регулярными выражениями Perl - регулярные выражения Mercurial применяются с начала строки. Таким образом, regexp ищет совпадения с начала строки и не ищет совпадения где-нибудь внутри строки. Для поиска везде в строке вы должны начинать ваше регулярное выражение с «.*».

7.5. Фильтрация файлов

Mercurial не только позволяет вам указывать разными способами нужные файлы, он также дает вам возможность отсеивать ненужные файлы. Команды, работающие с именами принимают две опции для фильтрования.

  • -I, или --include, позволяет указать шаблон имен файлов, которые должны быть обработаны.

  • -X, или --exclude, дает возможность указать шаблон имен для исключения из обработки.

Вы можете указывать многократно и ту и другую опции в командной строке и смешивать их так, как вам нужно. Mercurial интерпретирует шаблоны используя glob синтаксис по умолчанию (но вы можете использовать синтаксис regexp).

Вы можете считать опцию -I filter как «обрабатывать только те файлы, которые совпадают с этим фильтром».

$ hg status -I '*.in'
? MANIFEST.in

Опцию -X filter проще всего понять как «обрабатывать только те файлы, которые не попадают под фильтр».

$ hg status -X '**.py' src
? src/watcher/_watcher.c
? src/xyzzy.txt

7.6. Постоянное игнорирование ненужных файлов и директорий

Когда вы создаете новое хранилище, то вероятно что со временем оно будет расти содержать файлы, которые не должны управляется Mercurial, но вы же не хотите, чтобы они перечислялись при каждом запуске hg status. Например, файлы «сборки продукта», которые создаются как часть сборки, но которые не должны управляться системой контроля версий. Чаще всего файлы продуктов сборки, создаются программными инструментами, такими как компиляторы. В качестве другого примера, множество текстовых редакторов складывают в каталог блокировки файлов, временные рабочие файлы и файлы резервных копии, которые он также не имеет смысла в управлении.

Чтобы Mercurial постоянно игнорировал такие файлы, нужно создать файл с именем .hgignore в корневом каталоге вашего репозитория. Вы должны добавить его командой hg add, так чтобы он стал отслеживаемым вместе с остальным содержимым репозиторием, так как он вероятно будет полезным сотрудникам.

По умолчанию файл .hgignore должен содержать список регулярных выражений, по одному в каждой строке. Пустые строки пропускаются. Большинство людей предпочитают помечать файлы, которые они хотят игнорировать с использованием «glob» синтаксиса, который мы описали выше, такой типичный файл .hgignore будет начинаться с директивы:

syntax: glob

Это говорит Mercurial интерпретировать строки, указанные ниже, с использованием модели glob, а не регулярных выражений.

Вот типичный вид файла .hgignore.

syntax: glob
# This line is a comment, and will be skipped.
# Empty lines are skipped too.

# Backup files left behind by the Emacs editor.
*~

# Lock files used by the Emacs editor.
# Notice that the "#" character is quoted with a backslash.
# This prevents it from being interpreted as starting a comment.
.\#*

# Temporary files used by the vim editor.
.*.swp

# A hidden file created by the Mac OS X Finder.
.DS_Store

7.7. Регистрозависимость

Если вы работаете в гетерогенной среде разработки, которая содержит как Linux (или другие Unix) системы так и системы с Mac или Windows, вы должны помнить, что они относятся к регистру («N» и «n» ) имен файлов, по разному. Это вероятно не очень, повлияет на вас, и это легко исправляется, если это произойдет, но это может удивить вас, если вы не знаете об этом.

Операционные и файловые системы отличаются по способам работы с регистром символов в именах файлов и директорий. Существует три основных модели работы с именами.

  • Полностью без учета регистра. Буквы в верхнем и нижнем регистрах считаются идентичными как при создании файла, так и при последующей работе с ним. Это поведение типично для файловых системы выросших из DOS.

  • Сохранение регистра, без его учета в дальнейшем. Когда создается файл или каталог его имя сохраняется так как было введено. Оно также отображается операционной системой в сохраненном регистре. Когда производится работа с файлом, то регистр не учитывается. Это стандартное поведение в Windows и MaxOS. Например имена foo и FoO идентичны с этой точки зрения. Подобная обработка прописных и строчных букв как взаимозаменяемых также известна как сворачивание регистра.

  • С учетом регистра. В этом случае имя файла существенно всегда. Имена foo и FoO идентифицируют разные файлы. Это стандартно для Linux и Unix систем и в них это используется по умолчанию.

В Unix-подобных системах возможно иметь любой или даже все вышеупомянутые способы обработки имен сразу. Например, если вы используете USB накопитель с файловой системой FAT32 в Linux, то имена файлов в этой файловой системе будут сохранять регистр, но при работе он не будет учитываться.

7.7.1. Безопасное и переносимое хранилище

Система хранилищ Mercurial регистронезависима. Она переводит имена файлов так, что они могут быть безопасно сохранены и на регистрозависимых, и на регистронезависимых файловых системах. Это означает, что вы можете использовать обычное копирование файлов, например, на USB-флешку и спокойно переносить на ней хранилище между компьютерами, использующими MacOS, Windows и Linux.

7.7.2. Определение конфликтов регистра символов

Когда операционная система работает в директории, Mercurial соблюдает политику именования принятую в файловой системе где расположена директория. Если файловая система позволяет сохранять регистр, но не учитывает его, Mercurial считает имена, различные по регистру, равнозначными.

Важным аспектом этого поведения является то что возможно сделать commit набора изменений в системе с учетом регистра в файловой системе (в Linux или Unix), которые вызовут проблемы у пользователей с другим типом файловой системы (Windows или MacOS). Если Linux-пользователь создаст файлы myfile.c и MyFile.C, оба будут успешно сохранены в репозитории и с ними можно будет работать на других Linux-машинах.

Если пользователь Windows или Mac зальет в свой репозиторий подобные изменения, то он не получит каких-то проблем, т.к. механизм хранения в репозитории Mercurial безопасен к регистру символов. В тоже время, как только он попытается сделать hg update в рабочем каталоге до этого набора изменений, или hg merge с ним, Mercurial определит конфликт имен файлов, которые файловая система трактует как идентичные и запретит обновление или слияние.

7.7.3. Исправление конфликта регистра символов

Если вы используете Windows или Mac в среде, где кто-то использует Linux или Unix, и Mercurial сообщает о проблемах с регистром, когда вы пытаетесь сделать hg update или hg merge, процедура исправления этого очень проста.

Просто найдите ближайшую машину с Linux или Unix, клонируйте на нее репозиторий и используйте команду hg rename для изменения имени на какое-то другое, так чтобы конфликта не было. Сохраните свои изменения (hg commit), сделайте hg pull или hg push в ваш Windows или MacOS репозитарий и hg update на ревизию без конфликта.

Список изменений с конфликтом регистра останется в истории вашего проекта и вы все еще будете не в состоянии выполнить hg update вашей рабочей директории к этому набору изменений в Windows или MacOS, но вы сможете продолжить разработку.