Source code for maggit.repo

# This file is part of maggit.
#
# Copyright 2015 Matthieu Gautier <dev@mgautier.fr>
#
# Pit is free software: you can redistribute it and/or modify
# it under the terms of the GNU Affero General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pit is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# Additional permission under the GNU Affero GPL version 3 section 7:
#
# If you modify this Program, or any covered work, by linking or
# combining it with other code, such other code is not for that reason
# alone subject to any of the requirements of the GNU Affero GPL
# version 3.
#
# You should have received a copy of the GNU Affero General Public License
# along with maggit.  If not, see http://www.gnu.org/licenses
#
# In summary:
# - You can use this program for no cost.
# - You can use this program for both personal and commercial reasons.
# - You do not have to share your own program's code which uses this program.
# - You have to share modifications (e.g bug-fixes, improvements) you've made to this program.

from . import gitObjects
from . import refs
from .sha import Sha
import os

from maggit import db

[docs]class Repo(db.Repo): """This is the central piece of a git repository. """ @property def HEAD(self): """The current checkouted branch""" return refs.Branche(self, self.refs.HEAD) @property def branches(self): """A dict of branches in the repo""" return {k:refs.Branche(self, k) for k in self.refs.branches} @property def tags(self): """A dict of tags in the repo""" return {k:refs.Tag(self, k) for k in self.refs.tags}
[docs] def get_object(self, sha): """Get a git object for the sha. Arguments: sha(:class:`~maggit.Sha`) : The sha of the object. Returns: A :class:`~maggit.gitObjects.GitObject` object for this sha. Raises: :Exception: If sha doesn't name a object. """ sha = Sha.cast(sha) type_ = gitObjects.byte_to_class(self.db.object_type(sha)) return type_(self, sha)
[docs] def get_full_sha(self, prefix): """Return the full Sha of the prefix Arguments: prefix(bytes): The beginning of a sha. Returns: The :class:`~maggit.Sha` corresponding. Exemples: >>> repo.get_full_sha(b'bf09f0a9') <Sha b'bf09f0a9...'> Raises: :Exception: If number of object corresponding to prefix is not equal to one. """ sha = self.db.get_full_sha(prefix) return Sha(sha)
[docs]class Entry: """A Entry represent a entry (file or directory) at a specific time. We can somehow see a repository as a complex 2 dimentionnal array. Commits (and so the history) are rows. Files (and Trees) are columns. In this situations, Entry are the cells of this array. Arguments: commit(:class:`maggit.Commit`) : The commit associated to the Entry path(bytes path) : The path of the file to look at. The path must be a bytes where directory are separated by b'/'. Raise: KeyError if the path is not existing. """ def __init__(self, commit, path): self.commit = commit self.path = path current = commit.tree for part in path.split(b'/'): mode, current = current[part] self.mode = mode self.gitObject = current @property def repo(self): return self.commit.repo
[docs] def is_blob(self): """Return True if the entry is corresponding to a blob object""" return type(self.gitObject) == gitObjects.Blob
@property def parents(self): """The previous versions of the files. Previous versions can be equal to the current one if the current commit introduce no change on this file. The length of the parents will most of the time be 1 but may be greater in case of merge. """ return (Entry(p, self.path) for p in self.commit.parents)
[docs] def get_first_appearance(self): """Return the commit who firstly introduce the current version of the change. Returns: A :class:`maggit.Commit` Exemples: >>> first_appearance_commit = this_entry.get_first_appearance() >>> # first_appearance_commit is the first one, so previous version differs >>> parent = first_appearance_commit.parents[0] >>> assert Entry(first_appearance_commit, this_entry.path).gitObject != Entry(parent, this_entry.path).gitObject >>> # from this_commit to first_appearance_commit, there is no change >>> current = this_entry.commit >>> while current != first_appearance_commit: ... assert Entry(current, this_entry.path).gitObject == this_entry.gitObject ... current = current.parents[0] """ current = self.commit while True: try: parent = current.parents[0] except IndexError: # No parent return current c_tree = current.tree p_tree = parent.tree if c_tree.is_entry_diff(p_tree, self.path): # There is a diff, current is the commit who introduce # this versions. return current # No diff for this path # Continue check in the history current = parent