[Fai-commit] r4634 - people/eartoast/addons/class-reference
glaweh-guest at alioth.debian.org
glaweh-guest at alioth.debian.org
Thu Oct 18 15:54:06 UTC 2007
Author: glaweh-guest
Date: 2007-10-18 15:54:06 +0000 (Thu, 18 Oct 2007)
New Revision: 4634
Added:
people/eartoast/addons/class-reference/fai-classes-config
Log:
create a reference of all classes used in a fai config
run this script in the FAI config topdir
it extracts all references to classes and prints them on stdout
Format:
class: $classname
$filename[:linenumber]
...
Added: people/eartoast/addons/class-reference/fai-classes-config
===================================================================
--- people/eartoast/addons/class-reference/fai-classes-config (rev 0)
+++ people/eartoast/addons/class-reference/fai-classes-config 2007-10-18 15:54:06 UTC (rev 4634)
@@ -0,0 +1,287 @@
+#!/usr/bin/perl
+# HG: create a reference of all classes used in a fai config
+# run this script in the FAI config topdir
+# it extracts all references to classes and prints them on stdout
+# Format:
+# class: $classname
+# $filename[:linenumber]
+# ...
+
+use strict;
+use File::Find;
+use File::Basename;
+
+# Dirs used for revision control system's metadata
+my @rcs_dirs = qw'CVS .svn .arch-ids {arch}';
+
+# Hash of array-refs
+# keys: classes
+# values: list of places where the classes are referenced
+my %config_classes;
+
+# add a location to %config_classes
+sub add_class_ref {
+ my $class = shift;
+ my $location = shift;
+
+ # strip heading/tailing nonword-characters
+ $class =~ s#^\W*([\w-]+)\W*$#$1#;
+ push @{$config_classes{$class}},$location;
+}
+
+# generic subroutine to parse scripts for class references
+sub parse_script {
+ my $dir=shift;
+ my $fname=shift;
+ my $fh;
+ open $fh,$fname;
+ chomp (my $interpreter=<$fh>);
+
+ if ($interpreter =~ s/^#!//) {
+ $interpreter = basename($interpreter);
+ } else {
+ # files without a shebang are assumed to be shellscripts
+ $interpreter = 'bash';
+ }
+
+ # for the time being, only parse shellscripts
+ if ($interpreter =~ m#^(bash|sh|dash)#) {
+ while (<$fh>) {
+ # remove comments, skip over empty lines
+ s/#.*$//;
+ chomp;
+ next if (/^$/);
+ # extract class references from 'ifclass' calls
+ while (m#(^|\W)ifclass\s+(\S+)#g) {
+ add_class_ref($2,"$dir/$fname:$.");
+ }
+ }
+ } else {
+ print STDERR "unknown interpreter $interpreter in $dir/$fname\n";
+ }
+ close($fh);
+}
+
+# scan the $FAI/files hierarchy for classes
+sub scan_files {
+ # file-modes can contain classes
+ sub parse_filemodes {
+ my $dir=shift;
+ my $fname=shift;
+ my $fh;
+ open $fh,$fname;
+ while (<$fh>) {
+ s/#.*$//;
+ chomp;
+ my ($user,$grp,$mode,$class) = split;
+ add_class_ref($class,"$dir/$fname:$.") if ($class);
+ }
+ close($fh);
+ }
+
+ # put dirs to ignore when recursing into a hash
+ my %ignoredirs;
+ map $ignoredirs{$_}=1, at rcs_dirs;
+
+ # hardcoded list of files to ignore
+ my $ignore_files='^(fcopy.info|censored|make-passwd|zedv_webctl.sh|ZEDV-README|ZEDV-ifhp.conf.sample|ZEDV-ifhp.local)$';
+
+ File::Find::find({
+ wanted=>sub{
+ # check only files
+ if (-f) {
+ if ($_ eq 'postinst') { parse_script($File::Find::dir,$_); }
+ elsif ($_ eq 'file-modes') { parse_filemodes($File::Find::dir,$_); }
+ elsif ($_ =~ m#$ignore_files#o) { }
+ else {
+ add_class_ref($_,"$File::Find::dir/$_");
+ }
+ }
+ },
+ # remove dirs-to-ignore in preprocess-step
+ preprocess=>sub{grep ! (-d and exists($ignoredirs{$_})), at _}},
+ "files");
+}
+
+# scan the $FAI/scripts hierarchy for classes
+sub scan_scripts {
+ my %ignoredirs;
+ map $ignoredirs{$_}=1, at rcs_dirs;
+
+ # no files to ignore so far here...
+ my $ignore_files='^$';
+
+ File::Find::find({
+ wanted=>sub{
+ # check only files
+ if (-f) {
+ # the number of slashes in the name is the depth
+ # use list context in re match to get this number
+ my $depth= () = $File::Find::name =~ m#/#g;
+ if ($_ =~ m#$ignore_files#o) { }
+ else {
+ if ($depth == 1) {
+ # files at depth=1 are classnames
+ add_class_ref($_,$File::Find::name);
+ } elsif ($depth == 2) {
+ # files at depth=2 are numbered files in a classnamed dir
+ add_class_ref(basename($File::Find::dir),$File::Find::name);
+ }
+ # check script for additional class references
+ parse_script($File::Find::dir,$_);
+ }
+ }
+ },
+ # remove dirs-to-ignore in preprocess step
+ preprocess=>sub{grep ! (-d and exists($ignoredirs{$_})), at _}},
+ "scripts");
+}
+
+# scan the $FAI/hooks/* for classes
+sub scan_hooks {
+ my %ignoredirs;
+ map $ignoredirs{$_}=1, at rcs_dirs;
+ my $ignore_files='^$';
+
+ File::Find::find({
+ wanted=>sub{
+ # check only files
+ if (-f) {
+ my $depth= () = $File::Find::name =~ m#/#g;
+ if ($_ =~ m#$ignore_files#o) { }
+ else {
+ if ($depth == 1) {
+ # files at depth=1 are $taskname.$class[.source]
+ m#\.([^\.]+)(\.source|)$#;
+ add_class_ref($1,$File::Find::name);
+ }
+ # just-in-case that there's a script in a subdir
+ parse_script($File::Find::dir,$_);
+ }
+ }
+ },
+ # remove dirs-to-ignore in preprocess step
+ preprocess=>sub{grep ! (-d and exists($ignoredirs{$_})), at _}},
+ "hooks");
+}
+
+# scan the $FAI/package_config/* for classes
+sub scan_package_config {
+ # parse package conf for 'PACKAGES install [$class...]'
+ sub parse_package_config {
+ my $dir=shift;
+ my $fname=shift;
+ my $fh;
+ open $fh,$fname;
+ while (<$fh>) {
+ s/#.*$//;
+ chomp;
+ next if (/^$/);
+ if (m#^PACKAGES\s+\S+(.*)$#) {
+ $_=$1;
+ my @classes=split;
+ foreach (@classes) {
+ add_class_ref($_,"$dir/$fname:$.");
+ }
+ }
+ }
+ close($fh);
+ }
+
+ my %ignoredirs;
+ map $ignoredirs{$_}=1, at rcs_dirs;
+ my $ignore_files='^$';
+
+ File::Find::find({
+ wanted=>sub{
+ # check only files
+ if (-f) {
+ my $depth= () = $File::Find::name =~ m#/#g;
+ if ($_ =~ m#$ignore_files#) { }
+ else {
+ if ($depth == 1) {
+ # package_config/$class
+ add_class_ref($_,$File::Find::name);
+ # could reference other classes in 'PACKAGES install'
+ parse_package_config($File::Find::dir,$_);
+ }
+ }
+ }
+ },
+ # remove dirs-to-ignore in preprocess step
+ preprocess=>sub{grep ! (-d and exists($ignoredirs{$_})), at _}},
+ "package_config");
+}
+
+# generic dir parser extracting classes from $dir/$class and $dir/$class/*
+sub scan_dir {
+ my %ignoredirs;
+ map $ignoredirs{$_}=1, at rcs_dirs;
+ my $ignore_files='^$';
+
+ File::Find::find({
+ wanted=>sub{
+ if (-f) {
+ my $depth= () = $File::Find::name =~ m#/#g;
+ if ($_ =~ m#$ignore_files#) { }
+ else {
+ if ($depth == 1) {
+ add_class_ref($_,$File::Find::name);
+ } elsif ($depth == 2) {
+ add_class_ref(basename($File::Find::dir),$File::Find::name);
+ }
+ }
+ }
+ },
+ # remove dirs-to-ignore in preprocess step
+ preprocess=>sub{grep ! (-d and exists($ignoredirs{$_})), at _}},
+ @_);
+}
+
+# scan $FAI/class/* for references on other classes
+sub scan_class {
+ my %ignoredirs;
+ map $ignoredirs{$_}=1, at rcs_dirs;
+ my $ignore_files='^$';
+
+ File::Find::find({
+ wanted=>sub{
+ if (-f) {
+ my $depth= () = $File::Find::name =~ m#/#g;
+ if ($_ =~ m#$ignore_files#) { }
+ else {
+ if ($depth == 1) {
+ if (m#^\d+#) { }
+ elsif (m#^([^\.]+)\.var$#) {
+ add_class_ref($1,$File::Find::name);
+ }
+ parse_script($File::Find::dir,$_);
+ }
+ }
+ }
+ },
+ # remove dirs-to-ignore in preprocess step
+ preprocess=>sub{grep ! (-d and exists($ignoredirs{$_})), at _}},
+ "class");
+}
+
+# print the classes and the places referencing them to stdout (alphanum sorted)
+sub dump_class_refs {
+ foreach my $class (sort keys %config_classes) {
+ print "class: $class\n";
+ foreach my $file (sort @{$config_classes{$class}}) {
+ print " $file\n";
+ }
+ }
+}
+
+die "run this script within the fai config space" unless (-d "class");
+
+scan_class();
+scan_files();
+scan_scripts();
+scan_hooks();
+scan_dir("debconf","disk_config");
+scan_package_config();
+
+dump_class_refs();
Property changes on: people/eartoast/addons/class-reference/fai-classes-config
___________________________________________________________________
Name: svn:executable
+ *
More information about the Fai-commit
mailing list