c96248e676e751f98bece2f221db1d0100ea0738
[nethome.git] / bin / cvslinks
1 #! /usr/bin/perl
2
3 use strict;
4 use warnings;
5
6 use Getopt::Std;
7 use Cwd;
8
9 use constant FILENAME=>".cvslinks";
10 use constant ENTRIES=>"CVS/Entries";
11
12
13 our($opt_u,$opt_c,$opt_d,$opt_r,$opt_R,$opt_l,$opt_v);
14 getopts "ucdrRlv";
15
16 die "-u (update), -c (commit) or -R (delete) required"        if !$opt_u && !$opt_c && !$opt_d;
17 die "-r (recursive)/-R (recursive w/o CVS) and -l (local) are conflicting"
18                 if ($opt_r || $opt_R) && $opt_l;
19
20 $opt_r=1 if !$opt_r && !$opt_R && !$opt_l; # default
21
22 body();
23 exit 0;
24
25 sub body
26 {
27         do_u() if $opt_u;
28         do_c() if $opt_c;
29         do_d() if $opt_d;
30         do_r() if $opt_r;
31         do_R() if $opt_R;
32 }
33
34 sub verbose
35 {
36 my($msg)=@_;
37
38         return if !$opt_v;
39         print cwd().": $msg\n";
40 }
41
42 sub do_d
43 {
44         local *D;
45         opendir D,"." or die "Cannot open directory \".\": $!";
46         for (readdir D) {
47                 next if ! -l;
48                 verbose "Deleting local link $_";
49                 unlink;
50                 }
51         closedir D;
52 }
53
54 sub do_u
55 {
56         local *L;
57         open L,FILENAME or die "File ".FILENAME." cannot be opened: $!";
58         do_d();
59         verbose "Creating links from ".FILENAME;
60         while (<L>) {
61                 chomp;
62                 next if /^$/; # empty-file (->empty-dir) stub line
63                 /^(.+)\t(.+)$/ or warn "Unrecognized line: $_";
64                 verbose "Creating link $1";
65                 symlink $2,$1 or warn "symlink(\"$2\"->\"$1\"): $!";
66                 }
67         close L;
68 }
69
70 sub do_c
71 {
72         local(*L,*D);
73         opendir D,"." or die "Cannot open directory \".\": $!";
74         open L,">".FILENAME or die "File ".FILENAME." cannot be created: $!";
75         verbose "Storing links to ".FILENAME;
76         print L "\n"; # empty-file (->empty-dir) stub line
77         for (readdir D) {
78                 next if ! -l;
79                 my $target=readlink or die "Cannot read link $_: $!";
80                 verbose "Storing link $_";
81                 print L "$_\t$target\n";
82                 }
83         closedir D;
84 }
85
86 sub descent
87 {
88 my($dir)=@_;
89
90         if (!chdir $dir) {
91                 warn "Cannot chdir to $dir: $!";
92                 return;
93                 }
94         verbose "Descented to child directory";
95         body();
96         chdir ".." or die "Cannot return back to ..: $!";
97         verbose "Back in parent directory";
98 }
99
100 sub do_r
101 {
102         local *C;
103         if (!open C,ENTRIES) {
104                 warn "Cannot open file \"".ENTRIES."\": $!";
105                 return;
106                 }
107         while (<C>) {
108                 chomp;
109                 next if !m#^D/([^/]*)/#;
110                 descent($1);
111                 }
112         close C;
113 }
114
115 sub do_R
116 {
117         local *D;
118         opendir D,"." or die "Cannot open directory \".\": $!";
119         for (readdir D) {
120                 # Beware of symlinked-directories !
121                 next if -l || ! -d || $_ eq "." || $_ eq "..";
122                 descent($_);
123                 }
124         closedir D;
125 }