|
1 |
| -#!/usr/bin/env perl |
2 |
| -# |
| 1 | +#!/usr/bin/env python3 |
3 | 2 | # This script finds all CVS/Entries files in the current directory and below
|
4 | 3 | # and creates a local .cvsinclude file with non-inherited rules including each
|
5 | 4 | # checked-in file. Then, use this option whenever using --cvs-exclude (-C):
|
6 | 5 | #
|
7 |
| -# -f ': .cvsinclude' |
| 6 | +# -f ': .cvsinclude' |
8 | 7 | #
|
9 | 8 | # That ensures that all checked-in files/dirs are included in the transfer.
|
10 | 9 | # (You could alternately put ": .cvsinclude" into an .rsync-filter file and
|
11 | 10 | # use the -F option, which is easier to type.)
|
12 | 11 | #
|
13 | 12 | # The downside is that you need to remember to re-run cvs2includes whenever
|
14 |
| -# you add a new file to the project. |
15 |
| -use strict; |
16 |
| - |
17 |
| -open(FIND, 'find . -name CVS -type d |') or die $!; |
18 |
| -while (<FIND>) { |
19 |
| - chomp; |
20 |
| - s#^\./##; |
21 |
| - |
22 |
| - my $entries = "$_/Entries"; |
23 |
| - s/CVS$/.cvsinclude/; |
24 |
| - my $filter = $_; |
25 |
| - |
26 |
| - open(ENTRIES, $entries) or die "Unable to open $entries: $!\n"; |
27 |
| - my @includes; |
28 |
| - while (<ENTRIES>) { |
29 |
| - push(@includes, $1) if m#/(.+?)/#; |
30 |
| - } |
31 |
| - close ENTRIES; |
32 |
| - if (@includes) { |
33 |
| - open(FILTER, ">$filter") or die "Unable to write $filter: $!\n"; |
34 |
| - print FILTER map "+ /$_\n", @includes; |
35 |
| - close FILTER; |
36 |
| - print "Updated $filter\n"; |
37 |
| - } elsif (-f $filter) { |
38 |
| - unlink($filter); |
39 |
| - print "Removed $filter\n"; |
40 |
| - } |
41 |
| -} |
42 |
| -close FIND; |
| 13 | +# CVS gets an added or removed file. Maybe just run it before every copy. |
| 14 | + |
| 15 | +import os, argparse |
| 16 | + |
| 17 | +INC_NAME = '.cvsinclude' |
| 18 | + |
| 19 | +def main(): |
| 20 | + if args.dir: |
| 21 | + os.chdir(args.dir) |
| 22 | + |
| 23 | + cvs_includes = set() |
| 24 | + for root, dirs, files in os.walk('.'): |
| 25 | + if INC_NAME in files: |
| 26 | + cvs_includes.add((root + '/' + INC_NAME)[2:]) |
| 27 | + if root.endswith('/CVS') and 'Entries' in files: |
| 28 | + entries = root[2:] + '/Entries' |
| 29 | + includes = [ ] |
| 30 | + with open(entries) as fh: |
| 31 | + for line in fh: |
| 32 | + if line.startswith(('/', 'D/')): |
| 33 | + includes.append(line.split('/', 2)[1]) |
| 34 | + if includes: |
| 35 | + inc = root[2:-3] + INC_NAME |
| 36 | + cvs_includes.discard(inc) |
| 37 | + try: |
| 38 | + with open(inc) as fh: |
| 39 | + old_txt = fh.read() |
| 40 | + except OSError: |
| 41 | + old_txt = '' |
| 42 | + txt = ''.join(f"+ /{x}\n" for x in includes) |
| 43 | + if txt == old_txt: |
| 44 | + print("Unchanged", inc) |
| 45 | + else: |
| 46 | + print("Updating", inc) |
| 47 | + with open(inc, 'w') as fh: |
| 48 | + fh.write(txt) |
| 49 | + dirs.sort() |
| 50 | + |
| 51 | + for inc in sorted(cvs_includes): |
| 52 | + print("Removing", inc) |
| 53 | + os.unlink(inc) |
| 54 | + |
| 55 | + |
| 56 | +if __name__ == '__main__': |
| 57 | + parser = argparse.ArgumentParser(description=f"Transform CVS/Entries into {INC_NAME} files.", add_help=False) |
| 58 | + parser.add_argument("--help", "-h", action="help", help="Output this help message and exit.") |
| 59 | + parser.add_argument("dir", nargs='?', help="The top CVS dir. Defaults to the current directory.") |
| 60 | + args = parser.parse_args() |
| 61 | + main() |
| 62 | + |
| 63 | +# vim: sw=4 et |
0 commit comments