MFC: following 2 commits:
[dragonfly.git] / gnu / usr.bin / cvs / contrib / easy-import.pl
blob4103c1ddd6375d97e5371c555d2d0b32bb90f15e
1 #! xPERL_PATHx
3 # Support for importing a source collection into CVS.
4 # Tries to prevent the user from the most common pitfalls (like creating
5 # new top-level repositories or second-level areas accidentally), and
6 # cares to do some of the `dirty' work like maintaining the modules
7 # database accordingly.
9 # Written by Jörg Wunsch, 95/03/07, and placed in the public domain.
11 # $FreeBSD: src/gnu/usr.bin/cvs/contrib/easy-import.pl,v 1.16 1999/09/05 17:35:31 peter Exp $
12 # $DragonFly: src/gnu/usr.bin/cvs/contrib/easy-import.pl,v 1.2 2003/06/17 04:25:45 dillon Exp $
14 require "complete.pl";
15 require "getopts.pl";
18 sub scan_opts
20 local($status);
22 $status = &Getopts("nv");
24 $dont_do_it = "-n" if $opt_n;
25 if($opt_v) {
26 print STDERR '$FreeBSD: src/gnu/usr.bin/cvs/contrib/easy-import.pl,v 1.16 1999/09/05 17:35:31 peter Exp $' . "\n"; # 'emacs kludge
27 exit 0;
29 die "usage: $0 [-v] [-n] [moduledir]\n" .
30 " -n: don't do any commit, show only\n" .
31 " -v: show program version\n"
32 unless $status && $#ARGV <= 0;
34 if($#ARGV == 0) {
35 $moduledir = $ARGV[0];
36 shift;
40 sub lsdir
42 # find all subdirectories under @_
43 # ignore all CVS entries, dot entries, and non-directories
45 local($base) = @_;
46 local(@ls, @rv, $fname);
48 opendir(DIR, $base) || die "Cannot find dir $base.\n";
50 @ls = readdir(DIR);
51 closedir(DIR);
53 @rv = ();
55 foreach $fname (@ls) {
56 next if $fname =~ /^CVS/ || $fname eq "Attic"
57 || $fname =~ /^\./ || ! -d "$base/$fname";
58 @rv = (@rv, $fname);
61 return sort(@rv);
65 sub contains
67 # look if the first parameter is contained in the list following it
68 local($item, @list) = @_;
69 local($found, $i);
71 $found = 0;
72 foreach $i (@list) {
73 return 1 if $i eq $item;
75 return 0;
80 sub term_init
82 # first, get some terminal attributes
84 # try bold mode first
85 $so = `tput md`; $se = `tput me`;
87 # if no bold mode available, use standout mode
88 if ($so eq "") {
89 $so = `tput so`; $se = `tput se`;
92 # try if we can underscore
93 $us = `tput us`; $ue = `tput ue`;
94 # if we don't have it available, or same as bold/standout, disable it
95 if ($us eq "" || $us eq $so) {
96 $us = $ue = "";
99 # look how many columns we've got
100 if($ENV{'COLUMNS'} ne "") {
101 $columns = $ENV{'COLUMNS'};
102 } elsif(-t STDIN) { # if we operate on a terminal...
103 local($word, $tmp);
105 open(STTY, "stty -a|");
106 $_ = <STTY>; # try getting the tty win structure value
107 close(STTY);
108 chop;
109 $columns = 0;
110 foreach $word (split) {
111 $columns = $tmp if $word eq "columns;"; # the number preceding
112 $tmp = $word;
114 } else {
115 $columns = 80;
117 # sanity
118 $columns = 80 unless $columns >= 5;
122 sub list
124 # pretty-print a list
125 # imports: global variable $columns
126 local(@items) = @_;
127 local($longest,$i,$item,$cols,$width);
129 # find the longest item
130 $longest = 0;
131 foreach $item (@items) {
132 $i = length($item);
133 $longest = $i if $longest < $i;
135 $width = $longest + 1;
136 $cols = int($columns / $width);
138 $i = 0;
139 foreach $item (@items) {
140 print $item;
141 if(++$i == $cols) {
142 $i = 0; print "\n";
143 } else {
144 print ' ' x ($width - length($item));
147 print "\n" unless $i == 0;
150 sub cvs_init
152 # get the CVS repository(s)
154 die "You need to have the \$CVSROOT variable set.\n"
155 unless $ENV{'CVSROOT'} ne "";
157 # get the list of available repositories
158 $cvsroot = $ENV{'CVSROOT'};
159 $cvsroot = (split(/:/, $cvsroot, 2))[1] if $cvsroot =~ /:/;
160 @reps = &lsdir($cvsroot);
164 sub lsmodules
166 # list all known CVS modules
167 local(%rv, $mname, $mpath, $_);
169 %rv = ();
171 open(CVS, "cvs co -c|");
172 while($_ = <CVS>) {
173 chop;
174 ($mname,$mpath) = split;
175 next if $mname eq "";
176 $rv{$mname} = $mpath;
178 close(CVS);
180 return %rv;
184 sub checktag
186 # check a given string for tag rules
187 local($s, $name) = @_;
188 local($regexp);
190 if($name eq "vendor") { $regexp = '^[A-Z][A-Z0-9_]*$'; }
191 elsif($name eq "release") { $regexp = '^[a-z][a-z0-9_]*$'; }
192 else {
193 print STDERR "Internal error: unknown tag name $name\n";
194 exit(2);
197 if($s !~ /$regexp/) {
198 print "\a${us}Valid $name tags must match the regexp " .
199 "$regexp.${ue}\n";
200 return 0;
202 if($s =~ /^RELENG/) {
203 print "\a${us}Tags must not start with the word \"RELENG\".${ue}\n";
204 return 0;
207 return 1;
211 &scan_opts;
212 &term_init;
213 &cvs_init;
215 if(! $moduledir) {
216 @dirs = &lsdir(".");
217 print "${so}Import from which directory?${se}\n";
218 @dirs = (@dirs, ".");
219 &list(@dirs);
220 $moduledir = &Complete("Which? [.]: ", @dirs);
221 $moduledir = "." unless $moduledir ne "";
224 chdir $moduledir || die "Cannot chdir to $moduledir\n";
226 print "${so}Available repositories:${se}\n";
227 &list(@reps);
229 # the following kludge prevents the Complete package from starting
230 # over with the string just selected; Complete should better provide
231 # some reinitialize method
232 $Complete'return = ""; $Complete'r = 0;
234 $selected =
235 &Complete("Enter repository (<TAB>=complete, ^D=show): ",
236 @reps);
238 die "\aYou cannot create new repositories with this script.\n"
239 unless &contains($selected, @reps);
241 $rep = $selected;
243 print "\n${so}Selected repository:${se} ${us}$rep${ue}\n";
246 @areas = &lsdir("$cvsroot/$rep");
248 print "${so}Existent areas in this repository:${se}\n";
249 &list(@areas);
251 $Complete'return = ""; $Complete'r = 0;
253 $selected =
254 &Complete("Enter area name (<TAB>=complete, ^D=show): ",
255 @areas);
257 print "\a${us}Warning: this will create a new area.${ue}\n"
258 unless &contains($selected, @areas);
260 $area = "$rep/$selected";
262 print "\n${so}[Working on:${se} ${us}$area${ue}${so}]${se}\n";
264 %cvsmods = &lsmodules();
266 for(;;) {
267 $| = 1;
268 print "${so}Gimme the module name:${se} ";
269 $| = 0;
270 $modname = <>;
271 chop $modname;
272 if ($modname eq "") {
273 print "\a${us}You cannot use an empty module name.${ue}\n";
274 next;
276 last if !$cvsmods{$modname};
277 print "\a${us}This module name does already exist; do you intend to\n" .
278 "perform a vendor-branch import to the existing sources?${ue}: ";
279 $rep = <>;
280 if ($rep =~ /\s*[yY]/) {
281 ($area,$modpath) = split(/\//,$cvsmods{$modname},2);
282 $branchimport = 1;
283 last;
285 print "${us}Choose another name.${ue}\n";
289 if(!$branchimport) {
290 for(;;) {
291 $| = 1;
292 print "${so}Enter the module path:${se} $area/";
293 $| = 0;
294 $modpath = <>;
295 chop $modpath;
296 if ($modpath eq "") {
297 print "\a${us}You cannot use an empty module path.${ue}\n";
298 next;
300 last if ! -d "$cvsroot/$area/$modpath";
301 print "\a${us}This module path does already exist; " .
302 "choose another one.${ue}\n";
306 @newdirs = ();
307 $dir1 = "$cvsroot/$area";
308 $dir2 = "$area";
310 @newdirs = (@newdirs, "$dir2") if ! -d $dir1;
312 foreach $ele (split(/\//, $modpath)) {
313 $dir1 = "$dir1/$ele";
314 $dir2 = "$dir2/$ele";
315 @newdirs = (@newdirs, "$dir2") if ! -d $dir1;
318 print "${so}You're going to create the following new directories:${se}\n";
320 &list(@newdirs);
323 for(;;) {
324 $| = 1;
325 print "${so}Enter a \`vendor\' tag (e. g. the authors ID):${se} ";
326 $| = 0;
327 $vtag = <>;
328 chop $vtag;
329 last if &checktag($vtag, "vendor");
332 for(;;) {
333 $| = 1;
334 print "${so}Enter a \`release\' tag (e. g. the version #):${se} ";
335 $| = 0;
336 $rtag = <>;
337 chop $rtag;
338 last if &checktag($rtag, "release");
342 $| = 1;
343 print "${so}This is your last chance to interrupt, " .
344 "hit <return> to go on:${se} ";
345 $| = 0;
348 if (!$branchimport) {
349 $mod = "";
350 foreach $tmp (sort(keys(%cvsmods))) {
351 if($tmp gt $modname) {
352 $mod = $tmp;
353 last;
356 if($mod eq "") {
357 # we are going to append our module
358 $cmd = "\$\na\n";
359 } else {
360 # we can insert it
361 $cmd = "/^${mod}[ \t]/\ni\n";
364 print "${so}Checking out the modules database...${se}\n";
365 system("cvs co modules") && die "${us}failed.\n${ue}";
367 print "${so}Inserting new module...${se}\n";
368 open(ED, "|ed modules/modules") || die "${us}Cannot start ed${ue}\n";
369 print(ED "${cmd}${modname} " . ' ' x (15 - length($modname)) .
370 "$area/${modpath}\n.\nw\nq\n");
371 close(ED);
373 print "${so}Commiting new modules database...${se}\n";
374 system("cvs $dont_do_it commit -m \" " .
375 "${modname} --> $area/${modpath}\" modules")
376 && die "Commit failed\n";
378 # we always release "modules" to prevent duplicate
379 system("cvs -Q release -d modules");
382 print "${so}Importing source. Enter a commit message in the editor.${se}\n";
384 system("cvs $dont_do_it import $area/$modpath $vtag $rtag");
386 print "${so}You are done now. Go to a different directory, perform a${se}\n".
387 "${us}cvs co ${modname}${ue} ${so}command, and see if your new module" .
388 " builds ok.${se}\n";
390 print "\nPlease don't forget to edit the parent Makefile to add what you\n".
391 "just imported.\n";
393 if($dont_do_it) {
394 print <<END
397 ${so}Since you did not allow to commit anything, you'll have${se}
398 ${so}to remove the edited modules' database yourself.${se}
399 ${so}To do this, perform a${se}
400 ${us}cd ${moduledir}; cvs -Q release -d modules${ue}
401 ${so}command.${se}