diff options
Diffstat (limited to 'lib/git_python')
-rw-r--r-- | lib/git_python/__init__.py | 21 | ||||
-rw-r--r-- | lib/git_python/actor.py | 33 | ||||
-rw-r--r-- | lib/git_python/blob.py | 134 | ||||
-rw-r--r-- | lib/git_python/commit.py | 235 | ||||
-rw-r--r-- | lib/git_python/diff.py | 79 | ||||
-rw-r--r-- | lib/git_python/errors.py | 8 | ||||
-rw-r--r-- | lib/git_python/git.py | 190 | ||||
-rw-r--r-- | lib/git_python/head.py | 107 | ||||
-rw-r--r-- | lib/git_python/lazy.py | 26 | ||||
-rw-r--r-- | lib/git_python/method_missing.py | 21 | ||||
-rw-r--r-- | lib/git_python/repo.py | 435 | ||||
-rw-r--r-- | lib/git_python/stats.py | 17 | ||||
-rw-r--r-- | lib/git_python/tag.py | 85 | ||||
-rw-r--r-- | lib/git_python/tree.py | 89 | ||||
-rw-r--r-- | lib/git_python/utils.py | 11 |
15 files changed, 0 insertions, 1491 deletions
diff --git a/lib/git_python/__init__.py b/lib/git_python/__init__.py deleted file mode 100644 index 36eb7b37..00000000 --- a/lib/git_python/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -import inspect - -from git_python.actor import Actor -from git_python.blob import Blob -from git_python.commit import Commit -from git_python.diff import Diff -from git_python.errors import InvalidGitRepositoryError, NoSuchPathError -from git_python.git import Git -from git_python.head import Head -from git_python.repo import Repo -from git_python.stats import Stats -from git_python.tag import Tag -from git_python.tree import Tree -from git_python.utils import dashify -from git_python.utils import touch -from git_python.utils import pop_key - -__all__ = [ name for name, obj in locals().items() - if not (name.startswith('_') or inspect.ismodule(obj)) ] - -__version__ = 'svn' diff --git a/lib/git_python/actor.py b/lib/git_python/actor.py deleted file mode 100644 index ed21d8ba..00000000 --- a/lib/git_python/actor.py +++ /dev/null @@ -1,33 +0,0 @@ -import re - -class Actor(object): - def __init__(self, name, email): - self.name = name - self.email = email - - def __str__(self): - return self.name - - def __repr__(self): - return '<GitPython.Actor "%s <%s>">' % (self.name, self.email) - - @classmethod - def from_string(cls, string): - """ - Create an Actor from a string. - - ``str`` - is the string, which is expected to be in regular git format - - Format - John Doe <jdoe@example.com> - - Returns - Actor - """ - if re.search(r'<.+>', string): - m = re.search(r'(.*) <(.+?)>', string) - name, email = m.groups() - return Actor(name, email) - else: - return Actor(string, None) diff --git a/lib/git_python/blob.py b/lib/git_python/blob.py deleted file mode 100644 index 134cb93d..00000000 --- a/lib/git_python/blob.py +++ /dev/null @@ -1,134 +0,0 @@ -import mimetypes -import os -import re -import time -from actor import Actor -from commit import Commit - -class Blob(object): - DEFAULT_MIME_TYPE = "text/plain" - - def __init__(self, repo, **kwargs): - """ - Create an unbaked Blob containing just the specified attributes - - ``repo`` - is the Repo - - ``atts`` - is a dict of instance variable data - - Returns - GitPython.Blob - """ - self.id = None - self.mode = None - self.name = None - self._size = None - self.data_stored = None - - self.repo = repo - for k, v in kwargs.items(): - setattr(self, k, v) - - @property - def size(self): - """ - The size of this blob in bytes - - Returns - int - """ - if self._size is None: - self._size = int(self.repo.git.cat_file(self.id, **{'s': True}).rstrip()) - return self._size - - @property - def data(self): - """ - The binary contents of this blob. - - Returns - str - """ - self.data_stored = self.data_stored or self.repo.git.cat_file(self.id, **{'p': True}) - return self.data_stored - - @property - def mime_type(self): - """ - The mime type of this file (based on the filename) - - Returns - str - """ - guesses = None - if self.name: - guesses = mimetypes.guess_type(self.name) - return guesses and guesses[0] or self.DEFAULT_MIME_TYPE - - @property - def basename(self): - return os.path.basename(self.name) - - @classmethod - def blame(cls, repo, commit, file): - """ - The blame information for the given file at the given commit - - Returns - list: [GitPython.Commit, list: [<line>]] - """ - data = repo.git.blame(commit, '--', file, **{'p': True}) - commits = {} - blames = [] - info = None - - for line in data.splitlines(): - parts = re.split(r'\s+', line, 1) - if re.search(r'^[0-9A-Fa-f]{40}$', parts[0]): - if re.search(r'^([0-9A-Fa-f]{40}) (\d+) (\d+) (\d+)$', line): - m = re.search(r'^([0-9A-Fa-f]{40}) (\d+) (\d+) (\d+)$', line) - id, origin_line, final_line, group_lines = m.groups() - info = {'id': id} - blames.append([None, []]) - elif re.search(r'^([0-9A-Fa-f]{40}) (\d+) (\d+)$', line): - m = re.search(r'^([0-9A-Fa-f]{40}) (\d+) (\d+)$', line) - id, origin_line, final_line = m.groups() - info = {'id': id} - elif re.search(r'^(author|committer)', parts[0]): - if re.search(r'^(.+)-mail$', parts[0]): - m = re.search(r'^(.+)-mail$', parts[0]) - info["%s_email" % m.groups()[0]] = parts[-1] - elif re.search(r'^(.+)-time$', parts[0]): - m = re.search(r'^(.+)-time$', parts[0]) - info["%s_date" % m.groups()[0]] = time.gmtime(int(parts[-1])) - elif re.search(r'^(author|committer)$', parts[0]): - m = re.search(r'^(author|committer)$', parts[0]) - info[m.groups()[0]] = parts[-1] - elif re.search(r'^filename', parts[0]): - info['filename'] = parts[-1] - elif re.search(r'^summary', parts[0]): - info['summary'] = parts[-1] - elif parts[0] == '': - if info: - c = commits.has_key(info['id']) and commits[info['id']] - if not c: - c = Commit(repo, **{'id': info['id'], - 'author': Actor.from_string(info['author'] + ' ' + info['author_email']), - 'authored_date': info['author_date'], - 'committer': Actor.from_string(info['committer'] + ' ' + info['committer_email']), - 'committed_date': info['committer_date'], - 'message': info['summary']}) - commits[info['id']] = c - - m = re.search(r'^\t(.*)$', line) - text, = m.groups() - blames[-1][0] = c - blames[-1][1] += text - info = None - - return blames - - def __repr__(self): - return '<GitPython.Blob "%s">' % self.id diff --git a/lib/git_python/commit.py b/lib/git_python/commit.py deleted file mode 100644 index 701f6c04..00000000 --- a/lib/git_python/commit.py +++ /dev/null @@ -1,235 +0,0 @@ -import re -import time - -from actor import Actor -from lazy import LazyMixin -import tree -import diff -import stats - -class Commit(LazyMixin): - def __init__(self, repo, **kwargs): - """ - Instantiate a new Commit - - ``id`` - is the id of the commit - - ``parents`` - is a list of commit ids (will be converted into Commit instances) - - ``tree`` - is the correspdonding tree id (will be converted into a Tree object) - - ``author`` - is the author string - - ``authored_date`` - is the authored DateTime - - ``committer`` - is the committer string - - ``committed_date`` - is the committed DateTime - - ``message`` - is the first line of the commit message - - Returns - GitPython.Commit - """ - LazyMixin.__init__(self) - - self.repo = repo - self.id = None - self.tree = None - self.author = None - self.authored_date = None - self.committer = None - self.committed_date = None - self.message = None - self.parents = None - - for k, v in kwargs.items(): - setattr(self, k, v) - - if self.id: - if 'parents' in kwargs: - self.parents = map(lambda p: Commit(repo, **{'id': p}), kwargs['parents']) - if 'tree' in kwargs: - self.tree = tree.Tree(repo, **{'id': kwargs['tree']}) - - def __bake__(self): - temp = Commit.find_all(self.repo, self.id, **{'max_count': 1})[0] - self.parents = temp.parents - self.tree = temp.tree - self.author = temp.author - self.authored_date = temp.authored_date - self.committer = temp.committer - self.committed_date = temp.committed_date - self.message = temp.message - - @property - def id_abbrev(self): - return self.id[0:7] - - @classmethod - def count(cls, repo, ref): - """ - Count the number of commits reachable from this ref - - ``repo`` - is the Repo - - ``ref`` - is the ref from which to begin (SHA1 or name) - - Returns - int - """ - return len(repo.git.rev_list(ref).strip().splitlines()) - - @classmethod - def find_all(cls, repo, ref, **kwargs): - """ - Find all commits matching the given criteria. - ``repo`` - is the Repo - - ``ref`` - is the ref from which to begin (SHA1 or name) - - ``options`` - is a Hash of optional arguments to git where - ``max_count`` is the maximum number of commits to fetch - ``skip`` is the number of commits to skip - - Returns - GitPython.Commit[] - """ - options = {'pretty': 'raw'} - options.update(kwargs) - - output = repo.git.rev_list(ref, **options) - return cls.list_from_string(repo, output) - - @classmethod - def list_from_string(cls, repo, text): - """ - Parse out commit information into a list of Commit objects - - ``repo`` - is the Repo - - ``text`` - is the text output from the git command (raw format) - - Returns - GitPython.Commit[] - """ - lines = [l for l in text.splitlines() if l.strip()] - - commits = [] - - while lines: - id = lines.pop(0).split()[-1] - tree = lines.pop(0).split()[-1] - - parents = [] - while lines and re.search(r'^parent', lines[0]): - parents.append(lines.pop(0).split()[-1]) - author, authored_date = cls.actor(lines.pop(0)) - committer, committed_date = cls.actor(lines.pop(0)) - - messages = [] - while lines and re.search(r'^ {4}', lines[0]): - messages.append(lines.pop(0).strip()) - - message = messages and messages[0] or '' - - commits.append(Commit(repo, id=id, parents=parents, tree=tree, author=author, authored_date=authored_date, - committer=committer, committed_date=committed_date, message=message)) - - return commits - - @classmethod - def diff(cls, repo, a, b = None, paths = []): - """ - Show diffs between two trees: - - ``repo`` - is the Repo - - ``a`` - is a named commit - - ``b`` - is an optional named commit. Passing a list assumes you - wish to omit the second named commit and limit the diff to the - given paths. - - ``paths`` - is a list of paths to limit the diff. - - Returns - GitPython.Diff[] - """ - if isinstance(b, list): - paths = b - b = None - - if paths: - paths.insert(0, "--") - - if b: - paths.insert(0, b) - paths.insert(0, a) - text = repo.git.diff(*paths, **{'full_index': True}) - return diff.Diff.list_from_string(repo, text) - - @property - def diffs(self): - if not self.parents: - d = self.repo.git.show(self.id, **{'full_index': True, 'pretty': 'raw'}) - if re.search(r'diff --git a', d): - if not re.search(r'^diff --git a', d): - p = re.compile(r'.+?(diff --git a)', re.MULTILINE | re.DOTALL) - d = p.sub(r'diff --git a', d, 1) - else: - d = '' - return diff.Diff.list_from_string(self.repo, d) - else: - return self.diff(self.repo, self.parents[0].id, self.id) - - @property - def stats(self): - if not self.parents: - text = self.repo.git.diff(self.id, **{'numstat': True}) - text2 = "" - for line in text.splitlines(): - (insertions, deletions, filename) = line.split("\t") - text2 += "%s\t%s\t%s\n" % (deletions, insertions, filename) - text = text2 - else: - text = self.repo.git.diff(self.parents[0].id, self.id, **{'numstat': True}) - return stats.Stats.list_from_string(self.repo, text) - - def __str__(self): - """ Convert commit to string which is SHA1 """ - return self.id - - def __repr__(self): - return '<GitPython.Commit "%s">' % self.id - - @classmethod - def actor(cls, line): - """ - Parse out the actor (author or committer) info - - Returns - [str (actor name and email), time (acted at time)] - """ - m = re.search(r'^.+? (.*) (\d+) .*$', line) - actor, epoch = m.groups() - return [Actor.from_string(actor), time.gmtime(int(epoch))] diff --git a/lib/git_python/diff.py b/lib/git_python/diff.py deleted file mode 100644 index 075b0f87..00000000 --- a/lib/git_python/diff.py +++ /dev/null @@ -1,79 +0,0 @@ -import re -import commit - -class Diff(object): - """ - A Diff contains diff information between two commits. - """ - - def __init__(self, repo, a_path, b_path, a_commit, b_commit, a_mode, b_mode, new_file, deleted_file, diff): - self.repo = repo - self.a_path = a_path - self.b_path = b_path - - if not a_commit or re.search(r'^0{40}$', a_commit): - self.a_commit = None - else: - self.a_commit = commit.Commit(repo, **{'id': a_commit}) - if not b_commit or re.search(r'^0{40}$', b_commit): - self.b_commit = None - else: - self.b_commit = commit.Commit(repo, **{'id': b_commit}) - - self.a_mode = a_mode - self.b_mode = b_mode - self.new_file = new_file - self.deleted_file = deleted_file - self.diff = diff - - @classmethod - def list_from_string(cls, repo, text): - lines = text.splitlines() - a_mode = None - b_mode = None - diffs = [] - while lines: - m = re.search(r'^diff --git a/(\S+) b/(\S+)$', lines.pop(0)) - if m: - a_path, b_path = m.groups() - if re.search(r'^old mode', lines[0]): - m = re.search(r'^old mode (\d+)', lines.pop(0)) - if m: - a_mode, = m.groups() - m = re.search(r'^new mode (\d+)', lines.pop(0)) - if m: - b_mode, = m.groups() - if re.search(r'^diff --git', lines[0]): - diffs.append(Diff(repo, a_path, b_path, None, None, a_mode, b_mode, False, False, None)) - continue - - new_file = False - deleted_file = False - - if re.search(r'^new file', lines[0]): - m = re.search(r'^new file mode (.+)', lines.pop(0)) - if m: - b_mode, = m.groups() - a_mode = None - new_file = True - elif re.search(r'^deleted file', lines[0]): - m = re.search(r'^deleted file mode (.+)$', lines.pop(0)) - if m: - a_mode, = m.groups() - b_mode = None - deleted_file = True - - m = re.search(r'^index ([0-9A-Fa-f]+)\.\.([0-9A-Fa-f]+) ?(.+)?$', lines.pop(0)) - if m: - a_commit, b_commit, b_mode = m.groups() - if b_mode: - b_mode = b_mode.strip() - - diff_lines = [] - while lines and not re.search(r'^diff', lines[0]): - diff_lines.append(lines.pop(0)) - - diff = "\n".join(diff_lines) - diffs.append(Diff(repo, a_path, b_path, a_commit, b_commit, a_mode, b_mode, new_file, deleted_file, diff)) - - return diffs diff --git a/lib/git_python/errors.py b/lib/git_python/errors.py deleted file mode 100644 index f3fae26b..00000000 --- a/lib/git_python/errors.py +++ /dev/null @@ -1,8 +0,0 @@ -class InvalidGitRepositoryError(Exception): - pass - -class NoSuchPathError(Exception): - pass - -class GitCommandError(Exception): - pass diff --git a/lib/git_python/git.py b/lib/git_python/git.py deleted file mode 100644 index 759c9127..00000000 --- a/lib/git_python/git.py +++ /dev/null @@ -1,190 +0,0 @@ -import os -import subprocess -import re -from utils import * -from method_missing import MethodMissingMixin -from errors import GitCommandError - -# Enables debugging of GitPython's git commands -GIT_PYTHON_TRACE = os.environ.get("GIT_PYTHON_TRACE", False) - -class Git(MethodMissingMixin): - """ - The Git class manages communication with the Git binary - """ - def __init__(self, git_dir=None): - super(Git, self).__init__() - if git_dir: - self.find_git_dir( git_dir ) - else: - self.find_git_dir( os.getcwd() ) - - def find_git_dir(self, path): - """Find the best value for self.git_dir. - For bare repositories, this is the path to the bare repository. - For repositories with work trees, this is the work tree path. - - When barerepo.git is passed in, self.git_dir = barerepo.git - When worktree/.git is passed in, self.git_dir = worktree - When worktree is passed in, self.git_dir = worktree - """ - - path = os.path.abspath(path) - self.git_dir = path - - cdup = self.execute(["git", "rev-parse", "--show-cdup"]) - if cdup: - path = os.path.abspath( os.path.join( self.git_dir, cdup ) ) - else: - is_bare_repository =\ - self.rev_parse( is_bare_repository=True ) == "true" - is_inside_git_dir =\ - self.rev_parse( is_inside_git_dir=True ) == "true" - - if not is_bare_repository and is_inside_git_dir: - path = os.path.dirname( self.git_dir ) - - self.git_dir = path - - @property - def get_dir(self): - return self.git_dir - - def execute(self, command, - istream = None, - with_status = False, - with_stderr = False, - with_exceptions = False, - with_raw_output = False, - ): - """ - Handles executing the command on the shell and consumes and returns - the returned information (stdout) - - ``command`` - The command argument list to execute - - ``istream`` - Standard input filehandle passed to subprocess.Popen. - - ``with_status`` - Whether to return a (status, str) tuple. - - ``with_stderr`` - Whether to combine stderr into the output. - - ``with_exceptions`` - Whether to raise an exception when git returns a non-zero status. - - ``with_raw_output`` - Whether to avoid stripping off trailing whitespace. - - Returns - str(output) # with_status = False (Default) - tuple(int(status), str(output)) # with_status = True - """ - - if GIT_PYTHON_TRACE: - print command - - # Allow stderr to be merged into stdout when with_stderr is True. - # Otherwise, throw stderr away. - if with_stderr: - stderr = subprocess.STDOUT - else: - stderr = subprocess.PIPE - - # Start the process - proc = subprocess.Popen(command, - cwd = self.git_dir, - stdin = istream, - stderr = stderr, - stdout = subprocess.PIPE - ) - - # Wait for the process to return - stdout_value, err = proc.communicate() - proc.stdout.close() - if proc.stderr: - proc.stderr.close() - - # Strip off trailing whitespace by default - if not with_raw_output: - stdout_value = stdout_value.rstrip() - - # Grab the exit status - status = proc.poll() - if with_exceptions and status != 0: - raise GitCommandError("%s returned exit status %d" - % ( str(command), status )) - - # Allow access to the command's status code - if with_status: - return (status, stdout_value) - else: - return stdout_value - - def transform_kwargs(self, **kwargs): - """ - Transforms Python style kwargs into git command line options. - """ - args = [] - for k, v in kwargs.items(): - if len(k) == 1: - if v is True: - args.append("-%s" % k) - else: - args.append("-%s%s" % (k, v)) - else: - if v is True: - args.append("--%s" % dashify(k)) - else: - args.append("--%s=%s" % (dashify(k), v)) - return args - - def method_missing(self, method, *args, **kwargs): - """ - Run the given git command with the specified arguments and return - the result as a String - - ``method`` - is the command - - ``args`` - is the list of arguments - - ``kwargs`` - is a dict of keyword arguments. - This function accepts the same optional keyword arguments - as execute(). - - Examples - git.rev_list('master', max_count=10, header=True) - - Returns - Same as execute() - """ - - # Handle optional arguments prior to calling transform_kwargs - # otherwise these'll end up in args, which is bad. - istream = pop_key(kwargs, "istream") - with_status = pop_key(kwargs, "with_status") - with_stderr = pop_key(kwargs, "with_stderr") - with_exceptions = pop_key(kwargs, "with_exceptions") - with_raw_output = pop_key(kwargs, "with_raw_output") - - # Prepare the argument list - opt_args = self.transform_kwargs(**kwargs) - ext_args = map(str, args) - args = opt_args + ext_args - - call = ["git", dashify(method)] - call.extend(args) - - return self.execute(call, - istream = istream, - with_status = with_status, - with_stderr = with_stderr, - with_exceptions = with_exceptions, - with_raw_output = with_raw_output, - ) diff --git a/lib/git_python/head.py b/lib/git_python/head.py deleted file mode 100644 index 58191fd8..00000000 --- a/lib/git_python/head.py +++ /dev/null @@ -1,107 +0,0 @@ -import commit - -class Head(object): - """ - A Head is a named reference to a Commit. Every Head instance contains a name - and a Commit object. - - Examples:: - - >>> repo = Repo("/path/to/repo") - >>> head = repo.heads[0] - - >>> head.name - 'master' - - >>> head.commit - <GitPython.Commit "1c09f116cbc2cb4100fb6935bb162daa4723f455"> - - >>> head.commit.id - '1c09f116cbc2cb4100fb6935bb162daa4723f455' - """ - - def __init__(self, name, commit): - """ - Instantiate a new Head - - `name` - is the name of the head - - `commit` - is the Commit that the head points to - - Returns - GitPython.Head - """ - self.name = name - self.commit = commit - - @classmethod - def find_all(cls, repo, **kwargs): - """ - Find all Heads - - `repo` - is the Repo - - `kwargs` - is a dict of options - - Returns - GitPython.Head[] - """ - - options = {'sort': "committerdate", - 'format': "%(refname)%00%(objectname)"} - options.update(kwargs) - - output = repo.git.for_each_ref("refs/heads", **options) - return cls.list_from_string(repo, output) - - @classmethod - def list_from_string(cls, repo, text): - """ - Parse out head information into an array of baked head objects - - ``repo`` - is the Repo - ``text`` - is the text output from the git command - - Returns - GitPython.Head[] - """ - heads = [] - - for line in text.splitlines(): - heads.append(cls.from_string(repo, line)) - - return heads - - @classmethod - def from_string(cls, repo, line): - """ - Create a new Head instance from the given string. - - ``repo`` - is the Repo - - ``line`` - is the formatted head information - - Format - name: [a-zA-Z_/]+ - <null byte> - id: [0-9A-Fa-f]{40} - - Returns - GitPython.Head - """ - print line - full_name, ids = line.split("\x00") - name = full_name.split("/")[-1] - c = commit.Commit(repo, **{'id': ids}) - return Head(name, c) - - def __repr__(self): - return '<GitPython.Head "%s">' % self.name diff --git a/lib/git_python/lazy.py b/lib/git_python/lazy.py deleted file mode 100644 index 66e56c2b..00000000 --- a/lib/git_python/lazy.py +++ /dev/null @@ -1,26 +0,0 @@ -class LazyMixin(object): - lazy_properties = [] - - def __init__(self): - self.__baked__ = False - - def __getattribute__(self, attr): - val = object.__getattribute__(self, attr) - if val is not None: - return val - else: - self.__prebake__() - return object.__getattribute__(self, attr) - - def __bake__(self): - """ This method should be overridden in the derived class. """ - raise NotImplementedError(" '__bake__' method has not been implemented.") - - def __prebake__(self): - if self.__baked__: - return - self.__bake__() - self.__baked__ = True - - def __bake_it__(self): - self.__baked__ = True diff --git a/lib/git_python/method_missing.py b/lib/git_python/method_missing.py deleted file mode 100644 index 478ee1d3..00000000 --- a/lib/git_python/method_missing.py +++ /dev/null @@ -1,21 +0,0 @@ -class MethodMissingMixin(object): - """ - A Mixin' to implement the 'method_missing' Ruby-like protocol. - - This was `taken from a blog post <http://blog.iffy.us/?p=43>`_ - """ - def __getattribute__(self, attr): - try: - return object.__getattribute__(self, attr) - except: - class MethodMissing(object): - def __init__(self, wrapped, method): - self.__wrapped__ = wrapped - self.__method__ = method - def __call__(self, *args, **kwargs): - return self.__wrapped__.method_missing(self.__method__, *args, **kwargs) - return MethodMissing(self, attr) - - def method_missing(self, *args, **kwargs): - """ This method should be overridden in the derived class. """ - raise NotImplementedError(str(self.__wrapped__) + " 'method_missing' method has not been implemented.") diff --git a/lib/git_python/repo.py b/lib/git_python/repo.py deleted file mode 100644 index c71ae6fb..00000000 --- a/lib/git_python/repo.py +++ /dev/null @@ -1,435 +0,0 @@ -import os -import re -from errors import InvalidGitRepositoryError, NoSuchPathError -from utils import touch -from git import Git -from head import Head -from blob import Blob -from tag import Tag -from commit import Commit -from tree import Tree - -class Repo(object): - DAEMON_EXPORT_FILE = 'git-daemon-export-ok' - - def __init__(self, path): - """ - Create a new Repo instance - - ``path`` - is the path to either the root git directory or the bare git repo - - Examples:: - - repo = Repo("/Users/mtrier/Development/git-python") - repo = Repo("/Users/mtrier/Development/git-python.git") - - Returns - ``GitPython.Repo`` - """ - epath = os.path.abspath(path) - - if os.path.exists(os.path.join(epath, '.git')): - self.path = os.path.join(epath, '.git') - self.bare = False - elif os.path.exists(epath) and re.search('\.git$', epath): - self.path = epath - self.bare = True - elif os.path.exists(epath): - raise InvalidGitRepositoryError(epath) - else: - raise NoSuchPathError(epath) - self.git = Git(self.path) - - @property - def description(self): - """ - The project's description. Taken verbatim from GIT_REPO/description - - Returns - str - """ - try: - f = open(os.path.join(self.path, 'description')) - result = f.read() - return result.rstrip() - finally: - f.close() - - @property - def heads(self): - """ - A list of ``Head`` objects representing the branch heads in - this repo - - Returns - ``GitPython.Head[]`` - """ - return Head.find_all(self) - - # alias heads - branches = heads - - @property - def tags(self): - """ - A list of ``Tag`` objects that are available in this repo - - Returns - ``GitPython.Tag[]`` - """ - return Tag.find_all(self) - - def commits(self, start = 'master', max_count = 10, skip = 0): - """ - A list of Commit objects representing the history of a given ref/commit - - ``start`` - is the branch/commit name (default 'master') - - ``max_count`` - is the maximum number of commits to return (default 10) - - ``skip`` - is the number of commits to skip (default 0) - - Returns - ``GitPython.Commit[]`` - """ - options = {'max_count': max_count, - 'skip': skip} - - return Commit.find_all(self, start, **options) - - def commits_between(self, frm, to): - """ - The Commits objects that are reachable via ``to`` but not via ``frm`` - Commits are returned in chronological order. - - ``from`` - is the branch/commit name of the younger item - - ``to`` - is the branch/commit name of the older item - - Returns - ``GitPython.Commit[]`` - """ - return Commit.find_all(self, "%s..%s" % (frm, to)).reverse() - - def commits_since(self, start = 'master', since = '1970-01-01'): - """ - The Commits objects that are newer than the specified date. - Commits are returned in chronological order. - - ``start`` - is the branch/commit name (default 'master') - - ``since`` - is a string represeting a date/time - - Returns - ``GitPython.Commit[]`` - """ - options = {'since': since} - - return Commit.find_all(self, start, **options) - - def commit_count(self, start = 'master'): - """ - The number of commits reachable by the given branch/commit - - ``start`` - is the branch/commit name (default 'master') - - Returns - int - """ - return Commit.count(self, start) - - def commit(self, id): - """ - The Commit object for the specified id - - ``id`` - is the SHA1 identifier of the commit - - Returns - GitPython.Commit - """ - options = {'max_count': 1} - - commits = Commit.find_all(self, id, **options) - - if not commits: - raise ValueError, 'Invalid identifier %s' % id - return commits[0] - - def commit_deltas_from(self, other_repo, ref = 'master', other_ref = 'master'): - """ - Returns a list of commits that is in ``other_repo`` but not in self - - Returns - ``GitPython.Commit[]`` - """ - repo_refs = self.git.rev_list(ref).strip().splitlines() - other_repo_refs = other_repo.git.rev_list(other_ref).strip().splitlines() - - diff_refs = list(set(other_repo_refs) - set(repo_refs)) - return map(lambda ref: Commit.find_all(other_repo, ref, **{'max_count': 1}[0]), diff_refs) - - def tree(self, treeish = 'master', paths = []): - """ - The Tree object for the given treeish reference - - ``treeish`` - is the reference (default 'master') - ``paths`` - is an optional Array of directory paths to restrict the tree (default []) - - Examples:: - - repo.tree('master', ['lib/']) - - - Returns - ``GitPython.Tree`` - """ - return Tree.construct(self, treeish, paths) - - def blob(self, id): - """ - The Blob object for the given id - - ``id`` - is the SHA1 id of the blob - - Returns - ``GitPython.Blob`` - """ - return Blob(self, **{'id': id}) - - def log(self, commit = 'master', path = None, **kwargs): - """ - The commit log for a treeish - - Returns - ``GitPython.Commit[]`` - """ - options = {'pretty': 'raw'} - options.update(kwargs) - if path: - arg = [commit, '--', path] - else: - arg = [commit] - commits = self.git.log(*arg, **options) - return Commit.list_from_string(self, commits) - - def diff(self, a, b, *paths): - """ - The diff from commit ``a`` to commit ``b``, optionally restricted to the given file(s) - - ``a`` - is the base commit - ``b`` - is the other commit - - ``paths`` - is an optional list of file paths on which to restrict the diff - """ - return self.git.diff(a, b, '--', *paths) - - def commit_diff(self, commit): - """ - The commit diff for the given commit - ``commit`` is the commit name/id - - Returns - ``GitPython.Diff[]`` - """ - return Commit.diff(self, commit) - - @classmethod - def init_bare(self, path, mkdir=True, **kwargs): - """ - Initialize a bare git repository at the given path - - ``path`` - is the full path to the repo (traditionally ends with /<name>.git) - - ``mkdir`` - if specified will create the repository directory if it doesn't - already exists. Creates the directory with a mode=0755. - - ``kwargs`` - is any additional options to the git init command - - Examples:: - - GitPython.Repo.init_bare('/var/git/myrepo.git') - - Returns - ``GitPython.Repo`` (the newly created repo) - """ - split = os.path.split(path) - if split[-1] == '.git' or os.path.split(split[0])[-1] == '.git': - gitpath = path - else: - gitpath = os.path.join(path, '.git') - - if mkdir and not os.path.exists(gitpath): - os.makedirs(gitpath, 0755) - - git = Git(gitpath) - output = git.init(**kwargs) - return Repo(path) - create = init_bare - - def fork_bare(self, path, **kwargs): - """ - Fork a bare git repository from this repo - - ``path`` - is the full path of the new repo (traditionally ends with /<name>.git) - - ``options`` - is any additional options to the git clone command - - Returns - ``GitPython.Repo`` (the newly forked repo) - """ - options = {'bare': True} - options.update(kwargs) - self.git.clone(self.path, path, **options) - return Repo(path) - - def archive_tar(self, treeish = 'master', prefix = None): - """ - Archive the given treeish - - ``treeish`` - is the treeish name/id (default 'master') - - ``prefix`` - is the optional prefix - - Examples:: - - >>> repo.archive_tar - <String containing tar archive> - - >>> repo.archive_tar('a87ff14') - <String containing tar archive for commit a87ff14> - - >>> repo.archive_tar('master', 'myproject/') - <String containing tar archive and prefixed with 'myproject/'> - - Returns - str (containing tar archive) - """ - options = {} - if prefix: - options['prefix'] = prefix - return self.git.archive(treeish, **options) - - def archive_tar_gz(self, treeish = 'master', prefix = None): - """ - Archive and gzip the given treeish - - ``treeish`` - is the treeish name/id (default 'master') - - ``prefix`` - is the optional prefix - - Examples:: - - >>> repo.archive_tar_gz - <String containing tar.gz archive> - - >>> repo.archive_tar_gz('a87ff14') - <String containing tar.gz archive for commit a87ff14> - - >>> repo.archive_tar_gz('master', 'myproject/') - <String containing tar.gz archive and prefixed with 'myproject/'> - - Returns - str (containing tar.gz archive) - """ - kwargs = {} - if prefix: - kwargs['prefix'] = prefix - self.git.archive(treeish, "| gzip", **kwargs) - - def enable_daemon_serve(self): - """ - Enable git-daemon serving of this repository by writing the - git-daemon-export-ok file to its git directory - - Returns - None - """ - if self.bare: - touch(os.path.join(self.path, DAEMON_EXPORT_FILE)) - else: - touch(os.path.join(self.path, '.git', DAEMON_EXPORT_FILE)) - - def disable_daemon_serve(self): - """ - Disable git-daemon serving of this repository by ensuring there is no - git-daemon-export-ok file in its git directory - - Returns - None - """ - if self.bare: - return os.remove(os.path.join(self.path, DAEMON_EXPORT_FILE)) - else: - return os.remove(os.path.join(self.path, '.git', DAEMON_EXPORT_FILE)) - - def _get_alternates(self): - """ - The list of alternates for this repo - - Returns - list[str] (pathnames of alternates) - """ - alternates_path = os.path.join(self.path, *['objects', 'info', 'alternates']) - - if os.path.exists(alternates_path): - try: - f = open(alternates_path) - alts = f.read() - finally: - f.close() - return alts.strip().splitlines() - else: - return [] - - def _set_alternates(self, alts): - """ - Sets the alternates - - ``alts`` - is the Array of String paths representing the alternates - - Returns - None - """ - for alt in alts: - if not os.path.exists(alt): - raise NoSuchPathError("Could not set alternates. Alternate path %s must exist" % alt) - - if not alts: - os.remove(os.path.join(self.path, *['objects', 'info', 'alternates'])) - else: - try: - f = open(os.path.join(self.path, *['objects', 'info', 'alternates']), 'w') - f.write("\n".join(alts)) - finally: - f.close() - - alternates = property(_get_alternates, _set_alternates) - - def __repr__(self): - return '<GitPython.Repo "%s">' % self.path diff --git a/lib/git_python/stats.py b/lib/git_python/stats.py deleted file mode 100644 index 95dc875e..00000000 --- a/lib/git_python/stats.py +++ /dev/null @@ -1,17 +0,0 @@ -class Stats(object): - def __init__(self, repo, total, files): - self.repo = repo - self.total = total - self.files = files - - @classmethod - def list_from_string(cls, repo, text): - hsh = {'total': {'insertions': 0, 'deletions': 0, 'lines': 0, 'files': 0}, 'files': {}} - for line in text.splitlines(): - (insertions, deletions, filename) = line.split("\t") - hsh['total']['insertions'] += int(insertions) - hsh['total']['deletions'] += int(deletions) - hsh['total']['lines'] = (hsh['total']['deletions'] + hsh['total']['insertions']) - hsh['total']['files'] += 1 - hsh['files'][filename.strip()] = {'insertions': int(insertions), 'deletions': int(deletions)} - return Stats(repo, hsh['total'], hsh['files']) diff --git a/lib/git_python/tag.py b/lib/git_python/tag.py deleted file mode 100644 index fb119f76..00000000 --- a/lib/git_python/tag.py +++ /dev/null @@ -1,85 +0,0 @@ -from commit import Commit - -class Tag(object): - def __init__(self, name, commit): - """ - Instantiate a new Tag - - ``name`` - is the name of the head - - ``commit`` - is the Commit that the head points to - - Returns - ``GitPython.Tag`` - """ - self.name = name - self.commit = commit - - @classmethod - def find_all(cls, repo, **kwargs): - """ - Find all Tags - - ``repo`` - is the Repo - - ``kwargs`` - is a dict of options - - Returns - ``GitPython.Tag[]`` - """ - options = {'sort': "committerdate", - 'format': "%(refname)%00%(objectname)"} - options.update(**kwargs) - - output = repo.git.for_each_ref("refs/tags", **options) - return cls.list_from_string(repo, output) - - @classmethod - def list_from_string(cls, repo, text): - """ - Parse out tag information into an array of baked Tag objects - - ``repo`` - is the Repo - - ``text`` - is the text output from the git command - - Returns - ``GitPython.Tag[]`` - """ - tags = [] - for line in text.splitlines(): - tags.append(cls.from_string(repo, line)) - return tags - - @classmethod - def from_string(cls, repo, line): - """ - Create a new Tag instance from the given string. - - ``repo`` - is the Repo - - ``line`` - is the formatted tag information - - Format - name: [a-zA-Z_/]+ - <null byte> - id: [0-9A-Fa-f]{40} - - Returns - ``GitPython.Tag`` - """ - full_name, ids = line.split("\x00") - name = full_name.split("/")[-1] - commit = Commit(repo, **{'id': ids}) - return Tag(name, commit) - - def __repr__(self): - return '<GitPython.Tag "%s">' % self.name diff --git a/lib/git_python/tree.py b/lib/git_python/tree.py deleted file mode 100644 index 9c4dab1d..00000000 --- a/lib/git_python/tree.py +++ /dev/null @@ -1,89 +0,0 @@ -import os -from lazy import LazyMixin -import blob - -class Tree(LazyMixin): - def __init__(self, repo, **kwargs): - LazyMixin.__init__(self) - self.repo = repo - self.id = None - self.mode = None - self.name = None - self.contents = None - - for k, v in kwargs.items(): - setattr(self, k, v) - - def __bake__(self): - temp = Tree.construct(self.repo, self.id) - self.contents = temp.contents - - @classmethod - def construct(cls, repo, treeish, paths = []): - output = repo.git.ls_tree(treeish, *paths) - return Tree(repo, **{'id': treeish}).construct_initialize(repo, treeish, output) - - def construct_initialize(self, repo, id, text): - self.repo = repo - self.id = id - self.contents = [] - self.__baked__ = False - - for line in text.splitlines(): - self.contents.append(self.content_from_string(self.repo, line)) - - self.contents = [c for c in self.contents if c is not None] - - self.__bake_it__() - return self - - def content_from_string(self, repo, text): - """ - Parse a content item and create the appropriate object - - ``repo`` - is the Repo - - ``text`` - is the single line containing the items data in `git ls-tree` format - - Returns - ``GitPython.Blob`` or ``GitPython.Tree`` - """ - try: - mode, typ, id, name = text.expandtabs(1).split(" ", 4) - except: - return None - - if typ == "tree": - return Tree(repo, **{'id': id, 'mode': mode, 'name': name}) - elif typ == "blob": - return blob.Blob(repo, **{'id': id, 'mode': mode, 'name': name}) - elif typ == "commit": - return None - else: - raise(TypeError, "Invalid type: %s" % typ) - - def __div__(self, file): - """ - Find the named object in this tree's contents - - Examples:: - - >>> Repo('/path/to/python-git').tree/'lib' - <GitPython.Tree "6cc23ee138be09ff8c28b07162720018b244e95e"> - >>> Repo('/path/to/python-git').tree/'README.txt' - <GitPython.Blob "8b1e02c0fb554eed2ce2ef737a68bb369d7527df"> - - Returns - ``GitPython.Blob`` or ``GitPython.Tree`` or ``None`` if not found - """ - contents = [c for c in self.contents if c.name == file] - return contents and contents[0] or None - - @property - def basename(self): - os.path.basename(self.name) - - def __repr__(self): - return '<GitPython.Tree "%s">' % self.id diff --git a/lib/git_python/utils.py b/lib/git_python/utils.py deleted file mode 100644 index f367c3e2..00000000 --- a/lib/git_python/utils.py +++ /dev/null @@ -1,11 +0,0 @@ -def dashify(string): - return string.replace('_', '-') - -def touch(filename): - open(filename, "a").close() - -def pop_key(d, key): - value = d.get(key, None) - if key in d: - del d[key] - return value |