Skip to content

Commit

Permalink
Pkg.free: correctly set target nullable object (#17483)
Browse files Browse the repository at this point in the history
* correctly set target nullable object

* added: stage & stage tests
added: file status, index entry search

* throw if reset object wasn't found

* removed trailing spaces
  • Loading branch information
wildart authored and tkelman committed Jul 21, 2016
1 parent fa20d26 commit df307cd
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 5 deletions.
10 changes: 10 additions & 0 deletions base/libgit2/index.jl
Original file line number Diff line number Diff line change
Expand Up @@ -118,3 +118,13 @@ function Base.getindex(idx::GitIndex, i::Csize_t)
return unsafe_load(convert(Ptr{IndexEntry}, ie_ptr), 1)
end
Base.getindex(idx::GitIndex, i::Int) = getindex(idx, Csize_t(i))

function Base.find(path::String, idx::GitIndex)
pos_ref = Ref{Csize_t}(0)
ret = ccall((:git_index_find, :libgit2), Cint,
(Ref{Csize_t}, Ptr{Void}, Cstring), pos_ref, idx.ptr, path)
ret == Error.ENOTFOUND && return Nullable{Csize_t}()
return Nullable(pos_ref[]+1)
end

stage(ie::IndexEntry) = ccall((:git_index_entry_stage, :libgit2), Cint, (Ptr{IndexEntry},), Ref(ie))
12 changes: 7 additions & 5 deletions base/libgit2/libgit2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -310,19 +310,21 @@ end

""" git reset [<committish>] [--] <pathspecs>... """
function reset!(repo::GitRepo, committish::AbstractString, pathspecs::AbstractString...)
target_obj = isempty(committish) ? Nullable{GitAnyObject}() :
Nullable(revparse(repo, committish))
obj = revparse(repo, !isempty(committish) ? committish : Consts.HEAD_FILE)
# do not remove entries in the index matching the provided pathspecs with empty target commit tree
obj === nothing && throw(GitError(Error.Object, Error.ERROR, "`$committish` not found"))
try
reset!(repo, target_obj, pathspecs...)
reset!(repo, Nullable(obj), pathspecs...)
finally
!isnull(target_obj) && finalize(Base.get(target_obj))
finalize(obj)
end
end

""" git reset [--soft | --mixed | --hard] <commit> """
function reset!(repo::GitRepo, commit::Oid, mode::Cint = Consts.RESET_MIXED)
obj = get(GitAnyObject, repo, commit)
obj === nothing && return
# object must exist for reset
obj === nothing && throw(GitError(Error.Object, Error.ERROR, "Commit `$(string(commit))` object not found"))
try
reset!(repo, obj, mode)
finally
Expand Down
2 changes: 2 additions & 0 deletions base/libgit2/repository.jl
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ function checkout_head(repo::GitRepo; options::CheckoutOptions = CheckoutOptions
repo.ptr, Ref(options))
end

"""Updates some entries, determined by the `pathspecs`, in the index from the target commit tree."""
function reset!{T<:AbstractString, S<:GitObject}(repo::GitRepo, obj::Nullable{S}, pathspecs::T...)
with(StrArrayStruct(pathspecs...)) do sa
@check ccall((:git_reset_default, :libgit2), Cint,
Expand All @@ -175,6 +176,7 @@ function reset!{T<:AbstractString, S<:GitObject}(repo::GitRepo, obj::Nullable{S}
end
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())
@check ccall((:git_reset, :libgit2), Cint,
Expand Down
9 changes: 9 additions & 0 deletions base/libgit2/status.jl
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,12 @@ function Base.getindex(status::GitStatus, i::Csize_t)
return unsafe_load(convert(Ptr{StatusEntry}, entry_ptr), 1)
end
Base.getindex(status::GitStatus, i::Int) = getindex(status, Csize_t(i))

function status(repo::GitRepo, path::String)
status_ptr = Ref{Cuint}(0)
ret = ccall((:git_status_file, :libgit2), Cint,
(Ref{Cuint}, Ptr{Void}, Cstring),
status_ptr, repo.ptr, path)
(ret == Cint(Error.ENOTFOUND) || ret == Cint(Error.EAMBIGUOUS)) && return Nullable{Cuint}()
return Nullable(status_ptr[])
end
61 changes: 61 additions & 0 deletions test/libgit2.jl
Original file line number Diff line number Diff line change
Expand Up @@ -474,6 +474,67 @@ mktempdir() do dir
#end
#end

#@testset "Modify and reset repository" begin
repo = LibGit2.GitRepo(test_repo)
try
# check index for file
LibGit2.with(LibGit2.GitIndex(repo)) do idx
i = find(test_file, idx)
@test !isnull(i)
@test idx[get(i)] !== nothing
end

# check non-existent file status
st = LibGit2.status(repo, "XYZ")
@test isnull(st)

# check file status
st = LibGit2.status(repo, test_file)
@test !isnull(st)
@test LibGit2.isset(get(st), LibGit2.Consts.STATUS_CURRENT)

# modify file
open(joinpath(test_repo, test_file), "a") do io
write(io, 0x41)
end

# file modified but not staged
st_mod = LibGit2.status(repo, test_file)
@test !LibGit2.isset(get(st_mod), LibGit2.Consts.STATUS_INDEX_MODIFIED)
@test LibGit2.isset(get(st_mod), LibGit2.Consts.STATUS_WT_MODIFIED)

# stage file
LibGit2.add!(repo, test_file)

# modified file staged
st_stg = LibGit2.status(repo, test_file)
@test LibGit2.isset(get(st_stg), LibGit2.Consts.STATUS_INDEX_MODIFIED)
@test !LibGit2.isset(get(st_stg), LibGit2.Consts.STATUS_WT_MODIFIED)

# try to unstage to unknown commit
@test_throws LibGit2.Error.GitError LibGit2.reset!(repo, "XYZ", test_file)

# status should not change
st_new = LibGit2.status(repo, test_file)
@test get(st_new) == get(st_stg)

# try to unstage to HEAD
LibGit2.reset!(repo, LibGit2.Consts.HEAD_FILE, test_file)
st_uns = LibGit2.status(repo, test_file)
@test get(st_uns) == get(st_mod)

# reset repo
@test_throws LibGit2.Error.GitError LibGit2.reset!(repo, LibGit2.Oid(), LibGit2.Consts.RESET_HARD)

LibGit2.reset!(repo, LibGit2.head_oid(repo), LibGit2.Consts.RESET_HARD)
open(joinpath(test_repo, test_file), "r") do io
@test read(io)[end] != 0x41
end
finally
finalize(repo)
end
#end

#@testset "Transact test repository" begin
repo = LibGit2.GitRepo(test_repo)
try
Expand Down

0 comments on commit df307cd

Please sign in to comment.