blob: f4795a48964f8196ac0a1e0b041d0e1818a8e961 [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
Guido van Rossum097c55a1995-04-27 18:07:07 +0000170 e.rev = e.rrev
171 e.sum = e.rsum
172 e.new = e.sum is None and e.lsum is not None
173 if e.sum:
174 e.mtime, e.ctime = os.stat(e.file)[-2:]
Guido van Rossum097c55a1995-04-27 18:07:07 +0000175 self.entries[file] = e
176 continue
177 print 'C', file, '(not resolved)'
Guido van Rossum5f07b841995-04-26 22:57:11 +0000178 self.writeentries()
179 self.writesums()
180
Guido van Rossum097c55a1995-04-27 18:07:07 +0000181 def get(self, e):
182 data = self.proxy.get(e.file)
183 f = open(e.file, 'w')
184 f.write(data)
185 f.close()
186 nsum = md5.new(data).digest()
187 e.setsum(nsum)
188 e.mtime, e.ctime = os.stat(e.file)[-2:]
189 e.new = 0
190 e.rev = e.rrev
191
Guido van Rossum5f07b841995-04-26 22:57:11 +0000192 def commit(self):
193 if not self.fullcheck():
194 print "correct above errors first"
195 return
196 needed = []
197 for file in self.keys():
198 e = self.entries[file]
199 if e.new:
200 needed.append(file)
201 continue
202 lsum = sumfile(file)
203 if lsum != e.sum:
204 needed.append(file)
205 continue
206 if not needed:
207 print "no changes need committing"
208 return
209 message = raw_input("One-liner: ")
210 for file in needed:
211 print "%s: putting ..." % file
212 e = self.entries[file]
213 data = open(file).read()
214 self.proxy.put(file, data, message)
215 e.rev = self.proxy.head(file)
216 e.setsum(self.proxy.sum(file))
Guido van Rossum097c55a1995-04-27 18:07:07 +0000217 e.new = 0
Guido van Rossum5f07b841995-04-26 22:57:11 +0000218 # XXX get it?
219 mtime, ctime = os.stat(file)[-2:]
220 e.mtime = mtime
221 e.ctime = ctime
222 self.writeentries()
223 self.writesums()
224
Guido van Rossum5f07b841995-04-26 22:57:11 +0000225 def add(self, file):
226 if self.entries.has_key(file):
Guido van Rossum097c55a1995-04-27 18:07:07 +0000227 print "%s: already known" % file
Guido van Rossum5f07b841995-04-26 22:57:11 +0000228 else:
229 self.entries[file] = Entry('/%s/0/Initial %s//\n' %
230 (file, file))
231
232
233def sumfile(file):
234 return md5.new(open(file).read()).digest()
235
236
Guido van Rossumdeb627c1995-04-27 21:28:53 +0000237def main():
Guido van Rossum097c55a1995-04-27 18:07:07 +0000238 import sys
239 import getopt
240 from rcsclient import openrcsclient
241
242 opts, args = getopt.getopt(sys.argv[1:], 'd:h:p:vq')
243 proxy = openrcsclient(opts)
Guido van Rossum5f07b841995-04-26 22:57:11 +0000244 x = PCVS(proxy)
Guido van Rossum097c55a1995-04-27 18:07:07 +0000245
Guido van Rossum5f07b841995-04-26 22:57:11 +0000246 if args:
247 cmd = args[0]
248 files = args[1:]
249 if cmd == 'add':
250 if not files:
251 print "add needs at least one file argument"
252 else:
253 for file in files:
254 x.add(file)
255 x.writeentries()
256 elif cmd in ('update', 'up'):
257 if files:
258 print "updates wants no file arguments"
259 else:
260 x.update()
261 elif cmd in ('commit', 'com'):
262 if files:
263 print "commit wants no file arguments"
264 else:
265 x.commit()
266 else:
267 print "Unknown command", cmd
268 else:
269 x.report()
Guido van Rossum5f07b841995-04-26 22:57:11 +0000270
271if __name__ == "__main__":
Guido van Rossumdeb627c1995-04-27 21:28:53 +0000272 main()