def test_to_relative_path_with_super_at_root_drive(self): class Repo(object): working_tree_dir = 'D:\\' super_repo = Repo() submodule_path = 'D:\\submodule_path' relative_path = Submodule._to_relative_path(super_repo, submodule_path) msg = '_to_relative_path should be "submodule_path" but was "%s"' % relative_path assert relative_path == 'submodule_path', msg
def git_submodule(name, path, url, branch): #print sys.path from git.repo.base import Repo d = str(Path('.').abspath()) repo = Repo(d) # current repo from git.objects.submodule.base import Submodule s = Submodule.add(repo,name,path, url, branch) #s = self.repo.lookup_submodule(SUBM_PATH) #self.repo.listall_submodules() return str(Path(path).abspath())
def _do_base_tests(self, rwrepo): """Perform all tests in the given repository, it may be bare or nonbare""" # manual instantiation smm = Submodule(rwrepo, "\0"*20) # name needs to be set in advance self.failUnlessRaises(AttributeError, getattr, smm, 'name') # iterate - 1 submodule sms = Submodule.list_items(rwrepo, self.k_subm_current) assert len(sms) == 1 sm = sms[0] # at a different time, there is None assert len(Submodule.list_items(rwrepo, self.k_no_subm_tag)) == 0 assert sm.path == 'git/ext/gitdb' assert sm.path != sm.name # in our case, we have ids there, which don't equal the path assert sm.url == 'git://github.com/gitpython-developers/gitdb.git' assert sm.branch_path == 'refs/heads/master' # the default ... assert sm.branch_name == 'master' assert sm.parent_commit == rwrepo.head.commit # size is always 0 assert sm.size == 0 # the module is not checked-out yet self.failUnlessRaises(InvalidGitRepositoryError, sm.module) # which is why we can't get the branch either - it points into the module() repository self.failUnlessRaises(InvalidGitRepositoryError, getattr, sm, 'branch') # branch_path works, as its just a string assert isinstance(sm.branch_path, basestring) # some commits earlier we still have a submodule, but its at a different commit smold = Submodule.iter_items(rwrepo, self.k_subm_changed).next() assert smold.binsha != sm.binsha assert smold != sm # the name changed # force it to reread its information del(smold._url) smold.url == sm.url # test config_reader/writer methods sm.config_reader() new_smclone_path = None # keep custom paths for later new_csmclone_path = None # if rwrepo.bare: self.failUnlessRaises(InvalidGitRepositoryError, sm.config_writer) else: writer = sm.config_writer() # for faster checkout, set the url to the local path new_smclone_path = to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path)) writer.set_value('url', new_smclone_path) del(writer) assert sm.config_reader().get_value('url') == new_smclone_path assert sm.url == new_smclone_path # END handle bare repo smold.config_reader() # cannot get a writer on historical submodules if not rwrepo.bare: self.failUnlessRaises(ValueError, smold.config_writer) # END handle bare repo # make the old into a new - this doesn't work as the name changed prev_parent_commit = smold.parent_commit self.failUnlessRaises(ValueError, smold.set_parent_commit, self.k_subm_current) # the sha is properly updated smold.set_parent_commit(self.k_subm_changed+"~1") assert smold.binsha != sm.binsha # raises if the sm didn't exist in new parent - it keeps its # parent_commit unchanged self.failUnlessRaises(ValueError, smold.set_parent_commit, self.k_no_subm_tag) # TEST TODO: if a path in the gitmodules file, but not in the index, it raises # TEST UPDATE ############## # module retrieval is not always possible if rwrepo.bare: self.failUnlessRaises(InvalidGitRepositoryError, sm.module) self.failUnlessRaises(InvalidGitRepositoryError, sm.remove) self.failUnlessRaises(InvalidGitRepositoryError, sm.add, rwrepo, 'here', 'there') else: # its not checked out in our case self.failUnlessRaises(InvalidGitRepositoryError, sm.module) assert not sm.module_exists() # currently there is only one submodule assert len(list(rwrepo.iter_submodules())) == 1 assert sm.binsha != "\0"*20 # TEST ADD ########### # preliminary tests # adding existing returns exactly the existing sma = Submodule.add(rwrepo, sm.name, sm.path) assert sma.path == sm.path # no url and no module at path fails self.failUnlessRaises(ValueError, Submodule.add, rwrepo, "newsubm", "pathtorepo", url=None) # CONTINUE UPDATE ################# # lets update it - its a recursive one too newdir = os.path.join(sm.abspath, 'dir') os.makedirs(newdir) # update fails if the path already exists non-empty self.failUnlessRaises(OSError, sm.update) os.rmdir(newdir) # dry-run does nothing sm.update(dry_run=True, progress=prog) assert not sm.module_exists() assert sm.update() is sm sm_repopath = sm.path # cache for later assert sm.module_exists() assert isinstance(sm.module(), git.Repo) assert sm.module().working_tree_dir == sm.abspath # INTERLEAVE ADD TEST ##################### # url must match the one in the existing repository ( if submodule name suggests a new one ) # or we raise self.failUnlessRaises(ValueError, Submodule.add, rwrepo, "newsubm", sm.path, "git://someurl/repo.git") # CONTINUE UPDATE ################# # we should have setup a tracking branch, which is also active assert sm.module().head.ref.tracking_branch() is not None # delete the whole directory and re-initialize shutil.rmtree(sm.abspath) assert len(sm.children()) == 0 # dry-run does nothing sm.update(dry_run=True, recursive=False, progress=prog) assert len(sm.children()) == 0 sm.update(recursive=False) assert len(list(rwrepo.iter_submodules())) == 2 assert len(sm.children()) == 1 # its not checked out yet csm = sm.children()[0] assert not csm.module_exists() csm_repopath = csm.path # adjust the path of the submodules module to point to the local destination new_csmclone_path = to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path, csm.path)) csm.config_writer().set_value('url', new_csmclone_path) assert csm.url == new_csmclone_path # dry-run does nothing assert not csm.module_exists() sm.update(recursive=True, dry_run=True, progress=prog) assert not csm.module_exists() # update recursively again sm.update(recursive=True) assert csm.module_exists() # tracking branch once again csm.module().head.ref.tracking_branch() is not None # this flushed in a sub-submodule assert len(list(rwrepo.iter_submodules())) == 2 # reset both heads to the previous version, verify that to_latest_revision works smods = (sm.module(), csm.module()) for repo in smods: repo.head.reset('HEAD~2', working_tree=1) # END for each repo to reset # dry run does nothing sm.update(recursive=True, dry_run=True, progress=prog) for repo in smods: assert repo.head.commit != repo.head.ref.tracking_branch().commit # END for each repo to check sm.update(recursive=True, to_latest_revision=True) for repo in smods: assert repo.head.commit == repo.head.ref.tracking_branch().commit # END for each repo to check del(smods) # if the head is detached, it still works ( but warns ) smref = sm.module().head.ref sm.module().head.ref = 'HEAD~1' # if there is no tracking branch, we get a warning as well csm_tracking_branch = csm.module().head.ref.tracking_branch() csm.module().head.ref.set_tracking_branch(None) sm.update(recursive=True, to_latest_revision=True) # to_latest_revision changes the child submodule's commit, it needs an # update now csm.set_parent_commit(csm.repo.head.commit) # undo the changes sm.module().head.ref = smref csm.module().head.ref.set_tracking_branch(csm_tracking_branch) # REMOVAL OF REPOSITOTRY ######################## # must delete something self.failUnlessRaises(ValueError, csm.remove, module=False, configuration=False) # We have modified the configuration, hence the index is dirty, and the # deletion will fail # NOTE: As we did a few updates in the meanwhile, the indices were reset # Hence we create some changes csm.set_parent_commit(csm.repo.head.commit) sm.config_writer().set_value("somekey", "somevalue") csm.config_writer().set_value("okey", "ovalue") self.failUnlessRaises(InvalidGitRepositoryError, sm.remove) # if we remove the dirty index, it would work sm.module().index.reset() # still, we have the file modified self.failUnlessRaises(InvalidGitRepositoryError, sm.remove, dry_run=True) sm.module().index.reset(working_tree=True) # enforce the submodule to be checked out at the right spot as well. csm.update() # this would work assert sm.remove(dry_run=True) is sm assert sm.module_exists() sm.remove(force=True, dry_run=True) assert sm.module_exists() # but ... we have untracked files in the child submodule fn = join_path_native(csm.module().working_tree_dir, "newfile") open(fn, 'w').write("hi") self.failUnlessRaises(InvalidGitRepositoryError, sm.remove) # forcibly delete the child repository prev_count = len(sm.children()) assert csm.remove(force=True) is csm assert not csm.exists() assert not csm.module_exists() assert len(sm.children()) == prev_count - 1 # now we have a changed index, as configuration was altered. # fix this sm.module().index.reset(working_tree=True) # now delete only the module of the main submodule assert sm.module_exists() sm.remove(configuration=False) assert sm.exists() assert not sm.module_exists() assert sm.config_reader().get_value('url') # delete the rest sm.remove() assert not sm.exists() assert not sm.module_exists() assert len(rwrepo.submodules) == 0 # ADD NEW SUBMODULE ################### # add a simple remote repo - trailing slashes are no problem smid = "newsub" osmid = "othersub" nsm = Submodule.add(rwrepo, smid, sm_repopath, new_smclone_path+"/", None, no_checkout=True) assert nsm.name == smid assert nsm.module_exists() assert nsm.exists() # its not checked out assert not os.path.isfile(join_path_native(nsm.module().working_tree_dir, Submodule.k_modules_file)) assert len(rwrepo.submodules) == 1 # add another submodule, but into the root, not as submodule osm = Submodule.add(rwrepo, osmid, csm_repopath, new_csmclone_path, Submodule.k_head_default) assert osm != nsm assert osm.module_exists() assert osm.exists() assert os.path.isfile(join_path_native(osm.module().working_tree_dir, 'setup.py')) assert len(rwrepo.submodules) == 2 # commit the changes, just to finalize the operation rwrepo.index.commit("my submod commit") assert len(rwrepo.submodules) == 2 # needs update as the head changed, it thinks its in the history # of the repo otherwise nsm.set_parent_commit(rwrepo.head.commit) osm.set_parent_commit(rwrepo.head.commit) # MOVE MODULE ############# # invalid inptu self.failUnlessRaises(ValueError, nsm.move, 'doesntmatter', module=False, configuration=False) # renaming to the same path does nothing assert nsm.move(sm.path) is nsm # rename a module nmp = join_path_native("new", "module", "dir") + "/" # new module path pmp = nsm.path abspmp = nsm.abspath assert nsm.move(nmp) is nsm nmp = nmp[:-1] # cut last / nmpl = to_native_path_linux(nmp) assert nsm.path == nmpl assert rwrepo.submodules[0].path == nmpl mpath = 'newsubmodule' absmpath = join_path_native(rwrepo.working_tree_dir, mpath) open(absmpath, 'w').write('') self.failUnlessRaises(ValueError, nsm.move, mpath) os.remove(absmpath) # now it works, as we just move it back nsm.move(pmp) assert nsm.path == pmp assert rwrepo.submodules[0].path == pmp # TODO lowprio: test remaining exceptions ... for now its okay, the code looks right # REMOVE 'EM ALL ################ # if a submodule's repo has no remotes, it can't be added without an explicit url osmod = osm.module() osm.remove(module=False) for remote in osmod.remotes: remote.remove(osmod, remote.name) assert not osm.exists() self.failUnlessRaises(ValueError, Submodule.add, rwrepo, osmid, csm_repopath, url=None) # END handle bare mode # Error if there is no submodule file here self.failUnlessRaises(IOError, Submodule._config_parser, rwrepo, rwrepo.commit(self.k_no_subm_tag), True)
def test_root_module(self, rwrepo): # Can query everything without problems rm = RootModule(self.rorepo) assert rm.module() is self.rorepo # try attributes rm.binsha rm.mode rm.path assert rm.name == rm.k_root_name assert rm.parent_commit == self.rorepo.head.commit rm.url rm.branch assert len(rm.list_items(rm.module())) == 1 rm.config_reader() rm.config_writer() # deep traversal gitdb / async rsmsp = [sm.path for sm in rm.traverse()] assert len(rsmsp) >= 2 # gitdb and async [and smmap], async being a child of gitdb # cannot set the parent commit as root module's path didn't exist self.failUnlessRaises(ValueError, rm.set_parent_commit, 'HEAD') # TEST UPDATE ############# # setup commit which remove existing, add new and modify existing submodules rm = RootModule(rwrepo) assert len(rm.children()) == 1 # modify path without modifying the index entry # ( which is what the move method would do properly ) #================================================== sm = rm.children()[0] pp = "path/prefix" fp = join_path_native(pp, sm.path) prep = sm.path assert not sm.module_exists() # was never updated after rwrepo's clone # assure we clone from a local source sm.config_writer().set_value('url', to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, sm.path))) # dry-run does nothing sm.update(recursive=False, dry_run=True, progress=prog) assert not sm.module_exists() sm.update(recursive=False) assert sm.module_exists() sm.config_writer().set_value('path', fp) # change path to something with prefix AFTER url change # update fails as list_items in such a situations cannot work, as it cannot # find the entry at the changed path self.failUnlessRaises(InvalidGitRepositoryError, rm.update, recursive=False) # move it properly - doesn't work as it its path currently points to an indexentry # which doesn't exist ( move it to some path, it doesn't matter here ) self.failUnlessRaises(InvalidGitRepositoryError, sm.move, pp) # reset the path(cache) to where it was, now it works sm.path = prep sm.move(fp, module=False) # leave it at the old location assert not sm.module_exists() cpathchange = rwrepo.index.commit("changed sm path") # finally we can commit # update puts the module into place rm.update(recursive=False, progress=prog) sm.set_parent_commit(cpathchange) assert sm.module_exists() # add submodule #================ nsmn = "newsubmodule" nsmp = "submrepo" async_url = to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, rsmsp[0], rsmsp[1])) nsm = Submodule.add(rwrepo, nsmn, nsmp, url=async_url) csmadded = rwrepo.index.commit("Added submodule").hexsha # make sure we don't keep the repo reference nsm.set_parent_commit(csmadded) assert nsm.module_exists() # in our case, the module should not exist, which happens if we update a parent # repo and a new submodule comes into life nsm.remove(configuration=False, module=True) assert not nsm.module_exists() and nsm.exists() # dry-run does nothing rm.update(recursive=False, dry_run=True, progress=prog) # otherwise it will work rm.update(recursive=False, progress=prog) assert nsm.module_exists() # remove submodule - the previous one #==================================== sm.set_parent_commit(csmadded) smp = sm.abspath assert not sm.remove(module=False).exists() assert os.path.isdir(smp) # module still exists csmremoved = rwrepo.index.commit("Removed submodule") # an update will remove the module # not in dry_run rm.update(recursive=False, dry_run=True) assert os.path.isdir(smp) rm.update(recursive=False) assert not os.path.isdir(smp) # change url #============= # to the first repository, this way we have a fast checkout, and a completely different # repository at the different url nsm.set_parent_commit(csmremoved) nsmurl = to_native_path_linux(join_path_native(self.rorepo.working_tree_dir, rsmsp[0])) nsm.config_writer().set_value('url', nsmurl) csmpathchange = rwrepo.index.commit("changed url") nsm.set_parent_commit(csmpathchange) prev_commit = nsm.module().head.commit # dry-run does nothing rm.update(recursive=False, dry_run=True, progress=prog) assert nsm.module().remotes.origin.url != nsmurl rm.update(recursive=False, progress=prog) assert nsm.module().remotes.origin.url == nsmurl # head changed, as the remote url and its commit changed assert prev_commit != nsm.module().head.commit # add the submodule's changed commit to the index, which is what the # user would do # beforehand, update our instance's binsha with the new one nsm.binsha = nsm.module().head.commit.binsha rwrepo.index.add([nsm]) # change branch #================= # we only have one branch, so we switch to a virtual one, and back # to the current one to trigger the difference cur_branch = nsm.branch nsmm = nsm.module() prev_commit = nsmm.head.commit for branch in ("some_virtual_branch", cur_branch.name): nsm.config_writer().set_value(Submodule.k_head_option, git.Head.to_full_path(branch)) csmbranchchange = rwrepo.index.commit("changed branch to %s" % branch) nsm.set_parent_commit(csmbranchchange) # END for each branch to change # Lets remove our tracking branch to simulate some changes nsmmh = nsmm.head assert nsmmh.ref.tracking_branch() is None # never set it up until now assert not nsmmh.is_detached #dry run does nothing rm.update(recursive=False, dry_run=True, progress=prog) assert nsmmh.ref.tracking_branch() is None # the real thing does rm.update(recursive=False, progress=prog) assert nsmmh.ref.tracking_branch() is not None assert not nsmmh.is_detached # recursive update # ================= # finally we recursively update a module, just to run the code at least once # remove the module so that it has more work assert len(nsm.children()) >= 1 # could include smmap assert nsm.exists() and nsm.module_exists() and len(nsm.children()) >= 1 # assure we pull locally only nsmc = nsm.children()[0] nsmc.config_writer().set_value('url', async_url) rm.update(recursive=True, progress=prog, dry_run=True) # just to run the code rm.update(recursive=True, progress=prog) # gitdb: has either 1 or 2 submodules depending on the version assert len(nsm.children()) >= 1 and nsmc.module_exists()
def test_root_module(self, rwrepo): # Can query everything without problems rm = RootModule(self.rorepo) assert rm.module() is self.rorepo # try attributes rm.binsha rm.mode rm.path assert rm.name == rm.k_root_name assert rm.parent_commit == self.rorepo.head.commit rm.url rm.branch assert len(rm.list_items(rm.module())) == 1 rm.config_reader() with rm.config_writer(): pass # deep traversal gitdb / async rsmsp = [sm.path for sm in rm.traverse()] assert len(rsmsp) >= 2 # gitdb and async [and smmap], async being a child of gitdb # cannot set the parent commit as root module's path didn't exist self.failUnlessRaises(ValueError, rm.set_parent_commit, 'HEAD') # TEST UPDATE ############# # setup commit which remove existing, add new and modify existing submodules rm = RootModule(rwrepo) assert len(rm.children()) == 1 # modify path without modifying the index entry # ( which is what the move method would do properly ) #================================================== sm = rm.children()[0] pp = "path/prefix" fp = join_path_native(pp, sm.path) prep = sm.path assert not sm.module_exists() # was never updated after rwrepo's clone # assure we clone from a local source with sm.config_writer() as writer: writer.set_value('url', Git.polish_url(osp.join(self.rorepo.working_tree_dir, sm.path))) # dry-run does nothing sm.update(recursive=False, dry_run=True, progress=prog) assert not sm.module_exists() sm.update(recursive=False) assert sm.module_exists() with sm.config_writer() as writer: writer.set_value('path', fp) # change path to something with prefix AFTER url change # update fails as list_items in such a situations cannot work, as it cannot # find the entry at the changed path self.failUnlessRaises(InvalidGitRepositoryError, rm.update, recursive=False) # move it properly - doesn't work as it its path currently points to an indexentry # which doesn't exist ( move it to some path, it doesn't matter here ) self.failUnlessRaises(InvalidGitRepositoryError, sm.move, pp) # reset the path(cache) to where it was, now it works sm.path = prep sm.move(fp, module=False) # leave it at the old location assert not sm.module_exists() cpathchange = rwrepo.index.commit("changed sm path") # finally we can commit # update puts the module into place rm.update(recursive=False, progress=prog) sm.set_parent_commit(cpathchange) assert sm.module_exists() # add submodule #================ nsmn = "newsubmodule" nsmp = "submrepo" subrepo_url = Git.polish_url(osp.join(self.rorepo.working_tree_dir, rsmsp[0], rsmsp[1])) nsm = Submodule.add(rwrepo, nsmn, nsmp, url=subrepo_url) csmadded = rwrepo.index.commit("Added submodule").hexsha # make sure we don't keep the repo reference nsm.set_parent_commit(csmadded) assert nsm.module_exists() # in our case, the module should not exist, which happens if we update a parent # repo and a new submodule comes into life nsm.remove(configuration=False, module=True) assert not nsm.module_exists() and nsm.exists() # dry-run does nothing rm.update(recursive=False, dry_run=True, progress=prog) # otherwise it will work rm.update(recursive=False, progress=prog) assert nsm.module_exists() # remove submodule - the previous one #==================================== sm.set_parent_commit(csmadded) smp = sm.abspath assert not sm.remove(module=False).exists() assert osp.isdir(smp) # module still exists csmremoved = rwrepo.index.commit("Removed submodule") # an update will remove the module # not in dry_run rm.update(recursive=False, dry_run=True, force_remove=True) assert osp.isdir(smp) # when removing submodules, we may get new commits as nested submodules are auto-committing changes # to allow deletions without force, as the index would be dirty otherwise. # QUESTION: Why does this seem to work in test_git_submodule_compatibility() ? self.failUnlessRaises(InvalidGitRepositoryError, rm.update, recursive=False, force_remove=False) rm.update(recursive=False, force_remove=True) assert not osp.isdir(smp) # 'apply work' to the nested submodule and assure this is not removed/altered during updates # Need to commit first, otherwise submodule.update wouldn't have a reason to change the head touch(osp.join(nsm.module().working_tree_dir, 'new-file')) # We cannot expect is_dirty to even run as we wouldn't reset a head to the same location assert nsm.module().head.commit.hexsha == nsm.hexsha nsm.module().index.add([nsm]) nsm.module().index.commit("added new file") rm.update(recursive=False, dry_run=True, progress=prog) # would not change head, and thus doens't fail # Everything we can do from now on will trigger the 'future' check, so no is_dirty() check will even run # This would only run if our local branch is in the past and we have uncommitted changes prev_commit = nsm.module().head.commit rm.update(recursive=False, dry_run=False, progress=prog) assert prev_commit == nsm.module().head.commit, "head shouldn't change, as it is in future of remote branch" # this kills the new file rm.update(recursive=True, progress=prog, force_reset=True) assert prev_commit != nsm.module().head.commit, "head changed, as the remote url and its commit changed" # change url ... #=============== # ... to the first repository, this way we have a fast checkout, and a completely different # repository at the different url nsm.set_parent_commit(csmremoved) nsmurl = Git.polish_url(osp.join(self.rorepo.working_tree_dir, rsmsp[0])) with nsm.config_writer() as writer: writer.set_value('url', nsmurl) csmpathchange = rwrepo.index.commit("changed url") nsm.set_parent_commit(csmpathchange) # Now nsm head is in the future of the tracked remote branch prev_commit = nsm.module().head.commit # dry-run does nothing rm.update(recursive=False, dry_run=True, progress=prog) assert nsm.module().remotes.origin.url != nsmurl rm.update(recursive=False, progress=prog, force_reset=True) assert nsm.module().remotes.origin.url == nsmurl assert prev_commit != nsm.module().head.commit, "Should now point to gitdb" assert len(rwrepo.submodules) == 1 assert not rwrepo.submodules[0].children()[0].module_exists(), "nested submodule should not be checked out" # add the submodule's changed commit to the index, which is what the # user would do # beforehand, update our instance's binsha with the new one nsm.binsha = nsm.module().head.commit.binsha rwrepo.index.add([nsm]) # change branch #================= # we only have one branch, so we switch to a virtual one, and back # to the current one to trigger the difference cur_branch = nsm.branch nsmm = nsm.module() prev_commit = nsmm.head.commit for branch in ("some_virtual_branch", cur_branch.name): with nsm.config_writer() as writer: writer.set_value(Submodule.k_head_option, git.Head.to_full_path(branch)) csmbranchchange = rwrepo.index.commit("changed branch to %s" % branch) nsm.set_parent_commit(csmbranchchange) # END for each branch to change # Lets remove our tracking branch to simulate some changes nsmmh = nsmm.head assert nsmmh.ref.tracking_branch() is None # never set it up until now assert not nsmmh.is_detached # dry run does nothing rm.update(recursive=False, dry_run=True, progress=prog) assert nsmmh.ref.tracking_branch() is None # the real thing does rm.update(recursive=False, progress=prog) assert nsmmh.ref.tracking_branch() is not None assert not nsmmh.is_detached # recursive update # ================= # finally we recursively update a module, just to run the code at least once # remove the module so that it has more work assert len(nsm.children()) >= 1 # could include smmap assert nsm.exists() and nsm.module_exists() and len(nsm.children()) >= 1 # assure we pull locally only nsmc = nsm.children()[0] with nsmc.config_writer() as writer: writer.set_value('url', subrepo_url) rm.update(recursive=True, progress=prog, dry_run=True) # just to run the code rm.update(recursive=True, progress=prog) # gitdb: has either 1 or 2 submodules depending on the version assert len(nsm.children()) >= 1 and nsmc.module_exists()
def create_submodule(self, *args, **kwargs): return Submodule.add(self, *args, **kwargs)
def submodules(self): return Submodule.list_items(self)
def test_root_module(self, rwrepo): # Can query everything without problems rm = RootModule(self.rorepo) assert rm.module() is self.rorepo # try attributes rm.binsha rm.mode rm.path assert rm.name == rm.k_root_name assert rm.parent_commit == self.rorepo.head.commit rm.url rm.branch assert len(rm.list_items(rm.module())) == 1 rm.config_reader() with rm.config_writer(): pass # deep traversal gitdb / async rsmsp = [sm.path for sm in rm.traverse()] assert len( rsmsp ) >= 2 # gitdb and async [and smmap], async being a child of gitdb # cannot set the parent commit as root module's path didn't exist self.failUnlessRaises(ValueError, rm.set_parent_commit, 'HEAD') # TEST UPDATE ############# # setup commit which remove existing, add new and modify existing submodules rm = RootModule(rwrepo) assert len(rm.children()) == 1 # modify path without modifying the index entry # ( which is what the move method would do properly ) #================================================== sm = rm.children()[0] pp = "path/prefix" fp = join_path_native(pp, sm.path) prep = sm.path assert not sm.module_exists() # was never updated after rwrepo's clone # assure we clone from a local source with sm.config_writer() as writer: writer.set_value( 'url', Git.polish_url(osp.join(self.rorepo.working_tree_dir, sm.path))) # dry-run does nothing sm.update(recursive=False, dry_run=True, progress=prog) assert not sm.module_exists() sm.update(recursive=False) assert sm.module_exists() with sm.config_writer() as writer: writer.set_value( 'path', fp) # change path to something with prefix AFTER url change # update doesn't fail, because list_items ignores the wrong path in such situations. rm.update(recursive=False) # move it properly - doesn't work as it its path currently points to an indexentry # which doesn't exist ( move it to some path, it doesn't matter here ) self.failUnlessRaises(InvalidGitRepositoryError, sm.move, pp) # reset the path(cache) to where it was, now it works sm.path = prep sm.move(fp, module=False) # leave it at the old location assert not sm.module_exists() cpathchange = rwrepo.index.commit( "changed sm path") # finally we can commit # update puts the module into place rm.update(recursive=False, progress=prog) sm.set_parent_commit(cpathchange) assert sm.module_exists() # add submodule #================ nsmn = "newsubmodule" nsmp = "submrepo" subrepo_url = Git.polish_url( osp.join(self.rorepo.working_tree_dir, rsmsp[0], rsmsp[1])) nsm = Submodule.add(rwrepo, nsmn, nsmp, url=subrepo_url) csmadded = rwrepo.index.commit( "Added submodule" ).hexsha # make sure we don't keep the repo reference nsm.set_parent_commit(csmadded) assert nsm.module_exists() # in our case, the module should not exist, which happens if we update a parent # repo and a new submodule comes into life nsm.remove(configuration=False, module=True) assert not nsm.module_exists() and nsm.exists() # dry-run does nothing rm.update(recursive=False, dry_run=True, progress=prog) # otherwise it will work rm.update(recursive=False, progress=prog) assert nsm.module_exists() # remove submodule - the previous one #==================================== sm.set_parent_commit(csmadded) smp = sm.abspath assert not sm.remove(module=False).exists() assert osp.isdir(smp) # module still exists csmremoved = rwrepo.index.commit("Removed submodule") # an update will remove the module # not in dry_run rm.update(recursive=False, dry_run=True, force_remove=True) assert osp.isdir(smp) # when removing submodules, we may get new commits as nested submodules are auto-committing changes # to allow deletions without force, as the index would be dirty otherwise. # QUESTION: Why does this seem to work in test_git_submodule_compatibility() ? self.failUnlessRaises(InvalidGitRepositoryError, rm.update, recursive=False, force_remove=False) rm.update(recursive=False, force_remove=True) assert not osp.isdir(smp) # 'apply work' to the nested submodule and assure this is not removed/altered during updates # Need to commit first, otherwise submodule.update wouldn't have a reason to change the head touch(osp.join(nsm.module().working_tree_dir, 'new-file')) # We cannot expect is_dirty to even run as we wouldn't reset a head to the same location assert nsm.module().head.commit.hexsha == nsm.hexsha nsm.module().index.add([nsm]) nsm.module().index.commit("added new file") rm.update( recursive=False, dry_run=True, progress=prog) # would not change head, and thus doens't fail # Everything we can do from now on will trigger the 'future' check, so no is_dirty() check will even run # This would only run if our local branch is in the past and we have uncommitted changes prev_commit = nsm.module().head.commit rm.update(recursive=False, dry_run=False, progress=prog) assert prev_commit == nsm.module( ).head.commit, "head shouldn't change, as it is in future of remote branch" # this kills the new file rm.update(recursive=True, progress=prog, force_reset=True) assert prev_commit != nsm.module( ).head.commit, "head changed, as the remote url and its commit changed" # change url ... #=============== # ... to the first repository, this way we have a fast checkout, and a completely different # repository at the different url nsm.set_parent_commit(csmremoved) nsmurl = Git.polish_url( osp.join(self.rorepo.working_tree_dir, rsmsp[0])) with nsm.config_writer() as writer: writer.set_value('url', nsmurl) csmpathchange = rwrepo.index.commit("changed url") nsm.set_parent_commit(csmpathchange) # Now nsm head is in the future of the tracked remote branch prev_commit = nsm.module().head.commit # dry-run does nothing rm.update(recursive=False, dry_run=True, progress=prog) assert nsm.module().remotes.origin.url != nsmurl rm.update(recursive=False, progress=prog, force_reset=True) assert nsm.module().remotes.origin.url == nsmurl assert prev_commit != nsm.module( ).head.commit, "Should now point to gitdb" assert len(rwrepo.submodules) == 1 assert not rwrepo.submodules[0].children()[0].module_exists( ), "nested submodule should not be checked out" # add the submodule's changed commit to the index, which is what the # user would do # beforehand, update our instance's binsha with the new one nsm.binsha = nsm.module().head.commit.binsha rwrepo.index.add([nsm]) # change branch #================= # we only have one branch, so we switch to a virtual one, and back # to the current one to trigger the difference cur_branch = nsm.branch nsmm = nsm.module() prev_commit = nsmm.head.commit for branch in ("some_virtual_branch", cur_branch.name): with nsm.config_writer() as writer: writer.set_value(Submodule.k_head_option, git.Head.to_full_path(branch)) csmbranchchange = rwrepo.index.commit("changed branch to %s" % branch) nsm.set_parent_commit(csmbranchchange) # END for each branch to change # Lets remove our tracking branch to simulate some changes nsmmh = nsmm.head assert nsmmh.ref.tracking_branch() is None # never set it up until now assert not nsmmh.is_detached # dry run does nothing rm.update(recursive=False, dry_run=True, progress=prog) assert nsmmh.ref.tracking_branch() is None # the real thing does rm.update(recursive=False, progress=prog) assert nsmmh.ref.tracking_branch() is not None assert not nsmmh.is_detached # recursive update # ================= # finally we recursively update a module, just to run the code at least once # remove the module so that it has more work assert len(nsm.children()) >= 1 # could include smmap assert nsm.exists() and nsm.module_exists() and len( nsm.children()) >= 1 # assure we pull locally only nsmc = nsm.children()[0] with nsmc.config_writer() as writer: writer.set_value('url', subrepo_url) rm.update(recursive=True, progress=prog, dry_run=True) # just to run the code rm.update(recursive=True, progress=prog) # gitdb: has either 1 or 2 submodules depending on the version assert len(nsm.children()) >= 1 and nsmc.module_exists()
def _do_base_tests(self, rwrepo): """Perform all tests in the given repository, it may be bare or nonbare""" # manual instantiation smm = Submodule(rwrepo, "\0" * 20) # name needs to be set in advance self.failUnlessRaises(AttributeError, getattr, smm, 'name') # iterate - 1 submodule sms = Submodule.list_items(rwrepo, self.k_subm_current) assert len(sms) == 1 sm = sms[0] # at a different time, there is None assert len(Submodule.list_items(rwrepo, self.k_no_subm_tag)) == 0 assert sm.path == 'git/ext/gitdb' assert sm.path != sm.name # in our case, we have ids there, which don't equal the path assert sm.url.endswith('github.com/gitpython-developers/gitdb.git') assert sm.branch_path == 'refs/heads/master' # the default ... assert sm.branch_name == 'master' assert sm.parent_commit == rwrepo.head.commit # size is always 0 assert sm.size == 0 # the module is not checked-out yet self.failUnlessRaises(InvalidGitRepositoryError, sm.module) # which is why we can't get the branch either - it points into the module() repository self.failUnlessRaises(InvalidGitRepositoryError, getattr, sm, 'branch') # branch_path works, as its just a string assert isinstance(sm.branch_path, str) # some commits earlier we still have a submodule, but its at a different commit smold = next(Submodule.iter_items(rwrepo, self.k_subm_changed)) assert smold.binsha != sm.binsha assert smold != sm # the name changed # force it to reread its information del (smold._url) smold.url == sm.url # @NoEffect # test config_reader/writer methods sm.config_reader() new_smclone_path = None # keep custom paths for later new_csmclone_path = None # if rwrepo.bare: with self.assertRaises(InvalidGitRepositoryError): with sm.config_writer() as cw: pass else: with sm.config_writer() as writer: # for faster checkout, set the url to the local path new_smclone_path = Git.polish_url( osp.join(self.rorepo.working_tree_dir, sm.path)) writer.set_value('url', new_smclone_path) writer.release() assert sm.config_reader().get_value('url') == new_smclone_path assert sm.url == new_smclone_path # END handle bare repo smold.config_reader() # cannot get a writer on historical submodules if not rwrepo.bare: with self.assertRaises(ValueError): with smold.config_writer(): pass # END handle bare repo # make the old into a new - this doesn't work as the name changed self.failUnlessRaises(ValueError, smold.set_parent_commit, self.k_subm_current) # the sha is properly updated smold.set_parent_commit(self.k_subm_changed + "~1") assert smold.binsha != sm.binsha # raises if the sm didn't exist in new parent - it keeps its # parent_commit unchanged self.failUnlessRaises(ValueError, smold.set_parent_commit, self.k_no_subm_tag) # TEST TODO: if a path in the gitmodules file, but not in the index, it raises # TEST UPDATE ############## # module retrieval is not always possible if rwrepo.bare: self.failUnlessRaises(InvalidGitRepositoryError, sm.module) self.failUnlessRaises(InvalidGitRepositoryError, sm.remove) self.failUnlessRaises(InvalidGitRepositoryError, sm.add, rwrepo, 'here', 'there') else: # its not checked out in our case self.failUnlessRaises(InvalidGitRepositoryError, sm.module) assert not sm.module_exists() # currently there is only one submodule assert len(list(rwrepo.iter_submodules())) == 1 assert sm.binsha != "\0" * 20 # TEST ADD ########### # preliminary tests # adding existing returns exactly the existing sma = Submodule.add(rwrepo, sm.name, sm.path) assert sma.path == sm.path # no url and no module at path fails self.failUnlessRaises(ValueError, Submodule.add, rwrepo, "newsubm", "pathtorepo", url=None) # CONTINUE UPDATE ################# # lets update it - its a recursive one too newdir = osp.join(sm.abspath, 'dir') os.makedirs(newdir) # update fails if the path already exists non-empty self.failUnlessRaises(OSError, sm.update) os.rmdir(newdir) # dry-run does nothing sm.update(dry_run=True, progress=prog) assert not sm.module_exists() assert sm.update() is sm sm_repopath = sm.path # cache for later assert sm.module_exists() assert isinstance(sm.module(), git.Repo) assert sm.module().working_tree_dir == sm.abspath # INTERLEAVE ADD TEST ##################### # url must match the one in the existing repository ( if submodule name suggests a new one ) # or we raise self.failUnlessRaises(ValueError, Submodule.add, rwrepo, "newsubm", sm.path, "git://someurl/repo.git") # CONTINUE UPDATE ################# # we should have setup a tracking branch, which is also active assert sm.module().head.ref.tracking_branch() is not None # delete the whole directory and re-initialize assert len(sm.children()) != 0 # shutil.rmtree(sm.abspath) sm.remove(force=True, configuration=False) assert len(sm.children()) == 0 # dry-run does nothing sm.update(dry_run=True, recursive=False, progress=prog) assert len(sm.children()) == 0 sm.update(recursive=False) assert len(list(rwrepo.iter_submodules())) == 2 assert len(sm.children()) == 1 # its not checked out yet csm = sm.children()[0] assert not csm.module_exists() csm_repopath = csm.path # adjust the path of the submodules module to point to the local destination new_csmclone_path = Git.polish_url( osp.join(self.rorepo.working_tree_dir, sm.path, csm.path)) with csm.config_writer() as writer: writer.set_value('url', new_csmclone_path) assert csm.url == new_csmclone_path # dry-run does nothing assert not csm.module_exists() sm.update(recursive=True, dry_run=True, progress=prog) assert not csm.module_exists() # update recursively again sm.update(recursive=True) assert csm.module_exists() # tracking branch once again csm.module().head.ref.tracking_branch() is not None # @NoEffect # this flushed in a sub-submodule assert len(list(rwrepo.iter_submodules())) == 2 # reset both heads to the previous version, verify that to_latest_revision works smods = (sm.module(), csm.module()) for repo in smods: repo.head.reset('HEAD~2', working_tree=1) # END for each repo to reset # dry run does nothing self.failUnlessRaises(RepositoryDirtyError, sm.update, recursive=True, dry_run=True, progress=prog) sm.update(recursive=True, dry_run=True, progress=prog, force=True) for repo in smods: assert repo.head.commit != repo.head.ref.tracking_branch( ).commit # END for each repo to check self.failUnlessRaises(RepositoryDirtyError, sm.update, recursive=True, to_latest_revision=True) sm.update(recursive=True, to_latest_revision=True, force=True) for repo in smods: assert repo.head.commit == repo.head.ref.tracking_branch( ).commit # END for each repo to check del (smods) # if the head is detached, it still works ( but warns ) smref = sm.module().head.ref sm.module().head.ref = 'HEAD~1' # if there is no tracking branch, we get a warning as well csm_tracking_branch = csm.module().head.ref.tracking_branch() csm.module().head.ref.set_tracking_branch(None) sm.update(recursive=True, to_latest_revision=True) # to_latest_revision changes the child submodule's commit, it needs an # update now csm.set_parent_commit(csm.repo.head.commit) # undo the changes sm.module().head.ref = smref csm.module().head.ref.set_tracking_branch(csm_tracking_branch) # REMOVAL OF REPOSITOTRY ######################## # must delete something self.failUnlessRaises(ValueError, csm.remove, module=False, configuration=False) # module() is supposed to point to gitdb, which has a child-submodule whose URL is still pointing # to GitHub. To save time, we will change it to csm.set_parent_commit(csm.repo.head.commit) with csm.config_writer() as cw: cw.set_value('url', self._small_repo_url()) csm.repo.index.commit( "adjusted URL to point to local source, instead of the internet" ) # We have modified the configuration, hence the index is dirty, and the # deletion will fail # NOTE: As we did a few updates in the meanwhile, the indices were reset # Hence we create some changes csm.set_parent_commit(csm.repo.head.commit) with sm.config_writer() as writer: writer.set_value("somekey", "somevalue") with csm.config_writer() as writer: writer.set_value("okey", "ovalue") self.failUnlessRaises(InvalidGitRepositoryError, sm.remove) # if we remove the dirty index, it would work sm.module().index.reset() # still, we have the file modified self.failUnlessRaises(InvalidGitRepositoryError, sm.remove, dry_run=True) sm.module().index.reset(working_tree=True) # enforce the submodule to be checked out at the right spot as well. csm.update() assert csm.module_exists() assert csm.exists() assert osp.isdir(csm.module().working_tree_dir) # this would work assert sm.remove(force=True, dry_run=True) is sm assert sm.module_exists() sm.remove(force=True, dry_run=True) assert sm.module_exists() # but ... we have untracked files in the child submodule fn = join_path_native(csm.module().working_tree_dir, "newfile") with open(fn, 'w') as fd: fd.write("hi") self.failUnlessRaises(InvalidGitRepositoryError, sm.remove) # forcibly delete the child repository prev_count = len(sm.children()) self.failUnlessRaises(ValueError, csm.remove, force=True) # We removed sm, which removed all submodules. However, the instance we # have still points to the commit prior to that, where it still existed csm.set_parent_commit(csm.repo.commit(), check=False) assert not csm.exists() assert not csm.module_exists() assert len(sm.children()) == prev_count # now we have a changed index, as configuration was altered. # fix this sm.module().index.reset(working_tree=True) # now delete only the module of the main submodule assert sm.module_exists() sm.remove(configuration=False, force=True) assert sm.exists() assert not sm.module_exists() assert sm.config_reader().get_value('url') # delete the rest sm_path = sm.path sm.remove() assert not sm.exists() assert not sm.module_exists() self.failUnlessRaises(ValueError, getattr, sm, 'path') assert len(rwrepo.submodules) == 0 # ADD NEW SUBMODULE ################### # add a simple remote repo - trailing slashes are no problem smid = "newsub" osmid = "othersub" nsm = Submodule.add(rwrepo, smid, sm_repopath, new_smclone_path + "/", None, no_checkout=True) assert nsm.name == smid assert nsm.module_exists() assert nsm.exists() # its not checked out assert not osp.isfile( join_path_native(nsm.module().working_tree_dir, Submodule.k_modules_file)) assert len(rwrepo.submodules) == 1 # add another submodule, but into the root, not as submodule osm = Submodule.add(rwrepo, osmid, csm_repopath, new_csmclone_path, Submodule.k_head_default) assert osm != nsm assert osm.module_exists() assert osm.exists() assert osp.isfile( join_path_native(osm.module().working_tree_dir, 'setup.py')) assert len(rwrepo.submodules) == 2 # commit the changes, just to finalize the operation rwrepo.index.commit("my submod commit") assert len(rwrepo.submodules) == 2 # needs update as the head changed, it thinks its in the history # of the repo otherwise nsm.set_parent_commit(rwrepo.head.commit) osm.set_parent_commit(rwrepo.head.commit) # MOVE MODULE ############# # invalid input self.failUnlessRaises(ValueError, nsm.move, 'doesntmatter', module=False, configuration=False) # renaming to the same path does nothing assert nsm.move(sm_path) is nsm # rename a module nmp = join_path_native("new", "module", "dir") + "/" # new module path pmp = nsm.path assert nsm.move(nmp) is nsm nmp = nmp[:-1] # cut last / nmpl = to_native_path_linux(nmp) assert nsm.path == nmpl assert rwrepo.submodules[0].path == nmpl mpath = 'newsubmodule' absmpath = join_path_native(rwrepo.working_tree_dir, mpath) open(absmpath, 'w').write('') self.failUnlessRaises(ValueError, nsm.move, mpath) os.remove(absmpath) # now it works, as we just move it back nsm.move(pmp) assert nsm.path == pmp assert rwrepo.submodules[0].path == pmp # REMOVE 'EM ALL ################ # if a submodule's repo has no remotes, it can't be added without an explicit url osmod = osm.module() osm.remove(module=False) for remote in osmod.remotes: remote.remove(osmod, remote.name) assert not osm.exists() self.failUnlessRaises(ValueError, Submodule.add, rwrepo, osmid, csm_repopath, url=None) # END handle bare mode # Error if there is no submodule file here self.failUnlessRaises(IOError, Submodule._config_parser, rwrepo, rwrepo.commit(self.k_no_subm_tag), True)
def test_root_module(self, rwrepo): # Can query everything without problems rm = RootModule(rwrepo) # test new constructor assert rm.parent_commit == RootModule( self.rorepo, self.rorepo.commit(self.k_subm_current)).parent_commit assert rm.module() is rwrepo # try attributes rm.binsha rm.mode rm.path assert rm.name == rm.k_root_name assert rm.parent_commit == self.rorepo.commit(self.k_subm_current) rm.url rm.branch assert len(rm.list_items(rm.module())) == 1 rm.config_reader() rm.config_writer() # deep traversal git / async rsmsp = [sm.path for sm in rm.traverse()] assert len( rsmsp ) == 1 # gitdb only - its not yet uptodate so it has no submodule # cannot set the parent commit as root module's path didn't exist self.failUnlessRaises(ValueError, rm.set_parent_commit, 'HEAD') # TEST UPDATE ############# # setup commit which remove existing, add new and modify existing submodules rm = RootModule(rwrepo) assert len(rm.children()) == 1 # modify path without modifying the index entry # ( which is what the move method would do properly ) #================================================== sm = rm.children()[0] pp = "path/prefix" fp = join_path_native(pp, sm.path) prep = sm.path assert not sm.module_exists() # was never updated after rwrepo's clone # assure we clone from a local source self._rewrite_gitdb_to_local_path(sm) # dry-run does nothing sm.update(recursive=False, dry_run=True, progress=prog) assert not sm.module_exists() sm.update(recursive=False) assert sm.module_exists() sm.config_writer().set_value( 'path', fp) # change path to something with prefix AFTER url change # update fails as list_items in such a situations cannot work, as it cannot # find the entry at the changed path self.failUnlessRaises(InvalidGitRepositoryError, rm.update, recursive=False) # move it properly - doesn't work as it its path currently points to an indexentry # which doesn't exist ( move it to some path, it doesn't matter here ) self.failUnlessRaises(InvalidGitRepositoryError, sm.move, pp) # reset the path(cache) to where it was, now it works sm.path = prep sm.move(fp, module=False) # leave it at the old location assert not sm.module_exists() cpathchange = rwrepo.index.commit( "changed sm path") # finally we can commit # update puts the module into place rm.update(recursive=False, progress=prog) sm.set_parent_commit(cpathchange) assert sm.module_exists() # add submodule #================ nsmn = "newsubmodule" nsmp = "submrepo" async_url = self._generate_async_local_path() nsm = Submodule.add(rwrepo, nsmn, nsmp, url=async_url) csmadded = rwrepo.index.commit( "Added submodule" ).hexsha # make sure we don't keep the repo reference nsm.set_parent_commit(csmadded) assert nsm.module_exists() # in our case, the module should not exist, which happens if we update a parent # repo and a new submodule comes into life nsm.remove(configuration=False, module=True) assert not nsm.module_exists() and nsm.exists() # dry-run does nothing rm.update(recursive=False, dry_run=True, progress=prog) # otherwise it will work rm.update(recursive=False, progress=prog) assert nsm.module_exists() # remove submodule - the previous one #==================================== sm.set_parent_commit(csmadded) smp = sm.abspath assert not sm.remove(module=False).exists() assert os.path.isdir(smp) # module still exists csmremoved = rwrepo.index.commit("Removed submodule") # an update will remove the module # not in dry_run rm.update(recursive=False, dry_run=True) assert os.path.isdir(smp) rm.update(recursive=False) assert not os.path.isdir(smp) # change url #============= # to the first repository, this way we have a fast checkout, and a completely different # repository at the different url nsm.set_parent_commit(csmremoved) nsmurl = os.environ.get(self.env_gitdb_local_path, self.k_github_gitdb_url) # Note: We would have liked to have a different url, but we cannot # provoke this case assert nsm.url != nsmurl nsm.config_writer().set_value('url', nsmurl) csmpathchange = rwrepo.index.commit("changed url") nsm.set_parent_commit(csmpathchange) prev_commit = nsm.module().head.commit # dry-run does nothing rm.update(recursive=False, dry_run=True, progress=prog) assert nsm.module().remotes.origin.url != nsmurl rm.update(recursive=False, progress=prog) assert nsm.module().remotes.origin.url == nsmurl # head changed, as the remote url and its commit changed assert prev_commit != nsm.module().head.commit # add the submodule's changed commit to the index, which is what the # user would do # beforehand, update our instance's binsha with the new one nsm.binsha = nsm.module().head.commit.binsha rwrepo.index.add([nsm]) # change branch #================= # we only have one branch, so we switch to a virtual one, and back # to the current one to trigger the difference cur_branch = nsm.branch nsmm = nsm.module() prev_commit = nsmm.head.commit for branch in ("some_virtual_branch", cur_branch.name): nsm.config_writer().set_value(Submodule.k_head_option, git.Head.to_full_path(branch)) csmbranchchange = rwrepo.index.commit("changed branch to %s" % branch) nsm.set_parent_commit(csmbranchchange) # END for each branch to change # Lets remove our tracking branch to simulate some changes nsmmh = nsmm.head assert nsmmh.ref.tracking_branch() is None # never set it up until now assert not nsmmh.is_detached #dry run does nothing rm.update(recursive=False, dry_run=True, progress=prog) assert nsmmh.ref.tracking_branch() is None # the real thing does rm.update(recursive=False, progress=prog) assert nsmmh.ref.tracking_branch() is not None assert not nsmmh.is_detached # recursive update # ================= # finally we recursively update a module, just to run the code at least once # remove the module so that it has more work assert len(nsm.children()) >= 1 # could include smmap assert nsm.exists() and nsm.module_exists() and len( nsm.children()) >= 1 # assure we pull locally only nsmc = nsm.children()[0] nsmc.config_writer().set_value('url', async_url) rm.update(recursive=True, progress=prog, dry_run=True) # just to run the code rm.update(recursive=True, progress=prog) assert len(nsm.children()) >= 2 and nsmc.module_exists()