**--extensions** — список расширений, сужающий список файлов в расчёте; множество ограничений разделяется запятыми, например, `'.go,.md'`
**--languages** — список языков (программирования, разметки и др.), сужающий список файлов в расчёте; множество ограничений разделяется запятыми например `'go,markdown'`
Принадлежность файла к языку программирования определяется с помощью его расширения.
Неизвестные языки никаких ограничений не накладывают. При их использовании можно написать warning в stderr.
**--exclude** — набор [Glob](https://en.wikipedia.org/wiki/Glob_(programming)) паттернов, исключающих файлы из расчёта
**--restrict-to** — набор Glob паттернов, исключающий все файлы, не удовлетворяющие ни одному из паттерну из набора
### Тесты
В [/tests/integration/testdata/bundles](test/integration/testdata/bundles) лежат запакованные git репозитории.
Каждый интеграционный тест ссылается на какой-нибудь бандл.
Как создать bundle? Находясь в git репозитории выполнить
```
git bundle create my.bundle --all
```
Как распаковать bundle? Находясь в пустой директории.
```
git clone /path/to/my.bundle .
```
### Ненавязчивые предложения
#### Project layout
В go есть [набор рекомендаций](https://github.com/golang-standards/project-layout) по организации структуры проекта.
И подпроект этого задания уже частично ему следует. Например, `main.go`, который вам нужно реализовать, лежит в [cmd/gitfame](./cmd/gitfame),
интеграционные тесты в `/test`.
В небольших проектах нет ничего плохого в том, чтобы весь код лежал плоско в корне.
Здесь же, для ознакомления предлагаем изучить общепринятый подход.
#### Cli
Можно познакомиться с [spf13/cobra](https://github.com/spf13/cobra),
популярной библиотекой для написания [cli](https://en.wikipedia.org/wiki/Command-line_interface).
В этой задаче cobra поможет распарсить аргументы, написать подробный help message, сделать алиасы для флагов.
### Git ликбез
Вся информация взята из [книги](https://github.com/pluralsight/git-internals-pdf/releases/download/v2.0/peepcode-git.pdf).
Смело советуем прочитать её всем, даже если в контексте задания вы знаете про Git достаточно.
---------
Объекты Git хранятся в специальной базе данных `Git Object Database` в директории .git.
В базе в сжатом виде хранятся объекты разных типов.
У каждого объекта есть SHA-1 хэш, а также небольшой header.
Несколько основных типов объектов:
* **blob** — соответствует файлу; хранит его данные (только содержимое)
* **tree** — соответствует директории; хранит список блобов и деревьев, а также их описание (имена файлов, типы, права доступа)
* **commit** — соответствует истории изменения дерева; хранит указатель на дерево, автора изменений, субъекта, добавившего изменения (committer), сообщение с описанием изменений, ссылку на предыдущие (родительские) коммиты
**branch** (ветка) — это не объект `Git Object Database`, а всего лишь файл в директории `.git/refs/heads/`с хэшом последнего для этой ветки коммита.
То есть ветка — это указатель на коммит.
**head** — это ссылка на коммит. В каждом репозитории по умолчанию есть **head** именем **master**.
**HEAD** — один выделенный **head**. Файл `.git/HEAD`. Родитель следующего коммита.
**HEAD** может ссылаться на коммит напрямую (**detached HEAD**).
Следующий коммит в таком случае не будет принадлежать никакой ветке.
Гораздо чаще **HEAD** ссылается на ветку.
В таком случае следующий коммит "попадёт" в ту же ветку и продвинет **HEAD**.
**HEAD** определяет текущую активную ветку.
**revision** (ревизия) — способ сослаться на Git объект.
Например, SHA-1 коммита — это ревизия на коммит,
`HEAD@{5 minutes ago}` — это ревизия на последний коммит на момент 5 минут назад,
`HEAD:README` — это ревизия на блоб.
### Критерии сдачи
Решение должно проходить все тесты, так же как и в обычной задаче.