| Guido van Rossum | f06ee5f | 1996-11-27 19:52:01 +0000 | [diff] [blame] | 1 | #! /usr/bin/env python | 
| Guido van Rossum | 097c55a | 1995-04-27 18:07:07 +0000 | [diff] [blame] | 2 |  | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 3 | """Remote CVS -- command line interface""" | 
| Guido van Rossum | 097c55a | 1995-04-27 18:07:07 +0000 | [diff] [blame] | 4 |  | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 5 | # XXX To do: | 
 | 6 | # | 
| Guido van Rossum | 903afd0 | 1995-06-23 22:33:57 +0000 | [diff] [blame] | 7 | # Bugs: | 
 | 8 | # - if the remote file is deleted, "rcvs update" will fail | 
 | 9 | # | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 10 | # Functionality: | 
| Guido van Rossum | a79f5a3 | 1995-07-18 18:34:34 +0000 | [diff] [blame] | 11 | # - cvs rm | 
 | 12 | # - descend into directories (alraedy done for update) | 
 | 13 | # - conflict resolution | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 14 | # - other relevant commands? | 
 | 15 | # - branches | 
 | 16 | # | 
 | 17 | # - Finesses: | 
 | 18 | # - retain file mode's x bits | 
 | 19 | # - complain when "nothing known about filename" | 
 | 20 | # - edit log message the way CVS lets you edit it | 
 | 21 | # - cvs diff -rREVA -rREVB | 
 | 22 | # - send mail the way CVS sends it | 
 | 23 | # | 
 | 24 | # Performance: | 
 | 25 | # - cache remote checksums (for every revision ever seen!) | 
 | 26 | # - translate symbolic revisions to numeric revisions | 
 | 27 | # | 
 | 28 | # Reliability: | 
 | 29 | # - remote locking | 
 | 30 | # | 
 | 31 | # Security: | 
 | 32 | # - Authenticated RPC? | 
 | 33 |  | 
 | 34 |  | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 35 | from cvslib import CVS, File | 
| Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 36 | import md5 | 
 | 37 | import os | 
 | 38 | import string | 
 | 39 | import sys | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 40 | from cmdfw import CommandFrameWork | 
| Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 41 |  | 
 | 42 |  | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 43 | DEF_LOCAL = 1				# Default -l | 
 | 44 |  | 
 | 45 |  | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 46 | class MyFile(File): | 
| Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 47 |  | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 48 | 	def action(self): | 
 | 49 | 		"""Return a code indicating the update status of this file. | 
 | 50 |  | 
 | 51 | 		The possible return values are: | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 52 | 		 | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 53 | 		'=' -- everything's fine | 
 | 54 | 		'0' -- file doesn't exist anywhere | 
 | 55 | 		'?' -- exists locally only | 
 | 56 | 		'A' -- new locally | 
 | 57 | 		'R' -- deleted locally | 
 | 58 | 		'U' -- changed remotely, no changes locally | 
| Guido van Rossum | 6bb4a51 | 1995-04-28 15:26:37 +0000 | [diff] [blame] | 59 | 		       (includes new remotely or deleted remotely) | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 60 | 		'M' -- changed locally, no changes remotely | 
 | 61 | 		'C' -- conflict: changed locally as well as remotely | 
 | 62 | 		       (includes cases where the file has been added | 
 | 63 | 		       or removed locally and remotely) | 
| Guido van Rossum | ba24468 | 1995-04-28 15:33:03 +0000 | [diff] [blame] | 64 | 		'D' -- deleted remotely | 
 | 65 | 		'N' -- new remotely | 
| Guido van Rossum | 6bb4a51 | 1995-04-28 15:26:37 +0000 | [diff] [blame] | 66 | 		'r' -- get rid of entry | 
 | 67 | 		'c' -- create entry | 
 | 68 | 		'u' -- update entry | 
| Guido van Rossum | 2f7ef91 | 1995-05-01 20:22:01 +0000 | [diff] [blame] | 69 |  | 
 | 70 | 		(and probably others :-) | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 71 | 		""" | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 72 | 		if not self.lseen: | 
 | 73 | 			self.getlocal() | 
 | 74 | 		if not self.rseen: | 
 | 75 | 			self.getremote() | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 76 | 		if not self.eseen: | 
