/
githubmirror
/
julia
Обзор
Документация
Войти
/
githubmirror
/
julia
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
stdlib/LibGit2/src/repository.jl
555 строк
19 KB
Jameson Nash
docs: fix grammar and clarity in comments and docstrings (#62083)
17 июн 2026, 05:57
Не верифицирован
17 июн 2026, 05:57
27858bb
Код
Авторство
О чём код?
# This file is a part of Julia. License is MIT: https://julialang.org/license """ LibGit2.GitRepo(path::AbstractString) 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) return GitRepo(repo_ptr_ptr[]) end """ LibGit2.GitRepoExt(path::AbstractString, flags::Cuint = Cuint(Consts.REPOSITORY_OPEN_DEFAULT)) Open a git repository at `path` with extended controls (for instance, if the current 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, (Ptr{Ptr{Cvoid}}, Cstring, Cuint, Cstring), repo_ptr_ptr, path, flags, separator) return GitRepo(repo_ptr_ptr[]) end function cleanup(r::GitRepo) if r.ptr != C_NULL ensure_initialized() @check ccall((:git_repository__cleanup, libgit2), Cint, (Ptr{Cvoid},), r) end end """ LibGit2.init(path::AbstractString, bare::Bool=false)::GitRepo Initialize a new git repository at `path`. If `bare` is `false`, 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) return GitRepo(repo_ptr_ptr[]) end """ LibGit2.head_oid(repo::GitRepo)::GitHash Lookup the object id of the current HEAD of git repository `repo`. """ function head_oid(repo::GitRepo) head_ref = head(repo) try return GitHash(head_ref) finally close(head_ref) end end """ LibGit2.headname(repo::GitRepo) Lookup the name of the current HEAD of git repository `repo`. If `repo` is currently detached, return the name of the HEAD it's detached from. """ function headname(repo::GitRepo) with(head(repo)) do href if isattached(repo) shortname(href) else "(detached from $(string(GitHash(href))[1:7]))" end end end """ isbare(repo::GitRepo)::Bool Determine if `repo` is bare. Suppose the top level directory of `repo` is `DIR`. A non-bare repository is one in which the git directory (see [`gitdir`](@ref)) is `DIR/.git`, and the working tree can be checked out. A bare repository is one in which all of git's administrative files are simply in `DIR`, rather than "hidden" in the `.git` subdirectory. This means that there is nowhere to check out the working 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) == 1 end """ isattached(repo::GitRepo)::Bool Determine if `repo` is attached - 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) != 1 end """ isshallow(repo::GitRepo)::Bool Determine if `repo` is a shallow clone. A shallow clone has a truncated history, created by cloning with a specific depth (e.g., `LibGit2.clone(url, path, depth=1)`). # Examples ```julia shallow_repo = LibGit2.clone(url, "shallow_path", depth=1) LibGit2.isshallow(shallow_repo) # returns true normal_repo = LibGit2.clone(url, "normal_path") LibGit2.isshallow(normal_repo) # returns false ``` """ function isshallow(repo::GitRepo) ensure_initialized() @assert repo.ptr != C_NULL ccall((:git_repository_is_shallow, libgit2), Cint, (Ptr{Cvoid},), repo) == 1 end @doc """ GitObject(repo::GitRepo, hash::AbstractGitHash) GitObject(repo::GitRepo, spec::AbstractString) Return the specified object ([`GitCommit`](@ref), [`GitBlob`](@ref), [`GitTree`](@ref) or [`GitTag`](@ref)) from `repo` specified by `hash`/`spec`. - `hash` is a full (`GitHash`) or partial (`GitShortHash`) hash. - `spec` is a textual specification: see [the git docs](https://git-scm.com/docs/git-rev-parse.html#_specifying_revisions) for a full list. """ GitObject for T in (:GitCommit, :GitBlob, :GitTree, :GitTag) @eval @doc $""" $T(repo::GitRepo, hash::AbstractGitHash) $T(repo::GitRepo, spec::AbstractString) Return a `$T` object from `repo` specified by `hash`/`spec`. - `hash` is a full (`GitHash`) or partial (`GitShortHash`) hash. - `spec` is a textual specification: see [the git docs](https://git-scm.com/docs/git-rev-parse.html#_specifying_revisions) for a full list. """ $T 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, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cstring), obj_ptr_ptr, repo, spec) obj_ptr = obj_ptr_ptr[] # check object is of correct type if T != GitObject && T != GitUnknownObject t = Consts.OBJECT(obj_ptr) if t != Consts.OBJECT(T) if obj_ptr != C_NULL # free result ccall((:git_object_free, libgit2), Cvoid, (Ptr{Cvoid},), obj_ptr) end throw(GitError(Error.Object, Error.ERROR, "Expected object of type $T, received object of type $(objtype(t))")) end end return T(repo, obj_ptr) 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) @assert repo.ptr != C_NULL @check ccall((:git_object_lookup, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{GitHash}, Consts.OBJECT), obj_ptr_ptr, repo, oid_ptr, Consts.OBJECT(T)) 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) @assert repo.ptr != C_NULL @check ccall((:git_object_lookup_prefix, libgit2), Cint, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{GitHash}, Csize_t, Consts.OBJECT), obj_ptr_ptr, repo, oid_ptr, oid.len, Consts.OBJECT(T)) return T(repo, obj_ptr_ptr[]) end # TODO: deprecate this function revparseid(repo::GitRepo, spec) = GitHash(GitUnknownObject(repo, spec)) """ LibGit2.gitdir(repo::GitRepo) Return the location of the "git" files of `repo`: - for normal repositories, this is the location of the `.git` folder. - for bare repositories, this is the location of the repository itself. See also [`workdir`](@ref), [`path`](@ref). """ function gitdir(repo::GitRepo) ensure_initialized() @assert repo.ptr != C_NULL GC.@preserve repo begin return unsafe_string(ccall((:git_repository_path, libgit2), Cstring, (Ptr{Cvoid},), repo)) end end """ LibGit2.workdir(repo::GitRepo) Return the location of the working directory of `repo`. This will throw an error for bare repositories. !!! note This will typically be the parent directory of `gitdir(repo)`, but can be different in some cases: e.g. if either the `core.worktree` configuration variable or the `GIT_WORK_TREE` environment variable is set. See also [`gitdir`](@ref), [`path`](@ref). """ function workdir(repo::GitRepo) ensure_initialized() @assert repo.ptr != C_NULL GC.@preserve repo begin sptr = ccall((:git_repository_workdir, libgit2), Cstring, (Ptr{Cvoid},), repo) sptr == C_NULL && throw(GitError(Error.Object, Error.ERROR, "No working directory found.")) return unsafe_string(sptr) end end """ LibGit2.path(repo::GitRepo) Return the base file path of the repository `repo`. - for normal repositories, this will typically be the parent directory of the ".git" directory (note: this may be different than the working directory, see `workdir` for more details). - for bare repositories, this is the location of the "git" files. See also [`gitdir`](@ref), [`workdir`](@ref). """ function path(repo::GitRepo) d = gitdir(repo) if isdirpath(d) d = dirname(d) # strip trailing separator end if isbare(repo) return d else parent, base = splitdir(d) return base == ".git" ? parent : d end end """ peel([T,] obj::GitObject) Recursively peel `obj` until an object of type `T` is obtained. If no `T` is provided, then `obj` will be peeled until the type changes. - A `GitTag` will be peeled to the object it references. - 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, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Cint), new_ptr_ptr, obj, Consts.OBJECT(T)) return T(obj.owner, new_ptr_ptr[]) end peel(obj::GitObject) = peel(GitObject, obj) """ LibGit2.GitDescribeResult(committish::GitObject; kwarg...) Produce a `GitDescribeResult` of the `committish` `GitObject`, which contains detailed information about it based on the keyword argument: * `options::DescribeOptions=DescribeOptions()` A git description of a `committish` object looks for the tag (by default, annotated, although a search of all tags can be performed) which can be reached from `committish` which is most recent. If the tag is pointing to `committish`, then only the tag is included in the description. Otherwise, a suffix is included which contains the number of commits between `committish` and the most recent tag. If there is no such tag, the default behavior is for the description to fail, although this can be changed through `options`. Equivalent to `git describe <committish>`. See [`DescribeOptions`](@ref) for more information. """ function GitDescribeResult(committish::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}), result_ptr_ptr, committish, Ref(options)) return GitDescribeResult(committish.owner, result_ptr_ptr[]) end """ LibGit2.GitDescribeResult(repo::GitRepo; kwarg...) Produce a `GitDescribeResult` of the repository `repo`'s working directory. The `GitDescribeResult` contains detailed information about the workdir based on the keyword argument: * `options::DescribeOptions=DescribeOptions()` In this case, the description is run on HEAD, producing the most recent tag which is an ancestor of HEAD. Afterwards, a status check on the [`workdir`](@ref) is performed and if the `workdir` is dirty (see [`isdirty`](@ref)) the description is also considered dirty. 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, (Ptr{Ptr{Cvoid}}, Ptr{Cvoid}, Ptr{DescribeOptions}), result_ptr_ptr, repo, Ref(options)) return GitDescribeResult(repo, result_ptr_ptr[]) end """ LibGit2.format(result::GitDescribeResult; kwarg...)::String Produce a formatted string based on a `GitDescribeResult`. 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}), buf_ref, result, Ref(options)) buf = buf_ref[] str = unsafe_string(buf.ptr, buf.size) free(buf_ref) return str end function Base.show(io::IO, result::GitDescribeResult) fmt_desc = format(result) println(io, "GitDescribeResult:") println(io, fmt_desc) end """ checkout_tree(repo::GitRepo, obj::GitObject; options::CheckoutOptions = CheckoutOptions()) Update the working tree and index of `repo` to match the tree pointed to by `obj`. `obj` can be a commit, a tag, or a tree. `options` controls how the checkout will 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}), repo, obj, Ref(options)) end """ checkout_index(repo::GitRepo, idx::Union{GitIndex, Nothing} = nothing; options::CheckoutOptions = CheckoutOptions()) Update the working tree of `repo` to match the index `idx`. If `idx` is `nothing`, the index of `repo` will be used. `options` controls how the checkout will be performed. 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}), repo, idx === nothing ? C_NULL : idx, Ref(options)) end """ checkout_head(repo::GitRepo; options::CheckoutOptions = CheckoutOptions()) Update the index and working tree of `repo` to match the commit pointed to by HEAD. `options` controls how the checkout will be performed. See [`CheckoutOptions`](@ref) for more information. !!! warning *Do not* use this function to switch branches! Doing so will cause checkout 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}), repo, Ref(options)) end """ LibGit2.cherrypick(repo::GitRepo, commit::GitCommit; options::CherrypickOptions = CherrypickOptions()) Cherrypick the commit `commit` and apply the changes in it to the current state of `repo`. The keyword argument `options` sets checkout and merge options for the cherrypick. !!! note `cherrypick` will *apply* the changes in `commit` but not *commit* them, so `repo` will be left in a dirty state. If you want to also commit the changes in `commit` you must 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}), repo, commit, Ref(options)) 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}), repo, obj === nothing ? C_NULL : obj, collect(pathspecs)) return head_oid(repo) 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}), repo, obj, mode, Ref(checkout_opts)) return head_oid(repo) end """ clone(repo_url::AbstractString, repo_path::AbstractString, clone_opts::CloneOptions) Clone the remote repository at `repo_url` (which can be a remote URL or a path on the local filesystem) to `repo_path` (which must be a path on the local filesystem). Options for the clone, such as whether to perform a bare clone or not, are set by [`CloneOptions`](@ref). # Examples ```julia repo_url = "https://github.com/JuliaLang/Example.jl" 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, (Ptr{Ptr{Cvoid}}, Cstring, Cstring, Ref{CloneOptions}), repo_ptr_ptr, repo_url, repo_path, clone_opts_ref) return GitRepo(repo_ptr_ptr[]) end """ fetchheads(repo::GitRepo)::Vector{FetchHead} Return the list of all the fetch heads for `repo`, each represented as a [`FetchHead`](@ref), including their names, URLs, and merge statuses. # Examples ```julia-repl julia> fetch_heads = LibGit2.fetchheads(repo); julia> fetch_heads[1].name "refs/heads/master" julia> fetch_heads[1].ismerge true julia> fetch_heads[2].name "refs/heads/test_branch" julia> fetch_heads[2].ismerge false ``` """ function fetchheads(repo::GitRepo) ensure_initialized() fh = FetchHead[] ffcb = fetchhead_foreach_cb() @assert repo.ptr != C_NULL @check ccall((:git_repository_fetchhead_foreach, libgit2), Cint, (Ptr{Cvoid}, Ptr{Cvoid}, Any), repo, ffcb, fh) return fh end """ LibGit2.remotes(repo::GitRepo) 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, (Ptr{StrArrayStruct}, Ptr{Cvoid}), sa_ref, repo) res = collect(sa_ref[]) free(sa_ref) return res end function Base.show(io::IO, repo::GitRepo) print(io, "LibGit2.GitRepo(") if repo.ptr == C_NULL print(io, "<closed>") else show(io, path(repo)) end print(io, ")") end