Exemplo n.º 1
0
    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)

            # 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
            assert csm.remove(force=True) is csm
            assert not csm.exists()
            assert not csm.module_exists()
            assert len(sm.children()) == 0
            # 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 /
            assert nsm.path == nmp
            assert rwrepo.submodules[0].path == nmp

            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)