1 |
commit: 1587a9392d1325315e3feb1de5e59e19dd670b57 |
2 |
Author: André Erdmann <dywi <AT> mailerd <DOT> de> |
3 |
AuthorDate: Fri Feb 21 18:30:06 2014 +0000 |
4 |
Commit: André Erdmann <dywi <AT> mailerd <DOT> de> |
5 |
CommitDate: Fri Feb 21 18:30:06 2014 +0000 |
6 |
URL: http://git.overlays.gentoo.org/gitweb/?p=proj/R_overlay.git;a=commit;h=1587a939 |
7 |
|
8 |
roverlay/fsutil: walk_relpath() |
9 |
|
10 |
Common functionality for get_fs_dict(), walk_copy_tree(). |
11 |
|
12 |
+ pwd_unexpanduser() function |
13 |
* pwd_expanduser() uses roverlay.util.common.get_home_dir() now |
14 |
* get_fs_dict(): don't ignore top-level files unless explicitly stated |
15 |
|
16 |
--- |
17 |
roverlay/fsutil.py | 144 +++++++++++++++++++++++++++++----------- |
18 |
roverlay/setupscript/hookenv.py | 1 + |
19 |
2 files changed, 105 insertions(+), 40 deletions(-) |
20 |
|
21 |
diff --git a/roverlay/fsutil.py b/roverlay/fsutil.py |
22 |
index d0091c2..0e9d439 100644 |
23 |
--- a/roverlay/fsutil.py |
24 |
+++ b/roverlay/fsutil.py |
25 |
@@ -16,11 +16,57 @@ import sys |
26 |
|
27 |
import roverlay.util.common |
28 |
import roverlay.util.objects |
29 |
+from roverlay.util.common import get_home_dir |
30 |
|
31 |
_OS_CHOWN = getattr ( os, 'lchown', os.chown ) |
32 |
_OS_CHMOD = getattr ( os, 'lchmod', os.chmod ) |
33 |
|
34 |
|
35 |
+def walk_relpath ( |
36 |
+ root, include_root=False, |
37 |
+ dirname_filter=None, filename_filter=None, prune_empty=False, |
38 |
+ **os_walk_kwargs |
39 |
+): |
40 |
+ """See get_fs_dict(). |
41 |
+ |
42 |
+ arguments: |
43 |
+ * root -- |
44 |
+ * include_root -- |
45 |
+ * dirname_filter -- |
46 |
+ * filename_filter -- |
47 |
+ * prune_empty -- |
48 |
+ * os_walk_kwargs -- |
49 |
+ """ |
50 |
+ abs_root = os.path.abspath ( root ) |
51 |
+ if include_root: |
52 |
+ relpath_begin = 1 + abs_root.rfind ( os.sep ) |
53 |
+ else: |
54 |
+ relpath_begin = 1 + len ( abs_root ) |
55 |
+ |
56 |
+ walker = os.walk ( abs_root, **os_walk_kwargs ) |
57 |
+ |
58 |
+ if dirname_filter or filename_filter: |
59 |
+ for subroot, dirnames, filenames in walker: |
60 |
+ if dirname_filter: |
61 |
+ dirnames[:] = [ d for d in dirnames if dirname_filter ( d ) ] |
62 |
+ |
63 |
+ if filename_filter: |
64 |
+ filenames[:] = [ f for f in filenames if filename_filter ( f ) ] |
65 |
+ |
66 |
+ if not prune_empty or filenames or dirnames: |
67 |
+ yield ( subroot, subroot[relpath_begin:], dirnames, filenames ) |
68 |
+ |
69 |
+ elif prune_empty: |
70 |
+ for subroot, dirnames, filenames in walker: |
71 |
+ if dirnames or filenames: |
72 |
+ yield ( subroot, subroot[relpath_begin:], dirnames, filenames ) |
73 |
+ |
74 |
+ else: |
75 |
+ for subroot, dirnames, filenames in walker: |
76 |
+ yield ( subroot, subroot[relpath_begin:], dirnames, filenames ) |
77 |
+# --- end of walk_relpath (...) --- |
78 |
+ |
79 |
+ |
80 |
def walk_up ( dirpath, topdown=False, max_iter=None ): |
81 |
"""Generator that yields all (partial..full) filesystem paths contained |
82 |
in dirpath. |
83 |
@@ -75,7 +121,7 @@ def walk_up ( dirpath, topdown=False, max_iter=None ): |
84 |
def get_fs_dict ( |
85 |
initial_root, create_item=None, dict_cls=dict, |
86 |
dirname_filter=None, filename_filter=None, |
87 |
- include_root=False, prune_empty=False, file_key=None, |
88 |
+ include_root=False, toplevel_files=True, prune_empty=False, file_key=None, |
89 |
): |
90 |
"""Creates a dictionary-like object representing the filesystem structure |
91 |
starting at the given root directory. |
92 |
@@ -103,6 +149,8 @@ def get_fs_dict ( |
93 |
controls whether the return value should be a dict |
94 |
starting at initial_root or a dict containing the |
95 |
initial_root dict. Defaults to False. |
96 |
+ * toplevel_files -- whether to include top-level files in the dict (True) |
97 |
+ or not (False). Defaults to True. |
98 |
* prune_empty -- Whether to remove directory entries without any items. |
99 |
Defaults to False. |
100 |
* file_key -- Either a function that returns the dict key for a |
101 |
@@ -111,41 +159,43 @@ def get_fs_dict ( |
102 |
Inspired by http://code.activestate.com/recipes/577879-create-a-nested-dictionary-from-oswalk/ |
103 |
""" |
104 |
# TODO(could-do): max_depth=N |
105 |
- fsdict = dict_cls() |
106 |
- my_root = os.path.abspath ( initial_root ) |
107 |
+ fsdict = dict_cls() |
108 |
+ get_file_key = ( lambda x: x ) if file_key is None else file_key |
109 |
|
110 |
- get_file_key = ( lambda x: x ) if file_key is None else file_key |
111 |
|
112 |
- dictpath_begin = ( |
113 |
- 1 + ( my_root.rfind ( os.sep ) if include_root else len ( my_root ) ) |
114 |
- ) |
115 |
- |
116 |
- for root, dirnames, filenames in os.walk ( my_root ): |
117 |
- if dirname_filter: |
118 |
- dirnames[:] = [ d for d in dirnames if dirname_filter ( d ) ] |
119 |
+ for root, dict_relpath, dirnames, filenames in walk_relpath ( |
120 |
+ initial_root, include_root=include_root, prune_empty=prune_empty, |
121 |
+ dirname_filter=dirname_filter, filename_filter=filename_filter |
122 |
+ ): |
123 |
+ if dict_relpath: |
124 |
+ dictpath = dict_relpath.split ( os.sep ) |
125 |
+ parent = functools.reduce ( dict_cls.get, dictpath[:-1], fsdict ) |
126 |
|
127 |
- if filename_filter: |
128 |
- filenames[:] = [ f for f in filenames if filename_filter ( f ) ] |
129 |
+ if create_item is None: |
130 |
+ parent [dictpath[-1]] = dict_cls.fromkeys ( |
131 |
+ map ( get_file_key, filenames ) |
132 |
+ ) |
133 |
+ else: |
134 |
+ parent [dictpath[-1]] = dict_cls ( |
135 |
+ ( |
136 |
+ get_file_key ( fname ), |
137 |
+ create_item ( ( root + os.sep + fname ), fname, root ) |
138 |
+ ) |
139 |
+ for fname in filenames |
140 |
+ ) |
141 |
|
142 |
- if not prune_empty or filenames or dirnames: |
143 |
- dict_relpath = root[dictpath_begin:] |
144 |
+ elif not toplevel_files: |
145 |
+ pass |
146 |
|
147 |
- if dict_relpath: |
148 |
- dictpath = dict_relpath.split ( os.sep ) |
149 |
- parent = functools.reduce ( dict_cls.get, dictpath[:-1], fsdict ) |
150 |
+ elif create_item is None: |
151 |
+ for fname in filenames: |
152 |
+ fsdict [get_file_key(fname)] = None |
153 |
|
154 |
- if create_item is None: |
155 |
- parent [dictpath[-1]] = dict_cls.fromkeys ( |
156 |
- map ( get_file_key, filenames ) |
157 |
- ) |
158 |
- else: |
159 |
- parent [dictpath[-1]] = dict_cls ( |
160 |
- ( |
161 |
- get_file_key ( fname ), |
162 |
- create_item ( ( root + os.sep + fname ), fname, root ) |
163 |
- ) |
164 |
- for fname in filenames |
165 |
- ) |
166 |
+ else: |
167 |
+ for fname in filenames: |
168 |
+ fsdict [get_file_key(fname)] = create_item ( |
169 |
+ ( root + os.sep + fname ), fname, root |
170 |
+ ) |
171 |
# -- end for |
172 |
|
173 |
return fsdict |
174 |
@@ -203,13 +253,29 @@ def pwd_expanduser ( fspath, uid ): |
175 |
if not fspath or fspath[0] != '~': |
176 |
return fspath |
177 |
elif len ( fspath ) < 2: |
178 |
- return pwd.getpwuid ( uid ).pw_dir |
179 |
+ return get_home_dir ( uid ) |
180 |
elif fspath[1] == os.sep: |
181 |
- return pwd.getpwuid ( uid ).pw_dir + fspath[1:] |
182 |
+ return get_home_dir ( uid ) + fspath[1:] |
183 |
else: |
184 |
return fspath |
185 |
# --- end of pwd_expanduser (...) --- |
186 |
|
187 |
+def pwd_unexpanduser ( fspath, uid ): |
188 |
+ """Replaces a user's home directory with "~" in the given filesystem path. |
189 |
+ |
190 |
+ arguments: |
191 |
+ * fspath -- |
192 |
+ * uid -- |
193 |
+ """ |
194 |
+ home_dir = get_home_dir ( uid ) |
195 |
+ if not fspath.startswith ( home_dir ): |
196 |
+ return fspath |
197 |
+ elif len ( fspath ) == len ( home_dir ): |
198 |
+ return '~' |
199 |
+ else: |
200 |
+ return '~' + fspath[len(home_dir):] |
201 |
+# --- end of pwd_unexpanduser (...) --- |
202 |
+ |
203 |
def walk_copy_tree ( source, dest, subdir_root=False, **walk_kwargs ): |
204 |
"""Generator that iterates over the content of a filesystem tree starting |
205 |
at source and compares it to the filesystem tree starting at dest (which |
206 |
@@ -235,13 +301,10 @@ def walk_copy_tree ( source, dest, subdir_root=False, **walk_kwargs ): |
207 |
* dest -- absolute path to the dest root |
208 |
* subdir_root -- whether source should be a subdir of dest root or not |
209 |
Defaults to False. |
210 |
- * **walk_kwargs -- additional keyword arguments for os.walk() |
211 |
+ * **walk_kwargs -- additional keyword arguments for walk_relpath() |
212 |
""" |
213 |
- source_path = os.path.abspath ( source ) |
214 |
- dest_path = os.path.abspath ( dest ) |
215 |
- relpath_begin = 1 + ( |
216 |
- source_path.rfind ( os.sep ) if subdir_root else len ( source_path ) |
217 |
- ) |
218 |
+ source_path = os.path.abspath ( source ) |
219 |
+ dest_path = os.path.abspath ( dest ) |
220 |
|
221 |
get_entry = lambda path: ( |
222 |
path, os.lstat ( path ) if os.path.lexists ( path ) else None |
223 |
@@ -250,8 +313,9 @@ def walk_copy_tree ( source, dest, subdir_root=False, **walk_kwargs ): |
224 |
[ ( get_entry ( s + name ), get_entry ( d + name ) ) for name in names ] |
225 |
) |
226 |
|
227 |
- for root, dirnames, filenames in os.walk ( source, **walk_kwargs ): |
228 |
- root_rel = root[relpath_begin:] |
229 |
+ for root, root_rel, dirnames, filenames in walk_relpath ( |
230 |
+ source_path, include_root=subdir_root, **walk_kwargs |
231 |
+ ): |
232 |
root_dest = ( dest + os.sep + root_rel if root_rel else dest ) |
233 |
|
234 |
dirs = get_stat_list ( root + os.sep, root_dest + os.sep, dirnames ) |
235 |
|
236 |
diff --git a/roverlay/setupscript/hookenv.py b/roverlay/setupscript/hookenv.py |
237 |
index 23b1c68..46a2344 100644 |
238 |
--- a/roverlay/setupscript/hookenv.py |
239 |
+++ b/roverlay/setupscript/hookenv.py |
240 |
@@ -639,6 +639,7 @@ class NestedHookScriptDirBase ( HookScriptDirBase ): |
241 |
include_root = False, |
242 |
prune_empty = prune_empty, |
243 |
file_key = get_script_name, |
244 |
+ toplevel_files = False, |
245 |
) |
246 |
self.scripts.update ( new_scripts ) |
247 |
self.scan_scripts() |