Fields.pm 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. package Dpkg::Fields;
  2. use strict;
  3. use warnings;
  4. use Exporter;
  5. use Dpkg::Deps qw(@src_dep_fields @pkg_dep_fields);
  6. our @ISA = qw(Exporter);
  7. our @EXPORT_OK = qw(capit set_field_importance sort_field_by_importance
  8. %control_src_fields %control_pkg_fields $control_src_field_regex
  9. $control_pkg_field_regex);
  10. our %EXPORT_TAGS = ('list' => [qw(%control_src_fields %control_pkg_fields
  11. $control_src_field_regex $control_pkg_field_regex)]);
  12. # Some variables (list of fields)
  13. our %control_src_fields;
  14. our %control_pkg_fields;
  15. $control_src_fields{$_} = 1 foreach (qw(Bugs Dm-Upload-Allowed
  16. Homepage Origin Maintainer Priority Section Source Standards-Version
  17. Uploaders Vcs-Browser Vcs-Arch Vcs-Bzr Vcs-Cvs Vcs-Darcs Vcs-Git Vcs-Hg
  18. Vcs-Mtn Vcs-Svn));
  19. $control_src_fields{$_} = 1 foreach (@src_dep_fields);
  20. $control_pkg_fields{$_} = 1 foreach (qw(Architecture Bugs Description Essential
  21. Homepage Installer-Menu-Item Kernel-Version Package Package-Type
  22. Priority Section Subarchitecture Tag));
  23. $control_pkg_fields{$_} = 1 foreach (@pkg_dep_fields);
  24. our $control_src_field_regex = "(?:" . join("|", keys %control_src_fields) . ")";
  25. our $control_pkg_field_regex = "(?:" . join("|", keys %control_pkg_fields) . ")";
  26. # Some functions
  27. sub capit {
  28. my @pieces = map { ucfirst(lc) } split /-/, $_[0];
  29. return join '-', @pieces;
  30. }
  31. my %fieldimps;
  32. sub set_field_importance(@)
  33. {
  34. my @fields = @_;
  35. my $i = 1;
  36. grep($fieldimps{$_} = $i++, @fields);
  37. }
  38. sub sort_field_by_importance($$)
  39. {
  40. my ($a, $b) = @_;
  41. if (defined $fieldimps{$a} && defined $fieldimps{$b}) {
  42. $fieldimps{$a} <=> $fieldimps{$b};
  43. } elsif (defined($fieldimps{$a})) {
  44. -1;
  45. } elsif (defined($fieldimps{$b})) {
  46. 1;
  47. } else {
  48. $a cmp $b;
  49. }
  50. }
  51. package Dpkg::Fields::Object;
  52. =head1 OTHER OBJECTS
  53. =head2 Dpkg::Fields::Object
  54. This object is used to tie a hash. It implements hash-like functions by
  55. normalizing the name of fields received in keys (using
  56. Dpkg::Fields::capit). It also stores the order in which fields have been
  57. added in order to be able to dump them in the same order.
  58. You can also dump the content of the hash with tied(%hash)->dump($fh).
  59. =cut
  60. use Tie::Hash;
  61. our @ISA = qw(Tie::ExtraHash Tie::Hash);
  62. use Dpkg::ErrorHandling qw(internerr syserr);
  63. # Import capit
  64. Dpkg::Fields->import('capit', 'sort_field_by_importance');
  65. # $self->[0] is the real hash
  66. # $self->[1] is an array containing the ordered list of keys
  67. =head2 Dpkg::Fields::Object->new()
  68. Return a reference to a tied hash implementing storage of simple
  69. "field: value" mapping as used in many Debian-specific files.
  70. =cut
  71. sub new {
  72. my $hash = {};
  73. tie %{$hash}, 'Dpkg::Fields::Object';
  74. return $hash;
  75. }
  76. sub TIEHASH {
  77. my $class = shift;
  78. return bless [{}, []], $class;
  79. }
  80. sub FETCH {
  81. my ($self, $key) = @_;
  82. $key = capit($key);
  83. return $self->[0]->{$key} if exists $self->[0]->{$key};
  84. return undef;
  85. }
  86. sub STORE {
  87. my ($self, $key, $value) = @_;
  88. $key = capit($key);
  89. if (not exists $self->[0]->{$key}) {
  90. push @{$self->[1]}, $key;
  91. }
  92. $self->[0]->{$key} = $value;
  93. }
  94. sub EXISTS {
  95. my ($self, $key) = @_;
  96. $key = capit($key);
  97. return exists $self->[0]->{$key};
  98. }
  99. sub DELETE {
  100. my ($self, $key) = @_;
  101. $key = capit($key);
  102. if (exists $self->[0]->{$key}) {
  103. delete $self->[0]->{$key};
  104. @{$self->[1]} = grep { $_ ne $key } @{$self->[1]};
  105. return 1;
  106. } else {
  107. return 0;
  108. }
  109. }
  110. sub FIRSTKEY {
  111. my $self = shift;
  112. foreach (@{$self->[1]}) {
  113. return $_ if exists $self->[0]->{$_};
  114. }
  115. }
  116. sub NEXTKEY {
  117. my ($self, $last) = @_;
  118. my $found = 0;
  119. foreach (@{$self->[1]}) {
  120. if ($found) {
  121. return $_ if exists $self->[0]->{$_};
  122. } else {
  123. $found = 1 if $_ eq $last;
  124. }
  125. }
  126. return undef;
  127. }
  128. sub dump {
  129. my ($self, $fh) = @_;
  130. foreach (@{$self->[1]}) {
  131. if (exists $self->[0]->{$_}) {
  132. print $fh "$_: " . $self->[0]->{$_} . "\n";
  133. }
  134. }
  135. }
  136. sub output {
  137. my ($self, $fh, $substvars) = @_;
  138. # Add substvars to refer to other fields
  139. if (defined($substvars)) {
  140. foreach my $f (keys %{$self->[0]}) {
  141. $substvars->set("F:$f", $self->[0]->{$f});
  142. }
  143. }
  144. for my $f (sort sort_field_by_importance keys %{$self->[0]}) {
  145. my $v = $self->[0]->{$f};
  146. if (defined($substvars)) {
  147. $v = $substvars->substvars($v);
  148. }
  149. $v =~ m/\S/ || next; # delete whitespace-only fields
  150. $v =~ m/\n\S/ &&
  151. internerr(_g("field %s has newline then non whitespace >%s<"),
  152. $f, $v);
  153. $v =~ m/\n[ \t]*\n/ &&
  154. internerr(_g("field %s has blank lines >%s<"), $f, $v);
  155. $v =~ m/\n$/ &&
  156. internerr(_g("field %s has trailing newline >%s<"), $f, $v);
  157. if (defined($substvars)) {
  158. $v =~ s/,[\s,]*,/,/g;
  159. $v =~ s/^\s*,\s*//;
  160. $v =~ s/\s*,\s*$//;
  161. }
  162. $v =~ s/\$\{\}/\$/g;
  163. print $fh "$f: $v\n" || syserr(_g("write error on control data"));
  164. }
  165. }
  166. 1;