source: trunk/moap/vcs/darcs.py @ 366

Revision 366, 5.6 KB checked in by thomas, 5 years ago (diff)
  • moap/vcs/vcs.py: Unify getAdded/getDeleted/getIgnored/getUnknown. They now all take path as an argument. getNotIgnored was removed.
  • moap/command/ignore.py:
  • moap/test/test_vcs_bzr.py:
  • moap/test/test_vcs_cvs.py:
  • moap/test/test_vcs_darcs.py:
  • moap/test/test_vcs_git.py:
  • moap/test/test_vcs_git_svn.py:
  • moap/test/test_vcs_svn.py:
  • moap/vcs/bzr.py:
  • moap/vcs/cvs.py:
  • moap/vcs/darcs.py:
  • moap/vcs/git.py:
  • moap/vcs/git_svn.py:
  • moap/vcs/svn.py: Follow up on that change.
Line 
1# -*- Mode: Python; test-case-name: moap.test.test_vcs_darcs -*-
2# vi:si:et:sw=4:sts=4:ts=4
3
4"""
5Darcs functionality.
6"""
7
8import os
9import commands
10import re
11
12from moap.util import util, log
13from moap.vcs import vcs
14
15def detect(path):
16    """
17    Detect if the given source tree is using Darcs.
18
19    @return: True if the given path looks like a Darcs tree.
20    """
21    # for darcs, we may have to walk up directories
22    # see http://www.darcs.net/manual/node9.html
23    if not os.path.exists(os.path.join(path, '_darcs')):
24        log.debug('darcs', 'Did not find _darcs directory under %s' % path)
25        return False
26
27    # some paths I found after an initialize and get
28    for n in ['inventory', 'inventories', 'checkpoints']:
29        if not os.path.exists(os.path.join(path, '_darcs', n)):
30            log.debug('darcs', 'Did not find _darcs/%s under %s' % (n, path))
31            return False
32
33    return True
34
35class Darcs(vcs.VCS):
36    name = 'Darcs'
37
38    def getUnknown(self, path):
39        # darcs has "query manifest" to list version-controlled files,
40        # and a toplevel .darcs-boring file listing comments and regexps
41        oldPath = os.getcwd()
42
43        versioned = []
44        # output of this command starts with ./, filter that out
45        cmd = "darcs query manifest --repodir=%s" % path
46        output = commands.getoutput(cmd)
47        for line in output.split("\n"):
48            versioned.append(line[1 + len(os.path.sep):])
49        self.debug('%d versioned files' % len(versioned))
50
51        allFiles = []
52
53        def walker(allFiles, dirname, fnames):
54            if not dirname.startswith(self.path):
55                fnames = []
56                return
57
58            reldirname = dirname[len(os.path.join(self.path, '')):]
59            # copy fnames so we can remove from it safely
60            for fname in fnames[:]:
61                # ignore _darcs directory in toplevel
62                if dirname == self.path and fname == "_darcs":
63                    fnames.remove(fname)
64                    continue
65                # darcs doesn't list directories as part of manifest
66                if not os.path.isdir(os.path.join(dirname, fname)):
67                    allFiles.append(os.path.join(reldirname, fname))
68
69        os.path.walk(self.path, walker, allFiles)
70        self.debug('%d total files' % len(allFiles))
71
72        boringPath = os.path.join(self.path, '.darcs-boring')
73        boringRegExps = []
74        if os.path.exists(boringPath):
75            boringRegExps = open(boringPath).readlines()
76
77        unversioned = [n for n in allFiles if n not in versioned]
78        self.debug('%d unversioned files' % len(unversioned))
79
80        # now filter out based on the regexps
81        boring = []
82        for exp in boringRegExps:
83            exp = exp.rstrip()
84            if not exp:
85                continue
86            if exp.startswith('#'):
87                continue
88            matcher = re.compile(exp)
89            for name in unversioned:
90                if matcher.match(name):
91                    boring.append(name)
92
93        unignored = [n for n in unversioned if n not in boring]
94        self.debug('%d unignored files' % len(unignored))
95
96        os.chdir(oldPath)
97        return unignored
98
99    def ignore(self, paths, commit=True):
100        if not paths:
101            return
102        # FIXME: darcs allows regexp style, maybe our ignore should too
103        self.debug('ignoring %d paths' % len(paths))
104        oldPath = os.getcwd()
105        os.chdir(self.path)
106
107        boring = os.path.join(self.path, '.darcs-boring')
108        addBoring = not os.path.exists(boring)
109        handle = open(boring, "a")
110        self.debug('adding %d paths to %s' % (len(paths), boring))
111        for path in paths:
112            handle.write('%s\n' % path)
113        handle.close()
114
115        # FIXME: we should check if it is tracked, not if it exists;
116        # someone can have created it without adding it
117        if addBoring:
118            cmd = "darcs add .darcs-boring"
119            self.debug('Executing %s' % cmd)
120            os.system(cmd)
121        if commit:
122            cmd = "darcs record -am 'moap ignore' .darcs-boring"
123            self.debug('Executing %s' % cmd)
124            os.system(cmd)
125
126        os.chdir(oldPath)
127
128    def commit(self, paths, message):
129        # again, to commit, we need to be in the working directory
130        # paths are absolute, so scrub them
131        oldPath = os.getcwd()
132        os.chdir(self.path)
133
134        temp = util.writeTemp([message, ])
135        cmd = "darcs record -a --logfile=%s %s" % (
136            temp, " ".join(paths))
137        self.debug('running %s' % cmd)
138        status = os.system(cmd)
139        os.unlink(temp)
140
141        os.chdir(oldPath)
142
143        if status != 0:
144            return False
145
146        return True
147
148    def diff(self, path):
149        # darcs diff only works when in the working directory
150        oldPath = os.getcwd()
151        os.chdir(path)
152
153        cmd = "darcs diff --unified"
154        self.debug('Running %s' % cmd)
155        output = commands.getoutput(cmd)
156
157        os.chdir(oldPath)
158        return output
159
160    def getFileMatcher(self):
161        return re.compile('^diff -rN -u old-.*/(\S+)$')
162
163    def update(self, path):
164        # FIXME: I don't see a way to pull just updates to the given path
165        cmd = "darcs pull %s" % self.path
166        status, output = commands.getstatusoutput(cmd)
167        code = os.WEXITSTATUS(status)
168        if code not in (0, 2):
169            # darcs pull returns error code 2 when
170            # darcs failed:  No default repository to pull from, please specify
171            # one
172            # we let it pass
173            raise vcs.VCSException(output)
174
175        return output
176
177VCSClass = Darcs
Note: See TracBrowser for help on using the repository browser.