1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import os
23 from translate.storage.versioncontrol import run_command
24 from translate.storage.versioncontrol import GenericRevisionControlSystem
25
26
28 """check if cvs is installed"""
29 exitcode, output, error = run_command(["cvs", "--version"])
30 return exitcode == 0
31
32
33 -class cvs(GenericRevisionControlSystem):
34 """Class to manage items under revision control of CVS."""
35
36 RCS_METADIR = "CVS"
37 SCAN_PARENTS = False
38
39 - def _readfile(self, cvsroot, path, revision=None):
40 """
41 Read a single file from the CVS repository without checking out a full
42 working directory.
43
44 @param cvsroot: the CVSROOT for the repository
45 @param path: path to the file relative to cvs root
46 @param revision: revision or tag to get (retrieves from HEAD if None)
47 """
48 command = ["cvs", "-d", cvsroot, "-Q", "co", "-p"]
49 if revision:
50 command.extend(["-r", revision])
51
52 command.append(path)
53 exitcode, output, error = run_command(command)
54 if exitcode != 0:
55 raise IOError("[CVS] Could not read '%s' from '%s': %s / %s" % \
56 (path, cvsroot, output, error))
57 return output
58
60 """Get the content of the file for the given revision"""
61 parentdir = os.path.dirname(self.location_abs)
62 cvsdir = os.path.join(parentdir, "CVS")
63 cvsroot = open(os.path.join(cvsdir, "Root"), "r").read().strip()
64 cvspath = open(os.path.join(cvsdir, "Repository"), "r").read().strip()
65 cvsfilename = os.path.join(cvspath, os.path.basename(self.location_abs))
66 if revision is None:
67 cvsentries = open(os.path.join(cvsdir, "Entries"), "r").readlines()
68 revision = self._getcvstag(cvsentries)
69 if revision == "BASE":
70 cvsentries = open(os.path.join(cvsdir, "Entries"), "r").readlines()
71 revision = self._getcvsrevision(cvsentries)
72 return self._readfile(cvsroot, cvsfilename, revision)
73
74 - def update(self, revision=None):
75 """Does a clean update of the given path"""
76 working_dir = os.path.dirname(self.location_abs)
77 filename = self.location_abs
78 filename_backup = filename + os.path.extsep + "bak"
79
80 try:
81 os.rename(filename, filename_backup)
82 except OSError, error:
83 raise IOError("[CVS] could not move the file '%s' to '%s': %s" % \
84 (filename, filename_backup, error))
85 command = ["cvs", "-Q", "update", "-C"]
86 if revision:
87 command.extend(["-r", revision])
88
89 command.append(os.path.basename(filename))
90
91 exitcode, output, error = run_command(command, working_dir)
92
93 try:
94 if exitcode != 0:
95 os.rename(filename_backup, filename)
96 else:
97 os.remove(filename_backup)
98 except OSError:
99 pass
100
101 if exitcode != 0:
102 raise IOError("[CVS] Error running CVS command '%s': %s" \
103 % (command, error))
104 else:
105 return output
106
107 - def commit(self, message=None, author=None):
108 """Commits the file and supplies the given commit message if present
109
110 the 'author' parameter is not suitable for CVS, thus it is ignored
111 """
112 working_dir = os.path.dirname(self.location_abs)
113 filename = os.path.basename(self.location_abs)
114 command = ["cvs", "-Q", "commit"]
115 if message:
116 command.extend(["-m", message])
117
118 command.append(filename)
119 exitcode, output, error = run_command(command, working_dir)
120
121 if exitcode != 0:
122 raise IOError("[CVS] Error running CVS command '%s': %s" \
123 % (command, error))
124 else:
125 return output
126
128 """returns the revision number the file was checked out with by looking
129 in the lines of cvsentries
130 """
131 filename = os.path.basename(self.location_abs)
132 for cvsentry in cvsentries:
133
134
135 cvsentryparts = cvsentry.split("/")
136 if len(cvsentryparts) < 6:
137 continue
138 if os.path.normcase(cvsentryparts[1]) == os.path.normcase(filename):
139 return cvsentryparts[2].strip()
140 return None
141
143 """Returns the sticky tag the file was checked out with by looking in
144 the lines of cvsentries.
145 """
146 filename = os.path.basename(self.location_abs)
147 for cvsentry in cvsentries:
148
149
150 cvsentryparts = cvsentry.split("/")
151 if len(cvsentryparts) < 6:
152 continue
153 if os.path.normcase(cvsentryparts[1]) == os.path.normcase(filename):
154 if cvsentryparts[5].startswith("T"):
155 return cvsentryparts[5][1:].strip()
156 return None
157