Пример #1
0
    def test_force_sync_directory_symlink(self):
        """Test a forced sync on a directory symlink.

        A bug was reported where a user wanted to replace a dotfile repository
        with an other one. They had a .vim directory in their home directory
        which was obviously also a symbolic link. This caused:

        OSError: Cannot call rmtree on a symbolic link
        """

        # Create a dotfile symlink to some directory
        os.mkdir(os.path.join(self.homedir, 'vim'))
        os.symlink(os.path.join(self.homedir, 'vim'),
                   os.path.join(self.homedir, '.vim'))

        # Create a vim directory in the repository. This will cause the above
        # symlink to be overwritten on sync.
        os.mkdir(os.path.join(self.repository, 'vim'))

        # Make sure the symlink points to the correct location.
        self.assertPathEqual(
                os.path.join(self.homedir, '.vim'),
                os.path.join(self.homedir, 'vim'))

        dotfiles = Dotfiles(
                homedir=self.homedir, path=self.repository,
                prefix='', ignore=[], externals={}, packages=[], dry_run=False)

        dotfiles.sync(force=True)

        # The symlink should now point to the directory in the repository.
        self.assertPathEqual(
                os.path.join(self.homedir, '.vim'),
                os.path.join(self.repository, 'vim'))
Пример #2
0
    def test_add_package_file(self):
        """
        Test adding a package that isn't already in the repository

        """

        package_dir = os.path.join(self.homedir,
                                   '.%s/%s' % ('config', 'gtk-3.0'))

        os.makedirs(package_dir)
        touch('%s/testfile' % package_dir)

        dotfiles = Dotfiles(homedir=self.homedir,
                            path=self.repository,
                            prefix='',
                            ignore=[],
                            externals={},
                            packages=['config'],
                            dry_run=False)

        # This should succeed and the directory structure in the repository
        # should be created since it didn't already exist.
        dotfiles.add(['.config/gtk-3.0'])
        self.assertTrue(
            os.path.islink(os.path.join(self.homedir, '.config/gtk-3.0')))
Пример #3
0
    def test_package_and_prefix(self):
        """Test syncing a package when using a non-default prefix."""

        package_dir = os.path.join(self.repository, '.config/awesome')
        os.makedirs(package_dir)
        touch('%s/testfile' % package_dir)

        dotfiles = Dotfiles(homedir=self.homedir,
                                 path=self.repository,
                                 prefix='.',
                                 ignore=[],
                                 externals={},
                                 packages=['.config'],
                                 dry_run=False,
                                 quiet=True)

        dotfiles.sync()

        expected = os.path.join(self.homedir, ".config")
        self.assertTrue(os.path.isdir(expected))

        expected = os.path.join(expected, "awesome")
        self.assertTrue(os.path.islink(expected))

        expected = os.path.join(expected, "testfile")
        self.assertTrue(os.path.isfile(expected))
Пример #4
0
    def test_add_package(self):
        """
        Test adding a package that isn't already in the repository

        """

        package_dir = os.path.join(self.homedir,
                                   '.%s/%s' % ('config', 'gtk-3.0'))

        os.makedirs(package_dir)
        touch('%s/testfile' % package_dir)

        dotfiles = Dotfiles(homedir=self.homedir,
                            path=self.repository,
                            prefix='',
                            ignore=[],
                            externals={},
                            packages=['config'],
                            dry_run=False,
                            quiet=True)

        # This should fail, you should not be able to add dotfiles that are
        # defined to be packages.
        dotfiles.add(['.config'])
        self.assertFalse(os.path.islink(os.path.join(self.homedir, '.config')))
