1 #!/usr/bin/env python 2 3 """This is for cleaning up binary files improperly added to CVS. This script 4 scans the given path to find binary files; checks with CVS to see if the sticky 5 options are set to -kb; finally if sticky options are not -kb then uses 'cvs 6 admin' to set the -kb option. 7 8 This script ignores CVS directories, symbolic links, and files not known under 9 CVS control (cvs status is 'Unknown'). 10 11 Run this on a CHECKED OUT module sandbox, not on the repository itself. After 12 if fixes the sticky options on any files you should manually do a 'cvs commit' 13 to accept the changes. Then be sure to have all users do a 'cvs up -A' to 14 update the Sticky Option status. 15 16 Noah Spurrier 17 20030426 18 """ 19 20 import os, sys, time 21 import pexpect 22 23 VERBOSE = 1 24 25 def is_binary (filename): 26 27 """Assume that any file with a character where the 8th bit is set is 28 binary. """ 29 30 fin = open(filename, 'rb') 31 wholething = fin.read() 32 fin.close() 33 for c in wholething: 34 if ord(c) & 0x80: 35 return 1 36 return 0 37 38 def is_kb_sticky (filename): 39 40 """This checks if 'cvs status' reports '-kb' for Sticky options. If the 41 Sticky Option status is '-ks' then this returns 1. If the status is 42 'Unknown' then it returns 1. Otherwise 0 is returned. """ 43 44 try: 45 s = pexpect.spawn ('cvs status %s' % filename) 46 i = s.expect (['Sticky Options:\s*(.*)\r\n', 'Status: Unknown']) 47 if i==1 and VERBOSE: 48 print 'File not part of CVS repository:', filename 49 return 1 # Pretend it's OK. 50 if s.match.group(1) == '-kb': 51 return 1 52 s = None 53 except: 54 print 'Something went wrong trying to run external cvs command.' 55 print ' cvs status %s' % filename 56 print 'The cvs command returned:' 57 print s.before 58 return 0 59 60 def cvs_admin_kb (filename): 61 62 """This uses 'cvs admin' to set the '-kb' sticky option. """ 63 64 s = pexpect.run ('cvs admin -kb %s' % filename) 65 # There is a timing issue. If I run 'cvs admin' too quickly 66 # cvs sometimes has trouble obtaining the directory lock. 67 time.sleep(1) 68 69 def walk_and_clean_cvs_binaries (arg, dirname, names): 70 71 """This contains the logic for processing files. This is the os.path.walk 72 callback. This skips dirnames that end in CVS. """ 73 74 if len(dirname)>3 and dirname[-3:]=='CVS': 75 return 76 for n in names: 77 fullpath = os.path.join (dirname, n) 78 if os.path.isdir(fullpath) or os.path.islink(fullpath): 79 continue 80 if is_binary(fullpath): 81 if not is_kb_sticky (fullpath): 82 if VERBOSE: print fullpath 83 cvs_admin_kb (fullpath) 84 85 def main (): 86 87 if len(sys.argv) == 1: 88 root = '.' 89 else: 90 root = sys.argv[1] 91 os.path.walk (root, walk_and_clean_cvs_binaries, None) 92 93 if __name__ == '__main__': 94 main () 95 96