| Guido van Rossum | 2f7ef91 | 1995-05-01 20:22:01 +0000 | [diff] [blame] | 77 | 			if not self.lsum: | 
 | 78 | 				if not self.rsum: return '0' # Never heard of | 
| Guido van Rossum | 6bb4a51 | 1995-04-28 15:26:37 +0000 | [diff] [blame] | 79 | 				else: | 
 | 80 | 					return 'N' # New remotely | 
| Guido van Rossum | 2f7ef91 | 1995-05-01 20:22:01 +0000 | [diff] [blame] | 81 | 			else: # self.lsum | 
 | 82 | 				if not self.rsum: return '?' # Local only | 
| Guido van Rossum | 6bb4a51 | 1995-04-28 15:26:37 +0000 | [diff] [blame] | 83 | 				# Local and remote, but no entry | 
 | 84 | 				if self.lsum == self.rsum: | 
 | 85 | 					return 'c' # Restore entry only | 
 | 86 | 				else: return 'C' # Real conflict | 
 | 87 | 		else: # self.eseen | 
| Guido van Rossum | 2f7ef91 | 1995-05-01 20:22:01 +0000 | [diff] [blame] | 88 | 			if not self.lsum: | 
 | 89 | 				if self.edeleted: | 
 | 90 | 					if self.rsum: return 'R' # Removed | 
| Guido van Rossum | 6bb4a51 | 1995-04-28 15:26:37 +0000 | [diff] [blame] | 91 | 					else: return 'r' # Get rid of entry | 
| Guido van Rossum | 2f7ef91 | 1995-05-01 20:22:01 +0000 | [diff] [blame] | 92 | 				else: # not self.edeleted | 
 | 93 | 					if self.rsum: | 
| Guido van Rossum | 6bb4a51 | 1995-04-28 15:26:37 +0000 | [diff] [blame] | 94 | 						print "warning:", | 
 | 95 | 						print self.file, | 
 | 96 | 						print "was lost" | 
 | 97 | 						return 'U' | 
 | 98 | 					else: return 'r' # Get rid of entry | 
| Guido van Rossum | 2f7ef91 | 1995-05-01 20:22:01 +0000 | [diff] [blame] | 99 | 			else: # self.lsum | 
 | 100 | 				if not self.rsum: | 
| Guido van Rossum | 6bb4a51 | 1995-04-28 15:26:37 +0000 | [diff] [blame] | 101 | 					if self.enew: return 'A' # New locally | 
 | 102 | 					else: return 'D' # Deleted remotely | 
| Guido van Rossum | 2f7ef91 | 1995-05-01 20:22:01 +0000 | [diff] [blame] | 103 | 				else: # self.rsum | 
| Guido van Rossum | 6bb4a51 | 1995-04-28 15:26:37 +0000 | [diff] [blame] | 104 | 					if self.enew: | 
 | 105 | 						if self.lsum == self.rsum: | 
 | 106 | 							return 'u' | 
 | 107 | 						else: | 
 | 108 | 							return 'C' | 
 | 109 | 					if self.lsum == self.esum: | 
 | 110 | 						if self.esum == self.rsum: | 
 | 111 | 							return '=' | 
 | 112 | 						else: | 
 | 113 | 							return 'U' | 
 | 114 | 					elif self.esum == self.rsum: | 
 | 115 | 						return 'M' | 
 | 116 | 					elif self.lsum == self.rsum: | 
 | 117 | 						return 'u' | 
 | 118 | 					else: | 
 | 119 | 						return 'C' | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 120 |  | 
 | 121 | 	def update(self): | 
 | 122 | 		code = self.action() | 
