Libgit2 git_blob против памяти

Мне не ясно, в какой момент содержимое блоба действительно загружается в память.

Логика, которая у меня есть в моем коде, следующая:

git_blob_lookup(&blob_, repo_, oid)

if (git_blob_rawsize(blob_) < LIMIT)
  git_blob_rawcontent(blob_)

Это сделано для того, чтобы предотвратить DOS, читая большие файлы. Но из описания API я не совсем уверен, действительно ли это предотвращает загрузку большого двоичного объекта в память.

Если нет, есть ли вызов API, который даст мне размер большого двоичного объекта, не загружая его в память?


person Šimon Tóth    schedule 25.06.2020    source источник


Ответы (2)


Источник для git_blob_rawcontent из src/blob.c libgit2 выглядит следующим образом:

const void *git_blob_rawcontent(const git_blob *blob)
{
        assert(blob);
        if (blob->raw)
                return blob->data.raw.data;
        else
                return git_odb_object_data(blob->data.odb);
}

И источник для git_odb_object_data из src/odb.c выглядит следующим образом:

const void *git_odb_object_data(git_odb_object *object)
{
        return object->buffer;
}

Таким образом, git_block_rawcontent не загружает какие-либо данные из репо, он просто возвращает указатель на данные, которые уже были загружены и на которые указывает либо blob->data.raw.data, либо blob->data.odb->buffer. Загрузка (возможно, из кэша уже загруженных объектов) выполняется вызовом git_blob_lookup.


Единственный способ, который я могу найти для чтения размера без необходимости загрузки всего большого двоичного объекта (или другого типа объекта), — это вызвать git_odb_read_header, но обратите внимание на документацию для git_odb_read_header, в которой говорится:

Обратите внимание, что большинство бэкендов не поддерживают чтение только заголовка объекта, поэтому будет прочитан весь объект, а затем будет возвращен заголовок.

Тем не менее, если вы хотите попробовать, прототип выглядит следующим образом:

int get_odb_read_header(size_t *len_out, git_object_t *type_out, git_odb *db, const git_oid *id);

Если OID найден в ODB (возвращаемое значение равно 0, если найдено, GIT_ENOTFOUND, если не найдено), длина и тип объекта будут возвращены через len_out и type_out. Значение типа для большого двоичного объекта — GIT_OBJECT_BLOB.

Для вызова get_odb_read_header нужен указатель ODB на репозиторий. Это можно получить, вызвав git_repository_odb, прототип которого выглядит следующим образом:

int git_repository_odb(git_odb **out, git_repository *repo);

git_repository_odb возвращает 0 в случае успеха или код ошибки в случае неудачи. Если он вернулся успешно, ODB должен быть освобожден, когда он больше не требуется, путем вызова git_odb_free, который имеет следующий прототип:

void git_odb_free(git_odb *db);
person Ian Abbott    schedule 25.06.2020

Это приведет к считыванию всего содержимого большого двоичного объекта в память.

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

В частности, вызов git_odb_read_header будет выполняться только для чтения метаданные объекта, то есть тип объекта (blob/tree/commit) и размер объекта. (Это размер, который будет возвращен функцией git_blob_rawsize.)

person Edward Thomson    schedule 25.06.2020