Added jingo-minify and GitPython

This commit is contained in:
Fred Wenzel 2011-01-05 15:29:26 -08:00
Родитель a88a45646d
Коммит 50f7ed7ae3
34 изменённых файлов: 2303 добавлений и 0 удалений

3
.gitmodules поставляемый
Просмотреть файл

@ -13,3 +13,6 @@
[submodule "src/tower"]
path = src/tower
url = git://github.com/clouserw/tower.git
[submodule "src/jingo-minify"]
path = src/jingo-minify
url = git://github.com/jsocol/jingo-minify.git

Просмотреть файл

@ -0,0 +1,15 @@
GitPython was originally written by Michael Trier.
Contributors are:
-Michael Trier <mtrier _at_ gmail.com>
-Alan Briolat
-Florian Apolloner <florian _at_ apolloner.eu>
-David Aguilar <davvid _at_ gmail.com>
-Jelmer Vernooij <jelmer _at_ samba.org>
-Steve Frécinaux <code _at_ istique.net>
-Kai Lautaportti <kai _at_ lautaportti.fi>
-Paul Sowden <paul _at_ idontsmoke.co.uk>
-Sebastian Thiel http://www.linkedin.com/in/sebastianthiel
Portions derived from other open source works and are clearly marked.

188
packages/GitPython/CHANGES Normal file
Просмотреть файл

@ -0,0 +1,188 @@
=======
CHANGES
=======
0.1.7
=======
This is a bugfix release and the last of its kind in 0.1.X, as 0.2.X will receive
a major redesign that will change the API.
Bugfixes
--------
* Paths in Tree objects can now handle whitespace
* Blob.blame was returning incorrect results which has been fixed.
General
-------
* The test suite now supports Mock 0.5 and above. The transition between Mock 0.4
0.5 changed the API which required adjustments.
* Many small enhancements done to the method documentation
0.1.6
=====
General
-------
* Added in Sphinx documentation.
* Removed ambiguity between paths and treeishs. When calling commands that
accept treeish and path arguments and there is a path with the same name as
a treeish git cowardly refuses to pick one and asks for the command to use
the unambiguous syntax where '--' seperates the treeish from the paths.
* ``Repo.commits``, ``Repo.commits_between``, ``Reop.commits_since``,
``Repo.commit_count``, ``Repo.commit``, ``Commit.count`` and
``Commit.find_all`` all now optionally take a path argument which
constrains the lookup by path. This changes the order of the positional
arguments in ``Repo.commits`` and ``Repo.commits_since``.
Commit
------
* ``Commit.message`` now contains the full commit message (rather than just
the first line) and a new property ``Commit.summary`` contains the first
line of the commit message.
* Fixed a failure when trying to lookup the stats of a parentless commit from
a bare repo.
Diff
----
* The diff parser is now far faster and also addresses a bug where
sometimes b_mode was not set.
* Added support for parsing rename info to the diff parser. Addition of new
properties ``Diff.renamed``, ``Diff.rename_from``, and ``Diff.rename_to``.
Head
----
* Corrected problem where branches was only returning the last path component
instead of the entire path component following refs/heads/.
Repo
----
* Modified the gzip archive creation to use the python gzip module.
* Corrected ``commits_between`` always returning None instead of the reversed
list.
0.1.5
=====
General
-------
* upgraded to Mock 0.4 dependency.
* Replace GitPython with git in repr() outputs.
* Fixed packaging issue caused by ez_setup.py.
Blob
----
* No longer strip newlines from Blob data.
Commit
------
* Corrected problem with git-rev-list --bisect-all. See
http://groups.google.com/group/git-python/browse_thread/thread/aed1d5c4b31d5027
Repo
----
* Corrected problems with creating bare repositories.
* Repo.tree no longer accepts a path argument. Use:
>>> dict(k, o for k, o in tree.items() if k in paths)
* Made daemon export a property of Repo. Now you can do this:
>>> exported = repo.daemon_export
>>> repo.daemon_export = True
* Allows modifying the project description. Do this:
>>> repo.description = "Foo Bar"
>>> repo.description
'Foo Bar'
* Added a read-only property Repo.is_dirty which reflects the status of the
working directory.
* Added a read-only Repo.active_branch property which returns the name of the
currently active branch.
Tree
----
* Switched to using a dictionary for Tree contents since you will usually want
to access them by name and order is unimportant.
* Implemented a dictionary protocol for Tree objects. The following:
child = tree.contents['grit']
becomes:
child = tree['grit']
* Made Tree.content_from_string a static method.
0.1.4.1
=======
* removed ``method_missing`` stuff and replaced with a ``__getattr__``
override in ``Git``.
0.1.4
=====
* renamed ``git_python`` to ``git``. Be sure to delete all pyc files before
testing.
Commit
------
* Fixed problem with commit stats not working under all conditions.
Git
---
* Renamed module to cmd.
* Removed shell escaping completely.
* Added support for ``stderr``, ``stdin``, and ``with_status``.
* ``git_dir`` is now optional in the constructor for ``git.Git``. Git now
falls back to ``os.getcwd()`` when git_dir is not specified.
* add a ``with_exceptions`` keyword argument to git commands.
``GitCommandError`` is raised when the exit status is non-zero.
* add support for a ``GIT_PYTHON_TRACE`` environment variable.
``GIT_PYTHON_TRACE`` allows us to debug GitPython's usage of git through
the use of an environment variable.
Tree
----
* Fixed up problem where ``name`` doesn't exist on root of tree.
Repo
----
* Corrected problem with creating bare repo. Added ``Repo.create`` alias.
0.1.2
=====
Tree
----
* Corrected problem with ``Tree.__div__`` not working with zero length files.
Removed ``__len__`` override and replaced with size instead. Also made size
cach properly. This is a breaking change.
0.1.1
=====
Fixed up some urls because I'm a moron
0.1.0
=====
initial release

