Commit | Line | Data |
---|---|---|
959f3c4c JH |
1 | ;# $Id: locate.pl,v 3.0.1.1 1994/10/29 16:36:52 ram Exp $ |
2 | ;# | |
3 | ;# Copyright (c) 1991-1993, Raphael Manfredi | |
4 | ;# | |
5 | ;# You may redistribute only under the terms of the Artistic Licence, | |
6 | ;# as specified in the README file that comes with the distribution. | |
7 | ;# You may reuse parts of this distribution only within the terms of | |
8 | ;# that same Artistic Licence; a copy of which may be found at the root | |
9 | ;# of the source tree for dist 3.0. | |
10 | ;# | |
11 | ;# $Log: locate.pl,v $ | |
12 | ;# Revision 3.0.1.1 1994/10/29 16:36:52 ram | |
13 | ;# patch36: misspelled a 'closedir' as a 'close' statement | |
14 | ;# | |
15 | ;# Revision 3.0 1993/08/18 12:10:25 ram | |
16 | ;# Baseline for dist 3.0 netwide release. | |
17 | ;# | |
18 | ;# | |
19 | ;# Locate units and put them in the @ARGV array, for later perusal. We first | |
20 | ;# look in the private U directory, then in the public U library. In each U | |
21 | ;# directory, units may be gathered in clusters (directories). These clusters | |
22 | ;# should not have a name ending with .U, as those will never be stat()'ed. | |
23 | ;# | |
24 | ;# NB: Currently, the clusters are only a practical way of grouping a set of | |
25 | ;# closely related units. There must not be any name conflicts. | |
26 | ;# | |
27 | ;# The following variables are used: | |
28 | ;# $WD is assumed to be the working directory (where the process was spawned) | |
29 | ;# $MC is the location of metaconfig's public library | |
30 | ;# @ARGV is the list of all the units full path | |
31 | ;# %Unit maps an unit name (without final .U) to a path | |
32 | ;# @myUlist lists the user's units, which will be appended at the end of @ARGV | |
33 | ;# %myUseen lists the user's units which overwrite public ones | |
34 | ;# | |
35 | package locate; | |
36 | ||
37 | # Locate the units and push their path in @ARGV (sorted alphabetically) | |
38 | sub main'locate_units { | |
39 | print "Locating units...\n" unless $main'opt_s; | |
40 | local(*WD) = *main'WD; # Current working directory | |
41 | local(*MC) = *main'MC; # Public metaconfig library | |
42 | undef %myUlist; # Records private units paths | |
43 | undef %myUseen; # Records private/public conflicts | |
44 | &private_units; # Locate private units in @myUlist | |
45 | &public_units; # Locate public units in @ARGV | |
46 | @ARGV = sort @ARGV; # Sort it alphabetically | |
47 | push(@ARGV, sort @myUlist); # Append user's units sorted | |
48 | &dump_list if $main'opt_v; # Dump the list of units | |
49 | } | |
50 | ||
51 | # Dump the list of units on stdout | |
52 | sub dump_list { | |
53 | print "\t"; | |
54 | $, = "\n\t"; | |
55 | print @ARGV; | |
56 | $, = ''; | |
57 | print "\n"; | |
58 | } | |
59 | ||
60 | # Scan private units | |
61 | sub private_units { | |
62 | return unless -d 'U'; # Nothing to be done if no 'U' entry | |
63 | local(*ARGV) = *myUlist; # Really fill in @myUlist | |
64 | local($MC) = $WD; # We are really in the working directory | |
65 | &units_path("U"); # Locate units in the U directory | |
66 | local($unit_name); # Unit's name (without .U) | |
67 | local(@kept); # Array of kept units | |
68 | # Loop over the units and remove duplicates (the first one seen is the one | |
69 | # we keep). Also set the %myUseen H table to record private units seen. | |
70 | foreach (@ARGV) { | |
71 | ($unit_name) = m|^.*/(.*)\.U$|; # Get unit's name from path | |
72 | next if $myUseen{$unit_name}; # Already recorded | |
73 | $myUseen{$unit_name} = 1; # Record pirvate unit | |
74 | push(@kept, $_); # Keep this unit | |
75 | } | |
76 | @ARGV = @kept; | |
77 | } | |
78 | ||
79 | # Scan public units | |
80 | sub public_units { | |
81 | chdir($MC) || die "Can't find directory $MC.\n"; | |
82 | &units_path("U"); # Locate units in public U directory | |
83 | chdir($WD) || die "Can't go back to directory $WD.\n"; | |
84 | local($path); # Relative path from $WD | |
85 | local($unit_name); # Unit's name (without .U) | |
86 | local(*Unit) = *main'Unit; # Unit is a global from main package | |
87 | local(@kept); # Units kept | |
88 | local(%warned); # Units which have already issued a message | |
89 | # Loop over all the units and keep only the ones that were not found in | |
90 | # the user's U directory. As it is possible two or more units with the same | |
91 | # name be found in | |
92 | foreach (@ARGV) { | |
93 | ($unit_name) = m|^.*/(.*)\.U$|; # Get unit's name from path | |
94 | next if $warned{$unit_name}; # We have already seen this unit | |
95 | $warned{$unit_name} = 1; # Remember we have warned the user | |
96 | if ($myUseen{$unit_name}) { # User already has a private unit | |
97 | $path = $Unit{$unit_name}; # Extract user's unit path | |
98 | next if $path eq $_; # Same path, we must be in mcon/ | |
99 | $path =~ s|^$WD/||o; # Weed out leading working dir path | |
100 | print " Your private $path overrides the public one.\n" | |
101 | unless $main'opt_s; | |
102 | } else { | |
103 | push(@kept, $_); # We may keep this one | |
104 | } | |
105 | } | |
106 | @ARGV = @kept; | |
107 | } | |
108 | ||
109 | # Recursively locate units in the directory. Each file ending with .U has to be | |
110 | # a unit. Others are stat()'ed, and if they are a directory, they are also | |
111 | # scanned through. The $MC and @ARGV variable are dynamically set by the caller. | |
112 | sub units_path { | |
113 | local($dir) = @_; # Directory where units are to be found | |
114 | local(@contents); # Contents of the directory | |
115 | local($unit_name); # Unit's name, without final .U | |
116 | local($path); # Full path of a unit | |
117 | local(*Unit) = *main'Unit; # Unit is a global from main package | |
118 | unless (opendir(DIR, $dir)) { | |
119 | warn("Cannot open directory $dir.\n"); | |
120 | return; | |
121 | } | |
122 | print "Locating in $MC/$dir...\n" if $main'opt_v; | |
123 | @contents = readdir DIR; # Slurp the whole thing | |
124 | closedir DIR; # And close dir, ready for recursion | |
125 | foreach (@contents) { | |
126 | next if $_ eq '.' || $_ eq '..'; | |
127 | if (/\.U$/) { # A unit, definitely | |
128 | ($unit_name) = /^(.*)\.U$/; | |
129 | $path = "$MC/$dir/$_"; # Full path of unit | |
130 | push(@ARGV, $path); # Record its path | |
131 | if (defined $Unit{$unit_name}) { # Already seen this unit | |
132 | if ($main'opt_v) { | |
133 | ($path) = $Unit{$unit_name} =~ m|^(.*)/.*|; | |
134 | print " We've already seen $unit_name.U in $path.\n"; | |
135 | } | |
136 | } else { | |
137 | $Unit{$unit_name} = $path; # Map name to path | |
138 | } | |
139 | next; | |
140 | } | |
141 | # We have found a file which does not look like a unit. If it is a | |
142 | # directory, then scan it. Otherwise skip the file. | |
143 | unless (-d "$dir/$_") { | |
144 | print " Skipping file $_ in $dir.\n" if $main'opt_v; | |
145 | next; | |
146 | } | |
147 | &units_path("$dir/$_"); | |
148 | print "Back to $MC/$dir...\n" if $main'opt_v; | |
149 | } | |
150 | } | |
151 | ||
152 | package main; | |
153 |