Пример #5
0
    def test_glob_ignore_pattern(self):
        """ Test that the use of glob pattern matching works in the ignores
        list.

        The following repo dir exists:

        myscript.py
        myscript.pyc
        myscript.pyo
        bashrc
        bashrc.swp
        vimrc
        vimrc.swp
        install.sh

        Using the glob pattern dotfiles should have the following sync result
        in home:

        .myscript.py -> Dotfiles/myscript.py
        .bashrc -> Dotfiles/bashrc
        .vimrc -> Dotfiles/vimrc

        """
        ignore = ['*.swp', '*.py?', 'install.sh']

        all_repo_files = (
            ('myscript.py', '.myscript.py'),
            ('myscript.pyc', None),
            ('myscript.pyo', None),
            ('bashrc', '.bashrc'),
            ('bashrc.swp', None),
            ('vimrc', '.vimrc'),
            ('vimrc.swp', None),
            ('install.sh', None)
        )

        all_dotfiles = [f for f in all_repo_files if f[1] is not None]

        for original, symlink in all_repo_files:
            touch(os.path.join(self.repository, original))

        dotfiles = Dotfiles(
                homedir=self.homedir, path=self.repository,
                prefix='', ignore=ignore, externals={}, packages=[],
                dry_run=False)

        dotfiles.sync()

        # Now check that the files that should have a symlink
        # point to the correct file and are the only files that
        # exist in the home dir.
        self.assertEqual(
            sorted(os.listdir(self.homedir)),
            sorted([f[1] for f in all_dotfiles] + ['Dotfiles']))

        for original, symlink in all_dotfiles:
            self.assertPathEqual(
                os.path.join(self.repository, original),
                os.path.join(self.homedir, symlink))
Пример #6
0
    def test_glob_ignore_pattern(self):
        """ Test that the use of glob pattern matching works in the ignores
        list.

        The following repo dir exists:

        myscript.py
        myscript.pyc
        myscript.pyo
        bashrc
        bashrc.swp
        vimrc
        vimrc.swp
        install.sh

        Using the glob pattern dotfiles should have the following sync result
        in home:

        .myscript.py -> Dotfiles/myscript.py
        .bashrc -> Dotfiles/bashrc
        .vimrc -> Dotfiles/vimrc

        """
        ignore = ['*.swp', '*.py?', 'install.sh']

        all_repo_files = (
            ('myscript.py', '.myscript.py'),
            ('myscript.pyc', None),
            ('myscript.pyo', None),
            ('bashrc', '.bashrc'),
            ('bashrc.swp', None),
            ('vimrc', '.vimrc'),
            ('vimrc.swp', None),
            ('install.sh', None)
        )

        all_dotfiles = [f for f in all_repo_files if f[1] is not None]

        for original, symlink in all_repo_files:
            touch(os.path.join(self.repository, original))

        dotfiles = Dotfiles(homedir=self.homedir, path=self.repository,
                            prefix='', ignore=ignore,
                            externals={}, packages=[], dry_run=False)

        dotfiles.sync()

        # Now check that the files that should have a symlink
        # point to the correct file and are the only files that
        # exist in the home dir.
        self.assertEqual(
            sorted(os.listdir(self.homedir)),
            sorted([f[1] for f in all_dotfiles] + ['Dotfiles']))

        for original, symlink in all_dotfiles:
            self.assertPathEqual(
                os.path.join(self.repository, original),
                os.path.join(self.homedir, symlink))
Пример #7
0
    def test_packages(self):
        """
        Test packages.
        """
        files = ['foo', 'package/bar']
        symlinks = ['.foo', '.package/bar']
        join = os.path.join

        # Create files
        for filename in files:
            path = join(self.repository, filename)
            dirname = os.path.dirname(path)
            if not os.path.exists(dirname):
                os.makedirs(dirname)
            touch(path)

        # Create Dotfiles object
        dotfiles = Dotfiles(homedir=self.homedir,
                            path=self.repository,
                            prefix='',
                            ignore=[],
                            externals={},
                            packages=['package'],
                            dry_run=False)

        # Create symlinks in homedir
        dotfiles.sync()

        # Verify it created what we expect
        def check_all(files, symlinks):
            self.assertTrue(os.path.isdir(join(self.homedir, '.package')))
            for src, dst in zip(files, symlinks):
                self.assertTrue(
                    is_link_to(join(self.homedir, dst),
                               join(self.repository, src)))

        check_all(files, symlinks)

        # Add files to the repository
        new_files = [join(self.homedir, f) for f in ['.bar', '.package/foo']]
        for filename in new_files:
            path = join(self.homedir, filename)
            touch(path)
        new_repo_files = ['bar', 'package/foo']
        dotfiles.add(new_files)
        check_all(files + new_repo_files, symlinks + new_files)

        # Remove them from the repository
        dotfiles.remove(new_files)
        check_all(files, symlinks)

        # Move the repository
        self.repository = join(self.homedir, 'Dotfiles2')
        dotfiles.move(self.repository)
        check_all(files, symlinks)
