907.1.1
by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer. |
1 |
#!/usr/bin/env python
|
2 |
"""\
|
|
3 |
An implementation of the Transport object for local
|
|
4 |
filesystem access.
|
|
5 |
"""
|
|
6 |
||
7 |
from bzrlib.transport import Transport, protocol_handlers |
|
8 |
import os |
|
9 |
||
10 |
class LocalTransport(Transport): |
|
11 |
"""This is the transport agent for local filesystem access."""
|
|
12 |
||
13 |
def __init__(self, base): |
|
14 |
"""Set the base path where files will be stored."""
|
|
15 |
from os.path import realpath |
|
16 |
super(LocalTransport, self).__init__(realpath(base)) |
|
17 |
||
907.1.22
by John Arbash Meinel
Fixed some encoding issues, added is_remote function for Transport objects. |
18 |
def is_remote(self): |
19 |
return False |
|
20 |
||
907.1.2
by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport. |
21 |
def clone(self, offset=None): |
22 |
"""Return a new LocalTransport with root at self.base + offset
|
|
23 |
Because the local filesystem does not require a connection,
|
|
24 |
we can just return a new object.
|
|
25 |
"""
|
|
26 |
if offset is None: |
|
27 |
return LocalTransport(self.base) |
|
28 |
else: |
|
29 |
return LocalTransport(self.abspath(offset)) |
|
30 |
||
907.1.8
by John Arbash Meinel
Changed the format for abspath. Updated branch to use a hidden _transport |
31 |
def abspath(self, relpath): |
907.1.2
by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport. |
32 |
"""Return the full url to the given relative path.
|
907.1.8
by John Arbash Meinel
Changed the format for abspath. Updated branch to use a hidden _transport |
33 |
This can be supplied with a string or a list
|
907.1.2
by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport. |
34 |
"""
|
907.1.8
by John Arbash Meinel
Changed the format for abspath. Updated branch to use a hidden _transport |
35 |
if isinstance(relpath, basestring): |
36 |
relpath = [relpath] |
|
37 |
return os.path.join(self.base, *relpath) |
|
907.1.1
by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer. |
38 |
|
907.1.24
by John Arbash Meinel
Remote functionality work. |
39 |
def relpath(self, abspath): |
40 |
"""Return the local path portion from a given absolute path.
|
|
41 |
"""
|
|
42 |
from branch import _relpath |
|
43 |
return _relpath(self.base, abspath) |
|
44 |
||
907.1.1
by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer. |
45 |
def has(self, relpath): |
907.1.2
by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport. |
46 |
return os.access(self.abspath(relpath), os.F_OK) |
907.1.1
by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer. |
47 |
|
907.1.20
by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8 |
48 |
def get(self, relpath, decode=False): |
907.1.1
by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer. |
49 |
"""Get the file at the given relative path.
|
907.1.20
by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8 |
50 |
|
51 |
:param relpath: The relative path to the file
|
|
52 |
:param decode: If True, assume the file is utf-8 encoded and
|
|
53 |
decode it into Unicode
|
|
54 |
"""
|
|
55 |
if decode: |
|
56 |
import codecs |
|
907.1.22
by John Arbash Meinel
Fixed some encoding issues, added is_remote function for Transport objects. |
57 |
return codecs.open(self.abspath(relpath), 'rb', |
58 |
encoding='utf-8', buffering=60000) |
|
907.1.20
by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8 |
59 |
else: |
60 |
return open(self.abspath(relpath), 'rb') |
|
61 |
||
62 |
def put(self, relpath, f, encode=False): |
|
63 |
"""Copy the file-like or string object into the location.
|
|
64 |
||
65 |
:param relpath: Location to put the contents, relative to base.
|
|
66 |
:param f: File-like or string object.
|
|
67 |
:param encode: If True, translate the contents into utf-8 encoded text.
|
|
68 |
"""
|
|
907.1.1
by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer. |
69 |
from bzrlib.atomicfile import AtomicFile |
70 |
||
907.1.20
by John Arbash Meinel
Removed Transport.open(), making get + put encode/decode to utf-8 |
71 |
if encode: |
72 |
fp = AtomicFile(self.abspath(relpath), 'wb', encoding='utf-8') |
|
73 |
else: |
|
74 |
fp = AtomicFile(self.abspath(relpath), 'wb') |
|
907.1.2
by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport. |
75 |
try: |
76 |
self._pump(f, fp) |
|
77 |
fp.commit() |
|
78 |
finally: |
|
79 |
fp.close() |
|
80 |
||
81 |
def mkdir(self, relpath): |
|
82 |
"""Create a directory at the given path."""
|
|
83 |
os.mkdir(self.abspath(relpath)) |
|
84 |
||
907.1.1
by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer. |
85 |
def append(self, relpath, f): |
86 |
"""Append the text in the file-like object into the final
|
|
87 |
location.
|
|
88 |
"""
|
|
907.1.2
by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport. |
89 |
fp = open(self.abspath(relpath), 'a+b') |
907.1.1
by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer. |
90 |
self._pump(f, fp) |
91 |
||
92 |
def copy(self, rel_from, rel_to): |
|
93 |
"""Copy the item at rel_from to the location at rel_to"""
|
|
94 |
import shutil |
|
907.1.2
by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport. |
95 |
path_from = self.abspath(rel_from) |
96 |
path_to = self.abspath(rel_to) |
|
907.1.1
by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer. |
97 |
shutil.copy(path_from, path_to) |
98 |
||
99 |
def move(self, rel_from, rel_to): |
|
100 |
"""Move the item at rel_from to the location at rel_to"""
|
|
907.1.2
by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport. |
101 |
path_from = self.abspath(rel_from) |
102 |
path_to = self.abspath(rel_to) |
|
907.1.1
by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer. |
103 |
|
104 |
os.rename(path_from, path_to) |
|
105 |
||
106 |
def delete(self, relpath): |
|
107 |
"""Delete the item at relpath"""
|
|
907.1.2
by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport. |
108 |
os.remove(self.abspath(relpath)) |
907.1.1
by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer. |
109 |
|
110 |
def async_get(self, relpath): |
|
111 |
"""Make a request for an file at the given location, but
|
|
112 |
don't worry about actually getting it yet.
|
|
113 |
||
114 |
:rtype: AsyncFile
|
|
115 |
"""
|
|
116 |
raise NotImplementedError |
|
117 |
||
907.1.2
by John Arbash Meinel
Working on making Branch() do all of it's work over a Transport. |
118 |
def list_dir(self, relpath): |
119 |
"""Return a list of all files at the given location.
|
|
120 |
WARNING: many transports do not support this, so trying avoid using
|
|
121 |
it if at all possible.
|
|
122 |
"""
|
|
123 |
return os.listdir(self.abspath(relpath)) |
|
124 |
||
125 |
def stat(self, relpath): |
|
126 |
"""Return the stat information for a file.
|
|
127 |
"""
|
|
128 |
return os.stat(self.abspath(relpath)) |
|
129 |
||
907.1.24
by John Arbash Meinel
Remote functionality work. |
130 |
def lock_read(self, relpath): |
131 |
"""Lock the given file for shared (read) access.
|
|
132 |
:return: A lock object, which should be passed to Transport.unlock()
|
|
133 |
"""
|
|
134 |
from bzrlib.lock import ReadLock |
|
135 |
return ReadLock(self.abspath(relpath)) |
|
136 |
||
137 |
def lock_write(self, relpath): |
|
138 |
"""Lock the given file for exclusive (write) access.
|
|
139 |
WARNING: many transports do not support this, so trying avoid using it
|
|
140 |
||
141 |
:return: A lock object, which should be passed to Transport.unlock()
|
|
142 |
"""
|
|
143 |
from bzrlib.lock import WriteLock |
|
144 |
return WriteLock(self.abspath(relpath)) |
|
145 |
||
907.1.1
by John Arbash Meinel
Reworking the Branch and Store code to support an abstracted filesystem layer. |
146 |
# If nothing else matches, try the LocalTransport
|
147 |
protocol_handlers[None] = LocalTransport |
|
148 |