����JFIFXX�����    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222����"��4�� ���,�PG"Z_�4�˷����kjز�Z�,F+��_z�,�© �����zh6�٨�ic�fu���#ډb���_�N�?��wQ���5-�~�I���8����TK<5o�Iv-�����k�_U_�����~b�M��d����Ӝ�U�Hh��?]��E�w��Q���k�{��_}qFW7HTՑ��Y��F�?_�'ϔ��_�Ջt��=||I ��6�έ"�����D���/[�k�9���Y�8ds|\���Ҿp6�Ҵ���]��.����6�z<�v��@]�i%��$j��~�g��J>��no����pM[me�i$[����s�o�ᘨ�˸ nɜG-�ĨU�ycP�3.DB�li�;��hj���x7Z^�N�h������N3u{�:j�x�힞��#M&��jL P@_���� P��&��o8������9�����@Sz6�t7#O�ߋ �s}Yf�T���lmr����Z)'N��k�۞p����w\�Tȯ?�8`�O��i{wﭹW�[�r�� ��Q4F�׊���3m&L�=��h3����z~��#�\�l :�F,j@�� ʱ�wQT����8�"kJO���6�֚l����}���R�>ډK���]��y����&����p�}b��;N�1�m�r$�|��7�>e�@B�TM*-iH��g�D�)� E�m�|�ؘbҗ�a��Ҿ����t4���o���G��*oCN�rP���Q��@z,|?W[0�����:�n,jWiE��W��$~/�hp\��?��{(�0���+�Y8rΟ�+����>S-S����VN;�}�s?.����� w�9��˟<���Mq4�Wv'��{)0�1mB��V����W[�����8�/<� �%���wT^�5���b��)iM� pg�N�&ݝ��VO~�q���u���9� ����!��J27����$O-���! �:�%H��� ـ����y�ΠM=t{!S�� oK8������t<����è:a������[�����ա�H���~��w��Qz`�po�^ ����Q��n� �,uu�C�$ ^���,������8�#��:�6��e�|~���!�3�3.�\0��q��o�4`.|� ����y�Q�`~;�d�ׯ,��O�Zw�������`73�v�܋�<���Ȏ�� ـ4k��5�K�a�u�=9Yd��$>x�A�&�� j0� ���vF��� Y�|�y��� ~�6�@c��1vOp�Ig����4��l�OD���L����� R���c���j�_�uX6��3?nk��Wy�f;^*B� ��@�~a�`��Eu������+���6�L��.ü>��}y���}_�O�6�͐�:�YrG�X��kG�����l^w���~㒶sy��Iu�!� W ��X��N�7BV��O��!X�2����wvG�R�f�T#�����t�/?���%8�^�W�aT��G�cL�M���I��(J����1~�8�?aT ���]����AS�E��(��*E}� 2��#I/�׍qz��^t�̔���b�Yz4x���t�){ OH��+(E��A&�N�������XT��o��"�XC��'���)}�J�z�p� ��~5�}�^����+�6����w��c��Q�|Lp�d�H��}�(�.|����k��c4^�"�����Z?ȕ ��a<�L�!039C� �Eu�C�F�Ew�ç ;�n?�*o���B�8�bʝ���'#Rqf���M}7����]����s2tcS{�\icTx;�\��7K���P���ʇ Z O-��~��c>"��?�������P��E��O�8��@�8��G��Q�g�a�Վ���󁶠�䧘��_%#r�>�1�z�a��eb��qcPѵ��n���#L��� =��׀t� L�7�`��V���A{�C:�g���e@�w1 Xp3�c3�ġ����p��M"'-�@n4���fG��B3�DJ�8[Jo�ߐ���gK)ƛ��$���� ���8�3�����+���� �����6�ʻ���� ���S�kI�*KZlT _`���?��K����QK�d����B`�s}�>���`��*�>��,*@J�d�oF*����弝��O}�k��s��]��y�ߘ��c1G�V���<=�7��7����6�q�PT��tXԀ�!9*4�4Tހ3XΛex�46���Y��D ����� �BdemDa����\�_l,��G�/���֌7���Y�](�xTt^%�GE�����4�}bT���ڹ�����;Y)���B�Q��u��>J/J �⮶.�XԄ��j�ݳ�+E��d ��r�5�_D�1 ��o�� �B�x�΢�#���<��W�����8���R6�@g�M�.��� dr�D��>(otU��@x=��~v���2� ӣ�d�oBd��3�eO�6�㣷�����ݜ6��6Y��Qz`��S��{���\P�~z m5{J/L��1������<�e�ͅPu�b�]�ϔ���'������f�b� Zpw��c`"��i���BD@:)ִ�:�]��hv�E�w���T�l��P���"Ju�}��وV J��G6��. J/�Qgl߭�e�����@�z�Zev2u�)]կ�����7x���s�M�-<ɯ�c��r�v�����@��$�ޮ}lk���a���'����>x��O\�ZFu>�����ck#��&:��`�$�ai�>2Δ����l���oF[h��lE�ܺ�Πk:)���`�� $[6�����9�����kOw�\|���8}������ބ:��񶐕��I�A1/�=�2[�,�!��.}gN#�u����b��� ~��݊��}34q����d�E��Lc��$��"�[q�U�硬g^��%B �z���r�pJ�ru%v\h1Y�ne`ǥ:g���pQM~�^�Xi� ��`S�:V29.�P���V�?B�k�� AEvw%�_�9C�Q����wKekPؠ�\�;Io d�{ ߞo�c1eP����\� `����E=���@K<�Y���eڼ�J���w����{av�F�'�M�@/J��+9p���|]�����Iw &`��8���&M�hg��[�{��Xj��%��Ӓ�$��(����ʹN���<>�I���RY���K2�NPlL�ɀ)��&e����B+ь����( � �JTx���_?EZ� }@ 6�U���뙢ط�z��dWI�n` D����噥�[��uV��"�G&Ú����2g�}&m��?ċ�"����Om#��������� ��{�ON��"S�X��Ne��ysQ���@Fn��Vg���dX�~nj�]J�<�K]:��FW��b�������62�=��5f����JKw��bf�X�55��~J �%^����:�-�QIE��P��v�nZum� z � ~ə ���� ���ة����;�f��\v���g�8�1��f24;�V���ǔ�)����9���1\��c��v�/'Ƞ�w�������$�4�R-��t���� e�6�/�ġ �̕Ecy�J���u�B���<�W�ַ~�w[B1L۲�-JS΂�{���΃������A��20�c#��@ 0!1@AP"#2Q`$3V�%45a6�FRUq��� ����^7ׅ,$n�������+��F�`��2X'��0vM��p�L=������5��8������u�p~���.�`r�����\���O��,ư�0oS ��_�M�����l���4�kv\JSd���x���SW�<��Ae�IX����������$I���w�:S���y���›R��9�Q[���,�5�;�@]�%���u�@ *ro�lbI �� ��+���%m:�͇ZV�����u�̉����θau<�fc�.����{�4Ա� �Q����*�Sm��8\ujqs]{kN���)qO�y�_*dJ�b�7���yQqI&9�ԌK!�M}�R�;������S�T���1���i[U�ɵz�]��U)V�S6���3$K{�ߊ<�(� E]Զ[ǼENg�����'�\?#)Dkf��J���o��v���'�%ƞ�&K�u�!��b�35LX�Ϸ��63$K�a�;�9>,R��W��3�3� d�JeTYE.Mϧ��-�o�j3+y��y^�c�������VO�9NV\nd�1 ��!͕_)a�v;����թ�M�lWR1��)El��P;��yوÏ�u 3�k�5Pr6<�⒲l�!˞*��u־�n�!�l:����UNW ��%��Chx8vL'��X�@��*��)���̮��ˍ��� ���D-M�+J�U�kvK����+�x8��cY������?�Ԡ��~3mo��|�u@[XeY�C�\Kp�x8�oC�C�&����N�~3-H���� ��MX�s�u<`���~"WL��$8ξ��3���a�)|:@�m�\���^�`�@ҷ)�5p+��6���p�%i)P M���ngc�����#0Aruz���RL+xSS?���ʮ}()#�t��mˇ!��0}}y����<�e� �-ή�Ԩ��X������ MF���ԙ~l L.3���}�V뽺�v�����멬��Nl�)�2����^�Iq��a��M��qG��T�����c3#������3U�Ǎ���}��לS�|qa��ڃ�+���-��2�f����/��bz��ڐ�� �ݼ[2�ç����k�X�2�* �Z�d���J�G����M*9W���s{��w���T��x��y,�in�O�v��]���n����P�$�JB@=4�OTI�n��e�22a\����q�d���%�$��(���:���: /*�K[PR�fr\nڙdN���F�n�$�4�[�� U�zƶ����� �mʋ���,�ao�u 3�z� �x��Kn����\[��VFmbE;�_U��&V�Gg�]L�۪&#n%�$ɯ�dG���D�TI=�%+AB�Ru#��b4�1�»x�cs�YzڙJG��f��Il��d�eF'T� iA��T���uC�$����Y��H?����[!G`}���ͪ� �纤Hv\������j�Ex�K���!���OiƸ�Yj�+u-<���'q����uN�*�r\��+�]���<�wOZ.fp�ێ��,-*)V?j-kÊ#�`�r��dV����(�ݽBk�����G�ƛk�QmUڗe��Z���f}|����8�8��a���i��3'J�����~G_�^���d�8w������ R�`(�~�.��u���l�s+g�bv���W���lGc}��u���afE~1�Ue������Z�0�8�=e�� f@/�jqEKQQ�J��oN��J���W5~M>$6�Lt�;$ʳ{���^��6�{����v6���ķܰg�V�cnn �~z�x�«�,2�u�?cE+Ș�H؎�%�Za�)���X>uW�Tz�Nyo����s���FQƤ��$��*�&�LLXL)�1�" L��eO��ɟ�9=���:t��Z���c��Ž���Y?�ӭV�wv�~,Y��r�ۗ�|�y��GaF�����C�����.�+� ���v1���fήJ�����]�S��T��B��n5sW}y�$��~z�'�c ��8 ��� ,! �p��VN�S��N�N�q��y8z˱�A��4��*��'������2n<�s���^ǧ˭P�Jޮɏ�U�G�L�J�*#��<�V��t7�8����TĜ>��i}K%,���)[��z�21z ?�N�i�n1?T�I�R#��m-�����������������1����lA�`��fT5+��ܐ�c�q՝��ʐ��,���3�f2U�եmab��#ŠdQ�y>\��)�SLY����w#��.���ʑ�f��� ,"+�w�~�N�'�c�O�3F�������N<���)j��&��,-� �љ���֊�_�zS���TǦ����w�>��?�������n��U仆�V���e�����0���$�C�d���rP �m�׈e�Xm�Vu� �L��.�bֹ��� �[Դaզ���*��\y�8�Է:�Ez\�0�Kq�C b��̘��cө���Q��=0Y��s�N��S.���3.���O�o:���#���v7�[#߫ ��5�܎�L���Er4���9n��COWlG�^��0k�%<���ZB���aB_���������'=��{i�v�l�$�uC���mƎҝ{�c㱼�y]���W�i ��ߧc��m�H� m�"�"�����;Y�ߝ�Z�Ǔ�����:S#��|}�y�,/k�Ld� TA�(�AI$+I3��;Y*���Z��}|��ӧO��d�v��..#:n��f>�>���ȶI�TX��� 8��y����"d�R�|�)0���=���n4��6ⲑ�+��r<�O�܂~zh�z����7ܓ�HH�Ga롏���nCo�>������a ���~]���R���̲c?�6(�q�;5%� |�uj�~z8R=X��I�V=�|{v�Gj\gc��q����z�؋%M�ߍ����1y��#��@f^���^�>N�����#x#۹��6�Y~�?�dfPO��{��P�4��V��u1E1J �*|���%���JN��`eWu�zk M6���q t[�� ��g�G���v��WIG��u_ft����5�j�"�Y�:T��ɐ���*�;� e5���4����q$C��2d�}���� _S�L#m�Yp��O�.�C�;��c����Hi#֩%+) �Ӎ��ƲV���SYź��g |���tj��3�8���r|���V��1#;.SQ�A[���S������#���`n�+���$��$I �P\[�@�s��(�ED�z���P��])8�G#��0B��[ى��X�II�q<��9�~[Z멜�Z�⊔IWU&A>�P~�#��dp<�?����7���c��'~���5 ��+$���lx@�M�dm��n<=e�dyX��?{�|Aef ,|n3�<~z�ƃ�uۧ�����P��Y,�ӥQ�*g�#먙R�\���;T��i,��[9Qi歉����c>]9�� ��"�c��P�� �Md?٥��If�ت�u��k��/����F��9�c*9��Ǎ:�ØF���z�n*�@|I�ށ9����N3{'��[�'ͬ�Ҳ4��#}��!�V� Fu��,�,mTIk���v C�7v���B�6k�T9��1�*l� '~��ƞF��lU��'�M ����][ΩũJ_�{�i�I�n��$���L�� j��O�dx�����kza۪��#�E��Cl����x˘�o�����V���ɞ�ljr��)�/,�߬h�L��#��^��L�ф�,íMƁe�̩�NB�L�����iL����q�}��(��q��6IçJ$�W�E$��:������=#����(�K�B����zђ <��K(�N�۫K�w��^O{!����)�H���>x�������lx�?>Պ�+�>�W���,Ly!_�D���Ō�l���Q�!�[ �S����J��1��Ɛ�Y}��b,+�Lo�x�ɓ)����=�y�oh�@�꥟/��I��ѭ=��P�y9��� �ۍYӘ�e+�p�Jnϱ?V\SO%�(�t� ���=?MR�[Ș�����d�/ ��n�l��B�7j� ��!�;ӥ�/�[-���A�>�dN�sLj ��,ɪv��=1c�.SQ�O3�U���ƀ�ܽ�E����������̻��9G�ϷD�7(�}��Ävӌ\�y�_0[w ���<΍>����a_��[0+�L��F.�޺��f�>oN�T����q;���y\��bՃ��y�jH�<|q-eɏ�_?_9+P���Hp$�����[ux�K w�Mw��N�ی'$Y2�=��q���KB��P��~������Yul:�[<����F1�2�O���5=d����]Y�sw:���Ϯ���E��j,_Q��X��z`H1,#II ��d�wr��P˂@�ZJV����y$�\y�{}��^~���[:N����ߌ�U�������O��d�����ؾe��${p>G��3c���Ė�lʌ�� ת��[��`ϱ�-W����dg�I��ig2��� ��}s ��ؤ(%#sS@���~���3�X�nRG�~\jc3�v��ӍL��M[JB�T��s3}��j�Nʖ��W����;7��ç?=X�F=-�=����q�ߚ���#���='�c��7���ڑW�I(O+=:uxq�������������e2�zi+�kuG�R��������0�&e�n���iT^J����~\jy���p'dtG��s����O��3����9* �b#Ɋ�� p������[Bws�T�>d4�ۧs���nv�n���U���_�~,�v����ƜJ1��s�� �QIz��)�(lv8M���U=�;����56��G���s#�K���MP�=��LvyGd��}�VwWBF�'�à �?MH�U�g2�� ����!�p�7Q��j��ڴ����=��j�u��� Jn�A s���uM������e��Ɔ�Ҕ�!)'��8Ϣ�ٔ��ޝ(��Vp���צ֖d=�IC�J�Ǡ{q������kԭ�߸���i��@K����u�|�p=..�*+����x�����z[Aqġ#s2a�Ɗ���RR�)*HRsi�~�a &f��M��P����-K�L@��Z��Xy�'x�{}��Zm+���:�)�) IJ�-i�u���� ���ܒH��'�L(7�y�GӜq���� j��� 6ߌg1�g�o���,kر���tY�?W,���p���e���f�OQS��!K�۟cҒA�|ս�j�>��=⬒��˧L[�� �߿2JaB~R��u�:��Q�] �0H~���]�7��Ƽ�I���(}��cq '�ήET���q�?f�ab���ӥvr� �)o��-Q��_'����ᴎo��K������;��V���o��%���~OK ����*��b�f:���-ťIR��`B�5!RB@���ï�� �u �̯e\�_U�_������� g�ES��3�������QT��a����x����U<~�c?�*�#]�MW,[8O�a�x��]�1bC|踤�P��lw5V%�)�{t�<��d��5���0i�XSU��m:��Z�┵�i�"��1�^B�-��P�hJ��&)O��*�D��c�W��vM��)����}���P��ܗ-q����\mmζZ-l@�}��a��E�6��F�@��&Sg@���ݚ�M����� ȹ 4����#p�\H����dYDo�H���"��\��..R�B�H�z_�/5˘����6��KhJR��P�mƶi�m���3�,#c�co��q�a)*Pt����R�m�k�7x�D�E�\Y�閣_X�<���~�)���c[[�BP����6�Yq���S��0����%_����;��Àv�~�| VS؇ ��'O0��F0��\���U�-�d@�����7�SJ*z��3n��y��P����O���������m�~�P�3|Y��ʉr#�C�<�G~�.,! ���bqx���h~0=��!ǫ�jy����l�O,�[B��~��|9��ٱ����Xly�#�i�B��g%�S��������tˋ���e���ې��\[d�t)��.+u�|1 ������#�~Oj����hS�%��i.�~X���I�H�m��0n���c�1uE�q��cF�RF�o���7� �O�ꮧ� ���ۛ{��ʛi5�rw?׌#Qn�TW��~?y$��m\�\o����%W� ?=>S�N@�� �Ʈ���R����N�)�r"C�:��:����� �����#��qb��Y�. �6[��2K����2u�Ǧ�HYR��Q�MV��� �G�$��Q+.>�����nNH��q�^��� ����q��mM��V��D�+�-�#*�U�̒ ���p욳��u:�������IB���m���PV@O���r[b= �� ��1U�E��_Nm�yKbN�O���U�}�the�`�|6֮P>�\2�P�V���I�D�i�P�O;�9�r�mAHG�W�S]��J*�_�G��+kP�2����Ka�Z���H�'K�x�W�MZ%�O�YD�Rc+o��?�q��Ghm��d�S�oh�\�D�|:W������UA�Qc yT�q������~^�H��/��#p�CZ���T�I�1�ӏT����4��"�ČZ�����}��`w�#�*,ʹ�� ��0�i��課�Om�*�da��^gJ݅{���l�e9uF#T�ֲ��̲�ٞC"�q���ߍ ոޑ�o#�XZTp����@ o�8��(jd��xw�]�,f���`~�|,s��^����f�1���t��|��m�򸄭/ctr��5s��7�9Q�4�H1꠲BB@l9@���C�����+�wp�xu�£Yc�9��?`@#�o�mH�s2��)�=��2�.�l����jg�9$�Y�S�%*L������R�Y������7Z���,*=�䷘$�������arm�o�ϰ���UW.|�r�uf����IGw�t����Zwo��~5 ��YյhO+=8fF�)�W�7�L9lM�̘·Y���֘YLf�큹�pRF���99.A �"wz��=E\Z���'a� 2��Ǚ�#;�'}�G���*��l��^"q��+2FQ� hj��kŦ��${���ޮ-�T�٭cf�|�3#~�RJ����t��$b�(R��(����r���dx� >U b�&9,>���%E\� Ά�e�$��'�q't��*�א���ެ�b��-|d���SB�O�O��$�R+�H�)�܎�K��1m`;�J�2�Y~9��O�g8=vqD`K[�F)k�[���1m޼c��n���]s�k�z$@��)!I �x՝"v��9=�ZA=`Ɠi �:�E��)`7��vI��}d�YI�_ �o�:ob���o ���3Q��&D&�2=�� �Ά��;>�h����y.*ⅥS������Ӭ�+q&����j|UƧ����}���J0��WW< ۋS�)jQR�j���Ư��rN)�Gű�4Ѷ(�S)Ǣ�8��i��W52���No˓� ۍ%�5brOn�L�;�n��\G����=�^U�dI���8$�&���h��'���+�(������cȁ߫k�l��S^���cƗjԌE�ꭔ��gF���Ȓ��@���}O���*;e�v�WV���YJ\�]X'5��ղ�k�F��b 6R�o՜m��i N�i����>J����?��lPm�U��}>_Z&�KK��q�r��I�D�Չ~�q�3fL�:S�e>���E���-G���{L�6p�e,8��������QI��h��a�Xa��U�A'���ʂ���s�+טIjP�-��y�8ۈZ?J$��W�P� ��R�s�]��|�l(�ԓ��sƊi��o(��S0��Y� 8�T97.�����WiL��c�~�dxc�E|�2!�X�K�Ƙਫ਼�$((�6�~|d9u+�qd�^3�89��Y�6L�.I�����?���iI�q���9�)O/뚅����O���X��X�V��ZF[�یgQ�L��K1���RҖr@v�#��X�l��F���Нy�S�8�7�kF!A��sM���^rkp�jP�DyS$N���q��nxҍ!U�f�!eh�i�2�m���`�Y�I�9r�6� �TF���C}/�y�^���Η���5d�'��9A-��J��>{�_l+�`��A���[�'��յ�ϛ#w:݅�%��X�}�&�PSt�Q�"�-��\縵�/����$Ɨh�Xb�*�y��BS����;W�ջ_mc�����vt?2}1�;qS�d�d~u:2k5�2�R�~�z+|HE!)�Ǟl��7`��0�<�,�2*���Hl-��x�^����'_TV�gZA�'j� ^�2Ϊ��N7t�����?w�� �x1��f��Iz�C-Ȗ��K�^q�;���-W�DvT�7��8�Z�������� hK�(P:��Q- �8�n�Z���܃e貾�<�1�YT<�,�����"�6{/ �?�͟��|1�:�#g��W�>$����d��J��d�B��=��jf[��%rE^��il:��B���x���Sּ�1հ��,�=��*�7 fcG��#q� �eh?��2�7�����,�!7x��6�n�LC�4x��},Geǝ�tC.��vS �F�43��zz\��;QYC,6����~;RYS/6���|2���5���v��T��i����������mlv��������&� �nRh^ejR�LG�f���? �ۉҬܦƩ��|��Ȱ����>3����!v��i�ʯ�>�v��オ�X3e���_1z�Kȗ\<������!�8���V��]��?b�k41�Re��T�q��mz��TiOʦ�Z��Xq���L������q"+���2ۨ��8}�&N7XU7Ap�d�X��~�׿��&4e�o�F��� �H����O���č�c�� 懴�6���͉��+)��v;j��ݷ�� �UV�� i��� j���Y9GdÒJ1��詞�����V?h��l����l�cGs�ځ�������y�Ac�����\V3�? �� ܙg�>qH�S,�E�W�[�㺨�uch�⍸�O�}���a��>�q�6�n6����N6�q������N ! 1AQaq�0@����"2BRb�#Pr���3C`��Scst���$4D���%Td�� ?���N����a��3��m���C���w��������xA�m�q�m���m������$����4n淿t'��C"w��zU=D�\R+w�p+Y�T�&�պ@��ƃ��3ޯ?�Aﶂ��aŘ���@-�����Q�=���9D��ռ�ѻ@��M�V��P��܅�G5�f�Y<�u=,EC)�<�Fy'�"�&�չ�X~f��l�KԆV��?�� �W�N����=(� �;���{�r����ٌ�Y���h{�١������jW����P���Tc�����X�K�r��}���w�R��%��?���E��m�� �Y�q|����\lEE4���r���}�lsI�Y������f�$�=�d�yO����p�����yBj8jU�o�/�S��?�U��*������ˍ�0������u�q�m [�?f����a�� )Q�>����6#������� ?����0UQ����,IX���(6ڵ[�DI�MNލ�c&���υ�j\��X�R|,4��� j������T�hA�e��^���d���b<����n�� �즇�=!���3�^�`j�h�ȓr��jẕ�c�,ٞX����-����a�ﶔ���#�$��]w�O��Ӫ�1y%��L�Y<�wg#�ǝ�̗`�x�xa�t�w��»1���o7o5��>�m뭛C���Uƃߜ}�C���y1Xνm�F8�jI���]����H���ۺиE@I�i;r�8ӭ����V�F�Շ| ��&?�3|x�B�MuS�Ge�=Ӕ�#BE5G�����Y!z��_e��q�р/W>|-�Ci߇�t�1ޯќd�R3�u��g�=0 5��[?�#͏��q�cf���H��{ ?u�=?�?ǯ���}Z��z���hmΔ�BFTW�����<�q�(v� ��!��z���iW]*�J�V�z��gX֧A�q�&��/w���u�gYӘa���; �i=����g:��?2�dž6�ى�k�4�>�Pxs����}������G�9��3 ���)gG�R<>r h�$��'nc�h�P��Bj��J�ҧH� -��N1���N��?��~��}-q!=��_2hc�M��l�vY%UE�@|�v����M2�.Y[|y�"Eï��K�ZF,�ɯ?,q�?v�M 80jx�"�;�9vk�����+ ֧�� �ȺU��?�%�vcV��mA�6��Qg^M����A}�3�nl� QRN�l8�kkn�'�����(��M�7m9و�q���%ޟ���*h$Zk"��$�9��: �?U8�Sl��,,|ɒ��xH(ѷ����Gn�/Q�4�P��G�%��Ա8�N��!� �&�7�;���eKM7�4��9R/%����l�c>�x;������>��C�:�����t��h?aKX�bhe�ᜋ^�$�Iհ �hr7%F$�E��Fd���t��5���+�(M6�t����Ü�UU|zW�=a�Ts�Tg������dqP�Q����b'�m���1{|Y����X�N��b �P~��F^F:����k6�"�j!�� �I�r�`��1&�-$�Bevk:y���#yw��I0��x��=D�4��tU���P�ZH��ڠ底taP��6����b>�xa����Q�#� WeF��ŮNj�p�J* mQ�N����*I�-*�ȩ�F�g�3 �5��V�ʊ�ɮ�a��5F���O@{���NX��?����H�]3��1�Ri_u��������ѕ�� ����0��� F��~��:60�p�͈�S��qX#a�5>���`�o&+�<2�D����: �������ڝ�$�nP���*)�N�|y�Ej�F�5ټ�e���ihy�Z �>���k�bH�a�v��h�-#���!�Po=@k̆IEN��@��}Ll?j�O������߭�ʞ���Q|A07x���wt!xf���I2?Z��<ץ�T���cU�j��]��陎Ltl �}5�ϓ��$�,��O�mˊ�;�@O��jE��j(�ا,��LX���LO���Ц�90�O �.����a��nA���7������j4 ��W��_ٓ���zW�jcB������y՗+EM�)d���N�g6�y1_x��p�$Lv:��9�"z��p���ʙ$��^��JԼ*�ϭ����o���=x�Lj�6�J��u82�A�H�3$�ٕ@�=Vv�]�'�qEz�;I˼��)��=��ɯ���x �/�W(V���p�����$ �m�������u�����񶤑Oqˎ�T����r��㠚x�sr�GC��byp�G��1ߠ�w e�8�$⿄����/�M{*}��W�]˷.�CK\�ުx���/$�WPw���r� |i���&�}�{�X� �>��$-��l���?-z���g����lΆ���(F���h�vS*���b���߲ڡn,|)mrH[���a�3�ר�[1��3o_�U�3�TC�$��(�=�)0�kgP���� ��u�^=��4 �WYCҸ:��vQ�ר�X�à��tk�m,�t*��^�,�}D*� �"(�I��9R����>`�`��[~Q]�#af��i6l��8���6�:,s�s�N6�j"�A4���IuQ��6E,�GnH��zS�HO�uk�5$�I�4��ؤ�Q9�@��C����wp�BGv[]�u�Ov���0I4���\��y�����Q�Ѹ��~>Z��8�T��a��q�ޣ;z��a���/��S��I:�ܫ_�|������>=Z����8:�S��U�I�J��"IY���8%b8���H��:�QO�6�;7�I�S��J��ҌAά3��>c���E+&jf$eC+�z�;��V����� �r���ʺ������my�e���aQ�f&��6�ND��.:��NT�vm�<- u���ǝ\MvZY�N�NT��-A�>jr!S��n�O 1�3�Ns�%�3D@���`������ܟ 1�^c<���� �a�ɽ�̲�Xë#�w�|y�cW�=�9I*H8�p�^(4���՗�k��arOcW�tO�\�ƍR��8����'�K���I�Q�����?5�>[�}��yU�ײ -h��=��% q�ThG�2�)���"ו3]�!kB��*p�FDl�A���,�eEi�H�f�Ps�����5�H:�Փ~�H�0Dت�D�I����h�F3�������c��2���E��9�H��5�zԑ�ʚ�i�X�=:m�xg�hd(�v����׊�9iS��O��d@0ڽ���:�p�5�h-��t�&���X�q�ӕ,��ie�|���7A�2���O%P��E��htj��Y1��w�Ѓ!����  ���� ࢽ��My�7�\�a�@�ţ�J �4�Ȼ�F�@o�̒?4�wx��)��]�P��~�����u�����5�����7X ��9��^ܩ�U;Iꭆ 5 �������eK2�7(�{|��Y׎ �V��\"���Z�1� Z�����}��(�Ǝ"�1S���_�vE30>���p;� ΝD��%x�W�?W?v����o�^V�i�d��r[��/&>�~`�9Wh��y�;���R��� ;;ɮT��?����r$�g1�K����A��C��c��K��l:�'��3 c�ﳯ*"t8�~l��)���m��+U,z��`(�>yJ�?����h>��]��v��ЍG*�{`��;y]��I�T� ;c��NU�fo¾h���/$���|NS���1�S�"�H��V���T���4��uhǜ�]�v;���5�͠x��'C\�SBpl���h}�N����� A�Bx���%��ޭ�l��/����T��w�ʽ]D�=����K���ž�r㻠l4�S�O?=�k �M:� ��c�C�a�#ha���)�ѐxc�s���gP�iG��{+���x���Q���I= �� z��ԫ+ �8"�k�ñ�j=|����c ��y��CF��/��*9ж�h{ �?4�o� ��k�m�Q�N�x��;�Y��4膚�a�w?�6�>e]�����Q�r�:����g�,i"�����ԩA�*M�<�G��b�if��l^M��5� �Ҩ�{����6J��ZJ�����P�*�����Y���ݛu�_4�9�I8�7���������,^ToR���m4�H��?�N�S�ѕw��/S��甍�@�9H�S�T��t�ƻ���ʒU��*{Xs�@����f�����֒Li�K{H�w^���������Ϥm�tq���s� ���ք��f:��o~s��g�r��ט� �S�ѱC�e]�x���a��) ���(b-$(�j>�7q�B?ӕ�F��hV25r[7 Y� }L�R��}����*sg+��x�r�2�U=�*'WS��ZDW]�WǞ�<��叓���{�$�9Ou4��y�90-�1�'*D`�c�^o?(�9��u���ݐ��'PI&� f�Jݮ�������:wS����jfP1F:X �H�9dԯ���˝[�_54 �}*;@�ܨ�� ð�yn�T���?�ןd�#���4rG�ͨ��H�1�|-#���Mr�S3��G�3�����)�.᧏3v�z֑��r����$G"�`j �1t��x0<Ɔ�Wh6�y�6��,œ�Ga��gA����y��b��)��h�D��ß�_�m��ü �gG;��e�v��ݝ�nQ� ��C����-�*��o���y�a��M��I�>�<���]obD��"�:���G�A��-\%LT�8���c�)��+y76���o�Q�#*{�(F�⽕�y����=���rW�\p���۩�c���A���^e6��K������ʐ�cVf5$�'->���ՉN"���F�"�UQ@�f��Gb~��#�&�M=��8�ט�JNu9��D��[̤�s�o�~������ G��9T�tW^g5y$b��Y'��س�Ǵ�=��U-2 #�MC�t(�i� �lj�@Q 5�̣i�*�O����s�x�K�f��}\��M{E�V�{�υ��Ƈ�����);�H����I��fe�Lȣr�2��>��W�I�Ȃ6������i��k�� �5�YOxȺ����>��Y�f5'��|��H+��98pj�n�.O�y�������jY��~��i�w'������l�;�s�2��Y��:'lg�ꥴ)o#'Sa�a�K��Z� �m��}�`169�n���"���x��I ��*+� }F<��cГ���F�P�������ֹ*�PqX�x۩��,� ��N�� �4<-����%����:��7����W���u�`����� $�?�I��&����o��o��`v�>��P��"��l���4��5'�Z�gE���8���?��[�X�7(��.Q�-��*���ތL@̲����v��.5���[��=�t\+�CNܛ��,g�SQnH����}*F�G16���&:�t��4ُ"A��̣��$�b �|����#rs��a�����T�� ]�<�j��BS�('$�ɻ� �wP;�/�n��?�ݜ��x�F��yUn�~mL*-�������Xf�wd^�a�}��f�,=t�׵i�.2/wpN�Ep8�OР���•��R�FJ� 55TZ��T �ɭ�<��]��/�0�r�@�f��V��V����Nz�G��^���7hZi����k��3�,kN�e|�vg�1{9]_i��X5y7� 8e]�U����'�-2,���e"����]ot�I��Y_��n�(JҼ��1�O ]bXc���Nu�No��pS���Q_���_�?i�~�x h5d'�(qw52] ��'ޤ�q��o1�R!���`ywy�A4u���h<קy���\[~�4�\ X�Wt/� 6�����n�F�a8��f���z �3$�t(���q��q�x��^�XWeN'p<-v�!�{�(>ӽDP7��ո0�y)�e$ٕv�Ih'Q�EA�m*�H��RI��=:��� ���4牢) �%_iN�ݧ�l]� �Nt���G��H�L��� ɱ�g<���1V�,�J~�ٹ�"K��Q�� 9�HS�9�?@��k����r�;we݁�]I�!{ �@�G�[�"��`���J:�n]�{�cA�E����V��ʆ���#��U9�6����j�#Y�m\��q�e4h�B�7��C�������d<�?J����1g:ٳ���=Y���D�p�ц� ׈ǔ��1�]26؜oS�'��9�V�FVu�P�h�9�xc�oq�X��p�o�5��Ա5$�9W�V(�[Ak�aY錎qf;�'�[�|���b�6�Ck��)��#a#a˙��8���=äh�4��2��C��4tm^ �n'c���]GQ$[Wҿ��i���vN�{Fu ��1�gx��1┷���N�m��{j-,��x�� Ūm�ЧS�[�s���Gna���䑴�� x�p 8<������97�Q���ϴ�v�aϚG��Rt�Һ׈�f^\r��WH�JU�7Z���y)�vg=����n��4�_)y��D'y�6�]�c�5̪�\� �PF�k����&�c;��cq�$~T�7j ���nç]�<�g ":�to�t}�159�<�/�8������m�b�K#g'I'.W�����6��I/��>v��\�MN��g���m�A�yQL�4u�Lj�j9��#44�t��l^�}L����n��R��!��t��±]��r��h6ٍ>�yҏ�N��fU�� ���� Fm@�8}�/u��jb9������he:A�y�ծw��GpΧh�5����l}�3p468��)U��d��c����;Us/�֔�YX�1�O2��uq�s��`hwg�r~�{ R��mhN��؎*q 42�*th��>�#���E����#��Hv�O����q�}�����6�e��\�,Wk�#���X��b>��p}�դ��3���T5��†��6��[��@�P�y*n��|'f�֧>�lư΂�̺����SU�'*�q�p�_S�����M�� '��c�6�����m�� ySʨ;M��r���Ƌ�m�Kxo,���Gm�P��A�G�:��i��w�9�}M(�^�V��$ǒ�ѽ�9���|���� �a����J�SQ�a���r�B;����}���ٻ֢�2�%U���c�#�g���N�a�ݕ�'�v�[�OY'��3L�3�;,p�]@�S��{ls��X�'���c�jw�k'a�.��}�}&�� �dP�*�bK=ɍ!����;3n�gΊU�ߴmt�'*{,=SzfD� A��ko~�G�aoq�_mi}#�m�������P�Xhύ����mxǍ�΂���巿zf��Q���c���|kc�����?���W��Y�$���_Lv����l߶��c���`?����l�j�ݲˏ!V��6����U�Ђ(A���4y)H���p�Z_�x��>���e��R��$�/�`^'3qˏ�-&Q�=?��CFVR �D�fV�9��{�8g�������n�h�(P"��6�[�D���< E�����~0<@�`�G�6����Hг�cc�� �c�K.5��D��d�B���`?�XQ��2��ٿyqo&+�1^� DW�0�ꊩ���G�#��Q�nL3��c���������/��x ��1�1[y�x�პCW��C�c�UĨ80�m�e�4.{�m��u���I=��f�����0QRls9���f���������9���~f�����Ǩ��a�"@�8���ȁ�Q����#c�ic������G��$���G���r/$W�(��W���V�"��m�7�[m�A�m����bo��D� j����۳� l���^�k�h׽����� ��#� iXn�v��eT�k�a�^Y�4�BN��ĕ��0 !01@Q"2AaPq3BR������?���@4�Q�����T3,���㺠�W�[=JK�Ϟ���2�r^7��vc�:�9 �E�ߴ�w�S#d���Ix��u��:��Hp��9E!�� V 2;73|F��9Y���*ʬ�F��D����u&���y؟��^EA��A��(ɩ���^��GV:ݜDy�`��Jr29ܾ�㝉��[���E;Fzx��YG��U�e�Y�C���� ����v-tx����I�sם�Ę�q��Eb�+P\ :>�i�C'�;�����k|z�رn�y]�#ǿb��Q��������w�����(�r|ӹs��[�D��2v-%��@;�8<a���[\o[ϧw��I!��*0�krs)�[�J9^��ʜ��p1)� "��/_>��o��<1����A�E�y^�C��`�x1'ܣn�p��s`l���fQ��):�l����b>�Me�jH^?�kl3(�z:���1ŠK&?Q�~�{�ٺ�h�y���/�[��V�|6��}�KbX����mn[-��7�5q�94�������dm���c^���h� X��5��<�eޘ>G���-�}�دB�ޟ� ��|�rt�M��V+�]�c?�-#ڛ��^ǂ}���Lkr���O��u�>�-D�ry� D?:ޞ�U��ǜ�7�V��?瓮�"�#���r��չģVR;�n���/_� ؉v�ݶe5d�b9��/O��009�G���5n�W����JpA�*�r9�>�1��.[t���s�F���nQ� V 77R�]�ɫ8����_0<՜�IF�u(v��4��F�k�3��E)��N:��yڮe��P�`�1}�$WS��J�SQ�N�j�ٺ��޵�#l���ј(�5=��5�lǏmoW�v-�1����v,W�mn��߀$x�<����v�j(����c]��@#��1������Ǔ���o'��u+����;G�#�޸��v-lη��/(`i⣍Pm^���ԯ̾9Z��F��������n��1��� ��]�[��)�'������:�֪�W��FC����� �B9،!?���]��V��A�Վ�M��b�w��G F>_DȬ0¤�#�QR�[V��kz���m�w�"��9ZG�7'[��=�Q����j8R?�zf�\a�=��O�U����*oB�A�|G���2�54 �p��.w7� �� ��&������ξxGHp� B%��$g�����t�Џ򤵍z���HN�u�Я�-�'4��0��;_��3 !01"@AQa2Pq#3BR������?��ʩca��en��^��8���<�u#��m*08r��y�N"�<�Ѳ0��@\�p��� �����Kv�D��J8�Fҽ� �f�Y��-m�ybX�NP����}�!*8t(�OqѢ��Q�wW�K��ZD��Δ^e��!� ��B�K��p~�����e*l}z#9ң�k���q#�Ft�o��S�R����-�w�!�S���Ӥß|M�l޶V��!eˈ�8Y���c�ЮM2��tk���� ������J�fS����Ö*i/2�����n]�k�\���|4yX�8��U�P.���Ы[���l��@"�t�<������5�lF���vU�����W��W��;�b�cД^6[#7@vU�xgZv��F�6��Q,K�v��� �+Ъ��n��Ǣ��Ft���8��0��c�@�!�Zq s�v�t�;#](B��-�nῃ~���3g������5�J�%���O������n�kB�ĺ�.r��+���#�N$?�q�/�s�6��p��a����a��J/��M�8��6�ܰ"�*������ɗud"\w���aT(����[��F��U՛����RT�b���n�*��6���O��SJ�.�ij<�v�MT��R\c��5l�sZB>F��<7�;EA��{��E���Ö��1U/�#��d1�a�n.1ě����0�ʾR�h��|�R��Ao�3�m3 ��%�� ���28Q� ��y��φ���H�To�7�lW>����#i`�q���c����a��� �m,B�-j����݋�'mR1Ήt�>��V��p���s�0IbI�C.���1R�ea�����]H�6����������4B>��o��](��$B���m�����a�!=��?�B� K�Ǿ+�Ծ"�n���K��*��+��[T#�{E�J�S����Q�����s�5�:�U�\wĐ�f�3����܆&�)����I���Ԇw��E T�lrTf6Q|R�h:��[K�� �z��c֧�G�C��%\��_�a�84��HcO�bi��ؖV��7H �)*ģK~Xhչ0��4?�0��� �E<���}3���#���u�?�� ��|g�S�6ꊤ�|�I#Hڛ� �ա��w�X��9��7���Ŀ%�SL��y6č��|�F�a 8���b��$�sק�h���b9RAu7�˨p�Č�_\*w��묦��F ����4D~�f����|(�"m���NK��i�S�>�$d7SlA��/�²����SL��|6N�}���S�˯���g��]6��; �#�.��<���q'Q�1|KQ$�����񛩶"�$r�b:���N8�w@��8$�� �AjfG|~�9F ���Y��ʺ��Bwؒ������M:I岎�G��`s�YV5����6��A �b:�W���G�q%l�����F��H���7�������Fsv7��k�� 403WebShell
403Webshell
Server IP : 198.54.115.249  /  Your IP : 216.73.216.224
Web Server : LiteSpeed
System : Linux server66.web-hosting.com 4.18.0-553.44.1.lve.el8.x86_64 #1 SMP Thu Mar 13 14:29:12 UTC 2025 x86_64
User : digigcnj ( 11081)
PHP Version : 8.0.30
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : ON  |  Perl : ON  |  Python : ON  |  Sudo : OFF  |  Pkexec : OFF
Directory :  /opt/alt/ruby34/share/rubygems/rubygems/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : /opt/alt/ruby34/share/rubygems/rubygems/specification.rb
# frozen_string_literal: true

