summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEnrico Scholz <enrico.scholz@sigma-chemnitz.de>2013-02-11 20:21:52 +0100
committerRichard Purdie <richard.purdie@linuxfoundation.org>2013-02-11 22:45:25 +0000
commit8c22531e491e6b0cfffaaa80d6bc75db757fc1d1 (patch)
tree2d326aaea7250fac0e276500111c230cecbe971a
parentd518019d6ccb0ffebe7e21b973eb4f9aa5241dec (diff)
downloadpoky-8c22531e491e6b0cfffaaa80d6bc75db757fc1d1.tar.gz
lib/oe/path.py: support missing directory components in realpath()
Some use cases in OE operate on symlinks which dangling path components. Assume that these are directories instead of raising ENOENT. (From OE-Core rev: a96e2c84f24c15b77ee1fbc1f998b8b4796b8664) Signed-off-by: Enrico Scholz <enrico.scholz@sigma-chemnitz.de> Signed-off-by: Richard Purdie <richard.purdie@linuxfoundation.org>
-rw-r--r--meta/lib/oe/path.py26
-rw-r--r--meta/lib/oe/tests/test_path.py10
2 files changed, 19 insertions, 17 deletions
diff --git a/meta/lib/oe/path.py b/meta/lib/oe/path.py
index 0b34cebdab..faa0f61fab 100644
--- a/meta/lib/oe/path.py
+++ b/meta/lib/oe/path.py
@@ -168,13 +168,13 @@ def find(dir, **walkoptions):
168def __is_path_below(file, root): 168def __is_path_below(file, root):
169 return (file + os.path.sep).startswith(root) 169 return (file + os.path.sep).startswith(root)
170 170
171def __realpath_rel(start, rel_path, root, loop_cnt): 171def __realpath_rel(start, rel_path, root, loop_cnt, assume_dir):
172 """Calculates real path of symlink 'start' + 'rel_path' below 172 """Calculates real path of symlink 'start' + 'rel_path' below
173 'root'; no part of 'start' below 'root' must contain symlinks. """ 173 'root'; no part of 'start' below 'root' must contain symlinks. """
174 have_dir = True 174 have_dir = True
175 175
176 for d in rel_path.split(os.path.sep): 176 for d in rel_path.split(os.path.sep):
177 if not have_dir: 177 if not have_dir and not assume_dir:
178 raise OSError(errno.ENOENT, "no such directory %s" % start) 178 raise OSError(errno.ENOENT, "no such directory %s" % start)
179 179
180 if d == os.path.pardir: # '..' 180 if d == os.path.pardir: # '..'
@@ -186,13 +186,13 @@ def __realpath_rel(start, rel_path, root, loop_cnt):
186 pass 186 pass
187 else: 187 else:
188 (start, have_dir) = __realpath(os.path.join(start, d), 188 (start, have_dir) = __realpath(os.path.join(start, d),
189 root, loop_cnt) 189 root, loop_cnt, assume_dir)
190 190
191 assert(__is_path_below(start, root)) 191 assert(__is_path_below(start, root))
192 192
193 return start 193 return start
194 194
195def __realpath(file, root, loop_cnt): 195def __realpath(file, root, loop_cnt, assume_dir):
196 while os.path.islink(file) and len(file) >= len(root): 196 while os.path.islink(file) and len(file) >= len(root):
197 if loop_cnt == 0: 197 if loop_cnt == 0:
198 raise OSError(errno.ELOOP, file) 198 raise OSError(errno.ELOOP, file)
@@ -206,7 +206,7 @@ def __realpath(file, root, loop_cnt):
206 else: 206 else:
207 tdir = root 207 tdir = root
208 208
209 file = __realpath_rel(tdir, target, root, loop_cnt) 209 file = __realpath_rel(tdir, target, root, loop_cnt, assume_dir)
210 210
211 try: 211 try:
212 is_dir = os.path.isdir(file) 212 is_dir = os.path.isdir(file)
@@ -215,11 +215,13 @@ def __realpath(file, root, loop_cnt):
215 215
216 return (file, is_dir) 216 return (file, is_dir)
217 217
218def realpath(file, root, use_physdir = True, loop_cnt = 100): 218def realpath(file, root, use_physdir = True, loop_cnt = 100, assume_dir = False):
219 """ Returns the canonical path of 'file' with assuming a toplevel 219 """ Returns the canonical path of 'file' with assuming a
220 'root' directory. When 'use_physdir' is set, all preceding path 220 toplevel 'root' directory. When 'use_physdir' is set, all
221 components of 'file' will be resolved first; this flag should be 221 preceding path components of 'file' will be resolved first;
222 set unless it is guaranteed that there is no symlink in the path.""" 222 this flag should be set unless it is guaranteed that there is
223 no symlink in the path. When 'assume_dir' is not set, missing
224 path components will raise an ENOENT error"""
223 225
224 root = os.path.normpath(root) 226 root = os.path.normpath(root)
225 file = os.path.normpath(file) 227 file = os.path.normpath(file)
@@ -233,9 +235,9 @@ def realpath(file, root, use_physdir = True, loop_cnt = 100):
233 235
234 try: 236 try:
235 if use_physdir: 237 if use_physdir:
236 file = __realpath_rel(root, file[(len(root) - 1):], root, loop_cnt) 238 file = __realpath_rel(root, file[(len(root) - 1):], root, loop_cnt, assume_dir)
237 else: 239 else:
238 file = __realpath(file, root, loop_cnt)[0] 240 file = __realpath(file, root, loop_cnt, assume_dir)[0]
239 except OSError, e: 241 except OSError, e:
240 if e.errno == errno.ELOOP: 242 if e.errno == errno.ELOOP:
241 # make ELOOP more readable; without catching it, there will 243 # make ELOOP more readable; without catching it, there will
diff --git a/meta/lib/oe/tests/test_path.py b/meta/lib/oe/tests/test_path.py
index e6aa601618..3d41ce157a 100644
--- a/meta/lib/oe/tests/test_path.py
+++ b/meta/lib/oe/tests/test_path.py
@@ -25,7 +25,7 @@ class TestRealPath(unittest.TestCase):
25 ( "usr/bin/prog-F", "../../../sbin/prog-F", "/sbin/prog-F" ), 25 ( "usr/bin/prog-F", "../../../sbin/prog-F", "/sbin/prog-F" ),
26 ( "loop", "a/loop", None ), 26 ( "loop", "a/loop", None ),
27 ( "a/loop", "../loop", None ), 27 ( "a/loop", "../loop", None ),
28 ( "b/test", "file/foo", None ), 28 ( "b/test", "file/foo", "/b/file/foo" ),
29 ] 29 ]
30 30
31 LINKS_PHYS = [ 31 LINKS_PHYS = [
@@ -59,8 +59,9 @@ class TestRealPath(unittest.TestCase):
59 for l in self.LINKS: 59 for l in self.LINKS:
60 os.symlink(l[1], os.path.join(self.root, l[0])) 60 os.symlink(l[1], os.path.join(self.root, l[0]))
61 61
62 def __realpath(self, file, use_physdir): 62 def __realpath(self, file, use_physdir, assume_dir = True):
63 return oe.path.realpath(os.path.join(self.root, file), self.root, use_physdir) 63 return oe.path.realpath(os.path.join(self.root, file), self.root,
64 use_physdir, assume_dir = assume_dir)
64 65
65 def test_norm(self): 66 def test_norm(self):
66 for l in self.LINKS: 67 for l in self.LINKS:
@@ -85,5 +86,4 @@ class TestRealPath(unittest.TestCase):
85 def test_loop(self): 86 def test_loop(self):
86 for e in self.EXCEPTIONS: 87 for e in self.EXCEPTIONS:
87 self.assertRaisesRegexp(OSError, r'\[Errno %u\]' % e[1], 88 self.assertRaisesRegexp(OSError, r'\[Errno %u\]' % e[1],
88 self.__realpath, e[0], False) 89 self.__realpath, e[0], False, False)
89