source: soft/build_system/build_system/repsys/tags/V1_6_2/RepSys/svn.py @ 1

Last change on this file since 1 was 1, checked in by fasma, 12 years ago

Initial Import from Mandriva's soft revision 224062 and package revision 45733

File size: 12.3 KB
Line 
1from RepSys import Error, config, pexpect
2from RepSys.util import execcmd, get_auth
3import sys
4import re
5import time
6
7__all__ = ["SVN", "SVNLook", "SVNLogEntry"]
8
9class SVNLogEntry:
10    def __init__(self, revision, author, date):
11        self.revision = revision
12        self.author = author
13        self.date = date
14        self.lines = []
15
16    def __cmp__(self, other):
17        return cmp(self.date, other.date)
18
19class SVN:
20    def __init__(self, username=None, password=None, noauth=0, baseurl=None):
21        self.noauth = noauth or (
22            baseurl and (
23                baseurl.startswith("file:") or
24                baseurl.startswith("svn+ssh:")))
25        if not self.noauth: # argh
26            self.username, self.password = get_auth()
27
28
29    def _execsvn(self, *args, **kwargs):
30        cmdstr = "svn "+" ".join(args)
31        if kwargs.get("local") or kwargs.get("noauth") or self.noauth:
32            return execcmd(cmdstr, **kwargs)
33        show = kwargs.get("show")
34        noerror = kwargs.get("noerror")
35        p = pexpect.spawn(cmdstr, timeout=1)
36        p.setmaxread(1024)
37        p.setecho(False)
38        outlist = []
39        while True:
40            i = p.expect_exact([pexpect.EOF, pexpect.TIMEOUT,
41                    "username:", "password:",
42                    "(p)ermanently?",
43                    "Authorization failed"])
44            if i == 0:
45                if show and p.before:
46                    print p.before,
47                outlist.append(p.before)
48                break
49            elif i == 1:
50                if show and p.before:
51                    print p.before,
52                outlist.append(p.before)
53            elif i == 2:
54                p.sendline(self.username)
55                outlist = []
56            elif i == 3:
57                p.sendline(self.password)
58                outlist = []
59            elif i == 4:
60                p.sendline("p")
61                outlist = []
62            elif i == 5:
63                if not noerror:
64                    raise Error, "authorization failed"
65                else:
66                    break
67        while p.isalive():
68            try:
69                time.sleep(1)
70            except (pexpect.TIMEOUT, pexpect.EOF):
71                # Continue until the child dies
72                pass
73        status, output = p.exitstatus, "".join(outlist).strip()
74        if status != 0 and not kwargs.get("noerror"):
75            sys.stderr.write(cmdstr)
76            sys.stderr.write("\n")
77            sys.stderr.write(output)
78            sys.stderr.write("\n")
79            raise Error, "command failed: "+cmdstr
80        return status, output
81
82    def _execsvn_success(self, *args, **kwargs):
83        status, output = self._execsvn(*args, **kwargs)
84        return status == 0
85
86    def _add_log(self, cmd_args, received_kwargs, optional=0):
87        if (not optional or
88            received_kwargs.has_key("log") or
89            received_kwargs.has_key("logfile")):
90            ret = received_kwargs.get("log")
91            if ret is not None:
92                cmd_args.append("-m '%s'" % ret)
93            ret = received_kwargs.get("logfile")
94            if ret is not None:
95                cmd_args.append("-F '%s'" % ret)
96
97    def _add_revision(self, cmd_args, received_kwargs, optional=0):
98        if not optional or received_kwargs.has_key("rev"):
99            ret = received_kwargs.get("rev")
100            if isinstance(ret, basestring):
101                try:
102                    ret = int(ret)
103                except ValueError:
104                    raise Error, "invalid revision provided"
105            if ret:
106                cmd_args.append("-r %d" % ret)
107       
108    def add(self, path, **kwargs):
109        cmd = ["add", path]
110        return self._execsvn_success(noauth=1, *cmd, **kwargs)
111
112    def copy(self, pathfrom, pathto, **kwargs):
113        cmd = ["copy", pathfrom, pathto]
114        self._add_revision(cmd, kwargs, optional=1)
115        self._add_log(cmd, kwargs)
116        return self._execsvn_success(*cmd, **kwargs)
117
118    def remove(self, path, force=0, **kwargs):
119        cmd = ["remove", path]
120        self._add_log(cmd, kwargs)
121        if force:
122            cmd.append("--force")
123        return self._execsvn_success(*cmd, **kwargs)
124
125    def mkdir(self, path, **kwargs):
126        cmd = ["mkdir", path]
127        self._add_log(cmd, kwargs)
128        return self._execsvn_success(*cmd, **kwargs)
129
130    def commit(self, path, **kwargs):
131        cmd = ["commit", path]
132        self._add_log(cmd, kwargs)
133        return self._execsvn_success(*cmd, **kwargs)
134
135    def export(self, url, targetpath, **kwargs):
136        cmd = ["export", "'%s'" % url, targetpath]
137        self._add_revision(cmd, kwargs, optional=1)
138        return self._execsvn_success(*cmd, **kwargs)
139
140    def checkout(self, url, targetpath, **kwargs):
141        cmd = ["checkout", "'%s'" % url, targetpath]
142        self._add_revision(cmd, kwargs, optional=1)
143        return self._execsvn_success(*cmd, **kwargs)
144 
145    def propset(self, propname, value, targets, **kwargs):
146        cmd = ["propset", propname, "'%s'" % value, targets]
147        return self._execsvn_success(*cmd, **kwargs)
148
149    def propedit(self, propname, target, **kwargs):
150        cmd = ["propedit", propname, target]
151        if kwargs.get("rev"):
152            cmd.append("--revprop")
153            self._add_revision(cmd, kwargs)
154        return self._execsvn_success(local=True, show=True, *cmd, **kwargs)
155
156    def revision(self, path, **kwargs):
157        cmd = ["info", path]
158        status, output = self._execsvn(local=True, *cmd, **kwargs)
159        if status == 0:
160            for line in output.splitlines():
161                if line.startswith("Revision: "):
162                    return int(line.split()[1])
163        return None
164         
165    def info(self, path, **kwargs):
166        cmd = ["info", path]
167        status, output = self._execsvn(local=True, *cmd, **kwargs)
168        if status == 0:
169            return output.splitlines()
170        return None
171         
172    def ls(self, path, **kwargs):
173        cmd = ["ls", path]
174        status, output = self._execsvn(*cmd, **kwargs)
175        if status == 0:
176            return output.split()
177        return None
178
179    def status(self, path, **kwargs):
180        cmd = ["status", path]
181        if kwargs.get("verbose"):
182            cmd.append("-v")
183        status, output = self._execsvn(*cmd, **kwargs)
184        if status == 0:
185            return [x.split() for x in output.splitlines()]
186        return None
187
188    def cleanup(self, path, **kwargs):
189        cmd = ["cleanup", path]
190        return self._execsvn_success(*cmd, **kwargs)
191
192    def revert(self, path, **kwargs):
193        cmd = ["revert", path]
194        status, output = self._execsvn(*cmd, **kwargs)
195        if status == 0:
196            return [x.split() for x in output.split()]
197        return None
198
199    def update(self, path, **kwargs):
200        cmd = ["update", path]
201        self._add_revision(cmd, kwargs, optional=1)
202        status, output = self._execsvn(*cmd, **kwargs)
203        if status == 0:
204            return [x.split() for x in output.split()]
205        return None
206
207    def merge(self, url1, url2=None, rev1=None, rev2=None, path=None, **kwargs):
208        cmd = ["merge"]
209        if rev1 and rev2 and not url2:
210            cmd.append("-r")
211            cmd.append("%s:%s" % (rev1, rev2))
212            cmd.append(url1)
213        else:
214            if not url2:
215                raise ValueError, \
216                      "url2 needed if two revisions are not provided"
217            if rev1:
218                cmd.append("%s@%s" % (url1, rev1))
219            else:
220                cmd.append(url1)
221            if rev2:
222                cmd.append("%s@%s" % (url2, rev2))
223            else:
224                cmd.append(url2)
225        if path:
226            cmd.append(path)
227        status, output = self._execsvn(*cmd, **kwargs)
228        if status == 0:
229            return [x.split() for x in output.split()]
230        return None
231
232    def diff(self, pathurl1, pathurl2=None, **kwargs):
233        cmd = ["diff", pathurl1]
234        self._add_revision(cmd, kwargs, optional=1)
235        if pathurl2:
236            cmd.append(pathurl2)
237        status, output = self._execsvn(*cmd, **kwargs)
238        if status == 0:
239            return output
240        return None
241
242    def cat(self, url, **kwargs):
243        cmd = ["cat", url]
244        self._add_revision(cmd, kwargs, optional=1)
245        status, output = self._execsvn(*cmd, **kwargs)
246        if status == 0:
247            return output
248        return None
249
250    def log(self, url, start=None, end=0, limit=None, **kwargs):
251        cmd = ["log", url]
252        if start is not None or end != 0:
253            if start is not None and type(start) is not type(0):
254                try:
255                    start = int(start)
256                except (ValueError, TypeError):
257                    raise Error, "invalid log start revision provided"
258            if type(end) is not type(0):
259                try:
260                    end = int(end)
261                except (ValueError, TypeError):
262                    raise Error, "invalid log end revision provided"
263            start = start or "HEAD"
264            cmd.append("-r %s:%s" % (start, end))
265        if limit is not None:
266            try:
267                limit = int(limit)
268            except (ValueError, TypeError):
269                raise Error, "invalid limit number provided"
270            cmd.append("--limit %d" % limit)
271        status, output = self._execsvn(*cmd, **kwargs)
272        if status != 0:
273            return None
274
275        revheader = re.compile("^r(?P<revision>[0-9]+) \| (?P<author>[^\|]+) \| (?P<date>[^\|]+) \| (?P<lines>[0-9]+) (?:line|lines)$")
276        logseparator = "-"*72
277        linesleft = 0
278        entry = None
279        log = []
280        emptyline = 0
281        for line in output.splitlines():
282            if emptyline:
283                emptyline = 0
284                continue
285            line = line.rstrip()
286            if linesleft == 0:
287                if line != logseparator:
288                    m = revheader.match(line)
289                    if m:
290                        linesleft = int(m.group("lines"))
291                        timestr = " ".join(m.group("date").split()[:2])
292                        timetuple = time.strptime(timestr,
293                                                  "%Y-%m-%d %H:%M:%S")
294                        entry = SVNLogEntry(int(m.group("revision")),
295                                            m.group("author"), timetuple)
296                        log.append(entry)
297                        emptyline = 1
298            else:
299                entry.lines.append(line)
300                linesleft -= 1
301        log.sort()
302        log.reverse()
303        return log
304
305class SVNLook:
306    def __init__(self, repospath, txn=None, rev=None):
307        self.repospath = repospath
308        self.txn = txn
309        self.rev = rev
310
311    def _execsvnlook(self, cmd, *args, **kwargs):
312        execcmd_args = ["svnlook", cmd, self.repospath]
313        self._add_txnrev(execcmd_args, kwargs)
314        execcmd_args += args
315        execcmd_kwargs = {}
316        keywords = ["show", "noerror"]
317        for key in keywords:
318            if kwargs.has_key(key):
319                execcmd_kwargs[key] = kwargs[key]
320        return execcmd(*execcmd_args, **execcmd_kwargs)
321
322    def _add_txnrev(self, cmd_args, received_kwargs):
323        if received_kwargs.has_key("txn"):
324            txn = received_kwargs.get("txn")
325            if txn is not None:
326                cmd_args += ["-t", txn]
327        elif self.txn is not None:
328            cmd_args += ["-t", self.txn]
329        if received_kwargs.has_key("rev"):
330            rev = received_kwargs.get("rev")
331            if rev is not None:
332                cmd_args += ["-r", rev]
333        elif self.rev is not None:
334            cmd_args += ["-r", self.rev]
335
336    def changed(self, **kwargs):
337        status, output = self._execsvnlook("changed", **kwargs)
338        if status != 0:
339            return None
340        changes = []
341        for line in output.splitlines():
342            line = line.rstrip()
343            if not line:
344                continue
345            entry = [None, None, None]
346            changedata, changeprop, path = None, None, None
347            if line[0] != "_":
348                changedata = line[0]
349            if line[1] != " ":
350                changeprop = line[1]
351            path = line[4:]
352            changes.append((changedata, changeprop, path))
353        return changes
354
355    def author(self, **kwargs):
356        status, output = self._execsvnlook("author", **kwargs)
357        if status != 0:
358            return None
359        return output.strip()
360
361# vim:et:ts=4:sw=4
Note: See TracBrowser for help on using the repository browser.