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
|
from __future__ import absolute_import, division, print_function
import logging
import os
import shutil
from .exceptions import ArgumentError
from .spec import Spec
class NoSuchWorkspaceError(Exception):
pass
class Workspace(object):
"A mojo workspace"
def __init__(self, name, path, stage=None, spec_url=None, manifest_file=None, logfile=None):
if name is None:
raise ArgumentError("Workspace setting missing. Use --workspace or set MOJO_WORKSPACE")
self.name = name
self.manifest_file = manifest_file
if not path:
self.path = os.path.abspath(os.curdir)
logging.info("No workspace path specified, using {}"
"".format(self.path))
else:
self.path = os.path.abspath(path)
if not os.path.exists(self.path):
raise NoSuchWorkspaceError(path)
self.stage = stage
self.spec_url = spec_url
self.logfile = logfile
self._spec = None
@property
def spec(self):
if self._spec is None:
self._spec = Spec(self.spec_dir, self.spec_url, stage=self.stage, manifest_file=self.manifest_file)
return self._spec
@property
def all_dirs(self):
return [self.path,
self.build_dir,
self.local_dir,
self.log_dir,
self.spec_dir,
]
def prepare(self):
"Set up the workspace. Returns True on success, False on failure."
for path in self.all_dirs:
if path == self.spec_dir: # spec dir is initialized next
continue
if not os.path.isdir(path):
try:
os.makedirs(path)
except OSError as e:
logging.error("{} ({})".format(e.strerror, e.filename))
return False
self.spec # Initializes spec
self.create_file_logger()
return True
def clean(self):
"Reset the workspace"
existing_directories = (d for d in self.all_dirs if os.path.exists(d))
for directory in existing_directories:
shutil.rmtree(directory)
return self.prepare()
def delete(self):
"Destroy the workspace"
realpath = os.path.realpath(self.path)
shutil.rmtree(realpath)
def create_file_logger(self):
"If we haven't already, attach a file logger"
if logging.getLogger('file').handlers:
return
if not self.logfile:
self.logfile = os.path.join(self.log_dir, "mojo.log")
try:
logFormatter = logging.Formatter(
fmt="%(asctime)s [%(levelname)s] %(message)s",
datefmt="%Y-%m-%d %H:%M:%S")
rootLogger = logging.getLogger()
fileLogger = logging.getLogger('file')
# If we send output to the file logger specifically, don't propagate it
# to the root logger as well to avoid duplicate output. So if we want
# to only send logging output to the file, you would do this:
# logging.getLogger('file').info("message for logfile only")
# rather than this:
# logging.info("message for console and logfile")
fileLogger.propagate = False
fileHandler = logging.FileHandler(self.logfile)
fileHandler.setFormatter(logFormatter)
rootLogger.addHandler(fileHandler)
fileLogger.addHandler(fileHandler)
except IOError:
logging.error("Unable to write to logfile: {}".format(self.logfile))
@property
def build_dir(self):
return os.path.join(self.path, "build")
@property
def repo_dir(self):
return os.path.join(self.path, "charms")
@property
def local_dir(self):
return os.path.join(self.path, "local")
@property
def log_dir(self):
if self.logfile:
return os.path.dirname(os.path.abspath(self.logfile))
return os.path.join(self.path, "log")
@property
def spec_dir(self):
return os.path.join(self.path, "spec")
|