Show More
@@ -1,117 +1,118 b'' | |||
|
1 | 1 | 35fb62a3a673d5322f6274a44ba6456e5e4b3b37 0 iD8DBQBEYmO2ywK+sNU5EO8RAnaYAKCO7x15xUn5mnhqWNXqk/ehlhRt2QCfRDfY0LrUq2q4oK/KypuJYPHgq1A= |
|
2 | 2 | 2be3001847cb18a23c403439d9e7d0ace30804e9 0 iD8DBQBExUbjywK+sNU5EO8RAhzxAKCtyHAQUzcTSZTqlfJ0by6vhREwWQCghaQFHfkfN0l9/40EowNhuMOKnJk= |
|
3 | 3 | 36a957364b1b89c150f2d0e60a99befe0ee08bd3 0 iD8DBQBFfL2QywK+sNU5EO8RAjYFAKCoGlaWRTeMsjdmxAjUYx6diZxOBwCfY6IpBYsKvPTwB3oktnPt5Rmrlys= |
|
4 | 4 | 27230c29bfec36d5540fbe1c976810aefecfd1d2 0 iD8DBQBFheweywK+sNU5EO8RAt7VAKCrqJQWT2/uo2RWf0ZI4bLp6v82jACgjrMdsaTbxRsypcmEsdPhlG6/8F4= |
|
5 | 5 | fb4b6d5fe100b0886f8bc3d6731ec0e5ed5c4694 0 iD8DBQBGgHicywK+sNU5EO8RAgNxAJ0VG8ixAaeudx4sZbhngI1syu49HQCeNUJQfWBgA8bkJ2pvsFpNxwYaX3I= |
|
6 | 6 | 23889160905a1b09fffe1c07378e9fc1827606eb 0 iD8DBQBHGTzoywK+sNU5EO8RAr/UAJ0Y8s4jQtzgS+G9vM8z6CWBThZ8fwCcCT5XDj2XwxKkz/0s6UELwjsO3LU= |
|
7 | 7 | bae2e9c838e90a393bae3973a7850280413e091a 0 iD8DBQBH6DO5ywK+sNU5EO8RAsfrAJ0e4r9c9GF/MJsM7Xjd3NesLRC3+ACffj6+6HXdZf8cswAoFPO+DY00oD0= |
|
8 | 8 | d5cbbe2c49cee22a9fbeb9ea41daa0ac4e26b846 0 iD8DBQBINdwsywK+sNU5EO8RAjIUAKCPmlFJSpsPAAUKF+iNHAwVnwmzeQCdEXrL27CWclXuUKdbQC8De7LICtE= |
|
9 | 9 | d2375bbee6d47e62ba8e415c86e83a465dc4dce9 0 iD8DBQBIo1wpywK+sNU5EO8RAmRNAJ94x3OFt6blbqu/yBoypm/AJ44fuACfUaldXcV5z9tht97hSp22DVTEPGc= |
|
10 | 10 | 2a67430f92f15ea5159c26b09ec4839a0c549a26 0 iEYEABECAAYFAkk1hykACgkQywK+sNU5EO85QACeNJNUanjc2tl4wUoPHNuv+lSj0ZMAoIm93wSTc/feyYnO2YCaQ1iyd9Nu |
|
11 | 11 | 3773e510d433969e277b1863c317b674cbee2065 0 iEYEABECAAYFAklNbbAACgkQywK+sNU5EO8o+gCfeb2/lfIJZMvyDA1m+G1CsBAxfFsAoIa6iAMG8SBY7hW1Q85Yf/LXEvaE |
|
12 | 12 | 11a4eb81fb4f4742451591489e2797dc47903277 0 iEYEABECAAYFAklcAnsACgkQywK+sNU5EO+uXwCbBVHNNsLy1g7BlAyQJwadYVyHOXoAoKvtAVO71+bv7EbVoukwTzT+P4Sx |
|
13 | 13 | 11efa41037e280d08cfb07c09ad485df30fb0ea8 0 iEYEABECAAYFAkmvJRQACgkQywK+sNU5EO9XZwCeLMgDgPSMWMm6vgjL4lDs2pEc5+0AnRxfiFbpbBfuEFTqKz9nbzeyoBlx |
|
14 | 14 | 02981000012e3adf40c4849bd7b3d5618f9ce82d 0 iEYEABECAAYFAknEH3wACgkQywK+sNU5EO+uXwCeI+LbLMmhjU1lKSfU3UWJHjjUC7oAoIZLvYDGOL/tNZFUuatc3RnZ2eje |
|
15 | 15 | 196d40e7c885fa6e95f89134809b3ec7bdbca34b 0 iEYEABECAAYFAkpL2X4ACgkQywK+sNU5EO9FOwCfXJycjyKJXsvQqKkHrglwOQhEKS4An36GfKzptfN8b1qNc3+ya/5c2WOM |
|
16 | 16 | 3ef6c14a1e8e83a31226f5881b7fe6095bbfa6f6 0 iEYEABECAAYFAkpopLIACgkQywK+sNU5EO8QSgCfZ0ztsd071rOa2lhmp9Fyue/WoI0AoLTei80/xrhRlB8L/rZEf2KBl8dA |
|
17 | 17 | 31ec469f9b556f11819937cf68ee53f2be927ebf 0 iEYEABECAAYFAksBuxAACgkQywK+sNU5EO+mBwCfagB+A0txzWZ6dRpug3LEoK7Z1QsAoKpbk8vsLjv6/oRDicSk/qBu33+m |
|
18 | 18 | 439d7ea6fe3aa4ab9ec274a68846779153789de9 0 iEYEABECAAYFAksVw0kACgkQywK+sNU5EO/oZwCfdfBEkgp38xq6wN2F4nj+SzofrJIAnjmxt04vaJSeOOeHylHvk6lzuQsw |
|
19 | 19 | 296a0b14a68621f6990c54fdba0083f6f20935bf 0 iEYEABECAAYFAks+jCoACgkQywK+sNU5EO9J8wCeMUGF9E/gS2UBsqIz56WS4HMPRPUAoI5J95mwEIK8Clrl7qFRidNI6APq |
|
20 | 20 | 4aa619c4c2c09907034d9824ebb1dd0e878206eb 0 iEYEABECAAYFAktm9IsACgkQywK+sNU5EO9XGgCgk4HclRQhexEtooPE5GcUCdB6M8EAn2ptOhMVbIoO+JncA+tNACPFXh0O |
|
21 | 21 | ff2704a8ded37fbebd8b6eb5ec733731d725da8a 0 iEYEABECAAYFAkuRoSQACgkQywK+sNU5EO//3QCeJDc5r2uFyFCtAlpSA27DEE5rrxAAn2FSwTy9fhrB3QAdDQlwkEZcQzDh |
|
22 | 22 | 2b01dab594167bc0dd33331dbaa6dca3dca1b3aa 0 iEYEABECAAYFAku1IwIACgkQywK+sNU5EO9MjgCdHLVwkTZlNHxhcznZKBL1rjN+J7cAoLLWi9LTL6f/TgBaPSKOy1ublbaW |
|
23 | 23 | 39f725929f0c48c5fb3b90c071fc3066012456ca 0 iEYEABECAAYFAkvclvsACgkQywK+sNU5EO9FSwCeL9i5x8ALW/LE5+lCX6MFEAe4MhwAn1ev5o6SX6GrNdDfKweiemfO2VBk |
|
24 | 24 | fdcf80f26604f233dc4d8f0a5ef9d7470e317e8a 0 iEYEABECAAYFAkvsKTkACgkQywK+sNU5EO9qEACgiSiRGvTG2vXGJ65tUSOIYihTuFAAnRzRIqEVSw8M8/RGeUXRps0IzaCO |
|
25 | 25 | 24fe2629c6fd0c74c90bd066e77387c2b02e8437 0 iEYEABECAAYFAkwFLRsACgkQywK+sNU5EO+pJACgp13tPI+pbwKZV+LeMjcQ4H6tCZYAoJebzhd6a8yYx6qiwpJxA9BXZNXy |
|
26 | 26 | f786fc4b8764cd2a5526d259cf2f94d8a66924d9 0 iEYEABECAAYFAkwsyxcACgkQywK+sNU5EO+crACfUpNAF57PmClkSri9nJcBjb2goN4AniPCNaKvnki7TnUsi1u2oxltpKKL |
|
27 | 27 | bf1774d95bde614af3956d92b20e2a0c68c5fec7 0 iEYEABECAAYFAkxVwccACgkQywK+sNU5EO+oFQCeJzwZ+we1fIIyBGCddHceOUAN++cAnjvT6A8ZWW0zV21NXIFF1qQmjxJd |
|
28 | 28 | c00f03a4982e467fb6b6bd45908767db6df4771d 0 iEYEABECAAYFAkxXDqsACgkQywK+sNU5EO/GJACfT9Rz4hZOxPQEs91JwtmfjevO84gAmwSmtfo5mmWSm8gtTUebCcdTv0Kf |
|
29 | 29 | ff5cec76b1c5b6be9c3bb923aae8c3c6d079d6b9 0 iD8DBQBMdo+qywK+sNU5EO8RAqQpAJ975BL2CCAiWMz9SXthNQ9xG181IwCgp4O+KViHPkufZVFn2aTKMNvcr1A= |
|
30 | 30 | 93d8bff78c96fe7e33237b257558ee97290048a4 0 iD8DBQBMpfvdywK+sNU5EO8RAsxVAJ0UaL1XB51C76JUBhafc9GBefuMxwCdEWkTOzwvE0SarJBe9i008jhbqW4= |
|
31 | 31 | 333421b9e0f96c7bc788e5667c146a58a9440a55 0 iD8DBQBMz0HOywK+sNU5EO8RAlsEAJ0USh6yOG7OrWkADGunVt9QimBQnwCbBqeMnKgSbwEw8jZwE3Iz1mdrYlo= |
|
32 | 32 | 4438875ec01bd0fc32be92b0872eb6daeed4d44f 0 iD8DBQBM4WYUywK+sNU5EO8RAhCVAJ0dJswachwFAHALmk1x0RJehxzqPQCbBNskP9n/X689jB+btNTZTyKU/fw= |
|
33 | 33 | 6aff4f144ad356311318b0011df0bb21f2c97429 0 iD8DBQBM9uxXywK+sNU5EO8RAv+4AKCDj4qKP16GdPaq1tP6BUwpM/M1OACfRyzLPp/qiiN8xJTWoWYSe/XjJug= |
|
34 | 34 | e3bf16703e2601de99e563cdb3a5d50b64e6d320 0 iD8DBQBNH8WqywK+sNU5EO8RAiQTAJ9sBO+TeiGro4si77VVaQaA6jcRUgCfSA28dBbjj0oFoQwvPoZjANiZBH8= |
|
35 | 35 | a6c855c32ea081da3c3b8ff628f1847ff271482f 0 iD8DBQBNSJJ+ywK+sNU5EO8RAoJaAKCweDEF70fu+r1Zn7pYDXdlk5RuSgCeO9gK/eit8Lin/1n3pO7aYguFLok= |
|
36 | 36 | 2b2155623ee2559caf288fd333f30475966c4525 0 iD8DBQBNSJeBywK+sNU5EO8RAm1KAJ4hW9Cm9nHaaGJguchBaPLlAr+O3wCgqgmMok8bdAS06N6PL60PSTM//Gg= |
|
37 | 37 | 2616325766e3504c8ae7c84bd15ee610901fe91d 0 iD8DBQBNbWy9ywK+sNU5EO8RAlWCAJ4mW8HbzjJj9GpK98muX7k+7EvEHwCfaTLbC/DH3QEsZBhEP+M8tzL6RU4= |
|
38 | 38 | aa1f3be38ab127280761889d2dca906ca465b5f4 0 iD8DBQBNeQq7ywK+sNU5EO8RAlEOAJ4tlEDdetE9lKfjGgjbkcR8PrC3egCfXCfF3qNVvU/2YYjpgvRwevjvDy0= |
|
39 | 39 | b032bec2c0a651ca0ddecb65714bfe6770f67d70 0 iD8DBQBNlg5kywK+sNU5EO8RAnGEAJ9gmEx6MfaR4XcG2m/93vwtfyzs3gCgltzx8/YdHPwqDwRX/WbpYgi33is= |
|
40 | 40 | 3cb1e95676ad089596bd81d0937cad37d6e3b7fb 0 iD8DBQBNvTy4ywK+sNU5EO8RAmp8AJ9QnxK4jTJ7G722MyeBxf0UXEdGwACgtlM7BKtNQfbEH/fOW5y+45W88VI= |
|
41 | 41 | 733af5d9f6b22387913e1d11350fb8cb7c1487dd 0 iD8DBQBN5q/8ywK+sNU5EO8RArRGAKCNGT94GKIYtSuwZ57z1sQbcw6uLACfffpbMV4NAPMl8womAwg+7ZPKnIU= |
|
42 | 42 | de9eb6b1da4fc522b1cab16d86ca166204c24f25 0 iD8DBQBODhfhywK+sNU5EO8RAr2+AJ4ugbAj8ae8/K0bYZzx3sascIAg1QCeK3b+zbbVVqd3b7CDpwFnaX8kTd4= |
|
43 | 43 | 4a43e23b8c55b4566b8200bf69fe2158485a2634 0 iD8DBQBONzIMywK+sNU5EO8RAj5SAJ0aPS3+JHnyI6bHB2Fl0LImbDmagwCdGbDLp1S7TFobxXudOH49bX45Iik= |
|
44 | 44 | d629f1e89021103f1753addcef6b310e4435b184 0 iD8DBQBOWAsBywK+sNU5EO8RAht4AJwJl9oNFopuGkj5m8aKuf7bqPkoAQCeNrEm7UhFsZKYT5iUOjnMV7s2LaM= |
|
45 | 45 | 351a9292e430e35766c552066ed3e87c557b803b 0 iD8DBQBOh3zUywK+sNU5EO8RApFMAKCD3Y/u3avDFndznwqfG5UeTHMlvACfUivPIVQZyDZnhZMq0UhC6zhCEQg= |
|
46 | 46 | 384082750f2c51dc917d85a7145748330fa6ef4d 0 iD8DBQBOmd+OywK+sNU5EO8RAgDgAJ9V/X+G7VLwhTpHrZNiOHabzSyzYQCdE2kKfIevJUYB9QLAWCWP6DPwrwI= |
|
47 | 47 | 41453d55b481ddfcc1dacb445179649e24ca861d 0 iD8DBQBOsFhpywK+sNU5EO8RAqM6AKCyfxUae3/zLuiLdQz+JR78690eMACfQ6JTBQib4AbE+rUDdkeFYg9K/+4= |
|
48 | 48 | 195dbd1cef0c2f9f8bcf4ea303238105f716bda3 0 iD8DBQBO1/fWywK+sNU5EO8RAmoPAKCR5lpv1D6JLURHD8KVLSV4GRVEBgCgnd0Sy78ligNfqAMafmACRDvj7vo= |
|
49 | 49 | 6344043924497cd06d781d9014c66802285072e4 0 iD8DBQBPALgmywK+sNU5EO8RAlfhAJ9nYOdWnhfVDHYtDTJAyJtXBAQS9wCgnefoSQt7QABkbGxM+Q85UYEBuD0= |
|
50 | 50 | db33555eafeaf9df1e18950e29439eaa706d399b 0 iD8DBQBPGdzxywK+sNU5EO8RAppkAJ9jOXhUVE/97CPgiMA0pMGiIYnesQCfengAszcBiSiKGugiI8Okc9ghU+Y= |
|
51 | 51 | 2aa5b51f310fb3befd26bed99c02267f5c12c734 0 iD8DBQBPKZ9bywK+sNU5EO8RAt1TAJ45r1eJ0YqSkInzrrayg4TVCh0SnQCgm0GA/Ua74jnnDwVQ60lAwROuz1Q= |
|
52 | 52 | 53e2cd303ecf8ca7c7eeebd785c34e5ed6b0f4a4 0 iD8DBQBPT/fvywK+sNU5EO8RAnfYAKCn7d0vwqIb100YfWm1F7nFD5B+FACeM02YHpQLSNsztrBCObtqcnfod7Q= |
|
53 | 53 | b9bd95e61b49c221c4cca24e6da7c946fc02f992 0 iD8DBQBPeLsIywK+sNU5EO8RAvpNAKCtKe2gitz8dYn52IRF0hFOPCR7AQCfRJL/RWCFweu2T1vH/mUOCf8SXXc= |
|
54 | 54 | d9e2f09d5488c395ae9ddbb320ceacd24757e055 0 iD8DBQBPju/dywK+sNU5EO8RArBYAJ9xtifdbk+hCOJO8OZa4JfHX8OYZQCeKPMBaBWiT8N/WHoOm1XU0q+iono= |
|
55 | 55 | 00182b3d087909e3c3ae44761efecdde8f319ef3 0 iD8DBQBPoFhIywK+sNU5EO8RAhzhAKCBj1n2jxPTkZNJJ5pSp3soa+XHIgCgsZZpAQxOpXwCp0eCdNGe0+pmxmg= |
|
56 | 56 | 5983de86462c5a9f42a3ad0f5e90ce5b1d221d25 0 iD8DBQBPovNWywK+sNU5EO8RAhgiAJ980T91FdPTRMmVONDhpkMsZwVIMACgg3bKvoWSeuCW28llUhAJtUjrMv0= |
|
57 | 57 | 85a358df5bbbe404ca25730c9c459b34263441dc 0 iD8DBQBPyZsWywK+sNU5EO8RAnpLAJ48qrGDJRT+pteS0mSQ11haqHstPwCdG4ccGbk+0JHb7aNy8/NRGAOqn9w= |
|
58 | 58 | b013baa3898e117959984fc64c29d8c784d2f28b 0 iD8DBQBP8QOPywK+sNU5EO8RAqimAKCFRSx0lvG6y8vne2IhNG062Hn0dACeMLI5/zhpWpHBIVeAAquYfx2XFeA= |
|
59 | 59 | 7f5094bb3f423fc799e471aac2aee81a7ce57a0b 0 iD8DBQBQGiL8ywK+sNU5EO8RAq5oAJ4rMMCPx6O+OuzNXVOexogedWz/QgCeIiIxLd76I4pXO48tdXhr0hQcBuM= |
|
60 | 60 | 072209ae4ddb654eb2d5fd35bff358c738414432 0 iD8DBQBQQkq0ywK+sNU5EO8RArDTAJ9nk5CySnNAjAXYvqvx4uWCw9ThZwCgqmFRehH/l+oTwj3f8nw8u8qTCdc= |
|
61 | 61 | b3f0f9a39c4e1d0250048cd803ab03542d6f140a 0 iD8DBQBQamltywK+sNU5EO8RAlsqAJ4qF/m6aFu4mJCOKTiAP5RvZFK02ACfawYShUZO6OXEFfveU0aAxDR0M1k= |
|
62 | 62 | d118a4f4fd16d9b558ec3f3e87bfee772861d2b7 0 iD8DBQBQgPV5ywK+sNU5EO8RArylAJ0abcx5NlDjyv3ZDWpAfRIHyRsJtQCgn4TMuEayqgxzrvadQZHdTEU2g38= |
|
63 | 63 | 195ad823b5d58c68903a6153a25e3fb4ed25239d 0 iD8DBQBQkuT9ywK+sNU5EO8RAhB4AKCeerItoK2Jipm2cVf4euGofAa/WACeJj3TVd4pFILpb+ogj7ebweFLJi0= |
|
64 | 64 | 0c10cf8191469e7c3c8844922e17e71a176cb7cb 0 iD8DBQBQvQWoywK+sNU5EO8RAnq3AJoCn98u4geFx5YaQaeh99gFhCd7bQCgjoBwBSUyOvGd0yBy60E3Vv3VZhM= |
|
65 | 65 | a4765077b65e6ae29ba42bab7834717b5072d5ba 0 iD8DBQBQ486sywK+sNU5EO8RAhmJAJ90aLfLKZhmcZN7kqphigQJxiFOQACeJ5IUZxjGKH4xzi3MrgIcx9n+dB0= |
|
66 | 66 | f5fbe15ca7449f2c9a3cf817c86d0ae68b307214 0 iD8DBQBQ+yuYywK+sNU5EO8RAm9JAJoD/UciWvpGeKBcpGtZJBFJVcL/HACghDXSgQ+xQDjB+6uGrdgAQsRR1Lg= |
|
67 | 67 | a6088c05e43a8aee0472ca3a4f6f8d7dd914ebbf 0 iD8DBQBRDDROywK+sNU5EO8RAh75AJ9uJCGoCWnP0Lv/+XuYs4hvUl+sAgCcD36QgAnuw8IQXrvv684BAXAnHcA= |
|
68 | 68 | 7511d4df752e61fe7ae4f3682e0a0008573b0402 0 iD8DBQBRFYaoywK+sNU5EO8RAuErAJoDyhXn+lptU3+AevVdwAIeNFyR2gCdHzPHyWd+JDeWCUR+pSOBi8O2ppM= |
|
69 | 69 | 5b7175377babacce80a6c1e12366d8032a6d4340 0 iD8DBQBRMCYgywK+sNU5EO8RAq1/AKCWKlt9ysibyQgYwoxxIOZv5J8rpwCcDSHQaaf1fFZUTnQsOePwcM2Y/Sg= |
|
70 | 70 | 50c922c1b5145dab8baefefb0437d363b6a6c21c 0 iD8DBQBRWnUnywK+sNU5EO8RAuQRAJwM42cJqJPeqJ0jVNdMqKMDqr4dSACeP0cRVGz1gitMuV0x8f3mrZrqc7I= |
|
71 | 71 | 8a7bd2dccd44ed571afe7424cd7f95594f27c092 0 iD8DBQBRXfBvywK+sNU5EO8RAn+LAKCsMmflbuXjYRxlzFwId5ptm8TZcwCdGkyLbZcASBOkzQUm/WW1qfknJHU= |
|
72 | 72 | 292cd385856d98bacb2c3086f8897bc660c2beea 0 iD8DBQBRcM0BywK+sNU5EO8RAjp4AKCJBykQbvXhKuvLSMxKx3a2TBiXcACfbr/kLg5GlZTF/XDPmY+PyHgI/GM= |
|
73 | 73 | 23f785b38af38d2fca6b8f3db56b8007a84cd73a 0 iD8DBQBRgZwNywK+sNU5EO8RAmO4AJ4u2ILGuimRP6MJgE2t65LZ5dAdkACgiENEstIdrlFC80p+sWKD81kKIYI= |
|
74 | 74 | ddc7a6be20212d18f3e27d9d7e6f079a66d96f21 0 iD8DBQBRkswvywK+sNU5EO8RAiYYAJsHTHyHbJeAgmGvBTmDrfcKu4doUgCeLm7eGBjx7yAPUvEtxef8rAkQmXI= |
|
75 | 75 | cceaf7af4c9e9e6fa2dbfdcfe9856c5da69c4ffd 0 iD8DBQBRqnFLywK+sNU5EO8RAsWNAJ9RR6t+y1DLFc2HeH0eN9VfZAKF9gCeJ8ezvhtKq/LMs0/nvcgKQc/d5jk= |
|
76 | 76 | 009794acc6e37a650f0fae37872e733382ac1c0c 0 iD8DBQBR0guxywK+sNU5EO8RArNkAKCq9pMihVzP8Os5kCmgbWpe5C37wgCgqzuPZTHvAsXF5wTyaSTMVa9Ccq4= |
|
77 | 77 | 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 |
|
100 | 100 | 902554884335e5ca3661d63be9978eb4aec3f68a 0 iQIVAwUAVH0KMyBXgaxoKi1yAQLUKxAAjgyYpmqD0Ji5OQ3995yX0dmwHOaaSuYpq71VUsOMYBskjH4xE2UgcTrX8RWUf0E+Ya91Nw3veTf+IZlYLaWuOYuJPRzw+zD1sVY8xprwqBOXNaA7n8SsTqZPSh6qgw4S0pUm0xJUOZzUP1l9S7BtIdJP7KwZ7hs9YZev4r9M3G15xOIPn5qJqBAtIeE6f5+ezoyOpSPZFtLFc4qKQ/YWzOT5uuSaYogXgVByXRFaO84+1TD93LR0PyVWxhwU9JrDU5d7P/bUTW1BXdjsxTbBnigWswKHC71EHpgz/HCYxivVL30qNdOm4Fow1Ec2GdUzGunSqTPrq18ScZDYW1x87f3JuqPM+ce/lxRWBBqP1yE30/8l/Us67m6enWXdGER8aL1lYTGOIWAhvJpfzv9KebaUq1gMFLo6j+OfwR3rYPiCHgi20nTNBa+LOceWFjCGzFa3T9UQWHW/MBElfAxK65uecbGRRYY9V1/+wxtTUiS6ixpmzL8S7uUd5n6oMaeeMiD82NLgPIbMyUHQv6eFEcCj0U9NT2uKbFRmclMs5V+8D+RTCsLJ55R9PD5OoRw/6K/coqqPShYmJvgYsFQPzXVpQdCRae31xdfGFmd5KUetqyrT+4GUdJWzSm0giSgovpEJNxXglrvNdvSO7fX3R1oahhwOwtGqMwNilcK+iDw= |
|
101 | 101 | 6dad422ecc5adb63d9fa649eeb8e05a5f9bc4900 0 iQIVAwUAVJNALCBXgaxoKi1yAQKgmw/+OFbHHOMmN2zs2lI2Y0SoMALPNQBInMBq2E6RMCMbfcS9Cn75iD29DnvBwAYNWaWsYEGyheJ7JjGBiuNKPOrLaHkdjG+5ypbhAfNDyHDiteMsXfH7D1L+cTOAB8yvhimZHOTTVF0zb/uRyVIPNowAyervUVRjDptzdfcvjUS+X+/Ufgwms6Y4CcuzFLFCxpmryJhLtOpwUPLlzIqeNkFOYWkHanCgtZX03PNIWhorH3AWOc9yztwWPQ+kcKl3FMlyuNMPhS/ElxSF6GHGtreRbtP+ZLoSIOMb2QBKpGDpZLgJ3JQEHDcZ0h5CLZWL9dDUJR3M8pg1qglqMFSWMgRPTzxPS4QntPgT/Ewd3+U5oCZUh052fG41OeCZ0CnVCpqi5PjUIDhzQkONxRCN2zbjQ2GZY7glbXoqytissihEIVP9m7RmBVq1rbjOKr+yUetJ9gOZcsMtZiCEq4Uj2cbA1x32MQv7rxwAgQP1kgQ62b0sN08HTjQpI7/IkNALLIDHoQWWr45H97i34qK1dd5uCOnYk7juvhGNX5XispxNnC01/CUVNnqChfDHpgnDjgT+1H618LiTgUAD3zo4IVAhCqF5XWsS4pQEENOB3Msffi62fYowvJx7f/htWeRLZ2OA+B85hhDiD4QBdHCRoz3spVp0asNqDxX4f4ndj8RlzfM= |
|
102 | 102 | 1265a3a71d75396f5d4cf6935ae7d9ba5407a547 0 iQIVAwUAVKXKYCBXgaxoKi1yAQIfsA/+PFfaWuZ6Jna12Y3MpKMnBCXYLWEJgMNlWHWzwU8lD26SKSlvMyHQsVZlkld2JmFugUCn1OV3OA4YWT6BA7VALq6Zsdcu5Dc8LRbyajBUkzGRpOUyWuFzjkCpGVbrQzbCR/bel/BBXzSqL4ipdtWgJ4y+WpZIhWkNXclBkR52b5hUTjN9vzhyhVVI7eURGwIEf7vVs1fDOcEGtaGY/ynzMTzyxIDsEEygCZau86wpKlYlqhCgxKDyzyGfpH3B1UlNGFt1afW8AWe1eHjdqC7TJZpMqmQ/Ju8vco8Xht6OXw4ZLHj7y39lpccfKTBLiK/cAKSg+xgyaH/BLhzoEkNAwYSFAB4i4IoV0KUC8nFxHfsoswBxJnMqU751ziMrpZ/XHZ1xQoEOdXgz2I04vlRn8xtynOVhcgjoAXwtbia7oNh/qCH/hl5/CdAtaawuCxJBf237F+cwur4PMAAvsGefRfZco/DInpr3qegr8rwInTxlO48ZG+o5xA4TPwT0QQTUjMdNfC146ZSbp65wG7VxJDocMZ8KJN/lqPaOvX+FVYWq4YnJhlldiV9DGgmym1AAaP0D3te2GcfHXpt/f6NYUPpgiBHy0GnOlNcQyGnnONg1A6oKVWB3k7WP28+PQbQEiCIFk2nkf5VZmye7OdHRGKOFfuprYFP1WwTWnVoNX9c= |
|
103 | 103 | db8e3f7948b1fdeb9ad12d448fc3525759908b9f 0 iQIVAwUAVLsaciBXgaxoKi1yAQKMIA//a90/GvySL9UID+iYvzV2oDaAPDD0T+4Xs43I7DT5NIoDz+3yq2VV54XevQe5lYiURmsb/Q9nX2VR/Qq1J9c/R6Gy+CIfmJ3HzMZ0aAX8ZlZgQPYZKh/2kY5Ojl++k6MTqbqcrICNs4+UE/4IAxPyOfu5gy7TpdJmRZo2J3lWVC2Jbhd02Mzb+tjtfbOM+QcQxPwt9PpqmQszJceyVYOSm3jvD1uJdSOC04tBQrQwrxktQ09Om0LUMMaB5zFXpJtqUzfw7l4U4AaddEmkd3vUfLtHxc21RB01c3cpe2dJnjifDfwseLsI8rS4jmi/91c74TeBatSOhvbqzEkm/p8xZFXE4Uh+EpWjTsVqmfQaRq6NfNCR7I/kvGv8Ps6w8mg8uX8fd8lx+GJbodj+Uy0X3oqHyqPMky/df5i79zADBDuz+yuxFfDD9i22DJPIYcilfGgwpIUuO2lER5nSMVmReuWTVBnT6SEN66Q4KR8zLtIRr+t1qUUCy6wYbgwrdHVCbgMF8RPOVZPjbs17RIqcHjch0Xc7bShKGhQg4WHDjXHK61w4tOa1Yp7jT6COkl01XC9BLcGxJYKFvNCbeDZQGvVgJNoEvHxBxD9rGMVRjfuxeJawc2fGzZJn0ySyLDW0pfd4EJNgTh9bLdPjWz2VlXqn4A6bgaLgTPqjmN0VBXw= |
|
104 | 104 | fbdd5195528fae4f41feebc1838215c110b25d6a 0 iQIVAwUAVM7fBCBXgaxoKi1yAQKoYw/+LeIGcjQmHIVFQULsiBtPDf+eGAADQoP3mKBy+eX/3Fa0qqUNfES2Q3Y6RRApyZ1maPRMt8BvvhZMgQsu9QIrmf3zsFxZGFwoyrIj4hM3xvAbEZXqmWiR85/Ywd4ImeLaZ0c7mkO1/HGF1n2Mv47bfM4hhNe7VGJSSrTY4srFHDfk4IG9f18DukJVzRD9/dZeBw6eUN1ukuLEgQAD5Sl47bUdKSetglOSR1PjXfZ1hjtz5ywUyBc5P9p3LC4wSvlcJKl22zEvB3L0hkoDcPsdIPEnJAeXxKlR1rQpoA3fEgrstGiSNUW/9Tj0VekAHLO95SExmQyoG/AhbjRRzIj4uQ0aevCJyiAhkv+ffOSf99PMW9L1k3tVjLhpMWEz9BOAWyX7cDFWj5t/iktI046O9HGN9SGVx18e9xM6pEgRcLA2TyjEmtkA4jX0JeN7WeCweMLiSxyGP7pSPSJdpJeXaFtRpSF62p/G0Z5wN9s05LHqDyqNVtCvg4WjkuV5LZSdLbMcYBWGBxQzCG6qowXFXIawmbaFiBZwTfOgNls9ndz5RGupAaxY317prxPFv/pXoesc1P8bdK09ZvjhbmmD66Q/BmS2dOMQ8rXRjuVdlR8j2QBtFZxekMcRD02nBAVnwHg1VWQMIRaGjdgmW4wOkirWVn7me177FnBxrxW1tG4= |
|
105 | 105 | 5b4ed033390bf6e2879c8f5c28c84e1ee3b87231 0 iQIVAwUAVPQL9CBXgaxoKi1yAQJIXxAAtD2hWhaKa+lABmCOYG92FE/WdqY/91Xv5atTL8Xeko/MkirIKZiOuxNWX+J34TVevINZSWmMfDSc5TkGxktL9jW/pDB/CXn+CVZpxRabPYFH9HM2K3g8VaTV1MFtV2+feOMDIPCmq5ogMF9/kXjmifiEBrJcFsE82fdexJ3OHoOY4iHFxEhh3GzvNqEQygk4VeU6VYziNvSQj9G//PsK3Bmk7zm5ScsZcMVML3SIYFuej1b1PI1v0N8mmCRooVNBGhD/eA0iLtdh/hSb9s/8UgJ4f9HOcx9zqs8V4i14lpd/fo0+yvFuVrVbWGzrDrk5EKLENhVPwvc1KA32PTQ4Z9u7VQIBIxq3K5lL2VlCMIYc1BSaSQBjuiLm8VdN6iDuf5poNZhk1rvtpQgpxJzh362dlGtR/iTJuLCeW7gCqWUAorLTeHy0bLQ/jSOeTAGys8bUHtlRL4QbnhLbUmJmRYVvCJ+Yt1aTgTSNcoFjoLJarR1169BXgdCA38BgReUL6kB224UJSTzB1hJUyB2LvCWrXZMipZmR99Iwdq7MePD3+AoSIXQNUMY9blxuuF5x7W2ikNXmVWuab4Z8rQRtmGqEuIMBSunxAnZSn+i8057dFKlq+/yGy+WW3RQg+RnLnwZs1zCDTfu98/GT5k5hFpjXZeUWWiOVwQJ5HrqncCw= |
|
106 | 106 | 07a92bbd02e5e3a625e0820389b47786b02b2cea 0 iQIVAwUAVPSP9SBXgaxoKi1yAQLkBQ//dRQExJHFepJfZ0gvGnUoYI4APsLmne5XtfeXJ8OtUyC4a6RylxA5BavDWgXwUh9BGhOX2cBSz1fyvzohrPrvNnlBrYKAvOIJGEAiBTXHYTxHINEKPtDF92Uz23T0Rn/wnSvvlbWF7Pvd+0DMJpFDEyr9n6jvVLR7mgxMaCqZbVaB1W/wTwDjni780WgVx8OPUXkLx3/DyarMcIiPeI5UN+FeHDovTsBWFC95msFLm80PMRPuHOejWp65yyEemGujZEPO2D5VVah7fshM2HTz63+bkEBYoqrftuv3vXKBRG78MIrUrKpqxmnCKNKDUUWJ4yk3+NwuOiHlKdly5kZ7MNFaL73XKo8HH287lDWz0lIazs91dQA9a9JOyTsp8YqGtIJGGCbhrUDtiQJ199oBU84mw3VH/EEzm4mPv4sW5fm7BnnoH/a+9vXySc+498rkdLlzFwxrQkWyJ/pFOx4UA3mCtGQK+OSwLPc+X4SRqA4fiyqKxVAL1kpLTSDL3QA82I7GzBaXsxUXzS4nmteMhUyzTdwAhKVydL0gC3d7NmkAFSyRjdGzutUUXshYxg0ywRgYebe8uzJcTj4nNRgaalYLdg3guuDulD+dJmILsrcLmA6KD/pvfDn8PYt+4ZjNIvN2E9GF6uXDu4Ux+AlOTLk9BChxUF8uBX9ev5cvWtQ= |
|
107 | 107 | 2e2e9a0750f91a6fe0ad88e4de34f8efefdcab08 0 iQIVAwUAVRw4nyBXgaxoKi1yAQIFExAAkbCPtLjQlJvPaYCL1KhNR+ZVAmn7JrFH3XhvR26RayYbs4NxR3W1BhwhDy9+W+28szEx1kQvmr6t1bXAFywY0tNJOeuLU7uFfmbgAfYgkQ9kpsQNqFYkjbCyftw0S9vX9VOJ9DqUoDWuKfX7VzjkwE9dCfKI5F+dvzxnd6ZFjB85nyHBQuTZlzXl0+csY212RJ2G2j/mzEBVyeZj9l7Rm+1X8AC1xQMWRJGiyd0b7nhYqoOcceeJFAV1t9QO4+gjmkM5kL0orjxTnuVsxPTxcC5ca1BfidPWrZEto3duHWNiATGnCDylxxr52BxCAS+BWePW9J0PROtw1pYaZ9pF4N5X5LSXJzqX7ZiNGckxqIjry09+Tbsa8FS0VkkYBEiGotpuo4Jd05V6qpXfW2JqAfEVo6X6aGvPM2B7ZUtKi30I4J+WprrOP3WgZ/ZWHe1ERYKgjDqisn3t/D40q30WQUeQGltGsOX0Udqma2RjBugO5BHGzJ2yer4GdJXg7q1OMzrjAEuz1IoKvIB/o1pg86quVA4H2gQnL1B8t1M38/DIafyw7mrEY4Z3GL44Reev63XVvDE099Vbhqp7ufwq81Fpq7Xxa5vsr9SJ+8IqqQr8AcYSuK3G3L6BmIuSUAYMRqgl35FWoWkGyZIG5c6K6zI8w5Pb0aGi6Lb2Wfb9zbc= |
|
108 | 108 | e89f909edffad558b56f4affa8239e4832f88de0 0 iQIVAwUAVTBozCBXgaxoKi1yAQLHeg/+IvfpPmG7OSqCoHvMVETYdrqT7lKCwfCQWMFOC/2faWs1n4R/qQNm6ckE5OY888RK8tVQ7ue03Pg/iyWgQlYfS7Njd3WPjS4JsnEBxIvuGkIu6TPIXAUAH0PFTBh0cZEICDpPEVT2X3bPRwDHA+hUE9RrxM5zJ39Fpk/pTYCjQ9UKfEhXlEfka75YB39g2Y/ssaSbn5w/tAAx8sL72Y4G96D4IV2seLHZhB3VQ7UZKThEWn6UdVOoKj+urIwGaBYMeekGVtHSh6fnHOw3EtDO9mQ5HtAz2Bl4CwRYN8eSN+Dwgr+mdk8MWpQQJ+i1A8jUhUp8gn1Pe5GkIH4CWZ9+AvLLnshe2MkVaTT1g7EQk37tFkkdZDRBsOHIvpF71B9pEA1gMUlX4gKgh5YwukgpQlDmFCfY7XmX6eXw9Ub+EckEwYuGMz7Fbwe9J/Ce4DxvgJgq3/cu/jb3bmbewH6tZmcrlqziqqA8GySIwcURnF1c37e7+e7x1jhFJfCWpHzvCusjKhUp9tZsl9Rt1Bo/y41QY+avY7//ymhbwTMKgqjzCYoA+ipF4JfZlFiZF+JhvOSIFb0ltkfdqKD+qOjlkFaglvQU1bpGKLJ6cz4Xk2Jqt5zhcrpyDMGVv9aiWywCK2ZP34RNaJ6ZFwzwdpXihqgkm5dBGoZ4ztFUfmjXzIg= |
|
109 | 109 | 8cc6036bca532e06681c5a8fa37efaa812de67b5 0 iQIVAwUAVUP0xCBXgaxoKi1yAQLIChAAme3kg1Z0V8t5PnWKDoIvscIeAsD2s6EhMy1SofmdZ4wvYD1VmGC6TgXMCY7ssvRBhxqwG3GxwYpwELASuw2GYfVot2scN7+b8Hs5jHtkQevKbxarYni+ZI9mw/KldnJixD1yW3j+LoJFh/Fu6GD2yrfGIhimFLozcwUu3EbLk7JzyHSn7/8NFjLJz0foAYfcbowU9/BFwNVLrQPnsUbWcEifsq5bYso9MBO9k+25yLgqHoqMbGpJcgjubNy1cWoKnlKS+lOJl0/waAk+aIjHXMzFpRRuJDjxEZn7V4VdV5d23nrBTcit1BfMzga5df7VrLPVRbom1Bi0kQ0BDeDex3hHNqHS5X+HSrd/njzP1xp8twG8hTE+njv85PWoGBTo1eUGW/esChIJKA5f3/F4B9ErgBNNOKnYmRgxixd562OWAwAQZK0r0roe2H/Mfg2VvgxT0kHd22NQLoAv0YI4jcXcCFrnV/80vHUQ8AsAYAbkLcz1jkfk3YwYDP8jbJCqcwJRt9ialYKJwvXlEe0TMeGdq7EjCO0z/pIpu82k2R/C0FtCFih3bUvJEmWoVVx8UGkDDQEORLbzxQCt0IOiQGFcoCCxgQmL0x9ZoljCWg5vZuuhU4uSOuRTuM+aa4xoLkeOcvgGRSOXrqfkV8JpWKoJB4dmY2qSuxw8LsAAzK0= |
|
110 | 110 | ed18f4acf435a2824c6f49fba40f42b9df5da7ad 0 iQIVAwUAVWy9mCBXgaxoKi1yAQIm+Q/+I/tV8DC51d4f/6T5OR+motlIx9U5za5p9XUUzfp3tzSY2PutVko/FclajVdFekZsK5pUzlh/GZhfe1jjyEEIr3UC3yWk8hMcvvS+2UDmfy81QxN7Uf0kz4mZOlME6d/fYDzf4cDKkkCXoec3kyZBw7L84mteUcrJoyb5K3fkQBrK5CG/CV7+uZN6b9+quKjtDhDEkAyc6phNanzWNgiHGucEbNgXsKM01HmV1TnN4GXTKx8y2UDalIJOPyes2OWHggibMHbaNnGnwSBAK+k29yaQ5FD0rsA+q0j3TijA1NfqvtluNEPbFOx/wJV4CxonYad93gWyEdgU34LRqqw1bx7PFUvew2/T3TJsxQLoCt67OElE7ScG8evuNEe8/4r3LDnzYFx7QMP5r5+B7PxVpj/DT+buS16BhYS8pXMMqLynFOQkX5uhEM7mNC0JTXQsBMHSDAcizVDrdFCF2OSfQjLpUfFP1VEWX7EInqj7hZrd+GE7TfBD8/rwSBSkkCX2aa9uKyt6Ius1GgQUuEETskAUvvpsNBzZxtvGpMMhqQLGlJYnBbhOmsbOyTSnXU66KJ5e/H3O0KRrF09i74v30DaY4uIH8xG6KpSkfw5s/oiLCtagfc0goUvvojk9pACDR3CKM/jVC63EVp2oUcjT72jUgSLxBgi7siLD8IW86wc= |
|
111 | 111 | 540cd0ddac49c1125b2e013aa2ff18ecbd4dd954 0 iQIVAwUAVZRtzSBXgaxoKi1yAQJVLhAAtfn+8OzHIp6wRC4NUbkImAJRLsNTRPKeRSWPCF5O5XXQ84hp+86qjhndIE6mcJSAt4cVP8uky6sEa8ULd6b3ACRBvtgZtsecA9S/KtRjyE9CKr8nP+ogBNqJPaYlTz9RuwGedOd+8I9lYgsnRjfaHSByNMX08WEHtWqAWhSkAz/HO32ardS38cN97fckCgQtA8v7c77nBT7vcw4epgxyUQvMUxUhqmCVVhVfz8JXa5hyJxFrOtqgaVuQ1B5Y/EKxcyZT+JNHPtu3V1uc1awS/w16CEPstNBSFHax5MuT9UbY0mV2ZITP99EkM+vdomh82VHdnMo0i7Pz7XF45ychD4cteroO9gGqDDt9j7hd1rubBX1bfkPsd/APJlyeshusyTj+FqsUD/HDlvM9LRjY1HpU7i7yAlLQQ3851XKMLUPNFYu2r3bo8Wt/CCHtJvB4wYuH+7Wo3muudpU01ziJBxQrUWwPbUrG+7LvO1iEEVxB8l+8Vq0mU3Te7lJi1kGetm6xHNbtvQip5P2YUqvv+lLo/K8KoJDxsh63Y01JGwdmUDb8mnFlRx4J7hQJaoNEvz3cgnc4X8gDJD8sUOjGOPnbtz2QwTY+zj/5+FdLxWDCxNrHX5vvkVdJHcCqEfVvQTKfDMOUeKuhjI7GD7t3xRPfUxq19jjoLPe7aqn1Z1s= |
|
112 | 112 | 96a38d44ba093bd1d1ecfd34119e94056030278b 0 iQIVAwUAVarUUyBXgaxoKi1yAQIfJw/+MG/0736F/9IvzgCTF6omIC+9kS8JH0n/JBGPhpbPAHK4xxjhOOz6m3Ia3c3HNoy+I6calwU6YV7k5dUzlyLhM0Z5oYpdrH+OBNxDEsD5SfhclfR63MK1kmgtD33izijsZ++6a+ZaVfyxpMTksKOktWSIDD63a5b/avb6nKY64KwJcbbeXPdelxvXV7TXYm0GvWc46BgvrHOJpYHCDaXorAn6BMq7EQF8sxdNK4GVMNMVk1njve0HOg3Kz8llPB/7QmddZXYLFGmWqICyUn1IsJDfePxzh8sOYVCbxAgitTJHJJmmH5gzVzw7t7ljtmxSJpcUGQJB2MphejmNFGfgvJPB9c6xOCfUqDjxN5m24V+UYesZntpfgs3lpfvE7785IpVnf6WfKG4PKty01ome/joHlDlrRTekKMlpiBapGMfv8EHvPBrOA+5yAHNfKsmcyCcjD1nvXYZ2/X9qY35AhdcBuNkyp55oPDOdtYIHfnOIxlYMKG1dusDx3Z4eveF0lQTzfRVoE5w+k9A2Ov3Zx0aiSkFFevJjrq5QBfs9dAiT8JYgBmWhaJzCtJm12lQirRMKR/br88Vwt/ry/UVY9cereMNvRYUGOGfC8CGGDCw4WDD+qWvyB3mmrXVuMlXxQRIZRJy5KazaQXsBWuIsx4kgGqC5Uo+yzpiQ1VMuCyI= |
|
113 | 113 | 21aa1c313b05b1a85f8ffa1120d51579ddf6bf24 0 iQIVAwUAVbuouCBXgaxoKi1yAQL2ng//eI1w51F4YkDiUAhrZuc8RE/chEd2o4F6Jyu9laA03vbim598ntqGjX3+UkOyTQ/zGVeZfW2cNG8zkJjSLk138DHCYl2YPPD/yxqMOJp/a7U34+HrA0aE5Y2pcfx+FofZHRvRtt40UCngicjKivko8au7Ezayidpa/vQbc6dNvGrwwk4KMgOP2HYIfHgCirR5UmaWtNpzlLhf9E7JSNL5ZXij3nt6AgEPyn0OvmmOLyUARO/JTJ6vVyLEtwiXg7B3sF5RpmyFDhrkZ+MbFHgL4k/3y9Lb97WaZl8nXJIaNPOTPJqkApFY/56S12PKYK4js2OgU+QsX1XWvouAhEx6CC6Jk9EHhr6+9qxYFhBJw7RjbswUG6LvJy/kBe+Ei5UbYg9dATf3VxQ6Gqs19lebtzltERH2yNwaHyVeqqakPSonOaUyxGMRRosvNHyrTTor38j8d27KksgpocXzBPZcc1MlS3vJg2nIwZlc9EKM9z5R0J1KAi1Z/+xzBjiGRYg5EZY6ElAw30eCjGta7tXlBssJiKeHut7QTLxCZHQuX1tKxDDs1qlXlGCMbrFqo0EiF9hTssptRG3ZyLwMdzEjnh4ki6gzONZKDI8uayAS3N+CEtWcGUtiA9OwuiFXTwodmles/Mh14LEhiVZoDK3L9TPcY22o2qRuku/6wq6QKsg= |
|
114 | 114 | 1a45e49a6bed023deb229102a8903234d18054d3 0 iQIVAwUAVeYa2SBXgaxoKi1yAQLWVA//Q7vU0YzngbxIbrTPvfFiNTJcT4bx9u1xMHRZf6QBIE3KtRHKTooJwH9lGR0HHM+8DWWZup3Vzo6JuWHMGoW0v5fzDyk2czwM9BgQQPfEmoJ/ZuBMevTkTZngjgHVwhP3tHFym8Rk9vVxyiZd35EcxP+4F817GCzD+K7XliIBqVggmv9YeQDXfEtvo7UZrMPPec79t8tzt2UadI3KC1jWUriTS1Fg1KxgXW6srD80D10bYyCkkdo/KfF6BGZ9SkF+U3b95cuqSmOfoyyQwUA3JbMXXOnIefnC7lqRC2QTC6mYDx5hIkBiwymXJBe8rpq/S94VVvPGfW6A5upyeCZISLEEnAz0GlykdpIy/NogzhmWpbAMOus05Xnen6xPdNig6c/M5ZleRxVobNrZSd7c5qI3aUUyfMKXlY1j9oiUTjSKH1IizwaI3aL/MM70eErBxXiLs2tpQvZeaVLn3kwCB5YhywO3LK0x+FNx4Gl90deAXMYibGNiLTq9grpB8fuLg9M90JBjFkeYkrSJ2yGYumYyP/WBA3mYEYGDLNstOby4riTU3WCqVl+eah6ss3l+gNDjLxiMtJZ/g0gQACaAvxQ9tYp5eeRMuLRTp79QQPxv97s8IyVwE/TlPlcSFlEXAzsBvqvsolQXRVi9AxA6M2davYabBYAgRf6rRfgujoU= |
|
115 | 115 | 9a466b9f9792e3ad7ae3fc6c43c3ff2e136b718d 0 iQIVAwUAVg1oMSBXgaxoKi1yAQLPag/+Pv0+pR9b9Y5RflEcERUzVu92q+l/JEiP7PHP9pAZuXoQ0ikYBFo1Ygw8tkIG00dgEaLk/2b7E3OxaU9pjU3thoX//XpTcbkJtVhe7Bkjh9/S3dRpm2FWNL9n0qnywebziB45Xs8XzUwBZTYOkVRInYr/NzSo8KNbQH1B4u2g56veb8u/7GtEvBSGnMGVYKhVUZ3jxyDf371QkdafMOJPpogkZcVhXusvMZPDBYtTIzswyxBJ2jxHzjt8+EKs+FI3FxzvQ9Ze3M5Daa7xfiHI3sOgECO8GMVaJi0F49lttKx08KONw8xLlEof+cJ+qxLxQ42X5XOQglJ2/bv5ES5JiZYAti2XSXbZK96p4wexqL4hnaLVU/2iEUfqB9Sj6itEuhGOknPD9fQo1rZXYIS8CT5nGTNG4rEpLFN6VwWn1btIMNkEHw998zU7N3HAOk6adD6zGcntUfMBvQC3V4VK3o7hp8PGeySrWrOLcC/xLKM+XRonz46woJK5D8w8lCVYAxBWEGKAFtj9hv9R8Ye9gCW0Q8BvJ7MwGpn+7fLQ1BVZdV1LZQTSBUr5u8mNeDsRo4H2hITQRhUeElIwlMsUbbN078a4JPOUgPz1+Fi8oHRccBchN6I40QohL934zhcKXQ+NXYN8BgpCicPztSg8O8Y/qvhFP12Zu4tOH8P/dFY= |
|
116 | 116 | b66e3ca0b90c3095ea28dfd39aa24247bebf5c20 0 iQIVAwUAViarTyBXgaxoKi1yAQLZgRAAh7c7ebn7kUWI5M/b/T6qHGjFrU5azkjamzy9IG+KIa2hZgSMxyEM7JJUFqKP4TiWa3sW03bjKGSM/SjjDSSyheX+JIVSPNyKrBwneYhPq45Ius8eiHziClkt0CSsl2d9xDRpI0JmHbN0Pf8nh7rnbL+231GDAOT6dP+2S8K1HGa/0BgEcL9gpYs4/2GyjL+hBSUjyrabzvwe48DCN5W0tEJbGFw5YEADxdfbVbNEuXL81tR4PFGiJxPW0QKRLDB74MWmiWC0gi2ZC/IhbNBZ2sLb6694d4Bx4PVwtiARh63HNXVMEaBrFu1S9NcMQyHvAOc6Zw4izF/PCeTcdEnPk8J1t5PTz09Lp0EAKxe7CWIViy350ke5eiaxO3ySrNMX6d83BOHLDqEFMSWm+ad+KEMT4CJrK4X/n/XMgEFAaU5nWlIRqrLRIeU2Ifc625T0Xh4BgTqXPpytQxhgV5b+Fi6duNk4cy+QnHT4ymxI6BPD9HvSQwc+O7h37qjvJVZmpQX6AP8O75Yza8ZbcYKRIIxZzOkwNpzE5A/vpvP5bCRn7AGcT3ORWmAYr/etr3vxUvt2fQz6U/R4S915V+AeWBdcp+uExu6VZ42M0vhhh0lyzx1VRJGVdV+LoxFKkaC42d0yT+O1QEhSB7WL1D3/a/iWubv6ieB/cvNMhFaK9DA= |
|
117 | 117 | 47dd34f2e7272be9e3b2a5a83cd0d20be44293f4 0 iQIVAwUAVjZiKiBXgaxoKi1yAQKBWQ/+JcE37vprSOA5e0ezs/avC7leR6hTlXy9O5bpFnvMpbVMTUp+KfBE4HxTT0KKXKh9lGtNaQ+lAmHuy1OQE1hBKPIaCUd8/1gunGsXgRM3TJ9LwjFd4qFpOMxvOouc6kW5kmea7V9W2fg6aFNjjc/4/0J3HMOIjmf2fFz87xqR1xX8iezJ57A4pUPNViJlOWXRzfa56cI6VUe5qOMD0NRXcY+JyI5qW25Y/aL5D9loeKflpzd53Ue+Pu3qlhddJd3PVkaAiVDH+DYyRb8sKgwuiEsyaBO18IBgC8eDmTohEJt6707A+WNhwBJwp9aOUhHC7caaKRYhEKuDRQ3op++VqwuxbFRXx22XYR9bEzQIlpsv9GY2k8SShU5MZqUKIhk8vppFI6RaID5bmALnLLmjmXfSPYSJDzDuCP5UTQgI3PKPOATorVrqMdKzfb7FiwtcTvtHAXpOgLaY9P9XIePbnei6Rx9TfoHYDvzFWRqzSjl21xR+ZUrJtG2fx7XLbMjEAZJcnjP++GRvNbHBOi57aX0l2LO1peQqZVMULoIivaoLFP3i16RuXXQ/bvKyHmKjJzGrLc0QCa0yfrvV2m30RRMaYlOv7ToJfdfZLXvSAP0zbAuDaXdjGnq7gpfIlNE3xM+kQ75Akcf4V4fK1p061EGBQvQz6Ov3PkPiWL/bxrQ= |
|
118 | 1aa5083cbebbe7575c88f3402ab377539b484897 0 iQIVAwUAVkEdCCBXgaxoKi1yAQKdWg//crTr5gsnHQppuD1p+PPn3/7SMsWJ7bgbuaXgERDLC0zWMfhM2oMmu/4jqXnpangdBVvb0SojejgzxoBo9FfRQiIoKt0vxmmn+S8CrEwb99rpP4M7lgyMAInKPMXQdYxkoDNwL70Afmog6eBtlxjYnu8nmUE/swu6JoVns+tF8UOvIKFYbuCcGujo2pUOQC0xBGiHeHSGRDJOlWmY2d7D/PkQtQE/u/d4QZt7enTHMiV44XVJ8+0U0f1ZQE7V+hNWf+IjwcZtL95dnQzUKs6tXMIln/OwO+eJ3d61BfLvmABvCwUC9IepPssNSFBUfGqBAP5wXOzFIPSYn00IWpmZtCnpUNL99X1IV3RP+p99gnEDTScQFPYt5B0q5I1nFdRh1p48BSF/kjPA7V++UfBwMXrrYLKhUR9BjmrRzYnyXJKwbH6iCNj5hsXUkVrBdBi/FnMczgsVILfFcIXUfnJD3E/dG+1lmuObg6dEynxiGChTuaR4KkLa5ZRkUcUl6fWlSRsqSNbGEEbdwcI+nTCZqJUlLSghumhs0Z89Hs1nltBd1ALX2VLJEHrKMrFQ8NfEBeCB6ENqMJi5qPlq354MCdGOZ9RvisX/HlxE4Q61BW0+EwnyXSch6LFSOS3axOocUazMoK1XiOTJSv/5bAsnwb0ztDWeUj9fZEJL+SWtgB8= |
@@ -1,130 +1,131 b'' | |||
|
1 | 1 | d40cc5aacc31ed673d9b5b24f98bee78c283062c 0.4f |
|
2 | 2 | 1c590d34bf61e2ea12c71738e5a746cd74586157 0.4e |
|
3 | 3 | 7eca4cfa8aad5fce9a04f7d8acadcd0452e2f34e 0.4d |
|
4 | 4 | b4d0c3786ad3e47beacf8412157326a32b6d25a4 0.4c |
|
5 | 5 | f40273b0ad7b3a6d3012fd37736d0611f41ecf54 0.5 |
|
6 | 6 | 0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 0.5b |
|
7 | 7 | 12e0fdbc57a0be78f0e817fd1d170a3615cd35da 0.6 |
|
8 | 8 | 4ccf3de52989b14c3d84e1097f59e39a992e00bd 0.6b |
|
9 | 9 | eac9c8efcd9bd8244e72fb6821f769f450457a32 0.6c |
|
10 | 10 | 979c049974485125e1f9357f6bbe9c1b548a64c3 0.7 |
|
11 | 11 | 3a56574f329a368d645853e0f9e09472aee62349 0.8 |
|
12 | 12 | 6a03cff2b0f5d30281e6addefe96b993582f2eac 0.8.1 |
|
13 | 13 | 35fb62a3a673d5322f6274a44ba6456e5e4b3b37 0.9 |
|
14 | 14 | 2be3001847cb18a23c403439d9e7d0ace30804e9 0.9.1 |
|
15 | 15 | 36a957364b1b89c150f2d0e60a99befe0ee08bd3 0.9.2 |
|
16 | 16 | 27230c29bfec36d5540fbe1c976810aefecfd1d2 0.9.3 |
|
17 | 17 | fb4b6d5fe100b0886f8bc3d6731ec0e5ed5c4694 0.9.4 |
|
18 | 18 | 23889160905a1b09fffe1c07378e9fc1827606eb 0.9.5 |
|
19 | 19 | bae2e9c838e90a393bae3973a7850280413e091a 1.0 |
|
20 | 20 | d5cbbe2c49cee22a9fbeb9ea41daa0ac4e26b846 1.0.1 |
|
21 | 21 | d2375bbee6d47e62ba8e415c86e83a465dc4dce9 1.0.2 |
|
22 | 22 | 2a67430f92f15ea5159c26b09ec4839a0c549a26 1.1 |
|
23 | 23 | 3773e510d433969e277b1863c317b674cbee2065 1.1.1 |
|
24 | 24 | 11a4eb81fb4f4742451591489e2797dc47903277 1.1.2 |
|
25 | 25 | 11efa41037e280d08cfb07c09ad485df30fb0ea8 1.2 |
|
26 | 26 | 02981000012e3adf40c4849bd7b3d5618f9ce82d 1.2.1 |
|
27 | 27 | 196d40e7c885fa6e95f89134809b3ec7bdbca34b 1.3 |
|
28 | 28 | 3ef6c14a1e8e83a31226f5881b7fe6095bbfa6f6 1.3.1 |
|
29 | 29 | 31ec469f9b556f11819937cf68ee53f2be927ebf 1.4 |
|
30 | 30 | 439d7ea6fe3aa4ab9ec274a68846779153789de9 1.4.1 |
|
31 | 31 | 296a0b14a68621f6990c54fdba0083f6f20935bf 1.4.2 |
|
32 | 32 | 4aa619c4c2c09907034d9824ebb1dd0e878206eb 1.4.3 |
|
33 | 33 | ff2704a8ded37fbebd8b6eb5ec733731d725da8a 1.5 |
|
34 | 34 | 2b01dab594167bc0dd33331dbaa6dca3dca1b3aa 1.5.1 |
|
35 | 35 | 39f725929f0c48c5fb3b90c071fc3066012456ca 1.5.2 |
|
36 | 36 | fdcf80f26604f233dc4d8f0a5ef9d7470e317e8a 1.5.3 |
|
37 | 37 | 24fe2629c6fd0c74c90bd066e77387c2b02e8437 1.5.4 |
|
38 | 38 | f786fc4b8764cd2a5526d259cf2f94d8a66924d9 1.6 |
|
39 | 39 | bf1774d95bde614af3956d92b20e2a0c68c5fec7 1.6.1 |
|
40 | 40 | c00f03a4982e467fb6b6bd45908767db6df4771d 1.6.2 |
|
41 | 41 | ff5cec76b1c5b6be9c3bb923aae8c3c6d079d6b9 1.6.3 |
|
42 | 42 | 93d8bff78c96fe7e33237b257558ee97290048a4 1.6.4 |
|
43 | 43 | 333421b9e0f96c7bc788e5667c146a58a9440a55 1.7 |
|
44 | 44 | 4438875ec01bd0fc32be92b0872eb6daeed4d44f 1.7.1 |
|
45 | 45 | 6aff4f144ad356311318b0011df0bb21f2c97429 1.7.2 |
|
46 | 46 | e3bf16703e2601de99e563cdb3a5d50b64e6d320 1.7.3 |
|
47 | 47 | a6c855c32ea081da3c3b8ff628f1847ff271482f 1.7.4 |
|
48 | 48 | 2b2155623ee2559caf288fd333f30475966c4525 1.7.5 |
|
49 | 49 | 2616325766e3504c8ae7c84bd15ee610901fe91d 1.8 |
|
50 | 50 | aa1f3be38ab127280761889d2dca906ca465b5f4 1.8.1 |
|
51 | 51 | b032bec2c0a651ca0ddecb65714bfe6770f67d70 1.8.2 |
|
52 | 52 | 3cb1e95676ad089596bd81d0937cad37d6e3b7fb 1.8.3 |
|
53 | 53 | 733af5d9f6b22387913e1d11350fb8cb7c1487dd 1.8.4 |
|
54 | 54 | de9eb6b1da4fc522b1cab16d86ca166204c24f25 1.9 |
|
55 | 55 | 4a43e23b8c55b4566b8200bf69fe2158485a2634 1.9.1 |
|
56 | 56 | d629f1e89021103f1753addcef6b310e4435b184 1.9.2 |
|
57 | 57 | 351a9292e430e35766c552066ed3e87c557b803b 1.9.3 |
|
58 | 58 | 384082750f2c51dc917d85a7145748330fa6ef4d 2.0-rc |
|
59 | 59 | 41453d55b481ddfcc1dacb445179649e24ca861d 2.0 |
|
60 | 60 | 195dbd1cef0c2f9f8bcf4ea303238105f716bda3 2.0.1 |
|
61 | 61 | 6344043924497cd06d781d9014c66802285072e4 2.0.2 |
|
62 | 62 | db33555eafeaf9df1e18950e29439eaa706d399b 2.1-rc |
|
63 | 63 | 2aa5b51f310fb3befd26bed99c02267f5c12c734 2.1 |
|
64 | 64 | 53e2cd303ecf8ca7c7eeebd785c34e5ed6b0f4a4 2.1.1 |
|
65 | 65 | b9bd95e61b49c221c4cca24e6da7c946fc02f992 2.1.2 |
|
66 | 66 | d9e2f09d5488c395ae9ddbb320ceacd24757e055 2.2-rc |
|
67 | 67 | 00182b3d087909e3c3ae44761efecdde8f319ef3 2.2 |
|
68 | 68 | 5983de86462c5a9f42a3ad0f5e90ce5b1d221d25 2.2.1 |
|
69 | 69 | 85a358df5bbbe404ca25730c9c459b34263441dc 2.2.2 |
|
70 | 70 | b013baa3898e117959984fc64c29d8c784d2f28b 2.2.3 |
|
71 | 71 | a06e2681dd1786e2354d84a5fa9c1c88dd4fa3e0 2.3-rc |
|
72 | 72 | 7f5094bb3f423fc799e471aac2aee81a7ce57a0b 2.3 |
|
73 | 73 | 072209ae4ddb654eb2d5fd35bff358c738414432 2.3.1 |
|
74 | 74 | b3f0f9a39c4e1d0250048cd803ab03542d6f140a 2.3.2 |
|
75 | 75 | d118a4f4fd16d9b558ec3f3e87bfee772861d2b7 2.4-rc |
|
76 | 76 | 195ad823b5d58c68903a6153a25e3fb4ed25239d 2.4 |
|
77 | 77 | 0c10cf8191469e7c3c8844922e17e71a176cb7cb 2.4.1 |
|
78 | 78 | a4765077b65e6ae29ba42bab7834717b5072d5ba 2.4.2 |
|
79 | 79 | f5fbe15ca7449f2c9a3cf817c86d0ae68b307214 2.5-rc |
|
80 | 80 | a6088c05e43a8aee0472ca3a4f6f8d7dd914ebbf 2.5 |
|
81 | 81 | 7511d4df752e61fe7ae4f3682e0a0008573b0402 2.5.1 |
|
82 | 82 | 5b7175377babacce80a6c1e12366d8032a6d4340 2.5.2 |
|
83 | 83 | 50c922c1b5145dab8baefefb0437d363b6a6c21c 2.5.3 |
|
84 | 84 | 8a7bd2dccd44ed571afe7424cd7f95594f27c092 2.5.4 |
|
85 | 85 | 292cd385856d98bacb2c3086f8897bc660c2beea 2.6-rc |
|
86 | 86 | 23f785b38af38d2fca6b8f3db56b8007a84cd73a 2.6 |
|
87 | 87 | ddc7a6be20212d18f3e27d9d7e6f079a66d96f21 2.6.1 |
|
88 | 88 | cceaf7af4c9e9e6fa2dbfdcfe9856c5da69c4ffd 2.6.2 |
|
89 | 89 | 009794acc6e37a650f0fae37872e733382ac1c0c 2.6.3 |
|
90 | 90 | f0d7721d7322dcfb5af33599c2543f27335334bb 2.7-rc |
|
91 | 91 | f37b5a17e6a0ee17afde2cdde5393dd74715fb58 2.7 |
|
92 | 92 | 335a558f81dc73afeab4d7be63617392b130117f 2.7.1 |
|
93 | 93 | e7fa36d2ad3a7944a52dca126458d6f482db3524 2.7.2 |
|
94 | 94 | 1596f2d8f2421314b1ddead8f7d0c91009358994 2.8-rc |
|
95 | 95 | d825e4025e39d1c39db943cdc89818abd0a87c27 2.8 |
|
96 | 96 | 209e04a06467e2969c0cc6501335be0406d46ef0 2.8.1 |
|
97 | 97 | ca387377df7a3a67dbb90b6336b781cdadc3ef41 2.8.2 |
|
98 | 98 | 8862469e16f9236208581b20de5f96bd13cc039d 2.9-rc |
|
99 | 99 | 3cec5134e9c4bceab6a00c60f52a4f80677a78f2 2.9 |
|
100 | 100 | b96cb15ec9e04d8ac5ee08b34fcbbe4200588965 2.9.1 |
|
101 | 101 | 3f83fc5cfe715d292069ee8417c83804f6c6c1e4 2.9.2 |
|
102 | 102 | 564f55b251224f16508dd1311452db7780dafe2b 3.0-rc |
|
103 | 103 | 2195ac506c6ababe86985b932f4948837c0891b5 3.0 |
|
104 | 104 | 269c80ee5b3cb3684fa8edc61501b3506d02eb10 3.0.1 |
|
105 | 105 | 2d8cd3d0e83c7336c0cb45a9f88638363f993848 3.0.2 |
|
106 | 106 | 6c36dc6cd61a0e1b563f1d51e55bdf4dacf12162 3.1-rc |
|
107 | 107 | 3178e49892020336491cdc6945885c4de26ffa8b 3.1 |
|
108 | 108 | 5dc91146f35369949ea56b40172308158b59063a 3.1.1 |
|
109 | 109 | f768c888aaa68d12dd7f509dcc7f01c9584357d0 3.1.2 |
|
110 | 110 | 7f8d16af8cae246fa5a48e723d48d58b015aed94 3.2-rc |
|
111 | 111 | ced632394371a36953ce4d394f86278ae51a2aae 3.2 |
|
112 | 112 | 643c58303fb0ec020907af28b9e486be299ba043 3.2.1 |
|
113 | 113 | 902554884335e5ca3661d63be9978eb4aec3f68a 3.2.2 |
|
114 | 114 | 6dad422ecc5adb63d9fa649eeb8e05a5f9bc4900 3.2.3 |
|
115 | 115 | 1265a3a71d75396f5d4cf6935ae7d9ba5407a547 3.2.4 |
|
116 | 116 | db8e3f7948b1fdeb9ad12d448fc3525759908b9f 3.3-rc |
|
117 | 117 | fbdd5195528fae4f41feebc1838215c110b25d6a 3.3 |
|
118 | 118 | 5b4ed033390bf6e2879c8f5c28c84e1ee3b87231 3.3.1 |
|
119 | 119 | 07a92bbd02e5e3a625e0820389b47786b02b2cea 3.3.2 |
|
120 | 120 | 2e2e9a0750f91a6fe0ad88e4de34f8efefdcab08 3.3.3 |
|
121 | 121 | e89f909edffad558b56f4affa8239e4832f88de0 3.4-rc |
|
122 | 122 | 8cc6036bca532e06681c5a8fa37efaa812de67b5 3.4 |
|
123 | 123 | ed18f4acf435a2824c6f49fba40f42b9df5da7ad 3.4.1 |
|
124 | 124 | 540cd0ddac49c1125b2e013aa2ff18ecbd4dd954 3.4.2 |
|
125 | 125 | 96a38d44ba093bd1d1ecfd34119e94056030278b 3.5-rc |
|
126 | 126 | 21aa1c313b05b1a85f8ffa1120d51579ddf6bf24 3.5 |
|
127 | 127 | 1a45e49a6bed023deb229102a8903234d18054d3 3.5.1 |
|
128 | 128 | 9a466b9f9792e3ad7ae3fc6c43c3ff2e136b718d 3.5.2 |
|
129 | 129 | b66e3ca0b90c3095ea28dfd39aa24247bebf5c20 3.6-rc |
|
130 | 130 | 47dd34f2e7272be9e3b2a5a83cd0d20be44293f4 3.6 |
|
131 | 1aa5083cbebbe7575c88f3402ab377539b484897 3.6.1 |
@@ -1,42 +1,42 b'' | |||
|
1 | 1 | #!/bin/sh -eu |
|
2 | 2 | |
|
3 | 3 | # This function exists to set up the DOCKER variable and verify that |
|
4 | 4 | # it's the binary we expect. It also verifies that the docker service |
|
5 | 5 | # is running on the system and we can talk to it. |
|
6 | 6 | function checkdocker() { |
|
7 | 7 | if which docker.io >> /dev/null 2>&1 ; then |
|
8 | 8 | DOCKER=docker.io |
|
9 | 9 | elif which docker >> /dev/null 2>&1 ; then |
|
10 | 10 | DOCKER=docker |
|
11 | 11 | else |
|
12 | 12 | echo "Error: docker must be installed" |
|
13 | 13 | exit 1 |
|
14 | 14 | fi |
|
15 | 15 | |
|
16 | 16 | $DOCKER -h 2> /dev/null | grep -q Jansens && { echo "Error: $DOCKER is the Docking System Tray - install docker.io instead"; exit 1; } |
|
17 | 17 | $DOCKER version | grep -q "^Client version:" || { echo "Error: unexpected output from \"$DOCKER version\""; exit 1; } |
|
18 | 18 | $DOCKER version | grep -q "^Server version:" || { echo "Error: could not get docker server version - check it is running and your permissions"; exit 1; } |
|
19 | 19 | } |
|
20 | 20 | |
|
21 | 21 | # Construct a container and leave its name in $CONTAINER for future use. |
|
22 | 22 | function initcontainer() { |
|
23 | 23 | [ "$1" ] || { echo "Error: platform name must be specified"; exit 1; } |
|
24 | 24 | |
|
25 | 25 | DFILE="$ROOTDIR/contrib/docker/$1" |
|
26 | 26 | [ -f "$DFILE" ] || { echo "Error: docker file $DFILE not found"; exit 1; } |
|
27 | 27 | |
|
28 | 28 | CONTAINER="hg-dockerrpm-$1" |
|
29 | 29 | DBUILDUSER=build |
|
30 | 30 | ( |
|
31 | 31 | cat $DFILE |
|
32 | 32 | if [ $(uname) = "Darwin" ] ; then |
|
33 | 33 | # The builder is using boot2docker on OS X, so we're going to |
|
34 | 34 | # *guess* the uid of the user inside the VM that is actually |
|
35 | 35 | # running docker. This is *very likely* to fail at some point. |
|
36 | 36 | echo RUN useradd $DBUILDUSER -u 1000 |
|
37 | 37 | else |
|
38 | echo RUN groupadd $DBUILDUSER -g `id -g` | |
|
39 | echo RUN useradd $DBUILDUSER -u `id -u` -g $DBUILDUSER | |
|
38 | echo RUN groupadd $DBUILDUSER -g `id -g` --non-unique | |
|
39 | echo RUN useradd $DBUILDUSER -u `id -u` -g $DBUILDUSER --non-unique | |
|
40 | 40 | fi |
|
41 | 41 | ) | $DOCKER build --tag $CONTAINER - |
|
42 | 42 | } |
@@ -1,244 +1,244 b'' | |||
|
1 | 1 | <?xml version="1.0" encoding="utf-8"?> |
|
2 | 2 | <Wix xmlns="http://schemas.microsoft.com/wix/2006/wi"> |
|
3 | 3 | |
|
4 | 4 | <?include guids.wxi ?> |
|
5 | 5 | <?include defines.wxi ?> |
|
6 | 6 | |
|
7 | 7 | <Fragment> |
|
8 | 8 | <ComponentGroup Id="templatesFolder"> |
|
9 | 9 | |
|
10 | 10 | <ComponentRef Id="templates.root" /> |
|
11 | 11 | |
|
12 | 12 | <ComponentRef Id="templates.atom" /> |
|
13 | 13 | <ComponentRef Id="templates.coal" /> |
|
14 | 14 | <ComponentRef Id="templates.gitweb" /> |
|
15 | 15 | <ComponentRef Id="templates.json" /> |
|
16 | 16 | <ComponentRef Id="templates.monoblue" /> |
|
17 | 17 | <ComponentRef Id="templates.paper" /> |
|
18 | 18 | <ComponentRef Id="templates.raw" /> |
|
19 | 19 | <ComponentRef Id="templates.rss" /> |
|
20 | 20 | <ComponentRef Id="templates.spartan" /> |
|
21 | 21 | <ComponentRef Id="templates.static" /> |
|
22 | 22 | |
|
23 | 23 | </ComponentGroup> |
|
24 | 24 | </Fragment> |
|
25 | 25 | |
|
26 | 26 | <Fragment> |
|
27 | 27 | <DirectoryRef Id="INSTALLDIR"> |
|
28 | 28 | |
|
29 | 29 | <Directory Id="templatesdir" Name="templates" FileSource="$(var.SourceDir)"> |
|
30 | 30 | |
|
31 | 31 | <Component Id="templates.root" Guid="$(var.templates.root.guid)" Win64='$(var.IsX64)'> |
|
32 | 32 | <File Name="map-cmdline.changelog" KeyPath="yes" /> |
|
33 | 33 | <File Name="map-cmdline.compact" /> |
|
34 | 34 | <File Name="map-cmdline.default" /> |
|
35 | 35 | <File Name="map-cmdline.bisect" /> |
|
36 | 36 | <File Name="map-cmdline.xml" /> |
|
37 | 37 | <File Name="map-cmdline.phases" /> |
|
38 | 38 | </Component> |
|
39 | 39 | |
|
40 | 40 | <Directory Id="templates.jsondir" Name="json"> |
|
41 | 41 | <Component Id="templates.json" Guid="$(var.templates.json.guid)" Win64='$(var.IsX64)'> |
|
42 | 42 | <File Id="json.changelist.tmpl" Name="changelist.tmpl" KeyPath="yes" /> |
|
43 | 43 | <File Id="json.map" Name="map" /> |
|
44 | 44 | </Component> |
|
45 | 45 | </Directory> |
|
46 | 46 | |
|
47 | 47 | <Directory Id="templates.atomdir" Name="atom"> |
|
48 | 48 | <Component Id="templates.atom" Guid="$(var.templates.atom.guid)" Win64='$(var.IsX64)'> |
|
49 | 49 | <File Id="atom.changelog.tmpl" Name="changelog.tmpl" KeyPath="yes" /> |
|
50 | 50 | <File Id="atom.changelogentry.tmpl" Name="changelogentry.tmpl" /> |
|
51 | 51 | <File Id="atom.error.tmpl" Name="error.tmpl" /> |
|
52 | 52 | <File Id="atom.filelog.tmpl" Name="filelog.tmpl" /> |
|
53 | 53 | <File Id="atom.header.tmpl" Name="header.tmpl" /> |
|
54 | 54 | <File Id="atom.map" Name="map" /> |
|
55 | 55 | <File Id="atom.tagentry.tmpl" Name="tagentry.tmpl" /> |
|
56 | 56 | <File Id="atom.tags.tmpl" Name="tags.tmpl" /> |
|
57 | 57 | <File Id="atom.branchentry.tmpl" Name="branchentry.tmpl" /> |
|
58 | 58 | <File Id="atom.branches.tmpl" Name="branches.tmpl" /> |
|
59 | 59 | <File Id="atom.bookmarks.tmpl" Name="bookmarks.tmpl" /> |
|
60 | 60 | <File Id="atom.bookmarkentry.tmpl" Name="bookmarkentry.tmpl" /> |
|
61 | 61 | </Component> |
|
62 | 62 | </Directory> |
|
63 | 63 | |
|
64 | 64 | <Directory Id="templates.coaldir" Name="coal"> |
|
65 | 65 | <Component Id="templates.coal" Guid="$(var.templates.coal.guid)" Win64='$(var.IsX64)'> |
|
66 | 66 | <File Id="coal.header.tmpl" Name="header.tmpl" KeyPath="yes" /> |
|
67 | 67 | <File Id="coal.map" Name="map" /> |
|
68 | 68 | </Component> |
|
69 | 69 | </Directory> |
|
70 | 70 | |
|
71 | 71 | <Directory Id="templates.gitwebdir" Name="gitweb"> |
|
72 | 72 | <Component Id="templates.gitweb" Guid="$(var.templates.gitweb.guid)" Win64='$(var.IsX64)'> |
|
73 | 73 | <File Id="gitweb.branches.tmpl" Name="branches.tmpl" KeyPath="yes" /> |
|
74 | 74 | <File Id="gitweb.bookmarks.tmpl" Name="bookmarks.tmpl" /> |
|
75 | 75 | <File Id="gitweb.changelog.tmpl" Name="changelog.tmpl" /> |
|
76 | 76 | <File Id="gitweb.changelogentry.tmpl" Name="changelogentry.tmpl" /> |
|
77 | 77 | <File Id="gitweb.changeset.tmpl" Name="changeset.tmpl" /> |
|
78 | 78 | <File Id="gitweb.error.tmpl" Name="error.tmpl" /> |
|
79 | 79 | <File Id="gitweb.fileannotate.tmpl" Name="fileannotate.tmpl" /> |
|
80 | 80 | <File Id="gitweb.filecomparison.tmpl" Name="filecomparison.tmpl" /> |
|
81 | 81 | <File Id="gitweb.filediff.tmpl" Name="filediff.tmpl" /> |
|
82 | 82 | <File Id="gitweb.filelog.tmpl" Name="filelog.tmpl" /> |
|
83 | 83 | <File Id="gitweb.filerevision.tmpl" Name="filerevision.tmpl" /> |
|
84 | 84 | <File Id="gitweb.footer.tmpl" Name="footer.tmpl" /> |
|
85 | 85 | <File Id="gitweb.graph.tmpl" Name="graph.tmpl" /> |
|
86 | 86 | <File Id="gitweb.header.tmpl" Name="header.tmpl" /> |
|
87 | 87 | <File Id="gitweb.index.tmpl" Name="index.tmpl" /> |
|
88 | 88 | <File Id="gitweb.manifest.tmpl" Name="manifest.tmpl" /> |
|
89 | 89 | <File Id="gitweb.map" Name="map" /> |
|
90 | 90 | <File Id="gitweb.notfound.tmpl" Name="notfound.tmpl" /> |
|
91 | 91 | <File Id="gitweb.search.tmpl" Name="search.tmpl" /> |
|
92 | 92 | <File Id="gitweb.shortlog.tmpl" Name="shortlog.tmpl" /> |
|
93 | 93 | <File Id="gitweb.summary.tmpl" Name="summary.tmpl" /> |
|
94 | 94 | <File Id="gitweb.tags.tmpl" Name="tags.tmpl" /> |
|
95 | 95 | <File Id="gitweb.help.tmpl" Name="help.tmpl" /> |
|
96 | 96 | <File Id="gitweb.helptopics.tmpl" Name="helptopics.tmpl" /> |
|
97 | 97 | </Component> |
|
98 | 98 | </Directory> |
|
99 | 99 | |
|
100 | 100 | <Directory Id="templates.monobluedir" Name="monoblue"> |
|
101 | 101 | <Component Id="templates.monoblue" Guid="$(var.templates.monoblue.guid)" Win64='$(var.IsX64)'> |
|
102 | 102 | <File Id="monoblue.branches.tmpl" Name="branches.tmpl" KeyPath="yes" /> |
|
103 | 103 | <File Id="monoblue.bookmarks.tmpl" Name="bookmarks.tmpl" /> |
|
104 | 104 | <File Id="monoblue.changelog.tmpl" Name="changelog.tmpl" /> |
|
105 | 105 | <File Id="monoblue.changelogentry.tmpl" Name="changelogentry.tmpl" /> |
|
106 | 106 | <File Id="monoblue.changeset.tmpl" Name="changeset.tmpl" /> |
|
107 | 107 | <File Id="monoblue.error.tmpl" Name="error.tmpl" /> |
|
108 | 108 | <File Id="monoblue.fileannotate.tmpl" Name="fileannotate.tmpl" /> |
|
109 | 109 | <File Id="monoblue.filecomparison.tmpl" Name="filecomparison.tmpl" /> |
|
110 | 110 | <File Id="monoblue.filediff.tmpl" Name="filediff.tmpl" /> |
|
111 | 111 | <File Id="monoblue.filelog.tmpl" Name="filelog.tmpl" /> |
|
112 | 112 | <File Id="monoblue.filerevision.tmpl" Name="filerevision.tmpl" /> |
|
113 | 113 | <File Id="monoblue.footer.tmpl" Name="footer.tmpl" /> |
|
114 | 114 | <File Id="monoblue.graph.tmpl" Name="graph.tmpl" /> |
|
115 | 115 | <File Id="monoblue.header.tmpl" Name="header.tmpl" /> |
|
116 | 116 | <File Id="monoblue.index.tmpl" Name="index.tmpl" /> |
|
117 | 117 | <File Id="monoblue.manifest.tmpl" Name="manifest.tmpl" /> |
|
118 | 118 | <File Id="monoblue.map" Name="map" /> |
|
119 | 119 | <File Id="monoblue.notfound.tmpl" Name="notfound.tmpl" /> |
|
120 | 120 | <File Id="monoblue.search.tmpl" Name="search.tmpl" /> |
|
121 | 121 | <File Id="monoblue.shortlog.tmpl" Name="shortlog.tmpl" /> |
|
122 | 122 | <File Id="monoblue.summary.tmpl" Name="summary.tmpl" /> |
|
123 | 123 | <File Id="monoblue.tags.tmpl" Name="tags.tmpl" /> |
|
124 | 124 | <File Id="monoblue.help.tmpl" Name="help.tmpl" /> |
|
125 | 125 | <File Id="monoblue.helptopics.tmpl" Name="helptopics.tmpl" /> |
|
126 | 126 | </Component> |
|
127 | 127 | </Directory> |
|
128 | 128 | |
|
129 | 129 | <Directory Id="templates.paperdir" Name="paper"> |
|
130 | 130 | <Component Id="templates.paper" Guid="$(var.templates.paper.guid)" Win64='$(var.IsX64)'> |
|
131 | 131 | <File Id="paper.branches.tmpl" Name="branches.tmpl" KeyPath="yes" /> |
|
132 | 132 | <File Id="paper.bookmarks.tmpl" Name="bookmarks.tmpl" /> |
|
133 | 133 | <File Id="paper.changeset.tmpl" Name="changeset.tmpl" /> |
|
134 | 134 | <File Id="paper.diffstat.tmpl" Name="diffstat.tmpl" /> |
|
135 | 135 | <File Id="paper.error.tmpl" Name="error.tmpl" /> |
|
136 | 136 | <File Id="paper.fileannotate.tmpl" Name="fileannotate.tmpl" /> |
|
137 | 137 | <File Id="paper.filecomparison.tmpl" Name="filecomparison.tmpl" /> |
|
138 | 138 | <File Id="paper.filediff.tmpl" Name="filediff.tmpl" /> |
|
139 | 139 | <File Id="paper.filelog.tmpl" Name="filelog.tmpl" /> |
|
140 | 140 | <File Id="paper.filelogentry.tmpl" Name="filelogentry.tmpl" /> |
|
141 | 141 | <File Id="paper.filerevision.tmpl" Name="filerevision.tmpl" /> |
|
142 | 142 | <File Id="paper.footer.tmpl" Name="footer.tmpl" /> |
|
143 | 143 | <File Id="paper.graph.tmpl" Name="graph.tmpl" /> |
|
144 | 144 | <File Id="paper.header.tmpl" Name="header.tmpl" /> |
|
145 | 145 | <File Id="paper.index.tmpl" Name="index.tmpl" /> |
|
146 | 146 | <File Id="paper.manifest.tmpl" Name="manifest.tmpl" /> |
|
147 | 147 | <File Id="paper.map" Name="map" /> |
|
148 | 148 | <File Id="paper.notfound.tmpl" Name="notfound.tmpl" /> |
|
149 | 149 | <File Id="paper.search.tmpl" Name="search.tmpl" /> |
|
150 | 150 | <File Id="paper.shortlog.tmpl" Name="shortlog.tmpl" /> |
|
151 | 151 | <File Id="paper.shortlogentry.tmpl" Name="shortlogentry.tmpl" /> |
|
152 | 152 | <File Id="paper.tags.tmpl" Name="tags.tmpl" /> |
|
153 | 153 | <File Id="paper.help.tmpl" Name="help.tmpl" /> |
|
154 | 154 | <File Id="paper.helptopics.tmpl" Name="helptopics.tmpl" /> |
|
155 | 155 | </Component> |
|
156 | 156 | </Directory> |
|
157 | 157 | |
|
158 | 158 | <Directory Id="templates.rawdir" Name="raw"> |
|
159 | 159 | <Component Id="templates.raw" Guid="$(var.templates.raw.guid)" Win64='$(var.IsX64)'> |
|
160 | 160 | <File Id="raw.changeset.tmpl" Name="changeset.tmpl" KeyPath="yes" /> |
|
161 | 161 | <File Id="raw.error.tmpl" Name="error.tmpl" /> |
|
162 | 162 | <File Id="raw.fileannotate.tmpl" Name="fileannotate.tmpl" /> |
|
163 | 163 | <File Id="raw.filediff.tmpl" Name="filediff.tmpl" /> |
|
164 | 164 | <File Id="raw.graph.tmpl" Name="graph.tmpl" /> |
|
165 | 165 | <File Id="raw.graphedge.tmpl" Name="graphedge.tmpl" /> |
|
166 | 166 | <File Id="raw.graphnode.tmpl" Name="graphnode.tmpl" /> |
|
167 | 167 | <File Id="raw.index.tmpl" Name="index.tmpl" /> |
|
168 | 168 | <File Id="raw.manifest.tmpl" Name="manifest.tmpl" /> |
|
169 | 169 | <File Id="raw.map" Name="map" /> |
|
170 | 170 | <File Id="raw.notfound.tmpl" Name="notfound.tmpl" /> |
|
171 | 171 | <File Id="raw.search.tmpl" Name="search.tmpl" /> |
|
172 | 172 | <File Id="raw.logentry.tmpl" Name="logentry.tmpl" /> |
|
173 | 173 | <File Id="raw.changelog.tmpl" Name="changelog.tmpl" /> |
|
174 | 174 | </Component> |
|
175 | 175 | </Directory> |
|
176 | 176 | |
|
177 | 177 | <Directory Id="templates.rssdir" Name="rss"> |
|
178 | 178 | <Component Id="templates.rss" Guid="$(var.templates.rss.guid)" Win64='$(var.IsX64)'> |
|
179 | 179 | <File Id="rss.changelog.tmpl" Name="changelog.tmpl" KeyPath="yes" /> |
|
180 | 180 | <File Id="rss.changelogentry.tmpl" Name="changelogentry.tmpl" /> |
|
181 | 181 | <File Id="rss.error.tmpl" Name="error.tmpl" /> |
|
182 | 182 | <File Id="rss.filelog.tmpl" Name="filelog.tmpl" /> |
|
183 | 183 | <File Id="rss.filelogentry.tmpl" Name="filelogentry.tmpl" /> |
|
184 | 184 | <File Id="rss.header.tmpl" Name="header.tmpl" /> |
|
185 | 185 | <File Id="rss.map" Name="map" /> |
|
186 | 186 | <File Id="rss.tagentry.tmpl" Name="tagentry.tmpl" /> |
|
187 | 187 | <File Id="rss.tags.tmpl" Name="tags.tmpl" /> |
|
188 | 188 | <File Id="rss.bookmarks.tmpl" Name="bookmarks.tmpl" /> |
|
189 | 189 | <File Id="rss.bookmarkentry.tmpl" Name="bookmarkentry.tmpl" /> |
|
190 | 190 | <File Id="rss.branchentry.tmpl" Name="branchentry.tmpl" /> |
|
191 | 191 | <File Id="rss.branches.tmpl" Name="branches.tmpl" /> |
|
192 | 192 | </Component> |
|
193 | 193 | </Directory> |
|
194 | 194 | |
|
195 | 195 | <Directory Id="templates.spartandir" Name="spartan"> |
|
196 | 196 | <Component Id="templates.spartan" Guid="$(var.templates.spartan.guid)" Win64='$(var.IsX64)'> |
|
197 | 197 | <File Id="spartan.branches.tmpl" Name="branches.tmpl" KeyPath="yes" /> |
|
198 | 198 | <File Id="spartan.changelog.tmpl" Name="changelog.tmpl" /> |
|
199 | 199 | <File Id="spartan.changelogentry.tmpl" Name="changelogentry.tmpl" /> |
|
200 | 200 | <File Id="spartan.changeset.tmpl" Name="changeset.tmpl" /> |
|
201 | 201 | <File Id="spartan.error.tmpl" Name="error.tmpl" /> |
|
202 | 202 | <File Id="spartan.fileannotate.tmpl" Name="fileannotate.tmpl" /> |
|
203 | 203 | <File Id="spartan.filediff.tmpl" Name="filediff.tmpl" /> |
|
204 | 204 | <File Id="spartan.filelog.tmpl" Name="filelog.tmpl" /> |
|
205 | 205 | <File Id="spartan.filelogentry.tmpl" Name="filelogentry.tmpl" /> |
|
206 | 206 | <File Id="spartan.filerevision.tmpl" Name="filerevision.tmpl" /> |
|
207 | 207 | <File Id="spartan.footer.tmpl" Name="footer.tmpl" /> |
|
208 | 208 | <File Id="spartan.graph.tmpl" Name="graph.tmpl" /> |
|
209 | 209 | <File Id="spartan.header.tmpl" Name="header.tmpl" /> |
|
210 | 210 | <File Id="spartan.index.tmpl" Name="index.tmpl" /> |
|
211 | 211 | <File Id="spartan.manifest.tmpl" Name="manifest.tmpl" /> |
|
212 | 212 | <File Id="spartan.map" Name="map" /> |
|
213 | 213 | <File Id="spartan.notfound.tmpl" Name="notfound.tmpl" /> |
|
214 | 214 | <File Id="spartan.search.tmpl" Name="search.tmpl" /> |
|
215 | 215 | <File Id="spartan.shortlog.tmpl" Name="shortlog.tmpl" /> |
|
216 | 216 | <File Id="spartan.shortlogentry.tmpl" Name="shortlogentry.tmpl" /> |
|
217 | 217 | <File Id="spartan.tags.tmpl" Name="tags.tmpl" /> |
|
218 | 218 | </Component> |
|
219 | 219 | </Directory> |
|
220 | 220 | |
|
221 | 221 | <Directory Id="templates.staticdir" Name="static"> |
|
222 | 222 | <Component Id="templates.static" Guid="$(var.templates.static.guid)" Win64='$(var.IsX64)'> |
|
223 | 223 | <File Id="static.background.png" Name="background.png" KeyPath="yes" /> |
|
224 | 224 | <File Id="static.coal.file.png" Name="coal-file.png" /> |
|
225 | 225 | <File Id="static.coal.folder.png" Name="coal-folder.png" /> |
|
226 | 226 | <File Id="static.excanvas.js" Name="excanvas.js" /> |
|
227 | 227 | <File Id="static.mercurial.js" Name="mercurial.js" /> |
|
228 | 228 | <File Id="static.hgicon.png" Name="hgicon.png" /> |
|
229 | 229 | <File Id="static.hglogo.png" Name="hglogo.png" /> |
|
230 | <File Id="static.style.coal.css" Name="style-coal.css" /> | |
|
230 | <File Id="static.style.coal.css" Name="style-extra-coal.css" /> | |
|
231 | 231 | <File Id="static.style.gitweb.css" Name="style-gitweb.css" /> |
|
232 | 232 | <File Id="static.style.monoblue.css" Name="style-monoblue.css" /> |
|
233 | 233 | <File Id="static.style.paper.css" Name="style-paper.css" /> |
|
234 | 234 | <File Id="static.style.css" Name="style.css" /> |
|
235 | 235 | <File Id="static.feed.icon" Name="feed-icon-14x14.png" /> |
|
236 | 236 | </Component> |
|
237 | 237 | </Directory> |
|
238 | 238 | |
|
239 | 239 | </Directory> |
|
240 | 240 | |
|
241 | 241 | </DirectoryRef> |
|
242 | 242 | </Fragment> |
|
243 | 243 | |
|
244 | 244 | </Wix> |
@@ -1,1167 +1,1172 b'' | |||
|
1 | 1 | # dirstate.py - working directory tracking for mercurial |
|
2 | 2 | # |
|
3 | 3 | # Copyright 2005-2007 Matt Mackall <mpm@selenic.com> |
|
4 | 4 | # |
|
5 | 5 | # This software may be used and distributed according to the terms of the |
|
6 | 6 | # GNU General Public License version 2 or any later version. |
|
7 | 7 | |
|
8 | 8 | from node import nullid |
|
9 | 9 | from i18n import _ |
|
10 | 10 | import scmutil, util, osutil, parsers, encoding, pathutil, error |
|
11 | 11 | import os, stat, errno |
|
12 | 12 | import match as matchmod |
|
13 | 13 | |
|
14 | 14 | propertycache = util.propertycache |
|
15 | 15 | filecache = scmutil.filecache |
|
16 | 16 | _rangemask = 0x7fffffff |
|
17 | 17 | |
|
18 | 18 | dirstatetuple = parsers.dirstatetuple |
|
19 | 19 | |
|
20 | 20 | class repocache(filecache): |
|
21 | 21 | """filecache for files in .hg/""" |
|
22 | 22 | def join(self, obj, fname): |
|
23 | 23 | return obj._opener.join(fname) |
|
24 | 24 | |
|
25 | 25 | class rootcache(filecache): |
|
26 | 26 | """filecache for files in the repository root""" |
|
27 | 27 | def join(self, obj, fname): |
|
28 | 28 | return obj._join(fname) |
|
29 | 29 | |
|
30 | 30 | def _getfsnow(vfs): |
|
31 | 31 | '''Get "now" timestamp on filesystem''' |
|
32 | 32 | tmpfd, tmpname = vfs.mkstemp() |
|
33 | 33 | try: |
|
34 | 34 | return util.statmtimesec(os.fstat(tmpfd)) |
|
35 | 35 | finally: |
|
36 | 36 | os.close(tmpfd) |
|
37 | 37 | vfs.unlink(tmpname) |
|
38 | 38 | |
|
39 | 39 | def _trypending(root, vfs, filename): |
|
40 | 40 | '''Open file to be read according to HG_PENDING environment variable |
|
41 | 41 | |
|
42 | 42 | This opens '.pending' of specified 'filename' only when HG_PENDING |
|
43 | 43 | is equal to 'root'. |
|
44 | 44 | |
|
45 | 45 | This returns '(fp, is_pending_opened)' tuple. |
|
46 | 46 | ''' |
|
47 | 47 | if root == os.environ.get('HG_PENDING'): |
|
48 | 48 | try: |
|
49 | 49 | return (vfs('%s.pending' % filename), True) |
|
50 | 50 | except IOError as inst: |
|
51 | 51 | if inst.errno != errno.ENOENT: |
|
52 | 52 | raise |
|
53 | 53 | return (vfs(filename), False) |
|
54 | 54 | |
|
55 | 55 | class dirstate(object): |
|
56 | 56 | |
|
57 | 57 | def __init__(self, opener, ui, root, validate): |
|
58 | 58 | '''Create a new dirstate object. |
|
59 | 59 | |
|
60 | 60 | opener is an open()-like callable that can be used to open the |
|
61 | 61 | dirstate file; root is the root of the directory tracked by |
|
62 | 62 | the dirstate. |
|
63 | 63 | ''' |
|
64 | 64 | self._opener = opener |
|
65 | 65 | self._validate = validate |
|
66 | 66 | self._root = root |
|
67 | 67 | # ntpath.join(root, '') of Python 2.7.9 does not add sep if root is |
|
68 | 68 | # UNC path pointing to root share (issue4557) |
|
69 | 69 | self._rootdir = pathutil.normasprefix(root) |
|
70 | 70 | # internal config: ui.forcecwd |
|
71 | 71 | forcecwd = ui.config('ui', 'forcecwd') |
|
72 | 72 | if forcecwd: |
|
73 | 73 | self._cwd = forcecwd |
|
74 | 74 | self._dirty = False |
|
75 | 75 | self._dirtypl = False |
|
76 | 76 | self._lastnormaltime = 0 |
|
77 | 77 | self._ui = ui |
|
78 | 78 | self._filecache = {} |
|
79 | 79 | self._parentwriters = 0 |
|
80 | 80 | self._filename = 'dirstate' |
|
81 | 81 | self._pendingfilename = '%s.pending' % self._filename |
|
82 | 82 | |
|
83 | 83 | # for consistent view between _pl() and _read() invocations |
|
84 | 84 | self._pendingmode = None |
|
85 | 85 | |
|
86 | 86 | def beginparentchange(self): |
|
87 | 87 | '''Marks the beginning of a set of changes that involve changing |
|
88 | 88 | the dirstate parents. If there is an exception during this time, |
|
89 | 89 | the dirstate will not be written when the wlock is released. This |
|
90 | 90 | prevents writing an incoherent dirstate where the parent doesn't |
|
91 | 91 | match the contents. |
|
92 | 92 | ''' |
|
93 | 93 | self._parentwriters += 1 |
|
94 | 94 | |
|
95 | 95 | def endparentchange(self): |
|
96 | 96 | '''Marks the end of a set of changes that involve changing the |
|
97 | 97 | dirstate parents. Once all parent changes have been marked done, |
|
98 | 98 | the wlock will be free to write the dirstate on release. |
|
99 | 99 | ''' |
|
100 | 100 | if self._parentwriters > 0: |
|
101 | 101 | self._parentwriters -= 1 |
|
102 | 102 | |
|
103 | 103 | def pendingparentchange(self): |
|
104 | 104 | '''Returns true if the dirstate is in the middle of a set of changes |
|
105 | 105 | that modify the dirstate parent. |
|
106 | 106 | ''' |
|
107 | 107 | return self._parentwriters > 0 |
|
108 | 108 | |
|
109 | 109 | @propertycache |
|
110 | 110 | def _map(self): |
|
111 | 111 | '''Return the dirstate contents as a map from filename to |
|
112 | 112 | (state, mode, size, time).''' |
|
113 | 113 | self._read() |
|
114 | 114 | return self._map |
|
115 | 115 | |
|
116 | 116 | @propertycache |
|
117 | 117 | def _copymap(self): |
|
118 | 118 | self._read() |
|
119 | 119 | return self._copymap |
|
120 | 120 | |
|
121 | 121 | @propertycache |
|
122 | 122 | def _filefoldmap(self): |
|
123 | 123 | try: |
|
124 | 124 | makefilefoldmap = parsers.make_file_foldmap |
|
125 | 125 | except AttributeError: |
|
126 | 126 | pass |
|
127 | 127 | else: |
|
128 | 128 | return makefilefoldmap(self._map, util.normcasespec, |
|
129 | 129 | util.normcasefallback) |
|
130 | 130 | |
|
131 | 131 | f = {} |
|
132 | 132 | normcase = util.normcase |
|
133 | 133 | for name, s in self._map.iteritems(): |
|
134 | 134 | if s[0] != 'r': |
|
135 | 135 | f[normcase(name)] = name |
|
136 | 136 | f['.'] = '.' # prevents useless util.fspath() invocation |
|
137 | 137 | return f |
|
138 | 138 | |
|
139 | 139 | @propertycache |
|
140 | 140 | def _dirfoldmap(self): |
|
141 | 141 | f = {} |
|
142 | 142 | normcase = util.normcase |
|
143 | 143 | for name in self._dirs: |
|
144 | 144 | f[normcase(name)] = name |
|
145 | 145 | return f |
|
146 | 146 | |
|
147 | 147 | @repocache('branch') |
|
148 | 148 | def _branch(self): |
|
149 | 149 | try: |
|
150 | 150 | return self._opener.read("branch").strip() or "default" |
|
151 | 151 | except IOError as inst: |
|
152 | 152 | if inst.errno != errno.ENOENT: |
|
153 | 153 | raise |
|
154 | 154 | return "default" |
|
155 | 155 | |
|
156 | 156 | @propertycache |
|
157 | 157 | def _pl(self): |
|
158 | 158 | try: |
|
159 | 159 | fp = self._opendirstatefile() |
|
160 | 160 | st = fp.read(40) |
|
161 | 161 | fp.close() |
|
162 | 162 | l = len(st) |
|
163 | 163 | if l == 40: |
|
164 | 164 | return st[:20], st[20:40] |
|
165 | 165 | elif l > 0 and l < 40: |
|
166 | 166 | raise error.Abort(_('working directory state appears damaged!')) |
|
167 | 167 | except IOError as err: |
|
168 | 168 | if err.errno != errno.ENOENT: |
|
169 | 169 | raise |
|
170 | 170 | return [nullid, nullid] |
|
171 | 171 | |
|
172 | 172 | @propertycache |
|
173 | 173 | def _dirs(self): |
|
174 | 174 | return util.dirs(self._map, 'r') |
|
175 | 175 | |
|
176 | 176 | def dirs(self): |
|
177 | 177 | return self._dirs |
|
178 | 178 | |
|
179 | 179 | @rootcache('.hgignore') |
|
180 | 180 | def _ignore(self): |
|
181 | 181 | files = [] |
|
182 | 182 | if os.path.exists(self._join('.hgignore')): |
|
183 | 183 | files.append(self._join('.hgignore')) |
|
184 | 184 | for name, path in self._ui.configitems("ui"): |
|
185 | 185 | if name == 'ignore' or name.startswith('ignore.'): |
|
186 | 186 | # we need to use os.path.join here rather than self._join |
|
187 | 187 | # because path is arbitrary and user-specified |
|
188 | 188 | files.append(os.path.join(self._rootdir, util.expandpath(path))) |
|
189 | 189 | |
|
190 | 190 | if not files: |
|
191 | 191 | return util.never |
|
192 | 192 | |
|
193 | 193 | pats = ['include:%s' % f for f in files] |
|
194 | 194 | return matchmod.match(self._root, '', [], pats, warn=self._ui.warn) |
|
195 | 195 | |
|
196 | 196 | @propertycache |
|
197 | 197 | def _slash(self): |
|
198 | 198 | return self._ui.configbool('ui', 'slash') and os.sep != '/' |
|
199 | 199 | |
|
200 | 200 | @propertycache |
|
201 | 201 | def _checklink(self): |
|
202 | 202 | return util.checklink(self._root) |
|
203 | 203 | |
|
204 | 204 | @propertycache |
|
205 | 205 | def _checkexec(self): |
|
206 | 206 | return util.checkexec(self._root) |
|
207 | 207 | |
|
208 | 208 | @propertycache |
|
209 | 209 | def _checkcase(self): |
|
210 | 210 | return not util.checkcase(self._join('.hg')) |
|
211 | 211 | |
|
212 | 212 | def _join(self, f): |
|
213 | 213 | # much faster than os.path.join() |
|
214 | 214 | # it's safe because f is always a relative path |
|
215 | 215 | return self._rootdir + f |
|
216 | 216 | |
|
217 | 217 | def flagfunc(self, buildfallback): |
|
218 | 218 | if self._checklink and self._checkexec: |
|
219 | 219 | def f(x): |
|
220 | 220 | try: |
|
221 | 221 | st = os.lstat(self._join(x)) |
|
222 | 222 | if util.statislink(st): |
|
223 | 223 | return 'l' |
|
224 | 224 | if util.statisexec(st): |
|
225 | 225 | return 'x' |
|
226 | 226 | except OSError: |
|
227 | 227 | pass |
|
228 | 228 | return '' |
|
229 | 229 | return f |
|
230 | 230 | |
|
231 | 231 | fallback = buildfallback() |
|
232 | 232 | if self._checklink: |
|
233 | 233 | def f(x): |
|
234 | 234 | if os.path.islink(self._join(x)): |
|
235 | 235 | return 'l' |
|
236 | 236 | if 'x' in fallback(x): |
|
237 | 237 | return 'x' |
|
238 | 238 | return '' |
|
239 | 239 | return f |
|
240 | 240 | if self._checkexec: |
|
241 | 241 | def f(x): |
|
242 | 242 | if 'l' in fallback(x): |
|
243 | 243 | return 'l' |
|
244 | 244 | if util.isexec(self._join(x)): |
|
245 | 245 | return 'x' |
|
246 | 246 | return '' |
|
247 | 247 | return f |
|
248 | 248 | else: |
|
249 | 249 | return fallback |
|
250 | 250 | |
|
251 | 251 | @propertycache |
|
252 | 252 | def _cwd(self): |
|
253 | 253 | return os.getcwd() |
|
254 | 254 | |
|
255 | 255 | def getcwd(self): |
|
256 | 256 | '''Return the path from which a canonical path is calculated. |
|
257 | 257 | |
|
258 | 258 | This path should be used to resolve file patterns or to convert |
|
259 | 259 | canonical paths back to file paths for display. It shouldn't be |
|
260 | 260 | used to get real file paths. Use vfs functions instead. |
|
261 | 261 | ''' |
|
262 | 262 | cwd = self._cwd |
|
263 | 263 | if cwd == self._root: |
|
264 | 264 | return '' |
|
265 | 265 | # self._root ends with a path separator if self._root is '/' or 'C:\' |
|
266 | 266 | rootsep = self._root |
|
267 | 267 | if not util.endswithsep(rootsep): |
|
268 | 268 | rootsep += os.sep |
|
269 | 269 | if cwd.startswith(rootsep): |
|
270 | 270 | return cwd[len(rootsep):] |
|
271 | 271 | else: |
|
272 | 272 | # we're outside the repo. return an absolute path. |
|
273 | 273 | return cwd |
|
274 | 274 | |
|
275 | 275 | def pathto(self, f, cwd=None): |
|
276 | 276 | if cwd is None: |
|
277 | 277 | cwd = self.getcwd() |
|
278 | 278 | path = util.pathto(self._root, cwd, f) |
|
279 | 279 | if self._slash: |
|
280 | 280 | return util.pconvert(path) |
|
281 | 281 | return path |
|
282 | 282 | |
|
283 | 283 | def __getitem__(self, key): |
|
284 | 284 | '''Return the current state of key (a filename) in the dirstate. |
|
285 | 285 | |
|
286 | 286 | States are: |
|
287 | 287 | n normal |
|
288 | 288 | m needs merging |
|
289 | 289 | r marked for removal |
|
290 | 290 | a marked for addition |
|
291 | 291 | ? not tracked |
|
292 | 292 | ''' |
|
293 | 293 | return self._map.get(key, ("?",))[0] |
|
294 | 294 | |
|
295 | 295 | def __contains__(self, key): |
|
296 | 296 | return key in self._map |
|
297 | 297 | |
|
298 | 298 | def __iter__(self): |
|
299 | 299 | for x in sorted(self._map): |
|
300 | 300 | yield x |
|
301 | 301 | |
|
302 | 302 | def iteritems(self): |
|
303 | 303 | return self._map.iteritems() |
|
304 | 304 | |
|
305 | 305 | def parents(self): |
|
306 | 306 | return [self._validate(p) for p in self._pl] |
|
307 | 307 | |
|
308 | 308 | def p1(self): |
|
309 | 309 | return self._validate(self._pl[0]) |
|
310 | 310 | |
|
311 | 311 | def p2(self): |
|
312 | 312 | return self._validate(self._pl[1]) |
|
313 | 313 | |
|
314 | 314 | def branch(self): |
|
315 | 315 | return encoding.tolocal(self._branch) |
|
316 | 316 | |
|
317 | 317 | def setparents(self, p1, p2=nullid): |
|
318 | 318 | """Set dirstate parents to p1 and p2. |
|
319 | 319 | |
|
320 | 320 | When moving from two parents to one, 'm' merged entries a |
|
321 | 321 | adjusted to normal and previous copy records discarded and |
|
322 | 322 | returned by the call. |
|
323 | 323 | |
|
324 | 324 | See localrepo.setparents() |
|
325 | 325 | """ |
|
326 | 326 | if self._parentwriters == 0: |
|
327 | 327 | raise ValueError("cannot set dirstate parent without " |
|
328 | 328 | "calling dirstate.beginparentchange") |
|
329 | 329 | |
|
330 | 330 | self._dirty = self._dirtypl = True |
|
331 | 331 | oldp2 = self._pl[1] |
|
332 | 332 | self._pl = p1, p2 |
|
333 | 333 | copies = {} |
|
334 | 334 | if oldp2 != nullid and p2 == nullid: |
|
335 | 335 | for f, s in self._map.iteritems(): |
|
336 | 336 | # Discard 'm' markers when moving away from a merge state |
|
337 | 337 | if s[0] == 'm': |
|
338 | 338 | if f in self._copymap: |
|
339 | 339 | copies[f] = self._copymap[f] |
|
340 | 340 | self.normallookup(f) |
|
341 | 341 | # Also fix up otherparent markers |
|
342 | 342 | elif s[0] == 'n' and s[2] == -2: |
|
343 | 343 | if f in self._copymap: |
|
344 | 344 | copies[f] = self._copymap[f] |
|
345 | 345 | self.add(f) |
|
346 | 346 | return copies |
|
347 | 347 | |
|
348 | 348 | def setbranch(self, branch): |
|
349 | 349 | self._branch = encoding.fromlocal(branch) |
|
350 | 350 | f = self._opener('branch', 'w', atomictemp=True) |
|
351 | 351 | try: |
|
352 | 352 | f.write(self._branch + '\n') |
|
353 | 353 | f.close() |
|
354 | 354 | |
|
355 | 355 | # make sure filecache has the correct stat info for _branch after |
|
356 | 356 | # replacing the underlying file |
|
357 | 357 | ce = self._filecache['_branch'] |
|
358 | 358 | if ce: |
|
359 | 359 | ce.refresh() |
|
360 | 360 | except: # re-raises |
|
361 | 361 | f.discard() |
|
362 | 362 | raise |
|
363 | 363 | |
|
364 | 364 | def _opendirstatefile(self): |
|
365 | 365 | fp, mode = _trypending(self._root, self._opener, self._filename) |
|
366 | 366 | if self._pendingmode is not None and self._pendingmode != mode: |
|
367 | 367 | fp.close() |
|
368 | 368 | raise error.Abort(_('working directory state may be ' |
|
369 | 369 | 'changed parallelly')) |
|
370 | 370 | self._pendingmode = mode |
|
371 | 371 | return fp |
|
372 | 372 | |
|
373 | 373 | def _read(self): |
|
374 | 374 | self._map = {} |
|
375 | 375 | self._copymap = {} |
|
376 | 376 | try: |
|
377 | 377 | fp = self._opendirstatefile() |
|
378 | 378 | try: |
|
379 | 379 | st = fp.read() |
|
380 | 380 | finally: |
|
381 | 381 | fp.close() |
|
382 | 382 | except IOError as err: |
|
383 | 383 | if err.errno != errno.ENOENT: |
|
384 | 384 | raise |
|
385 | 385 | return |
|
386 | 386 | if not st: |
|
387 | 387 | return |
|
388 | 388 | |
|
389 | 389 | if util.safehasattr(parsers, 'dict_new_presized'): |
|
390 | 390 | # Make an estimate of the number of files in the dirstate based on |
|
391 | 391 | # its size. From a linear regression on a set of real-world repos, |
|
392 | 392 | # all over 10,000 files, the size of a dirstate entry is 85 |
|
393 | 393 | # bytes. The cost of resizing is significantly higher than the cost |
|
394 | 394 | # of filling in a larger presized dict, so subtract 20% from the |
|
395 | 395 | # size. |
|
396 | 396 | # |
|
397 | 397 | # This heuristic is imperfect in many ways, so in a future dirstate |
|
398 | 398 | # format update it makes sense to just record the number of entries |
|
399 | 399 | # on write. |
|
400 | 400 | self._map = parsers.dict_new_presized(len(st) / 71) |
|
401 | 401 | |
|
402 | 402 | # Python's garbage collector triggers a GC each time a certain number |
|
403 | 403 | # of container objects (the number being defined by |
|
404 | 404 | # gc.get_threshold()) are allocated. parse_dirstate creates a tuple |
|
405 | 405 | # for each file in the dirstate. The C version then immediately marks |
|
406 | 406 | # them as not to be tracked by the collector. However, this has no |
|
407 | 407 | # effect on when GCs are triggered, only on what objects the GC looks |
|
408 | 408 | # into. This means that O(number of files) GCs are unavoidable. |
|
409 | 409 | # Depending on when in the process's lifetime the dirstate is parsed, |
|
410 | 410 | # this can get very expensive. As a workaround, disable GC while |
|
411 | 411 | # parsing the dirstate. |
|
412 | 412 | # |
|
413 | 413 | # (we cannot decorate the function directly since it is in a C module) |
|
414 | 414 | parse_dirstate = util.nogc(parsers.parse_dirstate) |
|
415 | 415 | p = parse_dirstate(self._map, self._copymap, st) |
|
416 | 416 | if not self._dirtypl: |
|
417 | 417 | self._pl = p |
|
418 | 418 | |
|
419 | 419 | def invalidate(self): |
|
420 | 420 | for a in ("_map", "_copymap", "_filefoldmap", "_dirfoldmap", "_branch", |
|
421 | 421 | "_pl", "_dirs", "_ignore"): |
|
422 | 422 | if a in self.__dict__: |
|
423 | 423 | delattr(self, a) |
|
424 | 424 | self._lastnormaltime = 0 |
|
425 | 425 | self._dirty = False |
|
426 | 426 | self._parentwriters = 0 |
|
427 | 427 | |
|
428 | 428 | def copy(self, source, dest): |
|
429 | 429 | """Mark dest as a copy of source. Unmark dest if source is None.""" |
|
430 | 430 | if source == dest: |
|
431 | 431 | return |
|
432 | 432 | self._dirty = True |
|
433 | 433 | if source is not None: |
|
434 | 434 | self._copymap[dest] = source |
|
435 | 435 | elif dest in self._copymap: |
|
436 | 436 | del self._copymap[dest] |
|
437 | 437 | |
|
438 | 438 | def copied(self, file): |
|
439 | 439 | return self._copymap.get(file, None) |
|
440 | 440 | |
|
441 | 441 | def copies(self): |
|
442 | 442 | return self._copymap |
|
443 | 443 | |
|
444 | 444 | def _droppath(self, f): |
|
445 | 445 | if self[f] not in "?r" and "_dirs" in self.__dict__: |
|
446 | 446 | self._dirs.delpath(f) |
|
447 | 447 | |
|
448 | if "_filefoldmap" in self.__dict__: | |
|
449 | normed = util.normcase(f) | |
|
450 | if normed in self._filefoldmap: | |
|
451 | del self._filefoldmap[normed] | |
|
452 | ||
|
448 | 453 | def _addpath(self, f, state, mode, size, mtime): |
|
449 | 454 | oldstate = self[f] |
|
450 | 455 | if state == 'a' or oldstate == 'r': |
|
451 | 456 | scmutil.checkfilename(f) |
|
452 | 457 | if f in self._dirs: |
|
453 | 458 | raise error.Abort(_('directory %r already in dirstate') % f) |
|
454 | 459 | # shadows |
|
455 | 460 | for d in util.finddirs(f): |
|
456 | 461 | if d in self._dirs: |
|
457 | 462 | break |
|
458 | 463 | if d in self._map and self[d] != 'r': |
|
459 | 464 | raise error.Abort( |
|
460 | 465 | _('file %r in dirstate clashes with %r') % (d, f)) |
|
461 | 466 | if oldstate in "?r" and "_dirs" in self.__dict__: |
|
462 | 467 | self._dirs.addpath(f) |
|
463 | 468 | self._dirty = True |
|
464 | 469 | self._map[f] = dirstatetuple(state, mode, size, mtime) |
|
465 | 470 | |
|
466 | 471 | def normal(self, f): |
|
467 | 472 | '''Mark a file normal and clean.''' |
|
468 | 473 | s = os.lstat(self._join(f)) |
|
469 | 474 | mtime = util.statmtimesec(s) |
|
470 | 475 | self._addpath(f, 'n', s.st_mode, |
|
471 | 476 | s.st_size & _rangemask, mtime & _rangemask) |
|
472 | 477 | if f in self._copymap: |
|
473 | 478 | del self._copymap[f] |
|
474 | 479 | if mtime > self._lastnormaltime: |
|
475 | 480 | # Remember the most recent modification timeslot for status(), |
|
476 | 481 | # to make sure we won't miss future size-preserving file content |
|
477 | 482 | # modifications that happen within the same timeslot. |
|
478 | 483 | self._lastnormaltime = mtime |
|
479 | 484 | |
|
480 | 485 | def normallookup(self, f): |
|
481 | 486 | '''Mark a file normal, but possibly dirty.''' |
|
482 | 487 | if self._pl[1] != nullid and f in self._map: |
|
483 | 488 | # if there is a merge going on and the file was either |
|
484 | 489 | # in state 'm' (-1) or coming from other parent (-2) before |
|
485 | 490 | # being removed, restore that state. |
|
486 | 491 | entry = self._map[f] |
|
487 | 492 | if entry[0] == 'r' and entry[2] in (-1, -2): |
|
488 | 493 | source = self._copymap.get(f) |
|
489 | 494 | if entry[2] == -1: |
|
490 | 495 | self.merge(f) |
|
491 | 496 | elif entry[2] == -2: |
|
492 | 497 | self.otherparent(f) |
|
493 | 498 | if source: |
|
494 | 499 | self.copy(source, f) |
|
495 | 500 | return |
|
496 | 501 | if entry[0] == 'm' or entry[0] == 'n' and entry[2] == -2: |
|
497 | 502 | return |
|
498 | 503 | self._addpath(f, 'n', 0, -1, -1) |
|
499 | 504 | if f in self._copymap: |
|
500 | 505 | del self._copymap[f] |
|
501 | 506 | |
|
502 | 507 | def otherparent(self, f): |
|
503 | 508 | '''Mark as coming from the other parent, always dirty.''' |
|
504 | 509 | if self._pl[1] == nullid: |
|
505 | 510 | raise error.Abort(_("setting %r to other parent " |
|
506 | 511 | "only allowed in merges") % f) |
|
507 | 512 | if f in self and self[f] == 'n': |
|
508 | 513 | # merge-like |
|
509 | 514 | self._addpath(f, 'm', 0, -2, -1) |
|
510 | 515 | else: |
|
511 | 516 | # add-like |
|
512 | 517 | self._addpath(f, 'n', 0, -2, -1) |
|
513 | 518 | |
|
514 | 519 | if f in self._copymap: |
|
515 | 520 | del self._copymap[f] |
|
516 | 521 | |
|
517 | 522 | def add(self, f): |
|
518 | 523 | '''Mark a file added.''' |
|
519 | 524 | self._addpath(f, 'a', 0, -1, -1) |
|
520 | 525 | if f in self._copymap: |
|
521 | 526 | del self._copymap[f] |
|
522 | 527 | |
|
523 | 528 | def remove(self, f): |
|
524 | 529 | '''Mark a file removed.''' |
|
525 | 530 | self._dirty = True |
|
526 | 531 | self._droppath(f) |
|
527 | 532 | size = 0 |
|
528 | 533 | if self._pl[1] != nullid and f in self._map: |
|
529 | 534 | # backup the previous state |
|
530 | 535 | entry = self._map[f] |
|
531 | 536 | if entry[0] == 'm': # merge |
|
532 | 537 | size = -1 |
|
533 | 538 | elif entry[0] == 'n' and entry[2] == -2: # other parent |
|
534 | 539 | size = -2 |
|
535 | 540 | self._map[f] = dirstatetuple('r', 0, size, 0) |
|
536 | 541 | if size == 0 and f in self._copymap: |
|
537 | 542 | del self._copymap[f] |
|
538 | 543 | |
|
539 | 544 | def merge(self, f): |
|
540 | 545 | '''Mark a file merged.''' |
|
541 | 546 | if self._pl[1] == nullid: |
|
542 | 547 | return self.normallookup(f) |
|
543 | 548 | return self.otherparent(f) |
|
544 | 549 | |
|
545 | 550 | def drop(self, f): |
|
546 | 551 | '''Drop a file from the dirstate''' |
|
547 | 552 | if f in self._map: |
|
548 | 553 | self._dirty = True |
|
549 | 554 | self._droppath(f) |
|
550 | 555 | del self._map[f] |
|
551 | 556 | |
|
552 | 557 | def _discoverpath(self, path, normed, ignoremissing, exists, storemap): |
|
553 | 558 | if exists is None: |
|
554 | 559 | exists = os.path.lexists(os.path.join(self._root, path)) |
|
555 | 560 | if not exists: |
|
556 | 561 | # Maybe a path component exists |
|
557 | 562 | if not ignoremissing and '/' in path: |
|
558 | 563 | d, f = path.rsplit('/', 1) |
|
559 | 564 | d = self._normalize(d, False, ignoremissing, None) |
|
560 | 565 | folded = d + "/" + f |
|
561 | 566 | else: |
|
562 | 567 | # No path components, preserve original case |
|
563 | 568 | folded = path |
|
564 | 569 | else: |
|
565 | 570 | # recursively normalize leading directory components |
|
566 | 571 | # against dirstate |
|
567 | 572 | if '/' in normed: |
|
568 | 573 | d, f = normed.rsplit('/', 1) |
|
569 | 574 | d = self._normalize(d, False, ignoremissing, True) |
|
570 | 575 | r = self._root + "/" + d |
|
571 | 576 | folded = d + "/" + util.fspath(f, r) |
|
572 | 577 | else: |
|
573 | 578 | folded = util.fspath(normed, self._root) |
|
574 | 579 | storemap[normed] = folded |
|
575 | 580 | |
|
576 | 581 | return folded |
|
577 | 582 | |
|
578 | 583 | def _normalizefile(self, path, isknown, ignoremissing=False, exists=None): |
|
579 | 584 | normed = util.normcase(path) |
|
580 | 585 | folded = self._filefoldmap.get(normed, None) |
|
581 | 586 | if folded is None: |
|
582 | 587 | if isknown: |
|
583 | 588 | folded = path |
|
584 | 589 | else: |
|
585 | 590 | folded = self._discoverpath(path, normed, ignoremissing, exists, |
|
586 | 591 | self._filefoldmap) |
|
587 | 592 | return folded |
|
588 | 593 | |
|
589 | 594 | def _normalize(self, path, isknown, ignoremissing=False, exists=None): |
|
590 | 595 | normed = util.normcase(path) |
|
591 | 596 | folded = self._filefoldmap.get(normed, None) |
|
592 | 597 | if folded is None: |
|
593 | 598 | folded = self._dirfoldmap.get(normed, None) |
|
594 | 599 | if folded is None: |
|
595 | 600 | if isknown: |
|
596 | 601 | folded = path |
|
597 | 602 | else: |
|
598 | 603 | # store discovered result in dirfoldmap so that future |
|
599 | 604 | # normalizefile calls don't start matching directories |
|
600 | 605 | folded = self._discoverpath(path, normed, ignoremissing, exists, |
|
601 | 606 | self._dirfoldmap) |
|
602 | 607 | return folded |
|
603 | 608 | |
|
604 | 609 | def normalize(self, path, isknown=False, ignoremissing=False): |
|
605 | 610 | ''' |
|
606 | 611 | normalize the case of a pathname when on a casefolding filesystem |
|
607 | 612 | |
|
608 | 613 | isknown specifies whether the filename came from walking the |
|
609 | 614 | disk, to avoid extra filesystem access. |
|
610 | 615 | |
|
611 | 616 | If ignoremissing is True, missing path are returned |
|
612 | 617 | unchanged. Otherwise, we try harder to normalize possibly |
|
613 | 618 | existing path components. |
|
614 | 619 | |
|
615 | 620 | The normalized case is determined based on the following precedence: |
|
616 | 621 | |
|
617 | 622 | - version of name already stored in the dirstate |
|
618 | 623 | - version of name stored on disk |
|
619 | 624 | - version provided via command arguments |
|
620 | 625 | ''' |
|
621 | 626 | |
|
622 | 627 | if self._checkcase: |
|
623 | 628 | return self._normalize(path, isknown, ignoremissing) |
|
624 | 629 | return path |
|
625 | 630 | |
|
626 | 631 | def clear(self): |
|
627 | 632 | self._map = {} |
|
628 | 633 | if "_dirs" in self.__dict__: |
|
629 | 634 | delattr(self, "_dirs") |
|
630 | 635 | self._copymap = {} |
|
631 | 636 | self._pl = [nullid, nullid] |
|
632 | 637 | self._lastnormaltime = 0 |
|
633 | 638 | self._dirty = True |
|
634 | 639 | |
|
635 | 640 | def rebuild(self, parent, allfiles, changedfiles=None): |
|
636 | 641 | if changedfiles is None: |
|
637 | 642 | changedfiles = allfiles |
|
638 | 643 | oldmap = self._map |
|
639 | 644 | self.clear() |
|
640 | 645 | for f in allfiles: |
|
641 | 646 | if f not in changedfiles: |
|
642 | 647 | self._map[f] = oldmap[f] |
|
643 | 648 | else: |
|
644 | 649 | if 'x' in allfiles.flags(f): |
|
645 | 650 | self._map[f] = dirstatetuple('n', 0o777, -1, 0) |
|
646 | 651 | else: |
|
647 | 652 | self._map[f] = dirstatetuple('n', 0o666, -1, 0) |
|
648 | 653 | self._pl = (parent, nullid) |
|
649 | 654 | self._dirty = True |
|
650 | 655 | |
|
651 | 656 | def write(self, tr=False): |
|
652 | 657 | if not self._dirty: |
|
653 | 658 | return |
|
654 | 659 | |
|
655 | 660 | # enough 'delaywrite' prevents 'pack_dirstate' from dropping |
|
656 | 661 | # timestamp of each entries in dirstate, because of 'now > mtime' |
|
657 | 662 | delaywrite = self._ui.configint('debug', 'dirstate.delaywrite', 0) |
|
658 | 663 | if delaywrite > 0: |
|
659 | 664 | import time # to avoid useless import |
|
660 | 665 | time.sleep(delaywrite) |
|
661 | 666 | |
|
662 | 667 | filename = self._filename |
|
663 | 668 | if tr is False: # not explicitly specified |
|
664 | 669 | if (self._ui.configbool('devel', 'all-warnings') |
|
665 | 670 | or self._ui.configbool('devel', 'check-dirstate-write')): |
|
666 | 671 | self._ui.develwarn('use dirstate.write with ' |
|
667 | 672 | 'repo.currenttransaction()') |
|
668 | 673 | |
|
669 | 674 | if self._opener.lexists(self._pendingfilename): |
|
670 | 675 | # if pending file already exists, in-memory changes |
|
671 | 676 | # should be written into it, because it has priority |
|
672 | 677 | # to '.hg/dirstate' at reading under HG_PENDING mode |
|
673 | 678 | filename = self._pendingfilename |
|
674 | 679 | elif tr: |
|
675 | 680 | # 'dirstate.write()' is not only for writing in-memory |
|
676 | 681 | # changes out, but also for dropping ambiguous timestamp. |
|
677 | 682 | # delayed writing re-raise "ambiguous timestamp issue". |
|
678 | 683 | # See also the wiki page below for detail: |
|
679 | 684 | # https://www.mercurial-scm.org/wiki/DirstateTransactionPlan |
|
680 | 685 | |
|
681 | 686 | # emulate dropping timestamp in 'parsers.pack_dirstate' |
|
682 | 687 | now = _getfsnow(self._opener) |
|
683 | 688 | dmap = self._map |
|
684 | 689 | for f, e in dmap.iteritems(): |
|
685 | 690 | if e[0] == 'n' and e[3] == now: |
|
686 | 691 | dmap[f] = dirstatetuple(e[0], e[1], e[2], -1) |
|
687 | 692 | |
|
688 | 693 | # emulate that all 'dirstate.normal' results are written out |
|
689 | 694 | self._lastnormaltime = 0 |
|
690 | 695 | |
|
691 | 696 | # delay writing in-memory changes out |
|
692 | 697 | tr.addfilegenerator('dirstate', (self._filename,), |
|
693 | 698 | self._writedirstate, location='plain') |
|
694 | 699 | return |
|
695 | 700 | |
|
696 | 701 | st = self._opener(filename, "w", atomictemp=True) |
|
697 | 702 | self._writedirstate(st) |
|
698 | 703 | |
|
699 | 704 | def _writedirstate(self, st): |
|
700 | 705 | # use the modification time of the newly created temporary file as the |
|
701 | 706 | # filesystem's notion of 'now' |
|
702 | 707 | now = util.statmtimesec(util.fstat(st)) & _rangemask |
|
703 | 708 | st.write(parsers.pack_dirstate(self._map, self._copymap, self._pl, now)) |
|
704 | 709 | st.close() |
|
705 | 710 | self._lastnormaltime = 0 |
|
706 | 711 | self._dirty = self._dirtypl = False |
|
707 | 712 | |
|
708 | 713 | def _dirignore(self, f): |
|
709 | 714 | if f == '.': |
|
710 | 715 | return False |
|
711 | 716 | if self._ignore(f): |
|
712 | 717 | return True |
|
713 | 718 | for p in util.finddirs(f): |
|
714 | 719 | if self._ignore(p): |
|
715 | 720 | return True |
|
716 | 721 | return False |
|
717 | 722 | |
|
718 | 723 | def _walkexplicit(self, match, subrepos): |
|
719 | 724 | '''Get stat data about the files explicitly specified by match. |
|
720 | 725 | |
|
721 | 726 | Return a triple (results, dirsfound, dirsnotfound). |
|
722 | 727 | - results is a mapping from filename to stat result. It also contains |
|
723 | 728 | listings mapping subrepos and .hg to None. |
|
724 | 729 | - dirsfound is a list of files found to be directories. |
|
725 | 730 | - dirsnotfound is a list of files that the dirstate thinks are |
|
726 | 731 | directories and that were not found.''' |
|
727 | 732 | |
|
728 | 733 | def badtype(mode): |
|
729 | 734 | kind = _('unknown') |
|
730 | 735 | if stat.S_ISCHR(mode): |
|
731 | 736 | kind = _('character device') |
|
732 | 737 | elif stat.S_ISBLK(mode): |
|
733 | 738 | kind = _('block device') |
|
734 | 739 | elif stat.S_ISFIFO(mode): |
|
735 | 740 | kind = _('fifo') |
|
736 | 741 | elif stat.S_ISSOCK(mode): |
|
737 | 742 | kind = _('socket') |
|
738 | 743 | elif stat.S_ISDIR(mode): |
|
739 | 744 | kind = _('directory') |
|
740 | 745 | return _('unsupported file type (type is %s)') % kind |
|
741 | 746 | |
|
742 | 747 | matchedir = match.explicitdir |
|
743 | 748 | badfn = match.bad |
|
744 | 749 | dmap = self._map |
|
745 | 750 | lstat = os.lstat |
|
746 | 751 | getkind = stat.S_IFMT |
|
747 | 752 | dirkind = stat.S_IFDIR |
|
748 | 753 | regkind = stat.S_IFREG |
|
749 | 754 | lnkkind = stat.S_IFLNK |
|
750 | 755 | join = self._join |
|
751 | 756 | dirsfound = [] |
|
752 | 757 | foundadd = dirsfound.append |
|
753 | 758 | dirsnotfound = [] |
|
754 | 759 | notfoundadd = dirsnotfound.append |
|
755 | 760 | |
|
756 | 761 | if not match.isexact() and self._checkcase: |
|
757 | 762 | normalize = self._normalize |
|
758 | 763 | else: |
|
759 | 764 | normalize = None |
|
760 | 765 | |
|
761 | 766 | files = sorted(match.files()) |
|
762 | 767 | subrepos.sort() |
|
763 | 768 | i, j = 0, 0 |
|
764 | 769 | while i < len(files) and j < len(subrepos): |
|
765 | 770 | subpath = subrepos[j] + "/" |
|
766 | 771 | if files[i] < subpath: |
|
767 | 772 | i += 1 |
|
768 | 773 | continue |
|
769 | 774 | while i < len(files) and files[i].startswith(subpath): |
|
770 | 775 | del files[i] |
|
771 | 776 | j += 1 |
|
772 | 777 | |
|
773 | 778 | if not files or '.' in files: |
|
774 | 779 | files = ['.'] |
|
775 | 780 | results = dict.fromkeys(subrepos) |
|
776 | 781 | results['.hg'] = None |
|
777 | 782 | |
|
778 | 783 | alldirs = None |
|
779 | 784 | for ff in files: |
|
780 | 785 | # constructing the foldmap is expensive, so don't do it for the |
|
781 | 786 | # common case where files is ['.'] |
|
782 | 787 | if normalize and ff != '.': |
|
783 | 788 | nf = normalize(ff, False, True) |
|
784 | 789 | else: |
|
785 | 790 | nf = ff |
|
786 | 791 | if nf in results: |
|
787 | 792 | continue |
|
788 | 793 | |
|
789 | 794 | try: |
|
790 | 795 | st = lstat(join(nf)) |
|
791 | 796 | kind = getkind(st.st_mode) |
|
792 | 797 | if kind == dirkind: |
|
793 | 798 | if nf in dmap: |
|
794 | 799 | # file replaced by dir on disk but still in dirstate |
|
795 | 800 | results[nf] = None |
|
796 | 801 | if matchedir: |
|
797 | 802 | matchedir(nf) |
|
798 | 803 | foundadd((nf, ff)) |
|
799 | 804 | elif kind == regkind or kind == lnkkind: |
|
800 | 805 | results[nf] = st |
|
801 | 806 | else: |
|
802 | 807 | badfn(ff, badtype(kind)) |
|
803 | 808 | if nf in dmap: |
|
804 | 809 | results[nf] = None |
|
805 | 810 | except OSError as inst: # nf not found on disk - it is dirstate only |
|
806 | 811 | if nf in dmap: # does it exactly match a missing file? |
|
807 | 812 | results[nf] = None |
|
808 | 813 | else: # does it match a missing directory? |
|
809 | 814 | if alldirs is None: |
|
810 | 815 | alldirs = util.dirs(dmap) |
|
811 | 816 | if nf in alldirs: |
|
812 | 817 | if matchedir: |
|
813 | 818 | matchedir(nf) |
|
814 | 819 | notfoundadd(nf) |
|
815 | 820 | else: |
|
816 | 821 | badfn(ff, inst.strerror) |
|
817 | 822 | |
|
818 | 823 | # Case insensitive filesystems cannot rely on lstat() failing to detect |
|
819 | 824 | # a case-only rename. Prune the stat object for any file that does not |
|
820 | 825 | # match the case in the filesystem, if there are multiple files that |
|
821 | 826 | # normalize to the same path. |
|
822 | 827 | if match.isexact() and self._checkcase: |
|
823 | 828 | normed = {} |
|
824 | 829 | |
|
825 | 830 | for f, st in results.iteritems(): |
|
826 | 831 | if st is None: |
|
827 | 832 | continue |
|
828 | 833 | |
|
829 | 834 | nc = util.normcase(f) |
|
830 | 835 | paths = normed.get(nc) |
|
831 | 836 | |
|
832 | 837 | if paths is None: |
|
833 | 838 | paths = set() |
|
834 | 839 | normed[nc] = paths |
|
835 | 840 | |
|
836 | 841 | paths.add(f) |
|
837 | 842 | |
|
838 | 843 | for norm, paths in normed.iteritems(): |
|
839 | 844 | if len(paths) > 1: |
|
840 | 845 | for path in paths: |
|
841 | 846 | folded = self._discoverpath(path, norm, True, None, |
|
842 | 847 | self._dirfoldmap) |
|
843 | 848 | if path != folded: |
|
844 | 849 | results[path] = None |
|
845 | 850 | |
|
846 | 851 | return results, dirsfound, dirsnotfound |
|
847 | 852 | |
|
848 | 853 | def walk(self, match, subrepos, unknown, ignored, full=True): |
|
849 | 854 | ''' |
|
850 | 855 | Walk recursively through the directory tree, finding all files |
|
851 | 856 | matched by match. |
|
852 | 857 | |
|
853 | 858 | If full is False, maybe skip some known-clean files. |
|
854 | 859 | |
|
855 | 860 | Return a dict mapping filename to stat-like object (either |
|
856 | 861 | mercurial.osutil.stat instance or return value of os.stat()). |
|
857 | 862 | |
|
858 | 863 | ''' |
|
859 | 864 | # full is a flag that extensions that hook into walk can use -- this |
|
860 | 865 | # implementation doesn't use it at all. This satisfies the contract |
|
861 | 866 | # because we only guarantee a "maybe". |
|
862 | 867 | |
|
863 | 868 | if ignored: |
|
864 | 869 | ignore = util.never |
|
865 | 870 | dirignore = util.never |
|
866 | 871 | elif unknown: |
|
867 | 872 | ignore = self._ignore |
|
868 | 873 | dirignore = self._dirignore |
|
869 | 874 | else: |
|
870 | 875 | # if not unknown and not ignored, drop dir recursion and step 2 |
|
871 | 876 | ignore = util.always |
|
872 | 877 | dirignore = util.always |
|
873 | 878 | |
|
874 | 879 | matchfn = match.matchfn |
|
875 | 880 | matchalways = match.always() |
|
876 | 881 | matchtdir = match.traversedir |
|
877 | 882 | dmap = self._map |
|
878 | 883 | listdir = osutil.listdir |
|
879 | 884 | lstat = os.lstat |
|
880 | 885 | dirkind = stat.S_IFDIR |
|
881 | 886 | regkind = stat.S_IFREG |
|
882 | 887 | lnkkind = stat.S_IFLNK |
|
883 | 888 | join = self._join |
|
884 | 889 | |
|
885 | 890 | exact = skipstep3 = False |
|
886 | 891 | if match.isexact(): # match.exact |
|
887 | 892 | exact = True |
|
888 | 893 | dirignore = util.always # skip step 2 |
|
889 | 894 | elif match.prefix(): # match.match, no patterns |
|
890 | 895 | skipstep3 = True |
|
891 | 896 | |
|
892 | 897 | if not exact and self._checkcase: |
|
893 | 898 | normalize = self._normalize |
|
894 | 899 | normalizefile = self._normalizefile |
|
895 | 900 | skipstep3 = False |
|
896 | 901 | else: |
|
897 | 902 | normalize = self._normalize |
|
898 | 903 | normalizefile = None |
|
899 | 904 | |
|
900 | 905 | # step 1: find all explicit files |
|
901 | 906 | results, work, dirsnotfound = self._walkexplicit(match, subrepos) |
|
902 | 907 | |
|
903 | 908 | skipstep3 = skipstep3 and not (work or dirsnotfound) |
|
904 | 909 | work = [d for d in work if not dirignore(d[0])] |
|
905 | 910 | |
|
906 | 911 | # step 2: visit subdirectories |
|
907 | 912 | def traverse(work, alreadynormed): |
|
908 | 913 | wadd = work.append |
|
909 | 914 | while work: |
|
910 | 915 | nd = work.pop() |
|
911 | 916 | skip = None |
|
912 | 917 | if nd == '.': |
|
913 | 918 | nd = '' |
|
914 | 919 | else: |
|
915 | 920 | skip = '.hg' |
|
916 | 921 | try: |
|
917 | 922 | entries = listdir(join(nd), stat=True, skip=skip) |
|
918 | 923 | except OSError as inst: |
|
919 | 924 | if inst.errno in (errno.EACCES, errno.ENOENT): |
|
920 | 925 | match.bad(self.pathto(nd), inst.strerror) |
|
921 | 926 | continue |
|
922 | 927 | raise |
|
923 | 928 | for f, kind, st in entries: |
|
924 | 929 | if normalizefile: |
|
925 | 930 | # even though f might be a directory, we're only |
|
926 | 931 | # interested in comparing it to files currently in the |
|
927 | 932 | # dmap -- therefore normalizefile is enough |
|
928 | 933 | nf = normalizefile(nd and (nd + "/" + f) or f, True, |
|
929 | 934 | True) |
|
930 | 935 | else: |
|
931 | 936 | nf = nd and (nd + "/" + f) or f |
|
932 | 937 | if nf not in results: |
|
933 | 938 | if kind == dirkind: |
|
934 | 939 | if not ignore(nf): |
|
935 | 940 | if matchtdir: |
|
936 | 941 | matchtdir(nf) |
|
937 | 942 | wadd(nf) |
|
938 | 943 | if nf in dmap and (matchalways or matchfn(nf)): |
|
939 | 944 | results[nf] = None |
|
940 | 945 | elif kind == regkind or kind == lnkkind: |
|
941 | 946 | if nf in dmap: |
|
942 | 947 | if matchalways or matchfn(nf): |
|
943 | 948 | results[nf] = st |
|
944 | 949 | elif ((matchalways or matchfn(nf)) |
|
945 | 950 | and not ignore(nf)): |
|
946 | 951 | # unknown file -- normalize if necessary |
|
947 | 952 | if not alreadynormed: |
|
948 | 953 | nf = normalize(nf, False, True) |
|
949 | 954 | results[nf] = st |
|
950 | 955 | elif nf in dmap and (matchalways or matchfn(nf)): |
|
951 | 956 | results[nf] = None |
|
952 | 957 | |
|
953 | 958 | for nd, d in work: |
|
954 | 959 | # alreadynormed means that processwork doesn't have to do any |
|
955 | 960 | # expensive directory normalization |
|
956 | 961 | alreadynormed = not normalize or nd == d |
|
957 | 962 | traverse([d], alreadynormed) |
|
958 | 963 | |
|
959 | 964 | for s in subrepos: |
|
960 | 965 | del results[s] |
|
961 | 966 | del results['.hg'] |
|
962 | 967 | |
|
963 | 968 | # step 3: visit remaining files from dmap |
|
964 | 969 | if not skipstep3 and not exact: |
|
965 | 970 | # If a dmap file is not in results yet, it was either |
|
966 | 971 | # a) not matching matchfn b) ignored, c) missing, or d) under a |
|
967 | 972 | # symlink directory. |
|
968 | 973 | if not results and matchalways: |
|
969 | 974 | visit = dmap.keys() |
|
970 | 975 | else: |
|
971 | 976 | visit = [f for f in dmap if f not in results and matchfn(f)] |
|
972 | 977 | visit.sort() |
|
973 | 978 | |
|
974 | 979 | if unknown: |
|
975 | 980 | # unknown == True means we walked all dirs under the roots |
|
976 | 981 | # that wasn't ignored, and everything that matched was stat'ed |
|
977 | 982 | # and is already in results. |
|
978 | 983 | # The rest must thus be ignored or under a symlink. |
|
979 | 984 | audit_path = pathutil.pathauditor(self._root) |
|
980 | 985 | |
|
981 | 986 | for nf in iter(visit): |
|
982 | 987 | # If a stat for the same file was already added with a |
|
983 | 988 | # different case, don't add one for this, since that would |
|
984 | 989 | # make it appear as if the file exists under both names |
|
985 | 990 | # on disk. |
|
986 | 991 | if (normalizefile and |
|
987 | 992 | normalizefile(nf, True, True) in results): |
|
988 | 993 | results[nf] = None |
|
989 | 994 | # Report ignored items in the dmap as long as they are not |
|
990 | 995 | # under a symlink directory. |
|
991 | 996 | elif audit_path.check(nf): |
|
992 | 997 | try: |
|
993 | 998 | results[nf] = lstat(join(nf)) |
|
994 | 999 | # file was just ignored, no links, and exists |
|
995 | 1000 | except OSError: |
|
996 | 1001 | # file doesn't exist |
|
997 | 1002 | results[nf] = None |
|
998 | 1003 | else: |
|
999 | 1004 | # It's either missing or under a symlink directory |
|
1000 | 1005 | # which we in this case report as missing |
|
1001 | 1006 | results[nf] = None |
|
1002 | 1007 | else: |
|
1003 | 1008 | # We may not have walked the full directory tree above, |
|
1004 | 1009 | # so stat and check everything we missed. |
|
1005 | 1010 | nf = iter(visit).next |
|
1006 | 1011 | pos = 0 |
|
1007 | 1012 | while pos < len(visit): |
|
1008 | 1013 | # visit in mid-sized batches so that we don't |
|
1009 | 1014 | # block signals indefinitely |
|
1010 | 1015 | xr = xrange(pos, min(len(visit), pos + 1000)) |
|
1011 | 1016 | for st in util.statfiles([join(visit[n]) for n in xr]): |
|
1012 | 1017 | results[nf()] = st |
|
1013 | 1018 | pos += 1000 |
|
1014 | 1019 | return results |
|
1015 | 1020 | |
|
1016 | 1021 | def status(self, match, subrepos, ignored, clean, unknown): |
|
1017 | 1022 | '''Determine the status of the working copy relative to the |
|
1018 | 1023 | dirstate and return a pair of (unsure, status), where status is of type |
|
1019 | 1024 | scmutil.status and: |
|
1020 | 1025 | |
|
1021 | 1026 | unsure: |
|
1022 | 1027 | files that might have been modified since the dirstate was |
|
1023 | 1028 | written, but need to be read to be sure (size is the same |
|
1024 | 1029 | but mtime differs) |
|
1025 | 1030 | status.modified: |
|
1026 | 1031 | files that have definitely been modified since the dirstate |
|
1027 | 1032 | was written (different size or mode) |
|
1028 | 1033 | status.clean: |
|
1029 | 1034 | files that have definitely not been modified since the |
|
1030 | 1035 | dirstate was written |
|
1031 | 1036 | ''' |
|
1032 | 1037 | listignored, listclean, listunknown = ignored, clean, unknown |
|
1033 | 1038 | lookup, modified, added, unknown, ignored = [], [], [], [], [] |
|
1034 | 1039 | removed, deleted, clean = [], [], [] |
|
1035 | 1040 | |
|
1036 | 1041 | dmap = self._map |
|
1037 | 1042 | ladd = lookup.append # aka "unsure" |
|
1038 | 1043 | madd = modified.append |
|
1039 | 1044 | aadd = added.append |
|
1040 | 1045 | uadd = unknown.append |
|
1041 | 1046 | iadd = ignored.append |
|
1042 | 1047 | radd = removed.append |
|
1043 | 1048 | dadd = deleted.append |
|
1044 | 1049 | cadd = clean.append |
|
1045 | 1050 | mexact = match.exact |
|
1046 | 1051 | dirignore = self._dirignore |
|
1047 | 1052 | checkexec = self._checkexec |
|
1048 | 1053 | copymap = self._copymap |
|
1049 | 1054 | lastnormaltime = self._lastnormaltime |
|
1050 | 1055 | |
|
1051 | 1056 | # We need to do full walks when either |
|
1052 | 1057 | # - we're listing all clean files, or |
|
1053 | 1058 | # - match.traversedir does something, because match.traversedir should |
|
1054 | 1059 | # be called for every dir in the working dir |
|
1055 | 1060 | full = listclean or match.traversedir is not None |
|
1056 | 1061 | for fn, st in self.walk(match, subrepos, listunknown, listignored, |
|
1057 | 1062 | full=full).iteritems(): |
|
1058 | 1063 | if fn not in dmap: |
|
1059 | 1064 | if (listignored or mexact(fn)) and dirignore(fn): |
|
1060 | 1065 | if listignored: |
|
1061 | 1066 | iadd(fn) |
|
1062 | 1067 | else: |
|
1063 | 1068 | uadd(fn) |
|
1064 | 1069 | continue |
|
1065 | 1070 | |
|
1066 | 1071 | # This is equivalent to 'state, mode, size, time = dmap[fn]' but not |
|
1067 | 1072 | # written like that for performance reasons. dmap[fn] is not a |
|
1068 | 1073 | # Python tuple in compiled builds. The CPython UNPACK_SEQUENCE |
|
1069 | 1074 | # opcode has fast paths when the value to be unpacked is a tuple or |
|
1070 | 1075 | # a list, but falls back to creating a full-fledged iterator in |
|
1071 | 1076 | # general. That is much slower than simply accessing and storing the |
|
1072 | 1077 | # tuple members one by one. |
|
1073 | 1078 | t = dmap[fn] |
|
1074 | 1079 | state = t[0] |
|
1075 | 1080 | mode = t[1] |
|
1076 | 1081 | size = t[2] |
|
1077 | 1082 | time = t[3] |
|
1078 | 1083 | |
|
1079 | 1084 | if not st and state in "nma": |
|
1080 | 1085 | dadd(fn) |
|
1081 | 1086 | elif state == 'n': |
|
1082 | 1087 | mtime = util.statmtimesec(st) |
|
1083 | 1088 | if (size >= 0 and |
|
1084 | 1089 | ((size != st.st_size and size != st.st_size & _rangemask) |
|
1085 | 1090 | or ((mode ^ st.st_mode) & 0o100 and checkexec)) |
|
1086 | 1091 | or size == -2 # other parent |
|
1087 | 1092 | or fn in copymap): |
|
1088 | 1093 | madd(fn) |
|
1089 | 1094 | elif time != mtime and time != mtime & _rangemask: |
|
1090 | 1095 | ladd(fn) |
|
1091 | 1096 | elif mtime == lastnormaltime: |
|
1092 | 1097 | # fn may have just been marked as normal and it may have |
|
1093 | 1098 | # changed in the same second without changing its size. |
|
1094 | 1099 | # This can happen if we quickly do multiple commits. |
|
1095 | 1100 | # Force lookup, so we don't miss such a racy file change. |
|
1096 | 1101 | ladd(fn) |
|
1097 | 1102 | elif listclean: |
|
1098 | 1103 | cadd(fn) |
|
1099 | 1104 | elif state == 'm': |
|
1100 | 1105 | madd(fn) |
|
1101 | 1106 | elif state == 'a': |
|
1102 | 1107 | aadd(fn) |
|
1103 | 1108 | elif state == 'r': |
|
1104 | 1109 | radd(fn) |
|
1105 | 1110 | |
|
1106 | 1111 | return (lookup, scmutil.status(modified, added, removed, deleted, |
|
1107 | 1112 | unknown, ignored, clean)) |
|
1108 | 1113 | |
|
1109 | 1114 | def matches(self, match): |
|
1110 | 1115 | ''' |
|
1111 | 1116 | return files in the dirstate (in whatever state) filtered by match |
|
1112 | 1117 | ''' |
|
1113 | 1118 | dmap = self._map |
|
1114 | 1119 | if match.always(): |
|
1115 | 1120 | return dmap.keys() |
|
1116 | 1121 | files = match.files() |
|
1117 | 1122 | if match.isexact(): |
|
1118 | 1123 | # fast path -- filter the other way around, since typically files is |
|
1119 | 1124 | # much smaller than dmap |
|
1120 | 1125 | return [f for f in files if f in dmap] |
|
1121 | 1126 | if match.prefix() and all(fn in dmap for fn in files): |
|
1122 | 1127 | # fast path -- all the values are known to be files, so just return |
|
1123 | 1128 | # that |
|
1124 | 1129 | return list(files) |
|
1125 | 1130 | return [f for f in dmap if match(f)] |
|
1126 | 1131 | |
|
1127 | 1132 | def _actualfilename(self, tr): |
|
1128 | 1133 | if tr: |
|
1129 | 1134 | return self._pendingfilename |
|
1130 | 1135 | else: |
|
1131 | 1136 | return self._filename |
|
1132 | 1137 | |
|
1133 | 1138 | def _savebackup(self, tr, suffix): |
|
1134 | 1139 | '''Save current dirstate into backup file with suffix''' |
|
1135 | 1140 | filename = self._actualfilename(tr) |
|
1136 | 1141 | |
|
1137 | 1142 | # use '_writedirstate' instead of 'write' to write changes certainly, |
|
1138 | 1143 | # because the latter omits writing out if transaction is running. |
|
1139 | 1144 | # output file will be used to create backup of dirstate at this point. |
|
1140 | 1145 | self._writedirstate(self._opener(filename, "w", atomictemp=True)) |
|
1141 | 1146 | |
|
1142 | 1147 | if tr: |
|
1143 | 1148 | # ensure that subsequent tr.writepending returns True for |
|
1144 | 1149 | # changes written out above, even if dirstate is never |
|
1145 | 1150 | # changed after this |
|
1146 | 1151 | tr.addfilegenerator('dirstate', (self._filename,), |
|
1147 | 1152 | self._writedirstate, location='plain') |
|
1148 | 1153 | |
|
1149 | 1154 | # ensure that pending file written above is unlinked at |
|
1150 | 1155 | # failure, even if tr.writepending isn't invoked until the |
|
1151 | 1156 | # end of this transaction |
|
1152 | 1157 | tr.registertmp(filename, location='plain') |
|
1153 | 1158 | |
|
1154 | 1159 | self._opener.write(filename + suffix, self._opener.tryread(filename)) |
|
1155 | 1160 | |
|
1156 | 1161 | def _restorebackup(self, tr, suffix): |
|
1157 | 1162 | '''Restore dirstate by backup file with suffix''' |
|
1158 | 1163 | # this "invalidate()" prevents "wlock.release()" from writing |
|
1159 | 1164 | # changes of dirstate out after restoring from backup file |
|
1160 | 1165 | self.invalidate() |
|
1161 | 1166 | filename = self._actualfilename(tr) |
|
1162 | 1167 | self._opener.rename(filename + suffix, filename) |
|
1163 | 1168 | |
|
1164 | 1169 | def _clearbackup(self, tr, suffix): |
|
1165 | 1170 | '''Clear backup file with suffix''' |
|
1166 | 1171 | filename = self._actualfilename(tr) |
|
1167 | 1172 | self._opener.unlink(filename + suffix) |
@@ -1,630 +1,632 b'' | |||
|
1 | 1 | # posix.py - Posix utility function implementations for Mercurial |
|
2 | 2 | # |
|
3 | 3 | # Copyright 2005-2009 Matt Mackall <mpm@selenic.com> and others |
|
4 | 4 | # |
|
5 | 5 | # This software may be used and distributed according to the terms of the |
|
6 | 6 | # GNU General Public License version 2 or any later version. |
|
7 | 7 | |
|
8 | 8 | from __future__ import absolute_import |
|
9 | 9 | |
|
10 | 10 | import errno |
|
11 | 11 | import fcntl |
|
12 | 12 | import getpass |
|
13 | 13 | import grp |
|
14 | 14 | import os |
|
15 | 15 | import pwd |
|
16 | 16 | import re |
|
17 | 17 | import select |
|
18 | 18 | import socket |
|
19 | 19 | import stat |
|
20 | 20 | import sys |
|
21 | 21 | import tempfile |
|
22 | 22 | import unicodedata |
|
23 | 23 | |
|
24 | 24 | from .i18n import _ |
|
25 | 25 | from . import ( |
|
26 | 26 | encoding, |
|
27 | 27 | ) |
|
28 | 28 | |
|
29 | 29 | posixfile = open |
|
30 | 30 | normpath = os.path.normpath |
|
31 | 31 | samestat = os.path.samestat |
|
32 | 32 | oslink = os.link |
|
33 | 33 | unlink = os.unlink |
|
34 | 34 | rename = os.rename |
|
35 | 35 | removedirs = os.removedirs |
|
36 | 36 | expandglobs = False |
|
37 | 37 | |
|
38 | 38 | umask = os.umask(0) |
|
39 | 39 | os.umask(umask) |
|
40 | 40 | |
|
41 | 41 | def split(p): |
|
42 | 42 | '''Same as posixpath.split, but faster |
|
43 | 43 | |
|
44 | 44 | >>> import posixpath |
|
45 | 45 | >>> for f in ['/absolute/path/to/file', |
|
46 | 46 | ... 'relative/path/to/file', |
|
47 | 47 | ... 'file_alone', |
|
48 | 48 | ... 'path/to/directory/', |
|
49 | 49 | ... '/multiple/path//separators', |
|
50 | 50 | ... '/file_at_root', |
|
51 | 51 | ... '///multiple_leading_separators_at_root', |
|
52 | 52 | ... '']: |
|
53 | 53 | ... assert split(f) == posixpath.split(f), f |
|
54 | 54 | ''' |
|
55 | 55 | ht = p.rsplit('/', 1) |
|
56 | 56 | if len(ht) == 1: |
|
57 | 57 | return '', p |
|
58 | 58 | nh = ht[0].rstrip('/') |
|
59 | 59 | if nh: |
|
60 | 60 | return nh, ht[1] |
|
61 | 61 | return ht[0] + '/', ht[1] |
|
62 | 62 | |
|
63 | 63 | def openhardlinks(): |
|
64 | 64 | '''return true if it is safe to hold open file handles to hardlinks''' |
|
65 | 65 | return True |
|
66 | 66 | |
|
67 | 67 | def nlinks(name): |
|
68 | 68 | '''return number of hardlinks for the given file''' |
|
69 | 69 | return os.lstat(name).st_nlink |
|
70 | 70 | |
|
71 | 71 | def parsepatchoutput(output_line): |
|
72 | 72 | """parses the output produced by patch and returns the filename""" |
|
73 | 73 | pf = output_line[14:] |
|
74 | 74 | if os.sys.platform == 'OpenVMS': |
|
75 | 75 | if pf[0] == '`': |
|
76 | 76 | pf = pf[1:-1] # Remove the quotes |
|
77 | 77 | else: |
|
78 | 78 | if pf.startswith("'") and pf.endswith("'") and " " in pf: |
|
79 | 79 | pf = pf[1:-1] # Remove the quotes |
|
80 | 80 | return pf |
|
81 | 81 | |
|
82 | 82 | def sshargs(sshcmd, host, user, port): |
|
83 | 83 | '''Build argument list for ssh''' |
|
84 | 84 | args = user and ("%s@%s" % (user, host)) or host |
|
85 | 85 | return port and ("%s -p %s" % (args, port)) or args |
|
86 | 86 | |
|
87 | 87 | def isexec(f): |
|
88 | 88 | """check whether a file is executable""" |
|
89 | 89 | return (os.lstat(f).st_mode & 0o100 != 0) |
|
90 | 90 | |
|
91 | 91 | def setflags(f, l, x): |
|
92 | 92 | s = os.lstat(f).st_mode |
|
93 | 93 | if l: |
|
94 | 94 | if not stat.S_ISLNK(s): |
|
95 | 95 | # switch file to link |
|
96 | 96 | fp = open(f) |
|
97 | 97 | data = fp.read() |
|
98 | 98 | fp.close() |
|
99 | 99 | os.unlink(f) |
|
100 | 100 | try: |
|
101 | 101 | os.symlink(data, f) |
|
102 | 102 | except OSError: |
|
103 | 103 | # failed to make a link, rewrite file |
|
104 | 104 | fp = open(f, "w") |
|
105 | 105 | fp.write(data) |
|
106 | 106 | fp.close() |
|
107 | 107 | # no chmod needed at this point |
|
108 | 108 | return |
|
109 | 109 | if stat.S_ISLNK(s): |
|
110 | 110 | # switch link to file |
|
111 | 111 | data = os.readlink(f) |
|
112 | 112 | os.unlink(f) |
|
113 | 113 | fp = open(f, "w") |
|
114 | 114 | fp.write(data) |
|
115 | 115 | fp.close() |
|
116 | 116 | s = 0o666 & ~umask # avoid restatting for chmod |
|
117 | 117 | |
|
118 | 118 | sx = s & 0o100 |
|
119 | 119 | if x and not sx: |
|
120 | 120 | # Turn on +x for every +r bit when making a file executable |
|
121 | 121 | # and obey umask. |
|
122 | 122 | os.chmod(f, s | (s & 0o444) >> 2 & ~umask) |
|
123 | 123 | elif not x and sx: |
|
124 | 124 | # Turn off all +x bits |
|
125 | 125 | os.chmod(f, s & 0o666) |
|
126 | 126 | |
|
127 | 127 | def copymode(src, dst, mode=None): |
|
128 | 128 | '''Copy the file mode from the file at path src to dst. |
|
129 | 129 | If src doesn't exist, we're using mode instead. If mode is None, we're |
|
130 | 130 | using umask.''' |
|
131 | 131 | try: |
|
132 | 132 | st_mode = os.lstat(src).st_mode & 0o777 |
|
133 | 133 | except OSError as inst: |
|
134 | 134 | if inst.errno != errno.ENOENT: |
|
135 | 135 | raise |
|
136 | 136 | st_mode = mode |
|
137 | 137 | if st_mode is None: |
|
138 | 138 | st_mode = ~umask |
|
139 | 139 | st_mode &= 0o666 |
|
140 | 140 | os.chmod(dst, st_mode) |
|
141 | 141 | |
|
142 | 142 | def checkexec(path): |
|
143 | 143 | """ |
|
144 | 144 | Check whether the given path is on a filesystem with UNIX-like exec flags |
|
145 | 145 | |
|
146 | 146 | Requires a directory (like /foo/.hg) |
|
147 | 147 | """ |
|
148 | 148 | |
|
149 | 149 | # VFAT on some Linux versions can flip mode but it doesn't persist |
|
150 | 150 | # a FS remount. Frequently we can detect it if files are created |
|
151 | 151 | # with exec bit on. |
|
152 | 152 | |
|
153 | 153 | try: |
|
154 | 154 | EXECFLAGS = stat.S_IXUSR | stat.S_IXGRP | stat.S_IXOTH |
|
155 | 155 | fh, fn = tempfile.mkstemp(dir=path, prefix='hg-checkexec-') |
|
156 | 156 | try: |
|
157 | 157 | os.close(fh) |
|
158 | 158 | m = os.stat(fn).st_mode & 0o777 |
|
159 | 159 | new_file_has_exec = m & EXECFLAGS |
|
160 | 160 | os.chmod(fn, m ^ EXECFLAGS) |
|
161 | 161 | exec_flags_cannot_flip = ((os.stat(fn).st_mode & 0o777) == m) |
|
162 | 162 | finally: |
|
163 | 163 | os.unlink(fn) |
|
164 | 164 | except (IOError, OSError): |
|
165 | 165 | # we don't care, the user probably won't be able to commit anyway |
|
166 | 166 | return False |
|
167 | 167 | return not (new_file_has_exec or exec_flags_cannot_flip) |
|
168 | 168 | |
|
169 | 169 | def checklink(path): |
|
170 | 170 | """check whether the given path is on a symlink-capable filesystem""" |
|
171 | 171 | # mktemp is not racy because symlink creation will fail if the |
|
172 | 172 | # file already exists |
|
173 | 173 | while True: |
|
174 | 174 | name = tempfile.mktemp(dir=path, prefix='hg-checklink-') |
|
175 | 175 | try: |
|
176 | 176 | fd = tempfile.NamedTemporaryFile(dir=path, prefix='hg-checklink-') |
|
177 | 177 | try: |
|
178 | 178 | os.symlink(os.path.basename(fd.name), name) |
|
179 | 179 | os.unlink(name) |
|
180 | 180 | return True |
|
181 | 181 | except OSError as inst: |
|
182 | 182 | # link creation might race, try again |
|
183 | 183 | if inst[0] == errno.EEXIST: |
|
184 | 184 | continue |
|
185 | raise | |
|
186 | finally: | |
|
187 | fd.close() | |
|
188 | except AttributeError: | |
|
189 | return False | |
|
190 | except OSError as inst: | |
|
185 | 191 |
|
|
186 | 192 |
|
|
187 | 193 |
|
|
188 | 194 |
|
|
189 | finally: | |
|
190 | fd.close() | |
|
191 | except AttributeError: | |
|
192 | return False | |
|
193 | 195 | |
|
194 | 196 | def checkosfilename(path): |
|
195 | 197 | '''Check that the base-relative path is a valid filename on this platform. |
|
196 | 198 | Returns None if the path is ok, or a UI string describing the problem.''' |
|
197 | 199 | pass # on posix platforms, every path is ok |
|
198 | 200 | |
|
199 | 201 | def setbinary(fd): |
|
200 | 202 | pass |
|
201 | 203 | |
|
202 | 204 | def pconvert(path): |
|
203 | 205 | return path |
|
204 | 206 | |
|
205 | 207 | def localpath(path): |
|
206 | 208 | return path |
|
207 | 209 | |
|
208 | 210 | def samefile(fpath1, fpath2): |
|
209 | 211 | """Returns whether path1 and path2 refer to the same file. This is only |
|
210 | 212 | guaranteed to work for files, not directories.""" |
|
211 | 213 | return os.path.samefile(fpath1, fpath2) |
|
212 | 214 | |
|
213 | 215 | def samedevice(fpath1, fpath2): |
|
214 | 216 | """Returns whether fpath1 and fpath2 are on the same device. This is only |
|
215 | 217 | guaranteed to work for files, not directories.""" |
|
216 | 218 | st1 = os.lstat(fpath1) |
|
217 | 219 | st2 = os.lstat(fpath2) |
|
218 | 220 | return st1.st_dev == st2.st_dev |
|
219 | 221 | |
|
220 | 222 | # os.path.normcase is a no-op, which doesn't help us on non-native filesystems |
|
221 | 223 | def normcase(path): |
|
222 | 224 | return path.lower() |
|
223 | 225 | |
|
224 | 226 | # what normcase does to ASCII strings |
|
225 | 227 | normcasespec = encoding.normcasespecs.lower |
|
226 | 228 | # fallback normcase function for non-ASCII strings |
|
227 | 229 | normcasefallback = normcase |
|
228 | 230 | |
|
229 | 231 | if sys.platform == 'darwin': |
|
230 | 232 | |
|
231 | 233 | def normcase(path): |
|
232 | 234 | ''' |
|
233 | 235 | Normalize a filename for OS X-compatible comparison: |
|
234 | 236 | - escape-encode invalid characters |
|
235 | 237 | - decompose to NFD |
|
236 | 238 | - lowercase |
|
237 | 239 | - omit ignored characters [200c-200f, 202a-202e, 206a-206f,feff] |
|
238 | 240 | |
|
239 | 241 | >>> normcase('UPPER') |
|
240 | 242 | 'upper' |
|
241 | 243 | >>> normcase('Caf\xc3\xa9') |
|
242 | 244 | 'cafe\\xcc\\x81' |
|
243 | 245 | >>> normcase('\xc3\x89') |
|
244 | 246 | 'e\\xcc\\x81' |
|
245 | 247 | >>> normcase('\xb8\xca\xc3\xca\xbe\xc8.JPG') # issue3918 |
|
246 | 248 | '%b8%ca%c3\\xca\\xbe%c8.jpg' |
|
247 | 249 | ''' |
|
248 | 250 | |
|
249 | 251 | try: |
|
250 | 252 | return encoding.asciilower(path) # exception for non-ASCII |
|
251 | 253 | except UnicodeDecodeError: |
|
252 | 254 | return normcasefallback(path) |
|
253 | 255 | |
|
254 | 256 | normcasespec = encoding.normcasespecs.lower |
|
255 | 257 | |
|
256 | 258 | def normcasefallback(path): |
|
257 | 259 | try: |
|
258 | 260 | u = path.decode('utf-8') |
|
259 | 261 | except UnicodeDecodeError: |
|
260 | 262 | # OS X percent-encodes any bytes that aren't valid utf-8 |
|
261 | 263 | s = '' |
|
262 | 264 | pos = 0 |
|
263 | 265 | l = len(s) |
|
264 | 266 | while pos < l: |
|
265 | 267 | try: |
|
266 | 268 | c = encoding.getutf8char(path, pos) |
|
267 | 269 | pos += len(c) |
|
268 | 270 | except ValueError: |
|
269 | 271 | c = '%%%%02X' % path[pos] |
|
270 | 272 | pos += 1 |
|
271 | 273 | s += c |
|
272 | 274 | |
|
273 | 275 | u = s.decode('utf-8') |
|
274 | 276 | |
|
275 | 277 | # Decompose then lowercase (HFS+ technote specifies lower) |
|
276 | 278 | enc = unicodedata.normalize('NFD', u).lower().encode('utf-8') |
|
277 | 279 | # drop HFS+ ignored characters |
|
278 | 280 | return encoding.hfsignoreclean(enc) |
|
279 | 281 | |
|
280 | 282 | if sys.platform == 'cygwin': |
|
281 | 283 | # workaround for cygwin, in which mount point part of path is |
|
282 | 284 | # treated as case sensitive, even though underlying NTFS is case |
|
283 | 285 | # insensitive. |
|
284 | 286 | |
|
285 | 287 | # default mount points |
|
286 | 288 | cygwinmountpoints = sorted([ |
|
287 | 289 | "/usr/bin", |
|
288 | 290 | "/usr/lib", |
|
289 | 291 | "/cygdrive", |
|
290 | 292 | ], reverse=True) |
|
291 | 293 | |
|
292 | 294 | # use upper-ing as normcase as same as NTFS workaround |
|
293 | 295 | def normcase(path): |
|
294 | 296 | pathlen = len(path) |
|
295 | 297 | if (pathlen == 0) or (path[0] != os.sep): |
|
296 | 298 | # treat as relative |
|
297 | 299 | return encoding.upper(path) |
|
298 | 300 | |
|
299 | 301 | # to preserve case of mountpoint part |
|
300 | 302 | for mp in cygwinmountpoints: |
|
301 | 303 | if not path.startswith(mp): |
|
302 | 304 | continue |
|
303 | 305 | |
|
304 | 306 | mplen = len(mp) |
|
305 | 307 | if mplen == pathlen: # mount point itself |
|
306 | 308 | return mp |
|
307 | 309 | if path[mplen] == os.sep: |
|
308 | 310 | return mp + encoding.upper(path[mplen:]) |
|
309 | 311 | |
|
310 | 312 | return encoding.upper(path) |
|
311 | 313 | |
|
312 | 314 | normcasespec = encoding.normcasespecs.other |
|
313 | 315 | normcasefallback = normcase |
|
314 | 316 | |
|
315 | 317 | # Cygwin translates native ACLs to POSIX permissions, |
|
316 | 318 | # but these translations are not supported by native |
|
317 | 319 | # tools, so the exec bit tends to be set erroneously. |
|
318 | 320 | # Therefore, disable executable bit access on Cygwin. |
|
319 | 321 | def checkexec(path): |
|
320 | 322 | return False |
|
321 | 323 | |
|
322 | 324 | # Similarly, Cygwin's symlink emulation is likely to create |
|
323 | 325 | # problems when Mercurial is used from both Cygwin and native |
|
324 | 326 | # Windows, with other native tools, or on shared volumes |
|
325 | 327 | def checklink(path): |
|
326 | 328 | return False |
|
327 | 329 | |
|
328 | 330 | _needsshellquote = None |
|
329 | 331 | def shellquote(s): |
|
330 | 332 | if os.sys.platform == 'OpenVMS': |
|
331 | 333 | return '"%s"' % s |
|
332 | 334 | global _needsshellquote |
|
333 | 335 | if _needsshellquote is None: |
|
334 | 336 | _needsshellquote = re.compile(r'[^a-zA-Z0-9._/+-]').search |
|
335 | 337 | if s and not _needsshellquote(s): |
|
336 | 338 | # "s" shouldn't have to be quoted |
|
337 | 339 | return s |
|
338 | 340 | else: |
|
339 | 341 | return "'%s'" % s.replace("'", "'\\''") |
|
340 | 342 | |
|
341 | 343 | def quotecommand(cmd): |
|
342 | 344 | return cmd |
|
343 | 345 | |
|
344 | 346 | def popen(command, mode='r'): |
|
345 | 347 | return os.popen(command, mode) |
|
346 | 348 | |
|
347 | 349 | def testpid(pid): |
|
348 | 350 | '''return False if pid dead, True if running or not sure''' |
|
349 | 351 | if os.sys.platform == 'OpenVMS': |
|
350 | 352 | return True |
|
351 | 353 | try: |
|
352 | 354 | os.kill(pid, 0) |
|
353 | 355 | return True |
|
354 | 356 | except OSError as inst: |
|
355 | 357 | return inst.errno != errno.ESRCH |
|
356 | 358 | |
|
357 | 359 | def explainexit(code): |
|
358 | 360 | """return a 2-tuple (desc, code) describing a subprocess status |
|
359 | 361 | (codes from kill are negative - not os.system/wait encoding)""" |
|
360 | 362 | if code >= 0: |
|
361 | 363 | return _("exited with status %d") % code, code |
|
362 | 364 | return _("killed by signal %d") % -code, -code |
|
363 | 365 | |
|
364 | 366 | def isowner(st): |
|
365 | 367 | """Return True if the stat object st is from the current user.""" |
|
366 | 368 | return st.st_uid == os.getuid() |
|
367 | 369 | |
|
368 | 370 | def findexe(command): |
|
369 | 371 | '''Find executable for command searching like which does. |
|
370 | 372 | If command is a basename then PATH is searched for command. |
|
371 | 373 | PATH isn't searched if command is an absolute or relative path. |
|
372 | 374 | If command isn't found None is returned.''' |
|
373 | 375 | if sys.platform == 'OpenVMS': |
|
374 | 376 | return command |
|
375 | 377 | |
|
376 | 378 | def findexisting(executable): |
|
377 | 379 | 'Will return executable if existing file' |
|
378 | 380 | if os.path.isfile(executable) and os.access(executable, os.X_OK): |
|
379 | 381 | return executable |
|
380 | 382 | return None |
|
381 | 383 | |
|
382 | 384 | if os.sep in command: |
|
383 | 385 | return findexisting(command) |
|
384 | 386 | |
|
385 | 387 | if sys.platform == 'plan9': |
|
386 | 388 | return findexisting(os.path.join('/bin', command)) |
|
387 | 389 | |
|
388 | 390 | for path in os.environ.get('PATH', '').split(os.pathsep): |
|
389 | 391 | executable = findexisting(os.path.join(path, command)) |
|
390 | 392 | if executable is not None: |
|
391 | 393 | return executable |
|
392 | 394 | return None |
|
393 | 395 | |
|
394 | 396 | def setsignalhandler(): |
|
395 | 397 | pass |
|
396 | 398 | |
|
397 | 399 | _wantedkinds = set([stat.S_IFREG, stat.S_IFLNK]) |
|
398 | 400 | |
|
399 | 401 | def statfiles(files): |
|
400 | 402 | '''Stat each file in files. Yield each stat, or None if a file does not |
|
401 | 403 | exist or has a type we don't care about.''' |
|
402 | 404 | lstat = os.lstat |
|
403 | 405 | getkind = stat.S_IFMT |
|
404 | 406 | for nf in files: |
|
405 | 407 | try: |
|
406 | 408 | st = lstat(nf) |
|
407 | 409 | if getkind(st.st_mode) not in _wantedkinds: |
|
408 | 410 | st = None |
|
409 | 411 | except OSError as err: |
|
410 | 412 | if err.errno not in (errno.ENOENT, errno.ENOTDIR): |
|
411 | 413 | raise |
|
412 | 414 | st = None |
|
413 | 415 | yield st |
|
414 | 416 | |
|
415 | 417 | def getuser(): |
|
416 | 418 | '''return name of current user''' |
|
417 | 419 | return getpass.getuser() |
|
418 | 420 | |
|
419 | 421 | def username(uid=None): |
|
420 | 422 | """Return the name of the user with the given uid. |
|
421 | 423 | |
|
422 | 424 | If uid is None, return the name of the current user.""" |
|
423 | 425 | |
|
424 | 426 | if uid is None: |
|
425 | 427 | uid = os.getuid() |
|
426 | 428 | try: |
|
427 | 429 | return pwd.getpwuid(uid)[0] |
|
428 | 430 | except KeyError: |
|
429 | 431 | return str(uid) |
|
430 | 432 | |
|
431 | 433 | def groupname(gid=None): |
|
432 | 434 | """Return the name of the group with the given gid. |
|
433 | 435 | |
|
434 | 436 | If gid is None, return the name of the current group.""" |
|
435 | 437 | |
|
436 | 438 | if gid is None: |
|
437 | 439 | gid = os.getgid() |
|
438 | 440 | try: |
|
439 | 441 | return grp.getgrgid(gid)[0] |
|
440 | 442 | except KeyError: |
|
441 | 443 | return str(gid) |
|
442 | 444 | |
|
443 | 445 | def groupmembers(name): |
|
444 | 446 | """Return the list of members of the group with the given |
|
445 | 447 | name, KeyError if the group does not exist. |
|
446 | 448 | """ |
|
447 | 449 | return list(grp.getgrnam(name).gr_mem) |
|
448 | 450 | |
|
449 | 451 | def spawndetached(args): |
|
450 | 452 | return os.spawnvp(os.P_NOWAIT | getattr(os, 'P_DETACH', 0), |
|
451 | 453 | args[0], args) |
|
452 | 454 | |
|
453 | 455 | def gethgcmd(): |
|
454 | 456 | return sys.argv[:1] |
|
455 | 457 | |
|
456 | 458 | def termwidth(): |
|
457 | 459 | try: |
|
458 | 460 | import array |
|
459 | 461 | import termios |
|
460 | 462 | for dev in (sys.stderr, sys.stdout, sys.stdin): |
|
461 | 463 | try: |
|
462 | 464 | try: |
|
463 | 465 | fd = dev.fileno() |
|
464 | 466 | except AttributeError: |
|
465 | 467 | continue |
|
466 | 468 | if not os.isatty(fd): |
|
467 | 469 | continue |
|
468 | 470 | try: |
|
469 | 471 | arri = fcntl.ioctl(fd, termios.TIOCGWINSZ, '\0' * 8) |
|
470 | 472 | width = array.array('h', arri)[1] |
|
471 | 473 | if width > 0: |
|
472 | 474 | return width |
|
473 | 475 | except AttributeError: |
|
474 | 476 | pass |
|
475 | 477 | except ValueError: |
|
476 | 478 | pass |
|
477 | 479 | except IOError as e: |
|
478 | 480 | if e[0] == errno.EINVAL: |
|
479 | 481 | pass |
|
480 | 482 | else: |
|
481 | 483 | raise |
|
482 | 484 | except ImportError: |
|
483 | 485 | pass |
|
484 | 486 | return 80 |
|
485 | 487 | |
|
486 | 488 | def makedir(path, notindexed): |
|
487 | 489 | os.mkdir(path) |
|
488 | 490 | |
|
489 | 491 | def unlinkpath(f, ignoremissing=False): |
|
490 | 492 | """unlink and remove the directory if it is empty""" |
|
491 | 493 | try: |
|
492 | 494 | os.unlink(f) |
|
493 | 495 | except OSError as e: |
|
494 | 496 | if not (ignoremissing and e.errno == errno.ENOENT): |
|
495 | 497 | raise |
|
496 | 498 | # try removing directories that might now be empty |
|
497 | 499 | try: |
|
498 | 500 | os.removedirs(os.path.dirname(f)) |
|
499 | 501 | except OSError: |
|
500 | 502 | pass |
|
501 | 503 | |
|
502 | 504 | def lookupreg(key, name=None, scope=None): |
|
503 | 505 | return None |
|
504 | 506 | |
|
505 | 507 | def hidewindow(): |
|
506 | 508 | """Hide current shell window. |
|
507 | 509 | |
|
508 | 510 | Used to hide the window opened when starting asynchronous |
|
509 | 511 | child process under Windows, unneeded on other systems. |
|
510 | 512 | """ |
|
511 | 513 | pass |
|
512 | 514 | |
|
513 | 515 | class cachestat(object): |
|
514 | 516 | def __init__(self, path): |
|
515 | 517 | self.stat = os.stat(path) |
|
516 | 518 | |
|
517 | 519 | def cacheable(self): |
|
518 | 520 | return bool(self.stat.st_ino) |
|
519 | 521 | |
|
520 | 522 | __hash__ = object.__hash__ |
|
521 | 523 | |
|
522 | 524 | def __eq__(self, other): |
|
523 | 525 | try: |
|
524 | 526 | # Only dev, ino, size, mtime and atime are likely to change. Out |
|
525 | 527 | # of these, we shouldn't compare atime but should compare the |
|
526 | 528 | # rest. However, one of the other fields changing indicates |
|
527 | 529 | # something fishy going on, so return False if anything but atime |
|
528 | 530 | # changes. |
|
529 | 531 | return (self.stat.st_mode == other.stat.st_mode and |
|
530 | 532 | self.stat.st_ino == other.stat.st_ino and |
|
531 | 533 | self.stat.st_dev == other.stat.st_dev and |
|
532 | 534 | self.stat.st_nlink == other.stat.st_nlink and |
|
533 | 535 | self.stat.st_uid == other.stat.st_uid and |
|
534 | 536 | self.stat.st_gid == other.stat.st_gid and |
|
535 | 537 | self.stat.st_size == other.stat.st_size and |
|
536 | 538 | self.stat.st_mtime == other.stat.st_mtime and |
|
537 | 539 | self.stat.st_ctime == other.stat.st_ctime) |
|
538 | 540 | except AttributeError: |
|
539 | 541 | return False |
|
540 | 542 | |
|
541 | 543 | def __ne__(self, other): |
|
542 | 544 | return not self == other |
|
543 | 545 | |
|
544 | 546 | def executablepath(): |
|
545 | 547 | return None # available on Windows only |
|
546 | 548 | |
|
547 | 549 | class unixdomainserver(socket.socket): |
|
548 | 550 | def __init__(self, join, subsystem): |
|
549 | 551 | '''Create a unix domain socket with the given prefix.''' |
|
550 | 552 | super(unixdomainserver, self).__init__(socket.AF_UNIX) |
|
551 | 553 | sockname = subsystem + '.sock' |
|
552 | 554 | self.realpath = self.path = join(sockname) |
|
553 | 555 | if os.path.islink(self.path): |
|
554 | 556 | if os.path.exists(self.path): |
|
555 | 557 | self.realpath = os.readlink(self.path) |
|
556 | 558 | else: |
|
557 | 559 | os.unlink(self.path) |
|
558 | 560 | try: |
|
559 | 561 | self.bind(self.realpath) |
|
560 | 562 | except socket.error as err: |
|
561 | 563 | if err.args[0] == 'AF_UNIX path too long': |
|
562 | 564 | tmpdir = tempfile.mkdtemp(prefix='hg-%s-' % subsystem) |
|
563 | 565 | self.realpath = os.path.join(tmpdir, sockname) |
|
564 | 566 | try: |
|
565 | 567 | self.bind(self.realpath) |
|
566 | 568 | os.symlink(self.realpath, self.path) |
|
567 | 569 | except (OSError, socket.error): |
|
568 | 570 | self.cleanup() |
|
569 | 571 | raise |
|
570 | 572 | else: |
|
571 | 573 | raise |
|
572 | 574 | self.listen(5) |
|
573 | 575 | |
|
574 | 576 | def cleanup(self): |
|
575 | 577 | def okayifmissing(f, path): |
|
576 | 578 | try: |
|
577 | 579 | f(path) |
|
578 | 580 | except OSError as err: |
|
579 | 581 | if err.errno != errno.ENOENT: |
|
580 | 582 | raise |
|
581 | 583 | |
|
582 | 584 | okayifmissing(os.unlink, self.path) |
|
583 | 585 | if self.realpath != self.path: |
|
584 | 586 | okayifmissing(os.unlink, self.realpath) |
|
585 | 587 | okayifmissing(os.rmdir, os.path.dirname(self.realpath)) |
|
586 | 588 | |
|
587 | 589 | def statislink(st): |
|
588 | 590 | '''check whether a stat result is a symlink''' |
|
589 | 591 | return st and stat.S_ISLNK(st.st_mode) |
|
590 | 592 | |
|
591 | 593 | def statisexec(st): |
|
592 | 594 | '''check whether a stat result is an executable file''' |
|
593 | 595 | return st and (st.st_mode & 0o100 != 0) |
|
594 | 596 | |
|
595 | 597 | def poll(fds): |
|
596 | 598 | """block until something happens on any file descriptor |
|
597 | 599 | |
|
598 | 600 | This is a generic helper that will check for any activity |
|
599 | 601 | (read, write. exception) and return the list of touched files. |
|
600 | 602 | |
|
601 | 603 | In unsupported cases, it will raise a NotImplementedError""" |
|
602 | 604 | try: |
|
603 | 605 | res = select.select(fds, fds, fds) |
|
604 | 606 | except ValueError: # out of range file descriptor |
|
605 | 607 | raise NotImplementedError() |
|
606 | 608 | return sorted(list(set(sum(res, [])))) |
|
607 | 609 | |
|
608 | 610 | def readpipe(pipe): |
|
609 | 611 | """Read all available data from a pipe.""" |
|
610 | 612 | # We can't fstat() a pipe because Linux will always report 0. |
|
611 | 613 | # So, we set the pipe to non-blocking mode and read everything |
|
612 | 614 | # that's available. |
|
613 | 615 | flags = fcntl.fcntl(pipe, fcntl.F_GETFL) |
|
614 | 616 | flags |= os.O_NONBLOCK |
|
615 | 617 | oldflags = fcntl.fcntl(pipe, fcntl.F_SETFL, flags) |
|
616 | 618 | |
|
617 | 619 | try: |
|
618 | 620 | chunks = [] |
|
619 | 621 | while True: |
|
620 | 622 | try: |
|
621 | 623 | s = pipe.read() |
|
622 | 624 | if not s: |
|
623 | 625 | break |
|
624 | 626 | chunks.append(s) |
|
625 | 627 | except IOError: |
|
626 | 628 | break |
|
627 | 629 | |
|
628 | 630 | return ''.join(chunks) |
|
629 | 631 | finally: |
|
630 | 632 | fcntl.fcntl(pipe, fcntl.F_SETFL, oldflags) |
General Comments 0
You need to be logged in to leave comments.
Login now