Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add GitShortHash type, remove some get methods #20104

Merged
merged 11 commits into from
Jan 31, 2017
Merged

add GitShortHash type, remove some get methods #20104

merged 11 commits into from
Jan 31, 2017

Conversation

simonbyrne
Copy link
Contributor

Another part of #19839.

ccall((:git_oid_fromstrp, :libgit2), Cint,
(Ptr{GitHash}, Cstring), oid_ptr, bstr)
if len < OID_HEXSZ
error("Input string is too short, use `GitShortHash` for partial hashes")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Might make more sense as an ArgumentError?





Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Four newlines seems like a lot of vertical whitespace. Perhaps for consistency it should be 1-2?

@ararslan ararslan added the libgit2 The libgit2 library or the LibGit2 stdlib module label Jan 18, 2017
@deprecate get{T<:GitObject}(::Type{T}, repo::GitRepo, oid::GitHash, oid_size::Int) T(repo, GitShortHash(oid, oid_size))
@deprecate revparse(repo::GitRepo, objname::AbstractString) GitObject(repo, objname)
@deprecate object(repo::GitRepo, te::GitTreeEntry) GitObject(repo, te)
@deprecate commit(ann::GitAnnotated) GitHash(ann)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

were these previously exported from the LibGit2 module?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No. Should I not bother deprecating them then?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

dunno who if anyone would be using these. the main concern is that @deprecate exports by default, if you want a non exported deprecation then you have to manually call depwarn

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These are sometimes used externally (e.g. PkgDev calls LibGit2.get).
I've added an option to @deprecate on whether to export or not.

else
return nothing
nothing
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what does this correspond to?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the resulting object is a commit, tag or tree. Arguably this is another function that could be removed altogether.