| Guido van Rossum | 8b5e0fa | 1995-04-28 21:48:16 +0000 | [diff] [blame] | 123 | 		if code == '=': return | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 124 | 		print code, self.file | 
| Guido van Rossum | ba24468 | 1995-04-28 15:33:03 +0000 | [diff] [blame] | 125 | 		if code in ('U', 'N'): | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 126 | 			self.get() | 
 | 127 | 		elif code == 'C': | 
 | 128 | 			print "%s: conflict resolution not yet implemented" % \ | 
 | 129 | 			      self.file | 
| Guido van Rossum | ba24468 | 1995-04-28 15:33:03 +0000 | [diff] [blame] | 130 | 		elif code == 'D': | 
| Guido van Rossum | 330e884 | 1995-04-28 17:56:32 +0000 | [diff] [blame] | 131 | 			remove(self.file) | 
| Guido van Rossum | ba24468 | 1995-04-28 15:33:03 +0000 | [diff] [blame] | 132 | 			self.eseen = 0 | 
 | 133 | 		elif code == 'r': | 
 | 134 | 			self.eseen = 0 | 
 | 135 | 		elif code in ('c', 'u'): | 
| Guido van Rossum | d22f59f | 1995-04-28 15:37:22 +0000 | [diff] [blame] | 136 | 			self.eseen = 1 | 
| Guido van Rossum | ba24468 | 1995-04-28 15:33:03 +0000 | [diff] [blame] | 137 | 			self.erev = self.rrev | 
 | 138 | 			self.enew = 0 | 
 | 139 | 			self.edeleted = 0 | 
 | 140 | 			self.esum = self.rsum | 
 | 141 | 			self.emtime, self.ectime = os.stat(self.file)[-2:] | 
| Guido van Rossum | d22f59f | 1995-04-28 15:37:22 +0000 | [diff] [blame] | 142 | 			self.extra = '' | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 143 |  | 
 | 144 | 	def commit(self, message = ""): | 
 | 145 | 		code = self.action() | 
 | 146 | 		if code in ('A', 'M'): | 
 | 147 | 			self.put(message) | 
| Guido van Rossum | 7bde92b | 1995-10-07 19:47:26 +0000 | [diff] [blame] | 148 | 			return 1 | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 149 | 		elif code == 'R': | 
 | 150 | 			print "%s: committing removes not yet implemented" % \ | 
 | 151 | 			      self.file | 
 | 152 | 		elif code == 'C': | 
 | 153 | 			print "%s: conflict resolution not yet implemented" % \ | 
 | 154 | 			      self.file | 
 | 155 |  | 
| Guido van Rossum | 330e884 | 1995-04-28 17:56:32 +0000 | [diff] [blame] | 156 | 	def diff(self, opts = []): | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 157 | 		self.action()		# To update lseen, rseen | 
| Guido van Rossum | 330e884 | 1995-04-28 17:56:32 +0000 | [diff] [blame] | 158 | 		flags = '' | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 159 | 		rev = self.rrev | 
 | 160 | 		# XXX should support two rev options too! | 
| Guido van Rossum | 330e884 | 1995-04-28 17:56:32 +0000 | [diff] [blame] | 161 | 		for o, a in opts: | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 162 | 			if o == '-r': | 
 | 163 | 				rev = a | 
 | 164 | 			else: | 
 | 165 | 				flags = flags + ' ' + o + a | 
 | 166 | 		if rev == self.rrev and self.lsum == self.rsum: | 
 | 167 | 			return | 
| Guido van Rossum | 330e884 | 1995-04-28 17:56:32 +0000 | [diff] [blame] | 168 | 		flags = flags[1:] | 
 | 169 | 		fn = self.file | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 170 | 		data = self.proxy.get((fn, rev)) | 
 | 171 | 		sum = md5.new(data).digest() | 
 | 172 | 		if self.lsum == sum: | 
 | 173 | 			return | 
 | 174 | 		import tempfile | 
