summaryrefslogtreecommitdiffstats
path: root/Demo/pdist/rcvs.py
diff options
context:
space:
mode:
Diffstat (limited to 'Demo/pdist/rcvs.py')
-rwxr-xr-xDemo/pdist/rcvs.py476
1 files changed, 0 insertions, 476 deletions
diff --git a/Demo/pdist/rcvs.py b/Demo/pdist/rcvs.py
deleted file mode 100755
index ff178b7..0000000
--- a/Demo/pdist/rcvs.py
+++ /dev/null
@@ -1,476 +0,0 @@
-#! /usr/bin/env python3
-
-"""Remote CVS -- command line interface"""
-
-# XXX To do:
-#
-# Bugs:
-# - if the remote file is deleted, "rcvs update" will fail
-#
-# Functionality:
-# - cvs rm
-# - descend into directories (alraedy done for update)
-# - conflict resolution
-# - other relevant commands?
-# - branches
-#
-# - Finesses:
-# - retain file mode's x bits
-# - complain when "nothing known about filename"
-# - edit log message the way CVS lets you edit it
-# - cvs diff -rREVA -rREVB
-# - send mail the way CVS sends it
-#
-# Performance:
-# - cache remote checksums (for every revision ever seen!)
-# - translate symbolic revisions to numeric revisions
-#
-# Reliability:
-# - remote locking
-#
-# Security:
-# - Authenticated RPC?
-
-
-from cvslib import CVS, File
-import md5
-import os
-import sys
-from cmdfw import CommandFrameWork
-
-
-DEF_LOCAL = 1 # Default -l
-
-
-class MyFile(File):
-
- def action(self):
- """Return a code indicating the update status of this file.
-
- The possible return values are:
-
- '=' -- everything's fine
- '0' -- file doesn't exist anywhere
- '?' -- exists locally only
- 'A' -- new locally
- 'R' -- deleted locally
- 'U' -- changed remotely, no changes locally
- (includes new remotely or deleted remotely)
- '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)
- 'D' -- deleted remotely
- 'N' -- new remotely
- 'r' -- get rid of entry
- 'c' -- create entry
- 'u' -- update entry
-
- (and probably others :-)
- """
- if not self.lseen:
- self.getlocal()
- if not self.rseen:
- self.getremote()
- if not self.eseen:
- if not self.lsum:
- if not self.rsum: return '0' # Never heard of
- else:
- return 'N' # New remotely
- else: # self.lsum
- if not self.rsum: 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.lsum:
- if self.edeleted:
- if self.rsum: return 'R' # Removed
- else: return 'r' # Get rid of entry
- else: # not self.edeleted
- if self.rsum:
- print("warning:", end=' ')
- print(self.file, end=' ')
- print("was lost")
- return 'U'
- else: return 'r' # Get rid of entry
- else: # self.lsum
- if not self.rsum:
- if self.enew: return 'A' # New locally
- else: return 'D' # Deleted remotely
- else: # self.rsum
- 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'
-
- def update(self):
- code = self.action()
- if code == '=': return
- print(code, self.file)
- if code in ('U', 'N'):
- self.get()
- elif code == 'C':
- print("%s: conflict resolution not yet implemented" % \
- self.file)
- elif code == 'D':
- remove(self.file)
- self.eseen = 0
- elif code == 'r':
- self.eseen = 0
- elif code in ('c', 'u'):
- self.eseen = 1
- self.erev = self.rrev
- self.enew = 0
- self.edeleted = 0
- self.esum = self.rsum
- self.emtime, self.ectime = os.stat(self.file)[-2:]
- self.extra = ''
-
- def commit(self, message = ""):
- code = self.action()
- if code in ('A', 'M'):
- self.put(message)
- return 1
- elif code == 'R':
- print("%s: committing removes not yet implemented" % \
- self.file)
- elif code == 'C':
- print("%s: conflict resolution not yet implemented" % \
- self.file)
-
- def diff(self, opts = []):
- self.action() # To update lseen, rseen
- flags = ''
- rev = self.rrev
- # XXX should support two rev options too!
- for o, a in opts:
- if o == '-r':
- rev = a
- else:
- flags = flags + ' ' + o + a
- if rev == self.rrev and self.lsum == self.rsum:
- return
- flags = flags[1:]
- fn = self.file
- data = self.proxy.get((fn, rev))
- sum = md5.new(data).digest()
- if self.lsum == sum:
- return
- import tempfile
- tf = tempfile.NamedTemporaryFile()
- tf.write(data)
- tf.flush()
- print('diff %s -r%s %s' % (flags, rev, fn))
- sts = os.system('diff %s %s %s' % (flags, tf.name, fn))
- if sts:
- print('='*70)
-
- def commitcheck(self):
- return self.action() != 'C'
-
- def put(self, message = ""):
- print("Checking in", self.file, "...")
- data = open(self.file).read()
- if not self.enew:
- self.proxy.lock(self.file)
- messages = self.proxy.put(self.file, data, message)
- if messages:
- print(messages)
- self.setentry(self.proxy.head(self.file), self.lsum)
-
- def get(self):
- data = self.proxy.get(self.file)
- f = open(self.file, 'w')
- f.write(data)
- f.close()
- self.setentry(self.rrev, self.rsum)
-
- def log(self, otherflags):
- print(self.proxy.log(self.file, otherflags))
-
- def add(self):
- self.eseen = 0 # While we're hacking...
- self.esum = self.lsum
- self.emtime, self.ectime = 0, 0
- self.erev = ''
- self.enew = 1
- self.edeleted = 0
- self.eseen = 1 # Done
- self.extra = ''
-
- def setentry(self, erev, esum):
- self.eseen = 0 # While we're hacking...
- self.esum = esum
- self.emtime, self.ectime = os.stat(self.file)[-2:]
- self.erev = erev
- self.enew = 0
- self.edeleted = 0
- self.eseen = 1 # Done
- self.extra = ''
-
-
-SENDMAIL = "/usr/lib/sendmail -t"
-MAILFORM = """To: %s
-Subject: CVS changes: %s
-
-...Message from rcvs...
-
-Committed files:
- %s
-
-Log message:
- %s
-"""
-
-
-class RCVS(CVS):
-
- FileClass = MyFile
-
- def __init__(self):
- CVS.__init__(self)
-
- def update(self, files):
- for e in self.whichentries(files, 1):
- e.update()
-
- def commit(self, files, message = ""):
- list = self.whichentries(files)
- if not list: return
- 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 = input("One-liner: ")
- committed = []
- for e in list:
- if e.commit(message):
- committed.append(e.file)
- self.mailinfo(committed, message)
-
- def mailinfo(self, files, message = ""):
- towhom = "sjoerd@cwi.nl, jack@cwi.nl" # XXX
- mailtext = MAILFORM % (towhom, ' '.join(files),
- ' '.join(files), message)
- print('-'*70)
- print(mailtext)
- print('-'*70)
- ok = input("OK to mail to %s? " % towhom)
- if ok.lower().strip() in ('y', 'ye', 'yes'):
- p = os.popen(SENDMAIL, "w")
- p.write(mailtext)
- sts = p.close()
- if sts:
- print("Sendmail exit status %s" % str(sts))
- else:
- print("Mail sent.")
- else:
- print("No mail sent.")
-
- 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 add(self, files):
- if not files:
- raise RuntimeError("'cvs add' needs at least one file")
- list = []
- for e in self.whichentries(files, 1):
- e.add()
-
- def rm(self, files):
- if not files:
- raise RuntimeError("'cvs rm' needs at least one file")
- raise RuntimeError("'cvs rm' not yet imlemented")
-
- def log(self, files, opts):
- flags = ''
- for o, a in opts:
- flags = flags + ' ' + o + a
- for e in self.whichentries(files):
- e.log(flags)
-
- def whichentries(self, files, localfilestoo = 0):
- if files:
- list = []
- for file in files:
- if file in self.entries:
- e = self.entries[file]
- else:
- e = self.FileClass(file)
- self.entries[file] = e
- list.append(e)
- else:
- list = list(self.entries.values())
- for file in self.proxy.listfiles():
- if file in self.entries:
- continue
- e = self.FileClass(file)
- self.entries[file] = e
- list.append(e)
- if localfilestoo:
- for file in os.listdir(os.curdir):
- if file not in self.entries \
- 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
-
-
-class rcvs(CommandFrameWork):
-
- GlobalFlags = 'd:h:p:qvL'
- UsageMessage = \
-"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"
-
- def __init__(self):
- """Constructor."""
- CommandFrameWork.__init__(self)
- self.proxy = None
- self.cvs = RCVS()
-
- def close(self):
- if self.proxy:
- self.proxy._close()
- self.proxy = None
-
- def recurse(self):
- self.close()
- names = os.listdir(os.curdir)
- for name in names:
- if name == os.curdir or name == os.pardir:
- continue
- if name == "CVS":
- continue
- if not os.path.isdir(name):
- continue
- if os.path.islink(name):
- continue
- print("--- entering subdirectory", name, "---")
- os.chdir(name)
- try:
- if os.path.isdir("CVS"):
- self.__class__().run()
- else:
- self.recurse()
- finally:
- os.chdir(os.pardir)
- print("--- left subdirectory", name, "---")
-
- 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):
- self.cvs.report([])
-
- def do_report(self, opts, files):
- self.cvs.report(files)
-
- def do_update(self, opts, files):
- """update [-l] [-R] [file] ..."""
- local = DEF_LOCAL
- for o, a in opts:
- if o == '-l': local = 1
- if o == '-R': local = 0
- self.cvs.update(files)
- self.cvs.putentries()
- if not local and not files:
- self.recurse()
- flags_update = '-lR'
- do_up = do_update
- flags_up = flags_update
-
- def do_commit(self, opts, files):
- """commit [-m message] [file] ..."""
- message = ""
- for o, a in opts:
- if o == '-m': message = a
- self.cvs.commit(files, message)
- self.cvs.putentries()
- flags_commit = 'm:'
- do_com = do_commit
- flags_com = flags_commit
-
- def do_diff(self, opts, files):
- """diff [difflags] [file] ..."""
- self.cvs.diff(files, opts)
- flags_diff = 'cbitwcefhnlr:sD:S:'
- do_dif = do_diff
- flags_dif = flags_diff
-
- def do_add(self, opts, files):
- """add file ..."""
- if not files:
- print("'rcvs add' requires at least one file")
- return
- self.cvs.add(files)
- self.cvs.putentries()
-
- def do_remove(self, opts, files):
- """remove file ..."""
- if not files:
- print("'rcvs remove' requires at least one file")
- return
- self.cvs.remove(files)
- self.cvs.putentries()
- do_rm = do_remove
-
- def do_log(self, opts, files):
- """log [rlog-options] [file] ..."""
- self.cvs.log(files, opts)
- flags_log = 'bhLNRtd:s:V:r:'
-
-
-def remove(fn):
- try:
- os.unlink(fn)
- except os.error:
- pass
-
-
-def main():
- r = rcvs()
- try:
- r.run()
- finally:
- r.close()
-
-
-if __name__ == "__main__":
- main()