Review Board

beta

Initial Monotone Support

Updated 4 months, 2 weeks ago

Gary Kramlich Reviewers
reviewboard
None Review Board SVN
This basically works.  It depends on a local database which we somehow need to determine how to update.

Aside from that, binary files are not currently marked, and empty files cause the diff viewer to blow up.

I can provide some diffs for testing if anyone would so desire.

---

Round two, I think I got everything, although I'm not sure how to handle the FileNotFound, since I'm using file id's which don't contain the name or anything...

 

Diff revision 2 (Latest)

1 2
1 2

  1. /scmtools/mtn.py: 1 change [ new content ]
/scmtools/mtn.py
New File
1
import os
2
import re
3
import subprocess
4
5
from reviewboard.diffviewer.parser import DiffParser
6
from reviewboard.scmtools.core import FileNotFoundError, SCMError, \
7
                                      SCMTool
8
9
10
class MonotoneTool(SCMTool):
11
    def __init__(self, repository):
12
        SCMTool.__init__(self, repository)
13
        self.client = MonotoneClient(repository.path)
14
15
    def get_file(self, path, revision=None):
16
        # revision is actually the file id here...
17
        if not revision:
18
            return ""
19
20
        return self.client.get_file(revision)
21
22
    def file_exists(self, path, revision=None):
23
        # revision is actually the file id here...
24
        if not revision:
25
            return False
26
27
        try:
28
            self.client.get_file(revision)
29
        except FileNotFoundError:
30
            return False
31
32
        return True
33
34
    def parse_diff_revision(self, file_str, revision_str):
35
        return file_str, revision_str
36
37
    def get_diffs_use_absolute_paths(self):
38
        return True
39
40
    def get_fields(self):
41
        return ['diff_path']
42
43
    def get_parser(self, data):
44
        return MonotoneDiffParser(data)
45
46
47
class MonotoneDiffParser(DiffParser):
48
    INDEX_SEP = "=" * 60
49
50
    def parse_special_header(self, linenum, info):
51
        if self.lines[linenum].startswith("#"):
52
            if "is binary" in self.lines[linenum]:
53
                info['binary'] = True
54
                linenum += 1
55
            elif self.lines[linenum + 1] == self.INDEX_SEP:
56
                # this is a standard mtn diff header (comments with the file summary)
57
                linenum += 1
58
59
        return linenum
60
61
62
class MonotoneClient:
63
    def __init__(self, path):
64
        self.path = path
65
66
        if not os.path.isfile(self.path):
67
            raise ImportError
68
69
    def get_file(self, fileid):
70
        args = ['mtn', '-d', self.path, 'automate', 'get_file', fileid]
71
72
        p = subprocess.Popen(args, stderr=subprocess.PIPE, stdout=subprocess.PIPE, close_fds=True)
73
74
        out = p.stdout.read()
75
        err = p.stderr.read()
76
        status = p.wait()
77
78
        if status:
79
            if "mtn: misuse: no file" in err >= 0:
80
                raise FileNotFoundError
81
            else:
82
                raise SCMError(err)
83
84
        return out
85
86
87
# vi: et:sw=4 ts=4
  1. /scmtools/mtn.py: 1 change [ new content ]