1f06ee5fa072931fc807527535c91a46c149a6746Guido van Rossum#! /usr/bin/env python 25f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 34d4ee8bdb0023df9dba6f005a1e58efbf0962df0Guido van Rossum"Remote RCS -- command line interface" 44d4ee8bdb0023df9dba6f005a1e58efbf0962df0Guido van Rossum 55f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumimport sys 65f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumimport os 75f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumimport getopt 85f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumimport string 95f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumimport md5 105f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumimport tempfile 114d4ee8bdb0023df9dba6f005a1e58efbf0962df0Guido van Rossumfrom rcsclient import openrcsclient 125f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 135f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumdef main(): 14e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters sys.stdout = sys.stderr 15e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters try: 16e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters opts, rest = getopt.getopt(sys.argv[1:], 'h:p:d:qvL') 17e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters if not rest: 18e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters cmd = 'head' 19e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters else: 20e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters cmd, rest = rest[0], rest[1:] 21e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters if not commands.has_key(cmd): 22e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters raise getopt.error, "unknown command" 23e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters coptset, func = commands[cmd] 24e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters copts, files = getopt.getopt(rest, coptset) 25e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters except getopt.error, msg: 26e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print msg 27e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print "usage: rrcs [options] command [options] [file] ..." 28e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print "where command can be:" 29e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print " ci|put # checkin the given files" 30e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print " co|get # checkout" 31e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print " info # print header info" 32e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print " head # print revision of head branch" 33e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print " list # list filename if valid" 34e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print " log # print full log" 35e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print " diff # diff rcs file and work file" 36e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print "if no files are given, all remote rcs files are assumed" 37e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters sys.exit(2) 38e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters x = openrcsclient(opts) 39e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters if not files: 40e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters files = x.listfiles() 41e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters for fn in files: 42e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters try: 43e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters func(x, copts, fn) 44e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters except (IOError, os.error), msg: 45e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print "%s: %s" % (fn, msg) 465f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 475f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumdef checkin(x, copts, fn): 48e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters f = open(fn) 49e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters data = f.read() 50e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters f.close() 51e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters new = not x.isvalid(fn) 52e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters if not new and same(x, copts, fn, data): 53e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print "%s: unchanged since last checkin" % fn 54e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters return 55e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print "Checking in", fn, "..." 56e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters message = asklogmessage(new) 57e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters messages = x.put(fn, data, message) 58e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters if messages: 59e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print messages 605f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 615f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumdef checkout(x, copts, fn): 62e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters data = x.get(fn) 63e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters f = open(fn, 'w') 64e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters f.write(data) 65e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters f.close() 665f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 67ff99a72f53ca1007403e1bf3fcc2c6800370119bGuido van Rossumdef lock(x, copts, fn): 68e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters x.lock(fn) 69ff99a72f53ca1007403e1bf3fcc2c6800370119bGuido van Rossum 70ff99a72f53ca1007403e1bf3fcc2c6800370119bGuido van Rossumdef unlock(x, copts, fn): 71e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters x.unlock(fn) 72ff99a72f53ca1007403e1bf3fcc2c6800370119bGuido van Rossum 735f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumdef info(x, copts, fn): 74e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters dict = x.info(fn) 75e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters keys = dict.keys() 76e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters keys.sort() 77e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters for key in keys: 78e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print key + ':', dict[key] 79e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print '='*70 805f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 815f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumdef head(x, copts, fn): 82e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters head = x.head(fn) 83e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print fn, head 845f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 855f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumdef list(x, copts, fn): 86e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters if x.isvalid(fn): 87e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print fn 885f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 895f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumdef log(x, copts, fn): 90e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters flags = '' 91e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters for o, a in copts: 92e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters flags = flags + ' ' + o + a 93e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters flags = flags[1:] 94e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters messages = x.log(fn, flags) 95e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print messages 965f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 975f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumdef diff(x, copts, fn): 98e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters if same(x, copts, fn): 99e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters return 100e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters flags = '' 101e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters for o, a in copts: 102e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters flags = flags + ' ' + o + a 103e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters flags = flags[1:] 104e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters data = x.get(fn) 105e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters tf = tempfile.NamedTemporaryFile() 106e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters tf.write(data) 107e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters tf.flush() 108e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print 'diff %s -r%s %s' % (flags, x.head(fn), fn) 109e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters sts = os.system('diff %s %s %s' % (flags, tf.name, fn)) 110e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters if sts: 111e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print '='*70 1125f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 1135f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumdef same(x, copts, fn, data = None): 114e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters if data is None: 115e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters f = open(fn) 116e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters data = f.read() 117e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters f.close() 118e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters lsum = md5.new(data).digest() 119e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters rsum = x.sum(fn) 120e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters return lsum == rsum 1215f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 1225f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumdef asklogmessage(new): 123e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters if new: 124e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print "enter description,", 125e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters else: 126e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print "enter log message,", 127e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print "terminate with single '.' or end of file:" 128e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters if new: 129e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters print "NOTE: This is NOT the log message!" 130e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters message = "" 131e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters while 1: 132e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters sys.stderr.write(">> ") 133e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters sys.stderr.flush() 134e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters line = sys.stdin.readline() 135e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters if not line or line == '.\n': break 136e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters message = message + line 137e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters return message 1385f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 1395f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumdef remove(fn): 140e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters try: 141e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters os.unlink(fn) 142e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters except os.error: 143e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters pass 1445f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 1455f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossumcommands = { 146e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters 'ci': ('', checkin), 147e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters 'put': ('', checkin), 148e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters 'co': ('', checkout), 149e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters 'get': ('', checkout), 150e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters 'info': ('', info), 151e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters 'head': ('', head), 152e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters 'list': ('', list), 153e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters 'lock': ('', lock), 154e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters 'unlock': ('', unlock), 155e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters 'log': ('bhLRtd:l:r:s:w:V:', log), 156e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters 'diff': ('c', diff), 157e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters } 1585f07b84796c207a0068f6ac5a0d6981d14801ff6Guido van Rossum 159547e8d8c0f480b2647eeb2453f1fb9c77db42d0eGuido van Rossumif __name__ == '__main__': 160e6ddc8b20b493fef2e7cffb2e1351fe1d238857eTim Peters main() 161