summaryrefslogtreecommitdiff
path: root/lib/git_python
diff options
context:
space:
mode:
Diffstat (limited to 'lib/git_python')
-rw-r--r--lib/git_python/__init__.py21
-rw-r--r--lib/git_python/actor.py33
-rw-r--r--lib/git_python/blob.py134
-rw-r--r--lib/git_python/commit.py235
-rw-r--r--lib/git_python/diff.py79
-rw-r--r--lib/git_python/errors.py8
-rw-r--r--lib/git_python/git.py190
-rw-r--r--lib/git_python/head.py107
-rw-r--r--lib/git_python/lazy.py26
-rw-r--r--lib/git_python/method_missing.py21
-rw-r--r--lib/git_python/repo.py435
-rw-r--r--lib/git_python/stats.py17
-rw-r--r--lib/git_python/tag.py85
-rw-r--r--lib/git_python/tree.py89
-rw-r--r--lib/git_python/utils.py11
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