FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

GitHub Viewer

from . import util from .util import ( mkhead, sm_name, sm_section, SubmoduleConfigParser, find_first_remote_branch ) from git.objects.util import Traversable from io import BytesIO # need a dict to set bloody .name field from git.util import ( Iterable, join_path_native, to_native_path_linux, RemoteProgress, rmtree, unbare_repo ) from git.config import ( SectionConstraint, GitConfigParser, cp ) from git.exc import ( InvalidGitRepositoryError, NoSuchPathError, RepositoryDirtyError ) from git.compat import ( string_types, defenc ) import stat import git import os import logging import uuid __all__ = ["Submodule", "UpdateProgress"] log = logging.getLogger('git.objects.submodule.base') class UpdateProgress(RemoteProgress): """Class providing detailed progress information to the caller who should derive from it and implement the ``update(...)`` message""" CLONE, FETCH, UPDWKTREE = [1 =v1.8.0: move submodule repository to new name) As .gitmodules will be changed, you would need to make a commit afterwards. The changed .gitmodules file will already be added to the index :return: this submodule instance """ if self.name == new_name: return self # .git/config pw = self.repo.config_writer() # As we ourselves didn't write anything about submodules into the parent .git/config, we will not require # it to exist, and just ignore missing entries if pw.has_section(sm_section(self.name)): pw.rename_section(sm_section(self.name), sm_section(new_name)) # end pw.release() # .gitmodules cw = self.config_writer(write=True).config cw.rename_section(sm_section(self.name), sm_section(new_name)) cw.release() self._name = new_name # .git/modules mod = self.module() if mod.has_separate_working_tree(): destination_module_abspath = self._module_abspath(self.repo, self.path, new_name) source_dir = mod.git_dir # Let's be sure the submodule name is not so obviously tied to a directory if destination_module_abspath.startswith(mod.git_dir): tmp_dir = self._module_abspath(self.repo, self.path, str(uuid.uuid4())) os.renames(source_dir, tmp_dir) source_dir = tmp_dir # end handle self-containment os.renames(source_dir, destination_module_abspath) self._write_git_file_and_module_config(mod.working_tree_dir, destination_module_abspath) # end move separate git repository return self #} END edit interface #{ Query Interface @unbare_repo def module(self): """:return: Repo instance initialized from the repository at our submodule path :raise InvalidGitRepositoryError: if a repository was not available. This could also mean that it was not yet initialized""" # late import to workaround circular dependencies module_checkout_abspath = self.abspath try: repo = git.Repo(module_checkout_abspath) if repo != self.repo: return repo # END handle repo uninitialized except (InvalidGitRepositoryError, NoSuchPathError): raise InvalidGitRepositoryError("No valid repository at %s" % module_checkout_abspath) else: raise InvalidGitRepositoryError("Repository at %r was not yet checked out" % module_checkout_abspath) # END handle exceptions def module_exists(self): """:return: True if our module exists and is a valid git repository. See module() method""" try: self.module() return True except Exception: return False # END handle exception def exists(self): """ :return: True if the submodule exists, False otherwise. Please note that a submodule may exist (in the .gitmodules file) even though its module doesn't exist on disk""" # keep attributes for later, and restore them if we have no valid data # this way we do not actually alter the state of the object loc = locals() for attr in self._cache_attrs: try: if hasattr(self, attr): loc[attr] = getattr(self, attr) # END if we have the attribute cache except (cp.NoSectionError, ValueError): # on PY3, this can happen apparently ... don't know why this doesn't happen on PY2 pass # END for each attr self._clear_cache() try: try: self.path return True except Exception: return False # END handle exceptions finally: for attr in self._cache_attrs: if attr in loc: setattr(self, attr, loc[attr]) # END if we have a cache # END reapply each attribute # END handle object state consistency @property def branch(self): """:return: The branch instance that we are to checkout :raise InvalidGitRepositoryError: if our module is not yet checked out""" return mkhead(self.module(), self._branch_path) @property def branch_path(self): """ :return: full (relative) path as string to the branch we would checkout from the remote and track""" return self._branch_path @property def branch_name(self): """:return: the name of the branch, which is the shortest possible branch name""" # use an instance method, for this we create a temporary Head instance # which uses a repository that is available at least ( it makes no difference ) return git.Head(self.repo, self._branch_path).name @property def url(self): """:return: The url to the repository which our module-repository refers to""" return self._url @property def parent_commit(self): """:return: Commit instance with the tree containing the .gitmodules file :note: will always point to the current head's commit if it was not set explicitly""" if self._parent_commit is None: return self.repo.commit() return self._parent_commit @property def name(self): """:return: The name of this submodule. It is used to identify it within the .gitmodules file. :note: by default, the name is the path at which to find the submodule, but in git-python it should be a unique identifier similar to the identifiers used for remotes, which allows to change the path of the submodule easily """ return self._name def config_reader(self): """ :return: ConfigReader instance which allows you to qurey the configuration values of this submodule, as provided by the .gitmodules file :note: The config reader will actually read the data directly from the repository and thus does not need nor care about your working tree. :note: Should be cached by the caller and only kept as long as needed :raise IOError: If the .gitmodules file/blob could not be read""" return self._config_parser_constrained(read_only=True) def children(self): """ :return: IterableList(Submodule, ...) an iterable list of submodules instances which are children of this submodule or 0 if the submodule is not checked out""" return self._get_intermediate_items(self) #} END query interface #{ Iterable Interface @classmethod def iter_items(cls, repo, parent_commit='HEAD'): """:return: iterator yielding Submodule instances available in the given repository""" pc = repo.commit(parent_commit) # parent commit instance try: parser = cls._config_parser(repo, pc, read_only=True) except IOError: raise StopIteration # END handle empty iterator rt = pc.tree # root tree for sms in parser.sections(): n = sm_name(sms) p = parser.get_value(sms, 'path') u = parser.get_value(sms, 'url') b = cls.k_head_default if parser.has_option(sms, cls.k_head_option): b = str(parser.get_value(sms, cls.k_head_option)) # END handle optional information # get the binsha index = repo.index try: sm = rt[p] except KeyError: # try the index, maybe it was just added try: entry = index.entries[index.entry_key(p, 0)] sm = Submodule(repo, entry.binsha, entry.mode, entry.path) except KeyError: raise InvalidGitRepositoryError( "Gitmodule path %r did not exist in revision of parent commit %s" % (p, parent_commit)) # END handle keyerror # END handle critical error # fill in remaining info - saves time as it doesn't have to be parsed again sm._name = n if pc != repo.commit(): sm._parent_commit = pc # end set only if not most recent ! sm._branch_path = git.Head.to_full_path(b) sm._url = u yield sm # END for each section #} END iterable interface

Back | FazBrowse Home | New Git URL