| Guido van Rossum | 330e884 | 1995-04-28 17:56:32 +0000 | [diff] [blame] | 175 | 		tfn = tempfile.mktemp() | 
 | 176 | 		try: | 
 | 177 | 			tf = open(tfn, 'w') | 
 | 178 | 			tf.write(data) | 
 | 179 | 			tf.close() | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 180 | 			print 'diff %s -r%s %s' % (flags, rev, fn) | 
| Guido van Rossum | 330e884 | 1995-04-28 17:56:32 +0000 | [diff] [blame] | 181 | 			sts = os.system('diff %s %s %s' % (flags, tfn, fn)) | 
 | 182 | 			if sts: | 
 | 183 | 				print '='*70 | 
 | 184 | 		finally: | 
 | 185 | 			remove(tfn) | 
 | 186 |  | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 187 | 	def commitcheck(self): | 
 | 188 | 		return self.action() != 'C' | 
 | 189 |  | 
 | 190 | 	def put(self, message = ""): | 
| Guido van Rossum | bafc14d | 1995-04-28 15:41:51 +0000 | [diff] [blame] | 191 | 		print "Checking in", self.file, "..." | 
 | 192 | 		data = open(self.file).read() | 
| Guido van Rossum | a79f5a3 | 1995-07-18 18:34:34 +0000 | [diff] [blame] | 193 | 		if not self.enew: | 
 | 194 | 			self.proxy.lock(self.file) | 
| Guido van Rossum | bafc14d | 1995-04-28 15:41:51 +0000 | [diff] [blame] | 195 | 		messages = self.proxy.put(self.file, data, message) | 
 | 196 | 		if messages: | 
 | 197 | 			print messages | 
| Guido van Rossum | 8b5e0fa | 1995-04-28 21:48:16 +0000 | [diff] [blame] | 198 | 		self.setentry(self.proxy.head(self.file), self.lsum) | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 199 | 	 | 
 | 200 | 	def get(self): | 
 | 201 | 		data = self.proxy.get(self.file) | 
 | 202 | 		f = open(self.file, 'w') | 
 | 203 | 		f.write(data) | 
 | 204 | 		f.close() | 
| Guido van Rossum | 8b5e0fa | 1995-04-28 21:48:16 +0000 | [diff] [blame] | 205 | 		self.setentry(self.rrev, self.rsum) | 
 | 206 |  | 
| Guido van Rossum | 7bde92b | 1995-10-07 19:47:26 +0000 | [diff] [blame] | 207 | 	def log(self, otherflags): | 
 | 208 | 		print self.proxy.log(self.file, otherflags) | 
 | 209 |  | 
| Guido van Rossum | a79f5a3 | 1995-07-18 18:34:34 +0000 | [diff] [blame] | 210 | 	def add(self): | 
 | 211 | 		self.eseen = 0		# While we're hacking... | 
 | 212 | 		self.esum = self.lsum | 
 | 213 | 		self.emtime, self.ectime = 0, 0 | 
 | 214 | 		self.erev = '' | 
 | 215 | 		self.enew = 1 | 
 | 216 | 		self.edeleted = 0 | 
 | 217 | 		self.eseen = 1		# Done | 
 | 218 | 		self.extra = '' | 
 | 219 |  | 
| Guido van Rossum | 8b5e0fa | 1995-04-28 21:48:16 +0000 | [diff] [blame] | 220 | 	def setentry(self, erev, esum): | 
 | 221 | 		self.eseen = 0		# While we're hacking... | 
 | 222 | 		self.esum = esum | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 223 | 		self.emtime, self.ectime = os.stat(self.file)[-2:] | 
