blob: 5eead4d27c02a3e058ccdbb91803f2db42c20199 [file] [log] [blame]
Guido van Rossum097c55a1995-04-27 18:07:07 +00001#! /usr/local/bin/python
2
Guido van Rossumc218a7e1995-04-27 23:33:43 +00003"""Remote CVS -- command line interface"""
Guido van Rossum097c55a1995-04-27 18:07:07 +00004
Guido van Rossumc218a7e1995-04-27 23:33:43 +00005from cvslib import CVS, File
Guido van Rossum5f07b841995-04-26 22:57:11 +00006import md5
7import os
8import string
9import sys
Guido van Rossumc218a7e1995-04-27 23:33:43 +000010from cmdfw import CommandFrameWork
Guido van Rossum5f07b841995-04-26 22:57:11 +000011
12
Guido van Rossumc218a7e1995-04-27 23:33:43 +000013class MyFile(File):
Guido van Rossum5f07b841995-04-26 22:57:11 +000014
Guido van Rossumae21ced1995-04-28 14:32:26 +000015 def action(self):
16 """Return a code indicating the update status of this file.
17
18 The possible return values are:
Guido van Rossumc218a7e1995-04-27 23:33:43 +000019
Guido van Rossumae21ced1995-04-28 14:32:26 +000020 '=' -- everything's fine
21 '0' -- file doesn't exist anywhere
22 '?' -- exists locally only
23 'A' -- new locally
24 'R' -- deleted locally
25 'U' -- changed remotely, no changes locally
Guido van Rossum6bb4a511995-04-28 15:26:37 +000026 (includes new remotely or deleted remotely)
Guido van Rossumae21ced1995-04-28 14:32:26 +000027 'M' -- changed locally, no changes remotely
28 'C' -- conflict: changed locally as well as remotely
29 (includes cases where the file has been added
30 or removed locally and remotely)
Guido van Rossumba244681995-04-28 15:33:03 +000031 'D' -- deleted remotely
32 'N' -- new remotely
Guido van Rossum6bb4a511995-04-28 15:26:37 +000033 'r' -- get rid of entry
34 'c' -- create entry
35 'u' -- update entry
Guido van Rossumae21ced1995-04-28 14:32:26 +000036 """
37 if not self.eseen:
Guido van Rossum6bb4a511995-04-28 15:26:37 +000038 if not self.lseen:
39 if not self.rseen: return '0' # Never heard of
40 else:
41 return 'N' # New remotely
42 else: # self.lseen
43 if not self.rseen: return '?' # Local only
44 # Local and remote, but no entry
45 if self.lsum == self.rsum:
46 return 'c' # Restore entry only
47 else: return 'C' # Real conflict
48 else: # self.eseen
49 if not self.lseen:
50 if self.eremoved:
51 if self.rseen: return 'R' # Removed
52 else: return 'r' # Get rid of entry
53 else: # not self.eremoved
54 if self.rseen:
55 print "warning:",
56 print self.file,
57 print "was lost"
58 return 'U'
59 else: return 'r' # Get rid of entry
60 else: # self.lseen
61 if not self.rseen:
62 if self.enew: return 'A' # New locally
63 else: return 'D' # Deleted remotely
64 else: # self.rseen
65 if self.enew:
66 if self.lsum == self.rsum:
67 return 'u'
68 else:
69 return 'C'
70 if self.lsum == self.esum:
71 if self.esum == self.rsum:
72 return '='
73 else:
74 return 'U'
75 elif self.esum == self.rsum:
76 return 'M'
77 elif self.lsum == self.rsum:
78 return 'u'
79 else:
80 return 'C'
Guido van Rossumae21ced1995-04-28 14:32:26 +000081
82 def update(self):
83 code = self.action()
84 print code, self.file
Guido van Rossumba244681995-04-28 15:33:03 +000085 if code in ('U', 'N'):
Guido van Rossumae21ced1995-04-28 14:32:26 +000086 self.get()
87 elif code == 'C':
88 print "%s: conflict resolution not yet implemented" % \
89 self.file
Guido van Rossumba244681995-04-28 15:33:03 +000090 elif code == 'D':
91 try:
92 os.unlink(self.file)
93 except os.error:
94 pass
95 self.eseen = 0
96 elif code == 'r':
97 self.eseen = 0
98 elif code in ('c', 'u'):
Guido van Rossumd22f59f1995-04-28 15:37:22 +000099 self.eseen = 1
Guido van Rossumba244681995-04-28 15:33:03 +0000100 self.erev = self.rrev
101 self.enew = 0
102 self.edeleted = 0
103 self.esum = self.rsum
104 self.emtime, self.ectime = os.stat(self.file)[-2:]
Guido van Rossumd22f59f1995-04-28 15:37:22 +0000105 self.extra = ''
Guido van Rossumae21ced1995-04-28 14:32:26 +0000106
107 def commit(self, message = ""):
108 code = self.action()
109 if code in ('A', 'M'):
110 self.put(message)
111 elif code == 'R':
112 print "%s: committing removes not yet implemented" % \
113 self.file
114 elif code == 'C':
115 print "%s: conflict resolution not yet implemented" % \
116 self.file
117
118 def commitcheck(self):
119 return self.action() != 'C'
120
121 def put(self, message = ""):
Guido van Rossumbafc14d1995-04-28 15:41:51 +0000122 print "Checking in", self.file, "..."
123 data = open(self.file).read()
124 messages = self.proxy.put(self.file, data, message)
125 if messages:
126 print messages
Guido van Rossumae21ced1995-04-28 14:32:26 +0000127
128 def get(self):
129 data = self.proxy.get(self.file)
130 f = open(self.file, 'w')
131 f.write(data)
132 f.close()
133 self.eseen = 1
134 self.esum = self.rsum
135 self.emtime, self.ectime = os.stat(self.file)[-2:]
136 self.erev = self.rrev
137 self.enew = 0
138 self.edeleted = 0
139 # XXX anything else?
Guido van Rossum5f07b841995-04-26 22:57:11 +0000140
141
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000142class RCVS(CVS):
143
144 FileClass = MyFile
145
146 def __init__(self):
147 CVS.__init__(self)
148
149 def checkfiles(self, files):
150 if not files:
151 def ok(file, self=self):
152 e = self.entries[file]
153 return e.eseen or e.rseen
154 files[:] = filter(ok, self.entries.keys())
155 files.sort()
Guido van Rossumae21ced1995-04-28 14:32:26 +0000156 if not files:
157 print "no files to be processed"
158 return 1
159 else:
160 return None
161 else:
162 sts = None
163 for file in files:
164 if not self.entries.has_key(file):
165 print "%s: nothing known" % file
166 sts = 1
167 return sts
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000168
169
170class rcvs(CommandFrameWork):
171
172 GlobalFlags = 'd:h:p:qv'
173 UsageMessage = \
174 "usage: rcvs [-d directory] [-h host] [-p port] [-q] [-v] subcommand arg ..."
175
176 def __init__(self):
177 """Constructor."""
178 CommandFrameWork.__init__(self)
179 self.proxy = None
180 self.cvs = RCVS()
181
182 def options(self, opts):
183 self.opts = opts
184
185 def ready(self):
186 import rcsclient
187 self.proxy = rcsclient.openrcsclient(self.opts)
188 self.cvs.setproxy(self.proxy)
189 self.cvs.getentries()
190 self.cvs.getlocalfiles()
191 self.cvs.getremotefiles(self.proxy)
192
193 def default(self):
Guido van Rossumae21ced1995-04-28 14:32:26 +0000194 files = []
195 if self.cvs.checkfiles(files):
196 return 1
Guido van Rossum6bb4a511995-04-28 15:26:37 +0000197 for file in files:
198 print self.cvs.entries[file].action(), file
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000199
200 def do_update(self, opts, files):
Guido van Rossumae21ced1995-04-28 14:32:26 +0000201 """update [file] ..."""
202 if self.cvs.checkfiles(files):
203 return 1
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000204 for file in files:
205 if not self.cvs.entries.has_key(file):
206 print "%s: not found" % file
207 else:
208 self.cvs.entries[file].update()
Guido van Rossum6bb4a511995-04-28 15:26:37 +0000209 self.cvs.putentries()
Guido van Rossum5f07b841995-04-26 22:57:11 +0000210
Guido van Rossumae21ced1995-04-28 14:32:26 +0000211 def do_commit(self, opts, files):
212 """commit [file] ..."""
213 if self.cvs.checkfiles(files):
214 return 1
215 sts = 0
216 for file in files:
Guido van Rossum6bb4a511995-04-28 15:26:37 +0000217 if not self.cvs.entries[file].commitcheck():
Guido van Rossumae21ced1995-04-28 14:32:26 +0000218 sts = 1
219 if sts:
220 return sts
221 message = raw_input("One-liner: ")
222 for file in files:
Guido van Rossum6bb4a511995-04-28 15:26:37 +0000223 self.cvs.entries[file].commit(message)
224 self.cvs.putentries()
Guido van Rossumae21ced1995-04-28 14:32:26 +0000225
Guido van Rossum5f07b841995-04-26 22:57:11 +0000226
Guido van Rossumdeb627c1995-04-27 21:28:53 +0000227def main():
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000228 rcvs().run()
Guido van Rossum097c55a1995-04-27 18:07:07 +0000229
Guido van Rossum5f07b841995-04-26 22:57:11 +0000230
231if __name__ == "__main__":
Guido van Rossumdeb627c1995-04-27 21:28:53 +0000232 main()