##// END OF EJS Templates
remove unused function get_repo_paths...
Mads Kiilerich -
r3092:cd25fa6f beta
parent child Browse files
Show More
@@ -1,255 +1,240 b''
1 """
1 """
2 Utitlites aimed to help achieve mostly basic tasks.
2 Utitlites aimed to help achieve mostly basic tasks.
3 """
3 """
4 from __future__ import division
4 from __future__ import division
5
5
6 import re
6 import re
7 import time
7 import time
8 import datetime
8 import datetime
9 import os.path
9 import os.path
10 from subprocess import Popen, PIPE
10 from subprocess import Popen, PIPE
11 from rhodecode.lib.vcs.exceptions import VCSError
11 from rhodecode.lib.vcs.exceptions import VCSError
12 from rhodecode.lib.vcs.exceptions import RepositoryError
12 from rhodecode.lib.vcs.exceptions import RepositoryError
13 from rhodecode.lib.vcs.utils.paths import abspath
13 from rhodecode.lib.vcs.utils.paths import abspath
14
14
15 ALIASES = ['hg', 'git']
15 ALIASES = ['hg', 'git']
16
16
17
17
18 def get_scm(path, search_up=False, explicit_alias=None):
18 def get_scm(path, search_up=False, explicit_alias=None):
19 """
19 """
20 Returns one of alias from ``ALIASES`` (in order of precedence same as
20 Returns one of alias from ``ALIASES`` (in order of precedence same as
21 shortcuts given in ``ALIASES``) and top working dir path for the given
21 shortcuts given in ``ALIASES``) and top working dir path for the given
22 argument. If no scm-specific directory is found or more than one scm is
22 argument. If no scm-specific directory is found or more than one scm is
23 found at that directory, ``VCSError`` is raised.
23 found at that directory, ``VCSError`` is raised.
24
24
25 :param search_up: if set to ``True``, this function would try to
25 :param search_up: if set to ``True``, this function would try to
26 move up to parent directory every time no scm is recognized for the
26 move up to parent directory every time no scm is recognized for the
27 currently checked path. Default: ``False``.
27 currently checked path. Default: ``False``.
28 :param explicit_alias: can be one of available backend aliases, when given
28 :param explicit_alias: can be one of available backend aliases, when given
29 it will return given explicit alias in repositories under more than one
29 it will return given explicit alias in repositories under more than one
30 version control, if explicit_alias is different than found it will raise
30 version control, if explicit_alias is different than found it will raise
31 VCSError
31 VCSError
32 """
32 """
33 if not os.path.isdir(path):
33 if not os.path.isdir(path):
34 raise VCSError("Given path %s is not a directory" % path)
34 raise VCSError("Given path %s is not a directory" % path)
35
35
36 def get_scms(path):
36 def get_scms(path):
37 return [(scm, path) for scm in get_scms_for_path(path)]
37 return [(scm, path) for scm in get_scms_for_path(path)]
38
38
39 found_scms = get_scms(path)
39 found_scms = get_scms(path)
40 while not found_scms and search_up:
40 while not found_scms and search_up:
41 newpath = abspath(path, '..')
41 newpath = abspath(path, '..')
42 if newpath == path:
42 if newpath == path:
43 break
43 break
44 path = newpath
44 path = newpath
45 found_scms = get_scms(path)
45 found_scms = get_scms(path)
46
46
47 if len(found_scms) > 1:
47 if len(found_scms) > 1:
48 for scm in found_scms:
48 for scm in found_scms:
49 if scm[0] == explicit_alias:
49 if scm[0] == explicit_alias:
50 return scm
50 return scm
51 raise VCSError('More than one [%s] scm found at given path %s'
51 raise VCSError('More than one [%s] scm found at given path %s'
52 % (','.join((x[0] for x in found_scms)), path))
52 % (','.join((x[0] for x in found_scms)), path))
53
53
54 if len(found_scms) is 0:
54 if len(found_scms) is 0:
55 raise VCSError('No scm found at given path %s' % path)
55 raise VCSError('No scm found at given path %s' % path)
56
56
57 return found_scms[0]
57 return found_scms[0]
58
58
59
59
60 def get_scms_for_path(path):
60 def get_scms_for_path(path):
61 """
61 """
62 Returns all scm's found at the given path. If no scm is recognized
62 Returns all scm's found at the given path. If no scm is recognized
63 - empty list is returned.
63 - empty list is returned.
64
64
65 :param path: path to directory which should be checked. May be callable.
65 :param path: path to directory which should be checked. May be callable.
66
66
67 :raises VCSError: if given ``path`` is not a directory
67 :raises VCSError: if given ``path`` is not a directory
68 """
68 """
69 from rhodecode.lib.vcs.backends import get_backend
69 from rhodecode.lib.vcs.backends import get_backend
70 if hasattr(path, '__call__'):
70 if hasattr(path, '__call__'):
71 path = path()
71 path = path()
72 if not os.path.isdir(path):
72 if not os.path.isdir(path):
73 raise VCSError("Given path %r is not a directory" % path)
73 raise VCSError("Given path %r is not a directory" % path)
74
74
75 result = []
75 result = []
76 for key in ALIASES:
76 for key in ALIASES:
77 dirname = os.path.join(path, '.' + key)
77 dirname = os.path.join(path, '.' + key)
78 if os.path.isdir(dirname):
78 if os.path.isdir(dirname):
79 result.append(key)
79 result.append(key)
80 continue
80 continue
81 dirname = os.path.join(path, 'rm__.' + key)
81 dirname = os.path.join(path, 'rm__.' + key)
82 if os.path.isdir(dirname):
82 if os.path.isdir(dirname):
83 return [None]
83 return [None]
84 # We still need to check if it's not bare repository as
84 # We still need to check if it's not bare repository as
85 # bare repos don't have working directories
85 # bare repos don't have working directories
86 try:
86 try:
87 get_backend(key)(path)
87 get_backend(key)(path)
88 result.append(key)
88 result.append(key)
89 continue
89 continue
90 except RepositoryError:
90 except RepositoryError:
91 # Wrong backend
91 # Wrong backend
92 pass
92 pass
93 except VCSError:
93 except VCSError:
94 # No backend at all
94 # No backend at all
95 pass
95 pass
96 return result
96 return result
97
97
98
98
99 def get_repo_paths(path):
100 """
101 Returns path's subdirectories which seems to be a repository.
102 """
103 repo_paths = []
104 dirnames = (os.path.abspath(dirname) for dirname in os.listdir(path))
105 for dirname in dirnames:
106 try:
107 get_scm(dirname)
108 repo_paths.append(dirname)
109 except VCSError:
110 pass
111 return repo_paths
112
113
114 def run_command(cmd, *args):
99 def run_command(cmd, *args):
115 """
100 """
116 Runs command on the system with given ``args``.
101 Runs command on the system with given ``args``.
117 """
102 """
118 command = ' '.join((cmd, args))
103 command = ' '.join((cmd, args))
119 p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE)
104 p = Popen(command, shell=True, stdout=PIPE, stderr=PIPE)
120 stdout, stderr = p.communicate()
105 stdout, stderr = p.communicate()
121 return p.retcode, stdout, stderr
106 return p.retcode, stdout, stderr
122
107
123
108
124 def get_highlighted_code(name, code, type='terminal'):
109 def get_highlighted_code(name, code, type='terminal'):
125 """
110 """
126 If pygments are available on the system
111 If pygments are available on the system
127 then returned output is colored. Otherwise
112 then returned output is colored. Otherwise
128 unchanged content is returned.
113 unchanged content is returned.
129 """
114 """
130 import logging
115 import logging
131 try:
116 try:
132 import pygments
117 import pygments
133 pygments
118 pygments
134 except ImportError:
119 except ImportError:
135 return code
120 return code
136 from pygments import highlight
121 from pygments import highlight
137 from pygments.lexers import guess_lexer_for_filename, ClassNotFound
122 from pygments.lexers import guess_lexer_for_filename, ClassNotFound
138 from pygments.formatters import TerminalFormatter
123 from pygments.formatters import TerminalFormatter
139
124
140 try:
125 try:
141 lexer = guess_lexer_for_filename(name, code)
126 lexer = guess_lexer_for_filename(name, code)
142 formatter = TerminalFormatter()
127 formatter = TerminalFormatter()
143 content = highlight(code, lexer, formatter)
128 content = highlight(code, lexer, formatter)
144 except ClassNotFound:
129 except ClassNotFound:
145 logging.debug("Couldn't guess Lexer, will not use pygments.")
130 logging.debug("Couldn't guess Lexer, will not use pygments.")
146 content = code
131 content = code
147 return content
132 return content
148
133
149 def parse_changesets(text):
134 def parse_changesets(text):
150 """
135 """
151 Returns dictionary with *start*, *main* and *end* ids.
136 Returns dictionary with *start*, *main* and *end* ids.
152
137
153 Examples::
138 Examples::
154
139
155 >>> parse_changesets('aaabbb')
140 >>> parse_changesets('aaabbb')
156 {'start': None, 'main': 'aaabbb', 'end': None}
141 {'start': None, 'main': 'aaabbb', 'end': None}
157 >>> parse_changesets('aaabbb..cccddd')
142 >>> parse_changesets('aaabbb..cccddd')
158 {'start': 'aaabbb', 'main': None, 'end': 'cccddd'}
143 {'start': 'aaabbb', 'main': None, 'end': 'cccddd'}
159
144
160 """
145 """
161 text = text.strip()
146 text = text.strip()
162 CID_RE = r'[a-zA-Z0-9]+'
147 CID_RE = r'[a-zA-Z0-9]+'
163 if not '..' in text:
148 if not '..' in text:
164 m = re.match(r'^(?P<cid>%s)$' % CID_RE, text)
149 m = re.match(r'^(?P<cid>%s)$' % CID_RE, text)
165 if m:
150 if m:
166 return {
151 return {
167 'start': None,
152 'start': None,
168 'main': text,
153 'main': text,
169 'end': None,
154 'end': None,
170 }
155 }
171 else:
156 else:
172 RE = r'^(?P<start>%s)?\.{2,3}(?P<end>%s)?$' % (CID_RE, CID_RE)
157 RE = r'^(?P<start>%s)?\.{2,3}(?P<end>%s)?$' % (CID_RE, CID_RE)
173 m = re.match(RE, text)
158 m = re.match(RE, text)
174 if m:
159 if m:
175 result = m.groupdict()
160 result = m.groupdict()
176 result['main'] = None
161 result['main'] = None
177 return result
162 return result
178 raise ValueError("IDs not recognized")
163 raise ValueError("IDs not recognized")
179
164
180 def parse_datetime(text):
165 def parse_datetime(text):
181 """
166 """
182 Parses given text and returns ``datetime.datetime`` instance or raises
167 Parses given text and returns ``datetime.datetime`` instance or raises
183 ``ValueError``.
168 ``ValueError``.
184
169
185 :param text: string of desired date/datetime or something more verbose,
170 :param text: string of desired date/datetime or something more verbose,
186 like *yesterday*, *2weeks 3days*, etc.
171 like *yesterday*, *2weeks 3days*, etc.
187 """
172 """
188
173
189 text = text.strip().lower()
174 text = text.strip().lower()
190
175
191 INPUT_FORMATS = (
176 INPUT_FORMATS = (
192 '%Y-%m-%d %H:%M:%S',
177 '%Y-%m-%d %H:%M:%S',
193 '%Y-%m-%d %H:%M',
178 '%Y-%m-%d %H:%M',
194 '%Y-%m-%d',
179 '%Y-%m-%d',
195 '%m/%d/%Y %H:%M:%S',
180 '%m/%d/%Y %H:%M:%S',
196 '%m/%d/%Y %H:%M',
181 '%m/%d/%Y %H:%M',
197 '%m/%d/%Y',
182 '%m/%d/%Y',
198 '%m/%d/%y %H:%M:%S',
183 '%m/%d/%y %H:%M:%S',
199 '%m/%d/%y %H:%M',
184 '%m/%d/%y %H:%M',
200 '%m/%d/%y',
185 '%m/%d/%y',
201 )
186 )
202 for format in INPUT_FORMATS:
187 for format in INPUT_FORMATS:
203 try:
188 try:
204 return datetime.datetime(*time.strptime(text, format)[:6])
189 return datetime.datetime(*time.strptime(text, format)[:6])
205 except ValueError:
190 except ValueError:
206 pass
191 pass
207
192
208 # Try descriptive texts
193 # Try descriptive texts
209 if text == 'tomorrow':
194 if text == 'tomorrow':
210 future = datetime.datetime.now() + datetime.timedelta(days=1)
195 future = datetime.datetime.now() + datetime.timedelta(days=1)
211 args = future.timetuple()[:3] + (23, 59, 59)
196 args = future.timetuple()[:3] + (23, 59, 59)
212 return datetime.datetime(*args)
197 return datetime.datetime(*args)
213 elif text == 'today':
198 elif text == 'today':
214 return datetime.datetime(*datetime.datetime.today().timetuple()[:3])
199 return datetime.datetime(*datetime.datetime.today().timetuple()[:3])
215 elif text == 'now':
200 elif text == 'now':
216 return datetime.datetime.now()
201 return datetime.datetime.now()
217 elif text == 'yesterday':
202 elif text == 'yesterday':
218 past = datetime.datetime.now() - datetime.timedelta(days=1)
203 past = datetime.datetime.now() - datetime.timedelta(days=1)
219 return datetime.datetime(*past.timetuple()[:3])
204 return datetime.datetime(*past.timetuple()[:3])
220 else:
205 else:
221 days = 0
206 days = 0
222 matched = re.match(
207 matched = re.match(
223 r'^((?P<weeks>\d+) ?w(eeks?)?)? ?((?P<days>\d+) ?d(ays?)?)?$', text)
208 r'^((?P<weeks>\d+) ?w(eeks?)?)? ?((?P<days>\d+) ?d(ays?)?)?$', text)
224 if matched:
209 if matched:
225 groupdict = matched.groupdict()
210 groupdict = matched.groupdict()
226 if groupdict['days']:
211 if groupdict['days']:
227 days += int(matched.groupdict()['days'])
212 days += int(matched.groupdict()['days'])
228 if groupdict['weeks']:
213 if groupdict['weeks']:
229 days += int(matched.groupdict()['weeks']) * 7
214 days += int(matched.groupdict()['weeks']) * 7
230 past = datetime.datetime.now() - datetime.timedelta(days=days)
215 past = datetime.datetime.now() - datetime.timedelta(days=days)
231 return datetime.datetime(*past.timetuple()[:3])
216 return datetime.datetime(*past.timetuple()[:3])
232
217
233 raise ValueError('Wrong date: "%s"' % text)
218 raise ValueError('Wrong date: "%s"' % text)
234
219
235
220
236 def get_dict_for_attrs(obj, attrs):
221 def get_dict_for_attrs(obj, attrs):
237 """
222 """
238 Returns dictionary for each attribute from given ``obj``.
223 Returns dictionary for each attribute from given ``obj``.
239 """
224 """
240 data = {}
225 data = {}
241 for attr in attrs:
226 for attr in attrs:
242 data[attr] = getattr(obj, attr)
227 data[attr] = getattr(obj, attr)
243 return data
228 return data
244
229
245
230
246 def get_total_seconds(timedelta):
231 def get_total_seconds(timedelta):
247 """
232 """
248 Backported for Python 2.5.
233 Backported for Python 2.5.
249
234
250 See http://docs.python.org/library/datetime.html.
235 See http://docs.python.org/library/datetime.html.
251 """
236 """
252 return ((timedelta.microseconds + (
237 return ((timedelta.microseconds + (
253 timedelta.seconds +
238 timedelta.seconds +
254 timedelta.days * 24 * 60 * 60
239 timedelta.days * 24 * 60 * 60
255 ) * 10**6) / 10**6)
240 ) * 10**6) / 10**6)
General Comments 0
You need to be logged in to leave comments. Login now