| Guido van Rossum | 8b5e0fa | 1995-04-28 21:48:16 +0000 | [diff] [blame] | 224 | 		self.erev = erev | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 225 | 		self.enew = 0 | 
 | 226 | 		self.edeleted = 0 | 
| Guido van Rossum | 8b5e0fa | 1995-04-28 21:48:16 +0000 | [diff] [blame] | 227 | 		self.eseen = 1		# Done | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 228 | 		self.extra = '' | 
 | 229 |  | 
 | 230 |  | 
 | 231 | SENDMAIL = "/usr/lib/sendmail -t" | 
 | 232 | MAILFORM = """To: %s | 
 | 233 | Subject: CVS changes: %s | 
 | 234 |  | 
 | 235 | ...Message from rcvs... | 
 | 236 |  | 
 | 237 | Committed files: | 
 | 238 | 	%s | 
 | 239 |  | 
 | 240 | Log message: | 
 | 241 | 	%s | 
 | 242 | """ | 
| Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 243 |  | 
 | 244 |  | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 245 | class RCVS(CVS): | 
 | 246 |  | 
 | 247 | 	FileClass = MyFile | 
 | 248 |  | 
 | 249 | 	def __init__(self): | 
 | 250 | 		CVS.__init__(self) | 
 | 251 |  | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 252 | 	def update(self, files): | 
 | 253 | 		for e in self.whichentries(files, 1): | 
 | 254 | 			e.update() | 
 | 255 |  | 
 | 256 | 	def commit(self, files, message = ""): | 
 | 257 | 		list = self.whichentries(files) | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 258 | 		if not list: return | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 259 | 		ok = 1 | 
 | 260 | 		for e in list: | 
 | 261 | 			if not e.commitcheck(): | 
 | 262 | 				ok = 0 | 
 | 263 | 		if not ok: | 
 | 264 | 			print "correct above errors first" | 
 | 265 | 			return | 
 | 266 | 		if not message: | 
 | 267 | 			message = raw_input("One-liner: ") | 
| Guido van Rossum | a79f5a3 | 1995-07-18 18:34:34 +0000 | [diff] [blame] | 268 | 		committed = [] | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 269 | 		for e in list: | 
| Guido van Rossum | 7bde92b | 1995-10-07 19:47:26 +0000 | [diff] [blame] | 270 | 			if e.commit(message): | 
 | 271 | 				committed.append(e.file) | 
| Guido van Rossum | a79f5a3 | 1995-07-18 18:34:34 +0000 | [diff] [blame] | 272 | 		self.mailinfo(committed, message) | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 273 |  | 
 | 274 | 	def mailinfo(self, files, message = ""): | 
 | 275 | 		towhom = "sjoerd@cwi.nl, jack@cwi.nl" # XXX | 
 | 276 | 		mailtext = MAILFORM % (towhom, string.join(files), | 
 | 277 | 					string.join(files), message) | 
 | 278 | 		print '-'*70 | 
 | 279 | 		print mailtext | 
 | 280 | 		print '-'*70 | 
 | 281 | 		ok = raw_input("OK to mail to %s? " % towhom) | 
 | 282 | 		if string.lower(string.strip(ok)) in ('y', 'ye', 'yes'): | 
 | 283 | 			p = os.popen(SENDMAIL, "w") | 
 | 284 | 			p.write(mailtext) | 
 | 285 | 			sts = p.close() | 
 | 286 | 			if sts: | 
 | 287 | 				print "Sendmail exit status %s" % str(sts) | 
 | 288 | 			else: | 
 | 289 | 				print "Mail sent." | 
 | 290 | 		else: | 
 | 291 | 			print "No mail sent." | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 292 |  | 
 | 293 | 	def report(self, files): | 
 | 294 | 		for e in self.whichentries(files): | 
 | 295 | 			e.report() | 
 | 296 |  | 
 | 297 | 	def diff(self, files, opts): | 
 | 298 | 		for e in self.whichentries(files): | 
 | 299 | 			e.diff(opts) | 
 | 300 |  | 
