Example #1
0
def test_paths(tmpdir, HOME):
    from homely._utils import isnecessarypath
    l1 = os.path.join(tmpdir, 'link1')
    d1 = os.path.join(tmpdir, 'dir1')
    d1s = os.path.join(d1, 'subdir')
    l1s = os.path.join(l1, 'subdir')

    os.mkdir(d1)
    os.mkdir(d1s)
    os.symlink(d1, l1)
    assert os.path.isdir(l1s)

    assert isnecessarypath(tmpdir, d1)
    assert isnecessarypath(tmpdir, l1)
    assert isnecessarypath(l1, l1s)
    assert isnecessarypath(d1, l1s)
    assert not isnecessarypath(d1, l1)
Example #2
0
    def _trycleanpath(self, path, type_, conflicts):
        def _discard():
            note("    Forgetting about %s %s" % (type_, path))
            self._old_paths_owned.pop(path)
            self._postponed.discard(path)
            self._created.discard(path)
            self._savecfg()

        def _remove():
            # remove the thing
            if type_ == self.TYPE_FOLDER_ONLY:
                # TODO: what do we do if the folder isn't empty?
                with note("Removing dir %s" % path):
                    try:
                        os.rmdir(path)
                    except OSError as err:
                        from errno import ENOTEMPTY
                        if err.errno == ENOTEMPTY:
                            warn("Directory not empty: {}".format(path))
                        else:
                            raise
            elif type_ == self.TYPE_FILE_ALL:
                note("Removing {}".format(path))
                os.unlink(path)
            elif type_ == self.TYPE_FILE_PART:
                if os.stat(path).st_size == 0:
                    note("Removing empty {}".format(path))
                    os.unlink(path)
                else:
                    note("Refusing to remove non-empty {}".format(path))
            else:
                note("Removing link {}".format(path))
                os.unlink(path)
            _discard()

        def _postpone():
            with note("Postponing cleanup of path: {}".format(path)):
                self._postponed.add(path)
                assert path not in self._new_paths_owned
                self._new_paths_owned[path] = type_
                self._old_paths_owned.pop(path)
                self._savecfg()

        # if we didn't create the path, then we don't need to clean it up
        if path not in self._created:
            return _discard()

        # if the path no longer exists, we have nothing to do
        if not _exists(path):
            return _discard()

        # if the thing has the wrong type, we'll issue an note() and just skip
        if type_ in (self.TYPE_FILE_PART, self.TYPE_FILE_ALL):
            correcttype = os.path.isfile(path)
        elif type_ in (self.TYPE_FOLDER_ONLY, self.TYPE_FOLDER_ALL):
            correcttype = os.path.isdir(path)
        else:
            assert type_ == self.TYPE_LINK
            correcttype = os.path.islink(path)
        if not correcttype:
            with note("Ignoring: Won't remove {} as it is no longer a {}"
                      .format(path, type_)):
                return _discard()

        # work out if there is another path we need to remove first
        for otherpath in self._old_paths_owned:
            if otherpath != path and isnecessarypath(path, otherpath):
                # If there's another path we need to do first, then don't do
                # anything just yet. NOTE: there is an assertion to ensure that
                # we can't get stuck in an infinite loop repeatedly not
                # removing things.
                return

        # if any helpers want the path, don't delete it
        wantedby = None
        for c in self._new_cleaners:
            if c.wantspath(path):
                wantedby = c
                break

        if not wantedby:
            for otherpath in self._new_paths_owned:
                if isnecessarypath(path, otherpath):
                    wantedby = otherpath

        if wantedby:
            # if we previously postponed this path, keep postponing it
            # while there are still things hanging around that want it
            if path in self._postponed:
                return _postpone()
            if conflicts == self.ASK:
                raise Exception("TODO: ask the user what to do")  # noqa
                # NOTE: options are:
                # A) postpone until it can run later
                # B) discard it
            if conflicts == self.RAISE:
                raise CleanupConflict(conflictpath=path, pathwanter=wantedby)
            if conflicts == self.POSTPONE:
                return _postpone()
            assert conflicts == self.WARN
            warn("Couldn't clean up path {}; it is still needed for {}"
                 .format(path, wantedby))
            return _discard()

        # if nothing else wants this path, clean it up now
        return _remove()
Example #3
0
 def affectspath(self, path):
     return isnecessarypath(self._real_clone_to, path)
Example #4
0
 def wantspath(self, path):
     return path == self._filename or isnecessarypath(path, self._filename)
Example #5
0
 def affectspath(self, path):
     return isnecessarypath(self._real_clone_to, path)