def name_to_object(repo, name):
	""":return: object specified by the given name, hexshas ( short and long )
		as well as references are supported"""
	hexsha = None
	
	# is it a hexsha ? Try the most common ones, which is 7 to 40
	if repo.re_hexsha_shortened.match(name):
		if len(name) != 40:
			# find long sha for short sha
			hexsha = short_to_long(repo.odb, name)
		else:
			hexsha = name
		# END handle short shas
	else:
		for base in ('%s', 'refs/%s', 'refs/tags/%s', 'refs/heads/%s', 'refs/remotes/%s', 'refs/remotes/%s/HEAD'):
			try:
				hexsha = SymbolicReference.dereference_recursive(repo, base % name)
				break
			except ValueError:
				pass
		# END for each base
	# END handle hexsha
	
	# tried everything ? fail
	if hexsha is None:
		raise BadObject(name)
	# END assert hexsha was found
	
	return Object.new_from_sha(repo, hex_to_bin(hexsha))
Esempio n. 2
0
def name_to_object(repo, name):
    """:return: object specified by the given name, hexshas ( short and long )
		as well as references are supported"""
    hexsha = None

    # is it a hexsha ? Try the most common ones, which is 7 to 40
    if repo.re_hexsha_shortened.match(name):
        if len(name) != 40:
            # find long sha for short sha
            hexsha = short_to_long(repo.odb, name)
        else:
            hexsha = name
        # END handle short shas
    else:
        for base in ('%s', 'refs/%s', 'refs/tags/%s', 'refs/heads/%s',
                     'refs/remotes/%s', 'refs/remotes/%s/HEAD'):
            try:
                hexsha = SymbolicReference.dereference_recursive(
                    repo, base % name)
                break
            except ValueError:
                pass
        # END for each base
    # END handle hexsha

    # tried everything ? fail
    if hexsha is None:
        raise BadObject(name)
    # END assert hexsha was found

    return Object.new_from_sha(repo, hex_to_bin(hexsha))
Esempio n. 3
0
 def _get_object(self):
     """
     :return:
         The object our ref currently refers to. Refs can be cached, they will
         always point to the actual object as it gets re-created on each query"""
     # have to be dynamic here as we may be a tag which can point to anything
     # Our path will be resolved to the hexsha which will be used accordingly
     return Object.new_from_sha(self.repo, hex_to_bin(self.dereference_recursive(self.repo, self.path)))
 def _get_object(self):
     """
     :return:
         The object our ref currently refers to. Refs can be cached, they will
         always point to the actual object as it gets re-created on each query"""
     # have to be dynamic here as we may be a tag which can point to anything
     # Our path will be resolved to the hexsha which will be used accordingly
     return Object.new_from_sha(self.repo, hex_to_bin(self.dereference_recursive(self.repo, self.path)))
Esempio n. 5
0
def name_to_object(
    repo: 'Repo',
    name: str,
    return_ref: bool = False
) -> Union[SymbolicReference, 'Commit', 'TagObject', 'Blob', 'Tree']:
    """
    :return: object specified by the given name, hexshas ( short and long )
        as well as references are supported
    :param return_ref: if name specifies a reference, we will return the reference
        instead of the object. Otherwise it will raise BadObject or BadName
    """
    hexsha: Union[None, str, bytes] = None

    # is it a hexsha ? Try the most common ones, which is 7 to 40
    if repo.re_hexsha_shortened.match(name):
        if len(name) != 40:
            # find long sha for short sha
            hexsha = short_to_long(repo.odb, name)
        else:
            hexsha = name
        # END handle short shas
    # END find sha if it matches

    # if we couldn't find an object for what seemed to be a short hexsha
    # try to find it as reference anyway, it could be named 'aaa' for instance
    if hexsha is None:
        for base in ('%s', 'refs/%s', 'refs/tags/%s', 'refs/heads/%s',
                     'refs/remotes/%s', 'refs/remotes/%s/HEAD'):
            try:
                hexsha = SymbolicReference.dereference_recursive(
                    repo, base % name)
                if return_ref:
                    return SymbolicReference(repo, base % name)
                # END handle symbolic ref
                break
            except ValueError:
                pass
        # END for each base
    # END handle hexsha

    # didn't find any ref, this is an error
    if return_ref:
        raise BadObject("Couldn't find reference named %r" % name)
    # END handle return ref

    # tried everything ? fail
    if hexsha is None:
        raise BadName(name)
    # END assert hexsha was found

    return Object.new_from_sha(repo, hex_to_bin(hexsha))
