BasePkgPath.pm 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  1. # ex:ts=8 sw=4:
  2. # $OpenBSD: BasePkgPath.pm,v 1.6 2014/12/07 15:18:50 espie Exp $
  3. #
  4. # Copyright (c) 2010-2013 Marc Espie <espie@openbsd.org>
  5. #
  6. # Permission to use, copy, modify, and distribute this software for any
  7. # purpose with or without fee is hereby granted, provided that the above
  8. # copyright notice and this permission notice appear in all copies.
  9. #
  10. # THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
  16. # OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. use strict;
  18. use warnings;
  19. use DPB::Util;
  20. # Handles PkgPath;
  21. # all this code is *seriously* dependent on unique objects
  22. # everything is done to normalize PkgPaths, so that we have
  23. # one pkgpath object for each distinct flavor/subpackage combination
  24. package DPB::BasePkgPath;
  25. my $cache = {};
  26. sub create
  27. {
  28. my ($class, $fullpkgpath) = @_;
  29. # subdivide into flavors/multi
  30. # XXX we want to preserve empty fields
  31. my @list = split /,/, $fullpkgpath, -1;
  32. my $pkgpath = shift @list;
  33. my $o = bless { p => $pkgpath} , $class;
  34. $o->init;
  35. for my $v (@list) {
  36. if ($v =~ m/^\-/) {
  37. DPB::Util->die("$fullpkgpath has >1 multi")
  38. if exists $o->{m};
  39. if ($v eq '-main') {
  40. $o->{m} = undef;
  41. } else {
  42. $o->{m} = $v;
  43. }
  44. } else {
  45. # XXX rely on stuff existing, no need to spring
  46. # an empty hash into existence
  47. if ($v eq '') {
  48. $o->{f} = undef if !exists $o->{f};
  49. } else {
  50. $o->{f}{$v} = 1;
  51. }
  52. }
  53. }
  54. return $o;
  55. }
  56. # cache just once, put into standard order, so that we don't
  57. # create different objects for path,f1,f2 and path,f2,f1
  58. sub normalize
  59. {
  60. my $o = shift;
  61. my $fullpkgpath = $o->fullpkgpath;
  62. return $cache->{$fullpkgpath} //= $o;
  63. }
  64. # actual constructor
  65. sub new
  66. {
  67. my ($class, $fullpkgpath) = @_;
  68. if (defined $cache->{$fullpkgpath}) {
  69. return $cache->{$fullpkgpath};
  70. } else {
  71. return $class->create($fullpkgpath)->normalize;
  72. }
  73. }
  74. sub seen
  75. {
  76. return values %$cache;
  77. }
  78. sub basic_list
  79. {
  80. my $self = shift;
  81. my @list = ($self->{p});
  82. if (exists $self->{f}) {
  83. if (keys %{$self->{f}}) {
  84. push(@list, sort keys %{$self->{f}});
  85. } else {
  86. push(@list, '');
  87. }
  88. }
  89. return @list;
  90. }
  91. sub debug_dump
  92. {
  93. my $self = shift;
  94. return $self->fullpkgpath;
  95. }
  96. # string version, with everything in a standard order
  97. sub fullpkgpath
  98. {
  99. my $self = shift;
  100. my @list = $self->basic_list;
  101. if (defined $self->{m}) {
  102. push(@list, $self->{m});
  103. } elsif (exists $self->{m}) {
  104. push(@list, '-main');
  105. }
  106. return join (',', @list);
  107. }
  108. sub pkgpath
  109. {
  110. my $self = shift;
  111. return $self->{p};
  112. }
  113. sub multi
  114. {
  115. my $self = shift;
  116. if (defined $self->{m}) {
  117. return $self->{m};
  118. } elsif (exists $self->{m}) {
  119. return '-main';
  120. } else {
  121. return undef;
  122. }
  123. }
  124. # without multi. Used by the SUBDIRs code to make sure we get the right
  125. # value for default subpackage.
  126. sub pkgpath_and_flavors
  127. {
  128. my $self = shift;
  129. return join (',', $self->basic_list);
  130. }
  131. sub add_to_subdirlist
  132. {
  133. my ($self, $list) = @_;
  134. $list->{$self->pkgpath_and_flavors} = 1;
  135. }
  136. # XXX
  137. # in the ports tree, when you build with SUBDIR=n/value, you'll
  138. # get all the -multi packages, but with the default flavor.
  139. # we have to strip the flavor part to match the SUBDIR we asked for.
  140. sub compose
  141. {
  142. my ($class, $fullpkgpath, $pseudo) = @_;
  143. my $o = $class->create($fullpkgpath);
  144. if (defined $pseudo->{f}) {
  145. $o->{f} = $pseudo->{f};
  146. } else {
  147. delete $o->{f};
  148. }
  149. return $o->normalize;
  150. }
  151. sub may_create
  152. {
  153. my ($n, $o, $h) = @_;
  154. my $k = $n->fullpkgpath;
  155. if (defined $cache->{$k}) {
  156. $n = $cache->{$k};
  157. } else {
  158. $cache->{$k} = $n;
  159. }
  160. $n->clone_properties($o);
  161. $h->{$n} = $n;
  162. return $n;
  163. }
  164. # XXX
  165. # this is complicated, we want to mark equivalent paths, but we do not want
  166. # to record them as to build by default, but if we're asking for explicit
  167. # subdirs, we have to deal with them.
  168. # so, create $h that holds all paths, and selectively copy the ones from
  169. # todo, along with the set in $want that corresponds to the subdirlist.
  170. sub handle_equivalences
  171. {
  172. my ($class, $state, $todo, $want) = @_;
  173. my $h = {};
  174. my $result = {};
  175. for my $v (values %$todo) {
  176. $h->{$v} = $v;
  177. $result->{$v} = $v;
  178. $v->handle_default_flavor($h, $state);
  179. $v->handle_default_subpackage($h, $state);
  180. }
  181. $class->equates($h);
  182. if (defined $want) {
  183. for my $v (values %$h) {
  184. if ($want->{$v->fullpkgpath}) {
  185. $result->{$v} = $v;
  186. }
  187. }
  188. }
  189. return $result;
  190. }
  191. sub zap_default
  192. {
  193. my ($self, $subpackage) = @_;
  194. return $self unless defined $subpackage and defined $self->multi;
  195. if ($subpackage eq $self->multi) {
  196. my $o = bless {p => $self->{p}}, ref($self);
  197. if (defined $self->{f}) {
  198. $o->{f} = $self->{f};
  199. }
  200. return $o->normalize;
  201. } else {
  202. return $self;
  203. }
  204. }
  205. sub handle_default_flavor
  206. {
  207. my ($self, $h, $state) = @_;
  208. if (!defined $self->{f}) {
  209. my $m = bless { p => $self->{p},
  210. f => $self->flavor}, ref($self);
  211. if (exists $self->{m}) {
  212. $m->{m} = $self->{m};
  213. }
  214. $m = $m->may_create($self, $h);
  215. $m->simplifies_to($self, $state);
  216. $m->handle_default_subpackage($h, $state);
  217. }
  218. }
  219. # default subpackage leads to pkgpath,-default = pkgpath
  220. sub handle_default_subpackage
  221. {
  222. my ($self, $h, $state) = @_;
  223. my $m = $self->zap_default($self->subpackage);
  224. if ($m ne $self) {
  225. $m = $m->may_create($self, $h);
  226. $self->simplifies_to($m, $state);
  227. $m->handle_default_flavor($h, $state);
  228. }
  229. }
  230. 1;