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