-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdot_setup
executable file
·118 lines (96 loc) · 2.72 KB
/
dot_setup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
#!/usr/bin/env perl
=head1 NAME
dot_setup
=head1 DESCRIPTION
Create symlinks in home directory to files in directory which contains this
script. Symlink names will be same as the target name, but with a C<.>
prepended.
Files to be linked to are listed as command line arguments. If the name
C<USUAL> is given as an argument, that file in the target directory will be
opened, and each line in it will be added to the files specified on the command
line.
=cut
use strict;
use warnings;
use File::Compare;
my $use_exit = 0;
my $merge = 0;
my $home = $ENV{HOME};
# Get location of files from script location
my $src = $0;
# Convert relative path to absolute
$src = "$ENV{PWD}/$src" unless $src =~ m{^/};
# Eliminate useless references to "." directory
1 while $src =~ s{/\./}{/};
# Eliminate uses of ".."
1 while $src =~ s{/[^/]+/\.\./}{/};
# Remove script filename to get just dir name
$src =~ s{/[^/]+$}{};
# Copy of absolute for opening USUAL file
my $source = $src;
# Convert to being relative to home
$src =~ s{^$home/?}{};
my $added = 0;
my $conflicts = 0;
foreach my $f (@ARGV) {
chomp $f;
next if $f =~ /dot_setup/; # Never link this script
if ($f eq '-m') { $merge = 1; next; }
if ($f eq '-e') {
$use_exit = 1;
next;
}
# IF "USUAL" is used as name to link, actually each line in that file as a name to link
if( $f =~ /USUAL/ ) {
open USUAL, '<', "$source/$f" or die "Couldn't open '$source/$f': $!\n";
push @ARGV, <USUAL>;
close USUAL;
next;
}
my $dest = ".$f"; # Name of link to use, relative to home directory
$dest =~ s{/$}{}; # Remove trailing slash to avoid creating an empty directory where we want a symlink.
# If the link is supposed to be in a subdirectory:
# * Make sure the parent directories exist
# * Adjust the symlink to go up to home before pointing to target
my $parents = "";
my $dirs = "";
while( $dest =~ m{([^/]+/)}g ) {
$dirs .= $1;
$parents .= "../";
unless ( -d "$home/$dirs" ) {
mkdir "$home/$dirs" or die;
}
}
$dest = "$ENV{HOME}/$dest"; # Convert destination to absolute path
# Indicate what targets already exist and which are going to be created
my $target = "$parents$src/$f";
my $status = '!';
if ( -l $dest ) {
$status = '.' if readlink($dest) eq $target;
}
else {
$status = '+' unless -e $dest;
}
if ($status eq '!') {
foreach my $try (1,2) {
if (compare($dest, $f)) {
system "vimdiff", $dest, $f if $try == $merge;
}
else {
$status = '=';
last;
}
}
}
my $add = $status =~ /^[+=]$/;
$added++ if $add;
$conflicts++ if $status eq '!';
print "$status $f\n";
next unless $add;
unlink $dest if $status eq '=';
symlink $target => $dest or die "Couldn't create link $dest: $!";
}
if ($use_exit) {
exit 2 if $conflicts;
exit 1 if $added;
}