summaryrefslogtreecommitdiff
path: root/git/db/py
diff options
context:
space:
mode:
Diffstat (limited to 'git/db/py')
-rw-r--r--git/db/py/base.py74
-rw-r--r--git/db/py/complex.py18
-rw-r--r--git/db/py/resolve.py44
-rw-r--r--git/db/py/transport.py61
4 files changed, 142 insertions, 55 deletions
diff --git a/git/db/py/base.py b/git/db/py/base.py
index f45711d5..cc326c27 100644
--- a/git/db/py/base.py
+++ b/git/db/py/base.py
@@ -35,7 +35,7 @@ import os
__all__ = ( 'PureObjectDBR', 'PureObjectDBW', 'PureRootPathDB', 'PureCompoundDB',
- 'PureConfigurationMixin', 'PureRepositoryPathsMixin')
+ 'PureConfigurationMixin', 'PureRepositoryPathsMixin', 'PureAlternatesFileMixin')
class PureObjectDBR(ObjectDBR):
@@ -385,3 +385,75 @@ class PureConfigurationMixin(ConfigurationMixin):
#} END interface
+
+class PureAlternatesFileMixin(object):
+ """Utility able to read and write an alternates file through the alternates property
+ It needs to be part of a type with the git_dir or db_path property.
+
+ The file by default is assumed to be located at the default location as imposed
+ by the standard git repository layout"""
+
+ #{ Configuration
+ alternates_filepath = os.path.join('info', 'alternates') # relative path to alternates file
+
+ #} END configuration
+
+ def __init__(self, *args, **kwargs):
+ super(PureAlternatesFileMixin, self).__init__(*args, **kwargs)
+ self._alternates_path() # throws on incompatible type
+
+ #{ Interface
+
+ def _alternates_path(self):
+ if hasattr(self, 'git_dir'):
+ return join(self.git_dir, 'objects', self.alternates_filepath)
+ elif hasattr(self, 'db_path'):
+ return self.db_path(self.alternates_filepath)
+ else:
+ raise AssertionError("This mixin requires a parent type with either the git_dir property or db_path method")
+ #END handle path
+
+ def _get_alternates(self):
+ """The list of alternates for this repo from which objects can be retrieved
+
+ :return: list of strings being pathnames of alternates"""
+ alternates_path = self._alternates_path()
+
+ if os.path.exists(alternates_path):
+ try:
+ f = open(alternates_path)
+ alts = f.read()
+ finally:
+ f.close()
+ return alts.strip().splitlines()
+ else:
+ return list()
+ # END handle path exists
+
+ def _set_alternates(self, alts):
+ """Sets the alternates
+
+ :parm alts:
+ 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 = self._alternates_path()
+ if not alts:
+ if 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")
+
+ #} END interface
diff --git a/git/db/py/complex.py b/git/db/py/complex.py
index de68d4fd..6504b3ed 100644
--- a/git/db/py/complex.py
+++ b/git/db/py/complex.py
@@ -8,6 +8,7 @@ from base import (
PureRootPathDB,
PureRepositoryPathsMixin,
PureConfigurationMixin,
+ PureAlternatesFileMixin,
)
from resolve import PureReferencesMixin
@@ -17,6 +18,8 @@ from pack import PurePackedODB
from ref import PureReferenceDB
from submodule import PureSubmoduleDB
+from git.db.compat import RepoCompatInterface
+
from git.util import (
LazyMixin,
normpath,
@@ -30,10 +33,11 @@ from git.exc import (
)
import os
-__all__ = ('PureGitODB', 'PureGitDB')
+__all__ = ('PureGitODB', 'PureGitDB', 'PureCompatibilityGitDB')
-class PureGitODB(PureRootPathDB, PureObjectDBW, PureCompoundDB, PureSubmoduleDB):
+class PureGitODB(PureRootPathDB, PureObjectDBW, PureCompoundDB,
+ PureSubmoduleDB, PureAlternatesFileMixin):
"""A git-style object-only database, which contains all objects in the 'objects'
subdirectory.
:note: The type needs to be initialized on the ./objects directory to function,
@@ -47,7 +51,7 @@ class PureGitODB(PureRootPathDB, PureObjectDBW, PureCompoundDB, PureSubmoduleDB)
# Directories
packs_dir = 'pack'
loose_dir = ''
- alternates_dir = os.path.join('info', 'alternates')
+
def __init__(self, root_path):
"""Initialize ourselves on a git ./objects directory"""
@@ -59,7 +63,7 @@ class PureGitODB(PureRootPathDB, PureObjectDBW, PureCompoundDB, PureSubmoduleDB)
loose_db = None
for subpath, dbcls in ((self.packs_dir, self.PackDBCls),
(self.loose_dir, self.LooseDBCls),
- (self.alternates_dir, self.PureReferenceDBCls)):
+ (self.alternates_filepath, self.PureReferenceDBCls)):
path = self.db_path(subpath)
if os.path.exists(path):
self._dbs.append(dbcls(path))
@@ -75,7 +79,7 @@ class PureGitODB(PureRootPathDB, PureObjectDBW, PureCompoundDB, PureSubmoduleDB)
# END handle error
# we the first one should have the store method
- assert loose_db is not None and hasattr(loose_db, 'store'), "First database needs store functionality"
+ assert loose_db is not None and hasattr(loose_db, 'store'), "One database needs store functionality"
# finally set the value
self._loose_db = loose_db
@@ -97,6 +101,7 @@ class PureGitODB(PureRootPathDB, PureObjectDBW, PureCompoundDB, PureSubmoduleDB)
#} END objectdbw interface
+
class PureGitDB(PureGitODB, PureRepositoryPathsMixin, PureConfigurationMixin, PureReferencesMixin):
"""Git like database with support for object lookup as well as reference resolution.
Our rootpath is set to the actual .git directory (bare on unbare).
@@ -112,3 +117,6 @@ class PureGitDB(PureGitODB, PureRepositoryPathsMixin, PureConfigurationMixin, Pu
+class PureCompatibilityGitDB(PureGitDB, RepoCompatInterface):
+ """Pure git database with a compatability layer required by 0.3x code"""
+
diff --git a/git/db/py/resolve.py b/git/db/py/resolve.py
index 9cce8efe..94992d11 100644
--- a/git/db/py/resolve.py
+++ b/git/db/py/resolve.py
@@ -5,6 +5,9 @@ from git.db.interface import ReferencesMixin
from git.exc import BadObject
from git.refs import SymbolicReference
from git.objects.base import Object
+from git.refs.head import HEAD
+from git.refs.headref import Head
+from git.refs.tag import TagReference
from git.util import (
join,
isdir,
@@ -281,17 +284,52 @@ class PureReferencesMixin(ReferencesMixin):
re_hexsha_only = re.compile('^[0-9A-Fa-f]{40}$')
re_hexsha_shortened = re.compile('^[0-9A-Fa-f]{4,40}$')
+ #{ Configuration
+ # Types to use when instatiating references
+ TagReferenceCls = TagReference
+ HeadCls = Head
+ ReferenceCls = Reference
+ HEADCls = HEAD
+ #} END configuration
+
def resolve(self, name):
+ return self.resolve_object(name).binsha
+
+ def resolve_object(self, name):
return rev_parse(self, name)
@property
def references(self):
- raise NotImplementedError()
+ return self.ReferenceCls.list_items(self)
@property
def heads(self):
- raise NotImplementedError()
+ return self.HeadCls.list_items(self)
@property
def tags(self):
- raise NotImplementedError()
+ return self.TagReferenceCls.list_items(self)
+
+ def tag(self, name):
+ return self.tags[name]
+
+ @property
+ def head(self):
+ return self.HEADCls(self,'HEAD')
+
+ def create_head(self, path, commit='HEAD', force=False, logmsg=None ):
+ return self.HeadCls.create(self, path, commit, force, logmsg)
+
+ def delete_head(self, *heads, **kwargs):
+ return self.HeadCls.delete(self, *heads, **kwargs)
+
+ def create_tag(self, path, ref='HEAD', message=None, force=False, **kwargs):
+ return self.TagReferenceCls.create(self, path, ref, message, force, **kwargs)
+
+ def delete_tag(self, *tags):
+ return self.TagReferenceCls.delete(self, *tags)
+
+
+ # compat
+ branches = heads
+ refs = references
diff --git a/git/db/py/transport.py b/git/db/py/transport.py
index f8edfb23..00d222b0 100644
--- a/git/db/py/transport.py
+++ b/git/db/py/transport.py
@@ -9,6 +9,10 @@ from git.db.interface import ( TransportDB,
FetchInfo,
RefSpec )
+from git.refs.remote import RemoteReference
+from git.remote import Remote
+
+
__all__ = ["PureTransportDB"]
class PurePushInfo(PushInfo):
@@ -23,67 +27,32 @@ class PureFetchInfo(FetchInfo):
class PureTransportDB(TransportDB):
- """A database which allows to transport objects from and to different locations
- which are specified by urls (location) and refspecs (what to transport,
- see http://www.kernel.org/pub/software/scm/git/docs/git-fetch.html).
-
- At the beginning of a transport operation, it will be determined which objects
- have to be sent (either by this or by the other side).
-
- Afterwards a pack with the required objects is sent (or received). If there is
- nothing to send, the pack will be empty.
-
- The communication itself if implemented using a protocol instance which deals
- with the actual formatting of the lines sent.
-
- As refspecs involve symbolic names for references to be handled, we require
- RefParse functionality. How this is done is up to the actual implementation."""
# The following variables need to be set by the derived class
#{Configuration
protocol = None
+ RemoteCls = Remote
#}end configuraiton
#{ Interface
def fetch(self, url, refspecs, progress=None, **kwargs):
- """Fetch the objects defined by the given refspec from the given url.
- :param url: url identifying the source of the objects. It may also be
- a symbol from which the respective url can be resolved, like the
- name of the remote. The implementation should allow objects as input
- as well, these are assumed to resovle to a meaningful string though.
- :param refspecs: iterable of reference specifiers or RefSpec instance,
- identifying the references to be fetch from the remote.
- :param progress: callable which receives progress messages for user consumption
- :param kwargs: may be used for additional parameters that the actual implementation could
- find useful.
- :return: List of PureFetchInfo compatible instances which provide information about what
- was previously fetched, in the order of the input refspecs.
- :note: even if the operation fails, one of the returned PureFetchInfo instances
- may still contain errors or failures in only part of the refspecs.
- :raise: if any issue occours during the transport or if the url is not
- supported by the protocol.
- """
raise NotImplementedError()
def push(self, url, refspecs, progress=None, **kwargs):
- """Transport the objects identified by the given refspec to the remote
- at the given url.
- :param url: Decribes the location which is to receive the objects
- see fetch() for more details
- :param refspecs: iterable of refspecs strings or RefSpec instances
- to identify the objects to push
- :param progress: see fetch()
- :param kwargs: additional arguments which may be provided by the caller
- as they may be useful to the actual implementation
- :todo: what to return ?
- :raise: if any issue arises during transport or if the url cannot be handled"""
raise NotImplementedError()
@property
def remotes(self):
- """:return: An IterableList of Remote objects allowing to access and manipulate remotes
- :note: Remote objects can also be used for the actual push or fetch operation"""
- raise NotImplementedError()
+ return self.RemoteCls.list_items(self)
+
+ def remote(self, name='origin'):
+ return self.remotes[name]
+ def create_remote(self, name, url, **kwargs):
+ return self.RemoteCls.create(self, name, url, **kwargs)
+
+ def delete_remote(self, remote):
+ return self.RemoteCls.remove(self, remote)
+
#}end interface