| Guido van Rossum | a79f5a3 | 1995-07-18 18:34:34 +0000 | [diff] [blame] | 301 | 	def add(self, files): | 
 | 302 | 		if not files: | 
 | 303 | 			raise RuntimeError, "'cvs add' needs at least one file" | 
 | 304 | 		list = [] | 
 | 305 | 		for e in self.whichentries(files, 1): | 
| Guido van Rossum | a79f5a3 | 1995-07-18 18:34:34 +0000 | [diff] [blame] | 306 | 			e.add() | 
| Guido van Rossum | a79f5a3 | 1995-07-18 18:34:34 +0000 | [diff] [blame] | 307 |  | 
 | 308 | 	def rm(self, files): | 
 | 309 | 		if not files: | 
 | 310 | 			raise RuntimeError, "'cvs rm' needs at least one file" | 
 | 311 | 		raise RuntimeError, "'cvs rm' not yet imlemented" | 
 | 312 |  | 
| Guido van Rossum | 7bde92b | 1995-10-07 19:47:26 +0000 | [diff] [blame] | 313 | 	def log(self, files, opts): | 
 | 314 | 		flags = '' | 
 | 315 | 		for o, a in opts: | 
 | 316 | 			flags = flags + ' ' + o + a | 
 | 317 | 		for e in self.whichentries(files): | 
 | 318 | 			e.log(flags) | 
 | 319 |  | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 320 | 	def whichentries(self, files, localfilestoo = 0): | 
 | 321 | 		if files: | 
 | 322 | 			list = [] | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 323 | 			for file in files: | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 324 | 				if self.entries.has_key(file): | 
 | 325 | 					e = self.entries[file] | 
 | 326 | 				else: | 
 | 327 | 					e = self.FileClass(file) | 
 | 328 | 					self.entries[file] = e | 
 | 329 | 				list.append(e) | 
 | 330 | 		else: | 
 | 331 | 			list = self.entries.values() | 
 | 332 | 			for file in self.proxy.listfiles(): | 
 | 333 | 				if self.entries.has_key(file): | 
 | 334 | 					continue | 
 | 335 | 				e = self.FileClass(file) | 
 | 336 | 				self.entries[file] = e | 
 | 337 | 				list.append(e) | 
 | 338 | 			if localfilestoo: | 
 | 339 | 				for file in os.listdir(os.curdir): | 
 | 340 | 					if not self.entries.has_key(file) \ | 
 | 341 | 					   and not self.ignored(file): | 
 | 342 | 						e = self.FileClass(file) | 
 | 343 | 						self.entries[file] = e | 
 | 344 | 						list.append(e) | 
 | 345 | 			list.sort() | 
 | 346 | 		if self.proxy: | 
 | 347 | 			for e in list: | 
 | 348 | 				if e.proxy is None: | 
 | 349 | 					e.proxy = self.proxy | 
 | 350 | 		return list | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 351 |  | 
 | 352 |  | 
 | 353 | class rcvs(CommandFrameWork): | 
 | 354 |  | 
| Guido van Rossum | 903afd0 | 1995-06-23 22:33:57 +0000 | [diff] [blame] | 355 | 	GlobalFlags = 'd:h:p:qvL' | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 356 | 	UsageMessage = \ | 
| Guido van Rossum | 2d2a60e | 1995-04-28 19:24:50 +0000 | [diff] [blame] | 357 | "usage: rcvs [-d directory] [-h host] [-p port] [-q] [-v] [subcommand arg ...]" | 
 | 358 | 	PostUsageMessage = \ | 
 | 359 | 		"If no subcommand is given, the status of all files is listed" | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 360 |  | 
 | 361 | 	def __init__(self): | 
 | 362 | 		"""Constructor.""" | 
 | 363 | 		CommandFrameWork.__init__(self) | 
 | 364 | 		self.proxy = None | 
 | 365 | 		self.cvs = RCVS() | 