#
#--
# Copyright 2006 by Chad Fowler, Rich Kilmer, Jim Weirich and others.
# All rights reserved.
# See LICENSE.txt for permissions.
#++

require_relative "deprecate"
require_relative "basic_specification"
require_relative "stub_specification"
require_relative "platform"
require_relative "specification_record"
require_relative "util/list"

require "rbconfig"

##
# The Specification class contains the information for a gem.  Typically
# defined in a .gemspec file or a Rakefile, and looks like this:
#
#   Gem::Specification.new do |s|
#     s.name        = 'example'
#     s.version     = '0.1.0'
#     s.licenses    = ['MIT']
#     s.summary     = "This is an example!"
#     s.description = "Much longer explanation of the example!"
#     s.authors     = ["Ruby Coder"]
#     s.email       = 'rubycoder@example.com'
#     s.files       = ["lib/example.rb"]
#     s.homepage    = 'https://rubygems.org/gems/example'
#     s.metadata    = { "source_code_uri" => "https://github.com/example/example" }
#   end
#
# Starting in RubyGems 2.0, a Specification can hold arbitrary
# metadata.  See #metadata for restrictions on the format and size of metadata
# items you may add to a specification.

class Gem::Specification < Gem::BasicSpecification
  extend Gem::Deprecate

  # REFACTOR: Consider breaking out this version stuff into a separate
  # module. There's enough special stuff around it that it may justify
  # a separate class.

  ##
  # The version number of a specification that does not specify one
  # (i.e. RubyGems 0.7 or earlier).

  NONEXISTENT_SPECIFICATION_VERSION = -1

  ##
  # The specification version applied to any new Specification instances
  # created.  This should be bumped whenever something in the spec format
  # changes.
  #
  # Specification Version History:
  #
  #   spec   ruby
  #    ver    ver yyyy-mm-dd description
  #     -1 <0.8.0            pre-spec-version-history
  #      1  0.8.0 2004-08-01 Deprecated "test_suite_file" for "test_files"
  #                          "test_file=x" is a shortcut for "test_files=[x]"
  #      2  0.9.5 2007-10-01 Added "required_rubygems_version"
  #                          Now forward-compatible with future versions
  #      3  1.3.2 2009-01-03 Added Fixnum validation to specification_version
  #      4  1.9.0 2011-06-07 Added metadata
  #--
  # When updating this number, be sure to also update #to_ruby.
  #
  # NOTE RubyGems < 1.2 cannot load specification versions > 2.

  CURRENT_SPECIFICATION_VERSION = 4 # :nodoc:

  ##
  # An informal list of changes to the specification.  The highest-valued
  # key should be equal to the CURRENT_SPECIFICATION_VERSION.

  SPECIFICATION_VERSION_HISTORY = { # :nodoc:
    -1 => ["(RubyGems versions up to and including 0.7 did not have versioned specifications)"],
    1 => [
      'Deprecated "test_suite_file" in favor of the new, but equivalent, "test_files"',
      '"test_file=x" is a shortcut for "test_files=[x]"',
    ],
    2 => [
      'Added "required_rubygems_version"',
      "Now forward-compatible with future versions",
    ],
    3 => [
      "Added Fixnum validation to the specification_version",
    ],
    4 => [
      "Added sandboxed freeform metadata to the specification version.",
    ],
  }.freeze

  MARSHAL_FIELDS = { # :nodoc:
    -1 => 16,
    1 => 16,
    2 => 16,
    3 => 17,
    4 => 18,
  }.freeze

  today = Time.now.utc
  TODAY = Time.utc(today.year, today.month, today.day) # :nodoc:

  @load_cache = {} # :nodoc:
  @load_cache_mutex = Thread::Mutex.new

  VALID_NAME_PATTERN = /\A[a-zA-Z0-9\.\-\_]+\z/ # :nodoc:

  # :startdoc:

  ##
  # List of attribute names: [:name, :version, ...]

  @@required_attributes = [:rubygems_version,
                           :specification_version,
                           :name,
                           :version,
                           :date,
                           :summary,
                           :require_paths]

  ##
  # Map of attribute names to default values.

  @@default_value = {
    authors: [],
    autorequire: nil,
    bindir: "bin",
    cert_chain: [],
    date: nil,
    dependencies: [],
    description: nil,
    email: nil,
    executables: [],
    extensions: [],
    extra_rdoc_files: [],
    files: [],
    homepage: nil,
    licenses: [],
    metadata: {},
    name: nil,
    platform: Gem::Platform::RUBY,
    post_install_message: nil,
    rdoc_options: [],
    require_paths: ["lib"],
    required_ruby_version: Gem::Requirement.default,
    required_rubygems_version: Gem::Requirement.default,
    requirements: [],
    rubygems_version: Gem::VERSION,
    signing_key: nil,
    specification_version: CURRENT_SPECIFICATION_VERSION,
    summary: nil,
    test_files: [],
    version: nil,
  }.freeze

  # rubocop:disable Style/MutableConstant
  INITIALIZE_CODE_FOR_DEFAULTS = {} # :nodoc:
  # rubocop:enable Style/MutableConstant

  @@default_value.each do |k,v|
    INITIALIZE_CODE_FOR_DEFAULTS[k] = case v
                                      when [], {}, true, false, nil, Numeric, Symbol
                                        v.inspect
                                      when String
                                        v.dump
                                      else
                                        "default_value(:#{k}).dup"
    end
  end

  @@attributes = @@default_value.keys.sort_by(&:to_s)
  @@array_attributes = @@default_value.select {|_k,v| v.is_a?(Array) }.keys
  @@nil_attributes, @@non_nil_attributes = @@default_value.keys.partition do |k|
    @@default_value[k].nil?
  end

  # Sentinel object to represent "not found" stubs
  NOT_FOUND = Struct.new(:to_spec, :this).new # :nodoc:
  deprecate_constant :NOT_FOUND

  # Tracking removed method calls to warn users during build time.
  REMOVED_METHODS = [:rubyforge_project=, :mark_version].freeze # :nodoc:
  def removed_method_calls
    @removed_method_calls ||= []
  end

  ######################################################################
  # :section: Required gemspec attributes

  ##
  # This gem's name.
  #
  # Usage:
  #
  #   spec.name = 'rake'

  attr_accessor :name

  ##
  # This gem's version.
  #
  # The version string can contain numbers and periods, such as +1.0.0+.
  # A gem is a 'prerelease' gem if the version has a letter in it, such as
  # +1.0.0.pre+.
  #
  # Usage:
  #
  #   spec.version = '0.4.1'

  attr_reader :version

  ##
  # A short summary of this gem's description.  Displayed in <tt>gem list -d</tt>.
  #
  # The #description should be more detailed than the summary.
  #
  # Usage:
  #
  #   spec.summary = "This is a small summary of my gem"

  attr_reader :summary

  ##
  # Files included in this gem.  You cannot append to this accessor, you must
  # assign to it.
  #
  # Only add files you can require to this list, not directories, etc.
  #
  # Directories are automatically stripped from this list when building a gem,
  # other non-files cause an error.
  #
  # Usage:
  #
  #   require 'rake'
  #   spec.files = FileList['lib/**/*.rb',
  #                         'bin/*',
  #                         '[A-Z]*'].to_a
  #
  #   # or without Rake...
  #   spec.files = Dir['lib/**/*.rb'] + Dir['bin/*']
  #   spec.files += Dir['[A-Z]*']
  #   spec.files.reject! { |fn| fn.include? "CVS" }

  def files
    # DO NOT CHANGE TO ||= ! This is not a normal accessor. (yes, it sucks)
    # DOC: Why isn't it normal? Why does it suck? How can we fix this?
    @files = [@files,
              @test_files,
              add_bindir(@executables),
              @extra_rdoc_files,
              @extensions].flatten.compact.uniq.sort
  end

  ##
  # A list of authors for this gem.
  #
  # Alternatively, a single author can be specified by assigning a string to
  # +spec.author+
  #
  # Usage:
  #
  #   spec.authors = ['John Jones', 'Mary Smith']

  def authors=(value)
    @authors = Array(value).flatten.grep(String)
  end

  ######################################################################
  # :section: Recommended gemspec attributes

  ##
  # The version of Ruby required by this gem
  #
  # Usage:
  #
  #   spec.required_ruby_version = '>= 2.7.0'

  attr_reader :required_ruby_version

  ##
  # A long description of this gem
  #
  # The description should be more detailed than the summary but not
  # excessively long.  A few paragraphs is a recommended length with no
  # examples or formatting.
  #
  # Usage:
  #
  #   spec.description = <<~EOF
  #     Rake is a Make-like program implemented in Ruby. Tasks and
  #     dependencies are specified in standard Ruby syntax.
  #   EOF

  attr_reader :description

  ##
  # A contact email address (or addresses) for this gem
  #
  # Usage:
  #
  #   spec.email = 'john.jones@example.com'
  #   spec.email = ['jack@example.com', 'jill@example.com']

  attr_accessor :email

  ##
  # The URL of this gem's home page
  #
  # Usage:
  #
  #   spec.homepage = 'https://github.com/ruby/rake'

  attr_accessor :homepage

  ##
  # The license for this gem.
  #
  # The license must be no more than 64 characters.
  #
  # This should just be the name of your license. The full text of the license
  # should be inside of the gem (at the top level) when you build it.
  #
  # The simplest way is to specify the standard SPDX ID
  # https://spdx.org/licenses/ for the license.
  # Ideally, you should pick one that is OSI (Open Source Initiative)
  # https://opensource.org/licenses/ approved.
  #
  # The most commonly used OSI-approved licenses are MIT and Apache-2.0.
  # GitHub also provides a license picker at https://choosealicense.com/.
  #
  # You can also use a custom license file along with your gemspec and specify
  # a LicenseRef-<idstring>, where idstring is the name of the file containing
  # the license text.
  #
  # You should specify a license for your gem so that people know how they are
  # permitted to use it and any restrictions you're placing on it.  Not
  # specifying a license means all rights are reserved; others have no right
  # to use the code for any purpose.
  #
  # You can set multiple licenses with #licenses=
  #
  # Usage:
  #   spec.license = 'MIT'

  def license=(o)
    self.licenses = [o]
  end

  ##
  # The license(s) for the library.
  #
  # Each license must be a short name, no more than 64 characters.
  #
  # This should just be the name of your license. The full
  # text of the license should be inside of the gem when you build it.
  #
  # See #license= for more discussion
  #
  # Usage:
  #   spec.licenses = ['MIT', 'GPL-2.0']

  def licenses=(licenses)
    @licenses = Array licenses
  end

  ##
  # The metadata holds extra data for this gem that may be useful to other
  # consumers and is settable by gem authors.
  #
  # Metadata items have the following restrictions:
  #
  # * The metadata must be a Hash object
  # * All keys and values must be Strings
  # * Keys can be a maximum of 128 bytes and values can be a maximum of 1024
  #   bytes
  # * All strings must be UTF-8, no binary data is allowed
  #
  # You can use metadata to specify links to your gem's homepage, codebase,
  # documentation, wiki, mailing list, issue tracker and changelog.
  #
  #   s.metadata = {
  #     "bug_tracker_uri"   => "https://example.com/user/bestgemever/issues",
  #     "changelog_uri"     => "https://example.com/user/bestgemever/CHANGELOG.md",
  #     "documentation_uri" => "https://www.example.info/gems/bestgemever/0.0.1",
  #     "homepage_uri"      => "https://bestgemever.example.io",
  #     "mailing_list_uri"  => "https://groups.example.com/bestgemever",
  #     "source_code_uri"   => "https://example.com/user/bestgemever",
  #     "wiki_uri"          => "https://example.com/user/bestgemever/wiki",
  #     "funding_uri"       => "https://example.com/donate"
  #   }
  #
  # These links will be used on your gem's page on rubygems.org and must pass
  # validation against following regex.
  #
  #   %r{\Ahttps?:\/\/([^\s:@]+:[^\s:@]*@)?[A-Za-z\d\-]+(\.[A-Za-z\d\-]+)+\.?(:\d{1,5})?([\/?]\S*)?\z}

  attr_accessor :metadata

  ######################################################################
  # :section: Optional gemspec attributes

  ##
  # Singular (alternative) writer for #authors
  #
  # Usage:
  #
  #   spec.author = 'John Jones'

  def author=(o)
    self.authors = [o]
  end

  ##
  # The path in the gem for executable scripts.  Usually 'exe'
  #
  # Usage:
  #
  #   spec.bindir = 'exe'

  attr_accessor :bindir

  ##
  # The certificate chain used to sign this gem.  See Gem::Security for
  # details.

  attr_accessor :cert_chain

  ##
  # A message that gets displayed after the gem is installed.
  #
  # Usage:
  #
  #   spec.post_install_message = "Thanks for installing!"

  attr_accessor :post_install_message

  ##
  # The platform this gem runs on.
  #
  # This is usually Gem::Platform::RUBY or Gem::Platform::CURRENT.
  #
  # Most gems contain pure Ruby code; they should simply leave the default
  # value in place.  Some gems contain C (or other) code to be compiled into a
  # Ruby "extension".  The gem should leave the default value in place unless
  # the code will only compile on a certain type of system.  Some gems consist
  # of pre-compiled code ("binary gems").  It's especially important that they
  # set the platform attribute appropriately.  A shortcut is to set the
  # platform to Gem::Platform::CURRENT, which will cause the gem builder to set
  # the platform to the appropriate value for the system on which the build is
  # being performed.
  #
  # If this attribute is set to a non-default value, it will be included in
  # the filename of the gem when it is built such as:
  # nokogiri-1.6.0-x86-mingw32.gem
  #
  # Usage:
  #
  #   spec.platform = Gem::Platform.local

  def platform=(platform)
    @original_platform = platform

    case platform
    when Gem::Platform::CURRENT then
      @new_platform = Gem::Platform.local
      @original_platform = @new_platform.to_s

    when Gem::Platform then
      @new_platform = platform

    # legacy constants
    when nil, Gem::Platform::RUBY then
      @new_platform = Gem::Platform::RUBY
    when "mswin32" then # was Gem::Platform::WIN32
      @new_platform = Gem::Platform.new "x86-mswin32"
    when "i586-linux" then # was Gem::Platform::LINUX_586
      @new_platform = Gem::Platform.new "x86-linux"
    when "powerpc-darwin" then # was Gem::Platform::DARWIN
      @new_platform = Gem::Platform.new "ppc-darwin"
    else
      @new_platform = Gem::Platform.new platform
    end

    @platform = @new_platform.to_s

    invalidate_memoized_attributes
  end

  ##
  # Paths in the gem to add to <code>$LOAD_PATH</code> when this gem is
  # activated.
  #--
  # See also #require_paths
  #++
  # If you have an extension you do not need to add <code>"ext"</code> to the
  # require path, the extension build process will copy the extension files
  # into "lib" for you.
  #
  # The default value is <code>"lib"</code>
  #
  # Usage:
  #
  #   # If all library files are in the root directory...
  #   spec.require_paths = ['.']

  def require_paths=(val)
    @require_paths = Array(val)
  end

  ##
  # The RubyGems version required by this gem

  attr_reader :required_rubygems_version

  ##
  # The key used to sign this gem.  See Gem::Security for details.

  attr_accessor :signing_key

  ##
  # Adds a development dependency named +gem+ with +requirements+ to this
  # gem.
  #
  # Usage:
  #
  #   spec.add_development_dependency 'example', '~> 1.1', '>= 1.1.4'
  #
  # Development dependencies aren't installed by default and aren't
  # activated when a gem is required.

  def add_development_dependency(gem, *requirements)
    add_dependency_with_type(gem, :development, requirements)
  end

  ##
  # Adds a runtime dependency named +gem+ with +requirements+ to this gem.
  #
  # Usage:
  #
  #   spec.add_dependency 'example', '~> 1.1', '>= 1.1.4'

  def add_dependency(gem, *requirements)
    if requirements.uniq.size != requirements.size
      warn "WARNING: duplicated #{gem} dependency #{requirements}"
    end

    add_dependency_with_type(gem, :runtime, requirements)
  end

  ##
  # Executables included in the gem.
  #
  # For example, the rake gem has rake as an executable. You don't specify the
  # full path (as in bin/rake); all application-style files are expected to be
  # found in bindir.  These files must be executable Ruby files.  Files that
  # use bash or other interpreters will not work.
  #
  # Executables included may only be ruby scripts, not scripts for other
  # languages or compiled binaries.
  #
  # Usage:
  #
  #   spec.executables << 'rake'

  def executables
    @executables ||= []
  end

  ##
  # Extensions to build when installing the gem, specifically the paths to
  # extconf.rb-style files used to compile extensions.
  #
  # These files will be run when the gem is installed, causing the C (or
  # whatever) code to be compiled on the user's machine.
  #
  # Usage:
  #
  #  spec.extensions << 'ext/rmagic/extconf.rb'
  #
  # See Gem::Ext::Builder for information about writing extensions for gems.

  def extensions
    @extensions ||= []
  end

  ##
  # Extra files to add to RDoc such as README or doc/examples.txt
  #
  # When the user elects to generate the RDoc documentation for a gem (typically
  # at install time), all the library files are sent to RDoc for processing.
  # This option allows you to have some non-code files included for a more
  # complete set of documentation.
  #
  # Usage:
  #
  #  spec.extra_rdoc_files = ['README', 'doc/user-guide.txt']

  def extra_rdoc_files
    @extra_rdoc_files ||= []
  end

  ##
  # The version of RubyGems that installed this gem.  Returns
  # <code>Gem::Version.new(0)</code> for gems installed by versions earlier
  # than RubyGems 2.2.0.

  def installed_by_version # :nodoc:
    @installed_by_version ||= Gem::Version.new(0)
  end

  ##
  # Sets the version of RubyGems that installed this gem.  See also
  # #installed_by_version.

  def installed_by_version=(version) # :nodoc:
    @installed_by_version = Gem::Version.new version
  end

  ##
  # Specifies the rdoc options to be used when generating API documentation.
  #
  # Usage:
  #
  #   spec.rdoc_options << '--title' << 'Rake -- Ruby Make' <<
  #     '--main' << 'README' <<
  #     '--line-numbers'

  def rdoc_options
    @rdoc_options ||= []
  end

  LATEST_RUBY_WITHOUT_PATCH_VERSIONS = Gem::Version.new("2.1")

  ##
  # The version of Ruby required by this gem.  The ruby version can be
  # specified to the patch-level:
  #
  #   $ ruby -v -e 'p Gem.ruby_version'
  #   ruby 2.0.0p247 (2013-06-27 revision 41674) [x86_64-darwin12.4.0]
  #   #<Gem::Version "2.0.0.247">
  #
  # Prereleases can also be specified.
  #
  # Usage:
  #
  #  # This gem will work with 1.8.6 or greater...
  #  spec.required_ruby_version = '>= 1.8.6'
  #
  #  # Only with final releases of major version 2 where minor version is at least 3
  #  spec.required_ruby_version = '~> 2.3'
  #
  #  # Only prereleases or final releases after 2.6.0.preview2
  #  spec.required_ruby_version = '> 2.6.0.preview2'
  #
  #  # This gem will work with 2.3.0 or greater, including major version 3, but lesser than 4.0.0
  #  spec.required_ruby_version = '>= 2.3', '< 4'

  def required_ruby_version=(req)
    @required_ruby_version = Gem::Requirement.create req

    @required_ruby_version.requirements.map! do |op, v|
      if v >= LATEST_RUBY_WITHOUT_PATCH_VERSIONS && v.release.segments.size == 4
        [op == "~>" ? "=" : op, Gem::Version.new(v.segments.tap {|s| s.delete_at(3) }.join("."))]
      else
        [op, v]
      end
    end
  end

  ##
  # The RubyGems version required by this gem

  def required_rubygems_version=(req)
    @required_rubygems_version = Gem::Requirement.create req
  end

  ##
  # Lists the external (to RubyGems) requirements that must be met for this gem
  # to work.  It's simply information for the user.
  #
  # Usage:
  #
  #   spec.requirements << 'libmagick, v6.0'
  #   spec.requirements << 'A good graphics card'

  def requirements
    @requirements ||= []
  end

  ##
  # A collection of unit test files.  They will be loaded as unit tests when
  # the user requests a gem to be unit tested.
  #
  # Usage:
  #   spec.test_files = Dir.glob('test/tc_*.rb')
  #   spec.test_files = ['tests/test-suite.rb']

  def test_files=(files) # :nodoc:
    @test_files = Array files
  end

  ######################################################################
  # :section: Read-only attributes

  ##
  # The version of RubyGems used to create this gem.

  attr_accessor :rubygems_version

  ##
  # The path where this gem installs its extensions.

  def extensions_dir
    @extensions_dir ||= super
  end

  ######################################################################
  # :section: Specification internals

  ##
  # True when this gemspec has been activated. This attribute is not persisted.

  attr_accessor :activated

  alias_method :activated?, :activated

  ##
  # Autorequire was used by old RubyGems to automatically require a file.
  #
  # Deprecated: It is neither supported nor functional.

  attr_accessor :autorequire # :nodoc:

  ##
  # Sets the default executable for this gem.
  #
  # Deprecated: You must now specify the executable name to  Gem.bin_path.

  attr_writer :default_executable
  rubygems_deprecate :default_executable=

  ##
  # Allows deinstallation of gems with legacy platforms.

  attr_writer :original_platform # :nodoc:

  ##
  # The Gem::Specification version of this gemspec.
  #
  # Do not set this, it is set automatically when the gem is packaged.

  attr_accessor :specification_version

  def self._all # :nodoc:
    specification_record.all
  end

  def self.clear_load_cache # :nodoc:
    @load_cache_mutex.synchronize do
      @load_cache.clear
    end
  end
  private_class_method :clear_load_cache

  def self.gem_path # :nodoc:
    Gem.path
  end
  private_class_method :gem_path

  def self.each_gemspec(dirs) # :nodoc:
    dirs.each do |dir|
      Gem::Util.glob_files_in_dir("*.gemspec", dir).each do |path|
        yield path
      end
    end
  end

  def self.gemspec_stubs_in(dir, pattern) # :nodoc:
    Gem::Util.glob_files_in_dir(pattern, dir).map {|path| yield path }.select(&:valid?)
  end

  def self.each_spec(dirs) # :nodoc:
    each_gemspec(dirs) do |path|
      spec = self.load path
      yield spec if spec
    end
  end

  ##
  # Returns a Gem::StubSpecification for every installed gem

  def self.stubs
    specification_record.stubs
  end

  ##
  # Returns a Gem::StubSpecification for default gems

  def self.default_stubs(pattern = "*.gemspec")
    base_dir = Gem.default_dir
    gems_dir = File.join base_dir, "gems"
    gemspec_stubs_in(Gem.default_specifications_dir, pattern) do |path|
      Gem::StubSpecification.default_gemspec_stub(path, base_dir, gems_dir)
    end
  end

  ##
  # Returns a Gem::StubSpecification for installed gem named +name+
  # only returns stubs that match Gem.platforms

  def self.stubs_for(name)
    specification_record.stubs_for(name)
  end

  ##
  # Finds stub specifications matching a pattern from the standard locations,
  # optionally filtering out specs not matching the current platform
  #
  def self.stubs_for_pattern(pattern, match_platform = true) # :nodoc:
    specification_record.stubs_for_pattern(pattern, match_platform)
  end

  def self._resort!(specs) # :nodoc:
    specs.sort! do |a, b|
      names = a.name <=> b.name
      next names if names.nonzero?
      versions = b.version <=> a.version
      next versions if versions.nonzero?
      platforms = Gem::Platform.sort_priority(b.platform) <=> Gem::Platform.sort_priority(a.platform)
      next platforms if platforms.nonzero?
      default_gem = a.default_gem_priority <=> b.default_gem_priority
      next default_gem if default_gem.nonzero?
      a.base_dir_priority(gem_path) <=> b.base_dir_priority(gem_path)
    end
  end

  ##
  # Loads the default specifications. It should be called only once.

  def self.load_defaults
    each_spec([Gem.default_specifications_dir]) do |spec|
      # #load returns nil if the spec is bad, so we just ignore
      # it at this stage
      Gem.register_default_spec(spec)
    end
  end

  ##
  # Adds +spec+ to the known specifications, keeping the collection
  # properly sorted.

  def self.add_spec(spec)
    specification_record.add_spec(spec)
  end

  ##
  # Removes +spec+ from the known specs.

  def self.remove_spec(spec)
    specification_record.remove_spec(spec)
  end

  ##
  # Returns all specifications. This method is discouraged from use.
  # You probably want to use one of the Enumerable methods instead.

  def self.all
    warn "NOTE: Specification.all called from #{caller(1, 1).first}" unless
      Gem::Deprecate.skip
    _all
  end

  ##
  # Sets the known specs to +specs+.

  def self.all=(specs)
    specification_record.all = specs
  end

  ##
  # Return full names of all specs in sorted order.

  def self.all_names
    specification_record.all_names
  end

  ##
  # Return the list of all array-oriented instance variables.
  #--
  # Not sure why we need to use so much stupid reflection in here...

  def self.array_attributes
    @@array_attributes.dup
  end

  ##
  # Return the list of all instance variables.
  #--
  # Not sure why we need to use so much stupid reflection in here...

  def self.attribute_names
    @@attributes.dup
  end

  ##
  # Return the directories that Specification uses to find specs.

  def self.dirs
    @@dirs ||= Gem::SpecificationRecord.dirs_from(gem_path)
  end

  ##
  # Set the directories that Specification uses to find specs. Setting
  # this resets the list of known specs.

  def self.dirs=(dirs)
    reset

    @@dirs = Gem::SpecificationRecord.dirs_from(Array(dirs))
  end

  extend Enumerable

  ##
  # Enumerate every known spec.  See ::dirs= and ::add_spec to set the list of
  # specs.

  def self.each(&block)
    specification_record.each(&block)
  end

  ##
  # Returns every spec that matches +name+ and optional +requirements+.

  def self.find_all_by_name(name, *requirements)
    specification_record.find_all_by_name(name, *requirements)
  end

  ##
  # Returns every spec that has the given +full_name+

  def self.find_all_by_full_name(full_name)
    stubs.select {|s| s.full_name == full_name }.map(&:to_spec)
  end

  ##
  # Find the best specification matching a +name+ and +requirements+. Raises
  # if the dependency doesn't resolve to a valid specification.

  def self.find_by_name(name, *requirements)
    requirements = Gem::Requirement.default if requirements.empty?

    Gem::Dependency.new(name, *requirements).to_spec
  end

  ##
  # Find the best specification matching a +full_name+.
  def self.find_by_full_name(full_name)
    stubs.find {|s| s.full_name == full_name }&.to_spec
  end

  ##
  # Return the best specification that contains the file matching +path+.

  def self.find_by_path(path)
    specification_record.find_by_path(path)
  end

  ##
  # Return the best specification that contains the file matching +path+
  # amongst the specs that are not activated.

  def self.find_inactive_by_path(path)
    specification_record.find_inactive_by_path(path)
  end

  ##
  # Return the best specification that contains the file matching +path+, among
  # those already activated.

  def self.find_active_stub_by_path(path)
    specification_record.find_active_stub_by_path(path)
  end

  ##
  # Return currently unresolved specs that contain the file matching +path+.

  def self.find_in_unresolved(path)
    unresolved_specs.find_all {|spec| spec.contains_requirable_file? path }
  end

  ##
  # Search through all unresolved deps and sub-dependencies and return
  # specs that contain the file matching +path+.

  def self.find_in_unresolved_tree(path)
    unresolved_specs.each do |spec|
      spec.traverse do |_from_spec, _dep, to_spec, trail|
        if to_spec.has_conflicts? || to_spec.conficts_when_loaded_with?(trail)
          :next
        else
          return trail.reverse if to_spec.contains_requirable_file? path
        end
      end
    end

    []
  end

  def self.unresolved_specs
    unresolved_deps.values.flat_map(&:to_specs)
  end
  private_class_method :unresolved_specs

  ##
  # Special loader for YAML files.  When a Specification object is loaded
  # from a YAML file, it bypasses the normal Ruby object initialization
  # routine (#initialize).  This method makes up for that and deals with
  # gems of different ages.
  #
  # +input+ can be anything that YAML.load() accepts: String or IO.

  def self.from_yaml(input)
    Gem.load_yaml

    input = normalize_yaml_input input
    spec = Gem::SafeYAML.safe_load input

    if spec && spec.class == FalseClass
      raise Gem::EndOfYAMLException
    end

    unless Gem::Specification === spec
      raise Gem::Exception, "YAML data doesn't evaluate to gem specification"
    end

    spec.specification_version ||= NONEXISTENT_SPECIFICATION_VERSION
    spec.reset_nil_attributes_to_default
    spec.flatten_require_paths

    spec
  end

  ##
  # Return the latest specs, optionally including prerelease specs if
  # +prerelease+ is true.

  def self.latest_specs(prerelease = false)
    specification_record.latest_specs(prerelease)
  end

  ##
  # Return the latest installed spec for gem +name+.

  def self.latest_spec_for(name)
    specification_record.latest_spec_for(name)
  end

  def self._latest_specs(specs, prerelease = false) # :nodoc:
    result = {}

    specs.reverse_each do |spec|
      unless prerelease
        next if spec.version.prerelease?
      end

      result[spec.name] = spec
    end

    result.flat_map(&:last).sort_by(&:name)
  end

  ##
  # Loads Ruby format gemspec from +file+.

  def self.load(file)
    return unless file

    spec = @load_cache_mutex.synchronize { @load_cache[file] }
    return spec if spec

    return unless File.file?(file)

    code = Gem.open_file(file, "r:UTF-8:-", &:read)

    begin
      spec = eval code, binding, file

      if Gem::Specification === spec
        spec.loaded_from = File.expand_path file.to_s
        @load_cache_mutex.synchronize do
          prev = @load_cache[file]
          if prev
            spec = prev
          else
            @load_cache[file] = spec
          end
        end
        return spec
      end

      warn "[#{file}] isn't a Gem::Specification (#{spec.class} instead)."
    rescue SignalException, SystemExit
      raise
    rescue SyntaxError, StandardError => e
      warn "Invalid gemspec in [#{file}]: #{e}"
    end

    nil
  end

  ##
  # Specification attributes that must be non-nil

  def self.non_nil_attributes
    @@non_nil_attributes.dup
  end

  ##
  # Make sure the YAML specification is properly formatted with dashes

  def self.normalize_yaml_input(input)
    result = input.respond_to?(:read) ? input.read : input
    result = "--- " + result unless result.start_with?("--- ")
    result = result.dup
    result.gsub!(/ !!null \n/, " \n")
    # date: 2011-04-26 00:00:00.000000000Z
    # date: 2011-04-26 00:00:00.000000000 Z
    result.gsub!(/^(date: \d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d+?)Z/, '\1 Z')
    result
  end

  ##
  # Return a list of all outdated local gem names.  This method is HEAVY
  # as it must go fetch specifications from the server.
  #
  # Use outdated_and_latest_version if you wish to retrieve the latest remote
  # version as well.

  def self.outdated
    outdated_and_latest_version.map {|local, _| local.name }
  end

  ##
  # Enumerates the outdated local gems yielding the local specification and
  # the latest remote version.
  #
  # This method may take some time to return as it must check each local gem
  # against the server's index.

  def self.outdated_and_latest_version
    return enum_for __method__ unless block_given?

    # TODO: maybe we should switch to rubygems' version service?
    fetcher = Gem::SpecFetcher.fetcher

    latest_specs(true).each do |local_spec|
      dependency =
        Gem::Dependency.new local_spec.name, ">= #{local_spec.version}"

      remotes, = fetcher.search_for_dependency dependency
      remotes  = remotes.map {|n, _| n.version }

      latest_remote = remotes.sort.last

      yield [local_spec, latest_remote] if
        latest_remote && local_spec.version < latest_remote
    end

    nil
  end

  ##
  # Is +name+ a required attribute?

  def self.required_attribute?(name)
    @@required_attributes.include? name.to_sym
  end

  ##
  # Required specification attributes

  def self.required_attributes
    @@required_attributes.dup
  end

  ##
  # Reset the list of known specs, running pre and post reset hooks
  # registered in Gem.

  def self.reset
    @@dirs = nil
    Gem.pre_reset_hooks.each(&:call)
    @specification_record = nil
    clear_load_cache

    unless unresolved_deps.empty?
      unresolved = unresolved_deps.filter_map do |name, dep|
        matching_versions = find_all_by_name(name)
        next if dep.latest_version? && matching_versions.any?(&:default_gem?)

        [dep, matching_versions.uniq(&:full_name)]
      end.to_h

      unless unresolved.empty?
        warn "WARN: Unresolved or ambiguous specs during Gem::Specification.reset:"
        unresolved.each do |dep, versions|
          warn "      #{dep}"

          unless versions.empty?
            warn "      Available/installed versions of this gem:"
            versions.each {|s| warn "      - #{s.version}" }
          end
        end
        warn "WARN: Clearing out unresolved specs. Try 'gem cleanup <gem>'"
        warn "Please report a bug if this causes problems."
      end

      unresolved_deps.clear
    end
    Gem.post_reset_hooks.each(&:call)
  end

  ##
  # Keeps track of all currently known specifications

  def self.specification_record
    @specification_record ||= Gem::SpecificationRecord.new(dirs)
  end

  # DOC: This method needs documented or nodoc'd
  def self.unresolved_deps
    @unresolved_deps ||= Hash.new {|h, n| h[n] = Gem::Dependency.new n }
  end

  ##
  # Load custom marshal format, re-initializing defaults as needed

  def self._load(str)
    Gem.load_yaml
    Gem.load_safe_marshal

    yaml_set = false
    retry_count = 0

    array = begin
      Gem::SafeMarshal.safe_load str
    rescue ArgumentError => e
      # Avoid an infinite retry loop when the argument error has nothing to do
      # with the classes not being defined.
      # 1 retry each allowed in case all 3 of
      # - YAML
      # - YAML::Syck::DefaultKey
      # - YAML::PrivateType
      # need to be defined
      raise if retry_count >= 3

      #
      # Some very old marshaled specs included references to `YAML::PrivateType`
      # and `YAML::Syck::DefaultKey` constants due to bugs in the old emitter
      # that generated them. Workaround the issue by defining the necessary
      # constants and retrying.
      #
      message = e.message
      raise unless message.include?("YAML::")

      unless Object.const_defined?(:YAML)
        Object.const_set "YAML", Psych
        yaml_set = true
      end

      if message.include?("YAML::Syck::")
        YAML.const_set "Syck", YAML unless YAML.const_defined?(:Syck)

        YAML::Syck.const_set "DefaultKey", Class.new if message.include?("YAML::Syck::DefaultKey") && !YAML::Syck.const_defined?(:DefaultKey)
      elsif message.include?("YAML::PrivateType") && !YAML.const_defined?(:PrivateType)
        YAML.const_set "PrivateType", Class.new
      end

      retry_count += 1
      retry
    ensure
      Object.__send__(:remove_const, "YAML") if yaml_set
    end

    spec = Gem::Specification.new
    spec.instance_variable_set :@specification_version, array[1]

    current_version = CURRENT_SPECIFICATION_VERSION

    field_count = if spec.specification_version > current_version
      spec.instance_variable_set :@specification_version,
                                 current_version
      MARSHAL_FIELDS[current_version]
    else
      MARSHAL_FIELDS[spec.specification_version]
    end

    if array.size < field_count
      raise TypeError, "invalid Gem::Specification format #{array.inspect}"
    end

    spec.instance_variable_set :@rubygems_version,          array[0]
    # spec version
    spec.instance_variable_set :@name,                      array[2]
    spec.instance_variable_set :@version,                   array[3]
    spec.date =                                             array[4]
    spec.instance_variable_set :@summary,                   array[5]
    spec.instance_variable_set :@required_ruby_version,     array[6]
    spec.instance_variable_set :@required_rubygems_version, array[7]
    spec.platform =                                         array[8]
    spec.instance_variable_set :@dependencies,              array[9]
    # offset due to rubyforge_project removal
    spec.instance_variable_set :@email,                     array[11]
    spec.instance_variable_set :@authors,                   array[12]
    spec.instance_variable_set :@description,               array[13]
    spec.instance_variable_set :@homepage,                  array[14]
    spec.instance_variable_set :@has_rdoc,                  array[15]
    spec.instance_variable_set :@licenses,                  array[17]
    spec.instance_variable_set :@metadata,                  array[18]
    spec.instance_variable_set :@loaded,                    false
    spec.instance_variable_set :@activated,                 false

    spec
  end

  def <=>(other) # :nodoc:
    sort_obj <=> other.sort_obj
  end

  def ==(other) # :nodoc:
    self.class === other &&
      name == other.name &&
      version == other.version &&
      platform == other.platform
  end

  ##
  # Dump only crucial instance variables.
  #--
  # MAINTAIN ORDER!
  # (down with the man)

  def _dump(limit)
    Marshal.dump [
      @rubygems_version,
      @specification_version,
      @name,
      @version,
      date,
      @summary,
      @required_ruby_version,
      @required_rubygems_version,
      @original_platform,
      @dependencies,
      "", # rubyforge_project
      @email,
      @authors,
      @description,
      @homepage,
      true, # has_rdoc
      @new_platform,
      @licenses,
      @metadata,
    ]
  end

  ##
  # Activate this spec, registering it as a loaded spec and adding
  # it's lib paths to $LOAD_PATH. Returns true if the spec was
  # activated, false if it was previously activated. Freaks out if
  # there are conflicts upon activation.

  def activate
    other = Gem.loaded_specs[name]
    if other
      check_version_conflict other
      return false
    end

    raise_if_conflicts

    activate_dependencies
    add_self_to_load_path

    Gem.loaded_specs[name] = self
    @activated = true
    @loaded = true

    true
  end

  ##
  # Activate all unambiguously resolved runtime dependencies of this
  # spec. Add any ambiguous dependencies to the unresolved list to be
  # resolved later, as needed.

  def activate_dependencies
    unresolved = Gem::Specification.unresolved_deps

    runtime_dependencies.each do |spec_dep|
      if loaded = Gem.loaded_specs[spec_dep.name]
        next if spec_dep.matches_spec? loaded

        msg = "can't satisfy '#{spec_dep}', already activated '#{loaded.full_name}'"
        e = Gem::LoadError.new msg
        e.name = spec_dep.name

        raise e
      end

      specs = spec_dep.matching_specs(true).uniq(&:full_name)

      if specs.size == 0
        raise Gem::MissingSpecError.new(spec_dep.name, spec_dep.requirement, "at: #{spec_file}")
      elsif specs.size == 1
        specs.first.activate
      else
        name = spec_dep.name
        unresolved[name] = unresolved[name].merge spec_dep
      end
    end

    unresolved.delete self.name
  end

  ##
  # Abbreviate the spec for downloading.  Abbreviated specs are only used for
  # searching, downloading and related activities and do not need deployment
  # specific information (e.g. list of files).  So we abbreviate the spec,
  # making it much smaller for quicker downloads.

  def abbreviate
    self.files = []
    self.test_files = []
    self.rdoc_options = []
    self.extra_rdoc_files = []
    self.cert_chain = []
  end

  ##
  # Sanitize the descriptive fields in the spec.  Sometimes non-ASCII
  # characters will garble the site index.  Non-ASCII characters will
  # be replaced by their XML entity equivalent.

  def sanitize
    self.summary              = sanitize_string(summary)
    self.description          = sanitize_string(description)
    self.post_install_message = sanitize_string(post_install_message)
    self.authors              = authors.collect {|a| sanitize_string(a) }
  end

  ##
  # Sanitize a single string.

  def sanitize_string(string)
    return string unless string

    # HACK: the #to_s is in here because RSpec has an Array of Arrays of
    # Strings for authors.  Need a way to disallow bad values on gemspec
    # generation.  (Probably won't happen.)
    string.to_s
  end

  ##
  # Returns an array with bindir attached to each executable in the
  # +executables+ list

  def add_bindir(executables)
    return nil if executables.nil?

    if @bindir
      Array(executables).map {|e| File.join(@bindir, e) }
    else
      executables
    end
  rescue StandardError
    nil
  end

  ##
  # Adds a dependency on gem +dependency+ with type +type+ that requires
  # +requirements+.  Valid types are currently <tt>:runtime</tt> and
  # <tt>:development</tt>.

  def add_dependency_with_type(dependency, type, requirements)
    requirements = if requirements.empty?
      Gem::Requirement.default
    else
      requirements.flatten
    end

    unless dependency.respond_to?(:name) &&
           dependency.respond_to?(:requirement)
      dependency = Gem::Dependency.new(dependency.to_s, requirements, type)
    end

    dependencies << dependency
  end

  private :add_dependency_with_type

  alias_method :add_runtime_dependency, :add_dependency

  ##
  # Adds this spec's require paths to LOAD_PATH, in the proper location.

  def add_self_to_load_path
    return if default_gem?

    paths = full_require_paths

    Gem.add_to_load_path(*paths)
  end

  ##
  # Singular reader for #authors.  Returns the first author in the list

  def author
    (val = authors) && val.first
  end

  ##
  # The list of author names who wrote this gem.
  #
  #   spec.authors = ['Chad Fowler', 'Jim Weirich', 'Rich Kilmer']

  def authors
    @authors ||= []
  end

  ##
  # Returns the full path to installed gem's bin directory.
  #
  # NOTE: do not confuse this with +bindir+, which is just 'bin', not
  # a full path.

  def bin_dir
    @bin_dir ||= File.join gem_dir, bindir
  end

  ##
  # Returns the full path to an executable named +name+ in this gem.

  def bin_file(name)
    File.join bin_dir, name
  end

  ##
  # Returns the build_args used to install the gem

  def build_args
    if File.exist? build_info_file
      build_info = File.readlines build_info_file
      build_info = build_info.map(&:strip)
      build_info.delete ""
      build_info
    else
      []
    end
  end

  ##
  # Builds extensions for this platform if the gem has extensions listed and
  # the gem.build_complete file is missing.

  def build_extensions # :nodoc:
    return if extensions.empty?
    return if default_gem?
    # we need to fresh build when same name and version of default gems
    return if self.class.find_by_full_name(full_name)&.default_gem?
    return if File.exist? gem_build_complete_path
    return unless File.writable?(base_dir)
    return unless File.exist?(File.join(base_dir, "extensions"))

    begin
      # We need to require things in $LOAD_PATH without looking for the
      # extension we are about to build.
      unresolved_deps = Gem::Specification.unresolved_deps.dup
      Gem::Specification.unresolved_deps.clear

      require_relative "config_file"
      require_relative "ext"
      require_relative "user_interaction"

      ui = Gem::SilentUI.new
      Gem::DefaultUserInteraction.use_ui ui do
        builder = Gem::Ext::Builder.new self
        builder.build_extensions
      end
    ensure
      ui&.close
      Gem::Specification.unresolved_deps.replace unresolved_deps
    end
  end

  ##
  # Returns the full path to the build info directory

  def build_info_dir
    File.join base_dir, "build_info"
  end

  ##
  # Returns the full path to the file containing the build
  # information generated when the gem was installed

  def build_info_file
    File.join build_info_dir, "#{full_name}.info"
  end

  ##
  # Returns the full path to the cache directory containing this
  # spec's cached gem.

  def cache_dir
    @cache_dir ||= File.join base_dir, "cache"
  end

  ##
  # Returns the full path to the cached gem for this spec.

  def cache_file
    @cache_file ||= File.join cache_dir, "#{full_name}.gem"
  end

  ##
  # Return any possible conflicts against the currently loaded specs.

  def conflicts
    conflicts = {}
    runtime_dependencies.each do |dep|
      spec = Gem.loaded_specs[dep.name]
      if spec && !spec.satisfies_requirement?(dep)
        (conflicts[spec] ||= []) << dep
      end
    end
    env_req = Gem.env_requirement(name)
    (conflicts[self] ||= []) << env_req unless env_req.satisfied_by? version
    conflicts
  end

  ##
  # return true if there will be conflict when spec if loaded together with the list of specs.

  def conficts_when_loaded_with?(list_of_specs) # :nodoc:
    result = list_of_specs.any? do |spec|
      spec.runtime_dependencies.any? {|dep| (dep.name == name) && !satisfies_requirement?(dep) }
    end
    result
  end

  ##
  # Return true if there are possible conflicts against the currently loaded specs.

  def has_conflicts?
    return true unless Gem.env_requirement(name).satisfied_by?(version)
    runtime_dependencies.any? do |dep|
      spec = Gem.loaded_specs[dep.name]
      spec && !spec.satisfies_requirement?(dep)
    end
  rescue ArgumentError => e
    raise e, "#{name} #{version}: #{e.message}"
  end

  # The date this gem was created.
  #
  # If SOURCE_DATE_EPOCH is set as an environment variable, use that to support
  # reproducible builds; otherwise, default to the current UTC date.
  #
  # Details on SOURCE_DATE_EPOCH:
  # https://reproducible-builds.org/specs/source-date-epoch/

  def date
    @date ||= Time.utc(*Gem.source_date_epoch.utc.to_a[3..5].reverse)
  end

  DateLike = Object.new # :nodoc:
  def DateLike.===(obj) # :nodoc:
    defined?(::Date) && Date === obj
  end

  DateTimeFormat = # :nodoc:
    /\A
     (\d{4})-(\d{2})-(\d{2})
     (\s+ \d{2}:\d{2}:\d{2}\.\d+ \s* (Z | [-+]\d\d:\d\d) )?
     \Z/x

  ##
  # The date this gem was created
  #
  # DO NOT set this, it is set automatically when the gem is packaged.

  def date=(date)
    # We want to end up with a Time object with one-day resolution.
    # This is the cleanest, most-readable, faster-than-using-Date
    # way to do it.
    @date = case date
            when String then
              if DateTimeFormat =~ date
                Time.utc($1.to_i, $2.to_i, $3.to_i)
              else
                raise(Gem::InvalidSpecificationException,
                      "invalid date format in specification: #{date.inspect}")
              end
            when Time, DateLike then
              Time.utc(date.year, date.month, date.day)
            else
              TODAY
    end
  end

  ##
  # The default executable for this gem.
  #
  # Deprecated: The name of the gem is assumed to be the name of the
  # executable now.  See Gem.bin_path.

  def default_executable # :nodoc:
    if defined?(@default_executable) && @default_executable
      result = @default_executable
    elsif @executables && @executables.size == 1
      result = Array(@executables).first
    else
      result = nil
    end
    result
  end
  rubygems_deprecate :default_executable

  ##
  # The default value for specification attribute +name+

  def default_value(name)
    @@default_value[name]
  end

  ##
  # A list of Gem::Dependency objects this gem depends on.
  #
  # Use #add_dependency or #add_development_dependency to add dependencies to
  # a gem.

  def dependencies
    @dependencies ||= []
  end

  ##
  # Return a list of all gems that have a dependency on this gemspec.  The
  # list is structured with entries that conform to:
  #
  #   [depending_gem, dependency, [list_of_gems_that_satisfy_dependency]]

  def dependent_gems(check_dev=true)
    out = []
    Gem::Specification.each do |spec|
      deps = check_dev ? spec.dependencies : spec.runtime_dependencies
      deps.each do |dep|
        next unless satisfies_requirement?(dep)
        sats = []
        find_all_satisfiers(dep) do |sat|
          sats << sat
        end
        out << [spec, dep, sats]
      end
    end
    out
  end

  ##
  # Returns all specs that matches this spec's runtime dependencies.

  def dependent_specs
    runtime_dependencies.flat_map(&:to_specs)
  end

  ##
  # A detailed description of this gem.  See also #summary

  def description=(str)
    @description = str.to_s
  end

  ##
  # List of dependencies that are used for development

  def development_dependencies
    dependencies.select {|d| d.type == :development }
  end

  ##
  # Returns the full path to this spec's documentation directory.  If +type+
  # is given it will be appended to the end.  For example:
  #
  #   spec.doc_dir      # => "/path/to/gem_repo/doc/a-1"
  #
  #   spec.doc_dir 'ri' # => "/path/to/gem_repo/doc/a-1/ri"

  def doc_dir(type = nil)
    @doc_dir ||= File.join base_dir, "doc", full_name

    if type
      File.join @doc_dir, type
    else
      @doc_dir
    end
  end

  def encode_with(coder) # :nodoc:
    coder.add "name", @name
    coder.add "version", @version
    coder.add "platform", platform.to_s
    coder.add "original_platform", original_platform.to_s if platform.to_s != original_platform.to_s

    attributes = @@attributes.map(&:to_s) - %w[name version platform]
    attributes.each do |name|
      value = instance_variable_get("@#{name}")
      coder.add name, value unless value.nil?
    end
  end

  def eql?(other) # :nodoc:
    self.class === other && same_attributes?(other)
  end

  ##
  # Singular accessor for #executables

  def executable
    (val = executables) && val.first
  end

  ##
  # Singular accessor for #executables

  def executable=(o)
    self.executables = [o]
  end

  ##
  # Sets executables to +value+, ensuring it is an array.

  def executables=(value)
    @executables = Array(value)
  end

  ##
  # Sets extensions to +extensions+, ensuring it is an array.

  def extensions=(extensions)
    @extensions = Array extensions
  end

  ##
  # Sets extra_rdoc_files to +files+, ensuring it is an array.

  def extra_rdoc_files=(files)
    @extra_rdoc_files = Array files
  end

  ##
  # The default (generated) file name of the gem.  See also #spec_name.
  #
  #   spec.file_name # => "example-1.0.gem"

  def file_name
    "#{full_name}.gem"
  end

  ##
  # Sets files to +files+, ensuring it is an array.

  def files=(files)
    @files = Array files
  end

  ##
  # Finds all gems that satisfy +dep+

  def find_all_satisfiers(dep)
    Gem::Specification.each do |spec|
      yield spec if spec.satisfies_requirement? dep
    end
  end

  private :find_all_satisfiers

  ##
  # Creates a duplicate spec without large blobs that aren't used at runtime.

  def for_cache
    spec = dup

    spec.files = nil
    spec.test_files = nil

    spec
  end

  def full_name
    @full_name ||= super
  end

  ##
  # Work around old bundler versions removing my methods
  # Can be removed once RubyGems can no longer install Bundler 2.5

  def gem_dir # :nodoc:
    super
  end

  def gems_dir
    @gems_dir ||= File.join(base_dir, "gems")
  end

  ##
  # Deprecated and ignored, defaults to true.
  #
  # Formerly used to indicate this gem was RDoc-capable.

  def has_rdoc # :nodoc:
    true
  end
  rubygems_deprecate :has_rdoc

  ##
  # Deprecated and ignored.
  #
  # Formerly used to indicate this gem was RDoc-capable.

  def has_rdoc=(ignored) # :nodoc:
    @has_rdoc = true
  end
  rubygems_deprecate :has_rdoc=

  alias_method :has_rdoc?, :has_rdoc # :nodoc:
  rubygems_deprecate :has_rdoc?

  ##
  # True if this gem has files in test_files

  def has_unit_tests? # :nodoc:
    !test_files.empty?
  end

  # :stopdoc:
  alias_method :has_test_suite?, :has_unit_tests?
  # :startdoc:

  def hash # :nodoc:
    name.hash ^ version.hash
  end

  def init_with(coder) # :nodoc:
    @installed_by_version ||= nil
    yaml_initialize coder.tag, coder.map
  end

  eval <<-RUBY, binding, __FILE__, __LINE__ + 1
    # frozen_string_literal: true

    def set_nil_attributes_to_nil
      #{@@nil_attributes.map {|key| "@#{key} = nil" }.join "; "}
    end
    private :set_nil_attributes_to_nil

    def set_not_nil_attributes_to_default_values
      #{@@non_nil_attributes.map {|key| "@#{key} = #{INITIALIZE_CODE_FOR_DEFAULTS[key]}" }.join ";"}
    end
    private :set_not_nil_attributes_to_default_values
  RUBY

  ##
  # Specification constructor. Assigns the default values to the attributes
  # and yields itself for further initialization.  Optionally takes +name+ and
  # +version+.

  def initialize(name = nil, version = nil)
    super()
    @gems_dir              = nil
    @base_dir              = nil
    @loaded = false
    @activated = false
    @loaded_from = nil
    @original_platform = nil
    @installed_by_version = nil

    set_nil_attributes_to_nil
    set_not_nil_attributes_to_default_values

    @new_platform = Gem::Platform::RUBY

    self.name = name if name
    self.version = version if version

    if (platform = Gem.platforms.last) && platform != Gem::Platform::RUBY && platform != Gem::Platform.local
      self.platform = platform
    end

    yield self if block_given?
  end

  ##
  # Duplicates Array and Gem::Requirement attributes from +other_spec+ so state isn't shared.
  #

  def initialize_copy(other_spec)
    self.class.array_attributes.each do |name|
      name = :"@#{name}"
      next unless other_spec.instance_variable_defined? name

      begin
        val = other_spec.instance_variable_get(name)
        if val
          instance_variable_set name, val.dup
        elsif Gem.configuration.really_verbose
          warn "WARNING: #{full_name} has an invalid nil value for #{name}"
        end
      rescue TypeError
        e = Gem::FormatException.new \
          "#{full_name} has an invalid value for #{name}"

        e.file_path = loaded_from
        raise e
      end
    end

    @required_ruby_version = other_spec.required_ruby_version.dup
    @required_rubygems_version = other_spec.required_rubygems_version.dup
  end

  def base_dir
    return Gem.dir unless loaded_from
    @base_dir ||= if default_gem?
      File.dirname File.dirname File.dirname loaded_from
    else
      File.dirname File.dirname loaded_from
    end
  end

  ##
  # Expire memoized instance variables that can incorrectly generate, replace
  # or miss files due changes in certain attributes used to compute them.

  def invalidate_memoized_attributes
    @full_name = nil
    @cache_file = nil
  end

  private :invalidate_memoized_attributes

  def inspect # :nodoc:
    if $DEBUG
      super
    else
      "#{super[0..-2]} #{full_name}>"
    end
  end

  ##
  # Files in the Gem under one of the require_paths

  def lib_files
    @files.select do |file|
      require_paths.any? do |path|
        file.start_with? path
      end
    end
  end

  ##
  # Singular accessor for #licenses

  def license
    licenses.first
  end

  ##
  # Plural accessor for setting licenses
  #
  # See #license= for details

  def licenses
    @licenses ||= []
  end

  def internal_init # :nodoc:
    super
    @bin_dir       = nil
    @cache_dir     = nil
    @cache_file    = nil
    @doc_dir       = nil
    @ri_dir        = nil
    @spec_dir      = nil
    @spec_file     = nil
  end

  ##
  # Track removed method calls to warn about during build time.
  # Warn about unknown attributes while loading a spec.

  def method_missing(sym, *a, &b) # :nodoc:
    if REMOVED_METHODS.include?(sym)
      removed_method_calls << sym
      return
    end

    if @specification_version > CURRENT_SPECIFICATION_VERSION &&
       sym.to_s.end_with?("=")
      warn "ignoring #{sym} loading #{full_name}" if $DEBUG
    else
      super
    end
  end

  ##
  # Is this specification missing its extensions?  When this returns true you
  # probably want to build_extensions

  def missing_extensions?
    return false if extensions.empty?
    return false if default_gem?
    return false if File.exist? gem_build_complete_path

    true
  end

  ##
  # Normalize the list of files so that:
  # * All file lists have redundancies removed.
  # * Files referenced in the extra_rdoc_files are included in the package
  #   file list.

  def normalize
    if defined?(@extra_rdoc_files) && @extra_rdoc_files
      @extra_rdoc_files.uniq!
      @files ||= []
      @files.concat(@extra_rdoc_files)
    end

    @files            = @files.uniq.sort if @files
    @extensions       = @extensions.uniq.sort if @extensions
    @test_files       = @test_files.uniq.sort if @test_files
    @executables      = @executables.uniq.sort if @executables
    @extra_rdoc_files = @extra_rdoc_files.uniq.sort if @extra_rdoc_files
  end

  ##
  # Return a NameTuple that represents this Specification

  def name_tuple
    Gem::NameTuple.new name, version, original_platform
  end

  ##
  # Returns the full name (name-version) of this gemspec using the original
  # platform.  For use with legacy gems.

  def original_name # :nodoc:
    if platform == Gem::Platform::RUBY || platform.nil?
      "#{@name}-#{@version}"
    else
      "#{@name}-#{@version}-#{@original_platform}"
    end
  end

  ##
  # Cruft. Use +platform+.

  def original_platform # :nodoc:
    @original_platform ||= platform
  end

  ##
  # The platform this gem runs on.  See Gem::Platform for details.

  def platform
    @new_platform ||= Gem::Platform::RUBY # rubocop:disable Naming/MemoizedInstanceVariableName
  end

  def pretty_print(q) # :nodoc:
    q.group 2, "Gem::Specification.new do |s|", "end" do
      q.breakable

      attributes = @@attributes - [:name, :version]
      attributes.unshift :installed_by_version
      attributes.unshift :version
      attributes.unshift :name

      attributes.each do |attr_name|
        current_value = send attr_name
        current_value = current_value.sort if [:files, :test_files].include? attr_name
        next unless current_value != default_value(attr_name) ||
                    self.class.required_attribute?(attr_name)

        q.text "s.#{attr_name} = "

        if attr_name == :date
          current_value = current_value.utc

          q.text "Time.utc(#{current_value.year}, #{current_value.month}, #{current_value.day})"
        else
          q.pp current_value
        end

        q.breakable
      end
    end
  end

  ##
  # Raise an exception if the version of this spec conflicts with the one
  # that is already loaded (+other+)

  def check_version_conflict(other) # :nodoc:
    return if version == other.version

    # This gem is already loaded.  If the currently loaded gem is not in the
    # list of candidate gems, then we have a version conflict.

    msg = "can't activate #{full_name}, already activated #{other.full_name}"

    e = Gem::LoadError.new msg
    e.name = name

    raise e
  end

  private :check_version_conflict

  ##
  # Check the spec for possible conflicts and freak out if there are any.

  def raise_if_conflicts # :nodoc:
    if has_conflicts?
      raise Gem::ConflictError.new self, conflicts
    end
  end

  ##
  # Sets rdoc_options to +value+, ensuring it is an array.

  def rdoc_options=(options)
    @rdoc_options = Array options
  end

  ##
  # Singular accessor for #require_paths

  def require_path
    (val = require_paths) && val.first
  end

  ##
  # Singular accessor for #require_paths

  def require_path=(path)
    self.require_paths = Array(path)
  end

  ##
  # Set requirements to +req+, ensuring it is an array.

  def requirements=(req)
    @requirements = Array req
  end

  def respond_to_missing?(m, include_private = false) # :nodoc:
    false
  end

  ##
  # Returns the full path to this spec's ri directory.

  def ri_dir
    @ri_dir ||= File.join base_dir, "ri", full_name
  end

  ##
  # Return a string containing a Ruby code representation of the given
  # object.

  def ruby_code(obj)
    case obj
    when String             then obj.dump + ".freeze"
    when Array              then "[" + obj.map {|x| ruby_code x }.join(", ") + "]"
    when Hash               then
      seg = obj.keys.sort.map {|k| "#{k.to_s.dump} => #{obj[k].to_s.dump}" }
      "{ #{seg.join(", ")} }"
    when Gem::Version       then ruby_code(obj.to_s)
    when DateLike           then obj.strftime("%Y-%m-%d").dump
    when Time               then obj.strftime("%Y-%m-%d").dump
    when Numeric            then obj.inspect
    when true, false, nil   then obj.inspect
    when Gem::Platform      then "Gem::Platform.new(#{ruby_code obj.to_a})"
    when Gem::Requirement   then
      list = obj.as_list
      "Gem::Requirement.new(#{ruby_code(list.size == 1 ? obj.to_s : list)})"
    else raise Gem::Exception, "ruby_code case not handled: #{obj.class}"
    end
  end

  private :ruby_code

  ##
  # List of dependencies that will automatically be activated at runtime.

  def runtime_dependencies
    dependencies.select(&:runtime?)
  end

  ##
  # True if this gem has the same attributes as +other+.

  def same_attributes?(spec)
    @@attributes.all? {|name, _default| send(name) == spec.send(name) }
  end

  private :same_attributes?

  ##
  # Checks if this specification meets the requirement of +dependency+.

  def satisfies_requirement?(dependency)
    @name == dependency.name &&
      dependency.requirement.satisfied_by?(@version)
  end

  ##
  # Returns an object you can use to sort specifications in #sort_by.

  def sort_obj
    [@name, @version, Gem::Platform.sort_priority(@new_platform)]
  end

  ##
  # Used by Gem::Resolver to order Gem::Specification objects

  def source # :nodoc:
    Gem::Source::Installed.new
  end

  ##
  # Returns the full path to the directory containing this spec's
  # gemspec file. eg: /usr/local/lib/ruby/gems/1.8/specifications

  def spec_dir
    @spec_dir ||= File.join base_dir, "specifications"
  end

  ##
  # Returns the full path to this spec's gemspec file.
  # eg: /usr/local/lib/ruby/gems/1.8/specifications/mygem-1.0.gemspec

  def spec_file
    @spec_file ||= File.join spec_dir, "#{full_name}.gemspec"
  end

  ##
  # The default name of the gemspec.  See also #file_name
  #
  #   spec.spec_name # => "example-1.0.gemspec"

  def spec_name
    "#{full_name}.gemspec"
  end

  ##
  # A short summary of this gem's description.

  def summary=(str)
    @summary = str.to_s.strip.
      gsub(/(\w-)\n[ \t]*(\w)/, '\1\2').gsub(/\n[ \t]*/, " ") # so. weird.
  end

  ##
  # Singular accessor for #test_files

  def test_file # :nodoc:
    (val = test_files) && val.first
  end

  ##
  # Singular mutator for #test_files

  def test_file=(file) # :nodoc:
    self.test_files = [file]
  end

  ##
  # Test files included in this gem.  You cannot append to this accessor, you
  # must assign to it.

  def test_files # :nodoc:
    # Handle the possibility that we have @test_suite_file but not
    # @test_files.  This will happen when an old gem is loaded via
    # YAML.
    if defined? @test_suite_file
      @test_files = [@test_suite_file].flatten
      @test_suite_file = nil
    end
    if defined?(@test_files) && @test_files
      @test_files
    else
      @test_files = []
    end
  end

  ##
  # Returns a Ruby code representation of this specification, such that it can
  # be eval'ed and reconstruct the same specification later.  Attributes that
  # still have their default values are omitted.

  def to_ruby
    result = []
    result << "# -*- encoding: utf-8 -*-"
    result << "#{Gem::StubSpecification::PREFIX}#{name} #{version} #{platform} #{raw_require_paths.join("\0")}"
    result << "#{Gem::StubSpecification::PREFIX}#{extensions.join "\0"}" unless
      extensions.empty?
    result << nil
    result << "Gem::Specification.new do |s|"

    result << "  s.name = #{ruby_code name}"
    result << "  s.version = #{ruby_code version}"
    unless platform.nil? || platform == Gem::Platform::RUBY
      result << "  s.platform = #{ruby_code original_platform}"
    end
    result << ""
    result << "  s.required_rubygems_version = #{ruby_code required_rubygems_version} if s.respond_to? :required_rubygems_version="

    if metadata && !metadata.empty?
      result << "  s.metadata = #{ruby_code metadata} if s.respond_to? :metadata="
    end
    result << "  s.require_paths = #{ruby_code raw_require_paths}"

    handled = [
      :dependencies,
      :name,
      :platform,
      :require_paths,
      :required_rubygems_version,
      :specification_version,
      :version,
      :has_rdoc,
      :default_executable,
      :metadata,
      :signing_key,
    ]

    @@attributes.each do |attr_name|
      next if handled.include? attr_name
      current_value = send(attr_name)
      if current_value != default_value(attr_name) || self.class.required_attribute?(attr_name)
        result << "  s.#{attr_name} = #{ruby_code current_value}"
      end
    end

    if String === signing_key
      result << "  s.signing_key = #{ruby_code signing_key}"
    end

    if @installed_by_version
      result << nil
      result << "  s.installed_by_version = #{ruby_code Gem::VERSION}"
    end

    unless dependencies.empty?
      result << nil
      result << "  s.specification_version = #{specification_version}"
      result << nil

      dependencies.each do |dep|
        dep.instance_variable_set :@type, :runtime if dep.type.nil? # HACK
        result << "  s.add_#{dep.type}_dependency(%q<#{dep.name}>.freeze, #{ruby_code dep.requirements_list})"
      end
    end

    result << "end"
    result << nil

    result.join "\n"
  end

  ##
  # Returns a Ruby lighter-weight code representation of this specification,
  # used for indexing only.
  #
  # See #to_ruby.

  def to_ruby_for_cache
    for_cache.to_ruby
  end

  def to_s # :nodoc:
    "#<Gem::Specification name=#{@name} version=#{@version}>"
  end

  ##
  # Returns self

  def to_spec
    self
  end

  def to_yaml(opts = {}) # :nodoc:
    Gem.load_yaml

    # Because the user can switch the YAML engine behind our
    # back, we have to check again here to make sure that our
    # psych code was properly loaded, and load it if not.
    unless Gem.const_defined?(:NoAliasYAMLTree)
      require_relative "psych_tree"
    end

    builder = Gem::NoAliasYAMLTree.create
    builder << self
    ast = builder.tree

    require "stringio"
    io = StringIO.new
    io.set_encoding Encoding::UTF_8

    Psych::Visitors::Emitter.new(io).accept(ast)

    io.string.gsub(/ !!null \n/, " \n")
  end

  ##
  # Recursively walk dependencies of this spec, executing the +block+ for each
  # hop.

  def traverse(trail = [], visited = {}, &block)
    trail.push(self)
    begin
      runtime_dependencies.each do |dep|
        dep.matching_specs(true).each do |dep_spec|
          next if visited.key?(dep_spec)
          visited[dep_spec] = true
          trail.push(dep_spec)
          begin
            result = block[self, dep, dep_spec, trail]
          ensure
            trail.pop
          end
          next if result == :next
          spec_name = dep_spec.name
          dep_spec.traverse(trail, visited, &block) unless
            trail.any? {|s| s.name == spec_name }
        end
      end
    ensure
      trail.pop
    end
  end

  ##
  # Checks that the specification contains all required fields, and does a
  # very basic sanity check.
  #
  # Raises InvalidSpecificationException if the spec does not pass the
  # checks..

  def validate(packaging = true, strict = false)
    normalize

    validation_policy = Gem::SpecificationPolicy.new(self)
    validation_policy.packaging = packaging
    validation_policy.validate(strict)
  end

  def keep_only_files_and_directories
    @executables.delete_if      {|x| File.directory?(File.join(@bindir, x)) }
    @extensions.delete_if       {|x| File.directory?(x) && !File.symlink?(x) }
    @extra_rdoc_files.delete_if {|x| File.directory?(x) && !File.symlink?(x) }
    @files.delete_if            {|x| File.directory?(x) && !File.symlink?(x) }
    @test_files.delete_if       {|x| File.directory?(x) && !File.symlink?(x) }
  end

  def validate_for_resolution
    Gem::SpecificationPolicy.new(self).validate_for_resolution
  end

  def validate_metadata
    Gem::SpecificationPolicy.new(self).validate_metadata
  end
  rubygems_deprecate :validate_metadata

  def validate_dependencies
    Gem::SpecificationPolicy.new(self).validate_dependencies
  end
  rubygems_deprecate :validate_dependencies

  def validate_permissions
    Gem::SpecificationPolicy.new(self).validate_permissions
  end
  rubygems_deprecate :validate_permissions

  ##
  # Set the version to +version+.

  def version=(version)
    @version = Gem::Version.create(version)
    return if @version.nil?

    invalidate_memoized_attributes
  end

  def stubbed?
    false
  end

  def yaml_initialize(tag, vals) # :nodoc:
    vals.each do |ivar, val|
      case ivar
      when "date"
        # Force Date to go through the extra coerce logic in date=
        self.date = val
      when "platform"
        self.platform = val
      else
        instance_variable_set "@#{ivar}", val
      end
    end
  end

  ##
  # Reset nil attributes to their default values to make the spec valid

  def reset_nil_attributes_to_default
    nil_attributes = self.class.non_nil_attributes.find_all do |name|
      !instance_variable_defined?("@#{name}") || instance_variable_get("@#{name}").nil?
    end

    nil_attributes.each do |attribute|
      default = default_value attribute

      value = case default
              when Time, Numeric, Symbol, true, false, nil then default
              else default.dup
      end

      instance_variable_set "@#{attribute}", value
    end

    @installed_by_version ||= nil

    nil
  end

  def flatten_require_paths # :nodoc:
    return unless raw_require_paths.first.is_a?(Array)

    warn "#{name} #{version} includes a gemspec with `require_paths` set to an array of arrays. Newer versions of this gem might've already fixed this"
    raw_require_paths.flatten!
  end

  def raw_require_paths # :nodoc:
    @require_paths
  end
end

Youez - 2016 - github.com/yon3zu
LinuXploit