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