blob: 1c323e23a78a7ee34f3a39d1b9862c80182ed9c1 [file] [log] [blame]
Guido van Rossum097c55a1995-04-27 18:07:07 +00001#! /usr/local/bin/python
2
3"Remote CVS -- command line interface"
4
Guido van Rossum5f07b841995-04-26 22:57:11 +00005from cvslib import CVS, Entry
Guido van Rossum5f07b841995-04-26 22:57:11 +00006import md5
7import os
8import string
9import sys
10import time
11import fnmatch
12
13
14ignored_patterns = ['*.pyc', '.*', '*~', '@*']
15def ignored(file):
16 if os.path.isdir(file): return 1
17 for pat in ignored_patterns:
18 if fnmatch.fnmatch(file, pat): return 1
19 return 0
Guido van Rossum097c55a1995-04-27 18:07:07 +000020def not_ignored(file):
21 return not ignored(file)
Guido van Rossum5f07b841995-04-26 22:57:11 +000022
23
24class PCVS(CVS):
25
26 def __init__(self, proxy):
27 CVS.__init__(self)
28 self.proxy = proxy
29 self.readsums()
30 self.calcsums()
31
32 def calcsums(self):
33 for file in self.keys():
34 e = self.entries[file]
35 if not e.new and e.sum is None:
36 sum = self.proxy.sum((file, e.rev))
37 e.setsum(sum)
38
Guido van Rossum097c55a1995-04-27 18:07:07 +000039 def prepare(self):
40 self.localfiles = filter(not_ignored, os.listdir(os.curdir))
41 self.localfiles.sort()
42
43 self.entryfiles = self.keys()
44
45 self.remotefiles = self.proxy.listfiles()
46
47 self.rcsfiles = self.entryfiles[:]
48 for file in self.remotefiles:
49 if file not in self.rcsfiles:
50 self.rcsfiles.append(file)
51 self.rcsfiles.sort()
52
53 self.localonlyfiles = []
54 for file in self.localfiles:
55 if file not in self.rcsfiles:
56 self.localonlyfiles.append(file)
57 self.localonlyfiles.sort()
58
59 self.allfiles = self.rcsfiles + self.localonlyfiles
60 self.allfiles.sort()
61
62 def preparedetails(self, file):
63 entry = file in self.entryfiles
64 if entry:
Guido van Rossum5f07b841995-04-26 22:57:11 +000065 e = self.entries[file]
Guido van Rossum097c55a1995-04-27 18:07:07 +000066 else:
67 e = Entry('/%s/0///' % file)
68 e.entry = entry
69 e.local = file in self.localfiles
70 e.remote = file in self.remotefiles
71 if e.local:
72 e.lsum = sumfile(file)
73 else:
74 e.lsum = None
75 if e.remote:
76 e.rrev = self.proxy.head(file)
77 if e.rrev == e.rev:
78 e.rsum = e.sum
79 else:
80 e.rsum = self.proxy.sum(file)
81 else:
82 e.rrev = '0'
83 e.rsum = None
84 return e
85
86 def report(self):
87 self.prepare()
88 for file in self.allfiles:
89 e = self.preparedetails(file)
90 if e.lsum == e.sum == e.rsum:
91 # All three exist and are equal
92 print '=', file
93 elif e.lsum == e.sum:
94 # Not modified locally, remote update pending
95 if e.lsum is None:
96 print 'N', file, '(new remote)'
97 else:
98 print 'U', file
99 elif e.sum == e.rsum:
100 # No remote update, modified locally
101 if e.rsum is None:
102 if e.new:
103 print 'A', file
104 else:
105 print '?', file
106 else:
107 if e.lsum is None:
108 print 'LOST', file
109 else:
110 print 'M', file
111 else:
112 # Conflict: remote update and locally modified
113 if e.lsum == e.rsum:
114 # Local and remote match!
115 print 'c', file
116 else:
117 print 'C', file
118
119 def fullcheck(self):
120 self.prepare()
121 ok = 1
122 for file in self.allfiles:
123 if file not in self.entryfiles \
124 and file not in self.remotefiles:
125 continue
126 e = self.preparedetails(file)
Guido van Rossum5f07b841995-04-26 22:57:11 +0000127 if e.new:
Guido van Rossum097c55a1995-04-27 18:07:07 +0000128 if e.rrev:
129 print "%s: created by someone else"%file
Guido van Rossum5f07b841995-04-26 22:57:11 +0000130 ok = 0
131 continue
Guido van Rossum097c55a1995-04-27 18:07:07 +0000132 if e.rrev != e.rev:
Guido van Rossum5f07b841995-04-26 22:57:11 +0000133 print "%s: out of date (%s vs. %s)" % \
134 (file, e.rev, rrev)
135 ok = 0
136 return ok
137
138 def update(self):
Guido van Rossum097c55a1995-04-27 18:07:07 +0000139 self.prepare()
140 for file in self.rcsfiles:
141 e = self.preparedetails(file)
142 if e.lsum == e.sum == e.rsum:
143 print '=', file
Guido van Rossum5f07b841995-04-26 22:57:11 +0000144 continue
Guido van Rossum097c55a1995-04-27 18:07:07 +0000145 if e.sum == e.rsum:
146 if e.rev != e.rrev:
147 print '%s: %s -> %s w/o change' % \
148 (file, e.rev, e.rrev)
149 e.rev = e.rrev
150 if e.lsum != e.sum:
151 if e.lsum is None:
152 print '%s: file was lost' % \
153 (file,)
154 self.get(e)
155 elif e.new:
156 print 'A', file
157 else:
158 print 'M', file
Guido van Rossum5f07b841995-04-26 22:57:11 +0000159 continue
Guido van Rossum097c55a1995-04-27 18:07:07 +0000160 if e.lsum == e.sum:
161 if e.rev == e.rrev:
162 print '%s: no new revision' % file
163 print 'U', file,
164 sys.stdout.flush()
165 self.get(e)
166 print
Guido van Rossum5f07b841995-04-26 22:57:11 +0000167 continue
Guido van Rossum097c55a1995-04-27 18:07:07 +0000168 if e.lsum == e.rsum:
169 print 'c', file
170 print e.__dict__
171 e.rev = e.rrev
172 e.sum = e.rsum
173 e.new = e.sum is None and e.lsum is not None
174 if e.sum:
175 e.mtime, e.ctime = os.stat(e.file)[-2:]
176 print e.__dict__
177 self.entries[file] = e
178 continue
179 print 'C', file, '(not resolved)'
Guido van Rossum5f07b841995-04-26 22:57:11 +0000180 self.writeentries()
181 self.writesums()
182
Guido van Rossum097c55a1995-04-27 18:07:07 +0000183 def get(self, e):
184 data = self.proxy.get(e.file)
185 f = open(e.file, 'w')
186 f.write(data)
187 f.close()
188 nsum = md5.new(data).digest()
189 e.setsum(nsum)
190 e.mtime, e.ctime = os.stat(e.file)[-2:]
191 e.new = 0
192 e.rev = e.rrev
193
Guido van Rossum5f07b841995-04-26 22:57:11 +0000194 def commit(self):
195 if not self.fullcheck():
196 print "correct above errors first"
197 return
198 needed = []
199 for file in self.keys():
200 e = self.entries[file]
201 if e.new:
202 needed.append(file)
203 continue
204 lsum = sumfile(file)
205 if lsum != e.sum:
206 needed.append(file)
207 continue
208 if not needed:
209 print "no changes need committing"
210 return
211 message = raw_input("One-liner: ")
212 for file in needed:
213 print "%s: putting ..." % file
214 e = self.entries[file]
215 data = open(file).read()
216 self.proxy.put(file, data, message)
217 e.rev = self.proxy.head(file)
218 e.setsum(self.proxy.sum(file))
Guido van Rossum097c55a1995-04-27 18:07:07 +0000219 e.new = 0
Guido van Rossum5f07b841995-04-26 22:57:11 +0000220 # XXX get it?
221 mtime, ctime = os.stat(file)[-2:]
222 e.mtime = mtime
223 e.ctime = ctime
224 self.writeentries()
225 self.writesums()
226
Guido van Rossum5f07b841995-04-26 22:57:11 +0000227 def add(self, file):
228 if self.entries.has_key(file):
Guido van Rossum097c55a1995-04-27 18:07:07 +0000229 print "%s: already known" % file
Guido van Rossum5f07b841995-04-26 22:57:11 +0000230 else:
231 self.entries[file] = Entry('/%s/0/Initial %s//\n' %
232 (file, file))
233
234
235def sumfile(file):
236 return md5.new(open(file).read()).digest()
237
238
239def test():
Guido van Rossum097c55a1995-04-27 18:07:07 +0000240 import sys
241 import getopt
242 from rcsclient import openrcsclient
243
244 opts, args = getopt.getopt(sys.argv[1:], 'd:h:p:vq')
245 proxy = openrcsclient(opts)
Guido van Rossum5f07b841995-04-26 22:57:11 +0000246 x = PCVS(proxy)
Guido van Rossum097c55a1995-04-27 18:07:07 +0000247
Guido van Rossum5f07b841995-04-26 22:57:11 +0000248 if args:
249 cmd = args[0]
250 files = args[1:]
251 if cmd == 'add':
252 if not files:
253 print "add needs at least one file argument"
254 else:
255 for file in files:
256 x.add(file)
257 x.writeentries()
258 elif cmd in ('update', 'up'):
259 if files:
260 print "updates wants no file arguments"
261 else:
262 x.update()
263 elif cmd in ('commit', 'com'):
264 if files:
265 print "commit wants no file arguments"
266 else:
267 x.commit()
268 else:
269 print "Unknown command", cmd
270 else:
271 x.report()
Guido van Rossum5f07b841995-04-26 22:57:11 +0000272
273if __name__ == "__main__":
274 test()