#!/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 PEXPECT LICENSE This license is approved by the OSI and FSF as GPL-compatible. http://opensource.org/licenses/isc-license.txt Copyright (c) 2012, Noah Spurrier PERMISSION TO USE, COPY, MODIFY, AND/OR DISTRIBUTE THIS SOFTWARE FOR ANY PURPOSE WITH OR WITHOUT FEE IS HEREBY GRANTED, PROVIDED THAT THE ABOVE COPYRIGHT NOTICE AND THIS PERMISSION NOTICE APPEAR IN ALL COPIES. THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. """ 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 ()