Просмотреть файл

@ -0,0 +1,30 @@
Copyright (C) 2008-2010 Michael Trier and contributors
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of the GitPython project nor the names of
its contributors may be used to endorse or promote products derived
from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Просмотреть файл

@ -0,0 +1,5 @@
include VERSION
include LICENSE
include CHANGES
include AUTHORS
include README

Просмотреть файл

@ -0,0 +1,26 @@
Metadata-Version: 1.0
Name: GitPython
Version: 0.1.7
Summary: Python Git Library
Home-page: http://gitorious.org/projects/git-python/
Author: Michael Trier
Author-email: mtrier@gmail.com
License: BSD License
Description: GitPython is a python library used to interact with Git repositories.
GitPython provides object model access to your git repository. Once you have
created a repository object, you can traverse it to find parent commit(s),
trees, blobs, etc.
GitPython is a port of the grit library in Ruby created by
Tom Preston-Werner and Chris Wanstrath.
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.5
Classifier: Programming Language :: Python :: 2.6
Classifier: Topic :: Software Development :: Libraries :: Python Modules

42
packages/GitPython/README Normal file
Просмотреть файл

@ -0,0 +1,42 @@
==========
GitPython
==========
GitPython is a python library used to interact with Git repositories.
GitPython is a port of the grit_ library in Ruby created by
Tom Preston-Werner and Chris Wanstrath.
.. _grit: http://grit.rubyforge.org
REQUIREMENTS
============
* Git_ tested with 1.5.3.7
* `Python Nose`_ - used for running the tests
* `Mock by Michael Foord`_ used for tests. Requires 0.4
.. _Git: http://git.or.cz/
.. _Python Nose: http://code.google.com/p/python-nose/
.. _Mock by Michael Foord: http://www.voidspace.org.uk/python/mock.html
INSTALL
=======
python setup.py install
SOURCE
======
GitPython's git repo is available on Gitorious, which can be browsed at:
http://gitorious.org/projects/git-python/
and cloned from:
git://gitorious.org/git-python/mainline.git
LICENSE
=======
New BSD License. See the LICENSE file.

Просмотреть файл

@ -0,0 +1 @@
0.1.7

Просмотреть файл

@ -0,0 +1,26 @@
Metadata-Version: 1.0
Name: GitPython
Version: 0.1.7
Summary: Python Git Library
Home-page: http://gitorious.org/projects/git-python/
Author: Michael Trier
Author-email: mtrier@gmail.com
License: BSD License
Description: GitPython is a python library used to interact with Git repositories.
GitPython provides object model access to your git repository. Once you have
created a repository object, you can traverse it to find parent commit(s),
trees, blobs, etc.
GitPython is a port of the grit library in Ruby created by
Tom Preston-Werner and Chris Wanstrath.
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.5
Classifier: Programming Language :: Python :: 2.6
Classifier: Topic :: Software Development :: Libraries :: Python Modules

Просмотреть файл

@ -0,0 +1,25 @@
AUTHORS
CHANGES
LICENSE
MANIFEST.in
README
VERSION
setup.py
lib/GitPython.egg-info/PKG-INFO
lib/GitPython.egg-info/SOURCES.txt
lib/GitPython.egg-info/dependency_links.txt
lib/GitPython.egg-info/top_level.txt
lib/git/__init__.py
lib/git/actor.py
lib/git/blob.py
lib/git/cmd.py
lib/git/commit.py
lib/git/diff.py
lib/git/errors.py
lib/git/head.py
lib/git/lazy.py
lib/git/repo.py
lib/git/stats.py
lib/git/tag.py
lib/git/tree.py
lib/git/utils.py

Просмотреть файл

@ -0,0 +1 @@

Просмотреть файл

@ -0,0 +1 @@
git

Просмотреть файл

@ -0,0 +1,27 @@
# __init__.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import os
import inspect
__version__ = '0.1.7'
from git.actor import Actor
from git.blob import Blob
from git.commit import Commit
from git.diff import Diff
from git.errors import InvalidGitRepositoryError, NoSuchPathError, GitCommandError
from git.cmd import Git
from git.head import Head
from git.repo import Repo
from git.stats import Stats
from git.tag import Tag
from git.tree import Tree
from git.utils import dashify
from git.utils import touch
__all__ = [ name for name, obj in locals().items()
if not (name.startswith('_') or inspect.ismodule(obj)) ]