Пример #8
0
    def test_packages(self):
        """
        Test packages.
        """
        files = ['foo', 'package/bar', 'package2/foo/bar']
        symlinks = ['.foo', '.package/bar', '.package2/foo/bar']
        join = os.path.join

        # Create files
        for filename in files:
            path = join(self.repository, filename)
            dirname = os.path.dirname(path)
            if not os.path.exists(dirname):
                os.makedirs(dirname)
            touch(path)

        # Create Dotfiles object
        dotfiles = Dotfiles(
                homedir=self.homedir, path=self.repository,
                prefix='', ignore=[], externals={},
                packages=set(['package', 'package2/foo']), dry_run=False)

        # Create symlinks in homedir
        dotfiles.sync()

        # Verify it created what we expect
        for folder in ['.package', '.package2', '.package2/foo']:
            self.assertTrue(os.path.isdir(join(self.homedir, folder)))
        def check_all(files, symlinks):
            for src, dst in zip(files, symlinks):
                self.assertTrue(is_link_to(join(self.homedir, dst),
                    join(self.repository, src)))
        check_all(files, symlinks)

        # Add files to the repository
        new_files = [join(self.homedir, f) for f in 
                ['.bar', '.package/foo', '.package2/foo/bar2']]
        for filename in new_files:
            path = join(self.homedir, filename)
            touch(path)
        new_repo_files = ['bar', 'package/foo', 'package2/foo/bar2']
        dotfiles.add(new_files)
        check_all(files + new_repo_files, symlinks + new_files)

        # Remove them from the repository
        dotfiles.remove(new_files)
        check_all(files, symlinks)

        # Move the repository
        self.repository = join(self.homedir, 'Dotfiles2')
        dotfiles.move(self.repository)
        check_all(files, symlinks)
Пример #9
0
    def test_single_sync(self):
        """
        Test syncing a single file in the repo

        The following repo dir exists:

        bashrc
        netrc
        vimrc

        Syncing only vimrc should have the folowing sync result in home:

        .vimrc -> Dotfiles/vimrc

        """

        # define the repository contents
        repo_files = (
            ('bashrc', False),
            ('netrc',  False),
            ('vimrc',  True))

        # populate the repository
        for dotfile, _ in repo_files:
            touch(os.path.join(self.repository, dotfile))

        dotfiles = Dotfiles(
                homedir=self.homedir, path=self.repository,
                prefix='', ignore=[], externals={}, packages=[],
                dry_run=False)

        # sync only certain dotfiles
        for dotfile, should_sync in repo_files:
            if should_sync:
                dotfiles.sync(files=['.%s' % dotfile])

        # verify home directory contents
        for dotfile, should_sync in repo_files:
            if should_sync:
                self.assertPathEqual(
                    os.path.join(self.repository, dotfile),
                    os.path.join(self.homedir, '.%s' % dotfile))
            else:
                self.assertFalse(os.path.exists(
                    os.path.join(self.homedir, dotfile)))
Пример #10
0
    def test_missing_package(self):
        """
        Test a non-existent package.
        """

        package_file = '.package/bar'

        # Create Dotfiles object
        dotfiles = Dotfiles(homedir=self.homedir, path=self.repository,
                            prefix='', ignore=[],
                            externals={}, packages=['package'], dry_run=False)

        path = os.path.join(self.homedir, package_file)
        dirname = os.path.dirname(path)
        if not os.path.exists(dirname):
            os.makedirs(dirname)
        touch(path)

        dotfiles.add([os.path.join(self.homedir, package_file)])
Пример #11
0
    def test_no_dot_prefix(self):
        # define the repository contents
        repo_files = ('bashrc', 'netrc', 'vimrc')

        # populate the repository
        for dotfile in repo_files:
            touch(os.path.join(self.repository, dotfile))

        dotfiles = Dotfiles(
                homedir=self.homedir, path=self.repository,
                prefix='', ignore=[], externals={}, packages=[],
                dry_run=False, no_dot_prefix=True)

        dotfiles.sync()

        # verify home directory contents
        for dotfile in repo_files:
            self.assertPathEqual(
                os.path.join(self.repository, dotfile),
                os.path.join(self.homedir, dotfile))
Пример #12
0
    def test_add_package(self):
        """
        Test adding a package that isn't already in the repository

        """

        package_dir = os.path.join(self.homedir,
            '.%s/%s' % ('config', 'gtk-3.0'))

        os.makedirs(package_dir)
        touch('%s/testfile' % package_dir)

        dotfiles = Dotfiles(
                homedir=self.homedir, path=self.repository,
                prefix='', ignore=[], externals={}, packages=['config'],
                dry_run=False, quiet=True)

        # This should fail, you should not be able to add dotfiles that are
        # defined to be packages.
        dotfiles.add(['.config'])
        self.assertFalse(os.path.islink(os.path.join(self.homedir, '.config')))
Пример #13
0
    def test_add_package_file(self):
        """
        Test adding a package that isn't already in the repository

        """

        package_dir = os.path.join(self.homedir,
                                   '.%s/%s' % ('config', 'gtk-3.0'))

        os.makedirs(package_dir)
        touch('%s/testfile' % package_dir)

        dotfiles = Dotfiles(homedir=self.homedir, path=self.repository,
                            prefix='', ignore=[],
                            externals={}, packages=['config'], dry_run=False)

        # This should succeed and the directory structure in the repository
        # should be created since it didn't already exist.
        df = os.path.join(self.homedir, '.config/gtk-3.0')
        dotfiles.add([df])
        self.assertTrue(os.path.islink(df))
Пример #14
0
    def test_missing_remove(self):
        """Test removing a dotfile that's been removed from the repository."""

        repo_file = os.path.join(self.repository, 'testdotfile')

        touch(repo_file)

        dotfiles = Dotfiles(homedir=self.homedir,
                            path=self.repository,
                            prefix='',
                            ignore=[],
                            externals={},
                            packages=[],
                            dry_run=False)

        dotfiles.sync()

        # remove the dotfile from the repository, homedir symlink is now broken
        os.remove(repo_file)

        # remove the broken symlink
        dotfiles.remove(['.testdotfile'])

        # verify symlink was removed
        self.assertFalse(
            os.path.exists(os.path.join(self.homedir, '.testdotfile')))
Пример #15
0
    def test_move_repository(self):
        """Test the move() method for a Dotfiles repository."""

        touch(os.path.join(self.repository, 'bashrc'))

        dotfiles = Dotfiles(
                homedir=self.homedir, path=self.repository,
                prefix='', ignore=[], force=True, externals={}, packages=[],
                dry_run=False)

        dotfiles.sync()

        # Make sure sync() did the right thing.
        self.assertPathEqual(
                os.path.join(self.homedir, '.bashrc'),
                os.path.join(self.repository, 'bashrc'))

        target = os.path.join(self.homedir, 'MyDotfiles')

        dotfiles.move(target)

        self.assertTrue(os.path.exists(os.path.join(target, 'bashrc')))
        self.assertPathEqual(
                os.path.join(self.homedir, '.bashrc'),
                os.path.join(target, 'bashrc'))
Пример #16
0
    def test_missing_remove(self):
        """Test removing a dotfile that's been removed from the repository."""

        repo_file = os.path.join(self.repository, 'testdotfile')

        touch(repo_file)

        dotfiles = Dotfiles(homedir=self.homedir, path=self.repository,
                            prefix='', ignore=[],
                            externals={}, packages=[], dry_run=False)

        dotfiles.sync()

        # remove the dotfile from the repository, homedir symlink is now broken
        os.remove(repo_file)

        # remove the broken symlink
        dotfiles.remove(['.testdotfile'])

        # verify symlink was removed
        self.assertFalse(os.path.exists(
            os.path.join(self.homedir, '.testdotfile')))
Пример #17
0
    def test_force_sync_directory(self):
        """Test forced sync when the dotfile is a directory.

        I installed the lastpass chrome extension which stores a socket in
        ~/.lastpass. So I added that directory as an external to /tmp and
        attempted a forced sync. An error occurred because sync() calls
        os.remove() as it mistakenly assumes the dotfile is a file and not
        a directory.
        """

        os.mkdir(os.path.join(self.homedir, '.lastpass'))
        externals = {'.lastpass': '******'}

        dotfiles = Dotfiles(homedir=self.homedir, path=self.repository,
                            prefix='', ignore=[],
                            externals=externals, packages=[], dry_run=False)

        dotfiles.sync(force=True)

        self.assertPathEqual(
            os.path.join(self.homedir, '.lastpass'),
            '/tmp')
Пример #18
0
    def test_hosts_mode(self):
        """Test that host mode behaves correctly."""

        all_repo_files = (
            ('.vimrc', 'all'),
            ('.mozilla', 'guiworkstation'),
        )

        for homefile, host in all_repo_files:
            touch(os.path.join(self.homedir, homefile))

        os.makedirs(os.path.join(self.repository, 'all.host'))

        dotfiles = Dotfiles(homedir=self.homedir,
                            path=self.repository,
                            prefix='', ignore=[],
                            externals={}, packages=[], dry_run=False)
        self.assertTrue(dotfiles.hosts_mode())

        for homefile, host in all_repo_files:
            dotfiles.add([os.path.join(self.homedir, homefile)], host)
            self.verifyFileStatus(homefile, host)

        for homefile, host in all_repo_files:
            os.unlink(os.path.join(self.homedir, homefile))

        dotfiles._load()
        dotfiles.sync()
        self.verifyFileStatus('.vimrc', 'all')
        self.assertTrue(not os.path.exists(os.path.join(self.homedir,
                                           '.mozilla')))

        dotfiles._load()
        dotfiles.sync(hostname='guiworkstation')
        self.assertTrue(os.path.exists(os.path.join(self.homedir, '.mozilla')))

        dotfiles._load()
        dotfiles.remove([os.path.join(self.homedir, '.mozilla')],
                        'guiworkstation')

        dotfiles._load()
        dotfiles.sync(hostname='guiworkstation')
        self.verifyFileStatus('.vimrc', 'all')
        self.assertTrue(not os.path.islink(os.path.join(self.homedir,
                                                        '.mozilla')))
Пример #19
0
    def test_dotdir_file_add_sync_remove(self):
        """Test that is is possible to add files in dot-directories
        and that they are managed correctly.

        This is especially usefull for applications that mix state files and
        configuration files in their dot-directory, for instance :
            - .unison which contains *prf and state files
            - .lftp which contains rc (conf file) and log, cwd_history.
        """
        os.mkdir(os.path.join(self.homedir, '.unison'))
        os.mkdir(os.path.join(self.homedir, '.lftp'))
        all_repo_files = (
            ('.vimrc', True),
            ('.unison/home.prf', True),
            ('.unison/are8d491ed362b0a4cf3e8d77ef3e08a1c', False),
            ('.unison/fpe8d491ed362b0a4cf3e8d77ef3e08a1c', False),
            ('.lftp/log', False),
            ('.lftp/rc', True),
            ('.lftp/cwd_history', False),
        )
        repo_dir = '.ikiwiki'

        for homefile, in_repository in all_repo_files:
            touch(os.path.join(self.homedir, homefile))
        os.mkdir(os.path.join(self.homedir, repo_dir))

        dotfiles = Dotfiles(homedir=self.homedir,
                            path=self.repository,
                            prefix='', ignore=[],
                            externals={}, packages=[], dry_run=False)

        dotfiles.add([os.path.join(self.homedir, homefile)
                      for homefile, in_repo in all_repo_files
                      if in_repo])
        for homefile, in_repository in all_repo_files:
            if in_repository:
                self.verifyFileStatus(homefile)

            for dotdir in ('.unison', '.lftp'):
                homepath = os.path.join(self.homedir, dotdir)
                self.assertTrue(not os.path.islink(homepath))
                self.assertTrue(os.path.isdir(homepath))

        os.unlink(os.path.join(self.homedir, '.vimrc'))
        os.unlink(os.path.join(self.homedir, '.lftp/rc'))

        os.unlink(os.path.join(self.homedir, '.unison/home.prf'))
        touch(os.path.join(self.homedir, '.unison/home.prf'))

        dotfiles._load()  # refresh file states
        dotfiles.sync()
        for homefile in ('.vimrc', '.lftp/rc'):
            self.verifyFileStatus(homefile)
        self.assertTrue(not os.path.islink(os.path.join(self.homedir,
                                                        '.unison/home.prf')))
        self.assertTrue(os.path.isfile(os.path.join(self.homedir,
                                       '.unison/home.prf')))

        dotfiles._load()  # refresh file states
        dotfiles.sync(force=True)
        self.verifyFileStatus('.unison/home.prf')

        dotfiles.remove([os.path.join(self.homedir, '.lftp/rc')])
        self.assertTrue(not os.path.islink(os.path.join(self.homedir,
                                                        '.lftp/rc')))
        self.assertTrue(os.path.isfile(os.path.join(self.homedir, '.lftp/rc')))