##// END OF EJS Templates
merge with stable
Matt Mackall -
r26901:0e3d093c merge default
parent child Browse files
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 f0d7721d7322dcfb5af33599c2543f27335334bb 0 iD8DBQBR8taaywK+sNU5EO8RAqeEAJ4idDhhDuEsgsUjeQgWNj498matHACfT67gSF5w0ylsrBx1Hb52HkGXDm0=
78 78 f37b5a17e6a0ee17afde2cdde5393dd74715fb58 0 iD8DBQBR+ymFywK+sNU5EO8RAuSdAJkBMcd9DAZ3rWE9WGKPm2YZ8LBoXACfXn/wbEsVy7ZgJoUwiWmHSnQaWCI=
79 79 335a558f81dc73afeab4d7be63617392b130117f 0 iQIVAwUAUiZrIyBXgaxoKi1yAQK2iw//cquNqqSkc8Re5/TZT9I6NH+lh6DbOKjJP0Xl1Wqq0K+KSIUgZG4G32ovaEb2l5X0uY+3unRPiZ0ebl0YSw4Fb2ZiPIADXLBTOYRrY2Wwd3tpJeGI6wEgZt3SfcITV/g7NJrCjT3FlYoSOIayrExM80InSdcEM0Q3Rx6HKzY2acyxzgZeAtAW5ohFvHilSvY6p5Gcm4+QptMxvw45GPdreUmjeXZxNXNXZ8P+MjMz/QJbai/N7PjmK8lqnhkBsT48Ng/KhhmOkGntNJ2/ImBWLFGcWngSvJ7sfWwnyhndvGhe0Hq1NcCf7I8TjNDxU5TR+m+uW7xjXdLoDbUjBdX4sKXnh8ZjbYiODKBOrrDq25cf8nA/tnpKyE/qsVy60kOk6loY4XKiYmn1V49Ta0emmDx0hqo3HgxHHsHX0NDnGdWGol7cPRET0RzVobKq1A0jnrhPooWidvLh9bPzLonrWDo+ib+DuySoRkuYUK4pgZJ2mbg6daFOBEZygkSyRB8bo1UQUP7EgQDrWe4khb/5GHEfDkrQz3qu/sXvc0Ir1mOUWBFPHC2DjjCn/oMJuUkG1SwM8l2Bfv7h67ssES6YQ2+RjOix4yid7EXS/Ogl45PzCIPSI5+BbNs10JhE0w5uErBHlF53EDTe/TSLc+GU6DB6PP6dH912Njdr3jpNSUQ=
80 80 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
@@ -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 # sshfs might report failure while successfully creating the link
186 192 if inst[0] == errno.EIO and os.path.exists(name):
187 193 os.unlink(name)
188 194 return False
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