#!/usr/bin/env python """This is for cleaning up binary files improperly added to CVS. This script scans the given path to find binary files; checks with CVS to see if the sticky options are set to -kb; finally if sticky options are not -kb then uses 'cvs admin' to set the -kb option. This script ignores CVS directories, symbolic links, and files not known under CVS control (cvs status is 'Unknown'). Run this on a CHECKED OUT module sandbox, not on the repository itself. After if fixes the sticky options on any files you should manually do a 'cvs commit' to accept the changes. Then be sure to have all users do a 'cvs up -A' to update the Sticky Option status. Noah Spurrier 20030426 """ import os, sys, time import pexpect VERBOSE = 1 def is_binary (filename): """Assume that any file with a character where the 8th bit is set is binary. """ fin = open(filename, 'rb') wholething = fin.read() fin.close() for c in wholething: if ord(c) & 0x80: return 1 return 0 def is_kb_sticky (filename): """This checks if 'cvs status' reports '-kb' for Sticky options. If the Sticky Option status is '-ks' then this returns 1. If the status is 'Unknown' then it returns 1. Otherwise 0 is returned. """ try: s = pexpect.spawn ('cvs status %s' % filename) i = s.expect (['Sticky Options:\s*(.*)\r\n', 'Status: Unknown']) if i==1 and VERBOSE: print 'File not part of CVS repository:', filename return 1 # Pretend it's OK. if s.match.group(1) == '-kb': return 1 s = None except: print 'Something went wrong trying to run external cvs command.' print ' cvs status %s' % filename print 'The cvs command returned:' print s.before return 0 def cvs_admin_kb (filename): """This uses 'cvs admin' to set the '-kb' sticky option. """ s = pexpect.run ('cvs admin -kb %s' % filename) # There is a timing issue. If I run 'cvs admin' too quickly # cvs sometimes has trouble obtaining the directory lock. time.sleep(1) def walk_and_clean_cvs_binaries (arg, dirname, names): """This contains the logic for processing files. This is the os.path.walk callback. This skips dirnames that end in CVS. """ if len(dirname)>3 and dirname[-3:]=='CVS': return for n in names: fullpath = os.path.join (dirname, n) if os.path.isdir(fullpath) or os.path.islink(fullpath): continue if is_binary(fullpath): if not is_kb_sticky (fullpath): if VERBOSE: print fullpath cvs_admin_kb (fullpath) def main (): if len(sys.argv) == 1: root = '.' else: root = sys.argv[1] os.path.walk (root, walk_and_clean_cvs_binaries, None) if __name__ == '__main__': main ()