source: soft/build_system/build_system/repsys/tags/V1_5_7/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: 11.7 KB
Line 
1from RepSys import Error, config, pexpect
2from RepSys.util import execcmd
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):
21        if not username:
22            username = config.get("auth", "username")
23        if not password:
24            password = config.get("auth", "password")
25
26        self.username = username
27        self.password = password
28
29    def _execsvn(self, *args, **kwargs):
30        cmdstr = "svn "+" ".join(args)
31        if kwargs.get("local"):
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 for '%s':" % self.username,
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 checkout(self, url, targetpath, **kwargs):
136        cmd = ["checkout", "'%s'" % url, targetpath]
137        self._add_revision(cmd, kwargs, optional=1)
138        return self._execsvn_success(*cmd, **kwargs)
139 
140    def propset(self, propname, value, targets, **kwargs):
141        cmd = ["propset", propname, "'%s'" % value, targets]
142        return self._execsvn_success(*cmd, **kwargs)
143
144    def propedit(self, propname, target, **kwargs):
145        cmd = ["propedit", propname, target]
146        if kwargs.get("rev"):
147            cmd.append("--revprop")
148            self._add_revision(cmd, kwargs)
149        return self._execsvn_success(local=True, show=True, *cmd, **kwargs)
150
151    def revision(self, path, **kwargs):
152        cmd = ["info", path]
153        status, output = self._execsvn(local=True, *cmd, **kwargs)
154        if status == 0:
155            for line in output.splitlines():
156                if line.startswith("Revision: "):
157                    return int(line.split()[1])
158        return None
159         
160    def info(self, path, **kwargs):
161        cmd = ["info", path]
162        status, output = self._execsvn(local=True, *cmd, **kwargs)
163        if status == 0:
164            return output.splitlines()
165        return None
166         
167    def ls(self, path, **kwargs):
168        cmd = ["ls", path]
169        status, output = self._execsvn(*cmd, **kwargs)
170        if status == 0:
171            return output.split()
172        return None
173
174    def status(self, path, **kwargs):
175        cmd = ["status", path]
176        if kwargs.get("verbose"):
177            cmd.append("-v")
178        status, output = self._execsvn(*cmd, **kwargs)
179        if status == 0:
180            return [x.split() for x in output.splitlines()]
181        return None
182
183    def cleanup(self, path, **kwargs):
184        cmd = ["cleanup", path]
185        return self._execsvn_success(*cmd, **kwargs)
186
187    def revert(self, path, **kwargs):
188        cmd = ["revert", path]
189        status, output = self._execsvn(*cmd, **kwargs)
190        if status == 0:
191            return [x.split() for x in output.split()]
192        return None
193
194    def update(self, path, **kwargs):
195        cmd = ["update", path]
196        self._add_revision(cmd, kwargs, optional=1)
197        status, output = self._execsvn(*cmd, **kwargs)
198        if status == 0:
199            return [x.split() for x in output.split()]
200        return None
201
202    def merge(self, url1, url2=None, rev1=None, rev2=None, path=None, **kwargs):
203        cmd = ["merge"]
204        if rev1 and rev2 and not url2:
205            cmd.append("-r")
206            cmd.append("%s:%s" % (rev1, rev2))
207            cmd.append(url1)
208        else:
209            if not url2:
210                raise ValueError, \
211                      "url2 needed if two revisions are not provided"
212            if rev1:
213                cmd.append("%s@%s" % (url1, rev1))
214            else:
215                cmd.append(url1)
216            if rev2:
217                cmd.append("%s@%s" % (url2, rev2))
218            else:
219                cmd.append(url2)
220        if path:
221            cmd.append(path)
222        status, output = self._execsvn(*cmd, **kwargs)
223        if status == 0:
224            return [x.split() for x in output.split()]
225        return None
226
227    def diff(self, pathurl1, pathurl2=None, **kwargs):
228        cmd = ["diff", pathurl1]
229        self._add_revision(cmd, kwargs, optional=1)
230        if pathurl2:
231            cmd.append(pathurl2)
232        status, output = self._execsvn(*cmd, **kwargs)
233        if status == 0:
234            return output
235        return None
236
237    def cat(self, url, **kwargs):
238        cmd = ["cat", url]
239        self._add_revision(cmd, kwargs, optional=1)
240        status, output = self._execsvn(*cmd, **kwargs)
241        if status == 0:
242            return output
243        return None
244
245    def log(self, url, start=None, end=0, **kwargs):
246        cmd = ["log", url]
247        if start is not None:
248            if type(start) is not type(0):
249                try:
250                    start = int(start)
251                except (ValueError, TypeError):
252                    raise Error, "invalid log start revision provided"
253            if type(end) is not type(0):
254                try:
255                    end = int(end)
256                except (ValueError, TypeError):
257                    raise Error, "invalid log end revision provided"
258            cmd.append("-r %d:%d" % (start, end))
259        status, output = self._execsvn(*cmd, **kwargs)
260        if status != 0:
261            return None
262
263        revheader = re.compile("^r(?P<revision>[0-9]+) \| (?P<author>.+?) \| (?P<date>.+?) \| (?P<lines>[0-9]+) (?:line|lines)")
264        logseparator = "-"*72
265        linesleft = 0
266        entry = None
267        log = []
268        emptyline = 0
269        for line in output.splitlines():
270            if emptyline:
271                emptyline = 0
272                continue
273            line = line.rstrip()
274            if linesleft == 0:
275                if line != logseparator:
276                    m = revheader.match(line)
277                    if m:
278                        linesleft = int(m.group("lines"))
279                        timestr = " ".join(m.group("date").split()[:2])
280                        timetuple = time.strptime(timestr,
281                                                  "%Y-%m-%d %H:%M:%S")
282                        entry = SVNLogEntry(int(m.group("revision")),
283                                            m.group("author"), timetuple)
284                        log.append(entry)
285                        emptyline = 1
286            else:
287                entry.lines.append(line)
288                linesleft -= 1
289        log.sort()
290        log.reverse()
291        return log
292
293class SVNLook:
294    def __init__(self, repospath, txn=None, rev=None):
295        self.repospath = repospath
296        self.txn = txn
297        self.rev = rev
298
299    def _execsvnlook(self, cmd, *args, **kwargs):
300        execcmd_args = ["svnlook", cmd, self.repospath]
301        self._add_txnrev(execcmd_args, kwargs)
302        execcmd_args += args
303        execcmd_kwargs = {}
304        keywords = ["show", "noerror"]
305        for key in keywords:
306            if kwargs.has_key(key):
307                execcmd_kwargs[key] = kwargs[key]
308        return execcmd(*execcmd_args, **execcmd_kwargs)
309
310    def _add_txnrev(self, cmd_args, received_kwargs):
311        if received_kwargs.has_key("txn"):
312            txn = received_kwargs.get("txn")
313            if txn is not None:
314                cmd_args += ["-t", txn]
315        elif self.txn is not None:
316            cmd_args += ["-t", self.txn]
317        if received_kwargs.has_key("rev"):
318            rev = received_kwargs.get("rev")
319            if rev is not None:
320                cmd_args += ["-r", rev]
321        elif self.rev is not None:
322            cmd_args += ["-r", self.rev]
323
324    def changed(self, **kwargs):
325        status, output = self._execsvnlook("changed", **kwargs)
326        if status != 0:
327            return None
328        changes = []
329        for line in output.splitlines():
330            line = line.rstrip()
331            if not line:
332                continue
333            entry = [None, None, None]
334            changedata, changeprop, path = None, None, None
335            if line[0] != "_":
336                changedata = line[0]
337            if line[1] != " ":
338                changeprop = line[1]
339            path = line[4:]
340            changes.append((changedata, changeprop, path))
341        return changes
342
343    def author(self, **kwargs):
344        status, output = self._execsvnlook("author", **kwargs)
345        if status != 0:
346            return None
347        return output.strip()
348
349# vim:et:ts=4:sw=4
Note: See TracBrowser for help on using the repository browser.