From 723dbf59a13b3b98c06a081cb476f1bddd1ab98c Mon Sep 17 00:00:00 2001 From: Stefan Karpinski Date: Fri, 13 Jul 2018 15:34:02 -0400 Subject: [PATCH] lazy LibGit2 initialization --- base/precompile.jl | 3 ++- stdlib/LibGit2/src/LibGit2.jl | 41 ++++++++++++++++++++++---------- stdlib/LibGit2/src/blame.jl | 3 +++ stdlib/LibGit2/src/blob.jl | 4 ++++ stdlib/LibGit2/src/callbacks.jl | 7 ++++++ stdlib/LibGit2/src/commit.jl | 4 ++++ stdlib/LibGit2/src/config.jl | 17 +++++++++++++ stdlib/LibGit2/src/consts.jl | 2 +- stdlib/LibGit2/src/diff.jl | 8 +++++++ stdlib/LibGit2/src/error.jl | 3 +++ stdlib/LibGit2/src/index.jl | 16 ++++++++++++- stdlib/LibGit2/src/merge.jl | 7 ++++++ stdlib/LibGit2/src/oid.jl | 10 ++++++++ stdlib/LibGit2/src/rebase.jl | 8 +++++++ stdlib/LibGit2/src/reference.jl | 23 ++++++++++++++++++ stdlib/LibGit2/src/remote.jl | 17 +++++++++++++ stdlib/LibGit2/src/repository.jl | 24 +++++++++++++++++++ stdlib/LibGit2/src/signature.jl | 3 +++ stdlib/LibGit2/src/status.jl | 4 ++++ stdlib/LibGit2/src/tag.jl | 5 ++++ stdlib/LibGit2/src/tree.jl | 9 +++++++ stdlib/LibGit2/src/types.jl | 14 +++++++---- stdlib/LibGit2/src/walker.jl | 6 +++++ 23 files changed, 219 insertions(+), 19 deletions(-) diff --git a/base/precompile.jl b/base/precompile.jl index 16f58b58ff85b..7d1fc0ce5540d 100644 --- a/base/precompile.jl +++ b/base/precompile.jl @@ -465,7 +465,8 @@ precompile(Tuple{typeof(Core.Compiler.length), Tuple{typeof(Base.:(*)), Int64}}) precompile(Tuple{typeof(Core.Compiler.length), Tuple{typeof(Base.open_flags)}}) precompile(Tuple{typeof(Core.Compiler.vect), Type{typeof(typeassert)}}) precompile(Tuple{typeof(Distributed.terminate_all_workers)}) -precompile(Tuple{typeof(LibGit2.__init__)}) +precompile(Tuple{typeof(LibGit2.ensure_initialized)}) +precompile(Tuple{typeof(LibGit2.initialize)}) precompile(Tuple{typeof(Logging.__init__)}) precompile(Tuple{typeof(Logging.default_metafmt), Base.CoreLogging.LogLevel, Module, Symbol, Symbol, String, Int64}) precompile(Tuple{typeof(Logging.default_metafmt), Base.CoreLogging.LogLevel, Nothing, Symbol, Symbol, String, Int64}) diff --git a/stdlib/LibGit2/src/LibGit2.jl b/stdlib/LibGit2/src/LibGit2.jl index 55dde9a5a8203..7043c5de4c35c 100644 --- a/stdlib/LibGit2/src/LibGit2.jl +++ b/stdlib/LibGit2/src/LibGit2.jl @@ -16,7 +16,9 @@ export with, GitRepo, GitConfig const GITHUB_REGEX = r"^(?:git@|git://|https://(?:[\w\.\+\-]+@)?)github.com[:/](([^/].+)/(.+?))(?:\.git)?$"i -const REFCOUNT = Threads.Atomic{UInt}() +const REFCOUNT = Threads.Atomic{Int}(0) + +function ensure_initialized end include("utils.jl") include("consts.jl") @@ -963,22 +965,29 @@ function transact(f::Function, repo::GitRepo) end end -function set_ssl_cert_locations(cert_loc) - cert_file = isfile(cert_loc) ? cert_loc : Cstring(C_NULL) - cert_dir = isdir(cert_loc) ? cert_loc : Cstring(C_NULL) - cert_file == C_NULL && cert_dir == C_NULL && return - @check ccall((:git_libgit2_opts, :libgit2), Cint, - (Cint, Cstring, Cstring), - Cint(Consts.SET_SSL_CERT_LOCATIONS), cert_file, cert_dir) +## lazy libgit2 initialization + +function ensure_initialized() + x = Threads.atomic_cas!(REFCOUNT, 0, 1) + if x < 0 + negative_refcount_error(x)::Union{} + end + if x == 0 + initialize() + end + return nothing +end + +@noinline function negative_refcount_error(x::Int) + error("Negative LibGit2 REFCOUNT $x\nThis shouldn't happen, please file a bug report!") end -function __init__() +@noinline function initialize() @check ccall((:git_libgit2_init, :libgit2), Cint, ()) - REFCOUNT[] = 1 atexit() do - if Threads.atomic_sub!(REFCOUNT, UInt(1)) == 1 - # refcount zero, no objects to be finalized + # refcount zero, no objects to be finalized + if Threads.atomic_sub!(REFCOUNT, 1) >= 1 ccall((:git_libgit2_shutdown, :libgit2), Cint, ()) end end @@ -998,5 +1007,13 @@ function __init__() end end +function set_ssl_cert_locations(cert_loc) + cert_file = isfile(cert_loc) ? cert_loc : Cstring(C_NULL) + cert_dir = isdir(cert_loc) ? cert_loc : Cstring(C_NULL) + cert_file == C_NULL && cert_dir == C_NULL && return + @check ccall((:git_libgit2_opts, :libgit2), Cint, + (Cint, Cstring, Cstring), + Cint(Consts.SET_SSL_CERT_LOCATIONS), cert_file, cert_dir) +end end # module diff --git a/stdlib/LibGit2/src/blame.jl b/stdlib/LibGit2/src/blame.jl index 53e3b31326784..3aa94e30200b4 100644 --- a/stdlib/LibGit2/src/blame.jl +++ b/stdlib/LibGit2/src/blame.jl @@ -9,6 +9,7 @@ the file when, and how. `options` controls how to separate the contents of the f which commits to probe - see [`BlameOptions`](@ref) for more information. """ function GitBlame(repo::GitRepo, path::AbstractString; options::BlameOptions=BlameOptions()) + ensure_initialized() blame_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_blame_file, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Ptr{BlameOptions}), @@ -25,6 +26,7 @@ a function added to a source file or an inner loop that was optimized out of that function later. """ function counthunks(blame::GitBlame) + ensure_initialized() return ccall((:git_blame_get_hunk_count, :libgit2), Int32, (Ptr{Cvoid},), blame.ptr) end @@ -32,6 +34,7 @@ function Base.getindex(blame::GitBlame, i::Integer) if !(1 <= i <= counthunks(blame)) throw(BoundsError(blame, (i,))) end + ensure_initialized() GC.@preserve blame begin hunk_ptr = ccall((:git_blame_get_hunk_byindex, :libgit2), Ptr{BlameHunk}, diff --git a/stdlib/LibGit2/src/blob.jl b/stdlib/LibGit2/src/blob.jl index bbc69ef390bc9..b416fac7329e6 100644 --- a/stdlib/LibGit2/src/blob.jl +++ b/stdlib/LibGit2/src/blob.jl @@ -1,6 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license function Base.length(blob::GitBlob) + ensure_initialized() return ccall((:git_blob_rawsize, :libgit2), Int64, (Ptr{Cvoid},), blob.ptr) end @@ -18,6 +19,7 @@ See also [`content`](@ref), which *will* throw an error if the content of the `b is binary and not valid Unicode. """ function rawcontent(blob::GitBlob) + ensure_initialized() ptr = ccall((:git_blob_rawcontent, :libgit2), Ptr{UInt8}, (Ptr{Cvoid},), blob.ptr) copy(unsafe_wrap(Array, ptr, (length(blob),), own = false)) end @@ -44,6 +46,7 @@ looking for a reasonable ratio of printable to non-printable characters among the first 8000 bytes. """ function isbinary(blob::GitBlob) + ensure_initialized() bin_flag = ccall((:git_blob_is_binary, :libgit2), Cint, (Ptr{Cvoid},), blob.ptr) return bin_flag == 1 end @@ -62,6 +65,7 @@ id = LibGit2.addblob!(repo, blob_file) ``` """ function addblob!(repo::GitRepo, path::AbstractString) + ensure_initialized() id_ref = Ref{GitHash}() @check ccall((:git_blob_create_fromdisk, :libgit2), Cint, (Ptr{GitHash}, Ptr{Cvoid}, Cstring), diff --git a/stdlib/LibGit2/src/callbacks.jl b/stdlib/LibGit2/src/callbacks.jl index 3a4e9a8bfba11..b07764e0b033a 100644 --- a/stdlib/LibGit2/src/callbacks.jl +++ b/stdlib/LibGit2/src/callbacks.jl @@ -6,6 +6,7 @@ Function sets `+refs/*:refs/*` refspecs and `mirror` flag for remote reference. """ function mirror_callback(remote::Ptr{Ptr{Cvoid}}, repo_ptr::Ptr{Cvoid}, name::Cstring, url::Cstring, payload::Ptr{Cvoid}) + ensure_initialized() # Create the remote with a mirroring url fetch_spec = "+refs/*:refs/*" err = ccall((:git_remote_create_with_fetchspec, :libgit2), Cint, @@ -40,6 +41,7 @@ function is_passphrase_required(private_key::AbstractString) end function user_abort() + ensure_initialized() # Note: Potentially it could be better to just throw a Julia error. ccall((:giterr_set_str, :libgit2), Cvoid, (Cint, Cstring), Cint(Error.Callback), @@ -48,6 +50,7 @@ function user_abort() end function prompt_limit() + ensure_initialized() ccall((:giterr_set_str, :libgit2), Cvoid, (Cint, Cstring), Cint(Error.Callback), "Aborting, maximum number of prompts reached.") @@ -55,6 +58,7 @@ function prompt_limit() end function exhausted_abort() + ensure_initialized() ccall((:giterr_set_str, :libgit2), Cvoid, (Cint, Cstring), Cint(Error.Callback), "All authentication methods have failed.") @@ -62,6 +66,7 @@ function exhausted_abort() end function authenticate_ssh(libgit2credptr::Ptr{Ptr{Cvoid}}, p::CredentialPayload, username_ptr) + ensure_initialized() cred = p.credential::SSHCredential revised = false @@ -173,6 +178,7 @@ function authenticate_ssh(libgit2credptr::Ptr{Ptr{Cvoid}}, p::CredentialPayload, end function authenticate_userpass(libgit2credptr::Ptr{Ptr{Cvoid}}, p::CredentialPayload) + ensure_initialized() cred = p.credential::UserPasswordCredential revised = false @@ -326,6 +332,7 @@ function credentials_callback(libgit2credptr::Ptr{Ptr{Cvoid}}, url_ptr::Cstring, # with the requested authentication method. if err == 0 if p.explicit !== nothing + ensure_initialized() ccall((:giterr_set_str, :libgit2), Cvoid, (Cint, Cstring), Cint(Error.Callback), "The explicitly provided credential is incompatible with the requested " * "authentication methods.") diff --git a/stdlib/LibGit2/src/commit.jl b/stdlib/LibGit2/src/commit.jl index 148566f2220ac..db8cc822f7fc2 100644 --- a/stdlib/LibGit2/src/commit.jl +++ b/stdlib/LibGit2/src/commit.jl @@ -9,6 +9,7 @@ leading newlines removed). If `raw` is `true`, the message is not stripped of any such newlines. """ function message(c::GitCommit, raw::Bool=false) + ensure_initialized() GC.@preserve c begin local msg_ptr::Cstring msg_ptr = raw ? ccall((:git_commit_message_raw, :libgit2), Cstring, (Ptr{Cvoid},), c.ptr) : @@ -28,6 +29,7 @@ Return the `Signature` of the author of the commit `c`. The author is the person who made changes to the relevant file(s). See also [`committer`](@ref). """ function author(c::GitCommit) + ensure_initialized() GC.@preserve c begin ptr = ccall((:git_commit_author, :libgit2), Ptr{SignatureStruct}, (Ptr{Cvoid},), c.ptr) @assert ptr != C_NULL @@ -45,6 +47,7 @@ need not be the same as the `author`, for example, if the `author` emailed a pat a `committer` who committed it. """ function committer(c::GitCommit) + ensure_initialized() GC.@preserve c begin ptr = ccall((:git_commit_committer, :libgit2), Ptr{SignatureStruct}, (Ptr{Cvoid},), c.ptr) sig = Signature(ptr) @@ -65,6 +68,7 @@ function commit(repo::GitRepo, committer::GitSignature, tree::GitTree, parents::GitCommit...) + ensure_initialized() commit_id_ptr = Ref(GitHash()) nparents = length(parents) parentptrs = Ptr{Cvoid}[c.ptr for c in parents] diff --git a/stdlib/LibGit2/src/config.jl b/stdlib/LibGit2/src/config.jl index 304e19e25cf24..f4e3c729f8d2d 100644 --- a/stdlib/LibGit2/src/config.jl +++ b/stdlib/LibGit2/src/config.jl @@ -10,6 +10,7 @@ function GitConfig(path::AbstractString, level::Consts.GIT_CONFIG = Consts.CONFIG_LEVEL_APP, repo::Union{GitRepo, Nothing}=nothing, force::Bool=false) + ensure_initialized() # create new config object cfg_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_config_new, :libgit2), Cint, (Ptr{Ptr{Cvoid}},), cfg_ptr_ptr) @@ -31,6 +32,7 @@ have a specific configuration file set, the default git configuration will be used. """ function GitConfig(repo::GitRepo) + ensure_initialized() cfg_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_repository_config, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), cfg_ptr_ptr, repo.ptr) @@ -45,6 +47,7 @@ files into a prioritized configuration. This can be used to access default confi options outside a specific git repository. """ function GitConfig(level::Consts.GIT_CONFIG = Consts.CONFIG_LEVEL_DEFAULT) + ensure_initialized() cfg_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_config_open_default, :libgit2), Cint, (Ptr{Ptr{Cvoid}},), cfg_ptr_ptr) @@ -85,6 +88,7 @@ function addfile(cfg::GitConfig, path::AbstractString, level::Consts.GIT_CONFIG = Consts.CONFIG_LEVEL_APP, repo::Union{GitRepo, Nothing} = nothing, force::Bool=false) + ensure_initialized() @static if LibGit2.VERSION >= v"0.27.0" @check ccall((:git_config_add_file_ondisk, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Cstring, Cint, Ptr{Cvoid}, Cint), @@ -98,6 +102,7 @@ function addfile(cfg::GitConfig, path::AbstractString, end function get(::Type{<:AbstractString}, c::GitConfig, name::AbstractString) + ensure_initialized() buf_ref = Ref(Buffer()) @check ccall((:git_config_get_string_buf, :libgit2), Cint, (Ptr{Buffer}, Ptr{Cvoid}, Cstring), buf_ref, c.ptr, name) @@ -108,6 +113,7 @@ function get(::Type{<:AbstractString}, c::GitConfig, name::AbstractString) end function get(::Type{Bool}, c::GitConfig, name::AbstractString) + ensure_initialized() val_ptr = Ref(Cint(0)) @check ccall((:git_config_get_bool, :libgit2), Cint, (Ptr{Cint}, Ptr{Cvoid}, Cstring), val_ptr, c.ptr, name) @@ -115,6 +121,7 @@ function get(::Type{Bool}, c::GitConfig, name::AbstractString) end function get(::Type{Int32}, c::GitConfig, name::AbstractString) + ensure_initialized() val_ptr = Ref(Cint(0)) @check ccall((:git_config_get_int32, :libgit2), Cint, (Ptr{Cint}, Ptr{Cvoid}, Cstring), val_ptr, c.ptr, name) @@ -122,6 +129,7 @@ function get(::Type{Int32}, c::GitConfig, name::AbstractString) end function get(::Type{Int64}, c::GitConfig, name::AbstractString) + ensure_initialized() val_ptr = Ref(Cintmax_t(0)) @check ccall((:git_config_get_int64, :libgit2), Cint, (Ptr{Cintmax_t}, Ptr{Cvoid}, Cstring), val_ptr, c.ptr, name) @@ -155,27 +163,32 @@ function getconfig(name::AbstractString, default) end function set!(c::GitConfig, name::AbstractString, value::AbstractString) + ensure_initialized() @check ccall((:git_config_set_string, :libgit2), Cint, (Ptr{Cvoid}, Cstring, Cstring), c.ptr, name, value) end function set!(c::GitConfig, name::AbstractString, value::Bool) + ensure_initialized() bval = Int32(value) @check ccall((:git_config_set_bool, :libgit2), Cint, (Ptr{Cvoid}, Cstring, Cint), c.ptr, name, bval) end function set!(c::GitConfig, name::AbstractString, value::Int32) + ensure_initialized() @check ccall((:git_config_set_int32, :libgit2), Cint, (Ptr{Cvoid}, Cstring, Cint), c.ptr, name, value) end function set!(c::GitConfig, name::AbstractString, value::Int64) + ensure_initialized() @check ccall((:git_config_set_int64, :libgit2), Cint, (Ptr{Cvoid}, Cstring, Cintmax_t), c.ptr, name, value) end function GitConfigIter(cfg::GitConfig) + ensure_initialized() ci_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_config_iterator_new, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), ci_ptr, cfg.ptr) @@ -183,6 +196,7 @@ function GitConfigIter(cfg::GitConfig) end function GitConfigIter(cfg::GitConfig, name::AbstractString) + ensure_initialized() ci_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_config_multivar_iterator_new, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Cstring), @@ -191,6 +205,7 @@ function GitConfigIter(cfg::GitConfig, name::AbstractString) end function GitConfigIter(cfg::GitConfig, name::AbstractString, value::Regex) + ensure_initialized() ci_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_config_multivar_iterator_new, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Cstring), @@ -199,6 +214,7 @@ function GitConfigIter(cfg::GitConfig, name::AbstractString, value::Regex) end function GitConfigIter(cfg::GitConfig, name::Regex) + ensure_initialized() ci_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_config_iterator_glob_new, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), @@ -207,6 +223,7 @@ function GitConfigIter(cfg::GitConfig, name::Regex) end function Base.iterate(ci::GitConfigIter, state=nothing) + ensure_initialized() entry_ptr_ptr = Ref{Ptr{ConfigEntry}}(C_NULL) err = ccall((:git_config_next, :libgit2), Cint, (Ptr{Ptr{ConfigEntry}}, Ptr{Cvoid}), entry_ptr_ptr, ci.ptr) diff --git a/stdlib/LibGit2/src/consts.jl b/stdlib/LibGit2/src/consts.jl index 952954132f6bd..2aaa3e15a1d63 100644 --- a/stdlib/LibGit2/src/consts.jl +++ b/stdlib/LibGit2/src/consts.jl @@ -2,7 +2,7 @@ module Consts -import ..LibGit2: version +import ..LibGit2: version, ensure_initialized const HEAD_FILE = "HEAD" const FETCH_HEAD = "FETCH_HEAD" diff --git a/stdlib/LibGit2/src/diff.jl b/stdlib/LibGit2/src/diff.jl index a79a21090fdff..7c3df89e2f5ca 100644 --- a/stdlib/LibGit2/src/diff.jl +++ b/stdlib/LibGit2/src/diff.jl @@ -24,6 +24,7 @@ This compares the current working directory against the [`GitIndex`](@ref) and c for example, be used to examine the changes in staged files before a commit. """ function diff_tree(repo::GitRepo, tree::GitTree, pathspecs::AbstractString=""; cached::Bool=false) + ensure_initialized() diff_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) if cached @check ccall((:git_diff_tree_to_index, :libgit2), Cint, @@ -48,6 +49,7 @@ be used to compare a commit made 2 months ago with the current latest commit, or to compare a commit on another branch with the current latest commit on `master`. """ function diff_tree(repo::GitRepo, oldtree::GitTree, newtree::GitTree) + ensure_initialized() diff_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_diff_tree_to_tree, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{DiffOptionsStruct}), @@ -63,6 +65,7 @@ summary of changes made across the `diff`. In particular, it records how many files were changed, how many insertions were made, and how many deletions were made. """ function GitDiffStats(diff::GitDiff) + ensure_initialized() diff_stat_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_diff_get_stats, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), @@ -79,6 +82,7 @@ used to generate the parent `GitDiff` of `diff_stat` (for instance, whether igno are to be included or not). """ function files_changed(diff_stat::GitDiffStats) + ensure_initialized() return ccall((:git_diff_stats_files_changed, :libgit2), Csize_t, (Ptr{Cvoid},), diff_stat.ptr) end @@ -91,6 +95,7 @@ used to generate the parent `GitDiff` of `diff_stat` (for instance, whether igno are to be included or not). """ function insertions(diff_stat::GitDiffStats) + ensure_initialized() return ccall((:git_diff_stats_insertions, :libgit2), Csize_t, (Ptr{Cvoid},), diff_stat.ptr) end @@ -103,10 +108,12 @@ used to generate the parent `GitDiff` of `diff_stat` (for instance, whether igno are to be included or not). """ function deletions(diff_stat::GitDiffStats) + ensure_initialized() return ccall((:git_diff_stats_deletions, :libgit2), Csize_t, (Ptr{Cvoid},), diff_stat.ptr) end function count(diff::GitDiff) + ensure_initialized() return ccall((:git_diff_num_deltas, :libgit2), Cint, (Ptr{Cvoid},), diff.ptr) end @@ -114,6 +121,7 @@ function Base.getindex(diff::GitDiff, i::Integer) if i < 1 || i > count(diff) throw(BoundsError(diff, (i,))) end + ensure_initialized() delta_ptr = ccall((:git_diff_get_delta, :libgit2), Ptr{DiffDelta}, (Ptr{Cvoid}, Csize_t), diff.ptr, i-1) diff --git a/stdlib/LibGit2/src/error.jl b/stdlib/LibGit2/src/error.jl index b64e9f1b8d923..4d1e915cef314 100644 --- a/stdlib/LibGit2/src/error.jl +++ b/stdlib/LibGit2/src/error.jl @@ -2,6 +2,8 @@ module Error +import ..LibGit2: ensure_initialized + export GitError @enum(Code, GIT_OK = Cint(0), # no error @@ -71,6 +73,7 @@ end Base.show(io::IO, err::GitError) = print(io, "GitError(Code:$(err.code), Class:$(err.class), $(err.msg))") function last_error() + ensure_initialized() err = ccall((:giterr_last, :libgit2), Ptr{ErrorStruct}, ()) if err != C_NULL err_obj = unsafe_load(err) diff --git a/stdlib/LibGit2/src/index.jl b/stdlib/LibGit2/src/index.jl index 3255fd392de4a..b8baf624540b0 100644 --- a/stdlib/LibGit2/src/index.jl +++ b/stdlib/LibGit2/src/index.jl @@ -6,6 +6,7 @@ Load the index file for the repository `repo`. """ function GitIndex(repo::GitRepo) + ensure_initialized() idx_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_repository_index, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), idx_ptr_ptr, repo.ptr) @@ -23,6 +24,7 @@ If `force` is `false`, the index data is only updated from disk if the data on d has changed since the last time it was loaded into `idx`. """ function read!(idx::GitIndex, force::Bool = false) + ensure_initialized() @check ccall((:git_index_read, :libgit2), Cint, (Ptr{Cvoid}, Cint), idx.ptr, Cint(force)) return idx end @@ -33,6 +35,7 @@ end Write the state of index `idx` to disk using a file lock. """ function write!(idx::GitIndex) + ensure_initialized() @check ccall((:git_index_write, :libgit2), Cint, (Ptr{Cvoid},), idx.ptr) return idx end @@ -46,6 +49,7 @@ create a [`GitCommit`](@ref). `idx` must have a parent repository and this repository cannot be bare. `idx` must not contain any files with conflicts. """ function write_tree!(idx::GitIndex) + ensure_initialized() oid_ptr = Ref(GitHash()) @check ccall((:git_index_write_tree, :libgit2), Cint, (Ptr{GitHash}, Ptr{Cvoid}), oid_ptr, idx.ptr) @@ -68,6 +72,7 @@ Read the tree `tree` (or the tree pointed to by `treehash` in the repository own `idx`) into the index `idx`. The current index contents will be replaced. """ function read_tree!(idx::GitIndex, tree::GitTree) + ensure_initialized() @check ccall((:git_index_read_tree, :libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}), idx.ptr, tree.ptr) end @@ -98,6 +103,7 @@ with respect to ignored files: """ function add!(idx::GitIndex, files::AbstractString...; flags::Cuint = Consts.INDEX_ADD_DEFAULT) + ensure_initialized() @check ccall((:git_index_add_all, :libgit2), Cint, (Ptr{Cvoid}, Ptr{StrArrayStruct}, Cuint, Ptr{Cvoid}, Ptr{Cvoid}), idx.ptr, collect(files), flags, C_NULL, C_NULL) @@ -113,6 +119,7 @@ disk, removing it if it has been removed on disk, or updating its entry in the o database. """ function update!(idx::GitIndex, files::AbstractString...) + ensure_initialized() @check ccall((:git_index_update_all, :libgit2), Cint, (Ptr{Cvoid}, Ptr{StrArrayStruct}, Ptr{Cvoid}, Ptr{Cvoid}), idx.ptr, collect(files), C_NULL, C_NULL) @@ -126,6 +133,7 @@ Remove all the files with paths specified by `files` in the index `idx` (or the of the `repo`). """ function remove!(idx::GitIndex, files::AbstractString...) + ensure_initialized() @check ccall((:git_index_remove_all, :libgit2), Cint, (Ptr{Cvoid}, Ptr{StrArrayStruct}, Ptr{Cvoid}, Ptr{Cvoid}), idx.ptr, collect(files), C_NULL, C_NULL) @@ -164,10 +172,12 @@ function read!(repo::GitRepo, force::Bool = false) end function count(idx::GitIndex) + ensure_initialized() return ccall((:git_index_entrycount, :libgit2), Csize_t, (Ptr{Cvoid},), idx.ptr) end function Base.getindex(idx::GitIndex, i::Integer) + ensure_initialized() GC.@preserve idx begin ie_ptr = ccall((:git_index_get_byindex, :libgit2), Ptr{IndexEntry}, @@ -179,6 +189,7 @@ function Base.getindex(idx::GitIndex, i::Integer) end function Base.findall(path::String, idx::GitIndex) + ensure_initialized() pos_ref = Ref{Csize_t}(0) ret = ccall((:git_index_find, :libgit2), Cint, (Ref{Csize_t}, Ptr{Cvoid}, Cstring), pos_ref, idx.ptr, path) @@ -197,7 +208,10 @@ before the attempted merge, stage `1` is the changes which have been made locall stages `2` and larger are for changes from other branches (for instance, in the case of a multi-branch "octopus" merge, stages `2`, `3`, and `4` might be used). """ -stage(ie::IndexEntry) = ccall((:git_index_entry_stage, :libgit2), Cint, (Ptr{IndexEntry},), Ref(ie)) +function stage(ie::IndexEntry) + ensure_initialized() + return ccall((:git_index_entry_stage, :libgit2), Cint, (Ptr{IndexEntry},), Ref(ie)) +end function Base.show(io::IO, idx::GitIndex) println(io, "GitIndex:\nRepository: ", repository(idx), "\nNumber of elements: ", count(idx)) diff --git a/stdlib/LibGit2/src/merge.jl b/stdlib/LibGit2/src/merge.jl index 7698cb34fa26f..09ff4163aa768 100644 --- a/stdlib/LibGit2/src/merge.jl +++ b/stdlib/LibGit2/src/merge.jl @@ -14,6 +14,7 @@ tip of a remote branch, for instance when a [`FetchHead`](@ref) is passed, or to branch head described using `GitReference`. """ function GitAnnotated(repo::GitRepo, commit_id::GitHash) + ensure_initialized() ann_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_annotated_commit_lookup, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{GitHash}), @@ -22,6 +23,7 @@ function GitAnnotated(repo::GitRepo, commit_id::GitHash) end function GitAnnotated(repo::GitRepo, ref::GitReference) + ensure_initialized() ann_ref_ref = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_annotated_commit_from_ref, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{Cvoid}), @@ -30,6 +32,7 @@ function GitAnnotated(repo::GitRepo, ref::GitReference) end function GitAnnotated(repo::GitRepo, fh::FetchHead) + ensure_initialized() ann_ref_ref = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_annotated_commit_from_fetchhead, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Cstring, Ptr{GitHash}), @@ -44,6 +47,7 @@ function GitAnnotated(repo::GitRepo, comittish::AbstractString) end function GitHash(ann::GitAnnotated) + ensure_initialized() GC.@preserve ann begin oid = unsafe_load(ccall((:git_annotated_commit_id, :libgit2), Ptr{GitHash}, (Ptr{Cvoid},), ann.ptr)) end @@ -79,6 +83,7 @@ Return two outputs, `analysis` and `preference`. `analysis` has several possible `preference` can be controlled through the repository or global git configuration. """ function merge_analysis(repo::GitRepo, anns::Vector{GitAnnotated}) + ensure_initialized() analysis = Ref{Cint}(0) preference = Ref{Cint}(0) anns_ref = Ref(Base.map(a->a.ptr, anns), 1) @@ -140,6 +145,7 @@ LibGit2.merge!(repo, [upst_ann]) function merge!(repo::GitRepo, anns::Vector{GitAnnotated}; merge_opts::MergeOptions = MergeOptions(), checkout_opts::CheckoutOptions = CheckoutOptions()) + ensure_initialized() anns_size = Csize_t(length(anns)) @check ccall((:git_merge, :libgit2), Cint, (Ptr{Cvoid}, Ptr{Ptr{Cvoid}}, Csize_t, @@ -250,6 +256,7 @@ Find a merge base (a common ancestor) between the commits `one` and `two`. `one` and `two` may both be in string form. Return the `GitHash` of the merge base. """ function merge_base(repo::GitRepo, one::AbstractString, two::AbstractString) + ensure_initialized() oid1_ptr = Ref(GitHash(one)) oid2_ptr = Ref(GitHash(two)) moid_ptr = Ref(GitHash()) diff --git a/stdlib/LibGit2/src/oid.jl b/stdlib/LibGit2/src/oid.jl index 904f845d1434f..069d725685a62 100644 --- a/stdlib/LibGit2/src/oid.jl +++ b/stdlib/LibGit2/src/oid.jl @@ -11,6 +11,7 @@ function GitHash(ptr::Ptr{UInt8}) if ptr == C_NULL throw(ArgumentError("NULL pointer passed to GitHash() constructor")) end + ensure_initialized() oid_ptr = Ref(GitHash()) ccall((:git_oid_fromraw, :libgit2), Cvoid, (Ptr{GitHash}, Ptr{UInt8}), oid_ptr, ptr) return oid_ptr[] @@ -39,6 +40,7 @@ function GitHash(id::AbstractString) if len < OID_HEXSZ throw(ArgumentError("Input string is too short, use `GitShortHash` for partial hashes")) end + ensure_initialized() oid_ptr = Ref{GitHash}() @check ccall((:git_oid_fromstrn, :libgit2), Cint, (Ptr{GitHash}, Ptr{UInt8}, Csize_t), oid_ptr, bstr, len) @@ -51,6 +53,7 @@ end Construct a `GitShortHash` from the data stored in the given [`Buffer`](@ref). """ function GitShortHash(buf::Buffer) + ensure_initialized() oid_ptr = Ref{GitHash}() @check ccall((:git_oid_fromstrn, :libgit2), Cint, (Ptr{GitHash}, Ptr{UInt8}, Csize_t), oid_ptr, buf.ptr, buf.size) @@ -63,6 +66,7 @@ end Construct a `GitShortHash` from a string of at most $OID_HEXSZ hexadecimal digits. """ function GitShortHash(id::AbstractString) + ensure_initialized() bstr = String(id) len = sizeof(bstr) oid_ptr = Ref{GitHash}() @@ -106,6 +110,7 @@ Get the identifier (`GitHash`) of the object referred to by the direct reference function GitHash(ref::GitReference) isempty(ref) && return GitHash() reftype(ref) != Consts.REF_OID && return GitHash() + ensure_initialized() GC.@preserve ref begin oid_ptr = ccall((:git_reference_target, :libgit2), Ptr{UInt8}, (Ptr{Cvoid},), ref.ptr) oid_ptr == C_NULL && return GitHash() @@ -123,6 +128,7 @@ Get the identifier (`GitHash`) of the object referred to by reference specified """ function GitHash(repo::GitRepo, ref_name::AbstractString) isempty(repo) && return GitHash() + ensure_initialized() oid_ptr = Ref(GitHash()) @check ccall((:git_reference_name_to_id, :libgit2), Cint, (Ptr{GitHash}, Ptr{Cvoid}, Cstring), @@ -136,6 +142,7 @@ end Get the identifier (`GitHash`) of `obj`. """ function GitHash(obj::GitObject) + ensure_initialized() GitHash(ccall((:git_object_id, :libgit2), Ptr{UInt8}, (Ptr{Cvoid},), obj.ptr)) end @@ -149,6 +156,7 @@ is determined by the `core.abbrev` config option, and will be of sufficient leng unambiuously identify the object in the repository. """ function GitShortHash(obj::GitObject) + ensure_initialized() buf_ref = Ref(Buffer()) @check ccall((:git_object_short_id, :libgit2), Cint, (Ptr{Buffer},Ptr{Cvoid}), buf_ref, obj.ptr) @@ -177,11 +185,13 @@ Base.show(io::IO, id::GitShortHash) = print(io, "GitShortHash(\"$(string(id))\") Base.hash(id::GitHash, h::UInt) = hash(id.val, h) function Base.cmp(id1::GitHash, id2::GitHash) + ensure_initialized() Int(ccall((:git_oid_cmp, :libgit2), Cint, (Ptr{GitHash}, Ptr{GitHash}), Ref(id1), Ref(id2))) end function Base.cmp(id1::GitShortHash, id2::GitShortHash) + ensure_initialized() # shortened hashes appear at the beginning of the order, i.e. # 000 < 01 < 010 < 011 < 0112 c = Int(ccall((:git_oid_ncmp, :libgit2), Cint, diff --git a/stdlib/LibGit2/src/rebase.jl b/stdlib/LibGit2/src/rebase.jl index 36eb18cca41b5..00193b1a9d69f 100644 --- a/stdlib/LibGit2/src/rebase.jl +++ b/stdlib/LibGit2/src/rebase.jl @@ -3,6 +3,7 @@ function GitRebase(repo::GitRepo, branch::GitAnnotated, upstream::GitAnnotated; onto::Union{GitAnnotated, Nothing}=nothing, opts::RebaseOptions = RebaseOptions()) + ensure_initialized() rebase_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_rebase_init, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{Cvoid}, Ptr{Cvoid}, @@ -13,6 +14,7 @@ function GitRebase(repo::GitRepo, branch::GitAnnotated, upstream::GitAnnotated; end function count(rb::GitRebase) + ensure_initialized() return ccall((:git_rebase_operation_entrycount, :libgit2), Csize_t, (Ptr{Cvoid},), rb.ptr) end @@ -25,6 +27,7 @@ has not yet been called or iteration over `rb` has not yet begun), return `GIT_REBASE_NO_OPERATION`, which is equal to `typemax(Csize_t)`. """ function current(rb::GitRebase) + ensure_initialized() return ccall((:git_rebase_operation_current, :libgit2), Csize_t, (Ptr{Cvoid},), rb.ptr) end @@ -32,6 +35,7 @@ function Base.getindex(rb::GitRebase, i::Integer) if !(1 <= i <= count(rb)) throw(BoundsError(rb, (i,))) end + ensure_initialized() GC.@preserve rb begin rb_op_ptr = ccall((:git_rebase_operation_byindex, :libgit2), Ptr{RebaseOperation}, @@ -42,6 +46,7 @@ function Base.getindex(rb::GitRebase, i::Integer) end function Base.next(rb::GitRebase) + ensure_initialized() rb_op_ptr_ptr = Ref{Ptr{RebaseOperation}}(C_NULL) GC.@preserve rb begin try @@ -70,6 +75,7 @@ Commit the current patch to the rebase `rb`, using `sig` as the committer. Is si the commit has already been applied. """ function commit(rb::GitRebase, sig::GitSignature) + ensure_initialized() oid_ptr = Ref(GitHash()) try @check ccall((:git_rebase_commit, :libgit2), Error.Code, @@ -93,6 +99,7 @@ the rebase was initiated. Return `0` if the abort is successful, rebase had completed), and `-1` for other errors. """ function abort(rb::GitRebase) + ensure_initialized() return ccall((:git_rebase_abort, :libgit2), Csize_t, (Ptr{Cvoid},), rb.ptr) end @@ -105,6 +112,7 @@ to specify the identity of the user finishing the rebase. Return `0` if the rebase finishes successfully, `-1` if there is an error. """ function finish(rb::GitRebase, sig::GitSignature) + ensure_initialized() return ccall((:git_rebase_finish, :libgit2), Csize_t, (Ptr{Cvoid}, Ptr{SignatureStruct}), rb.ptr, sig.ptr) diff --git a/stdlib/LibGit2/src/reference.jl b/stdlib/LibGit2/src/reference.jl index 7ff669e5316e0..345c546946ee5 100644 --- a/stdlib/LibGit2/src/reference.jl +++ b/stdlib/LibGit2/src/reference.jl @@ -1,6 +1,7 @@ # This file is a part of Julia. License is MIT: https://julialang.org/license function GitReference(repo::GitRepo, refname::AbstractString) + ensure_initialized() ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_reference_lookup, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), @@ -10,6 +11,7 @@ end function GitReference(repo::GitRepo, obj_oid::GitHash, refname::AbstractString = Consts.HEAD_FILE; force::Bool=false, msg::AbstractString="") + ensure_initialized() ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_reference_create, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{UInt8}, Ptr{GitHash}, Cint, Cstring), @@ -25,6 +27,7 @@ Check if the current branch is an "orphan" branch, i.e. has no commits. The firs to this branch will have no parents. """ function isorphan(repo::GitRepo) + ensure_initialized() r = @check ccall((:git_repository_head_unborn, :libgit2), Cint, (Ptr{Cvoid},), repo.ptr) r != 0 @@ -36,6 +39,7 @@ end Return a `GitReference` to the current HEAD of `repo`. """ function head(repo::GitRepo) + ensure_initialized() head_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_repository_head, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), head_ptr_ptr, repo.ptr) @@ -62,6 +66,7 @@ julia> LibGit2.shortname(branch_ref) """ function shortname(ref::GitReference) isempty(ref) && return "" + ensure_initialized() GC.@preserve ref begin name_ptr = ccall((:git_reference_shorthand, :libgit2), Cstring, (Ptr{Cvoid},), ref.ptr) name_ptr == C_NULL && return "" @@ -79,6 +84,7 @@ Return a `Cint` corresponding to the type of `ref`: * `2` if the reference is symbolic """ function reftype(ref::GitReference) + ensure_initialized() return ccall((:git_reference_type, :libgit2), Cint, (Ptr{Cvoid},), ref.ptr) end @@ -92,6 +98,7 @@ reference, return an empty string. function fullname(ref::GitReference) isempty(ref) && return "" reftype(ref) == Consts.REF_OID && return "" + ensure_initialized() GC.@preserve ref begin rname = ccall((:git_reference_symbolic_target, :libgit2), Cstring, (Ptr{Cvoid},), ref.ptr) rname == C_NULL && return "" @@ -107,6 +114,7 @@ Return the full name of `ref`. """ function name(ref::GitReference) isempty(ref) && return "" + ensure_initialized() GC.@preserve ref begin name_ptr = ccall((:git_reference_name, :libgit2), Cstring, (Ptr{Cvoid},), ref.ptr) name_ptr == C_NULL && return "" @@ -117,6 +125,7 @@ end function branch(ref::GitReference) isempty(ref) && return "" + ensure_initialized() str_ptr_ptr = Ref{Cstring}() GC.@preserve ref begin @check ccall((:git_branch_name, :libgit2), Cint, @@ -128,6 +137,7 @@ end function ishead(ref::GitReference) isempty(ref) && return false + ensure_initialized() err = ccall((:git_branch_is_head, :libgit2), Cint, (Ptr{Cvoid},), ref.ptr) return err == 1 @@ -135,6 +145,7 @@ end function isbranch(ref::GitReference) isempty(ref) && return false + ensure_initialized() err = ccall((:git_reference_is_branch, :libgit2), Cint, (Ptr{Cvoid},), ref.ptr) return err == 1 @@ -142,6 +153,7 @@ end function istag(ref::GitReference) isempty(ref) && return false + ensure_initialized() err = ccall((:git_reference_is_tag, :libgit2), Cint, (Ptr{Cvoid},), ref.ptr) return err == 1 @@ -149,6 +161,7 @@ end function isremote(ref::GitReference) isempty(ref) && return false + ensure_initialized() err = ccall((:git_reference_is_remote, :libgit2), Cint, (Ptr{Cvoid},), ref.ptr) return err == 1 @@ -184,6 +197,7 @@ then `ref` will be peeled until an object other than a [`GitTag`](@ref) is obtai are references under `refs/tags/` which point directly to `GitCommit` objects. """ function peel(::Type{T}, ref::GitReference) where T<:GitObject + ensure_initialized() obj_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_reference_peel, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cint), obj_ptr_ptr, ref.ptr, Consts.OBJECT(T)) @@ -197,6 +211,7 @@ peel(ref::GitReference) = peel(GitObject, ref) Get a list of all reference names in the `repo` repository. """ function ref_list(repo::GitRepo) + ensure_initialized() sa_ref = Ref(StrArrayStruct()) @check ccall((:git_reference_list, :libgit2), Cint, (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, repo.ptr) @@ -218,6 +233,7 @@ function create_branch(repo::GitRepo, bname::AbstractString, commit_obj::GitCommit; force::Bool=false) + ensure_initialized() ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_branch_create, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Ptr{Cvoid}, Cint), @@ -231,6 +247,7 @@ end Delete the branch pointed to by `branch`. """ function delete_branch(branch::GitReference) + ensure_initialized() @check ccall((:git_branch_delete, :libgit2), Cint, (Ptr{Cvoid},), branch.ptr) end @@ -240,6 +257,7 @@ end Set the HEAD of `repo` to the object pointed to by `ref`. """ function head!(repo::GitRepo, ref::GitReference) + ensure_initialized() ref_name = name(ref) @check ccall((:git_repository_set_head, :libgit2), Cint, (Ptr{Cvoid}, Cstring), repo.ptr, ref_name) @@ -259,6 +277,7 @@ if it exists, or [`nothing`](@ref) if not. function lookup_branch(repo::GitRepo, branch_name::AbstractString, remote::Bool=false) + ensure_initialized() ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) branch_type = remote ? Consts.BRANCH_REMOTE : Consts.BRANCH_LOCAL err = ccall((:git_branch_lookup, :libgit2), Cint, @@ -286,6 +305,7 @@ or [`nothing`](@ref) if the requested branch does not have an upstream counterpa """ function upstream(ref::GitReference) isempty(ref) && return nothing + ensure_initialized() ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) err = ccall((:git_branch_upstream, :libgit2), Cint, (Ref{Ptr{Cvoid}}, Ptr{Cvoid},), ref_ptr_ptr, ref.ptr) @@ -304,6 +324,7 @@ end repository(ref::GitReference) = ref.owner function target!(ref::GitReference, new_oid::GitHash; msg::AbstractString="") + ensure_initialized() ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_reference_set_target, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{GitHash}, Cstring), @@ -312,6 +333,7 @@ function target!(ref::GitReference, new_oid::GitHash; msg::AbstractString="") end function GitBranchIter(repo::GitRepo, flags::Cint=Cint(Consts.BRANCH_LOCAL)) + ensure_initialized() bi_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_branch_iterator_new, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cint), bi_ptr, repo.ptr, flags) @@ -319,6 +341,7 @@ function GitBranchIter(repo::GitRepo, flags::Cint=Cint(Consts.BRANCH_LOCAL)) end function Base.iterate(bi::GitBranchIter, state=nothing) + ensure_initialized() ref_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) btype = Ref{Cint}() err = ccall((:git_branch_next, :libgit2), Cint, diff --git a/stdlib/LibGit2/src/remote.jl b/stdlib/LibGit2/src/remote.jl index 09a6b9a6ab6ec..384a3b21bdbfa 100644 --- a/stdlib/LibGit2/src/remote.jl +++ b/stdlib/LibGit2/src/remote.jl @@ -12,6 +12,7 @@ remote = LibGit2.GitRemote(repo, "upstream", repo_url) ``` """ function GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString) + ensure_initialized() rmt_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_remote_create, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Cstring), @@ -34,6 +35,7 @@ remote = LibGit2.GitRemote(repo, "upstream", repo_url, refspec) ``` """ function GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString, fetch_spec::AbstractString) + ensure_initialized() rmt_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_remote_create_with_fetchspec, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring, Cstring, Cstring), @@ -53,6 +55,7 @@ remote = LibGit2.GitRemoteAnon(repo, repo_url) ``` """ function GitRemoteAnon(repo::GitRepo, url::AbstractString) + ensure_initialized() rmt_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_remote_create_anonymous, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), @@ -75,6 +78,7 @@ LibGit2.lookup_remote(repo, remote_name) # will return nothing ``` """ function lookup_remote(repo::GitRepo, remote_name::AbstractString) + ensure_initialized() rmt_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) err = ccall((:git_remote_lookup, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), @@ -89,6 +93,7 @@ function lookup_remote(repo::GitRepo, remote_name::AbstractString) end function get(::Type{GitRemote}, repo::GitRepo, rmt_name::AbstractString) + ensure_initialized() rmt_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_remote_lookup, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), @@ -114,6 +119,7 @@ julia> LibGit2.url(remote) ``` """ function url(rmt::GitRemote) + ensure_initialized() url_ptr = ccall((:git_remote_url, :libgit2), Cstring, (Ptr{Cvoid},), rmt.ptr) url_ptr == C_NULL && return "" return unsafe_string(url_ptr) @@ -137,6 +143,7 @@ julia> LibGit2.push_url(LibGit2.get(LibGit2.GitRemote, repo, "origin")) ``` """ function push_url(rmt::GitRemote) + ensure_initialized() url_ptr = ccall((:git_remote_pushurl, :libgit2), Cstring, (Ptr{Cvoid},), rmt.ptr) url_ptr == C_NULL && return "" return unsafe_string(url_ptr) @@ -162,6 +169,7 @@ julia> name(remote) ``` """ function name(rmt::GitRemote) + ensure_initialized() name_ptr = ccall((:git_remote_name, :libgit2), Cstring, (Ptr{Cvoid},), rmt.ptr) name_ptr == C_NULL && return "" return unsafe_string(name_ptr) @@ -184,6 +192,7 @@ String["+refs/heads/*:refs/remotes/upstream/*"] ``` """ function fetch_refspecs(rmt::GitRemote) + ensure_initialized() sa_ref = Ref(StrArrayStruct()) @check ccall((:git_remote_get_fetch_refspecs, :libgit2), Cint, (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, rmt.ptr) @@ -213,6 +222,7 @@ String["refs/heads/master"] ``` """ function push_refspecs(rmt::GitRemote) + ensure_initialized() sa_ref = Ref(StrArrayStruct()) @check ccall((:git_remote_get_push_refspecs, :libgit2), Cint, (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, rmt.ptr) @@ -236,6 +246,7 @@ String["+refs/heads/*:refs/remotes/upstream/*"] ``` """ function add_fetch!(repo::GitRepo, rmt::GitRemote, fetch_spec::String) + ensure_initialized() @check ccall((:git_remote_add_fetch, :libgit2), Cint, (Ptr{Cvoid}, Cstring, Cstring), repo.ptr, name(rmt), fetch_spec) @@ -264,6 +275,7 @@ String["refs/heads/master"] to work. """ function add_push!(repo::GitRepo, rmt::GitRemote, push_spec::String) + ensure_initialized() @check ccall((:git_remote_add_push, :libgit2), Cint, (Ptr{Cvoid}, Cstring, Cstring), repo.ptr, name(rmt), push_spec) @@ -282,6 +294,7 @@ The keyword arguments are: function fetch(rmt::GitRemote, refspecs::Vector{<:AbstractString}; options::FetchOptions = FetchOptions(), msg::AbstractString="") + ensure_initialized() msg = "libgit2.fetch: $msg" @check ccall((:git_remote_fetch, :libgit2), Cint, (Ptr{Cvoid}, Ptr{StrArrayStruct}, Ptr{FetchOptions}, Cstring), @@ -307,6 +320,7 @@ The keyword arguments are: """ function push(rmt::GitRemote, refspecs::Vector{<:AbstractString}; force::Bool = false, options::PushOptions = PushOptions()) + ensure_initialized() @check ccall((:git_remote_push, :libgit2), Cint, (Ptr{Cvoid}, Ptr{StrArrayStruct}, Ptr{PushOptions}), rmt.ptr, isempty(refspecs) ? C_NULL : refspecs, Ref(options)) @@ -318,6 +332,7 @@ end Delete the `remote_name` from the git `repo`. """ function remote_delete(repo::GitRepo, remote_name::AbstractString) + ensure_initialized() @check ccall((:git_remote_delete, :libgit2), Cint, (Ptr{Cvoid}, Cstring), repo.ptr, remote_name) @@ -336,6 +351,7 @@ located at `path`. Typically git repos use `"origin"` as the remote name. function set_remote_fetch_url end function set_remote_fetch_url(repo::GitRepo, remote_name::AbstractString, url::AbstractString) + ensure_initialized() @check ccall((:git_remote_set_url, :libgit2), Cint, (Ptr{Cvoid}, Cstring, Cstring), repo.ptr, remote_name, url) @@ -358,6 +374,7 @@ located at `path`. Typically git repos use `"origin"` as the remote name. function set_remote_push_url end function set_remote_push_url(repo::GitRepo, remote_name::AbstractString, url::AbstractString) + ensure_initialized() @check ccall((:git_remote_set_pushurl, :libgit2), Cint, (Ptr{Cvoid}, Cstring, Cstring), repo.ptr, remote_name, url) diff --git a/stdlib/LibGit2/src/repository.jl b/stdlib/LibGit2/src/repository.jl index 50ef21fbdeae7..96249bd9f69dd 100644 --- a/stdlib/LibGit2/src/repository.jl +++ b/stdlib/LibGit2/src/repository.jl @@ -6,6 +6,7 @@ Open a git repository at `path`. """ function GitRepo(path::AbstractString) + ensure_initialized() repo_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_repository_open, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Cstring), repo_ptr_ptr, path) @@ -19,6 +20,7 @@ Open a git repository at `path` with extended controls (for instance, if the cur user must be a member of a special access group to read `path`). """ function GitRepoExt(path::AbstractString, flags::Cuint = Cuint(Consts.REPOSITORY_OPEN_DEFAULT)) + ensure_initialized() separator = @static Sys.iswindows() ? ";" : ":" repo_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_repository_open_ext, :libgit2), Cint, @@ -29,6 +31,7 @@ end function cleanup(r::GitRepo) if r.ptr != C_NULL + ensure_initialized() ccall((:git_repository__cleanup, :libgit2), Cvoid, (Ptr{Cvoid},), r.ptr) end end @@ -41,6 +44,7 @@ the working tree will be created in `path/.git`. If `bare` is `true`, no working directory will be created. """ function init(path::AbstractString, bare::Bool=false) + ensure_initialized() repo_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_repository_init, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Cstring, Cuint), repo_ptr_ptr, path, bare) @@ -91,6 +95,7 @@ in the `.git` subdirectory. This means that there is nowhere to check out the wo tree, and no tracking information for remote branches or configurations is present. """ function isbare(repo::GitRepo) + ensure_initialized() @assert repo.ptr != C_NULL return ccall((:git_repository_is_bare, :libgit2), Cint, (Ptr{Cvoid},), repo.ptr) == 1 end @@ -102,6 +107,7 @@ Determine if `repo` is detached - that is, whether its HEAD points to a commit (detached) or whether HEAD points to a branch tip (attached). """ function isattached(repo::GitRepo) + ensure_initialized() @assert repo.ptr != C_NULL ccall((:git_repository_head_detached, :libgit2), Cint, (Ptr{Cvoid},), repo.ptr) != 1 end @@ -130,6 +136,7 @@ Return a `$T` object from `repo` specified by `hash`/`spec`. end function (::Type{T})(repo::GitRepo, spec::AbstractString) where T<:GitObject + ensure_initialized() obj_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @assert repo.ptr != C_NULL @check ccall((:git_revparse_single, :libgit2), Cint, @@ -143,6 +150,7 @@ function (::Type{T})(repo::GitRepo, spec::AbstractString) where T<:GitObject end function (::Type{T})(repo::GitRepo, oid::GitHash) where T<:GitObject + ensure_initialized() oid_ptr = Ref(oid) obj_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @@ -154,6 +162,7 @@ function (::Type{T})(repo::GitRepo, oid::GitHash) where T<:GitObject return T(repo, obj_ptr_ptr[]) end function (::Type{T})(repo::GitRepo, oid::GitShortHash) where T<:GitObject + ensure_initialized() oid_ptr = Ref(oid.hash) obj_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @@ -179,6 +188,7 @@ Return the location of the "git" files of `repo`: See also [`workdir`](@ref), [`path`](@ref). """ function gitdir(repo::GitRepo) + ensure_initialized() @assert repo.ptr != C_NULL return unsafe_string(ccall((:git_repository_path, :libgit2), Cstring, (Ptr{Cvoid},), repo.ptr)) @@ -199,6 +209,7 @@ This will throw an error for bare repositories. See also [`gitdir`](@ref), [`path`](@ref). """ function workdir(repo::GitRepo) + ensure_initialized() @assert repo.ptr != C_NULL sptr = ccall((:git_repository_workdir, :libgit2), Cstring, (Ptr{Cvoid},), repo.ptr) @@ -241,6 +252,7 @@ then `obj` will be peeled until the type changes. - A `GitCommit` will be peeled to a `GitTree`. """ function peel(::Type{T}, obj::GitObject) where T<:GitObject + ensure_initialized() new_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_object_peel, :libgit2), Cint, @@ -271,6 +283,7 @@ information. """ function GitDescribeResult(commitish::GitObject; options::DescribeOptions=DescribeOptions()) + ensure_initialized() result_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_describe_commit, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{DescribeOptions}), @@ -296,6 +309,7 @@ Equivalent to `git describe`. See [`DescribeOptions`](@ref) for more information. """ function GitDescribeResult(repo::GitRepo; options::DescribeOptions=DescribeOptions()) + ensure_initialized() result_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @assert repo.ptr != C_NULL @check ccall((:git_describe_workdir, :libgit2), Cint, @@ -313,6 +327,7 @@ Formatting options are controlled by the keyword argument: * `options::DescribeFormatOptions=DescribeFormatOptions()` """ function format(result::GitDescribeResult; options::DescribeFormatOptions=DescribeFormatOptions()) + ensure_initialized() buf_ref = Ref(Buffer()) @check ccall((:git_describe_format, :libgit2), Cint, (Ptr{Buffer}, Ptr{Cvoid}, Ptr{DescribeFormatOptions}), @@ -338,6 +353,7 @@ be performed. See [`CheckoutOptions`](@ref) for more information. """ function checkout_tree(repo::GitRepo, obj::GitObject; options::CheckoutOptions = CheckoutOptions()) + ensure_initialized() @assert repo.ptr != C_NULL @check ccall((:git_checkout_tree, :libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{CheckoutOptions}), @@ -353,6 +369,7 @@ See [`CheckoutOptions`](@ref) for more information. """ function checkout_index(repo::GitRepo, idx::Union{GitIndex, Nothing} = nothing; options::CheckoutOptions = CheckoutOptions()) + ensure_initialized() @assert repo.ptr != C_NULL @check ccall((:git_checkout_index, :libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{CheckoutOptions}), @@ -372,6 +389,7 @@ Update the index and working tree of `repo` to match the commit pointed to by HE conflicts. """ function checkout_head(repo::GitRepo; options::CheckoutOptions = CheckoutOptions()) + ensure_initialized() @assert repo.ptr != C_NULL @check ccall((:git_checkout_head, :libgit2), Cint, (Ptr{Cvoid}, Ptr{CheckoutOptions}), @@ -390,6 +408,7 @@ The keyword argument `options` sets checkout and merge options for the cherrypic call [`commit`](@ref) yourself. """ function cherrypick(repo::GitRepo, commit::GitCommit; options::CherrypickOptions = CherrypickOptions()) + ensure_initialized() @assert repo.ptr != C_NULL @check ccall((:git_cherrypick, :libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{CherrypickOptions}), @@ -398,6 +417,7 @@ end """Updates some entries, determined by the `pathspecs`, in the index from the target commit tree.""" function reset!(repo::GitRepo, obj::Union{GitObject, Nothing}, pathspecs::AbstractString...) + ensure_initialized() @assert repo.ptr != C_NULL @check ccall((:git_reset_default, :libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Ptr{StrArrayStruct}), @@ -410,6 +430,7 @@ end """Sets the current head to the specified commit oid and optionally resets the index and working tree to match.""" function reset!(repo::GitRepo, obj::GitObject, mode::Cint; checkout_opts::CheckoutOptions = CheckoutOptions()) + ensure_initialized() @assert repo.ptr != C_NULL @check ccall((:git_reset, :libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Cint, Ptr{CheckoutOptions}), @@ -432,6 +453,7 @@ repo = LibGit2.clone(repo_url, "/home/me/projects/Example") """ function clone(repo_url::AbstractString, repo_path::AbstractString, clone_opts::CloneOptions) + ensure_initialized() clone_opts_ref = Ref(clone_opts) repo_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_clone, :libgit2), Cint, @@ -464,6 +486,7 @@ false ``` """ function fetchheads(repo::GitRepo) + ensure_initialized() fh = FetchHead[] ffcb = fetchhead_foreach_cb() @assert repo.ptr != C_NULL @@ -479,6 +502,7 @@ end Return a vector of the names of the remotes of `repo`. """ function remotes(repo::GitRepo) + ensure_initialized() sa_ref = Ref(StrArrayStruct()) @assert repo.ptr != C_NULL @check ccall((:git_remote_list, :libgit2), Cint, diff --git a/stdlib/LibGit2/src/signature.jl b/stdlib/LibGit2/src/signature.jl index bcb6a41164e87..9c13bc2256ef5 100644 --- a/stdlib/LibGit2/src/signature.jl +++ b/stdlib/LibGit2/src/signature.jl @@ -11,6 +11,7 @@ end Signature(sig::GitSignature) = Signature(sig.ptr) function Signature(name::AbstractString, email::AbstractString) + ensure_initialized() sig_ptr_ptr = Ref{Ptr{SignatureStruct}}(C_NULL) @check ccall((:git_signature_now, :libgit2), Cint, (Ptr{Ptr{SignatureStruct}}, Cstring, Cstring), sig_ptr_ptr, name, email) @@ -28,6 +29,7 @@ function Signature(repo::GitRepo) end function Base.convert(::Type{GitSignature}, sig::Signature) + ensure_initialized() sig_ptr_ptr = Ref{Ptr{SignatureStruct}}(C_NULL) @check ccall((:git_signature_new, :libgit2), Cint, (Ptr{Ptr{SignatureStruct}}, Cstring, Cstring, Int64, Cint), @@ -62,6 +64,7 @@ end """Return signature object. Free it after use.""" function default_signature(repo::GitRepo) + ensure_initialized() sig_ptr_ptr = Ref{Ptr{SignatureStruct}}(C_NULL) @check ccall((:git_signature_default, :libgit2), Cint, (Ptr{Ptr{SignatureStruct}}, Ptr{Cvoid}), sig_ptr_ptr, repo.ptr) diff --git a/stdlib/LibGit2/src/status.jl b/stdlib/LibGit2/src/status.jl index b05a8ac4a8c65..cd871681e4ae9 100644 --- a/stdlib/LibGit2/src/status.jl +++ b/stdlib/LibGit2/src/status.jl @@ -10,6 +10,7 @@ whether or not to look at untracked files or whether to include submodules or not. See [`StatusOptions`](@ref) for more information. """ function GitStatus(repo::GitRepo; status_opts=StatusOptions()) + ensure_initialized() stat_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_status_list_new, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{StatusOptions}), @@ -18,12 +19,14 @@ function GitStatus(repo::GitRepo; status_opts=StatusOptions()) end function Base.length(status::GitStatus) + ensure_initialized() return Int(ccall((:git_status_list_entrycount, :libgit2), Csize_t, (Ptr{Ptr{Cvoid}},), status.ptr)) end function Base.getindex(status::GitStatus, i::Integer) 1 <= i <= length(status) || throw(BoundsError()) + ensure_initialized() GC.@preserve status begin entry_ptr = ccall((:git_status_byindex, :libgit2), Ptr{StatusEntry}, @@ -44,6 +47,7 @@ to check if the file at `path` has been modified and needs to be staged and committed. """ function status(repo::GitRepo, path::String) + ensure_initialized() status_ptr = Ref{Cuint}(0) ret = ccall((:git_status_file, :libgit2), Cint, (Ref{Cuint}, Ptr{Cvoid}, Cstring), diff --git a/stdlib/LibGit2/src/tag.jl b/stdlib/LibGit2/src/tag.jl index 6f917435271bc..4209a4e2f917d 100644 --- a/stdlib/LibGit2/src/tag.jl +++ b/stdlib/LibGit2/src/tag.jl @@ -6,6 +6,7 @@ Get a list of all tags in the git repository `repo`. """ function tag_list(repo::GitRepo) + ensure_initialized() sa_ref = Ref(StrArrayStruct()) @check ccall((:git_tag_list, :libgit2), Cint, (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, repo.ptr) @@ -20,6 +21,7 @@ end Remove the git tag `tag` from the repository `repo`. """ function tag_delete(repo::GitRepo, tag::AbstractString) + ensure_initialized() @check ccall((:git_tag_delete, :libgit2), Cint, (Ptr{Cvoid}, Cstring), repo.ptr, tag) end @@ -43,6 +45,7 @@ function tag_create(repo::GitRepo, tag::AbstractString, commit::Union{AbstractSt with(GitCommit(repo, commit)) do commit_obj commit_obj === nothing && return oid_ptr[] # return empty oid with(convert(GitSignature, sig)) do git_sig + ensure_initialized() @check ccall((:git_tag_create, :libgit2), Cint, (Ptr{GitHash}, Ptr{Cvoid}, Cstring, Ptr{Cvoid}, Ptr{SignatureStruct}, Cstring, Cint), oid_ptr, repo.ptr, tag, commit_obj.ptr, git_sig.ptr, msg, Cint(force)) @@ -57,6 +60,7 @@ end The name of `tag` (e.g. `"v0.5"`). """ function name(tag::GitTag) + ensure_initialized() GC.@preserve tag begin str_ptr = ccall((:git_tag_name, :libgit2), Cstring, (Ptr{Cvoid},), tag.ptr) str_ptr == C_NULL && throw(Error.GitError(Error.ERROR)) @@ -72,6 +76,7 @@ end The `GitHash` of the target object of `tag`. """ function target(tag::GitTag) + ensure_initialized() GC.@preserve tag begin oid_ptr = ccall((:git_tag_target_id, :libgit2), Ptr{GitHash}, (Ptr{Cvoid},), tag.ptr) oid_ptr == C_NULL && throw(Error.GitError(Error.ERROR)) diff --git a/stdlib/LibGit2/src/tree.jl b/stdlib/LibGit2/src/tree.jl index f8bafbd0da36d..0b4778166f3f3 100644 --- a/stdlib/LibGit2/src/tree.jl +++ b/stdlib/LibGit2/src/tree.jl @@ -18,6 +18,7 @@ A negative value returned from `f` stops the tree walk. A positive value means that the entry will be skipped if `post` is `false`. """ function treewalk(f, tree::GitTree, post::Bool = false) + ensure_initialized() # NOTE: don't use @check/GitError directly, because the code can be arbitrary payload = Any[ tree, f ] cbf = @cfunction(function treewalk_callback(root_cstr::Cstring, entry_ptr::Ptr{Cvoid}, payload::Vector{Any})::Cint @@ -50,6 +51,7 @@ repository(te::GitTreeEntry) = repository(te.owner) Return the filename of the object on disk to which `te` refers. """ function filename(te::GitTreeEntry) + ensure_initialized() str = ccall((:git_tree_entry_name, :libgit2), Cstring, (Ptr{Cvoid},), te.ptr) str != C_NULL && return unsafe_string(str) return nothing @@ -61,6 +63,7 @@ end Return the UNIX filemode of the object on disk to which `te` refers as an integer. """ function filemode(te::GitTreeEntry) + ensure_initialized() return ccall((:git_tree_entry_filemode, :libgit2), Cint, (Ptr{Cvoid},), te.ptr) end @@ -71,6 +74,7 @@ Return the type of the object to which `te` refers. The result will be one of the types which [`objtype`](@ref) returns, e.g. a `GitTree` or `GitBlob`. """ function entrytype(te::GitTreeEntry) + ensure_initialized() otype = ccall((:git_tree_entry_type, :libgit2), Cint, (Ptr{Cvoid},), te.ptr) return objtype(Consts.OBJECT(otype)) end @@ -81,6 +85,7 @@ end Return the [`GitHash`](@ref) of the object to which `te` refers. """ function entryid(te::GitTreeEntry) + ensure_initialized() GC.@preserve te begin oid_ptr = ccall((:git_tree_entry_id, :libgit2), Ptr{UInt8}, (Ptr{Cvoid},), te.ptr) oid = GitHash(oid_ptr) @@ -89,6 +94,7 @@ function entryid(te::GitTreeEntry) end function count(tree::GitTree) + ensure_initialized() return ccall((:git_tree_entrycount, :libgit2), Csize_t, (Ptr{Cvoid},), tree.ptr) end @@ -96,6 +102,7 @@ function Base.getindex(tree::GitTree, i::Integer) if i < 1 || i > count(tree) throw(BoundsError(tree, i)) end + ensure_initialized() te_ptr = ccall((:git_tree_entry_byindex, :libgit2), Ptr{Cvoid}, (Ptr{Cvoid}, Csize_t), tree.ptr, i-1) @@ -117,6 +124,7 @@ blob = LibGit2.GitBlob(tree_entry) """ function GitObject(e::GitTreeEntry) end function (::Type{T})(te::GitTreeEntry) where T<:GitObject + ensure_initialized() repo = repository(te) obj_ptr_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_tree_entry_to_object, :libgit2), Cint, @@ -168,6 +176,7 @@ function Base.getindex(tree::GitTree, target::AbstractString) # we found the target, save the oid and stop the walk oid = entryid(entry) # workaround for issue: https://github.com/libgit2/libgit2/issues/4693 + ensure_initialized() ccall((:giterr_set_str, :libgit2), Cvoid, (Cint, Cstring), Cint(Error.Callback), "git_tree_walk callback returned -1") diff --git a/stdlib/LibGit2/src/types.jl b/stdlib/LibGit2/src/types.jl index 2c92efa110c1f..3348206ffa477 100644 --- a/stdlib/LibGit2/src/types.jl +++ b/stdlib/LibGit2/src/types.jl @@ -98,6 +98,7 @@ end StrArrayStruct() = StrArrayStruct(C_NULL, 0) function free(sa_ref::Base.Ref{StrArrayStruct}) + ensure_initialized() ccall((:git_strarray_free, :libgit2), Cvoid, (Ptr{StrArrayStruct},), sa_ref) end @@ -124,6 +125,7 @@ end Buffer() = Buffer(C_NULL, 0, 0) function free(buf_ref::Base.Ref{Buffer}) + ensure_initialized() ccall((:git_buf_free, :libgit2), Cvoid, (Ptr{Buffer},), buf_ref) end @@ -999,7 +1001,7 @@ for (typ, owntyp, sup, cname) in [ @assert ptr != C_NULL obj = new(ptr) if fin - Threads.atomic_add!(REFCOUNT, UInt(1)) + Threads.atomic_add!(REFCOUNT, 1) finalizer(Base.close, obj) end return obj @@ -1013,7 +1015,7 @@ for (typ, owntyp, sup, cname) in [ @assert ptr != C_NULL obj = new(owner, ptr) if fin - Threads.atomic_add!(REFCOUNT, UInt(1)) + Threads.atomic_add!(REFCOUNT, 1) finalizer(Base.close, obj) end return obj @@ -1027,9 +1029,10 @@ for (typ, owntyp, sup, cname) in [ end @eval function Base.close(obj::$typ) if obj.ptr != C_NULL + ensure_initialized() ccall(($(string(cname, :_free)), :libgit2), Cvoid, (Ptr{Cvoid},), obj.ptr) obj.ptr = C_NULL - if Threads.atomic_sub!(REFCOUNT, UInt(1)) == 1 + if Threads.atomic_sub!(REFCOUNT, 1) == 1 # will the last finalizer please turn out the lights? ccall((:git_libgit2_shutdown, :libgit2), Cint, ()) end @@ -1060,6 +1063,7 @@ mutable struct GitSignature <: AbstractGitObject end function Base.close(obj::GitSignature) if obj.ptr != C_NULL + ensure_initialized() ccall((:git_signature_free, :libgit2), Cvoid, (Ptr{SignatureStruct},), obj.ptr) obj.ptr = C_NULL end @@ -1156,8 +1160,10 @@ Consts.OBJECT(::Type{GitTag}) = Consts.OBJ_TAG Consts.OBJECT(::Type{GitUnknownObject}) = Consts.OBJ_ANY Consts.OBJECT(::Type{GitObject}) = Consts.OBJ_ANY -Consts.OBJECT(ptr::Ptr{Cvoid}) = +function Consts.OBJECT(ptr::Ptr{Cvoid}) + ensure_initialized() ccall((:git_object_type, :libgit2), Consts.OBJECT, (Ptr{Cvoid},), ptr) +end """ objtype(obj_type::Consts.OBJECT) diff --git a/stdlib/LibGit2/src/walker.jl b/stdlib/LibGit2/src/walker.jl index 0546a6f024f77..1d2fbcb52f9bc 100644 --- a/stdlib/LibGit2/src/walker.jl +++ b/stdlib/LibGit2/src/walker.jl @@ -19,6 +19,7 @@ Here, `count` finds the number of commits along the walk with a certain `GitHash Since the `GitHash` is unique to a commit, `cnt` will be `1`. """ function GitRevWalker(repo::GitRepo) + ensure_initialized() w_ptr = Ref{Ptr{Cvoid}}(C_NULL) @check ccall((:git_revwalk_new, :libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}), w_ptr, repo.ptr) @@ -26,6 +27,7 @@ function GitRevWalker(repo::GitRepo) end function Base.iterate(w::GitRevWalker, state=nothing) + ensure_initialized() id_ptr = Ref(GitHash()) err = ccall((:git_revwalk_next, :libgit2), Cint, (Ptr{GitHash}, Ptr{Cvoid}), id_ptr, w.ptr) @@ -48,6 +50,7 @@ Push the HEAD commit and its ancestors onto the [`GitRevWalker`](@ref) during the walk. """ function push_head!(w::GitRevWalker) + ensure_initialized() @check ccall((:git_revwalk_push_head, :libgit2), Cint, (Ptr{Cvoid},), w.ptr) return w end @@ -60,16 +63,19 @@ to apply a function to all commits since a certain year, by passing the first co of that year as `cid` and then passing the resulting `w` to [`map`](@ref LibGit2.map). """ function push!(w::GitRevWalker, cid::GitHash) + ensure_initialized() @check ccall((:git_revwalk_push, :libgit2), Cint, (Ptr{Cvoid}, Ptr{GitHash}), w.ptr, Ref(cid)) return w end function push!(w::GitRevWalker, range::AbstractString) + ensure_initialized() @check ccall((:git_revwalk_push_range, :libgit2), Cint, (Ptr{Cvoid}, Ptr{UInt8}), w.ptr, range) return w end function Base.sort!(w::GitRevWalker; by::Cint = Consts.SORT_NONE, rev::Bool=false) + ensure_initialized() rev && (by |= Consts.SORT_REVERSE) ccall((:git_revwalk_sorting, :libgit2), Cvoid, (Ptr{Cvoid}, Cint), w.ptr, by) return w