Просмотреть файл

@ -0,0 +1,42 @@
# actor.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import re
class Actor(object):
"""Actors hold information about a person acting on the repository. They
can be committers and authors or anything with a name and an email as
mentioned in the git log entries."""
def __init__(self, name, email):
self.name = name
self.email = email
def __str__(self):
return self.name
def __repr__(self):
return '<git.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)

Просмотреть файл

@ -0,0 +1,161 @@
# blob.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import mimetypes
import os
import re
import time
from actor import Actor
from commit import Commit
class Blob(object):
"""A Blob encapsulates a git blob object"""
DEFAULT_MIME_TYPE = "text/plain"
def __init__(self, repo, id, mode=None, name=None):
"""
Create an unbaked Blob containing just the specified attributes
``repo``
is the Repo
``id``
is the git object id
``mode``
is the file mode
``name``
is the file name
Returns
git.Blob
"""
self.repo = repo
self.id = id
self.mode = mode
self.name = name
self._size = None
self.data_stored = None
@property
def size(self):
"""
The size of this blob in bytes
Returns
int
NOTE
The size will be cached after the first access
"""
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
NOTE
The data will be cached after the first access.
"""
self.data_stored = self.data_stored or self.repo.git.cat_file(self.id, p=True, with_raw_output=True)
return self.data_stored
@property
def mime_type(self):
"""
The mime type of this file (based on the filename)
Returns
str
NOTE
Defaults to 'text/plain' in case the actual file type is unknown.
"""
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):
"""
Returns
The basename of the Blobs file name
"""
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: [git.Commit, list: [<line>]]
A list of tuples associating a Commit object with a list of lines that
changed within the given commit. The Commit objects will be given in order
of appearance.
"""
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].append( text )
info = None
return blames
def __repr__(self):
return '<git.Blob "%s">' % self.id

Просмотреть файл

@ -0,0 +1,221 @@
# cmd.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import os, sys
import subprocess
import re
from utils import *
from errors import GitCommandError
# Enables debugging of GitPython's git commands
GIT_PYTHON_TRACE = os.environ.get("GIT_PYTHON_TRACE", False)
execute_kwargs = ('istream', 'with_keep_cwd', 'with_extended_output',
'with_exceptions', 'with_raw_output')
extra = {}
if sys.platform == 'win32':
extra = {'shell': True}
class Git(object):
"""
The Git class manages communication with the Git binary.
It provides a convenient interface to calling the Git binary, such as in::
g = Git( git_dir )
g.init() # calls 'git init' program
rval = g.ls_files() # calls 'git ls-files' program
``Debugging``
Set the GIT_PYTHON_TRACE environment variable print each invocation
of the command to stdout.
Set its value to 'full' to see details about the returned values.
"""
def __init__(self, git_dir=None):
"""
Initialize this instance with:
``git_dir``
Git directory we should work in. If None, we always work in the current
directory as returned by os.getcwd()
"""
super(Git, self).__init__()
self.git_dir = git_dir
def __getattr__(self, name):
"""
A convenience method as it allows to call the command as if it was
an object.
Returns
Callable object that will execute call _call_process with your arguments.
"""
if name[:1] == '_':
raise AttributeError(name)
return lambda *args, **kwargs: self._call_process(name, *args, **kwargs)
@property
def get_dir(self):
"""
Returns
Git directory we are working on
"""
return self.git_dir
def execute(self, command,
istream=None,
with_keep_cwd=False,
with_extended_output=False,
with_exceptions=True,
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.
It should be a string, or a sequence of program arguments. The
program to execute is the first item in the args sequence or string.
``istream``
Standard input filehandle passed to subprocess.Popen.
``with_keep_cwd``
Whether to use the current working directory from os.getcwd().
GitPython uses get_work_tree() as its working directory by
default and get_git_dir() for bare repositories.
``with_extended_output``
Whether to return a (status, stdout, stderr) tuple.
``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) # extended_output = False (Default)
tuple(int(status), str(stdout), str(stderr)) # extended_output = True
Raise
GitCommandError
NOTE
If you add additional keyword arguments to the signature of this method,
you must update the execute_kwargs tuple housed in this module.
"""
if GIT_PYTHON_TRACE and not GIT_PYTHON_TRACE == 'full':
print ' '.join(command)
# Allow the user to have the command executed in their working dir.
if with_keep_cwd or self.git_dir is None:
cwd = os.getcwd()
else:
cwd=self.git_dir
# Start the process
proc = subprocess.Popen(command,
cwd=cwd,
stdin=istream,
stderr=subprocess.PIPE,
stdout=subprocess.PIPE,
**extra
)
# Wait for the process to return
try:
stdout_value = proc.stdout.read()
stderr_value = proc.stderr.read()
status = proc.wait()
finally:
proc.stdout.close()
proc.stderr.close()
# Strip off trailing whitespace by default
if not with_raw_output:
stdout_value = stdout_value.rstrip()
stderr_value = stderr_value.rstrip()
if with_exceptions and status != 0:
raise GitCommandError(command, status, stderr_value)
if GIT_PYTHON_TRACE == 'full':
if stderr_value:
print "%s -> %d: '%s' !! '%s'" % (command, status, stdout_value, stderr_value)
elif stdout_value:
print "%s -> %d: '%s'" % (command, status, stdout_value)
else:
print "%s -> %d" % (command, status)
# Allow access to the command's status code
if with_extended_output:
return (status, stdout_value, stderr_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)
elif type(v) is not bool:
args.append("-%s%s" % (k, v))
else:
if v is True:
args.append("--%s" % dashify(k))
elif type(v) is not bool:
args.append("--%s=%s" % (dashify(k), v))
return args
def _call_process(self, method, *args, **kwargs):
"""
Run the given git command with the specified arguments and return
the result as a String
``method``
is the command. Contained "_" characters will be converted to dashes,
such as in 'ls_files' to call 'ls-files'.
``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.
_kwargs = {}
for kwarg in execute_kwargs:
try:
_kwargs[kwarg] = kwargs.pop(kwarg)
except KeyError:
pass
# 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, **_kwargs)