Esempio n. 6
0
def name_to_object(repo, name, return_ref=False):
    """
    :return: object specified by the given name, hexshas ( short and long )
        as well as references are supported
    :param return_ref: if name specifies a reference, we will return the reference
        instead of the object. Otherwise it will raise BadObject
    """
    hexsha = None

    # is it a hexsha ? Try the most common ones, which is 7 to 40
    if repo.re_hexsha_shortened.match(name):
        if len(name) != 40:
            # find long sha for short sha
            hexsha = short_to_long(repo.odb, name)
        else:
            hexsha = name
        # END handle short shas
        # END find sha if it matches

    # if we couldn't find an object for what seemed to be a short hexsha
    # try to find it as reference anyway, it could be named 'aaa' for instance
    if hexsha is None:
        for base in ('%s', 'refs/%s', 'refs/tags/%s', 'refs/heads/%s', 'refs/remotes/%s',
                     'refs/remotes/%s/HEAD'):
            try:
                hexsha = SymbolicReference.dereference_recursive(repo, base % name)
                if return_ref:
                    return SymbolicReference(repo, base % name)
                #END handle symbolic ref
                break
            except ValueError:
                pass
            # END for each base
    # END handle hexsha

    # didn't find any ref, this is an error
    if return_ref:
        raise BadObject("Couldn't find reference named %r" % name)
    #END handle return ref

    # tried everything ? fail
    if hexsha is None:
        raise BadObject(name)
    # END assert hexsha was found

    return Object.new_from_sha(repo, hex_to_bin(hexsha))
Esempio n. 7
0
def name_to_object(repo, name, return_ref=False):
    """
	:return: object specified by the given name, hexshas ( short and long )
		as well as references are supported
	:param return_ref: if name specifies a reference, we will return the reference
		instead of the object. Otherwise it will raise BadObject
	"""
    hexsha = None

    # is it a hexsha ? Try the most common ones, which is 7 to 40
    if repo.re_hexsha_shortened.match(name):
        if len(name) != 40:
            # find long sha for short sha
            hexsha = short_to_long(repo.odb, name)
        else:
            hexsha = name
        # END handle short shas
    else:
        for base in ('%s', 'refs/%s', 'refs/tags/%s', 'refs/heads/%s',
                     'refs/remotes/%s', 'refs/remotes/%s/HEAD'):
            try:
                hexsha = SymbolicReference.dereference_recursive(
                    repo, base % name)
                if return_ref:
                    return SymbolicReference(repo, base % name)
                #END handle symbolic ref
                break
            except ValueError:
                pass
        # END for each base
    # END handle hexsha

    # didn't find any ref, this is an error
    if return_ref:
        raise BadObject("Couldn't find reference named %r" % name)
    #END handle return ref

    # tried everything ? fail
    if hexsha is None:
        raise BadObject(name)
    # END assert hexsha was found

    return Object.new_from_sha(repo, hex_to_bin(hexsha))
