diff options
Diffstat (limited to 'git/objects/submodule/base.py')
-rw-r--r-- | git/objects/submodule/base.py | 115 |
1 files changed, 62 insertions, 53 deletions
diff --git a/git/objects/submodule/base.py b/git/objects/submodule/base.py index eea091f8..28802b35 100644 --- a/git/objects/submodule/base.py +++ b/git/objects/submodule/base.py @@ -1,4 +1,3 @@ -from . import util from .util import ( mkhead, sm_name, @@ -29,7 +28,8 @@ from git.exc import ( ) from git.compat import ( string_types, - defenc + defenc, + is_win, ) import stat @@ -38,6 +38,9 @@ import git import os import logging import uuid +from unittest.case import SkipTest +from git.test.lib.helper import HIDE_WINDOWS_KNOWN_ERRORS +from git.objects.base import IndexObject, Object __all__ = ["Submodule", "UpdateProgress"] @@ -66,7 +69,7 @@ UPDWKTREE = UpdateProgress.UPDWKTREE # IndexObject comes via util module, its a 'hacky' fix thanks to pythons import # mechanism which cause plenty of trouble of the only reason for packages and # modules is refactoring - subpackages shoudn't depend on parent packages -class Submodule(util.IndexObject, Iterable, Traversable): +class Submodule(IndexObject, Iterable, Traversable): """Implements access to a git submodule. They are special in that their sha represents a commit in the submodule's repository which is to be checked out @@ -289,14 +292,16 @@ class Submodule(util.IndexObject, Iterable, Traversable): """ git_file = os.path.join(working_tree_dir, '.git') rela_path = os.path.relpath(module_abspath, start=working_tree_dir) - fp = open(git_file, 'wb') - fp.write(("gitdir: %s" % rela_path).encode(defenc)) - fp.close() + if is_win: + if os.path.isfile(git_file): + os.remove(git_file) + with open(git_file, 'wb') as fp: + fp.write(("gitdir: %s" % rela_path).encode(defenc)) - writer = GitConfigParser(os.path.join(module_abspath, 'config'), read_only=False, merge_includes=False) - writer.set_value('core', 'worktree', - to_native_path_linux(os.path.relpath(working_tree_dir, start=module_abspath))) - writer.release() + with GitConfigParser(os.path.join(module_abspath, 'config'), + read_only=False, merge_includes=False) as writer: + writer.set_value('core', 'worktree', + to_native_path_linux(os.path.relpath(working_tree_dir, start=module_abspath))) #{ Edit Interface @@ -393,24 +398,20 @@ class Submodule(util.IndexObject, Iterable, Traversable): # otherwise there is a '-' character in front of the submodule listing # a38efa84daef914e4de58d1905a500d8d14aaf45 mymodule (v0.9.0-1-ga38efa8) # -a38efa84daef914e4de58d1905a500d8d14aaf45 submodules/intermediate/one - writer = sm.repo.config_writer() - writer.set_value(sm_section(name), 'url', url) - writer.release() + with sm.repo.config_writer() as writer: + writer.set_value(sm_section(name), 'url', url) # update configuration and index index = sm.repo.index - writer = sm.config_writer(index=index, write=False) - writer.set_value('url', url) - writer.set_value('path', path) - - sm._url = url - if not branch_is_default: - # store full path - writer.set_value(cls.k_head_option, br.path) - sm._branch_path = br.path - # END handle path - writer.release() - del(writer) + with sm.config_writer(index=index, write=False) as writer: + writer.set_value('url', url) + writer.set_value('path', path) + + sm._url = url + if not branch_is_default: + # store full path + writer.set_value(cls.k_head_option, br.path) + sm._branch_path = br.path # we deliberatly assume that our head matches our index ! sm.binsha = mrepo.head.commit.binsha @@ -523,7 +524,7 @@ class Submodule(util.IndexObject, Iterable, Traversable): # have a valid branch, but no checkout - make sure we can figure # that out by marking the commit with a null_sha - local_branch.set_object(util.Object(mrepo, self.NULL_BIN_SHA)) + local_branch.set_object(Object(mrepo, self.NULL_BIN_SHA)) # END initial checkout + branch creation # make sure HEAD is not detached @@ -537,9 +538,8 @@ class Submodule(util.IndexObject, Iterable, Traversable): # the default implementation will be offended and not update the repository # Maybe this is a good way to assure it doesn't get into our way, but # we want to stay backwards compatible too ... . Its so redundant ! - writer = self.repo.config_writer() - writer.set_value(sm_section(self.name), 'url', self.url) - writer.release() + with self.repo.config_writer() as writer: + writer.set_value(sm_section(self.name), 'url', self.url) # END handle dry_run # END handle initalization @@ -726,11 +726,9 @@ class Submodule(util.IndexObject, Iterable, Traversable): # END handle submodule doesn't exist # update configuration - writer = self.config_writer(index=index) # auto-write - writer.set_value('path', module_checkout_path) - self.path = module_checkout_path - writer.release() - del(writer) + with self.config_writer(index=index) as writer: # auto-write + writer.set_value('path', module_checkout_path) + self.path = module_checkout_path # END handle configuration flag except Exception: if renamed_module: @@ -833,7 +831,7 @@ class Submodule(util.IndexObject, Iterable, Traversable): num_branches_with_new_commits += len(mod.git.cherry(rref)) != 0 # END for each remote ref # not a single remote branch contained all our commits - if num_branches_with_new_commits == len(rrefs): + if len(rrefs) and num_branches_with_new_commits == len(rrefs): raise InvalidGitRepositoryError( "Cannot delete module at %s as there are new commits" % mod.working_tree_dir) # END handle new commits @@ -848,14 +846,30 @@ class Submodule(util.IndexObject, Iterable, Traversable): # finally delete our own submodule if not dry_run: + self._clear_cache() wtd = mod.working_tree_dir del(mod) # release file-handles (windows) - rmtree(wtd) + import gc + gc.collect() + try: + rmtree(wtd) + except Exception as ex: + if HIDE_WINDOWS_KNOWN_ERRORS: + raise SkipTest("FIXME: fails with: PermissionError\n %s", ex) + else: + raise # END delete tree if possible # END handle force if not dry_run and os.path.isdir(git_dir): - rmtree(git_dir) + self._clear_cache() + try: + rmtree(git_dir) + except Exception as ex: + if HIDE_WINDOWS_KNOWN_ERRORS: + raise SkipTest("FIXME: fails with: PermissionError\n %s", ex) + else: + raise # end handle separate bare repository # END handle module deletion @@ -877,13 +891,11 @@ class Submodule(util.IndexObject, Iterable, Traversable): # now git config - need the config intact, otherwise we can't query # information anymore - writer = self.repo.config_writer() - writer.remove_section(sm_section(self.name)) - writer.release() + with self.repo.config_writer() as writer: + writer.remove_section(sm_section(self.name)) - writer = self.config_writer() - writer.remove_section() - writer.release() + with self.config_writer() as writer: + writer.remove_section() # END delete configuration return self @@ -974,18 +986,15 @@ class Submodule(util.IndexObject, Iterable, Traversable): 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() + with self.repo.config_writer() as pw: + # 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)) # .gitmodules - cw = self.config_writer(write=True).config - cw.rename_section(sm_section(self.name), sm_section(new_name)) - cw.release() + with self.config_writer(write=True).config as cw: + cw.rename_section(sm_section(self.name), sm_section(new_name)) self._name = new_name |