|
1 #!/usr/bin/python2.5 |
|
2 # |
|
3 # Copyright 2008 the Melange authors. |
|
4 # |
|
5 # Licensed under the Apache License, Version 2.0 (the "License"); |
|
6 # you may not use this file except in compliance with the License. |
|
7 # You may obtain a copy of the License at |
|
8 # |
|
9 # http://www.apache.org/licenses/LICENSE-2.0 |
|
10 # |
|
11 # Unless required by applicable law or agreed to in writing, software |
|
12 # distributed under the License is distributed on an "AS IS" BASIS, |
|
13 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
14 # See the License for the specific language governing permissions and |
|
15 # limitations under the License. |
|
16 |
|
17 """Helper functions that wrap the pysvn Python svn bindings. |
|
18 |
|
19 ls(): returns list of selected directory entries from an SVN repository |
|
20 lsDirs(): wrapper around ls() that only returns node_kind.dir entries |
|
21 lsFiles(): wrapper around ls() that only returns node_kind.files entries |
|
22 exists(): returns True if repo_path exists in the svn repository |
|
23 |
|
24 DEF_SVN_REPO: default HTTPS path to the SoC project SVN repo |
|
25 PYSVN_ALL_NODE_KINDS: all directory entry node_kinds supported by pysvn |
|
26 PYSVN_FILE_DIR_NODE_KINDS: actual file and directory node_kinds |
|
27 """ |
|
28 |
|
29 __authors__ = [ |
|
30 # alphabetical order by last name, please |
|
31 '"Todd Larsen" <tlarsen@google.com>', |
|
32 ] |
|
33 |
|
34 |
|
35 import pysvn |
|
36 |
|
37 |
|
38 #: default HTTPS path to the SoC project SVN repo |
|
39 DEF_SVN_REPO = 'https://soc.googlecode.com/svn/' |
|
40 |
|
41 #: all of the directory entry node_kinds supported py pysvn |
|
42 PYSVN_ALL_NODE_KINDS = set([pysvn.node_kind.none, pysvn.node_kind.dir, |
|
43 pysvn.node_kind.file, pysvn.node_kind.unknown]) |
|
44 |
|
45 #: actual file and directory node_kinds (includes dir and file, but excludes |
|
46 #: the "non-file" none and unknown) |
|
47 PYSVN_FILE_DIR_NODE_KINDS = set([pysvn.node_kind.dir, pysvn.node_kind.file]) |
|
48 |
|
49 |
|
50 def ls(client, repo_path, keep_kinds=PYSVN_FILE_DIR_NODE_KINDS, **kwargs): |
|
51 """Returns a list of (possibly recursive) svn repo directory entries. |
|
52 |
|
53 Args: |
|
54 client: pysvn Client instance |
|
55 repo_path: absolute svn repository path URL, including the server and |
|
56 directory path within the repo |
|
57 keep_kinds: types of directory entries to keep in the returned list; a |
|
58 collection of pysvn.node_kind objects; default is |
|
59 PYSVN_FILE_DIR_NODE_KINDS |
|
60 **kwargs: keyword arguments passed on to Client.list(), including: |
|
61 recurse: indicates if return results should include entries from |
|
62 subdirectories of repo_path as well; default is False |
|
63 |
|
64 Returns: |
|
65 list of (Unicode, coming from pysvn) strings representing the entries |
|
66 of types indicated by keep_kinds; strings are altered to match the |
|
67 output of the actual 'svn ls' command: repo_path prefix is removed, |
|
68 directories end with the / separator. |
|
69 """ |
|
70 raw_entries = client.list(repo_path, **kwargs) |
|
71 entries = [] |
|
72 |
|
73 # Find shortest repos_path that is a 'dir' entry; will be prefix of all |
|
74 # other entries, since Client.list() always returns repo_path as one of |
|
75 # the entries. It is easier and more reliable to do this search than to |
|
76 # try to manipulate repo_path into the prefix (since the user could supply |
|
77 # any number of valid, but different, formats). |
|
78 shortest_path = raw_entries[0][0].repos_path |
|
79 |
|
80 for svn_list, _ in raw_entries: |
|
81 if svn_list.kind == pysvn.node_kind.dir: |
|
82 entry_path = svn_list.repos_path |
|
83 |
|
84 if len(entry_path) < len(shortest_path): |
|
85 shortest_path = entry_path |
|
86 |
|
87 # normalize the path name of entry_prefix to include a trailing separator |
|
88 entry_prefix = shortest_path |
|
89 |
|
90 if not entry_prefix.endswith('/'): |
|
91 entry_prefix = entry_prefix + '/' |
|
92 |
|
93 for svn_list,_ in raw_entries: |
|
94 # only include requested node kinds (dir, file, etc.) |
|
95 if svn_list.kind not in keep_kinds: |
|
96 continue |
|
97 |
|
98 entry_path = svn_list.repos_path |
|
99 |
|
100 # omit the repo_path directory entry itself (simiilar to omitting '.' as |
|
101 # is done by the actual 'svn ls' command) |
|
102 if entry_path == shortest_path: |
|
103 continue |
|
104 |
|
105 # all entry_paths except for the shortest should start with that |
|
106 # shortest entry_prefix, so assert that and remove the prefix |
|
107 assert entry_path.startswith(entry_prefix) |
|
108 entry_path = entry_path[len(entry_prefix):] |
|
109 |
|
110 # normalize directory entry_paths to include a trailing separator |
|
111 if ((svn_list.kind == pysvn.node_kind.dir) |
|
112 and (not entry_path.endswith('/'))): |
|
113 entry_path = entry_path + '/' |
|
114 |
|
115 entries.append(entry_path) |
|
116 |
|
117 return entries |
|
118 |
|
119 |
|
120 def lsDirs(client, repo_path, **kwargs): |
|
121 """Wrapper around ls() that only returns node_kind.dir entries. |
|
122 """ |
|
123 return ls(client, repo_path, keep_kinds=(pysvn.node_kind.dir,), **kwargs) |
|
124 |
|
125 |
|
126 def lsFiles(client, repo_path, **kwargs): |
|
127 """Wrapper around ls() that only returns node_kind.files entries. |
|
128 """ |
|
129 return ls(client, repo_path, keep_kinds=(pysvn.node_kind.file,), **kwargs) |
|
130 |
|
131 |
|
132 def exists(client, repo_path): |
|
133 """Returns True if repo_path exists in the svn repository.""" |
|
134 try: |
|
135 raw_entries = client.list(repo_path) |
|
136 return True |
|
137 except pysvn._pysvn.ClientError: |
|
138 # Client.list() raises an exception if the path is not present in the repo |
|
139 return False |