end
err != 0 && return GitHash()
oid_ptr = Ref{GitHash}()
@check ccall((:git_oid_fromstrn, :libgit2), Cint,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it had been calling fromstrp in this case, will they return the same thing if full length?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe so

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, fromstrp is just the null-terminated version of fromstrn. Since Julia strings store the length, we might as well use fromstrn.

end

Base.hex(id::GitHash) = join([hex(i,2) for i in id.val])
Base.hex(id::GitShortHash) = hex(id.hash)[1:id.len]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looks like there are two concepts of length for hashes, raw size and hex size, that differ by a factor of 2?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, exactly. id.len is hex size.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it looked like it was getting used as if it was raw size in a few places, though I may have misread

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's only used in a handful of functions: git_oid_ncmp and git_object_lookup_prefix

val::NTuple{OID_RAWSZ, UInt8}
GitHash(val::NTuple{OID_RAWSZ, UInt8}) = new(val)
end
GitHash() = GitHash(ntuple(i->zero(UInt8), OID_RAWSZ))

immutable GitShortHash <: AbstractGitHash
hash::GitHash
len::Csize_t
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be extra careful (and add lots of comments) that this gets used consistently as the right notion of length everywhere, hex or raw

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point.

return c == 0 ? cmp(id1.len, id2.len) : c
end
Base.cmp(id1::GitHash, id2::GitShortHash) = cmp(GitShortHash(id1, OID_RAWSZ), id2)
Base.cmp(id1::GitShortHash, id2::GitHash) = cmp(id1, GitShortHash(id2, OID_RAWSZ))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should these be using OID_HEXSZ then when converting a full GitHash to a GitShortHash?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, yes...

This is a shortened form of `GitHash`, which can be used to identify a git object when it
is unique.

Internally it is stored as two fields: a full-size `GitHash` (`hash`) and a length (`len`). Only the initial `len` hex digits of `hash` are used.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line length

close(obj)
return oid
Return the specified git object from `repo` specified by `hash` or `spec`.
- `hash` is a full (`GitHash`) or partial (`GitShortHash`)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

either leave out the parens or add the word hash at the end

Base.cmp(id1::GitHash, id2::GitShortHash) = cmp(GitShortHash(id1, OID_RAWSZ), id2)
Base.cmp(id1::GitShortHash, id2::GitHash) = cmp(id1, GitShortHash(id2, OID_RAWSZ))
Base.cmp(id1::GitHash, id2::GitShortHash) = cmp(GitShortHash(id1, OID_HEXSZ), id2)
Base.cmp(id1::GitShortHash, id2::GitHash) = cmp(id1, GitShortHash(id2, OID_HEXSZ))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

guess a comparison that depended on the latter half of the full input would have given differing results here, but we didn't have any such cases?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this function was used (or tested for that matter).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

via equality only?


==(id1::GitHash, id2::GitHash) = cmp(id1, id2) == 0
Base.isless(id1::GitHash, id2::GitHash) = cmp(id1, id2) < 0
==(id1::AbstractGitHash, id2::AbstractGitHash) = cmp(id1, id2) == 0
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this try to canonicalize short hashes and consider them equal to a full hash if they are unambiguous?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The problem is that they can only be canonicalized in the context of a single repository. But GitHashes exist independent of the repository.

Copy link
Contributor

@tkelman tkelman Jan 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh good point. So maybe we shouldn't define this for short hashes, and only use repo-context-aware equality testing with them?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Perhaps we could define isequal with a repo argument for any AbstractGitHash then as Tony said only have == for GitHash?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Meh, I'm not really convinced it's a problem that different AbstractGitHashes can refer identify the same object.

We should probably define == for GitObjects as well: could be "are they from the same repo, and are their GitHashes equal"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

two references to the same object comparing as not equal because they had different partial hash lengths strikes me as unintuitive and not a useful notion of equality

Copy link
Contributor Author

@simonbyrne simonbyrne Jan 21, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess it depends on whether you view a GitHash by itself as a reference to an object? Or is it only a reference in the context of a specific repo, in which case you have a GitObject?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm thinking that a GitHash type without a reference to an owning repository isn't all that meaningful on its own.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

okay, should we just revert this to ==(id1::GitHash, id2::GitHash) = cmp(id1, id2) == 0?

@check ccall((:git_index_read_tree, :libgit2), Cint,
(Ptr{Void}, Ptr{Void}), idx.ptr, tree.ptr)
end
function read_tree!(idx::GitIndex, hash::AbstractGitHash)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a one-line?

end
return head_oid(repo)
""" git reset [--soft | --mixed | --hard] <id> """
function reset!(repo::GitRepo, id::GitHash, mode::Cint = Consts.RESET_MIXED)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again can this be a one-line?

peel([T,] ref::GitReference)

Recursively peel `ref` until an object of type `T` is obtained. If no `T` is provided,
then it will be peeled until an object other than a `GitTag` is obtained.
Copy link
Contributor

@tkelman tkelman Jan 25, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maybe ref in place of "it" would be more clear

(same for L181 of repository.jl)

@simonbyrne
Copy link
Contributor Author

I think this is ready to go.

peel([T,] obj::GitObject)

Recursively peel `obj` until an object of type `T` is obtained. If no `T` is provided,
then it will be peeled until the type changes.
Copy link
Contributor

@tkelman tkelman Jan 27, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we put obj instead of "it" here, otherwise it's potentially ambiguous whether "it" refers to T or obj

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done. I've also added docs for all the GitObject types.

for i in 1:showlen
print(io, conts[i],"\n")
end
else
print(io, "GitBlob:\nBlob id: ", GitHash(blob.ptr), "\nContents are binary.")
print(io, "GitBlob:\nBlob id: ", GitHash(blob), "\nContents are binary.")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should this be println? along with the other prints in this function that have been adding \n manually

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done.

@@ -73,15 +73,29 @@ function isattached(repo::GitRepo)
ccall((:git_repository_head_detached, :libgit2), Cint, (Ptr{Void},), repo.ptr) != 1
end

"""
@doc """
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the @doc necessary here?

@@ -1,7 +1,7 @@
# This file is a part of Julia. License is MIT: http://julialang.org/license

function content(blob::GitBlob)
return ccall((:git_blob_rawcontent, :libgit2), Ptr{Void}, (Ptr{Void},), blob.ptr)
unsafe_string(ccall((:git_blob_rawcontent, :libgit2), Ptr{UInt8}, (Ptr{Void},), blob.ptr))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if this is binary content, it could easily have embedded nuls or be invalid utf-8, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. We can deal with the NUL issue by calling it with a length argument (which I presume is git_blob_rawsize). But I don't know how we could deal with non-UTF8 data.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

have it return an array of bytes?

end

function content(blob::GitBlob)
s = String(rawcontent)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rawcontent(blob)

@kshyatt
Copy link
Contributor

kshyatt commented Jan 31, 2017

Can this be merged?

Copy link
Member

@ararslan ararslan left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me!

@kshyatt kshyatt merged commit c99e12c into master Jan 31, 2017
@kshyatt kshyatt deleted the sb/gitshorthash branch January 31, 2017 18:53
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
libgit2 The libgit2 library or the LibGit2 stdlib module
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants