blob: d9d1c55d6245359354c1bff33389fc44a40f59c8 [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 = []):
Guido van Rossum2d2a60e1995-04-28 19:24:50 +0000116 if self.lsum == self.rsum:
117 return
Guido van Rossum330e8841995-04-28 17:56:32 +0000118 import tempfile
119 flags = ''
120 for o, a in opts:
121 flags = flags + ' ' + o + a
122 flags = flags[1:]
123 fn = self.file
124 data = self.proxy.get(fn)
125 tfn = tempfile.mktemp()
126 try:
127 tf = open(tfn, 'w')
128 tf.write(data)
129 tf.close()
130 print 'diff %s -r%s %s' % (flags, self.rrev, fn)
131 sts = os.system('diff %s %s %s' % (flags, tfn, fn))
132 if sts:
133 print '='*70
134 finally:
135 remove(tfn)
136
Guido van Rossumae21ced1995-04-28 14:32:26 +0000137 def commitcheck(self):
138 return self.action() != 'C'
139
140 def put(self, message = ""):
Guido van Rossumbafc14d1995-04-28 15:41:51 +0000141 print "Checking in", self.file, "..."
142 data = open(self.file).read()
143 messages = self.proxy.put(self.file, data, message)
144 if messages:
145 print messages
Guido van Rossumae21ced1995-04-28 14:32:26 +0000146
147 def get(self):
148 data = self.proxy.get(self.file)
149 f = open(self.file, 'w')
150 f.write(data)
151 f.close()
152 self.eseen = 1
153 self.esum = self.rsum
154 self.emtime, self.ectime = os.stat(self.file)[-2:]
155 self.erev = self.rrev
156 self.enew = 0
157 self.edeleted = 0
158 # XXX anything else?
Guido van Rossum5f07b841995-04-26 22:57:11 +0000159
160
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000161class RCVS(CVS):
162
163 FileClass = MyFile
164
165 def __init__(self):
166 CVS.__init__(self)
167
168 def checkfiles(self, files):
169 if not files:
170 def ok(file, self=self):
171 e = self.entries[file]
172 return e.eseen or e.rseen
173 files[:] = filter(ok, self.entries.keys())
174 files.sort()
Guido van Rossumae21ced1995-04-28 14:32:26 +0000175 if not files:
176 print "no files to be processed"
177 return 1
178 else:
179 return None
180 else:
181 sts = None
182 for file in files:
183 if not self.entries.has_key(file):
184 print "%s: nothing known" % file
185 sts = 1
186 return sts
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000187
188
189class rcvs(CommandFrameWork):
190
191 GlobalFlags = 'd:h:p:qv'
192 UsageMessage = \
Guido van Rossum2d2a60e1995-04-28 19:24:50 +0000193"usage: rcvs [-d directory] [-h host] [-p port] [-q] [-v] [subcommand arg ...]"
194 PostUsageMessage = \
195 "If no subcommand is given, the status of all files is listed"
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000196
197 def __init__(self):
198 """Constructor."""
199 CommandFrameWork.__init__(self)
200 self.proxy = None
201 self.cvs = RCVS()
202
203 def options(self, opts):
204 self.opts = opts
205
206 def ready(self):
207 import rcsclient
208 self.proxy = rcsclient.openrcsclient(self.opts)
209 self.cvs.setproxy(self.proxy)
210 self.cvs.getentries()
211 self.cvs.getlocalfiles()
212 self.cvs.getremotefiles(self.proxy)
213
214 def default(self):
Guido van Rossumae21ced1995-04-28 14:32:26 +0000215 files = []
216 if self.cvs.checkfiles(files):
217 return 1
Guido van Rossum6bb4a511995-04-28 15:26:37 +0000218 for file in files:
219 print self.cvs.entries[file].action(), file
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000220
221 def do_update(self, opts, files):
Guido van Rossumae21ced1995-04-28 14:32:26 +0000222 """update [file] ..."""
223 if self.cvs.checkfiles(files):
224 return 1
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000225 for file in files:
226 if not self.cvs.entries.has_key(file):
227 print "%s: not found" % file
228 else:
229 self.cvs.entries[file].update()
Guido van Rossum6bb4a511995-04-28 15:26:37 +0000230 self.cvs.putentries()
Guido van Rossum330e8841995-04-28 17:56:32 +0000231 do_up = do_update
Guido van Rossum5f07b841995-04-26 22:57:11 +0000232
Guido van Rossumae21ced1995-04-28 14:32:26 +0000233 def do_commit(self, opts, files):
234 """commit [file] ..."""
235 if self.cvs.checkfiles(files):
236 return 1
237 sts = 0
238 for file in files:
Guido van Rossum6bb4a511995-04-28 15:26:37 +0000239 if not self.cvs.entries[file].commitcheck():
Guido van Rossumae21ced1995-04-28 14:32:26 +0000240 sts = 1
241 if sts:
242 return sts
243 message = raw_input("One-liner: ")
244 for file in files:
Guido van Rossum6bb4a511995-04-28 15:26:37 +0000245 self.cvs.entries[file].commit(message)
246 self.cvs.putentries()
Guido van Rossum330e8841995-04-28 17:56:32 +0000247 do_com = do_commit
248
249 def do_diff(self, opts, files):
250 """diff [difflags] [file] ..."""
251 if self.cvs.checkfiles(files):
252 return 1
253 for file in files:
254 self.cvs.entries[file].diff(opts)
255 do_dif = do_diff
256 flags_diff = 'cbitwcefhnlrsD:S:'
257
258
259
260def remove(fn):
261 try:
262 os.unlink(fn)
263 except os.error:
264 pass
Guido van Rossumae21ced1995-04-28 14:32:26 +0000265
Guido van Rossum5f07b841995-04-26 22:57:11 +0000266
Guido van Rossumdeb627c1995-04-27 21:28:53 +0000267def main():
Guido van Rossumc218a7e1995-04-27 23:33:43 +0000268 rcvs().run()
Guido van Rossum097c55a1995-04-27 18:07:07 +0000269
Guido van Rossum5f07b841995-04-26 22:57:11 +0000270
271if __name__ == "__main__":
Guido van Rossumdeb627c1995-04-27 21:28:53 +0000272 main()