| 
									
										
										
										
											1995-04-27 18:07:07 +00:00
										 |  |  | #! /usr/local/bin/python | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-27 23:33:43 +00:00
										 |  |  | """Remote CVS -- command line interface""" | 
					
						
							| 
									
										
										
										
											1995-04-27 18:07:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-27 23:33:43 +00:00
										 |  |  | from cvslib import CVS, File | 
					
						
							| 
									
										
										
										
											1995-04-26 22:57:11 +00:00
										 |  |  | import md5 | 
					
						
							|  |  |  | import os | 
					
						
							|  |  |  | import string | 
					
						
							|  |  |  | import sys | 
					
						
							| 
									
										
										
										
											1995-04-27 23:33:43 +00:00
										 |  |  | from cmdfw import CommandFrameWork | 
					
						
							| 
									
										
										
										
											1995-04-26 22:57:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-27 23:33:43 +00:00
										 |  |  | class MyFile(File): | 
					
						
							| 
									
										
										
										
											1995-04-26 22:57:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 	def action(self): | 
					
						
							|  |  |  | 		"""Return a code indicating the update status of this file.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		The possible return values are: | 
					
						
							| 
									
										
										
										
											1995-04-27 23:33:43 +00:00
										 |  |  | 		 | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 		'=' -- everything's fine | 
					
						
							|  |  |  | 		'0' -- file doesn't exist anywhere | 
					
						
							|  |  |  | 		'?' -- exists locally only | 
					
						
							|  |  |  | 		'A' -- new locally | 
					
						
							|  |  |  | 		'R' -- deleted locally | 
					
						
							|  |  |  | 		'U' -- changed remotely, no changes locally | 
					
						
							| 
									
										
										
										
											1995-04-28 15:26:37 +00:00
										 |  |  | 		       (includes new remotely or deleted remotely) | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 		'M' -- changed locally, no changes remotely | 
					
						
							|  |  |  | 		'C' -- conflict: changed locally as well as remotely | 
					
						
							|  |  |  | 		       (includes cases where the file has been added | 
					
						
							|  |  |  | 		       or removed locally and remotely) | 
					
						
							| 
									
										
										
										
											1995-04-28 15:33:03 +00:00
										 |  |  | 		'D' -- deleted remotely | 
					
						
							|  |  |  | 		'N' -- new remotely | 
					
						
							| 
									
										
										
										
											1995-04-28 15:26:37 +00:00
										 |  |  | 		'r' -- get rid of entry | 
					
						
							|  |  |  | 		'c' -- create entry | 
					
						
							|  |  |  | 		'u' -- update entry | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 		"""
 | 
					
						
							| 
									
										
										
										
											1995-05-01 20:06:44 +00:00
										 |  |  | 		if not self.lseen: | 
					
						
							|  |  |  | 			self.getlocal() | 
					
						
							|  |  |  | 		if not self.rseen: | 
					
						
							|  |  |  | 			self.getremote() | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 		if not self.eseen: | 
					
						
							| 
									
										
										
										
											1995-04-28 15:26:37 +00:00
										 |  |  | 			if not self.lseen: | 
					
						
							|  |  |  | 				if not self.rseen: return '0' # Never heard of | 
					
						
							|  |  |  | 				else: | 
					
						
							|  |  |  | 					return 'N' # New remotely | 
					
						
							|  |  |  | 			else: # self.lseen | 
					
						
							|  |  |  | 				if not self.rseen: return '?' # Local only | 
					
						
							|  |  |  | 				# Local and remote, but no entry | 
					
						
							|  |  |  | 				if self.lsum == self.rsum: | 
					
						
							|  |  |  | 					return 'c' # Restore entry only | 
					
						
							|  |  |  | 				else: return 'C' # Real conflict | 
					
						
							|  |  |  | 		else: # self.eseen | 
					
						
							|  |  |  | 			if not self.lseen: | 
					
						
							|  |  |  | 				if self.eremoved: | 
					
						
							|  |  |  | 					if self.rseen: return 'R' # Removed | 
					
						
							|  |  |  | 					else: return 'r' # Get rid of entry | 
					
						
							|  |  |  | 				else: # not self.eremoved | 
					
						
							|  |  |  | 					if self.rseen: | 
					
						
							|  |  |  | 						print "warning:", | 
					
						
							|  |  |  | 						print self.file, | 
					
						
							|  |  |  | 						print "was lost" | 
					
						
							|  |  |  | 						return 'U' | 
					
						
							|  |  |  | 					else: return 'r' # Get rid of entry | 
					
						
							|  |  |  | 			else: # self.lseen | 
					
						
							|  |  |  | 				if not self.rseen: | 
					
						
							|  |  |  | 					if self.enew: return 'A' # New locally | 
					
						
							|  |  |  | 					else: return 'D' # Deleted remotely | 
					
						
							|  |  |  | 				else: # self.rseen | 
					
						
							|  |  |  | 					if self.enew: | 
					
						
							|  |  |  | 						if self.lsum == self.rsum: | 
					
						
							|  |  |  | 							return 'u' | 
					
						
							|  |  |  | 						else: | 
					
						
							|  |  |  | 							return 'C' | 
					
						
							|  |  |  | 					if self.lsum == self.esum: | 
					
						
							|  |  |  | 						if self.esum == self.rsum: | 
					
						
							|  |  |  | 							return '=' | 
					
						
							|  |  |  | 						else: | 
					
						
							|  |  |  | 							return 'U' | 
					
						
							|  |  |  | 					elif self.esum == self.rsum: | 
					
						
							|  |  |  | 						return 'M' | 
					
						
							|  |  |  | 					elif self.lsum == self.rsum: | 
					
						
							|  |  |  | 						return 'u' | 
					
						
							|  |  |  | 					else: | 
					
						
							|  |  |  | 						return 'C' | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def update(self): | 
					
						
							|  |  |  | 		code = self.action() | 
					
						
							| 
									
										
										
										
											1995-04-28 21:48:16 +00:00
										 |  |  | 		if code == '=': return | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 		print code, self.file | 
					
						
							| 
									
										
										
										
											1995-04-28 15:33:03 +00:00
										 |  |  | 		if code in ('U', 'N'): | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 			self.get() | 
					
						
							|  |  |  | 		elif code == 'C': | 
					
						
							|  |  |  | 			print "%s: conflict resolution not yet implemented" % \ | 
					
						
							|  |  |  | 			      self.file | 
					
						
							| 
									
										
										
										
											1995-04-28 15:33:03 +00:00
										 |  |  | 		elif code == 'D': | 
					
						
							| 
									
										
										
										
											1995-04-28 17:56:32 +00:00
										 |  |  | 			remove(self.file) | 
					
						
							| 
									
										
										
										
											1995-04-28 15:33:03 +00:00
										 |  |  | 			self.eseen = 0 | 
					
						
							|  |  |  | 		elif code == 'r': | 
					
						
							|  |  |  | 			self.eseen = 0 | 
					
						
							|  |  |  | 		elif code in ('c', 'u'): | 
					
						
							| 
									
										
										
										
											1995-04-28 15:37:22 +00:00
										 |  |  | 			self.eseen = 1 | 
					
						
							| 
									
										
										
										
											1995-04-28 15:33:03 +00:00
										 |  |  | 			self.erev = self.rrev | 
					
						
							|  |  |  | 			self.enew = 0 | 
					
						
							|  |  |  | 			self.edeleted = 0 | 
					
						
							|  |  |  | 			self.esum = self.rsum | 
					
						
							|  |  |  | 			self.emtime, self.ectime = os.stat(self.file)[-2:] | 
					
						
							| 
									
										
										
										
											1995-04-28 15:37:22 +00:00
										 |  |  | 			self.extra = '' | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def commit(self, message = ""): | 
					
						
							|  |  |  | 		code = self.action() | 
					
						
							|  |  |  | 		if code in ('A', 'M'): | 
					
						
							|  |  |  | 			self.put(message) | 
					
						
							|  |  |  | 		elif code == 'R': | 
					
						
							|  |  |  | 			print "%s: committing removes not yet implemented" % \ | 
					
						
							|  |  |  | 			      self.file | 
					
						
							|  |  |  | 		elif code == 'C': | 
					
						
							|  |  |  | 			print "%s: conflict resolution not yet implemented" % \ | 
					
						
							|  |  |  | 			      self.file | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-28 17:56:32 +00:00
										 |  |  | 	def diff(self, opts = []): | 
					
						
							| 
									
										
										
										
											1995-05-01 20:06:44 +00:00
										 |  |  | 		self.action()		# To update lseen, rseen | 
					
						
							| 
									
										
										
										
											1995-04-28 19:24:50 +00:00
										 |  |  | 		if self.lsum == self.rsum: | 
					
						
							|  |  |  | 			return | 
					
						
							| 
									
										
										
										
											1995-04-28 17:56:32 +00:00
										 |  |  | 		import tempfile | 
					
						
							|  |  |  | 		flags = '' | 
					
						
							|  |  |  | 		for o, a in opts: | 
					
						
							|  |  |  | 			flags = flags + ' ' + o + a | 
					
						
							|  |  |  | 		flags = flags[1:] | 
					
						
							|  |  |  | 		fn = self.file | 
					
						
							|  |  |  | 		data = self.proxy.get(fn) | 
					
						
							|  |  |  | 		tfn = tempfile.mktemp() | 
					
						
							|  |  |  | 		try: | 
					
						
							|  |  |  | 			tf = open(tfn, 'w') | 
					
						
							|  |  |  | 			tf.write(data) | 
					
						
							|  |  |  | 			tf.close() | 
					
						
							|  |  |  | 			print 'diff %s -r%s %s' % (flags, self.rrev, fn) | 
					
						
							|  |  |  | 			sts = os.system('diff %s %s %s' % (flags, tfn, fn)) | 
					
						
							|  |  |  | 			if sts: | 
					
						
							|  |  |  | 				print '='*70 | 
					
						
							|  |  |  | 		finally: | 
					
						
							|  |  |  | 			remove(tfn) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 	def commitcheck(self): | 
					
						
							|  |  |  | 		return self.action() != 'C' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def put(self, message = ""): | 
					
						
							| 
									
										
										
										
											1995-04-28 15:41:51 +00:00
										 |  |  | 		print "Checking in", self.file, "..." | 
					
						
							|  |  |  | 		data = open(self.file).read() | 
					
						
							|  |  |  | 		messages = self.proxy.put(self.file, data, message) | 
					
						
							|  |  |  | 		if messages: | 
					
						
							|  |  |  | 			print messages | 
					
						
							| 
									
										
										
										
											1995-04-28 21:48:16 +00:00
										 |  |  | 		self.setentry(self.proxy.head(self.file), self.lsum) | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 	 | 
					
						
							|  |  |  | 	def get(self): | 
					
						
							|  |  |  | 		data = self.proxy.get(self.file) | 
					
						
							|  |  |  | 		f = open(self.file, 'w') | 
					
						
							|  |  |  | 		f.write(data) | 
					
						
							|  |  |  | 		f.close() | 
					
						
							| 
									
										
										
										
											1995-04-28 21:48:16 +00:00
										 |  |  | 		self.setentry(self.rrev, self.rsum) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def setentry(self, erev, esum): | 
					
						
							|  |  |  | 		self.eseen = 0		# While we're hacking... | 
					
						
							|  |  |  | 		self.esum = esum | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 		self.emtime, self.ectime = os.stat(self.file)[-2:] | 
					
						
							| 
									
										
										
										
											1995-04-28 21:48:16 +00:00
										 |  |  | 		self.erev = erev | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 		self.enew = 0 | 
					
						
							|  |  |  | 		self.edeleted = 0 | 
					
						
							| 
									
										
										
										
											1995-04-28 21:48:16 +00:00
										 |  |  | 		self.eseen = 1		# Done | 
					
						
							| 
									
										
										
										
											1995-04-26 22:57:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-27 18:07:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-27 23:33:43 +00:00
										 |  |  | class RCVS(CVS): | 
					
						
							| 
									
										
										
										
											1995-04-27 18:07:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-27 23:33:43 +00:00
										 |  |  | 	FileClass = MyFile | 
					
						
							| 
									
										
										
										
											1995-04-27 18:07:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-27 23:33:43 +00:00
										 |  |  | 	def __init__(self): | 
					
						
							|  |  |  | 		CVS.__init__(self) | 
					
						
							| 
									
										
										
										
											1995-04-27 18:07:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-05-01 20:06:44 +00:00
										 |  |  | 	def update(self, files): | 
					
						
							|  |  |  | 		for e in self.whichentries(files, 1): | 
					
						
							|  |  |  | 			e.update() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def commit(self, files, message = ""): | 
					
						
							|  |  |  | 		list = self.whichentries(files) | 
					
						
							|  |  |  | 		ok = 1 | 
					
						
							|  |  |  | 		for e in list: | 
					
						
							|  |  |  | 			if not e.commitcheck(): | 
					
						
							|  |  |  | 				ok = 0 | 
					
						
							|  |  |  | 		if not ok: | 
					
						
							|  |  |  | 			print "correct above errors first" | 
					
						
							|  |  |  | 			return | 
					
						
							|  |  |  | 		if not message: | 
					
						
							|  |  |  | 			message = raw_input("One-liner: ") | 
					
						
							|  |  |  | 		for e in list: | 
					
						
							|  |  |  | 			e.commit(message) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def report(self, files): | 
					
						
							|  |  |  | 		for e in self.whichentries(files): | 
					
						
							|  |  |  | 			e.report() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def diff(self, files, opts): | 
					
						
							|  |  |  | 		for e in self.whichentries(files): | 
					
						
							|  |  |  | 			e.diff(opts) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def whichentries(self, files, localfilestoo = 0): | 
					
						
							|  |  |  | 		if files: | 
					
						
							|  |  |  | 			list = [] | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 			for file in files: | 
					
						
							| 
									
										
										
										
											1995-05-01 20:06:44 +00:00
										 |  |  | 				if self.entries.has_key(file): | 
					
						
							|  |  |  | 					e = self.entries[file] | 
					
						
							|  |  |  | 				else: | 
					
						
							|  |  |  | 					e = self.FileClass(file) | 
					
						
							|  |  |  | 					self.entries[file] = e | 
					
						
							|  |  |  | 				list.append(e) | 
					
						
							|  |  |  | 		else: | 
					
						
							|  |  |  | 			list = self.entries.values() | 
					
						
							|  |  |  | 			for file in self.proxy.listfiles(): | 
					
						
							|  |  |  | 				if self.entries.has_key(file): | 
					
						
							|  |  |  | 					continue | 
					
						
							|  |  |  | 				e = self.FileClass(file) | 
					
						
							|  |  |  | 				self.entries[file] = e | 
					
						
							|  |  |  | 				list.append(e) | 
					
						
							|  |  |  | 			if localfilestoo: | 
					
						
							|  |  |  | 				for file in os.listdir(os.curdir): | 
					
						
							|  |  |  | 					if not self.entries.has_key(file) \ | 
					
						
							|  |  |  | 					   and not self.ignored(file): | 
					
						
							|  |  |  | 						e = self.FileClass(file) | 
					
						
							|  |  |  | 						self.entries[file] = e | 
					
						
							|  |  |  | 						list.append(e) | 
					
						
							|  |  |  | 			list.sort() | 
					
						
							|  |  |  | 		if self.proxy: | 
					
						
							|  |  |  | 			for e in list: | 
					
						
							|  |  |  | 				if e.proxy is None: | 
					
						
							|  |  |  | 					e.proxy = self.proxy | 
					
						
							|  |  |  | 		return list | 
					
						
							| 
									
										
										
										
											1995-04-27 23:33:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | class rcvs(CommandFrameWork): | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	GlobalFlags = 'd:h:p:qv' | 
					
						
							|  |  |  | 	UsageMessage = \ | 
					
						
							| 
									
										
										
										
											1995-04-28 19:24:50 +00:00
										 |  |  | "usage: rcvs [-d directory] [-h host] [-p port] [-q] [-v] [subcommand arg ...]" | 
					
						
							|  |  |  | 	PostUsageMessage = \ | 
					
						
							|  |  |  | 		"If no subcommand is given, the status of all files is listed" | 
					
						
							| 
									
										
										
										
											1995-04-27 23:33:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def __init__(self): | 
					
						
							|  |  |  | 		"""Constructor.""" | 
					
						
							|  |  |  | 		CommandFrameWork.__init__(self) | 
					
						
							|  |  |  | 		self.proxy = None | 
					
						
							|  |  |  | 		self.cvs = RCVS() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def options(self, opts): | 
					
						
							|  |  |  | 		self.opts = opts | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def ready(self): | 
					
						
							|  |  |  | 		import rcsclient | 
					
						
							|  |  |  | 		self.proxy = rcsclient.openrcsclient(self.opts) | 
					
						
							|  |  |  | 		self.cvs.setproxy(self.proxy) | 
					
						
							|  |  |  | 		self.cvs.getentries() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	def default(self): | 
					
						
							| 
									
										
										
										
											1995-05-01 20:06:44 +00:00
										 |  |  | 		self.cvs.report([]) | 
					
						
							| 
									
										
										
										
											1995-04-27 23:33:43 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def do_update(self, opts, files): | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 		"""update [file] ...""" | 
					
						
							| 
									
										
										
										
											1995-05-01 20:06:44 +00:00
										 |  |  | 		self.cvs.update(files) | 
					
						
							| 
									
										
										
										
											1995-04-28 15:26:37 +00:00
										 |  |  | 		self.cvs.putentries() | 
					
						
							| 
									
										
										
										
											1995-04-28 17:56:32 +00:00
										 |  |  | 	do_up = do_update | 
					
						
							| 
									
										
										
										
											1995-04-26 22:57:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 	def do_commit(self, opts, files): | 
					
						
							| 
									
										
										
										
											1995-05-01 20:06:44 +00:00
										 |  |  | 		"""commit [-m message] [file] ...""" | 
					
						
							|  |  |  | 		message = "" | 
					
						
							|  |  |  | 		for o, a in opts: | 
					
						
							|  |  |  | 			if o == '-m': message = a | 
					
						
							|  |  |  | 		self.cvs.commit(files, message) | 
					
						
							| 
									
										
										
										
											1995-04-28 15:26:37 +00:00
										 |  |  | 		self.cvs.putentries() | 
					
						
							| 
									
										
										
										
											1995-04-28 17:56:32 +00:00
										 |  |  | 	do_com = do_commit | 
					
						
							| 
									
										
										
										
											1995-05-01 20:06:44 +00:00
										 |  |  | 	flags_commit = 'm:' | 
					
						
							| 
									
										
										
										
											1995-04-28 17:56:32 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	def do_diff(self, opts, files): | 
					
						
							|  |  |  | 		"""diff [difflags] [file] ...""" | 
					
						
							| 
									
										
										
										
											1995-05-01 20:06:44 +00:00
										 |  |  | 		self.cvs.diff(files, opts) | 
					
						
							| 
									
										
										
										
											1995-04-28 17:56:32 +00:00
										 |  |  | 	do_dif = do_diff | 
					
						
							|  |  |  | 	flags_diff = 'cbitwcefhnlrsD:S:' | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | def remove(fn): | 
					
						
							|  |  |  | 	try: | 
					
						
							|  |  |  | 		os.unlink(fn) | 
					
						
							|  |  |  | 	except os.error: | 
					
						
							|  |  |  | 		pass | 
					
						
							| 
									
										
										
										
											1995-04-28 14:32:26 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-26 22:57:11 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-27 21:28:53 +00:00
										 |  |  | def main(): | 
					
						
							| 
									
										
										
										
											1995-04-27 23:33:43 +00:00
										 |  |  | 	rcvs().run() | 
					
						
							| 
									
										
										
										
											1995-04-27 18:07:07 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											1995-04-26 22:57:11 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | if __name__ == "__main__": | 
					
						
							| 
									
										
										
										
											1995-04-27 21:28:53 +00:00
										 |  |  | 	main() |