darcs.py 4.55 KB
Newer Older
1 2 3
# -*- coding: utf-8 -*- 

# vim:set shiftwidth=4 tabstop=4 expandtab textwidth=79:
Stephen Kennedy's avatar
Stephen Kennedy committed
4
#Copyright (c) 2005 Ali Afshar <aafshar@gmail.com>
5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25

#Permission is hereby granted, free of charge, to any person obtaining a copy
#of this software and associated documentation files (the "Software"), to deal
#in the Software without restriction, including without limitation the rights
#to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
#copies of the Software, and to permit persons to whom the Software is
#furnished to do so, subject to the following conditions:

#The above copyright notice and this permission notice shall be included in
#all copies or substantial portions of the Software.

#THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
#IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
#FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
#AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
#LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
#OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
#SOFTWARE.

import os
import errno
26 27
from . import _vc

28

29
class Vc(_vc.CachedVc):
30 31 32

    CMD = "darcs"
    NAME = "Darcs"
33
    VC_DIR = "_darcs"
34 35
    PATCH_STRIP_NUM = 1
    PATCH_INDEX_RE = "--- old.+?/(.+?)\\t+.*[0-9]{4}$"
36 37 38 39 40 41 42
    state_map = {
        "a": _vc.STATE_NONE,
        "A": _vc.STATE_NEW,
        "M": _vc.STATE_MODIFIED,
        "C": _vc.STATE_CONFLICT,
        "R": _vc.STATE_REMOVED,
    }
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59

    def commit_command(self, message):
        return [self.CMD, "record",
                "--skip-long-comment",
                "--repodir=%s" % self.root,
                "-a",
                "-m", message]

    def diff_command(self):
        return [self.CMD, "diff", "-u",
                "--repodir=%s" % self.root]

    def update_command(self):
        # This will not work while passing the files parameter after it
        # This hack allows you to update in the root directory
        return [self.CMD, "pull", "-a", "-p"]

60
    def add_command(self):
61 62 63 64 65 66 67 68 69
        return [self.CMD, "add"]

    def remove_command(self, force=0):
        return [self.CMD, "remove"]
 
    def revert_command(self):
        # will not work, since darcs needs interaction it seems
        return [self.CMD, "revert", "-a"]

70 71 72 73
    def resolved_command(self):
        # untested
        return [self.CMD, "resolve"]

74
    def valid_repo(self):
75
        if _vc.call([self.CMD, "query", "tags"], cwd=self.root):
76 77 78 79
            return False
        else:
            return True

80 81
    def get_working_directory(self, workdir):
        return self.root
82

83
    def _get_dirsandfiles(self, directory, dirs, files):
84
        whatsnew = self._get_tree_cache(directory)
85 86 87
        retfiles, retdirs = (self._get_statuses(whatsnew, files, _vc.File),
                             self._get_statuses(whatsnew, dirs, _vc.Dir))
        return retfiles, retdirs
88

89
    def _lookup_tree_cache(self, rootdir):
90 91 92 93 94 95 96 97 98
        non_boring = self._get_whatsnew()
        boring = self._get_whatsnew(boring=True)
        for path in boring:
            if not path in non_boring:
                non_boring[path] = _vc.STATE_IGNORED
        return non_boring

    def _get_whatsnew(self, boring=False):
        whatsnew = {}
Kai Willadsen's avatar
Kai Willadsen committed
99
        commandline = [self.CMD, "whatsnew", "--summary", "-l", "--repodir=" + self.root]
100
        if boring:
101
            commandline.append("--boring")
102 103
        while 1:
            try:
104
                p = _vc.popen(commandline)
105
                break
106
            except OSError as e:
107 108 109
                if e.errno != errno.EAGAIN:
                    raise
        for line in p:
110 111
            if line.startswith('No changes!'):
                continue
112
            elements = line.split()
113 114 115 116 117
            if len(elements) > 1:
                if elements[1] == '->':
                    status = _vc.STATE_NEW
                    filename = elements.pop()
                else:
118
                    status = self.state_map[elements.pop(0)]
119 120 121 122
                    filename = elements.pop(0)
                filepath = os.path.join(self.root,
                                        os.path.normpath(filename))
                whatsnew[filepath] = status
123 124 125 126 127 128 129 130 131
        return whatsnew

    def _get_statuses(self, whatsnew, files, fstype):
        rets = []
        for filename, path in files:
            state = _vc.STATE_NORMAL
            if path in whatsnew:
                state = whatsnew[path]
            vcfile = fstype(path, filename, state)
132
            if filename != self.VC_DIR:
133 134
                rets.append(vcfile)
        return rets