Bug 255 fixed
[mediagoblin.git] / mediagoblin / storage / filestorage.py
CommitLineData
a2468d18 1# GNU MediaGoblin -- federated, autonomous media hosting
cf29e8a8 2# Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
a2468d18
JW
3#
4# This program is free software: you can redistribute it and/or modify
5# it under the terms of the GNU Affero General Public License as published by
6# the Free Software Foundation, either version 3 of the License, or
7# (at your option) any later version.
8#
9# This program is distributed in the hope that it will be useful,
10# but WITHOUT ANY WARRANTY; without even the implied warranty of
11# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12# GNU Affero General Public License for more details.
13#
14# You should have received a copy of the GNU Affero General Public License
15# along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17from mediagoblin.storage import (
18 StorageInterface,
19 clean_listy_filepath,
20 NoWebServing)
21
22import os
98f6efb0 23import shutil
a2468d18
JW
24import urlparse
25
26
27class BasicFileStorage(StorageInterface):
28 """
29 Basic local filesystem implementation of storage API
30 """
31
32 local_storage = True
33
34 def __init__(self, base_dir, base_url=None, **kwargs):
35 """
36 Keyword arguments:
37 - base_dir: Base directory things will be served out of. MUST
38 be an absolute path.
39 - base_url: URL files will be served from
40 """
41 self.base_dir = base_dir
42 self.base_url = base_url
43
44 def _resolve_filepath(self, filepath):
45 """
46 Transform the given filepath into a local filesystem filepath.
47 """
48 return os.path.join(
49 self.base_dir, *clean_listy_filepath(filepath))
50
51 def file_exists(self, filepath):
52 return os.path.exists(self._resolve_filepath(filepath))
53
54 def get_file(self, filepath, mode='r'):
55 # Make directories if necessary
56 if len(filepath) > 1:
57 directory = self._resolve_filepath(filepath[:-1])
58 if not os.path.exists(directory):
59 os.makedirs(directory)
60
61 # Grab and return the file in the mode specified
62 return open(self._resolve_filepath(filepath), mode)
63
64 def delete_file(self, filepath):
65 # TODO: Also delete unused directories if empty (safely, with
66 # checks to avoid race conditions).
ddaf070a
JAN
67 try:
68 os.remove(self._resolve_filepath(filepath))
69 except OSError:
70 # the file do not exists!
71 # This should fix bug #255
72 pass
a2468d18
JW
73
74 def file_url(self, filepath):
75 if not self.base_url:
76 raise NoWebServing(
77 "base_url not set, cannot provide file urls")
78
79 return urlparse.urljoin(
80 self.base_url,
81 '/'.join(clean_listy_filepath(filepath)))
82
83 def get_local_path(self, filepath):
84 return self._resolve_filepath(filepath)
98f6efb0
CAW
85
86 def copy_local_to_storage(self, filename, filepath):
87 """
88 Copy this file from locally to the storage system.
89 """
90 # Make directories if necessary
91 if len(filepath) > 1:
92 directory = self._resolve_filepath(filepath[:-1])
93 if not os.path.exists(directory):
94 os.makedirs(directory)
95
96 shutil.copy(
97 filename, self.get_local_path(filepath))