blob: 462025652bb6f6551f42d7f567314356cb8e3b57 [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':
Guido van Rossum330e8841995-04-28 17:56:32 +000091 remove(self.file)
Guido van Rossumba244681995-04-28 15:33:03 +000092 self.eseen = 0
93 elif code == 'r':
94 self.eseen = 0
95 elif code in ('c', 'u'):
Guido van Rossumd22f59f1995-04-28 15:37:22 +000096 self.eseen = 1
Guido van Rossumba244681995-04-28 15:33:03 +000097 self.erev = self.rrev
98 self.enew = 0
99 self.edeleted = 0
100 self.esum = self.rsum
101 self.emtime, self.ectime = os.stat(self.file)[-2:]
Guido van Rossumd22f59f1995-04-28 15:37:22 +0000102 self.extra = ''
Guido van Rossumae21ced1995-04-28 14:32:26 +0000103
104 def commit(self, message = ""):
105 code = self.action()
106 if code in ('A', 'M'):
107 self.put(message)
108 elif code == 'R':
109 print "%s: committing removes not yet implemented" % \
110 self.file
111 elif code == 'C':
112 print "%s: conflict resolution not yet implemented" % \
113 self.file
114
Guido van Rossum330e8841995-04-28 17:56:32 +0000115 def diff(self, opts = []):
116 import tempfile
117 flags = ''
118 for o, a in opts:
119 flags = flags + ' ' + o + a
120 flags = flags[1:]
121 fn = self.file
122 data = self.proxy.get(fn)
123 tfn = tempfile.mktemp()
124 try:
125 tf = open(tfn, 'w')
126 tf.write(data)
127 tf.close()
128 print 'diff %s -r%s %s' % (flags, self.rrev, fn)
129 sts = os.system('diff %s %s %s' % (flags, tfn, fn))
130 if sts:
131 print '='*70
132 finally:
133 remove(tfn)
134
Guido van Rossumae21ced1995-04-28 14:32:26 +0000135 def commitcheck(self):
136 return self.action() != 'C'
137
138 def put(self, message = ""):
Guido van Rossumbafc14d1995-04-28 15:41:51 +0000139 print "Checking in", self.file, "..."
140 data = open(self.file).read()
141 messages = self.proxy.put(self.file, data, message)
142 if messages:
143 print messages
Guido van Rossumae21ced1995-04-28 14:32:26 +0000144
145 def get(self):
146 data = self.proxy.get(self.file)
147 f = open(self.file, 'w')
148 f.write(data)
149 f.close()
150 self.eseen = 1
151 self.esum = self.rsum
152 self.emtime, self.ectime = os.stat(self.file)[-2:]
153 self.erev = self.rrev
154 self.enew = 0
155 self.edeleted = 0
156 # XXX anything else?
Guido van Rossum5f07b841995-04-26 22:57:11 +0000157
158
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000159class RCVS(CVS):
160
161 FileClass = MyFile
162
163 def __init__(self):
164 CVS.__init__(self)
165
166 def checkfiles(self, files):
167 if not files:
168 def ok(file, self=self):
169 e = self.entries[file]
170 return e.eseen or e.rseen
171 files[:] = filter(ok, self.entries.keys())
172 files.sort()
Guido van Rossumae21ced1995-04-28 14:32:26 +0000173 if not files:
174 print "no files to be processed"
175 return 1
176 else:
177 return None
178 else:
179 sts = None
180 for file in files:
181 if not self.entries.has_key(file):
182 print "%s: nothing known" % file
183 sts = 1
184 return sts
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000185
186
187class rcvs(CommandFrameWork):
188
189 GlobalFlags = 'd:h:p:qv'
190 UsageMessage = \
191 "usage: rcvs [-d directory] [-h host] [-p port] [-q] [-v] subcommand arg ..."
192
193 def __init__(self):
194 """Constructor."""
195 CommandFrameWork.__init__(self)
196 self.proxy = None
197 self.cvs = RCVS()
198
199 def options(self, opts):
200 self.opts = opts
201
202 def ready(self):
203 import rcsclient
204 self.proxy = rcsclient.openrcsclient(self.opts)
205 self.cvs.setproxy(self.proxy)
206 self.cvs.getentries()
207 self.cvs.getlocalfiles()
208 self.cvs.getremotefiles(self.proxy)
209
210 def default(self):
Guido van Rossumae21ced1995-04-28 14:32:26 +0000211 files = []
212 if self.cvs.checkfiles(files):
213 return 1
Guido van Rossum6bb4a511995-04-28 15:26:37 +0000214 for file in files:
215 print self.cvs.entries[file].action(), file
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000216
217 def do_update(self, opts, files):
Guido van Rossumae21ced1995-04-28 14:32:26 +0000218 """update [file] ..."""
219 if self.cvs.checkfiles(files):
220 return 1
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000221 for file in files:
222 if not self.cvs.entries.has_key(file):
223 print "%s: not found" % file
224 else:
225 self.cvs.entries[file].update()
Guido van Rossum6bb4a511995-04-28 15:26:37 +0000226 self.cvs.putentries()
Guido van Rossum330e8841995-04-28 17:56:32 +0000227 do_up = do_update
Guido van Rossum5f07b841995-04-26 22:57:11 +0000228
Guido van Rossumae21ced1995-04-28 14:32:26 +0000229 def do_commit(self, opts, files):
230 """commit [file] ..."""
231 if self.cvs.checkfiles(files):
232 return 1
233 sts = 0
234 for file in files:
Guido van Rossum6bb4a511995-04-28 15:26:37 +0000235 if not self.cvs.entries[file].commitcheck():
Guido van Rossumae21ced1995-04-28 14:32:26 +0000236 sts = 1
237 if sts:
238 return sts
239 message = raw_input("One-liner: ")
240 for file in files:
Guido van Rossum6bb4a511995-04-28 15:26:37 +0000241 self.cvs.entries[file].commit(message)
242 self.cvs.putentries()
Guido van Rossum330e8841995-04-28 17:56:32 +0000243 do_com = do_commit
244
245 def do_diff(self, opts, files):
246 """diff [difflags] [file] ..."""
247 if self.cvs.checkfiles(files):
248 return 1
249 for file in files:
250 self.cvs.entries[file].diff(opts)
251 do_dif = do_diff
252 flags_diff = 'cbitwcefhnlrsD:S:'
253
254
255
256def remove(fn):
257 try:
258 os.unlink(fn)
259 except os.error:
260 pass
Guido van Rossumae21ced1995-04-28 14:32:26 +0000261
Guido van Rossum5f07b841995-04-26 22:57:11 +0000262
Guido van Rossumdeb627c1995-04-27 21:28:53 +0000263def main():
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000264 rcvs().run()
Guido van Rossum097c55a1995-04-27 18:07:07 +0000265
Guido van Rossum5f07b841995-04-26 22:57:11 +0000266
267if __name__ == "__main__":
Guido van Rossumdeb627c1995-04-27 21:28:53 +0000268 main()