Просмотреть файл

@ -0,0 +1,289 @@
# commit.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import re
import time
from actor import Actor
from lazy import LazyMixin
from tree import Tree
import diff
import stats
class Commit(LazyMixin):
"""
Wraps a git Commit object.
This class will act lazily on some of its attributes and will query the
value on demand only if it involves calling the git binary.
"""
def __init__(self, repo, id, tree=None, author=None, authored_date=None,
committer=None, committed_date=None, message=None, parents=None):
"""
Instantiate a new Commit. All keyword arguments taking None as default will
be implicitly set if id names a valid sha.
The parameter documentation indicates the type of the argument after a colon ':'.
``id``
is the sha id of the commit
``parents`` : list( Commit, ... )
is a list of commit ids
``tree`` : Tree
is the corresponding tree id
``author`` : Actor
is the author string ( will be implicitly converted into an Actor object )
``authored_date`` : (tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst )
is the authored DateTime
``committer`` : Actor
is the committer string
``committed_date`` : (tm_year, tm_mon, tm_mday, tm_hour, tm_min, tm_sec, tm_wday, tm_yday, tm_isdst)
is the committed DateTime
``message`` : string
is the commit message
Returns
git.Commit
"""
LazyMixin.__init__(self)
self.repo = repo
self.id = id
self.parents = None
self.tree = None
self.author = author
self.authored_date = authored_date
self.committer = committer
self.committed_date = committed_date
self.message = message
if self.id:
if parents is not None:
self.parents = [Commit(repo, p) for p in parents]
if tree is not None:
self.tree = Tree(repo, id=tree)
def __bake__(self):
"""
Called by LazyMixin superclass when the first uninitialized member needs
to be set as it is queried.
"""
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):
"""
Returns
First 7 bytes of the commit's sha id as an abbreviation of the full string.
"""
return self.id[0:7]
@property
def summary(self):
"""
Returns
First line of the commit message.
"""
return self.message.split('\n', 1)[0]
@classmethod
def count(cls, repo, ref, path=''):
"""
Count the number of commits reachable from this ref
``repo``
is the Repo
``ref``
is the ref from which to begin (SHA1 or name)
``path``
is an optional path
Returns
int
"""
return len(repo.git.rev_list(ref, '--', path).strip().splitlines())
@classmethod
def find_all(cls, repo, ref, path='', **kwargs):
"""
Find all commits matching the given criteria.
``repo``
is the Repo
``ref``
is the ref from which to begin (SHA1 or name)
``path``
is an optinal path, if set only Commits that include the path
will be considered
``kwargs``
optional keyword arguments to git where
``max_count`` is the maximum number of commits to fetch
``skip`` is the number of commits to skip
Returns
git.Commit[]
"""
options = {'pretty': 'raw'}
options.update(kwargs)
output = repo.git.rev_list(ref, '--', path, **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-rev-list command (raw format)
Returns
git.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 lines[0].startswith('parent'):
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 lines[0].startswith(' '):
messages.append(lines.pop(0).strip())
message = '\n'.join(messages)
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=None):
"""
Creates diffs between a tree and the index or 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 to.
Returns
git.Diff[]::
between tree and the index if only a is given
between two trees if a and b are given and are commits
"""
paths = paths or []
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('-M', full_index=True, *paths)
return diff.Diff.list_from_string(repo, text)
@property
def diffs(self):
"""
Returns
git.Diff[]
Diffs between this commit and its first parent or all changes if this
commit is the first commit and has no parent.
"""
if not self.parents:
d = self.repo.git.show(self.id, '-M', 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):
"""
Create a git stat from changes between this commit and its first parent
or from all changes done if this is the very first commit.
Return
git.Stats
"""
if not self.parents:
text = self.repo.git.diff_tree(self.id, '--', numstat=True, root=True)
text2 = ""
for line in text.splitlines()[1:]:
(insertions, deletions, filename) = line.split("\t")
text2 += "%s\t%s\t%s\n" % (insertions, deletions, 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 '<git.Commit "%s">' % self.id
@classmethod
def actor(cls, line):
"""
Parse out the actor (author or committer) info
Returns
[Actor, gmtime(acted at time)]
"""
m = re.search(r'^.+? (.*) (\d+) .*$', line)
actor, epoch = m.groups()
return [Actor.from_string(actor), time.gmtime(int(epoch))]

Просмотреть файл

@ -0,0 +1,71 @@
# diff.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
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, rename_from,
rename_to, 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.rename_from = rename_from
self.rename_to = rename_to
self.renamed = rename_from != rename_to
self.diff = diff
@classmethod
def list_from_string(cls, repo, text):
diffs = []
diff_header = re.compile(r"""
#^diff[ ]--git
[ ]a/(?P<a_path>\S+)[ ]b/(?P<b_path>\S+)\n
(?:^similarity[ ]index[ ](?P<similarity_index>\d+)%\n
^rename[ ]from[ ](?P<rename_from>\S+)\n
^rename[ ]to[ ](?P<rename_to>\S+)(?:\n|$))?
(?:^old[ ]mode[ ](?P<old_mode>\d+)\n
^new[ ]mode[ ](?P<new_mode>\d+)(?:\n|$))?
(?:^new[ ]file[ ]mode[ ](?P<new_file_mode>.+)(?:\n|$))?
(?:^deleted[ ]file[ ]mode[ ](?P<deleted_file_mode>.+)(?:\n|$))?
(?:^index[ ](?P<a_commit>[0-9A-Fa-f]+)
\.\.(?P<b_commit>[0-9A-Fa-f]+)[ ]?(?P<b_mode>.+)?(?:\n|$))?
""", re.VERBOSE | re.MULTILINE).match
for diff in ('\n' + text).split('\ndiff --git')[1:]:
header = diff_header(diff)
a_path, b_path, similarity_index, rename_from, rename_to, \
old_mode, new_mode, new_file_mode, deleted_file_mode, \
a_commit, b_commit, b_mode = header.groups()
new_file, deleted_file = bool(new_file_mode), bool(deleted_file_mode)
diffs.append(Diff(repo, a_path, b_path, a_commit, b_commit,
old_mode or deleted_file_mode, new_mode or new_file_mode or b_mode,
new_file, deleted_file, rename_from, rename_to, diff[header.end():]))
return diffs

Просмотреть файл

@ -0,0 +1,32 @@
# errors.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
"""
Module containing all exceptions thrown througout the git package,
"""
class InvalidGitRepositoryError(Exception):
"""
Thrown if the given repository appears to have an invalid format.
"""
class NoSuchPathError(Exception):
"""
Thrown if a path could not be access by the system.
"""
class GitCommandError(Exception):
"""
Thrown if execution of the git command fails with non-zero status code.
"""
def __init__(self, command, status, stderr=None):
self.stderr = stderr
self.status = status
self.command = command
def __str__(self):
return repr("%s returned exit status %d" %
(str(self.command), self.status))

Просмотреть файл

@ -0,0 +1,118 @@
# head.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
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
<git.Commit "1c09f116cbc2cb4100fb6935bb162daa4723f455">
>>> head.commit.id
'1c09f116cbc2cb4100fb6935bb162daa4723f455'
"""
def __init__(self, name, commit):
"""
Initialize a newly instanced Head
`name`
is the name of the head
`commit`
is the Commit object that the head points to
"""
self.name = name
self.commit = commit
@classmethod
def find_all(cls, repo, **kwargs):
"""
Find all Heads in the repository
`repo`
is the Repo
`kwargs`
Additional options given as keyword arguments, will be passed
to git-for-each-ref
Returns
git.Head[]
List is sorted by committerdate
"""
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 a list of head objects
``repo``
is the Repo
``text``
is the text output from the git-for-each-ref command
Returns
git.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
git.Head
"""
full_name, ids = line.split("\x00")
if full_name.startswith('refs/heads/'):
name = full_name[len('refs/heads/'):]
else:
name = full_name
c = commit.Commit(repo, id=ids)
return Head(name, c)
def __repr__(self):
return '<git.Head "%s">' % self.name

Просмотреть файл

@ -0,0 +1,32 @@
# lazy.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
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

Просмотреть файл

@ -0,0 +1,517 @@
# repo.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import os
import re
import gzip
import StringIO
from errors import InvalidGitRepositoryError, NoSuchPathError
from utils import touch, is_git_dir
from cmd 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):
"""
Represents a git repository and allows you to query references,
gather commit information, generate diffs, create and clone repositories query
the log.
"""
DAEMON_EXPORT_FILE = 'git-daemon-export-ok'
def __init__(self, path=None):
"""
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")
Raises
InvalidGitRepositoryError or NoSuchPathError
Returns
``git.Repo``
"""
epath = os.path.abspath(os.path.expanduser(path or os.getcwd()))
if not os.path.exists(epath):
raise NoSuchPathError(epath)
self.path = None
curpath = epath
while curpath:
if is_git_dir(curpath):
self.bare = True
self.path = curpath
self.wd = curpath
break
gitpath = os.path.join(curpath, '.git')
if is_git_dir(gitpath):
self.bare = False
self.path = gitpath
self.wd = curpath
break
curpath, dummy = os.path.split(curpath)
if not dummy:
break
if self.path is None:
raise InvalidGitRepositoryError(epath)
self.git = Git(self.wd)
# Description property
def _get_description(self):
filename = os.path.join(self.path, 'description')
return file(filename).read().rstrip()
def _set_description(self, descr):
filename = os.path.join(self.path, 'description')
file(filename, 'w').write(descr+'\n')
description = property(_get_description, _set_description,
doc="the project's description")
del _get_description
del _set_description
@property
def heads(self):
"""
A list of ``Head`` objects representing the branch heads in
this repo
Returns
``git.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
``git.Tag[]``
"""
return Tag.find_all(self)
def commits(self, start='master', path='', 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')
``path``
is an optional path to limit the returned commits to
Commits that do not contain that path will not be returned.
``max_count``
is the maximum number of commits to return (default 10)
``skip``
is the number of commits to skip (default 0) which will effectively
move your commit-window by the given number.
Returns
``git.Commit[]``
"""
options = {'max_count': max_count,
'skip': skip}
return Commit.find_all(self, start, path, **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
``git.Commit[]``
"""
return reversed(Commit.find_all(self, "%s..%s" % (frm, to)))
def commits_since(self, start='master', path='', 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')
``path``
is an optional path to limit the returned commits to.
``since``
is a string representing a date/time
Returns
``git.Commit[]``
"""
options = {'since': since}
return Commit.find_all(self, start, path, **options)
def commit_count(self, start='master', path=''):
"""
The number of commits reachable by the given branch/commit
``start``
is the branch/commit name (default 'master')
``path``
is an optional path
Commits that do not contain the path will not contribute to the count.
Returns
``int``
"""
return Commit.count(self, start, path)
def commit(self, id, path = ''):
"""
The Commit object for the specified id
``id``
is the SHA1 identifier of the commit
``path``
is an optional path, if set the returned commit must contain the path.
Returns
``git.Commit``
"""
options = {'max_count': 1}
commits = Commit.find_all(self, id, path, **options)
if not commits:
raise ValueError, "Invalid identifier %s, or given path '%s' too restrictive" % ( id, path )
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
git.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'):
"""
The Tree object for the given treeish reference
``treeish``
is the reference (default 'master')
Examples::
repo.tree('master')
Returns
``git.Tree``
"""
return Tree(self, id=treeish)
def blob(self, id):
"""
The Blob object for the given id
``id``
is the SHA1 id of the blob
Returns
``git.Blob``
"""
return Blob(self, id=id)
def log(self, commit='master', path=None, **kwargs):
"""
The Commit for a treeish, and all commits leading to it.
``kwargs``
keyword arguments specifying flags to be used in git-log command,
i.e.: max_count=1 to limit the amount of commits returned
Returns
``git.Commit[]``
"""
options = {'pretty': 'raw'}
options.update(kwargs)
arg = [commit, '--']
if path:
arg.append(path)
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
Returns
``str``
"""
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
``git.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``
keyword arguments serving as additional options to the git init command
Examples::
git.Repo.init_bare('/var/git/myrepo.git')
Returns
``git.Repo`` (the newly created repo)
"""
if mkdir and not os.path.exists(path):
os.makedirs(path, 0755)
git = Git(path)
output = git.init('--bare', **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)
``kwargs``
keyword arguments to be given to the git clone command
Returns
``git.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 to prepend to each filename in the archive
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 bytes archive, whose files are prefixed with 'myproject/'>
Returns
str (containing bytes of 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 to prepend to each filename in the archive
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 the bytes of tar.gz archive)
"""
kwargs = {}
if prefix:
kwargs['prefix'] = prefix
resultstr = self.git.archive(treeish, **kwargs)
sio = StringIO.StringIO()
gf = gzip.GzipFile(fileobj=sio, mode ='wb')
gf.write(resultstr)
gf.close()
return sio.getvalue()
def _get_daemon_export(self):
filename = os.path.join(self.path, self.DAEMON_EXPORT_FILE)
return os.path.exists(filename)
def _set_daemon_export(self, value):
filename = os.path.join(self.path, self.DAEMON_EXPORT_FILE)
fileexists = os.path.exists(filename)
if value and not fileexists:
touch(filename)
elif not value and fileexists:
os.unlink(filename)
daemon_export = property(_get_daemon_export, _set_daemon_export,
doc="If True, git-daemon may export this repository")
del _get_daemon_export
del _set_daemon_export
def _get_alternates(self):
"""
The list of alternates for this repo from which objects can be retrieved
Returns
list of strings being 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 at which
git should look for objects, i.e. /home/user/repo/.git/objects
Raises
NoSuchPathError
Note
The method does not check for the existance of the paths in alts
as the caller is responsible.
Returns
None
"""
alternates_path = os.path.join(self.path, 'objects', 'info', 'alternates')
if not alts:
if os.path.isfile(alternates_path):
os.remove(alternates_path)
else:
try:
f = open(alternates_path, 'w')
f.write("\n".join(alts))
finally:
f.close()
# END file handling
# END alts handling
alternates = property(_get_alternates, _set_alternates, doc="Retrieve a list of alternates paths or set a list paths to be used as alternates")
@property
def is_dirty(self):
"""
Return the status of the index.
Returns
``True``, if the index has any uncommitted changes,
otherwise ``False``
NOTE
Working tree changes that have not been staged will not be detected !
"""
if self.bare:
# Bare repositories with no associated working directory are
# always considered to be clean.
return False
return len(self.git.diff('HEAD', '--').strip()) > 0
@property
def active_branch(self):
"""
The name of the currently active branch.
Returns
str (the branch name)
"""
branch = self.git.symbolic_ref('HEAD').strip()
if branch.startswith('refs/heads/'):
branch = branch[len('refs/heads/'):]
return branch
def __repr__(self):
return '<git.Repo "%s">' % self.path

Просмотреть файл

@ -0,0 +1,59 @@
# stats.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
class Stats(object):
"""
Represents stat information as presented by git at the end of a merge. It is
created from the output of a diff operation.
``Example``::
c = Commit( sha1 )
s = c.stats
s.total # full-stat-dict
s.files # dict( filepath : stat-dict )
``stat-dict``
A dictionary with the following keys and values::
deletions = number of deleted lines as int
insertions = number of inserted lines as int
lines = total number of lines changed as int, or deletions + insertions
``full-stat-dict``
In addition to the items in the stat-dict, it features additional information::
files = number of changed files as int
"""
def __init__(self, repo, total, files):
self.repo = repo
self.total = total
self.files = files
@classmethod
def list_from_string(cls, repo, text):
"""
Create a Stat object from output retrieved by git-diff.
Returns
git.Stat
"""
hsh = {'total': {'insertions': 0, 'deletions': 0, 'lines': 0, 'files': 0}, 'files': {}}
for line in text.splitlines():
(raw_insertions, raw_deletions, filename) = line.split("\t")
insertions = raw_insertions != '-' and int(raw_insertions) or 0
deletions = raw_deletions != '-' and int(raw_deletions) or 0
hsh['total']['insertions'] += insertions
hsh['total']['deletions'] += deletions
hsh['total']['lines'] += insertions + deletions
hsh['total']['files'] += 1
hsh['files'][filename.strip()] = {'insertions': insertions,
'deletions': deletions,
'lines': insertions + deletions}
return Stats(repo, hsh['total'], hsh['files'])

Просмотреть файл

@ -0,0 +1,92 @@
# tag.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
from commit import Commit
class Tag(object):
def __init__(self, name, commit):
"""
Initialize a newly instantiated Tag
``name``
is the name of the head
``commit``
is the Commit that the head points to
"""
self.name = name
self.commit = commit
@classmethod
def find_all(cls, repo, **kwargs):
"""
Find all Tags in the repository
``repo``
is the Repo
``kwargs``
Additional options given as keyword arguments, will be passed
to git-for-each-ref
Returns
``git.Tag[]``
List is sorted by committerdate
"""
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 Tag objects
``repo``
is the Repo
``text``
is the text output from the git-for-each command
Returns
git.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
git.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 '<git.Tag "%s">' % self.name

Просмотреть файл

@ -0,0 +1,108 @@
# tree.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import os
from lazy import LazyMixin
import blob
class Tree(LazyMixin):
def __init__(self, repo, id, mode=None, name=None):
LazyMixin.__init__(self)
self.repo = repo
self.id = id
self.mode = mode
self.name = name
self._contents = None
def __bake__(self):
# Ensure the treeish references directly a tree
treeish = self.id
if not treeish.endswith(':'):
treeish = treeish + ':'
# Read the tree contents.
self._contents = {}
for line in self.repo.git.ls_tree(self.id).splitlines():
obj = self.content_from_string(self.repo, line)
if obj is not None:
self._contents[obj.name] = obj
@staticmethod
def content_from_string(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
``git.Blob`` or ``git.Tree``
"""
try:
mode, typ, id, name = text.expandtabs(1).split(" ", 3)
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'
<git.Tree "6cc23ee138be09ff8c28b07162720018b244e95e">
>>> Repo('/path/to/python-git').tree()/'README'
<git.Blob "8b1e02c0fb554eed2ce2ef737a68bb369d7527df">
Returns
``git.Blob`` or ``git.Tree`` or ``None`` if not found
"""
return self.get(file)
@property
def basename(self):
os.path.basename(self.name)
def __repr__(self):
return '<git.Tree "%s">' % self.id
# Implement the basics of the dict protocol:
# directories/trees can be seen as object dicts.
def __getitem__(self, key):
return self._contents[key]
def __iter__(self):
return iter(self._contents)
def __len__(self):
return len(self._contents)
def __contains__(self, key):
return key in self._contents
def get(self, key):
return self._contents.get(key)
def items(self):
return self._contents.items()
def keys(self):
return self._contents.keys()
def values(self):
return self._contents.values()

Просмотреть файл

@ -0,0 +1,27 @@
# utils.py
# Copyright (C) 2008-2010 Michael Trier (mtrier@gmail.com) and contributors
#
# This module is part of GitPython and is released under
# the BSD License: http://www.opensource.org/licenses/bsd-license.php
import os
def dashify(string):
return string.replace('_', '-')
def touch(filename):
fp = open(filename, 'a')
fp.close()
def is_git_dir(d):
""" This is taken from the git setup.c:is_git_directory
function."""
if os.path.isdir(d) and \
os.path.isdir(os.path.join(d, 'objects')) and \
os.path.isdir(os.path.join(d, 'refs')):
headref = os.path.join(d, 'HEAD')
return os.path.isfile(headref) or \
(os.path.islink(headref) and
os.readlink(headref).startswith('refs'))
return False

Просмотреть файл

@ -0,0 +1,26 @@
Metadata-Version: 1.0
Name: GitPython
Version: 0.1.7
Summary: Python Git Library
Home-page: http://gitorious.org/projects/git-python/
Author: Michael Trier
Author-email: mtrier@gmail.com
License: BSD License
Description: GitPython is a python library used to interact with Git repositories.
GitPython provides object model access to your git repository. Once you have
created a repository object, you can traverse it to find parent commit(s),
trees, blobs, etc.
GitPython is a port of the grit library in Ruby created by
Tom Preston-Werner and Chris Wanstrath.
Platform: UNKNOWN
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: BSD License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 2.5
Classifier: Programming Language :: Python :: 2.6
Classifier: Topic :: Software Development :: Libraries :: Python Modules

Просмотреть файл

@ -0,0 +1,25 @@
AUTHORS
CHANGES
LICENSE
MANIFEST.in
README
VERSION
setup.cfg
lib/git/__init__.py
lib/git/actor.py
lib/git/blob.py
lib/git/cmd.py
lib/git/commit.py
lib/git/diff.py
lib/git/errors.py
lib/git/head.py
lib/git/lazy.py
lib/git/repo.py
lib/git/stats.py
lib/git/tag.py
lib/git/tree.py
lib/git/utils.py
pip-egg-info/GitPython.egg-info/PKG-INFO
pip-egg-info/GitPython.egg-info/SOURCES.txt
pip-egg-info/GitPython.egg-info/dependency_links.txt
pip-egg-info/GitPython.egg-info/top_level.txt

Просмотреть файл

@ -0,0 +1 @@

Просмотреть файл

@ -0,0 +1 @@
git

Просмотреть файл

@ -0,0 +1,5 @@
[egg_info]
tag_build =
tag_date = 0
tag_svn_revision = 0

Просмотреть файл

@ -0,0 +1,83 @@
try:
from setuptools import setup, find_packages
except ImportError:
from ez_setup import use_setuptools
use_setuptools()
from setuptools import setup, find_packages
from distutils.command.build_py import build_py as _build_py
from setuptools.command.sdist import sdist as _sdist
import os
from os import path
v = open(path.join(path.dirname(__file__), 'VERSION'))
VERSION = v.readline().strip()
v.close()
class build_py(_build_py):
def run(self):
init = path.join(self.build_lib, 'git', '__init__.py')
if path.exists(init):
os.unlink(init)
_build_py.run(self)
_stamp_version(init)
self.byte_compile([init])
class sdist(_sdist):
def make_release_tree (self, base_dir, files):
_sdist.make_release_tree(self, base_dir, files)
orig = path.join('lib', 'git', '__init__.py')
assert path.exists(orig)
dest = path.join(base_dir, orig)
if hasattr(os, 'link') and path.exists(dest):
os.unlink(dest)
self.copy_file(orig, dest)
_stamp_version(dest)
def _stamp_version(filename):
found, out = False, []
f = open(filename, 'r')
for line in f:
if '__version__ =' in line:
line = line.replace("'git'", "'%s'" % VERSION)
found = True
out.append(line)
f.close()
if found:
f = open(filename, 'w')
f.writelines(out)
f.close()
setup(name = "GitPython",
cmdclass={'build_py': build_py, 'sdist': sdist},
version = VERSION,
description = "Python Git Library",
author = "Michael Trier",
author_email = "mtrier@gmail.com",
url = "http://gitorious.org/projects/git-python/",
packages = find_packages('lib'),
package_dir = {'':'lib'},
license = "BSD License",
long_description = """\
GitPython is a python library used to interact with Git repositories.
GitPython provides object model access to your git repository. Once you have
created a repository object, you can traverse it to find parent commit(s),
trees, blobs, etc.
GitPython is a port of the grit library in Ruby created by
Tom Preston-Werner and Chris Wanstrath.
""",
classifiers = [
"Development Status :: 3 - Alpha",
"Intended Audience :: Developers",
"License :: OSI Approved :: BSD License",
"Operating System :: OS Independent",
"Programming Language :: Python",
"Programming Language :: Python :: 2.5",
"Programming Language :: Python :: 2.6",
"Topic :: Software Development :: Libraries :: Python Modules",
]
)

1
src/jingo-minify Submodule

@ -0,0 +1 @@
Subproject commit 95f24e9ecdbeb5d1d88029896b3d53ae8828e533

Просмотреть файл

@ -1,6 +1,8 @@
packages/GitPython/lib
src/commonware
src/django
src/django-sha2
src/jingo
src/jingo-minify
src/tower