Мы стремимся поддерживать исходный код последовательным и читаемым. В данном разделе приведены некоторые руководства, которые помогут вам в этом.
У нас есть несколько правил, чтобы избежать неожиданных способов вызова функций и некоторых правил для потребителей библиотеки, чтобы избежать конфликтов между собой.
Доступ к свойствам возвращает значение напрямую (например, int
или const char *
), но если функция может завершиться ошибкой, мы возвращаем значение типа int
, а выходные параметры располагаются первыми в списке параметров, за ними следует объект, над которым выполняется операция, и затем любые другие аргументы, необходимые данной функции.
Если функция возвращает объект как возвращаемое значение, эта функция является получателем, и срок службы этого объекта связан с родительским объектом. Объекты, которые возвращаются как первый аргумент в виде указателя на указатель, принадлежат вызывающему и он отвечает за его освобождение. Строки возвращаются через git_buf
, чтобы обеспечить возможность повторного использования и безопасное освобождение.- Большинство действий, выполненных libgit2, связано с вводом-выводом, поэтому общее правило состоит в том, что вы должны предполагать, что любая функция может завершиться ошибкой из-за различных проблем и сложных случаев ошибок. Даже получение данных из файловой системы может привести к различным ошибкам и сложным случаям ошибок. - Пути внутри системы Git разделены слешем (0x2F). Если функция принимает путь на диске, то обратные слеши (0x5C) также принимаются на Windows.
Не смешивайте аллокаторы. Если что-то было распределено с помощью libgit2
, вы не знаете, какой метод освобождения является правильным в общем случае. Используйте методы освобождения, предоставляемые для каждого типа объекта.
libgit2
работает на многих разных платформах с множеством различных компиляторов.
Открытый API libgit2
совместим с стандартом ANSI C (или C89).
Внутри libgit2
используется портабельная часть стандарта C99 — для максимизации совместимости (например, с MSVC) мы избегаем некоторых расширений C99. Конкретнее, мы сохраняем объявления локальных переменных только в начале блока и избегаем стиля комментариев //
.
Кроме того, насколько это возможно, мы стараемся избегать большого количества #ifdef
внутри основной базы кода. Это в некоторой степени неизбежно, но поскольку это может существенно затруднять поддержание кода, мы стараемся ограничить использование этих директив до минимума.## Соответствие окружающему коду
Если есть одна ключевая рекомендация, которую следует вынести из этого документа, это правило: новый код должен соответствовать окружающему коду так, чтобы было невозможно отличить новое от старого. Консистентность важнее личного мнения о том, где должны располагаться фигурные скобки или пробелы вместо табуляции.Если часть кода полностью перезаписывается, можно привести её в соответствие с здесь описываемыми стандартами, но мы не примем подачи, содержащие большое количество изменений, которые являются лишь реформаттированием.
Все внешние типы и функции начинаются с префикса git_
, а все макросы #define
— с префикса GIT_
. API библиотеки libgit2 в основном разделён на связанные функциональные модули, каждый из которых имеет соответствующий заголовочный файл. Все функции внутри модуля должны называться как git_modulename_functionname()
(например, git_repository_open()
).
Функции с одним выходным параметром должны называть этот параметр out
. Множественные выходные параметры должны называться foo_out
, bar_out
и т.д.
Параметры типа git_oid
должны называться id
или foo_id
. Вызовы, которые возвращают OID, должны называться git_foo_id
.
Когда используется обратный вызов функции, функция также должна содержать дополнительный входной параметр пользователя типа void *
, который будет передан обратному вызову при каждом вызове.
По возможности используйте typedef
. В некоторых случаях, если структура представляет собой просто коллекцию указателей на функции, эти указатели не требуют отдельного определения типа typedef
, но свободные указатели на функции должны быть определены.## Экспорты
Все экспортированные функции должны объявляться следующим образом:
GIT_EXTERN(результат_тип) git_имя_модуля_функции(список_аргументов);
Функции, чье имя модуля заканчивается двумя подчеркиваниями (например, git_odb__read_packed
), являются полу-непубличными функциями. Они предназначены главным образом для использования внутри самой библиотеки и могут исчезнуть или изменить свой прототип в будущих версиях.
Выходные параметры располагаются первыми.
По возможности передавайте указатели аргументов как const
. Некоторые структуры (например, git_repository
и git_index
) имеют внутреннюю структуру, которая делает невозможным использование const
.
Обратные вызовы всегда должны принимать void *
payload в качестве последнего параметра. Указатели обратных вызовов группируются вместе со своими payload, и обычно располагаются последними при передаче как аргументы.
int git_foo(git_repository *repo, git_foo_cb callback, void *payload);
Некоторые API выделяют память, за освобождением которой отвечает вызывающая сторона; другие возвращают указатель на буфер, который принадлежит какому-то другому объекту. Укажите это явно в документации.
Большинство открытых API должны возвращать целочисленный код ошибки. Как обычно с большинством функций C-библиотек, нулевое значение указывает на успешное выполнение, а отрицательное — на ошибку.Некоторые привязки преобразуют эти коды ошибок в типы исключений, поэтому важно возвращать семантически подходящий код ошибки. Проверьте
include/git2/errors.h
для уже определённых кодов возврата.
В вашей реализации используйте git_error_set()
, чтобы предоставить расширенную информацию об ошибке вызывающей стороне.
Если внутренняя функция libgit2
вызывает другую функцию, которая сообщает об ошибке, но эта ошибка не передается выше, используйте git_error_clear()
, чтобы предотвратить получение неверного сообщения об ошибке вызывающей стороной позднее.
Большинство открытых типов должны быть прозрачными, например:
typedef struct git_odb git_odb;
...с функциями выделения памяти, которые возвращают "экземпляр", созданный внутри библиотеки, а не внутри приложения. Это позволяет типу расти (или уменьшаться) по размеру без необходимости перестроения клиентского кода.
Чтобы сохранить совместимость ABI, включите поле int version
во всех прозрачных структурах, и инициализируйте его последней версией в конструкторе. Увеличивайте "последнюю" версию каждый раз, когда структура изменяется, и старайтесь добавлять новые поля только в конец структуры.
git_foo_options opts = GIT_FOO_OPTIONS_INIT; opts.baz = BAZ_OPTION_ONE; git_foo(&opts);
## Перечисления
Создайте typedef для всех перечисляемых типов. Если каждая опция стоит отдельно, используйте тип перечисления для передачи их как параметров; если они являются флагами, которые следует объединять операцией OR, передавайте их как `unsigned int` или `uint32_t` или какого-либо подходящего типа.
## Размещение кода
Постарайтесь сохранять строки менее 80 символов в длину. Это слабое требование, но превышение 80 столбцов — это не очень хорошо.
Используйте здравый смысл для переноса большинства строк кода; объявления публичных функций могут использовать несколько различных стилей:
```c
/** Все на одной строке допустимо, если помещается */
GIT_EXTERN(int) git_foo_simple(git_oid *id);
/** В противном случае один аргумент на каждую строку — хорошее следующее решение */
GIT_EXTERN(int) git_foo_id(
git_oid **out,
int a,
int b);
Отступайте с помощью табуляций; установите ширину табуляции вашего редактора на восемь для наилучшего эффекта.
Избегайте пробелов в конце строк и только коммитьте Unix-стильные новогодние строки (то есть без CRLF в репозитории — просто установите core.autocrlf
как true, если вы пишете код на машине Windows).
Используйте этот шаблон при создании нового публичного заголовка.
#ifndef INCLUDE_git_${filename}_h__
#define INCLUDE_git_${filename}_h__
#include "git/common.h"
/**
* @file git/${filename}.h
* @brief Описание Git
* @defgroup git_${filename} описание рутин
* @ingroup Git
* @{
*/
GIT_BEGIN_DECL
/* ... определения ... */
/** @} */
GIT_END_DECL
#endif
Все встроенные функции должны объявляться как:
GIT_INLINE(тип_результата) git_modulename_functionname(список_параметров);
GIT_INLINE
(или inline
) не следует использовать в публичных заголовках для сохранения совместимости с ANSI C.
libgit2
использует тестовый фреймворк clar.
Все запросы на слияние (PRs) должны иметь соответствующие тесты.
Когда добавляются новые тесты, мы предпочитаем попытки переиспользования существующих данных тестов (в tests-clar/resources/
) по мере возможности. Если вы собираетесь добавить новые тестовые хранилища, пожалуйста, постарайтесь удалить из них ненужные файлы (например, образцы хуков и т.д.).
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )