aboutsummaryrefslogtreecommitdiffstats
path: root/dotfiles/repository.py
blob: 0c3a4f3b7ea0b4ea99269f2a0525b23b6f7b62c4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
import py
from operator import attrgetter

from .dotfile import Dotfile


class Repository(object):
    """
    This class implements the 'repository' abstraction.

    A repository is a directory that contains dotfiles.  It has two primary
    attributes:

    repodir -- the location of the repository directory
    homedir -- the location of the home directory (primarily for testing)

    Both of the above attributes are received as string objects and converted
    to py.path.local objects for internal use.

    The repository implements these fundamental operations:

    status -- list the dotfiles (and their state) contained herein
    check  -- list any dotfiles unsynced or unmanaged that require attention
    sync   -- create some or all missing dotfile symlinks
    unsync -- remove some or all dotfile symlinks
    add    -- add a dotfile to this repository and create its symlink
    remove -- the opposited of add
    move   -- change the name of this repository and update dependent symlinks
    """

    def __init__(self, repodir, homedir='~'):
        self.repodir = repodir
        self.homedir = homedir

    def __str__(self):
        return self._contents() or '[no dotfiles found]'

    def __repr__(self):
        return '<Repository %r>' % self.repodir

    @property
    def repodir(self):
        return str(self._repodir)

    @repodir.setter
    def repodir(self, path):
        self._repodir = py.path.local(path, expanduser=True)

    @property
    def homedir(self):
        return str(self._homedir)

    @homedir.setter
    def homedir(self, path):
        self._homedir = py.path.local(path, expanduser=True)

    def _target_to_name(self, target):
        return py.path.local("%s/.%s" % (self.homedir, target.basename))

    def _load(self):
        """Given a repository path, discover all existing dotfiles."""
        dotfiles = []
        self._repodir.ensure(dir=1)
        targets = self._repodir.listdir()
        for target in targets:
            target = py.path.local(target)
            name = self._target_to_name(target)
            dotfiles.append(Dotfile(name, target))
        return sorted(dotfiles, key=attrgetter('name'))

    def _contents(self, all=True):
        """Convert loaded contents to human readable form."""
        contents = ''
        dotfiles = self._load()
        for dotfile in dotfiles:
            if all or dotfile.invalid():
                contents += '\n%s' % dotfile
        return contents.lstrip()

    def status(self):
        """Returns a string list of all dotfiles."""
        return str(self)

    def check(self):
        """Returns a string list of only unsynced or missing dotfiles."""
        return self._contents(all=False)

    def sync(self):
        raise NotImplementedError

    def unsync(self):
        raise NotImplementedError

    def add(self):
        raise NotImplementedError

    def remove(self):
        raise NotImplementedError

    def move(self):
        raise NotImplementedError