| Guido van Rossum | 7bde92b | 1995-10-07 19:47:26 +0000 | [diff] [blame] | 366 | 		 | 
 | 367 | 	def close(self): | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 368 | 		if self.proxy: | 
 | 369 | 			self.proxy._close() | 
 | 370 | 		self.proxy = None | 
| Guido van Rossum | 7bde92b | 1995-10-07 19:47:26 +0000 | [diff] [blame] | 371 |  | 
 | 372 | 	def recurse(self): | 
 | 373 | 		self.close() | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 374 | 		names = os.listdir(os.curdir) | 
 | 375 | 		for name in names: | 
 | 376 | 			if name == os.curdir or name == os.pardir: | 
 | 377 | 				continue | 
 | 378 | 			if name == "CVS": | 
 | 379 | 				continue | 
 | 380 | 			if not os.path.isdir(name): | 
 | 381 | 				continue | 
 | 382 | 			if os.path.islink(name): | 
 | 383 | 				continue | 
 | 384 | 			print "--- entering subdirectory", name, "---" | 
 | 385 | 			os.chdir(name) | 
 | 386 | 			try: | 
 | 387 | 				if os.path.isdir("CVS"): | 
 | 388 | 					self.__class__().run() | 
 | 389 | 				else: | 
 | 390 | 					self.recurse() | 
 | 391 | 			finally: | 
 | 392 | 				os.chdir(os.pardir) | 
 | 393 | 				print "--- left subdirectory", name, "---" | 
 | 394 |  | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 395 | 	def options(self, opts): | 
 | 396 | 		self.opts = opts | 
 | 397 |  | 
 | 398 | 	def ready(self): | 
 | 399 | 		import rcsclient | 
 | 400 | 		self.proxy = rcsclient.openrcsclient(self.opts) | 
 | 401 | 		self.cvs.setproxy(self.proxy) | 
 | 402 | 		self.cvs.getentries() | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 403 |  | 
 | 404 | 	def default(self): | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 405 | 		self.cvs.report([]) | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 406 |  | 
| Guido van Rossum | a79f5a3 | 1995-07-18 18:34:34 +0000 | [diff] [blame] | 407 | 	def do_report(self, opts, files): | 
 | 408 | 		self.cvs.report(files) | 
 | 409 |  | 
| Guido van Rossum | c218a7e | 1995-04-27 23:33:43 +0000 | [diff] [blame] | 410 | 	def do_update(self, opts, files): | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 411 | 		"""update [-l] [-R] [file] ...""" | 
 | 412 | 		local = DEF_LOCAL | 
 | 413 | 		for o, a in opts: | 
 | 414 | 			if o == '-l': local = 1 | 
 | 415 | 			if o == '-R': local = 0 | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 416 | 		self.cvs.update(files) | 
| Guido van Rossum | 6bb4a51 | 1995-04-28 15:26:37 +0000 | [diff] [blame] | 417 | 		self.cvs.putentries() | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 418 | 		if not local and not files: | 
 | 419 | 			self.recurse() | 
 | 420 | 	flags_update = '-lR' | 
| Guido van Rossum | 330e884 | 1995-04-28 17:56:32 +0000 | [diff] [blame] | 421 | 	do_up = do_update | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 422 | 	flags_up = flags_update | 
| Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 423 |  | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 424 | 	def do_commit(self, opts, files): | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 425 | 		"""commit [-m message] [file] ...""" | 
 | 426 | 		message = "" | 
 | 427 | 		for o, a in opts: | 
 | 428 | 			if o == '-m': message = a | 
 | 429 | 		self.cvs.commit(files, message) | 
| Guido van Rossum | 6bb4a51 | 1995-04-28 15:26:37 +0000 | [diff] [blame] | 430 | 		self.cvs.putentries() | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 431 | 	flags_commit = 'm:' | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 432 | 	do_com = do_commit | 
 | 433 | 	flags_com = flags_commit | 