Esempio n. 8
0
def rev_parse(repo, rev):
    """
    :return: Object at the given revision, either Commit, Tag, Tree or Blob
    :param rev: git-rev-parse compatible revision specification as string, please see
        http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html
        for details
    :raise BadObject: if the given revision could not be found
    :raise ValueError: If rev couldn't be parsed
    :raise IndexError: If invalid reflog index is specified"""

    # colon search mode ?
    if rev.startswith(':/'):
        # colon search mode
        raise NotImplementedError("commit by message search ( regex )")
    # END handle search

    obj = None
    ref = None
    output_type = "commit"
    start = 0
    parsed_to = 0
    lr = len(rev)
    while start < lr:
        if rev[start] not in "^~:@":
            start += 1
            continue
        # END handle start

        token = rev[start]

        if obj is None:
            # token is a rev name
            if start == 0:
                ref = repo.head.ref
            else:
                if token == '@':
                    ref = name_to_object(repo, rev[:start], return_ref=True)
                else:
                    obj = name_to_object(repo, rev[:start])
                # END handle token
            # END handle refname

            if ref is not None:
                obj = ref.commit
            # END handle ref
        # END initialize obj on first token

        start += 1

        # try to parse {type}
        if start < lr and rev[start] == '{':
            end = rev.find('}', start)
            if end == -1:
                raise ValueError("Missing closing brace to define type in %s" %
                                 rev)
            output_type = rev[start + 1:end]  # exclude brace

            # handle type
            if output_type == 'commit':
                pass  # default
            elif output_type == 'tree':
                try:
                    obj = to_commit(obj).tree
                except (AttributeError, ValueError):
                    pass  # error raised later
                # END exception handling
            elif output_type in ('', 'blob'):
                if obj.type == 'tag':
                    obj = deref_tag(obj)
                else:
                    # cannot do anything for non-tags
                    pass
                # END handle tag
            elif token == '@':
                # try single int
                assert ref is not None, "Requre Reference to access reflog"
                revlog_index = None
                try:
                    # transform reversed index into the format of our revlog
                    revlog_index = -(int(output_type) + 1)
                except ValueError:
                    # TODO: Try to parse the other date options, using parse_date
                    # maybe
                    raise NotImplementedError(
                        "Support for additional @{...} modes not implemented")
                # END handle revlog index

                try:
                    entry = ref.log_entry(revlog_index)
                except IndexError:
                    raise IndexError("Invalid revlog index: %i" % revlog_index)
                # END handle index out of bound

                obj = Object.new_from_sha(repo, hex_to_bin(entry.newhexsha))

                # make it pass the following checks
                output_type = None
            else:
                raise ValueError("Invalid output type: %s ( in %s )" %
                                 (output_type, rev))
            # END handle output type

            # empty output types don't require any specific type, its just about dereferencing tags
            if output_type and obj.type != output_type:
                raise ValueError(
                    "Could not accommodate requested object type %r, got %s" %
                    (output_type, obj.type))
            # END verify output type

            start = end + 1  # skip brace
            parsed_to = start
            continue
        # END parse type

        # try to parse a number
        num = 0
        if token != ":":
            found_digit = False
            while start < lr:
                if rev[start] in digits:
                    num = num * 10 + int(rev[start])
                    start += 1
                    found_digit = True
                else:
                    break
                # END handle number
            # END number parse loop

            # no explicit number given, 1 is the default
            # It could be 0 though
            if not found_digit:
                num = 1
            # END set default num
        # END number parsing only if non-blob mode

        parsed_to = start
        # handle hierarchy walk
        try:
            if token == "~":
                obj = to_commit(obj)
                for _ in xrange(num):
                    obj = obj.parents[0]
                # END for each history item to walk
            elif token == "^":
                obj = to_commit(obj)
                # must be n'th parent
                if num:
                    obj = obj.parents[num - 1]
            elif token == ":":
                if obj.type != "tree":
                    obj = obj.tree
                # END get tree type
                obj = obj[rev[start:]]
                parsed_to = lr
            else:
                raise ValueError("Invalid token: %r" % token)
            # END end handle tag
        except (IndexError, AttributeError):
            raise BadName(
                "Invalid revision spec '%s' - not enough parent commits to reach '%s%i'"
                % (rev, token, num))
        # END exception handling
    # END parse loop

    # still no obj ? Its probably a simple name
    if obj is None:
        obj = name_to_object(repo, rev)
        parsed_to = lr
    # END handle simple name

    if obj is None:
        raise ValueError("Revision specifier could not be parsed: %s" % rev)

    if parsed_to != lr:
        raise ValueError(
            "Didn't consume complete rev spec %s, consumed part: %s" %
            (rev, rev[:parsed_to]))

    return obj
