summaryrefslogtreecommitdiffstats
path: root/modules/directory.py
blob: 1c6c02aef1c4e44a0f2e146c09a7b35243a4ade6 (plain)
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
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
# Fedora Developer Shell
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Library General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
# Authors: Luke Macken <lmacken@redhat.com>
#          Yaakov M. Nemoy <ynemoy@redhat.com>
#

from __future__ import with_statement

import base.factories as factories

from configobj import ConfigObj
from os import makedirs, getcwd, listdir
from os.path import abspath, join, split, splitext, basename, exists, dirname

from base.base import log
from base.factories import DirFactory
from base.module import Module
from base.util import pwd, copytree, close_all

class MetaDirectory(type):
    def __init__(cls, name, bases, attrs):
        t = name.lower()
        cls._type = t
        factories.register_directory(cls, t)

class Directory(Module):
    '''a generic base class for any module that has to maintain state 
    on the file system in a directory
    '''
    __metaclass__ = MetaDirectory
    def __init__(self, name=None):
        ''' initializer
        
        name is a path to the directory we are loading, if not given
            name is gleaned by assuming the current directory is the
            package desired
        '''
        if not name:
            log.debug('no name with directory')
            cwd = getcwd()
            log.debug(split(cwd))
            if self.is_sysdir_dir(cwd):
                self.load_dir(cwd)
            else:
                self.make_dir(cwd)
        else:
            log.debug('directory.init with name ' + name)
            dir = abspath(name)
            if not exists(dir):
                makedirs(dir)
            if self.is_sysdir_dir(dir):
                self.load_dir(dir)
            else:
                self.make_dir(dir)

    def is_sysdir_dir(self, dir):
        '''given a directory, determine if the system directory is
        already a directory or not'''
        with pwd(dir):
            cfg = ConfigObj('.devshell')
            try:
                if self._type  in cfg['type']:
                    log.debug('is type ' + self._type)
                    return True
                else:
                    return False
            except KeyError, e:
                return False

    def load_dir(self, dir):
        '''presuming dir is a directory, load it's state'''
        log.debug('directory.load_dir')
        with pwd(dir):
            parent, name = split(getcwd())
            self.parent = parent
            self.cfg = ConfigObj('.devshell')
            if not self.name == name:
                # we are saving name in the .devshell file so we can detect
                # if the name has been changed or not. we don't want to have to run
                # rename all the time
                self.rename(name)
                pass

    def make_dir(self, dir):
        '''since dir is not a directory, make it into one'''
        log.debug('directory.make_dir')
        with pwd(dir):
            self.cfg = ConfigObj('.devshell')
            parent, name = split(getcwd())
            # type is defined by the subclass
            self.cfg['type'] = self._type
            self.cfg['name'] = name
            self.parent = parent
            self.cfg.write()

    @property
    def name(self):
        ''' the name of the directory/module as defined by the user
        '''
        return self.cfg['name']

    @property
    def dir(self):
        '''absolute pathname to the directory where it is held on the file system'''
        return join(self.parent, self.name)

    def close(self):
        '''called by devshell, closes the open objects'''
        log.debug('writing self.cfg for directory')
        with pwd(self.dir):
            self.cfg.write()
        close_all()

    def rename(self, new_name):
        '''renames the directory internally, assuming it's been renamed 
        on the file system

        subclass authors take note, this must be reimplemented, and the 
        superclass version called when any property or state depends on
        self.name in any way shape or form.
        '''
        self.cfg['name'] = new_name

    def move(self, new_loc):
        '''given a new location, moves everything there, and renames'''
        new_loc = abspath(new_loc)
        new_parent, new_name = split(new_loc)
        old_dir = self.dir
        copytree(self.dir, new_loc)
        self.parent = new_parent
        self.rename(new_name)
        with pwd(self.dir):
            self.cfg.write()
        rm(old_dir)

    def copy(self, new_loc):
        '''makes a copy of the contents in a new location, renames, 
        and returns a reference to a new object rpresenting the new directory'''
        new_loc = abspath(new_loc)
        new_parent, new_name = split(new_loc)
        copytree(self.dir, new_loc)
        new_dir = DirFactory(new_loc)
        return new_dir

__all__ = ['Directory']