| Guido van Rossum | 330e884 | 1995-04-28 17:56:32 +0000 | [diff] [blame] | 434 |  | 
 | 435 | 	def do_diff(self, opts, files): | 
 | 436 | 		"""diff [difflags] [file] ...""" | 
| Guido van Rossum | ec8cfd4 | 1995-05-01 20:06:44 +0000 | [diff] [blame] | 437 | 		self.cvs.diff(files, opts) | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 438 | 	flags_diff = 'cbitwcefhnlr:sD:S:' | 
| Guido van Rossum | 330e884 | 1995-04-28 17:56:32 +0000 | [diff] [blame] | 439 | 	do_dif = do_diff | 
| Guido van Rossum | d1972af | 1995-06-21 01:02:06 +0000 | [diff] [blame] | 440 | 	flags_dif = flags_diff | 
| Guido van Rossum | 330e884 | 1995-04-28 17:56:32 +0000 | [diff] [blame] | 441 |  | 
| Guido van Rossum | a79f5a3 | 1995-07-18 18:34:34 +0000 | [diff] [blame] | 442 | 	def do_add(self, opts, files): | 
 | 443 | 		"""add file ...""" | 
 | 444 | 		if not files: | 
 | 445 | 			print "'rcvs add' requires at least one file" | 
 | 446 | 			return | 
 | 447 | 		self.cvs.add(files) | 
 | 448 | 		self.cvs.putentries() | 
 | 449 |  | 
 | 450 | 	def do_remove(self, opts, files): | 
 | 451 | 		"""remove file ...""" | 
 | 452 | 		if not files: | 
 | 453 | 			print "'rcvs remove' requires at least one file" | 
 | 454 | 			return | 
 | 455 | 		self.cvs.remove(files) | 
 | 456 | 		self.cvs.putentries() | 
 | 457 | 	do_rm = do_remove | 
 | 458 |  | 
| Guido van Rossum | 7bde92b | 1995-10-07 19:47:26 +0000 | [diff] [blame] | 459 | 	def do_log(self, opts, files): | 
 | 460 | 		"""log [rlog-options] [file] ...""" | 
 | 461 | 		self.cvs.log(files, opts) | 
| Guido van Rossum | a176f58 | 1995-10-07 20:47:35 +0000 | [diff] [blame] | 462 | 	flags_log = 'bhLNRtd:s:V:r:' | 
| Guido van Rossum | 330e884 | 1995-04-28 17:56:32 +0000 | [diff] [blame] | 463 |  | 
 | 464 |  | 
 | 465 | def remove(fn): | 
 | 466 | 	try: | 
 | 467 | 		os.unlink(fn) | 
 | 468 | 	except os.error: | 
 | 469 | 		pass | 
| Guido van Rossum | ae21ced | 1995-04-28 14:32:26 +0000 | [diff] [blame] | 470 |  | 
| Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 471 |  | 
| Guido van Rossum | deb627c | 1995-04-27 21:28:53 +0000 | [diff] [blame] | 472 | def main(): | 
| Guido van Rossum | 7bde92b | 1995-10-07 19:47:26 +0000 | [diff] [blame] | 473 | 	r = rcvs() | 
 | 474 | 	try: | 
 | 475 | 		r.run() | 
 | 476 | 	finally: | 
 | 477 | 		r.close() | 
| Guido van Rossum | 097c55a | 1995-04-27 18:07:07 +0000 | [diff] [blame] | 478 |  | 
| Guido van Rossum | 5f07b84 | 1995-04-26 22:57:11 +0000 | [diff] [blame] | 479 |  | 
 | 480 | if __name__ == "__main__": | 
| Guido van Rossum | deb627c | 1995-04-27 21:28:53 +0000 | [diff] [blame] | 481 | 	main() |