aboutsummaryrefslogtreecommitdiff
path: root/git/repo
diff options
context:
space:
mode:
Diffstat (limited to 'git/repo')
-rw-r--r--git/repo/__init__.py2
-rw-r--r--git/repo/base.py263
-rw-r--r--git/repo/fun.py79
3 files changed, 173 insertions, 171 deletions
diff --git a/git/repo/__init__.py b/git/repo/__init__.py
index 8902a254..09051bd4 100644
--- a/git/repo/__init__.py
+++ b/git/repo/__init__.py
@@ -1,3 +1,3 @@
"""Initialize the Repo package"""
-from base import * \ No newline at end of file
+from base import *
diff --git a/git/repo/base.py b/git/repo/base.py
index 6a311f0b..a5bbaa64 100644
--- a/git/repo/base.py
+++ b/git/repo/base.py
@@ -7,9 +7,9 @@
from git.exc import InvalidGitRepositoryError, NoSuchPathError
from git.cmd import Git
from git.util import (
- Actor,
- finalize_process
- )
+ Actor,
+ finalize_process
+ )
from git.refs import *
from git.index import IndexFile
from git.objects import *
@@ -21,7 +21,7 @@ from git.remote import (
)
from git.db import (
- GitCmdObjectDB,
+ GitCmdObjectDB,
GitDB
)
@@ -52,34 +52,35 @@ __all__ = ('Repo', )
class Repo(object):
- """Represents a git repository and allows you to query references,
+
+ """Represents a git repository and allows you to query references,
gather commit information, generate diffs, create and clone repositories query
the log.
-
+
The following attributes are worth using:
-
- 'working_dir' is the working directory of the git command, which is the working tree
+
+ 'working_dir' is the working directory of the git command, which is the working tree
directory if available or the .git directory in case of bare repositories
-
+
'working_tree_dir' is the working tree directory, but will raise AssertionError
if we are a bare repository.
-
+
'git_dir' is the .git repository directory, which is always set."""
DAEMON_EXPORT_FILE = 'git-daemon-export-ok'
- __slots__ = ( "working_dir", "_working_tree_dir", "git_dir", "_bare", "git", "odb" )
-
+ __slots__ = ("working_dir", "_working_tree_dir", "git_dir", "_bare", "git", "odb")
+
# precompiled regex
re_whitespace = re.compile(r'\s+')
re_hexsha_only = re.compile('^[0-9A-Fa-f]{40}$')
re_hexsha_shortened = re.compile('^[0-9A-Fa-f]{4,40}$')
re_author_committer_start = re.compile(r'^(author|committer)')
re_tab_full_line = re.compile(r'^\t(.*)$')
-
+
# invariants
# represents the configuration level of a configuration file
config_level = ("system", "global", "repository")
- def __init__(self, path=None, odbt = DefaultDBType):
+ def __init__(self, path=None, odbt=DefaultDBType):
"""Create a new Repo instance
:param path: is the path to either the root git directory or the bare git repo::
@@ -88,8 +89,8 @@ class Repo(object):
repo = Repo("/Users/mtrier/Development/git-python.git")
repo = Repo("~/Development/git-python.git")
repo = Repo("$REPOSITORIES/Development/git-python.git")
-
- :param odbt: Object DataBase type - a type which is constructed by providing
+
+ :param odbt: Object DataBase type - a type which is constructed by providing
the directory containing the database objects, i.e. .git/objects. It will
be used to access all object data
:raise InvalidGitRepositoryError:
@@ -104,7 +105,7 @@ class Repo(object):
self._working_tree_dir = None
self.git_dir = None
curpath = epath
-
+
# walk up the path to find the .git dir
while curpath:
if is_git_dir(curpath):
@@ -120,26 +121,26 @@ class Repo(object):
if not dummy:
break
# END while curpath
-
+
if self.git_dir is None:
raise InvalidGitRepositoryError(epath)
self._bare = False
try:
- self._bare = self.config_reader("repository").getboolean('core','bare')
+ self._bare = self.config_reader("repository").getboolean('core', 'bare')
except Exception:
# lets not assume the option exists, although it should
pass
- # adjust the wd in case we are actually bare - we didn't know that
+ # adjust the wd in case we are actually bare - we didn't know that
# in the first place
if self._bare:
self._working_tree_dir = None
# END working dir handling
-
+
self.working_dir = self._working_tree_dir or self.git_dir
self.git = Git(self.working_dir)
-
+
# special handling, in special times
args = [join(self.git_dir, 'objects')]
if issubclass(odbt, GitCmdObjectDB):
@@ -150,10 +151,10 @@ class Repo(object):
if isinstance(rhs, Repo):
return self.git_dir == rhs.git_dir
return False
-
+
def __ne__(self, rhs):
return not self.__eq__(rhs)
-
+
def __hash__(self):
return hash(self.git_dir)
@@ -167,23 +168,21 @@ class Repo(object):
def _set_description(self, descr):
filename = join(self.git_dir, 'description')
- file(filename, 'w').write(descr+'\n')
+ 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 working_tree_dir(self):
""":return: The working tree directory of our git repository
:raise AssertionError: If we are a bare repository"""
if self._working_tree_dir is None:
- raise AssertionError( "Repository at %r is bare and does not have a working tree directory" % self.git_dir )
+ raise AssertionError("Repository at %r is bare and does not have a working tree directory" % self.git_dir)
return self._working_tree_dir
-
+
@property
def bare(self):
""":return: True if the repository is bare"""
@@ -196,20 +195,20 @@ class Repo(object):
:return: ``git.IterableList(Head, ...)``"""
return Head.list_items(self)
-
+
@property
def references(self):
"""A list of Reference objects representing tags, heads and remote references.
-
+
:return: IterableList(Reference, ...)"""
return Reference.list_items(self)
-
+
# alias for references
refs = references
# alias for heads
branches = heads
-
+
@property
def index(self):
""":return: IndexFile representing this repository's index."""
@@ -218,57 +217,57 @@ class Repo(object):
@property
def head(self):
""":return: HEAD Object pointing to the current head reference"""
- return HEAD(self,'HEAD')
-
+ return HEAD(self, 'HEAD')
+
@property
def remotes(self):
"""A list of Remote objects allowing to access and manipulate remotes
:return: ``git.IterableList(Remote, ...)``"""
return Remote.list_items(self)
-
+
def remote(self, name='origin'):
""":return: Remote with the specified name
:raise ValueError: if no remote with such a name exists"""
return Remote(self, name)
-
+
#{ Submodules
-
+
@property
def submodules(self):
"""
:return: git.IterableList(Submodule, ...) of direct submodules
available from the current head"""
return Submodule.list_items(self)
-
+
def submodule(self, name):
- """ :return: Submodule with the given name
+ """ :return: Submodule with the given name
:raise ValueError: If no such submodule exists"""
try:
return self.submodules[name]
except IndexError:
raise ValueError("Didn't find submodule named %r" % name)
# END exception handling
-
+
def create_submodule(self, *args, **kwargs):
"""Create a new submodule
-
- :note: See the documentation of Submodule.add for a description of the
+
+ :note: See the documentation of Submodule.add for a description of the
applicable parameters
:return: created submodules"""
return Submodule.add(self, *args, **kwargs)
-
+
def iter_submodules(self, *args, **kwargs):
"""An iterator yielding Submodule instances, see Traversable interface
for a description of args and kwargs
:return: Iterator"""
return RootModule(self).traverse(*args, **kwargs)
-
+
def submodule_update(self, *args, **kwargs):
- """Update the submodules, keeping the repository consistent as it will
+ """Update the submodules, keeping the repository consistent as it will
take the previous state into consideration. For more information, please
see the documentation of RootModule.update"""
return RootModule(self).update(*args, **kwargs)
-
+
#}END submodules
@property
@@ -276,101 +275,101 @@ class Repo(object):
"""A list of ``Tag`` objects that are available in this repo
:return: ``git.IterableList(TagReference, ...)`` """
return TagReference.list_items(self)
-
- def tag(self,path):
+
+ def tag(self, path):
""":return: TagReference Object, reference pointing to a Commit or Tag
:param path: path to the tag reference, i.e. 0.1.5 or tags/0.1.5 """
return TagReference(self, path)
-
- def create_head(self, path, commit='HEAD', force=False, logmsg=None ):
- """Create a new head within the repository.
+
+ def create_head(self, path, commit='HEAD', force=False, logmsg=None):
+ """Create a new head within the repository.
For more documentation, please see the Head.create method.
-
+
:return: newly created Head Reference"""
return Head.create(self, path, commit, force, logmsg)
-
+
def delete_head(self, *heads, **kwargs):
"""Delete the given heads
-
+
:param kwargs: Additional keyword arguments to be passed to git-branch"""
return Head.delete(self, *heads, **kwargs)
-
+
def create_tag(self, path, ref='HEAD', message=None, force=False, **kwargs):
"""Create a new tag reference.
For more documentation, please see the TagReference.create method.
-
+
:return: TagReference object """
return TagReference.create(self, path, ref, message, force, **kwargs)
-
+
def delete_tag(self, *tags):
"""Delete the given tag references"""
return TagReference.delete(self, *tags)
-
+
def create_remote(self, name, url, **kwargs):
"""Create a new remote.
-
- For more information, please see the documentation of the Remote.create
- methods
-
+
+ For more information, please see the documentation of the Remote.create
+ methods
+
:return: Remote reference"""
return Remote.create(self, name, url, **kwargs)
-
+
def delete_remote(self, remote):
"""Delete the given remote."""
return Remote.remove(self, remote)
-
- def _get_config_path(self, config_level ):
- # we do not support an absolute path of the gitconfig on windows ,
+
+ def _get_config_path(self, config_level):
+ # we do not support an absolute path of the gitconfig on windows ,
# use the global config instead
if sys.platform == "win32" and config_level == "system":
config_level = "global"
-
+
if config_level == "system":
return "/etc/gitconfig"
elif config_level == "global":
return os.path.normpath(os.path.expanduser("~/.gitconfig"))
elif config_level == "repository":
return join(self.git_dir, "config")
-
- raise ValueError( "Invalid configuration level: %r" % config_level )
-
+
+ raise ValueError("Invalid configuration level: %r" % config_level)
+
def config_reader(self, config_level=None):
"""
:return:
GitConfigParser allowing to read the full git configuration, but not to write it
-
- The configuration will include values from the system, user and repository
+
+ The configuration will include values from the system, user and repository
configuration files.
-
+
:param config_level:
For possible values, see config_writer method
- If None, all applicable levels will be used. Specify a level in case
- you know which exact file you whish to read to prevent reading multiple files for
+ If None, all applicable levels will be used. Specify a level in case
+ you know which exact file you whish to read to prevent reading multiple files for
instance
- :note: On windows, system configuration cannot currently be read as the path is
+ :note: On windows, system configuration cannot currently be read as the path is
unknown, instead the global path will be used."""
files = None
if config_level is None:
- files = [ self._get_config_path(f) for f in self.config_level ]
+ files = [self._get_config_path(f) for f in self.config_level]
else:
- files = [ self._get_config_path(config_level) ]
+ files = [self._get_config_path(config_level)]
return GitConfigParser(files, read_only=True)
-
+
def config_writer(self, config_level="repository"):
"""
:return:
GitConfigParser allowing to write values of the specified configuration file level.
- Config writers should be retrieved, used to change the configuration ,and written
+ Config writers should be retrieved, used to change the configuration ,and written
right away as they will lock the configuration file in question and prevent other's
to write it.
-
+
:param config_level:
One of the following values
system = sytem wide configuration file
global = user level configuration file
repository = configuration file for this repostory only"""
- return GitConfigParser(self._get_config_path(config_level), read_only = False)
-
+ return GitConfigParser(self._get_config_path(config_level), read_only=False)
+
def commit(self, rev=None):
"""The Commit object for the specified revision
:param rev: revision specifier, see git-rev-parse for viable options.
@@ -378,30 +377,30 @@ class Repo(object):
if rev is None:
return self.head.commit
else:
- return self.rev_parse(unicode(rev)+"^0")
-
+ return self.rev_parse(unicode(rev) + "^0")
+
def iter_trees(self, *args, **kwargs):
""":return: Iterator yielding Tree objects
:note: Takes all arguments known to iter_commits method"""
- return ( c.tree for c in self.iter_commits(*args, **kwargs) )
+ return (c.tree for c in self.iter_commits(*args, **kwargs))
def tree(self, rev=None):
"""The Tree object for the given treeish revision
Examples::
-
+
repo.tree(repo.heads[0])
:param rev: is a revision pointing to a Treeish ( being a commit or tree )
:return: ``git.Tree``
-
+
:note:
If you need a non-root level tree, find it by iterating the root tree. Otherwise
- it cannot know about its path relative to the repository root and subsequent
+ it cannot know about its path relative to the repository root and subsequent
operations might have unexpected results."""
if rev is None:
return self.head.commit.tree
else:
- return self.rev_parse(unicode(rev)+"^{tree}")
+ return self.rev_parse(unicode(rev) + "^{tree}")
def iter_commits(self, rev=None, paths='', **kwargs):
"""A list of Commit objects representing the history of a given ref/commit
@@ -413,18 +412,18 @@ class Repo(object):
:parm paths:
is an optional path or a list of paths to limit the returned commits to
Commits that do not contain that path or the paths will not be returned.
-
+
:parm kwargs:
- Arguments to be passed to git-rev-list - common ones are
+ Arguments to be passed to git-rev-list - common ones are
max_count and skip
- :note: to receive only commits between two named revisions, use the
+ :note: to receive only commits between two named revisions, use the
"revA..revB" revision specifier
:return ``git.Commit[]``"""
if rev is None:
rev = self.head.commit
-
+
return Commit.iter_items(self, rev, paths, **kwargs)
def _get_daemon_export(self):
@@ -464,14 +463,14 @@ class Repo(object):
"""Sets the alternates
:parm alts:
- is the array of string paths representing the alternates at which
+ is the array of string paths representing the alternates at which
git should look for objects, i.e. /home/user/repo/.git/objects
:raise NoSuchPathError:
:note:
The method does not check for the existance of the paths in alts
as the caller is responsible."""
- alternates_path = join(self.git_dir, 'objects', 'info', 'alternates')
+ alternates_path = join(self.git_dir, 'objects', 'info', 'alternates')
if not alts:
if isfile(alternates_path):
os.remove(alternates_path)
@@ -481,7 +480,7 @@ class Repo(object):
f.write("\n".join(alts))
finally:
f.close()
- # END file handling
+ # 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")
@@ -490,16 +489,16 @@ class Repo(object):
"""
:return:
``True``, the repository is considered dirty. By default it will react
- like a git-status without untracked files, hence it is dirty if the
+ like a git-status without untracked files, hence it is dirty if the
index or the working copy have changes."""
if self._bare:
# Bare repositories with no associated working directory are
# always consired to be clean.
return False
-
+
# start from the one which is fastest to evaluate
default_args = ('--abbrev=40', '--full-index', '--raw')
- if index:
+ if index:
# diff index against HEAD
if isfile(self.index.path) and \
len(self.git.diff('--cached', *default_args)):
@@ -551,14 +550,14 @@ class Repo(object):
:return: Head to the active branch"""
return self.head.reference
-
+
def blame(self, rev, file):
"""The blame information for the given file at the given revision.
:parm rev: revision specifier, see git-rev-parse for viable options.
:return:
list: [git.Commit, list: [<line>]]
- A list of tuples associating a Commit object with a list of lines that
+ 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 = self.git.blame(rev, '--', file, p=True)
@@ -570,7 +569,7 @@ class Repo(object):
parts = self.re_whitespace.split(line, 1)
firstpart = parts[0]
if self.re_hexsha_only.search(firstpart):
- # handles
+ # handles
# 634396b2f541a9f2d58b00be1a07f0c358b999b3 1 1 7 - indicates blame-data start
# 634396b2f541a9f2d58b00be1a07f0c358b999b3 2 2 - indicates another line of blame with the same data
digits = parts[-1].split(" ")
@@ -584,7 +583,7 @@ class Repo(object):
else:
m = self.re_author_committer_start.search(firstpart)
if m:
- # handles:
+ # handles:
# author Tom Preston-Werner
# author-mail <tom@mojombo.com>
# author-time 1192271832
@@ -615,7 +614,7 @@ class Repo(object):
sha = info['id']
c = commits.get(sha)
if c is None:
- c = Commit( self, hex_to_bin(sha),
+ c = Commit(self, hex_to_bin(sha),
author=Actor._from_string(info['author'] + ' ' + info['author_email']),
authored_date=info['author_date'],
committer=Actor._from_string(info['committer'] + ' ' + info['committer_email']),
@@ -624,9 +623,9 @@ class Repo(object):
commits[sha] = c
# END if commit objects needs initial creation
m = self.re_tab_full_line.search(line)
- text, = m.groups()
+ text, = m.groups()
blames[-1][0] = c
- blames[-1][1].append( text )
+ blames[-1][1].append(text)
info = {'id': sha}
# END if we collected commit info
# END distinguish filename,summary,rest
@@ -640,12 +639,12 @@ class Repo(object):
:param path:
is the full path to the repo (traditionally ends with /<name>.git)
- or None in which case the repository will be created in the current
+ or None in which case the repository will be created in the current
working directory
:parm mkdir:
if specified will create the repository directory if it doesn't
- already exists. Creates the directory with a mode=0755.
+ already exists. Creates the directory with a mode=0755.
Only effective if a path is explicitly given
:parm kwargs:
@@ -663,7 +662,7 @@ class Repo(object):
@classmethod
def _clone(cls, git, url, path, odb_default_type, progress, **kwargs):
- # special handling for windows for path at which the clone should be
+ # special handling for windows for path at which the clone should be
# created.
# tilde '~' will be expanded to the HOME no matter where the ~ occours. Hence
# we at least give a proper error instead of letting git fail
@@ -673,9 +672,9 @@ class Repo(object):
if os.name == 'nt':
if '~' in path:
raise OSError("Git cannot handle the ~ character in path %r correctly" % path)
-
- # on windows, git will think paths like c: are relative and prepend the
- # current working dir ( before it fails ). We temporarily adjust the working
+
+ # on windows, git will think paths like c: are relative and prepend the
+ # current working dir ( before it fails ). We temporarily adjust the working
# dir to make this actually work
match = re.match("(\w:[/\\\])(.*)", path)
if match:
@@ -685,9 +684,9 @@ class Repo(object):
os.chdir(drive)
path = rest_of_path
kwargs['with_keep_cwd'] = True
- # END cwd preparation
- # END windows handling
-
+ # END cwd preparation
+ # END windows handling
+
try:
proc = git.clone(url, path, with_extended_output=True, as_process=True, v=True, **add_progress(kwargs, git, progress))
if progress:
@@ -700,18 +699,18 @@ class Repo(object):
path = prev_path
# END reset previous working dir
# END bad windows handling
-
- # our git command could have a different working dir than our actual
+
+ # our git command could have a different working dir than our actual
# environment, hence we prepend its working dir if required
if not os.path.isabs(path) and git.working_dir:
path = join(git._working_dir, path)
-
- # adjust remotes - there may be operating systems which use backslashes,
+
+ # adjust remotes - there may be operating systems which use backslashes,
# These might be given as initial paths, but when handling the config file
# that contains the remote from which we were clones, git stops liking it
- # as it will escape the backslashes. Hence we undo the escaping just to be
+ # as it will escape the backslashes. Hence we undo the escaping just to be
# sure
- repo = cls(os.path.abspath(path), odbt = odbt)
+ repo = cls(os.path.abspath(path), odbt=odbt)
if repo.remotes:
repo.remotes[0].config_writer.set_value('url', repo.remotes[0].url.replace("\\\\", "\\").replace("\\", "/"))
# END handle remote repo
@@ -727,9 +726,9 @@ class Repo(object):
:param kwargs:
odbt = ObjectDatabase Type, allowing to determine the object database
implementation used by the returned Repo instance
-
+
All remaining keyword arguments are given to the git-clone command
-
+
:return: ``git.Repo`` (the newly cloned repo)"""
return self._clone(self.git, self.git_dir, path, type(self.odb), progress, **kwargs)
@@ -743,14 +742,14 @@ class Repo(object):
:return: Repo instance pointing to the cloned directory"""
return cls._clone(Git(os.getcwd()), url, to_path, GitCmdObjectDB, progress, **kwargs)
- def archive(self, ostream, treeish=None, prefix=None, **kwargs):
+ def archive(self, ostream, treeish=None, prefix=None, **kwargs):
"""Archive the tree at the given revision.
:parm ostream: file compatible stream object to which the archive will be written
:parm treeish: is the treeish name/id, defaults to active branch
:parm prefix: is the optional prefix to prepend to each filename in the archive
:parm kwargs:
Additional arguments passed to git-archive
- NOTE: Use the 'format' argument to define the kind of format. Use
+ NOTE: Use the 'format' argument to define the kind of format. Use
specialized ostreams to write any format supported by python
:raise GitCommandError: in case something went wrong
@@ -758,13 +757,13 @@ class Repo(object):
if treeish is None:
treeish = self.head.commit
if prefix and 'prefix' not in kwargs:
- kwargs['prefix'] = prefix
+ kwargs['prefix'] = prefix
kwargs['output_stream'] = ostream
-
+
self.git.archive(treeish, **kwargs)
return self
-
+
rev_parse = rev_parse
-
+
def __repr__(self):
return '<git.Repo "%s">' % self.git_dir
diff --git a/git/repo/fun.py b/git/repo/fun.py
index 2c49d836..9dfc00ea 100644
--- a/git/repo/fun.py
+++ b/git/repo/fun.py
@@ -5,20 +5,22 @@ from git.refs import SymbolicReference
from git.objects import Object
from gitdb.util import (
join,
- isdir,
+ isdir,
isfile,
dirname,
- hex_to_bin,
+ hex_to_bin,
bin_to_hex
)
from string import digits
__all__ = ('rev_parse', 'is_git_dir', 'touch')
+
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."""
@@ -53,8 +55,8 @@ def short_to_long(odb, hexsha):
except BadObject:
return None
# END exception handling
-
-
+
+
def name_to_object(repo, name, return_ref=False):
"""
:return: object specified by the given name, hexshas ( short and long )
@@ -63,7 +65,7 @@ def name_to_object(repo, name, return_ref=False):
instead of the object. Otherwise it will raise BadObject
"""
hexsha = None
-
+
# is it a hexsha ? Try the most common ones, which is 7 to 40
if repo.re_hexsha_shortened.match(name):
if len(name) != 40:
@@ -73,8 +75,8 @@ def name_to_object(repo, name, return_ref=False):
hexsha = name
# END handle short shas
#END find sha if it matches
-
- # if we couldn't find an object for what seemed to be a short hexsha
+
+ # if we couldn't find an object for what seemed to be a short hexsha
# try to find it as reference anyway, it could be named 'aaa' for instance
if hexsha is None:
for base in ('%s', 'refs/%s', 'refs/tags/%s', 'refs/heads/%s', 'refs/remotes/%s', 'refs/remotes/%s/HEAD'):
@@ -98,9 +100,10 @@ def name_to_object(repo, name, return_ref=False):
if hexsha is None:
raise BadObject(name)
# END assert hexsha was found
-
+
return Object.new_from_sha(repo, hex_to_bin(hexsha))
+
def deref_tag(tag):
"""Recursively dereerence a tag and return the resulting object"""
while True:
@@ -111,16 +114,18 @@ def deref_tag(tag):
# END dereference tag
return tag
+
def to_commit(obj):
"""Convert the given object to a commit if possible and return it"""
if obj.type == 'tag':
obj = deref_tag(obj)
-
+
if obj.type != "commit":
raise ValueError("Cannot convert object %r to type commit" % obj)
# END verify type
return obj
+
def rev_parse(repo, rev):
"""
:return: Object at the given revision, either Commit, Tag, Tree or Blob
@@ -132,13 +137,13 @@ def rev_parse(repo, rev):
:raise BadObject: if the given revision could not be found
:raise ValueError: If rev couldn't be parsed
:raise IndexError: If invalid reflog index is specified"""
-
+
# colon search mode ?
if rev.startswith(':/'):
# colon search mode
raise NotImplementedError("commit by message search ( regex )")
# END handle search
-
+
obj = None
ref = None
output_type = "commit"
@@ -150,9 +155,9 @@ def rev_parse(repo, rev):
start += 1
continue
# END handle start
-
+
token = rev[start]
-
+
if obj is None:
# token is a rev name
if start == 0:
@@ -164,25 +169,24 @@ def rev_parse(repo, rev):
obj = name_to_object(repo, rev[:start])
#END handle token
#END handle refname
-
+
if ref is not None:
obj = ref.commit
#END handle ref
# END initialize obj on first token
-
-
+
start += 1
-
+
# try to parse {type}
if start < lr and rev[start] == '{':
end = rev.find('}', start)
if end == -1:
raise ValueError("Missing closing brace to define type in %s" % rev)
- output_type = rev[start+1:end] # exclude brace
-
- # handle type
+ output_type = rev[start + 1:end] # exclude brace
+
+ # handle type
if output_type == 'commit':
- pass # default
+ pass # default
elif output_type == 'tree':
try:
obj = to_commit(obj).tree
@@ -202,37 +206,37 @@ def rev_parse(repo, rev):
revlog_index = None
try:
# transform reversed index into the format of our revlog
- revlog_index = -(int(output_type)+1)
+ revlog_index = -(int(output_type) + 1)
except ValueError:
# TODO: Try to parse the other date options, using parse_date
# maybe
raise NotImplementedError("Support for additional @{...} modes not implemented")
#END handle revlog index
-
+
try:
entry = ref.log_entry(revlog_index)
except IndexError:
raise IndexError("Invalid revlog index: %i" % revlog_index)
#END handle index out of bound
-
+
obj = Object.new_from_sha(repo, hex_to_bin(entry.newhexsha))
-
+
# make it pass the following checks
output_type = None
else:
- raise ValueError("Invalid output type: %s ( in %s )" % (output_type, rev))
+ raise ValueError("Invalid output type: %s ( in %s )" % (output_type, rev))
# END handle output type
-
+
# empty output types don't require any specific type, its just about dereferencing tags
if output_type and obj.type != output_type:
raise ValueError("Could not accomodate requested object type %r, got %s" % (output_type, obj.type))
# END verify ouput type
-
- start = end+1 # skip brace
+
+ start = end + 1 # skip brace
parsed_to = start
continue
# END parse type
-
+
# try to parse a number
num = 0
if token != ":":
@@ -246,15 +250,14 @@ def rev_parse(repo, rev):
break
# END handle number
# END number parse loop
-
+
# no explicit number given, 1 is the default
- # It could be 0 though
+ # It could be 0 though
if not found_digit:
num = 1
# END set default num
# END number parsing only if non-blob mode
-
-
+
parsed_to = start
# handle hiererarchy walk
try:
@@ -267,7 +270,7 @@ def rev_parse(repo, rev):
obj = to_commit(obj)
# must be n'th parent
if num:
- obj = obj.parents[num-1]
+ obj = obj.parents[num - 1]
elif token == ":":
if obj.type != "tree":
obj = obj.tree
@@ -281,17 +284,17 @@ def rev_parse(repo, rev):
raise BadObject("Invalid Revision in %s" % rev)
# END exception handling
# END parse loop
-
+
# still no obj ? Its probably a simple name
if obj is None:
obj = name_to_object(repo, rev)
parsed_to = lr
# END handle simple name
-
+
if obj is None:
raise ValueError("Revision specifier could not be parsed: %s" % rev)
if parsed_to != lr:
raise ValueError("Didn't consume complete rev spec %s, consumed part: %s" % (rev, rev[:parsed_to]))
-
+
return obj