NICBase.pm 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222
  1. package NIC::NICBase;
  2. use strict;
  3. use warnings;
  4. use NIC::NICBase::File;
  5. use NIC::NICBase::Directory;
  6. use NIC::NICBase::Symlink;
  7. use List::Util qw(first);
  8. sub new {
  9. my $proto = shift;
  10. my $class = ref($proto) || $proto;
  11. my $self = {};
  12. $self->{NAME} = shift;
  13. $self->{CONTENTS} = [];
  14. $self->{VARIABLES} = {};
  15. $self->{CONSTRAINTS} = {};
  16. $self->{PROMPTS} = [];
  17. $self->{IGNORED_VARS} = {};
  18. bless($self, $class);
  19. return $self;
  20. }
  21. sub _fileClass { "NIC::NICBase::File"; }
  22. sub _directoryClass { "NIC::NICBase::Directory"; }
  23. sub _symlinkClass { "NIC::NICBase::Symlink"; }
  24. sub _getContentWithoutCreate {
  25. my $self = shift;
  26. my $name = shift;
  27. return first { $_->name eq $name } @{$self->{CONTENTS}};
  28. }
  29. sub _getContent {
  30. my $self = shift;
  31. my $ref = $self->_getContentWithoutCreate(@_);
  32. return $ref if $ref;
  33. $ref = NIC::NICType->new($self, @_);
  34. push(@{$self->{CONTENTS}}, $ref);
  35. return $ref;
  36. }
  37. sub _generate {
  38. my $self = shift;
  39. my $class = shift;
  40. my $name = shift;
  41. my $ref = $self->_getContent($name, @_);
  42. if($ref->type == NIC::NICType::TYPE_UNKNOWN) {
  43. $class->take($ref, @_);
  44. }
  45. return $ref;
  46. }
  47. sub registerDirectory {
  48. my $self = shift;
  49. my $dir = $self->_generate($self->_directoryClass, @_);
  50. return $dir;
  51. }
  52. sub registerFile {
  53. my $self = shift;
  54. my $file = $self->_generate($self->_fileClass, @_);
  55. return $file;
  56. }
  57. sub registerSymlink {
  58. my $self = shift;
  59. my $symlink = $self->_generate($self->_symlinkClass, @_);
  60. return $symlink;
  61. }
  62. sub registerPrompt {
  63. my($self, $key, $prompt, $default) = @_;
  64. push(@{$self->{PROMPTS}}, {
  65. name => $key,
  66. prompt => $prompt,
  67. default => $default
  68. });
  69. }
  70. sub registerFileConstraint {
  71. my $self = shift;
  72. my $filename = shift;
  73. my $constraint = shift;
  74. $self->_getContent($filename)->addConstraint($constraint);
  75. }
  76. sub resolveSymlinks {
  77. my $self = shift;
  78. for(@{$self->{CONTENTS}}) {
  79. next unless $_->type == NIC::NICType::TYPE_SYMLINK;
  80. next if $_->target_type != NIC::NICType::TYPE_UNKNOWN;
  81. my $ref = $self->_getContentWithoutCreate($_->target);
  82. $_->target($ref) if $ref;
  83. }
  84. }
  85. sub variable: lvalue {
  86. my $self = shift;
  87. my $key = shift;
  88. $self->{VARIABLES}->{$key};
  89. }
  90. sub name {
  91. my $self = shift;
  92. if(@_) { $self->{NAME} = shift; }
  93. return $self->{NAME} // "(unnamed template)";
  94. }
  95. sub prompts {
  96. my $self = shift;
  97. return @{$self->{PROMPTS}};
  98. }
  99. sub addConstraint {
  100. my $self = shift;
  101. my $constraint = shift;
  102. $self->{CONSTRAINTS}->{$constraint} = 1;
  103. }
  104. sub removeConstraint {
  105. my $self = shift;
  106. my $constraint = shift;
  107. delete $self->{CONSTRAINTS}->{$constraint};
  108. }
  109. sub _constraintMatch {
  110. my $self = shift;
  111. my $constraint = shift;
  112. my $negated = 0;
  113. if(substr($constraint, 0, 1) eq "!") {
  114. $negated = 1;
  115. substr($constraint, 0, 1, "");
  116. }
  117. return 0 if(!$negated && (!defined $self->{CONSTRAINTS}->{$constraint} || $self->{CONSTRAINTS}->{$constraint} != 1));
  118. return 0 if($negated && (defined $self->{CONSTRAINTS}->{$constraint} || $self->{CONSTRAINTS}->{$constraint} != 0));
  119. return 1;
  120. }
  121. sub _meetsConstraints {
  122. my $self = shift;
  123. my $content = shift;
  124. foreach ($content->constraints) {
  125. return 0 if !$self->_constraintMatch($_);
  126. }
  127. return 1;
  128. }
  129. sub substituteVariables {
  130. my $self = shift;
  131. my $line = shift;
  132. foreach my $key (keys %{$self->{VARIABLES}}) {
  133. my $value = $self->{VARIABLES}->{$key};
  134. $line =~ s/\@\@$key\@\@/$value/g;
  135. }
  136. return $line;
  137. }
  138. sub ignoreVariable {
  139. my $self = shift;
  140. my $var = shift;
  141. $self->{IGNORED_VARS}->{$var}++;
  142. }
  143. sub variableIgnored {
  144. my $self = shift;
  145. my $var = shift;
  146. return defined $self->{IGNORED_VARS}->{$var};
  147. }
  148. sub prebuild {
  149. }
  150. sub postbuild {
  151. }
  152. sub exec {
  153. return 1;
  154. }
  155. sub build {
  156. my $self = shift;
  157. my $dir = shift;
  158. mkdir($dir) or die "Failed to create the directory '$dir': $!\n";
  159. chdir($dir) or die $!;
  160. $self->prebuild();
  161. foreach my $content (sort { $a->type <=> $b->type } (@{$self->{CONTENTS}})) {
  162. next if $content->type == NIC::NICType::TYPE_UNKNOWN;
  163. next if !$self->_meetsConstraints($content);
  164. $content->create();
  165. }
  166. $self->postbuild();
  167. }
  168. sub dumpPreamble {
  169. my $self = shift;
  170. my $preamblefn = shift;
  171. open(my $pfh, ">", $preamblefn);
  172. print $pfh "name \"".$self->{NAME}."\"",$/;
  173. foreach my $prompt (@{$self->{PROMPTS}}) {
  174. print $pfh "prompt ".$prompt->{name}." \"".$prompt->{prompt}."\"";
  175. print $pfh " \"".$prompt->{default}."\"" if defined $prompt->{default};
  176. print $pfh $/;
  177. }
  178. foreach my $filename (keys %{$self->{FILES}}) {
  179. my $file = $self->{FILES}->{$filename};
  180. if(!defined $file->{constraints}) {
  181. next;
  182. }
  183. foreach (@{$file->{constraints}}) {
  184. print $pfh "constrain file \"".$filename."\" to ".$_,$/
  185. }
  186. }
  187. close($pfh);
  188. }
  189. 1;