# This file is a part of Julia. License is MIT: https://julialang.org/license """ GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString) -> GitRemote Look up a remote git repository using its name and URL. Uses the default fetch refspec. # Example ```julia repo = LibGit2.init(repo_path) remote = LibGit2.GitRemote(repo, "upstream", repo_url) ``` """ function GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString) rmt_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_remote_create, :libgit2), Cint, (Ptr{Ptr{Void}}, Ptr{Void}, Cstring, Cstring), rmt_ptr_ptr, repo.ptr, rmt_name, rmt_url) return GitRemote(repo, rmt_ptr_ptr[]) end """ GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString, fetch_spec::AbstractString) -> GitRemote Look up a remote git repository using the repository's name and URL, as well as specifications for how to fetch from the remote (e.g. which remote branch to fetch from). # Example ```julia repo = LibGit2.init(repo_path) refspec = "+refs/heads/mybranch:refs/remotes/origin/mybranch" remote = LibGit2.GitRemote(repo, "upstream", repo_url, refspec) ``` """ function GitRemote(repo::GitRepo, rmt_name::AbstractString, rmt_url::AbstractString, fetch_spec::AbstractString) rmt_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_remote_create_with_fetchspec, :libgit2), Cint, (Ptr{Ptr{Void}}, Ptr{Void}, Cstring, Cstring, Cstring), rmt_ptr_ptr, repo.ptr, rmt_name, rmt_url, fetch_spec) return GitRemote(repo, rmt_ptr_ptr[]) end """ GitRemoteAnon(repo::GitRepo, url::AbstractString) -> GitRemote Look up a remote git repository using only its URL, not its name. # Example ```julia repo = LibGit2.init(repo_path) remote = LibGit2.GitRemoteAnon(repo, repo_url) ``` """ function GitRemoteAnon(repo::GitRepo, url::AbstractString) rmt_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_remote_create_anonymous, :libgit2), Cint, (Ptr{Ptr{Void}}, Ptr{Void}, Cstring), rmt_ptr_ptr, repo.ptr, url) return GitRemote(repo, rmt_ptr_ptr[]) end function get(::Type{GitRemote}, repo::GitRepo, rmt_name::AbstractString) rmt_ptr_ptr = Ref{Ptr{Void}}(C_NULL) @check ccall((:git_remote_lookup, :libgit2), Cint, (Ptr{Ptr{Void}}, Ptr{Void}, Cstring), rmt_ptr_ptr, repo.ptr, rmt_name) return GitRemote(repo, rmt_ptr_ptr[]) end """ url(rmt::GitRemote) Get the fetch URL of a remote git repository. # Example ```julia-repl julia> repo_url = "https://github.com/JuliaLang/Example.jl"; julia> repo = LibGit2.init(mktempdir()); julia> remote = LibGit2.GitRemote(repo, "origin", repo_url); julia> LibGit2.url(remote) "https://github.com/JuliaLang/Example.jl" ``` """ function url(rmt::GitRemote) url_ptr = ccall((:git_remote_url, :libgit2), Cstring, (Ptr{Void},), rmt.ptr) url_ptr == C_NULL && return "" return unsafe_string(url_ptr) end """ push_url(rmt::GitRemote) Get the push URL of a remote git repository. """ function push_url(rmt::GitRemote) url_ptr = ccall((:git_remote_pushurl, :libgit2), Cstring, (Ptr{Void},), rmt.ptr) url_ptr == C_NULL && return "" return unsafe_string(url_ptr) end """ name(rmt::GitRemote) Get the name of a remote repository, for instance `"origin"`. If the remote is anonymous (see [`GitRemoteAnon`](@ref)) the name will be an empty string `""`. # Example ```julia-repl julia> repo_url = "https://github.com/JuliaLang/Example.jl"; julia> repo = LibGit2.clone(cache_repo, "test_directory"); julia> remote = LibGit2.GitRemote(repo, "origin", repo_url); julia> name(remote) "origin" ``` """ function name(rmt::GitRemote) name_ptr = ccall((:git_remote_name, :libgit2), Cstring, (Ptr{Void},), rmt.ptr) name_ptr == C_NULL && return "" return unsafe_string(name_ptr) end """ fetch_refspecs(rmt::GitRemote) -> Vector{String} Get the *fetch* refspecs for the specified `rmt`. These refspecs contain information about which branch(es) to fetch from. """ function fetch_refspecs(rmt::GitRemote) sa_ref = Ref(StrArrayStruct()) @check ccall((:git_remote_get_fetch_refspecs, :libgit2), Cint, (Ptr{StrArrayStruct}, Ptr{Void}), sa_ref, rmt.ptr) res = convert(Vector{String}, sa_ref[]) free(sa_ref) res end """ push_refspecs(rmt::GitRemote) -> Vector{String} Get the *push* refspecs for the specified `rmt`. These refspecs contain information about which branch(es) to push to. """ function push_refspecs(rmt::GitRemote) sa_ref = Ref(StrArrayStruct()) @check ccall((:git_remote_get_push_refspecs, :libgit2), Cint, (Ptr{StrArrayStruct}, Ptr{Void}), sa_ref, rmt.ptr) res = convert(Vector{String}, sa_ref[]) free(sa_ref) res end """ add_fetch!(repo::GitRepo, rmt::GitRemote, fetch_spec::String) Add a *fetch* refspec for the specified `rmt`. This refspec will contain information about which branch(es) to fetch from. # Example ```julia-repl julia> LibGit2.add_fetch!(repo, remote, "upstream"); julia> LibGit2.fetch_refspecs(remote) String["+refs/heads/*:refs/remotes/upstream/*"] ``` """ function add_fetch!(repo::GitRepo, rmt::GitRemote, fetch_spec::String) @check ccall((:git_remote_add_fetch, :libgit2), Cint, (Ptr{Void}, Cstring, Cstring), repo.ptr, name(rmt), fetch_spec) end """ add_push!(repo::GitRepo, rmt::GitRemote, push_spec::String) Add a *push* refspec for the specified `rmt`. This refspec will contain information about which branch(es) to push to. # Example ```julia-repl julia> LibGit2.add_push!(repo, remote, "refs/heads/master"); julia> remote = LibGit2.get(LibGit2.GitRemote, repo, branch); julia> LibGit2.push_refspecs(remote) String["refs/heads/master"] ``` !!! note You may need to [`close`](@ref) and reopen the `GitRemote` in question after updating its push refspecs in order for the change to take effect and for calls to [`push`](@ref) to work. """ function add_push!(repo::GitRepo, rmt::GitRemote, push_spec::String) @check ccall((:git_remote_add_push, :libgit2), Cint, (Ptr{Void}, Cstring, Cstring), repo.ptr, name(rmt), push_spec) end """ fetch(rmt::GitRemote, refspecs; options::FetchOptions=FetchOptions(), msg="") Fetch from the specified `rmt` remote git repository, using `refspecs` to determine which remote branch(es) to fetch. The keyword arguments are: * `options`: determines the options for the fetch, e.g. whether to prune afterwards. * `msg`: a message to insert into the reflogs. """ function fetch(rmt::GitRemote, refspecs::Vector{<:AbstractString}; options::FetchOptions = FetchOptions(), msg::AbstractString="") msg = "libgit2.fetch: $msg" @check ccall((:git_remote_fetch, :libgit2), Cint, (Ptr{Void}, Ptr{StrArrayStruct}, Ptr{FetchOptions}, Cstring), rmt.ptr, isempty(refspecs) ? C_NULL : refspecs, Ref(options), msg) end """ push(rmt::GitRemote, refspecs; force::Bool=false, options::PushOptions=PushOptions()) Push to the specified `rmt` remote git repository, using `refspecs` to determine which remote branch(es) to push to. The keyword arguments are: * `force`: if `true`, a force-push will occur, disregarding conflicts. * `options`: determines the options for the push, e.g. which proxy headers to use. !!! note You can add information about the push refspecs in two other ways: by setting an option in the repository's `GitConfig` (with `push.default` as the key) or by calling [`add_push!`](@ref). Otherwise you will need to explicitly specify a push refspec in the call to `push` for it to have any effect, like so: `LibGit2.push(repo, refspecs=["refs/heads/master"])`. """ function push(rmt::GitRemote, refspecs::Vector{<:AbstractString}; force::Bool = false, options::PushOptions = PushOptions()) @check ccall((:git_remote_push, :libgit2), Cint, (Ptr{Void}, Ptr{StrArrayStruct}, Ptr{PushOptions}), rmt.ptr, isempty(refspecs) ? C_NULL : refspecs, Ref(options)) end Base.show(io::IO, rmt::GitRemote) = print(io, "GitRemote:\nRemote name: ", name(rmt), " url: ", url(rmt))