import 'dart:ffi'; import 'package:ffi/ffi.dart'; import 'package:libgit2dart/src/bindings/libgit2_bindings.dart'; import 'package:libgit2dart/src/error.dart'; import 'package:libgit2dart/src/util.dart'; /// Lookup a blob object from a repository. /// /// Throws a [LibGit2Error] if error occured. Pointer lookup({ required Pointer repoPointer, required Pointer oidPointer, }) { final out = calloc>(); final error = libgit2.git_blob_lookup(out, repoPointer, oidPointer); final result = out.value; calloc.free(out); if (error < 0) { throw LibGit2Error(libgit2.git_error_last()); } else { return result; } } /// Get the id of a blob. Pointer id(Pointer blob) => libgit2.git_blob_id(blob); /// Determine if the blob content is most certainly binary or not. /// /// The heuristic used to guess if a file is binary is taken from core git: /// Searching for NUL bytes and looking for a reasonable ratio of printable to /// non-printable characters among the first 8000 bytes. bool isBinary(Pointer blob) { return libgit2.git_blob_is_binary(blob) == 1 || false; } /// Get a read-only buffer with the raw content of a blob. /// /// A pointer to the raw content of a blob is returned; this pointer is owned /// internally by the object and shall not be free'd. The pointer may be /// invalidated at a later time. String content(Pointer blob) { return libgit2.git_blob_rawcontent(blob).cast().toDartString(); } /// Get the size in bytes of the contents of a blob. int size(Pointer blob) => libgit2.git_blob_rawsize(blob); /// Write content of a string buffer to the ODB as a blob. /// /// Throws a [LibGit2Error] if error occured. Pointer create({ required Pointer repoPointer, required String buffer, required int len, }) { final out = calloc(); final bufferC = buffer.toNativeUtf8().cast(); final error = libgit2.git_blob_create_from_buffer( out, repoPointer, bufferC, len, ); calloc.free(bufferC); if (error < 0) { calloc.free(out); throw LibGit2Error(libgit2.git_error_last()); } else { return out; } } /// Read a file from the working folder of a repository and write it to the /// Object Database as a loose blob. /// /// Throws a [LibGit2Error] if error occured. Pointer createFromWorkdir({ required Pointer repoPointer, required String relativePath, }) { final out = calloc(); final relativePathC = relativePath.toNativeUtf8().cast(); final error = libgit2.git_blob_create_from_workdir( out, repoPointer, relativePathC, ); calloc.free(relativePathC); if (error < 0) { calloc.free(out); throw LibGit2Error(libgit2.git_error_last()); } else { return out; } } /// Read a file from the filesystem and write its content to the Object /// Database as a loose blob. /// /// Throws a [LibGit2Error] if error occured. Pointer createFromDisk({ required Pointer repoPointer, required String path, }) { final out = calloc(); final pathC = path.toNativeUtf8().cast(); final error = libgit2.git_blob_create_from_disk(out, repoPointer, pathC); calloc.free(pathC); if (error < 0) { calloc.free(out); throw LibGit2Error(libgit2.git_error_last()); } else { return out; } } /// Create an in-memory copy of a blob. The copy must be explicitly free'd or /// it will leak. Pointer duplicate(Pointer source) { final out = calloc>(); libgit2.git_blob_dup(out, source); final result = out.value; calloc.free(out); return result; } /// Get a buffer with the filtered content of a blob. /// /// This applies filters as if the blob was being checked out to the working /// directory under the specified filename. This may apply CRLF filtering or /// other types of changes depending on the file attributes set for the blob /// and the content detected in it. /// /// Throws a [LibGit2Error] if error occured. String filterContent({ required Pointer blobPointer, required String asPath, required int flags, git_oid? attributesCommit, }) { final out = calloc(); final asPathC = asPath.toNativeUtf8().cast(); final opts = calloc(); libgit2.git_blob_filter_options_init(opts, GIT_BLOB_FILTER_OPTIONS_VERSION); opts.ref.flags = flags; if (attributesCommit != null) { opts.ref.attr_commit_id = attributesCommit; } final error = libgit2.git_blob_filter(out, blobPointer, asPathC, opts); late final String result; if (out.ref.ptr != nullptr) { result = out.ref.ptr.cast().toDartString(length: out.ref.size); } libgit2.git_buf_dispose(out); calloc.free(out); calloc.free(asPathC); calloc.free(opts); if (error < 0) { throw LibGit2Error(libgit2.git_error_last()); } else { return result; } } /// Close an open blob to release memory. void free(Pointer blob) => libgit2.git_blob_free(blob);