Esempio n. 9
0
def rev_parse(repo, rev):
    """
    :return: Object at the given revision, either Commit, Tag, Tree or Blob
    :param rev: git-rev-parse compatible revision specification, please see
        http://www.kernel.org/pub/software/scm/git/docs/git-rev-parse.html
        for details
    :note: Currently there is no access to the rev-log, rev-specs may only contain
        topological tokens such ~ and ^.
    :raise BadObject: if the given revision could not be found
    :raise ValueError: If rev couldn't be parsed
    :raise IndexError: If invalid reflog index is specified"""

    # colon search mode ?
    if rev.startswith(':/'):
        # colon search mode
        raise NotImplementedError("commit by message search ( regex )")
    # END handle search

    obj = None
    ref = None
    output_type = "commit"
    start = 0
    parsed_to = 0
    lr = len(rev)
    while start < lr:
        if rev[start] not in "^~:@":
            start += 1
            continue
        # END handle start

        token = rev[start]

        if obj is None:
            # token is a rev name
            if start == 0:
                ref = repo.head.ref
            else:
                if token == '@':
                    ref = name_to_object(repo, rev[:start], return_ref=True)
                else:
                    obj = name_to_object(repo, rev[:start])
                    # END handle token
                    # END handle refname

            if ref is not None:
                obj = ref.commit
            #END handle ref
        # END initialize obj on first token


        start += 1

        # try to parse {type}
        if start < lr and rev[start] == '{':
            end = rev.find('}', start)
            if end == -1:
                raise ValueError("Missing closing brace to define type in %s" % rev)
            output_type = rev[start + 1:end]  # exclude brace

            # handle type
            if output_type == 'commit':
                pass  # default
            elif output_type == 'tree':
                try:
                    obj = to_commit(obj).tree
                except (AttributeError, ValueError):
                    pass  # error raised later
                # END exception handling
            elif output_type in ('', 'blob'):
                if obj.type == 'tag':
                    obj = deref_tag(obj)
                else:
                    # cannot do anything for non-tags
                    pass
                # END handle tag
            elif token == '@':
                # try single int
                assert ref is not None, "Requre Reference to access reflog"
                revlog_index = None
                try:
                    # transform reversed index into the format of our revlog
                    revlog_index = -(int(output_type) + 1)
                except ValueError:
                    # TODO: Try to parse the other date options, using parse_date
                    # maybe
                    raise NotImplementedError("Support for additional @{...} modes not implemented")
                    # END handle revlog index

                try:
                    entry = ref.log_entry(revlog_index)
                except IndexError:
                    raise IndexError("Invalid revlog index: %i" % revlog_index)
                #END handle index out of bound

                obj = Object.new_from_sha(repo, hex_to_bin(entry.newhexsha))

                # make it pass the following checks
                output_type = None
            else:
                raise ValueError("Invalid output type: %s ( in %s )" % (output_type, rev))
            # END handle output type

            # empty output types don't require any specific type, its just about dereferencing tags
            if output_type and obj.type != output_type:
                raise ValueError("Could not accomodate requested object type %r, got %s" % (
                output_type, obj.type))
            # END verify ouput type

            start = end + 1  # skip brace
            parsed_to = start
            continue
        # END parse type

        # try to parse a number
        num = 0
        if token != ":":
            found_digit = False
            while start < lr:
                if rev[start] in digits:
                    num = num * 10 + int(rev[start])
                    start += 1
                    found_digit = True
                else:
                    break
                # END handle number
            # END number parse loop

            # no explicit number given, 1 is the default
            # It could be 0 though
            if not found_digit:
                num = 1
            # END set default num
        # END number parsing only if non-blob mode


        parsed_to = start
        # handle hiererarchy walk
        try:
            if token == "~":
                obj = to_commit(obj)
                for item in xrange(num):
                    obj = obj.parents[0]
                # END for each history item to walk
            elif token == "^":
                obj = to_commit(obj)
                # must be n'th parent
                if num:
                    obj = obj.parents[num - 1]
            elif token == ":":
                if obj.type != "tree":
                    obj = obj.tree
                # END get tree type
                obj = obj[rev[start:]]
                parsed_to = lr
            else:
                raise ValueError("Invalid token: %r" % token)
            # END end handle tag
        except (IndexError, AttributeError):
            raise BadObject("Invalid Revision in %s" % rev)
        # END exception handling
    # END parse loop

    # still no obj ? Its probably a simple name
    if obj is None:
        obj = name_to_object(repo, rev)
        parsed_to = lr
    # END handle simple name

    if obj is None:
        raise ValueError("Revision specifier could not be parsed: %s" % rev)

    if parsed_to != lr:
        raise ValueError(
            "Didn't consume complete rev spec %s, consumed part: %s" % (rev, rev[:parsed_to]))

    return obj