chiark / gitweb /
Correct handling of @@ stuff inside @@?; make NC_SITES vary.
[ian-dotfiles.git] / process
1 #!/usr/bin/perl
2
3 use POSIX;
4
5 $action=0;
6 defined($umask=umask) or die $!;
7 $home= $ENV{'HOME'}.'/';
8
9 while ($ARGV[0] =~ m/^-/) {
10     $_= shift(@ARGV);
11     last if m/^--$/;
12     while (m/^-./) {
13         if (s/^-y/-/) {
14             $action=1;
15         } elsif (s/^-u([0-7]{3})/-/) {
16             $umask= oct $1;
17         } elsif (s/^-h/-/) {
18             $home= $';
19         } else {
20             die;
21         }
22     }
23 }
24 die if @ARGV;
25
26 stat $home or die $!;
27 -d _ or die;
28
29 sub read_prep ($) {
30     my ($inputfile) = @_;
31     defined($c= open P, "-|") or die $!;
32     if (!$c) { exec './gpt','config',$inputfile; die $!; }
33 }
34 sub fin_prep () {
35     close P; die "$?" if $?;
36 }
37
38 read_prep('perms');
39 for (;;) {
40     $!=0; defined($_=<P>) or die $!;
41     chomp; s/^\s+//; s/\s+$//;
42     next if m/^\#/; next unless m/\S/;
43     last if m/^\.$/;
44     if (m/(.*\S)\s+\-\>\s+(\S.*)/) {
45         $linktargs{$1}= $2;
46     } elsif (m/^(.*\S)\s+(\S+)$/) {
47         ($of,$pe)=($1,$2);
48         $isdir= $of =~ s,/$,,;
49         if ($pe =~ m/^[0-7]+$/) {
50             $pe= oct $&;
51         } elsif ($pe eq '+x') {
52             $pe= 0777&~$umask;
53         } elsif ($pe eq '/') {
54             $pe= 02777&~$umask;
55         } else {
56             die "$pe ?";
57         }
58         ($isdir ? $dirperms{$of} : $fileperms{$of}) = $pe;
59     }
60 }
61 fin_prep();
62
63 sub mkparents ($) {
64     my ($parent) = @_;
65     $parent =~ s,/[^/]+$,, or return;
66     ensuredir($parent);
67 }
68
69 sub maybe_chmod ($$$) {
70     my ($nowperms,$perms,$obj) = @_;
71     return if $nowperms==$perms;
72     if ($action) {
73         chmod $perms, $home.$obj or die $!;
74     } else {
75         would($obj, sprintf 'chmod %04o -> %04o', $nowperms, $perms);
76     }
77 }
78
79 sub ensuredir ($) {
80     my ($dir) = @_;
81     mkparents($dir);
82     $perms= exists $dirperms{$dir} ? $dirperms{$dir} : 02777&~$umask;
83     if (stat $home.$dir) {
84         -d _ or die "$dir is not a directory!";
85         $nowperms= (stat _)[2] & 07777;
86         maybe_chmod($nowperms,$perms,$dir);
87     } else {
88         die $! unless $!==&ENOENT;
89         if ($action) {
90             mkdir $home.$dir, $perms or die $!;
91         } else {
92             would($dir, sprintf 'mkdir %04o', $perms);
93         }
94     }
95 }
96
97 -d 'new' or mkdir 'new', 02700 or die $!;
98
99 sub prep_proc ($$) {
100     my ($if,$newf) = @_;
101     my ($c);
102     defined($c= fork) or die $!;
103     if (!$c) {
104         unlink $newf;
105         open STDOUT, "> $newf" or die "$newf $!";
106         exec './gpt','config',$if; die $!;
107     }
108     $!=0; waitpid($c,0)==$c or die $!;
109     $? and die $?;
110 }
111
112 opendir D, "files" or die $!;
113 while ($if=readdir D) {
114     next unless $if =~ m/^[_a-z0-9\\]/;
115     $of= $if; 
116     $of =~ s,_,/,g; 
117     $of =~ s,^/,,;
118     $of =~ s,//,_,g;
119     $of =~ s/\\([0-9a-f][0-9a-f]|_|\\)/
120         length $1 eq 1 ? $1 : sprintf '%c', hex $1 
121             /ge;
122
123     mkparents($of);
124     $newf= 'new/'.$if;
125     prep_proc('files/'.$if,$newf);
126
127     $perms= exists $fileperms{$of} ? $fileperms{$of} : 00666&~$umask;
128     chmod $perms, $newf or die $!;
129     
130     if (stat $home.$of) {
131         -f _ or die "$of is not a file!";
132         $nowperms= (stat _)[2] & 07777;
133         if ($nowperms != $perms) {
134             would($of, sprintf 'chmod %04o -> %04o', $nowperms, $perms);
135         }
136         system 'diff','-u',$home.$of,$newf;
137         $?==0 or $?==256 or die $?;
138         $changes++ if $?;
139     } else {
140         die unless $!==&ENOENT;
141         would($of, sprintf 'create %04o', $perms);
142     }
143     if ($action) {
144         rename $newf,$home.$of or die $!;
145     }
146
147     delete $fileperms{$of};
148 }
149 closedir D or die $!;
150
151 die join(', ', keys %fileperms) if %fileperms;
152
153 foreach $link (keys %linktargs) {
154     mkparents($link);
155     $targ= $linktargs{$link};
156     if (lstat $home.$link) {
157         -l _ or die "$link is not a link!";
158         defined($rl= readlink $home.$link) or die $!;
159     } else {
160         die unless $!==&ENOENT;
161         $rl= undef;
162     }
163     if ($rl ne $targ) {
164         would($link, "symlink $targ <-");
165         if ($action) {
166             unlink $home.$link if defined $rl;
167             symlink $targ,$home.$link or die $!;
168         }
169     }
170 }
171
172 foreach $dir (keys %dirperms) {
173     ensuredir($dir);
174 }
175
176 sub would ($$) {
177     my ($obj,$what) = @_;
178     return if $would_done{$obj}++;
179     print STDOUT "*** $what $obj\n" or die $!;
180     $changes++;
181 }
182
183 if ($changes) {
184     print STDOUT "=== $changes changes\n" or die $!;
185 } else {
186     print STDOUT "=== no changes\n" or die $!;
187 }
188
189 prep_proc('execute','new/,execute');
190 if ($action) {
191     chmod 0700,'new/,execute' or die $!;
192     system 'new/,execute'; $? and die $?;
193 }
194
195 close STDOUT or die $!;