Show More
The requested changes are too big and content was truncated. Show full diff
@@ -1,135 +1,137 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 | 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 |
@@ -1,148 +1,150 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 |
|
131 | 1aa5083cbebbe7575c88f3402ab377539b484897 3.6.1 | |
132 | 2d437a0f3355834a9485bbbeb30a52a052c98f19 3.6.2 |
|
132 | 2d437a0f3355834a9485bbbeb30a52a052c98f19 3.6.2 | |
133 | ea389970c08449440587712117f178d33bab3f1e 3.6.3 |
|
133 | ea389970c08449440587712117f178d33bab3f1e 3.6.3 | |
134 | 158bdc8965720ca4061f8f8d806563cfc7cdb62e 3.7-rc |
|
134 | 158bdc8965720ca4061f8f8d806563cfc7cdb62e 3.7-rc | |
135 | 2408645de650d8a29a6ce9e7dce601d8dd0d1474 3.7 |
|
135 | 2408645de650d8a29a6ce9e7dce601d8dd0d1474 3.7 | |
136 | b698abf971e7377d9b7ec7fc8c52df45255b0329 3.7.1 |
|
136 | b698abf971e7377d9b7ec7fc8c52df45255b0329 3.7.1 | |
137 | d493d64757eb45ada99fcb3693e479a51b7782da 3.7.2 |
|
137 | d493d64757eb45ada99fcb3693e479a51b7782da 3.7.2 | |
138 | ae279d4a19e9683214cbd1fe8298cf0b50571432 3.7.3 |
|
138 | ae279d4a19e9683214cbd1fe8298cf0b50571432 3.7.3 | |
139 | 740156eedf2c450aee58b1a90b0e826f47c5da64 3.8-rc |
|
139 | 740156eedf2c450aee58b1a90b0e826f47c5da64 3.8-rc | |
140 | f85de28eae32e7d3064b1a1321309071bbaaa069 3.8 |
|
140 | f85de28eae32e7d3064b1a1321309071bbaaa069 3.8 | |
141 | a56296f55a5e1038ea5016dace2076b693c28a56 3.8.1 |
|
141 | a56296f55a5e1038ea5016dace2076b693c28a56 3.8.1 | |
142 | aaabed77791a75968a12b8c43ad263631a23ee81 3.8.2 |
|
142 | aaabed77791a75968a12b8c43ad263631a23ee81 3.8.2 | |
143 | a9764ab80e11bcf6a37255db7dd079011f767c6c 3.8.3 |
|
143 | a9764ab80e11bcf6a37255db7dd079011f767c6c 3.8.3 | |
144 | 26a5d605b8683a292bb89aea11f37a81b06ac016 3.8.4 |
|
144 | 26a5d605b8683a292bb89aea11f37a81b06ac016 3.8.4 | |
145 | 519bb4f9d3a47a6e83c2b414d58811ed38f503c2 3.9-rc |
|
145 | 519bb4f9d3a47a6e83c2b414d58811ed38f503c2 3.9-rc | |
146 | 299546f84e68dbb9bd026f0f3a974ce4bdb93686 3.9 |
|
146 | 299546f84e68dbb9bd026f0f3a974ce4bdb93686 3.9 | |
147 | ccd436f7db6d5d7b9af89715179b911d031d44f1 3.9.1 |
|
147 | ccd436f7db6d5d7b9af89715179b911d031d44f1 3.9.1 | |
148 | 149433e68974eb5c63ccb03f794d8b57339a80c4 3.9.2 |
|
148 | 149433e68974eb5c63ccb03f794d8b57339a80c4 3.9.2 | |
|
149 | 438173c415874f6ac653efc1099dec9c9150e90f 4.0-rc | |||
|
150 | eab27446995210c334c3d06f1a659e3b9b5da769 4.0 |
@@ -1,657 +1,671 b'' | |||||
1 | #!/usr/bin/env python |
|
1 | #!/usr/bin/env python | |
2 | # |
|
2 | # | |
3 | # check-code - a style and portability checker for Mercurial |
|
3 | # check-code - a style and portability checker for Mercurial | |
4 | # |
|
4 | # | |
5 | # Copyright 2010 Matt Mackall <mpm@selenic.com> |
|
5 | # Copyright 2010 Matt Mackall <mpm@selenic.com> | |
6 | # |
|
6 | # | |
7 | # This software may be used and distributed according to the terms of the |
|
7 | # This software may be used and distributed according to the terms of the | |
8 | # GNU General Public License version 2 or any later version. |
|
8 | # GNU General Public License version 2 or any later version. | |
9 |
|
9 | |||
10 | """style and portability checker for Mercurial |
|
10 | """style and portability checker for Mercurial | |
11 |
|
11 | |||
12 | when a rule triggers wrong, do one of the following (prefer one from top): |
|
12 | when a rule triggers wrong, do one of the following (prefer one from top): | |
13 | * do the work-around the rule suggests |
|
13 | * do the work-around the rule suggests | |
14 | * doublecheck that it is a false match |
|
14 | * doublecheck that it is a false match | |
15 | * improve the rule pattern |
|
15 | * improve the rule pattern | |
16 | * add an ignore pattern to the rule (3rd arg) which matches your good line |
|
16 | * add an ignore pattern to the rule (3rd arg) which matches your good line | |
17 | (you can append a short comment and match this, like: #re-raises) |
|
17 | (you can append a short comment and match this, like: #re-raises) | |
18 | * change the pattern to a warning and list the exception in test-check-code-hg |
|
18 | * change the pattern to a warning and list the exception in test-check-code-hg | |
19 | * ONLY use no--check-code for skipping entire files from external sources |
|
19 | * ONLY use no--check-code for skipping entire files from external sources | |
20 | """ |
|
20 | """ | |
21 |
|
21 | |||
22 | from __future__ import absolute_import, print_function |
|
22 | from __future__ import absolute_import, print_function | |
23 | import glob |
|
23 | import glob | |
24 | import keyword |
|
24 | import keyword | |
25 | import optparse |
|
25 | import optparse | |
26 | import os |
|
26 | import os | |
27 | import re |
|
27 | import re | |
28 | import sys |
|
28 | import sys | |
29 | if sys.version_info[0] < 3: |
|
29 | if sys.version_info[0] < 3: | |
30 | opentext = open |
|
30 | opentext = open | |
31 | else: |
|
31 | else: | |
32 | def opentext(f): |
|
32 | def opentext(f): | |
33 | return open(f, encoding='ascii') |
|
33 | return open(f, encoding='ascii') | |
34 | try: |
|
34 | try: | |
35 | xrange |
|
35 | xrange | |
36 | except NameError: |
|
36 | except NameError: | |
37 | xrange = range |
|
37 | xrange = range | |
38 | try: |
|
38 | try: | |
39 | import re2 |
|
39 | import re2 | |
40 | except ImportError: |
|
40 | except ImportError: | |
41 | re2 = None |
|
41 | re2 = None | |
42 |
|
42 | |||
43 | def compilere(pat, multiline=False): |
|
43 | def compilere(pat, multiline=False): | |
44 | if multiline: |
|
44 | if multiline: | |
45 | pat = '(?m)' + pat |
|
45 | pat = '(?m)' + pat | |
46 | if re2: |
|
46 | if re2: | |
47 | try: |
|
47 | try: | |
48 | return re2.compile(pat) |
|
48 | return re2.compile(pat) | |
49 | except re2.error: |
|
49 | except re2.error: | |
50 | pass |
|
50 | pass | |
51 | return re.compile(pat) |
|
51 | return re.compile(pat) | |
52 |
|
52 | |||
53 | # check "rules depending on implementation of repquote()" in each |
|
53 | # check "rules depending on implementation of repquote()" in each | |
54 | # patterns (especially pypats), before changing around repquote() |
|
54 | # patterns (especially pypats), before changing around repquote() | |
55 | _repquotefixedmap = {' ': ' ', '\n': '\n', '.': 'p', ':': 'q', |
|
55 | _repquotefixedmap = {' ': ' ', '\n': '\n', '.': 'p', ':': 'q', | |
56 | '%': '%', '\\': 'b', '*': 'A', '+': 'P', '-': 'M'} |
|
56 | '%': '%', '\\': 'b', '*': 'A', '+': 'P', '-': 'M'} | |
57 | def _repquoteencodechr(i): |
|
57 | def _repquoteencodechr(i): | |
58 | if i > 255: |
|
58 | if i > 255: | |
59 | return 'u' |
|
59 | return 'u' | |
60 | c = chr(i) |
|
60 | c = chr(i) | |
61 | if c in _repquotefixedmap: |
|
61 | if c in _repquotefixedmap: | |
62 | return _repquotefixedmap[c] |
|
62 | return _repquotefixedmap[c] | |
63 | if c.isalpha(): |
|
63 | if c.isalpha(): | |
64 | return 'x' |
|
64 | return 'x' | |
65 | if c.isdigit(): |
|
65 | if c.isdigit(): | |
66 | return 'n' |
|
66 | return 'n' | |
67 | return 'o' |
|
67 | return 'o' | |
68 | _repquotett = ''.join(_repquoteencodechr(i) for i in xrange(256)) |
|
68 | _repquotett = ''.join(_repquoteencodechr(i) for i in xrange(256)) | |
69 |
|
69 | |||
70 | def repquote(m): |
|
70 | def repquote(m): | |
71 | t = m.group('text') |
|
71 | t = m.group('text') | |
72 | t = t.translate(_repquotett) |
|
72 | t = t.translate(_repquotett) | |
73 | return m.group('quote') + t + m.group('quote') |
|
73 | return m.group('quote') + t + m.group('quote') | |
74 |
|
74 | |||
75 | def reppython(m): |
|
75 | def reppython(m): | |
76 | comment = m.group('comment') |
|
76 | comment = m.group('comment') | |
77 | if comment: |
|
77 | if comment: | |
78 | l = len(comment.rstrip()) |
|
78 | l = len(comment.rstrip()) | |
79 | return "#" * l + comment[l:] |
|
79 | return "#" * l + comment[l:] | |
80 | return repquote(m) |
|
80 | return repquote(m) | |
81 |
|
81 | |||
82 | def repcomment(m): |
|
82 | def repcomment(m): | |
83 | return m.group(1) + "#" * len(m.group(2)) |
|
83 | return m.group(1) + "#" * len(m.group(2)) | |
84 |
|
84 | |||
85 | def repccomment(m): |
|
85 | def repccomment(m): | |
86 | t = re.sub(r"((?<=\n) )|\S", "x", m.group(2)) |
|
86 | t = re.sub(r"((?<=\n) )|\S", "x", m.group(2)) | |
87 | return m.group(1) + t + "*/" |
|
87 | return m.group(1) + t + "*/" | |
88 |
|
88 | |||
89 | def repcallspaces(m): |
|
89 | def repcallspaces(m): | |
90 | t = re.sub(r"\n\s+", "\n", m.group(2)) |
|
90 | t = re.sub(r"\n\s+", "\n", m.group(2)) | |
91 | return m.group(1) + t |
|
91 | return m.group(1) + t | |
92 |
|
92 | |||
93 | def repinclude(m): |
|
93 | def repinclude(m): | |
94 | return m.group(1) + "<foo>" |
|
94 | return m.group(1) + "<foo>" | |
95 |
|
95 | |||
96 | def rephere(m): |
|
96 | def rephere(m): | |
97 | t = re.sub(r"\S", "x", m.group(2)) |
|
97 | t = re.sub(r"\S", "x", m.group(2)) | |
98 | return m.group(1) + t |
|
98 | return m.group(1) + t | |
99 |
|
99 | |||
100 |
|
100 | |||
101 | testpats = [ |
|
101 | testpats = [ | |
102 | [ |
|
102 | [ | |
103 | (r'pushd|popd', "don't use 'pushd' or 'popd', use 'cd'"), |
|
103 | (r'pushd|popd', "don't use 'pushd' or 'popd', use 'cd'"), | |
104 | (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"), |
|
104 | (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"), | |
105 | (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"), |
|
105 | (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"), | |
106 | (r'(?<!hg )grep.* -a', "don't use 'grep -a', use in-line python"), |
|
106 | (r'(?<!hg )grep.* -a', "don't use 'grep -a', use in-line python"), | |
107 | (r'sed.*-i', "don't use 'sed -i', use a temporary file"), |
|
107 | (r'sed.*-i', "don't use 'sed -i', use a temporary file"), | |
108 | (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"), |
|
108 | (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"), | |
109 | (r'echo -n', "don't use 'echo -n', use printf"), |
|
109 | (r'echo -n', "don't use 'echo -n', use printf"), | |
110 | (r'(^|\|\s*)\bwc\b[^|]*$\n(?!.*\(re\))', "filter wc output"), |
|
110 | (r'(^|\|\s*)\bwc\b[^|]*$\n(?!.*\(re\))', "filter wc output"), | |
111 | (r'head -c', "don't use 'head -c', use 'dd'"), |
|
111 | (r'head -c', "don't use 'head -c', use 'dd'"), | |
112 | (r'tail -n', "don't use the '-n' option to tail, just use '-<num>'"), |
|
112 | (r'tail -n', "don't use the '-n' option to tail, just use '-<num>'"), | |
113 | (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"), |
|
113 | (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"), | |
114 | (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"), |
|
114 | (r'ls.*-\w*R', "don't use 'ls -R', use 'find'"), | |
115 | (r'printf.*[^\\]\\([1-9]|0\d)', r"don't use 'printf \NNN', use Python"), |
|
115 | (r'printf.*[^\\]\\([1-9]|0\d)', r"don't use 'printf \NNN', use Python"), | |
116 | (r'printf.*[^\\]\\x', "don't use printf \\x, use Python"), |
|
116 | (r'printf.*[^\\]\\x', "don't use printf \\x, use Python"), | |
117 | (r'\$\(.*\)', "don't use $(expr), use `expr`"), |
|
117 | (r'\$\(.*\)', "don't use $(expr), use `expr`"), | |
118 | (r'rm -rf \*', "don't use naked rm -rf, target a directory"), |
|
118 | (r'rm -rf \*', "don't use naked rm -rf, target a directory"), | |
119 | (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w', |
|
119 | (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w', | |
120 | "use egrep for extended grep syntax"), |
|
120 | "use egrep for extended grep syntax"), | |
121 | (r'/bin/', "don't use explicit paths for tools"), |
|
121 | (r'/bin/', "don't use explicit paths for tools"), | |
122 | (r'[^\n]\Z', "no trailing newline"), |
|
122 | (r'[^\n]\Z', "no trailing newline"), | |
123 | (r'export .*=', "don't export and assign at once"), |
|
123 | (r'export .*=', "don't export and assign at once"), | |
124 | (r'^source\b', "don't use 'source', use '.'"), |
|
124 | (r'^source\b', "don't use 'source', use '.'"), | |
125 | (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"), |
|
125 | (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"), | |
126 | (r'\bls +[^|\n-]+ +-', "options to 'ls' must come before filenames"), |
|
126 | (r'\bls +[^|\n-]+ +-', "options to 'ls' must come before filenames"), | |
127 | (r'[^>\n]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"), |
|
127 | (r'[^>\n]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"), | |
128 | (r'^stop\(\)', "don't use 'stop' as a shell function name"), |
|
128 | (r'^stop\(\)', "don't use 'stop' as a shell function name"), | |
129 | (r'(\[|\btest\b).*-e ', "don't use 'test -e', use 'test -f'"), |
|
129 | (r'(\[|\btest\b).*-e ', "don't use 'test -e', use 'test -f'"), | |
130 | (r'\[\[\s+[^\]]*\]\]', "don't use '[[ ]]', use '[ ]'"), |
|
130 | (r'\[\[\s+[^\]]*\]\]', "don't use '[[ ]]', use '[ ]'"), | |
131 | (r'^alias\b.*=', "don't use alias, use a function"), |
|
131 | (r'^alias\b.*=', "don't use alias, use a function"), | |
132 | (r'if\s*!', "don't use '!' to negate exit status"), |
|
132 | (r'if\s*!', "don't use '!' to negate exit status"), | |
133 | (r'/dev/u?random', "don't use entropy, use /dev/zero"), |
|
133 | (r'/dev/u?random', "don't use entropy, use /dev/zero"), | |
134 | (r'do\s*true;\s*done', "don't use true as loop body, use sleep 0"), |
|
134 | (r'do\s*true;\s*done', "don't use true as loop body, use sleep 0"), | |
135 | (r'^( *)\t', "don't use tabs to indent"), |
|
135 | (r'^( *)\t', "don't use tabs to indent"), | |
136 | (r'sed (-e )?\'(\d+|/[^/]*/)i(?!\\\n)', |
|
136 | (r'sed (-e )?\'(\d+|/[^/]*/)i(?!\\\n)', | |
137 | "put a backslash-escaped newline after sed 'i' command"), |
|
137 | "put a backslash-escaped newline after sed 'i' command"), | |
138 | (r'^diff *-\w*[uU].*$\n(^ \$ |^$)', "prefix diff -u/-U with cmp"), |
|
138 | (r'^diff *-\w*[uU].*$\n(^ \$ |^$)', "prefix diff -u/-U with cmp"), | |
139 | (r'^\s+(if)? diff *-\w*[uU]', "prefix diff -u/-U with cmp"), |
|
139 | (r'^\s+(if)? diff *-\w*[uU]', "prefix diff -u/-U with cmp"), | |
140 | (r'seq ', "don't use 'seq', use $TESTDIR/seq.py"), |
|
140 | (r'seq ', "don't use 'seq', use $TESTDIR/seq.py"), | |
141 | (r'\butil\.Abort\b', "directly use error.Abort"), |
|
141 | (r'\butil\.Abort\b', "directly use error.Abort"), | |
142 | (r'\|&', "don't use |&, use 2>&1"), |
|
142 | (r'\|&', "don't use |&, use 2>&1"), | |
143 | (r'\w = +\w', "only one space after = allowed"), |
|
143 | (r'\w = +\w', "only one space after = allowed"), | |
144 | (r'\bsed\b.*[^\\]\\n', "don't use 'sed ... \\n', use a \\ and a newline"), |
|
144 | (r'\bsed\b.*[^\\]\\n', "don't use 'sed ... \\n', use a \\ and a newline"), | |
145 | (r'env.*-u', "don't use 'env -u VAR', use 'unset VAR'") |
|
145 | (r'env.*-u', "don't use 'env -u VAR', use 'unset VAR'") | |
146 | ], |
|
146 | ], | |
147 | # warnings |
|
147 | # warnings | |
148 | [ |
|
148 | [ | |
149 | (r'^function', "don't use 'function', use old style"), |
|
149 | (r'^function', "don't use 'function', use old style"), | |
150 | (r'^diff.*-\w*N', "don't use 'diff -N'"), |
|
150 | (r'^diff.*-\w*N', "don't use 'diff -N'"), | |
151 | (r'\$PWD|\${PWD}', "don't use $PWD, use `pwd`"), |
|
151 | (r'\$PWD|\${PWD}', "don't use $PWD, use `pwd`"), | |
152 | (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\^', "^ must be quoted"), |
|
152 | (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\^', "^ must be quoted"), | |
153 | (r'kill (`|\$\()', "don't use kill, use killdaemons.py") |
|
153 | (r'kill (`|\$\()', "don't use kill, use killdaemons.py") | |
154 | ] |
|
154 | ] | |
155 | ] |
|
155 | ] | |
156 |
|
156 | |||
157 | testfilters = [ |
|
157 | testfilters = [ | |
158 | (r"( *)(#([^\n]*\S)?)", repcomment), |
|
158 | (r"( *)(#([^\n]*\S)?)", repcomment), | |
159 | (r"<<(\S+)((.|\n)*?\n\1)", rephere), |
|
159 | (r"<<(\S+)((.|\n)*?\n\1)", rephere), | |
160 | ] |
|
160 | ] | |
161 |
|
161 | |||
162 | winglobmsg = "use (glob) to match Windows paths too" |
|
162 | winglobmsg = "use (glob) to match Windows paths too" | |
163 | uprefix = r"^ \$ " |
|
163 | uprefix = r"^ \$ " | |
164 | utestpats = [ |
|
164 | utestpats = [ | |
165 | [ |
|
165 | [ | |
166 | (r'^(\S.*|| [$>] \S.*)[ \t]\n', "trailing whitespace on non-output"), |
|
166 | (r'^(\S.*|| [$>] \S.*)[ \t]\n', "trailing whitespace on non-output"), | |
167 | (uprefix + r'.*\|\s*sed[^|>\n]*\n', |
|
167 | (uprefix + r'.*\|\s*sed[^|>\n]*\n', | |
168 | "use regex test output patterns instead of sed"), |
|
168 | "use regex test output patterns instead of sed"), | |
169 | (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"), |
|
169 | (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"), | |
170 | (uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"), |
|
170 | (uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"), | |
171 | (uprefix + r'.*\|\| echo.*(fail|error)', |
|
171 | (uprefix + r'.*\|\| echo.*(fail|error)', | |
172 | "explicit exit code checks unnecessary"), |
|
172 | "explicit exit code checks unnecessary"), | |
173 | (uprefix + r'set -e', "don't use set -e"), |
|
173 | (uprefix + r'set -e', "don't use set -e"), | |
174 | (uprefix + r'(\s|fi\b|done\b)', "use > for continued lines"), |
|
174 | (uprefix + r'(\s|fi\b|done\b)', "use > for continued lines"), | |
175 | (uprefix + r'.*:\.\S*/', "x:.y in a path does not work on msys, rewrite " |
|
175 | (uprefix + r'.*:\.\S*/', "x:.y in a path does not work on msys, rewrite " | |
176 | "as x://.y, or see `hg log -k msys` for alternatives", r'-\S+:\.|' #-Rxxx |
|
176 | "as x://.y, or see `hg log -k msys` for alternatives", r'-\S+:\.|' #-Rxxx | |
177 | '# no-msys'), # in test-pull.t which is skipped on windows |
|
177 | '# no-msys'), # in test-pull.t which is skipped on windows | |
178 | (r'^ saved backup bundle to \$TESTTMP.*\.hg$', winglobmsg), |
|
178 | (r'^ saved backup bundle to \$TESTTMP.*\.hg$', winglobmsg), | |
179 | (r'^ changeset .* references (corrupted|missing) \$TESTTMP/.*[^)]$', |
|
179 | (r'^ changeset .* references (corrupted|missing) \$TESTTMP/.*[^)]$', | |
180 | winglobmsg), |
|
180 | winglobmsg), | |
181 | (r'^ pulling from \$TESTTMP/.*[^)]$', winglobmsg, |
|
181 | (r'^ pulling from \$TESTTMP/.*[^)]$', winglobmsg, | |
182 | '\$TESTTMP/unix-repo$'), # in test-issue1802.t which skipped on windows |
|
182 | '\$TESTTMP/unix-repo$'), # in test-issue1802.t which skipped on windows | |
183 | (r'^ reverting (?!subrepo ).*/.*[^)]$', winglobmsg), |
|
183 | (r'^ reverting (?!subrepo ).*/.*[^)]$', winglobmsg), | |
184 | (r'^ cloning subrepo \S+/.*[^)]$', winglobmsg), |
|
184 | (r'^ cloning subrepo \S+/.*[^)]$', winglobmsg), | |
185 | (r'^ pushing to \$TESTTMP/.*[^)]$', winglobmsg), |
|
185 | (r'^ pushing to \$TESTTMP/.*[^)]$', winglobmsg), | |
186 | (r'^ pushing subrepo \S+/\S+ to.*[^)]$', winglobmsg), |
|
186 | (r'^ pushing subrepo \S+/\S+ to.*[^)]$', winglobmsg), | |
187 | (r'^ moving \S+/.*[^)]$', winglobmsg), |
|
187 | (r'^ moving \S+/.*[^)]$', winglobmsg), | |
188 | (r'^ no changes made to subrepo since.*/.*[^)]$', winglobmsg), |
|
188 | (r'^ no changes made to subrepo since.*/.*[^)]$', winglobmsg), | |
189 | (r'^ .*: largefile \S+ not available from file:.*/.*[^)]$', winglobmsg), |
|
189 | (r'^ .*: largefile \S+ not available from file:.*/.*[^)]$', winglobmsg), | |
190 | (r'^ .*file://\$TESTTMP', |
|
190 | (r'^ .*file://\$TESTTMP', | |
191 | 'write "file:/*/$TESTTMP" + (glob) to match on windows too'), |
|
191 | 'write "file:/*/$TESTTMP" + (glob) to match on windows too'), | |
192 | (r'^ [^$>].*27\.0\.0\.1.*[^)]$', |
|
192 | (r'^ [^$>].*27\.0\.0\.1.*[^)]$', | |
193 | 'use (glob) to match localhost IP on hosts without 127.0.0.1 too'), |
|
193 | 'use (glob) to match localhost IP on hosts without 127.0.0.1 too'), | |
194 | (r'^ (cat|find): .*: No such file or directory', |
|
194 | (r'^ (cat|find): .*: No such file or directory', | |
195 | 'use test -f to test for file existence'), |
|
195 | 'use test -f to test for file existence'), | |
196 | (r'^ diff -[^ -]*p', |
|
196 | (r'^ diff -[^ -]*p', | |
197 | "don't use (external) diff with -p for portability"), |
|
197 | "don't use (external) diff with -p for portability"), | |
198 | (r'^ [-+][-+][-+] .* [-+]0000 \(glob\)', |
|
198 | (r'^ [-+][-+][-+] .* [-+]0000 \(glob\)', | |
199 | "glob timezone field in diff output for portability"), |
|
199 | "glob timezone field in diff output for portability"), | |
200 | (r'^ @@ -[0-9]+ [+][0-9]+,[0-9]+ @@', |
|
200 | (r'^ @@ -[0-9]+ [+][0-9]+,[0-9]+ @@', | |
201 | "use '@@ -N* +N,n @@ (glob)' style chunk header for portability"), |
|
201 | "use '@@ -N* +N,n @@ (glob)' style chunk header for portability"), | |
202 | (r'^ @@ -[0-9]+,[0-9]+ [+][0-9]+ @@', |
|
202 | (r'^ @@ -[0-9]+,[0-9]+ [+][0-9]+ @@', | |
203 | "use '@@ -N,n +N* @@ (glob)' style chunk header for portability"), |
|
203 | "use '@@ -N,n +N* @@ (glob)' style chunk header for portability"), | |
204 | (r'^ @@ -[0-9]+ [+][0-9]+ @@', |
|
204 | (r'^ @@ -[0-9]+ [+][0-9]+ @@', | |
205 | "use '@@ -N* +N* @@ (glob)' style chunk header for portability"), |
|
205 | "use '@@ -N* +N* @@ (glob)' style chunk header for portability"), | |
206 | (uprefix + r'hg( +-[^ ]+( +[^ ]+)?)* +extdiff' |
|
206 | (uprefix + r'hg( +-[^ ]+( +[^ ]+)?)* +extdiff' | |
207 | r'( +(-[^ po-]+|--(?!program|option)[^ ]+|[^-][^ ]*))*$', |
|
207 | r'( +(-[^ po-]+|--(?!program|option)[^ ]+|[^-][^ ]*))*$', | |
208 | "use $RUNTESTDIR/pdiff via extdiff (or -o/-p for false-positives)"), |
|
208 | "use $RUNTESTDIR/pdiff via extdiff (or -o/-p for false-positives)"), | |
209 | ], |
|
209 | ], | |
210 | # warnings |
|
210 | # warnings | |
211 | [ |
|
211 | [ | |
212 | (r'^ (?!.*127\.0\.0\.1)[^*?/\n]* \(glob\)$', |
|
212 | (r'^ (?!.*127\.0\.0\.1)[^*?/\n]* \(glob\)$', | |
213 | "glob match with no glob string (?, *, /, and 127.0.0.1)"), |
|
213 | "glob match with no glob string (?, *, /, and 127.0.0.1)"), | |
214 | ] |
|
214 | ] | |
215 | ] |
|
215 | ] | |
216 |
|
216 | |||
217 | for i in [0, 1]: |
|
217 | for i in [0, 1]: | |
218 | for tp in testpats[i]: |
|
218 | for tp in testpats[i]: | |
219 | p = tp[0] |
|
219 | p = tp[0] | |
220 | m = tp[1] |
|
220 | m = tp[1] | |
221 | if p.startswith(r'^'): |
|
221 | if p.startswith(r'^'): | |
222 | p = r"^ [$>] (%s)" % p[1:] |
|
222 | p = r"^ [$>] (%s)" % p[1:] | |
223 | else: |
|
223 | else: | |
224 | p = r"^ [$>] .*(%s)" % p |
|
224 | p = r"^ [$>] .*(%s)" % p | |
225 | utestpats[i].append((p, m) + tp[2:]) |
|
225 | utestpats[i].append((p, m) + tp[2:]) | |
226 |
|
226 | |||
227 | utestfilters = [ |
|
227 | utestfilters = [ | |
228 | (r"<<(\S+)((.|\n)*?\n > \1)", rephere), |
|
228 | (r"<<(\S+)((.|\n)*?\n > \1)", rephere), | |
229 | (r"( +)(#([^\n]*\S)?)", repcomment), |
|
229 | (r"( +)(#([^\n]*\S)?)", repcomment), | |
230 | ] |
|
230 | ] | |
231 |
|
231 | |||
232 | pypats = [ |
|
232 | pypats = [ | |
233 | [ |
|
233 | [ | |
234 | (r'^\s*def\s*\w+\s*\(.*,\s*\(', |
|
234 | (r'^\s*def\s*\w+\s*\(.*,\s*\(', | |
235 | "tuple parameter unpacking not available in Python 3+"), |
|
235 | "tuple parameter unpacking not available in Python 3+"), | |
236 | (r'lambda\s*\(.*,.*\)', |
|
236 | (r'lambda\s*\(.*,.*\)', | |
237 | "tuple parameter unpacking not available in Python 3+"), |
|
237 | "tuple parameter unpacking not available in Python 3+"), | |
238 | (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"), |
|
238 | (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"), | |
239 | (r'\breduce\s*\(.*', "reduce is not available in Python 3+"), |
|
239 | (r'\breduce\s*\(.*', "reduce is not available in Python 3+"), | |
240 | (r'\bdict\(.*=', 'dict() is different in Py2 and 3 and is slower than {}', |
|
240 | (r'\bdict\(.*=', 'dict() is different in Py2 and 3 and is slower than {}', | |
241 | 'dict-from-generator'), |
|
241 | 'dict-from-generator'), | |
242 | (r'\.has_key\b', "dict.has_key is not available in Python 3+"), |
|
242 | (r'\.has_key\b', "dict.has_key is not available in Python 3+"), | |
243 | (r'\s<>\s', '<> operator is not available in Python 3+, use !='), |
|
243 | (r'\s<>\s', '<> operator is not available in Python 3+, use !='), | |
244 | (r'^\s*\t', "don't use tabs"), |
|
244 | (r'^\s*\t', "don't use tabs"), | |
245 | (r'\S;\s*\n', "semicolon"), |
|
245 | (r'\S;\s*\n', "semicolon"), | |
246 | (r'[^_]_\([ \t\n]*(?:"[^"]+"[ \t\n+]*)+%', "don't use % inside _()"), |
|
246 | (r'[^_]_\([ \t\n]*(?:"[^"]+"[ \t\n+]*)+%', "don't use % inside _()"), | |
247 | (r"[^_]_\([ \t\n]*(?:'[^']+'[ \t\n+]*)+%", "don't use % inside _()"), |
|
247 | (r"[^_]_\([ \t\n]*(?:'[^']+'[ \t\n+]*)+%", "don't use % inside _()"), | |
248 | (r'(\w|\)),\w', "missing whitespace after ,"), |
|
248 | (r'(\w|\)),\w', "missing whitespace after ,"), | |
249 | (r'(\w|\))[+/*\-<>]\w', "missing whitespace in expression"), |
|
249 | (r'(\w|\))[+/*\-<>]\w', "missing whitespace in expression"), | |
250 | (r'^\s+(\w|\.)+=\w[^,()\n]*$', "missing whitespace in assignment"), |
|
250 | (r'^\s+(\w|\.)+=\w[^,()\n]*$', "missing whitespace in assignment"), | |
251 | (r'\w\s=\s\s+\w', "gratuitous whitespace after ="), |
|
251 | (r'\w\s=\s\s+\w', "gratuitous whitespace after ="), | |
252 | (r'.{81}', "line too long"), |
|
252 | (r'.{81}', "line too long"), | |
253 | (r'[^\n]\Z', "no trailing newline"), |
|
253 | (r'[^\n]\Z', "no trailing newline"), | |
254 | (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"), |
|
254 | (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"), | |
255 | # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', |
|
255 | # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', | |
256 | # "don't use underbars in identifiers"), |
|
256 | # "don't use underbars in identifiers"), | |
257 | (r'^\s+(self\.)?[A-za-z][a-z0-9]+[A-Z]\w* = ', |
|
257 | (r'^\s+(self\.)?[A-za-z][a-z0-9]+[A-Z]\w* = ', | |
258 | "don't use camelcase in identifiers"), |
|
258 | "don't use camelcase in identifiers"), | |
259 | (r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+', |
|
259 | (r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+', | |
260 | "linebreak after :"), |
|
260 | "linebreak after :"), | |
261 | (r'class\s[^( \n]+:', "old-style class, use class foo(object)", |
|
261 | (r'class\s[^( \n]+:', "old-style class, use class foo(object)", | |
262 | r'#.*old-style'), |
|
262 | r'#.*old-style'), | |
263 | (r'class\s[^( \n]+\(\):', |
|
263 | (r'class\s[^( \n]+\(\):', | |
264 | "class foo() creates old style object, use class foo(object)", |
|
264 | "class foo() creates old style object, use class foo(object)", | |
265 | r'#.*old-style'), |
|
265 | r'#.*old-style'), | |
266 | (r'\b(%s)\(' % '|'.join(k for k in keyword.kwlist |
|
266 | (r'\b(%s)\(' % '|'.join(k for k in keyword.kwlist | |
267 | if k not in ('print', 'exec')), |
|
267 | if k not in ('print', 'exec')), | |
268 | "Python keyword is not a function"), |
|
268 | "Python keyword is not a function"), | |
269 | (r',]', "unneeded trailing ',' in list"), |
|
269 | (r',]', "unneeded trailing ',' in list"), | |
270 | # (r'class\s[A-Z][^\(]*\((?!Exception)', |
|
270 | # (r'class\s[A-Z][^\(]*\((?!Exception)', | |
271 | # "don't capitalize non-exception classes"), |
|
271 | # "don't capitalize non-exception classes"), | |
272 | # (r'in range\(', "use xrange"), |
|
272 | # (r'in range\(', "use xrange"), | |
273 | # (r'^\s*print\s+', "avoid using print in core and extensions"), |
|
273 | # (r'^\s*print\s+', "avoid using print in core and extensions"), | |
274 | (r'[\x80-\xff]', "non-ASCII character literal"), |
|
274 | (r'[\x80-\xff]', "non-ASCII character literal"), | |
275 | (r'("\')\.format\(', "str.format() has no bytes counterpart, use %"), |
|
275 | (r'("\')\.format\(', "str.format() has no bytes counterpart, use %"), | |
276 | (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist), |
|
276 | (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist), | |
277 | "gratuitous whitespace after Python keyword"), |
|
277 | "gratuitous whitespace after Python keyword"), | |
278 | (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"), |
|
278 | (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"), | |
279 | # (r'\s\s=', "gratuitous whitespace before ="), |
|
279 | # (r'\s\s=', "gratuitous whitespace before ="), | |
280 | (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S', |
|
280 | (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S', | |
281 | "missing whitespace around operator"), |
|
281 | "missing whitespace around operator"), | |
282 | (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\s', |
|
282 | (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\s', | |
283 | "missing whitespace around operator"), |
|
283 | "missing whitespace around operator"), | |
284 | (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S', |
|
284 | (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S', | |
285 | "missing whitespace around operator"), |
|
285 | "missing whitespace around operator"), | |
286 | (r'[^^+=*/!<>&| %-](\s=|=\s)[^= ]', |
|
286 | (r'[^^+=*/!<>&| %-](\s=|=\s)[^= ]', | |
287 | "wrong whitespace around ="), |
|
287 | "wrong whitespace around ="), | |
288 | (r'\([^()]*( =[^=]|[^<>!=]= )', |
|
288 | (r'\([^()]*( =[^=]|[^<>!=]= )', | |
289 | "no whitespace around = for named parameters"), |
|
289 | "no whitespace around = for named parameters"), | |
290 | (r'raise Exception', "don't raise generic exceptions"), |
|
290 | (r'raise Exception', "don't raise generic exceptions"), | |
291 | (r'raise [^,(]+, (\([^\)]+\)|[^,\(\)]+)$', |
|
291 | (r'raise [^,(]+, (\([^\)]+\)|[^,\(\)]+)$', | |
292 | "don't use old-style two-argument raise, use Exception(message)"), |
|
292 | "don't use old-style two-argument raise, use Exception(message)"), | |
293 | (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"), |
|
293 | (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"), | |
294 | (r' [=!]=\s+(True|False|None)', |
|
294 | (r' [=!]=\s+(True|False|None)', | |
295 | "comparison with singleton, use 'is' or 'is not' instead"), |
|
295 | "comparison with singleton, use 'is' or 'is not' instead"), | |
296 | (r'^\s*(while|if) [01]:', |
|
296 | (r'^\s*(while|if) [01]:', | |
297 | "use True/False for constant Boolean expression"), |
|
297 | "use True/False for constant Boolean expression"), | |
298 | (r'(?:(?<!def)\s+|\()hasattr\(', |
|
298 | (r'(?:(?<!def)\s+|\()hasattr\(', | |
299 | 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'), |
|
299 | 'hasattr(foo, bar) is broken, use util.safehasattr(foo, bar) instead'), | |
300 | (r'opener\([^)]*\).read\(', |
|
300 | (r'opener\([^)]*\).read\(', | |
301 | "use opener.read() instead"), |
|
301 | "use opener.read() instead"), | |
302 | (r'opener\([^)]*\).write\(', |
|
302 | (r'opener\([^)]*\).write\(', | |
303 | "use opener.write() instead"), |
|
303 | "use opener.write() instead"), | |
304 | (r'[\s\(](open|file)\([^)]*\)\.read\(', |
|
304 | (r'[\s\(](open|file)\([^)]*\)\.read\(', | |
305 | "use util.readfile() instead"), |
|
305 | "use util.readfile() instead"), | |
306 | (r'[\s\(](open|file)\([^)]*\)\.write\(', |
|
306 | (r'[\s\(](open|file)\([^)]*\)\.write\(', | |
307 | "use util.writefile() instead"), |
|
307 | "use util.writefile() instead"), | |
308 | (r'^[\s\(]*(open(er)?|file)\([^)]*\)', |
|
308 | (r'^[\s\(]*(open(er)?|file)\([^)]*\)', | |
309 | "always assign an opened file to a variable, and close it afterwards"), |
|
309 | "always assign an opened file to a variable, and close it afterwards"), | |
310 | (r'[\s\(](open|file)\([^)]*\)\.', |
|
310 | (r'[\s\(](open|file)\([^)]*\)\.', | |
311 | "always assign an opened file to a variable, and close it afterwards"), |
|
311 | "always assign an opened file to a variable, and close it afterwards"), | |
312 | (r'(?i)descend[e]nt', "the proper spelling is descendAnt"), |
|
312 | (r'(?i)descend[e]nt', "the proper spelling is descendAnt"), | |
313 | (r'\.debug\(\_', "don't mark debug messages for translation"), |
|
313 | (r'\.debug\(\_', "don't mark debug messages for translation"), | |
314 | (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"), |
|
314 | (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"), | |
315 | (r'^\s*except\s*:', "naked except clause", r'#.*re-raises'), |
|
315 | (r'^\s*except\s*:', "naked except clause", r'#.*re-raises'), | |
316 | (r'^\s*except\s([^\(,]+|\([^\)]+\))\s*,', |
|
316 | (r'^\s*except\s([^\(,]+|\([^\)]+\))\s*,', | |
317 | 'legacy exception syntax; use "as" instead of ","'), |
|
317 | 'legacy exception syntax; use "as" instead of ","'), | |
318 | (r':\n( )*( ){1,3}[^ ]', "must indent 4 spaces"), |
|
318 | (r':\n( )*( ){1,3}[^ ]', "must indent 4 spaces"), | |
319 | (r'release\(.*wlock, .*lock\)', "wrong lock release order"), |
|
319 | (r'release\(.*wlock, .*lock\)', "wrong lock release order"), | |
320 | (r'\b__bool__\b', "__bool__ should be __nonzero__ in Python 2"), |
|
320 | (r'\b__bool__\b', "__bool__ should be __nonzero__ in Python 2"), | |
321 | (r'os\.path\.join\(.*, *(""|\'\')\)', |
|
321 | (r'os\.path\.join\(.*, *(""|\'\')\)', | |
322 | "use pathutil.normasprefix(path) instead of os.path.join(path, '')"), |
|
322 | "use pathutil.normasprefix(path) instead of os.path.join(path, '')"), | |
323 | (r'\s0[0-7]+\b', 'legacy octal syntax; use "0o" prefix instead of "0"'), |
|
323 | (r'\s0[0-7]+\b', 'legacy octal syntax; use "0o" prefix instead of "0"'), | |
324 | # XXX only catch mutable arguments on the first line of the definition |
|
324 | # XXX only catch mutable arguments on the first line of the definition | |
325 | (r'def.*[( ]\w+=\{\}', "don't use mutable default arguments"), |
|
325 | (r'def.*[( ]\w+=\{\}', "don't use mutable default arguments"), | |
326 | (r'\butil\.Abort\b', "directly use error.Abort"), |
|
326 | (r'\butil\.Abort\b', "directly use error.Abort"), | |
327 | (r'^import Queue', "don't use Queue, use util.queue + util.empty"), |
|
327 | (r'^import Queue', "don't use Queue, use util.queue + util.empty"), | |
328 | (r'^import cStringIO', "don't use cStringIO.StringIO, use util.stringio"), |
|
328 | (r'^import cStringIO', "don't use cStringIO.StringIO, use util.stringio"), | |
329 | (r'^import urllib', "don't use urllib, use util.urlreq/util.urlerr"), |
|
329 | (r'^import urllib', "don't use urllib, use util.urlreq/util.urlerr"), | |
330 | (r'^import SocketServer', "don't use SockerServer, use util.socketserver"), |
|
330 | (r'^import SocketServer', "don't use SockerServer, use util.socketserver"), | |
331 | (r'^import urlparse', "don't use urlparse, use util.urlparse"), |
|
331 | (r'^import urlparse', "don't use urlparse, use util.urlparse"), | |
332 | (r'^import xmlrpclib', "don't use xmlrpclib, use util.xmlrpclib"), |
|
332 | (r'^import xmlrpclib', "don't use xmlrpclib, use util.xmlrpclib"), | |
333 | (r'^import cPickle', "don't use cPickle, use util.pickle"), |
|
333 | (r'^import cPickle', "don't use cPickle, use util.pickle"), | |
334 | (r'^import pickle', "don't use pickle, use util.pickle"), |
|
334 | (r'^import pickle', "don't use pickle, use util.pickle"), | |
335 | (r'^import httplib', "don't use httplib, use util.httplib"), |
|
335 | (r'^import httplib', "don't use httplib, use util.httplib"), | |
336 | (r'^import BaseHTTPServer', "use util.httpserver instead"), |
|
336 | (r'^import BaseHTTPServer', "use util.httpserver instead"), | |
337 | (r'\.next\(\)', "don't use .next(), use next(...)"), |
|
337 | (r'\.next\(\)', "don't use .next(), use next(...)"), | |
338 |
|
338 | |||
339 | # rules depending on implementation of repquote() |
|
339 | # rules depending on implementation of repquote() | |
340 | (r' x+[xpqo%APM][\'"]\n\s+[\'"]x', |
|
340 | (r' x+[xpqo%APM][\'"]\n\s+[\'"]x', | |
341 | 'string join across lines with no space'), |
|
341 | 'string join across lines with no space'), | |
342 | (r'''(?x)ui\.(status|progress|write|note|warn)\( |
|
342 | (r'''(?x)ui\.(status|progress|write|note|warn)\( | |
343 | [ \t\n#]* |
|
343 | [ \t\n#]* | |
344 | (?# any strings/comments might precede a string, which |
|
344 | (?# any strings/comments might precede a string, which | |
345 | # contains translatable message) |
|
345 | # contains translatable message) | |
346 | ((['"]|\'\'\'|""")[ \npq%bAPMxno]*(['"]|\'\'\'|""")[ \t\n#]+)* |
|
346 | ((['"]|\'\'\'|""")[ \npq%bAPMxno]*(['"]|\'\'\'|""")[ \t\n#]+)* | |
347 | (?# sequence consisting of below might precede translatable message |
|
347 | (?# sequence consisting of below might precede translatable message | |
348 | # - formatting string: "% 10s", "%05d", "% -3.2f", "%*s", "%%" ... |
|
348 | # - formatting string: "% 10s", "%05d", "% -3.2f", "%*s", "%%" ... | |
349 | # - escaped character: "\\", "\n", "\0" ... |
|
349 | # - escaped character: "\\", "\n", "\0" ... | |
350 | # - character other than '%', 'b' as '\', and 'x' as alphabet) |
|
350 | # - character other than '%', 'b' as '\', and 'x' as alphabet) | |
351 | (['"]|\'\'\'|""") |
|
351 | (['"]|\'\'\'|""") | |
352 | ((%([ n]?[PM]?([np]+|A))?x)|%%|b[bnx]|[ \nnpqAPMo])*x |
|
352 | ((%([ n]?[PM]?([np]+|A))?x)|%%|b[bnx]|[ \nnpqAPMo])*x | |
353 | (?# this regexp can't use [^...] style, |
|
353 | (?# this regexp can't use [^...] style, | |
354 | # because _preparepats forcibly adds "\n" into [^...], |
|
354 | # because _preparepats forcibly adds "\n" into [^...], | |
355 | # even though this regexp wants match it against "\n")''', |
|
355 | # even though this regexp wants match it against "\n")''', | |
356 | "missing _() in ui message (use () to hide false-positives)"), |
|
356 | "missing _() in ui message (use () to hide false-positives)"), | |
357 | ], |
|
357 | ], | |
358 | # warnings |
|
358 | # warnings | |
359 | [ |
|
359 | [ | |
360 | # rules depending on implementation of repquote() |
|
360 | # rules depending on implementation of repquote() | |
361 | (r'(^| )pp +xxxxqq[ \n][^\n]', "add two newlines after '.. note::'"), |
|
361 | (r'(^| )pp +xxxxqq[ \n][^\n]', "add two newlines after '.. note::'"), | |
362 | ] |
|
362 | ] | |
363 | ] |
|
363 | ] | |
364 |
|
364 | |||
365 | pyfilters = [ |
|
365 | pyfilters = [ | |
366 | (r"""(?msx)(?P<comment>\#.*?$)| |
|
366 | (r"""(?msx)(?P<comment>\#.*?$)| | |
367 | ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!"))) |
|
367 | ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!"))) | |
368 | (?P<text>(([^\\]|\\.)*?)) |
|
368 | (?P<text>(([^\\]|\\.)*?)) | |
369 | (?P=quote))""", reppython), |
|
369 | (?P=quote))""", reppython), | |
370 | ] |
|
370 | ] | |
371 |
|
371 | |||
372 | txtfilters = [] |
|
372 | txtfilters = [] | |
373 |
|
373 | |||
374 | txtpats = [ |
|
374 | txtpats = [ | |
375 | [ |
|
375 | [ | |
376 | ('\s$', 'trailing whitespace'), |
|
376 | ('\s$', 'trailing whitespace'), | |
377 | ('.. note::[ \n][^\n]', 'add two newlines after note::') |
|
377 | ('.. note::[ \n][^\n]', 'add two newlines after note::') | |
378 | ], |
|
378 | ], | |
379 | [] |
|
379 | [] | |
380 | ] |
|
380 | ] | |
381 |
|
381 | |||
382 | cpats = [ |
|
382 | cpats = [ | |
383 | [ |
|
383 | [ | |
384 | (r'//', "don't use //-style comments"), |
|
384 | (r'//', "don't use //-style comments"), | |
385 | (r'^ ', "don't use spaces to indent"), |
|
385 | (r'^ ', "don't use spaces to indent"), | |
386 | (r'\S\t', "don't use tabs except for indent"), |
|
386 | (r'\S\t', "don't use tabs except for indent"), | |
387 | (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"), |
|
387 | (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"), | |
388 | (r'.{81}', "line too long"), |
|
388 | (r'.{81}', "line too long"), | |
389 | (r'(while|if|do|for)\(', "use space after while/if/do/for"), |
|
389 | (r'(while|if|do|for)\(', "use space after while/if/do/for"), | |
390 | (r'return\(', "return is not a function"), |
|
390 | (r'return\(', "return is not a function"), | |
391 | (r' ;', "no space before ;"), |
|
391 | (r' ;', "no space before ;"), | |
392 | (r'[^;] \)', "no space before )"), |
|
392 | (r'[^;] \)', "no space before )"), | |
393 | (r'[)][{]', "space between ) and {"), |
|
393 | (r'[)][{]', "space between ) and {"), | |
394 | (r'\w+\* \w+', "use int *foo, not int* foo"), |
|
394 | (r'\w+\* \w+', "use int *foo, not int* foo"), | |
395 | (r'\W\([^\)]+\) \w+', "use (int)foo, not (int) foo"), |
|
395 | (r'\W\([^\)]+\) \w+', "use (int)foo, not (int) foo"), | |
396 | (r'\w+ (\+\+|--)', "use foo++, not foo ++"), |
|
396 | (r'\w+ (\+\+|--)', "use foo++, not foo ++"), | |
397 | (r'\w,\w', "missing whitespace after ,"), |
|
397 | (r'\w,\w', "missing whitespace after ,"), | |
398 | (r'^[^#]\w[+/*]\w', "missing whitespace in expression"), |
|
398 | (r'^[^#]\w[+/*]\w', "missing whitespace in expression"), | |
399 | (r'\w\s=\s\s+\w', "gratuitous whitespace after ="), |
|
399 | (r'\w\s=\s\s+\w', "gratuitous whitespace after ="), | |
400 | (r'^#\s+\w', "use #foo, not # foo"), |
|
400 | (r'^#\s+\w', "use #foo, not # foo"), | |
401 | (r'[^\n]\Z', "no trailing newline"), |
|
401 | (r'[^\n]\Z', "no trailing newline"), | |
402 | (r'^\s*#import\b', "use only #include in standard C code"), |
|
402 | (r'^\s*#import\b', "use only #include in standard C code"), | |
403 | (r'strcpy\(', "don't use strcpy, use strlcpy or memcpy"), |
|
403 | (r'strcpy\(', "don't use strcpy, use strlcpy or memcpy"), | |
404 | (r'strcat\(', "don't use strcat"), |
|
404 | (r'strcat\(', "don't use strcat"), | |
405 |
|
405 | |||
406 | # rules depending on implementation of repquote() |
|
406 | # rules depending on implementation of repquote() | |
407 | ], |
|
407 | ], | |
408 | # warnings |
|
408 | # warnings | |
409 | [ |
|
409 | [ | |
410 | # rules depending on implementation of repquote() |
|
410 | # rules depending on implementation of repquote() | |
411 | ] |
|
411 | ] | |
412 | ] |
|
412 | ] | |
413 |
|
413 | |||
414 | cfilters = [ |
|
414 | cfilters = [ | |
415 | (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment), |
|
415 | (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment), | |
416 | (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote), |
|
416 | (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote), | |
417 | (r'''(#\s*include\s+<)([^>]+)>''', repinclude), |
|
417 | (r'''(#\s*include\s+<)([^>]+)>''', repinclude), | |
418 | (r'(\()([^)]+\))', repcallspaces), |
|
418 | (r'(\()([^)]+\))', repcallspaces), | |
419 | ] |
|
419 | ] | |
420 |
|
420 | |||
421 | inutilpats = [ |
|
421 | inutilpats = [ | |
422 | [ |
|
422 | [ | |
423 | (r'\bui\.', "don't use ui in util"), |
|
423 | (r'\bui\.', "don't use ui in util"), | |
424 | ], |
|
424 | ], | |
425 | # warnings |
|
425 | # warnings | |
426 | [] |
|
426 | [] | |
427 | ] |
|
427 | ] | |
428 |
|
428 | |||
429 | inrevlogpats = [ |
|
429 | inrevlogpats = [ | |
430 | [ |
|
430 | [ | |
431 | (r'\brepo\.', "don't use repo in revlog"), |
|
431 | (r'\brepo\.', "don't use repo in revlog"), | |
432 | ], |
|
432 | ], | |
433 | # warnings |
|
433 | # warnings | |
434 | [] |
|
434 | [] | |
435 | ] |
|
435 | ] | |
436 |
|
436 | |||
437 | webtemplatefilters = [] |
|
437 | webtemplatefilters = [] | |
438 |
|
438 | |||
439 | webtemplatepats = [ |
|
439 | webtemplatepats = [ | |
440 | [], |
|
440 | [], | |
441 | [ |
|
441 | [ | |
442 | (r'{desc(\|(?!websub|firstline)[^\|]*)+}', |
|
442 | (r'{desc(\|(?!websub|firstline)[^\|]*)+}', | |
443 | 'follow desc keyword with either firstline or websub'), |
|
443 | 'follow desc keyword with either firstline or websub'), | |
444 | ] |
|
444 | ] | |
445 | ] |
|
445 | ] | |
446 |
|
446 | |||
|
447 | allfilesfilters = [] | |||
|
448 | ||||
|
449 | allfilespats = [ | |||
|
450 | [ | |||
|
451 | (r'(http|https)://[a-zA-Z0-9./]*selenic.com/', | |||
|
452 | 'use mercurial-scm.org domain URL'), | |||
|
453 | ], | |||
|
454 | # warnings | |||
|
455 | [], | |||
|
456 | ] | |||
|
457 | ||||
447 | checks = [ |
|
458 | checks = [ | |
448 | ('python', r'.*\.(py|cgi)$', r'^#!.*python', pyfilters, pypats), |
|
459 | ('python', r'.*\.(py|cgi)$', r'^#!.*python', pyfilters, pypats), | |
449 | ('test script', r'(.*/)?test-[^.~]*$', '', testfilters, testpats), |
|
460 | ('test script', r'(.*/)?test-[^.~]*$', '', testfilters, testpats), | |
450 | ('c', r'.*\.[ch]$', '', cfilters, cpats), |
|
461 | ('c', r'.*\.[ch]$', '', cfilters, cpats), | |
451 | ('unified test', r'.*\.t$', '', utestfilters, utestpats), |
|
462 | ('unified test', r'.*\.t$', '', utestfilters, utestpats), | |
452 | ('layering violation repo in revlog', r'mercurial/revlog\.py', '', |
|
463 | ('layering violation repo in revlog', r'mercurial/revlog\.py', '', | |
453 | pyfilters, inrevlogpats), |
|
464 | pyfilters, inrevlogpats), | |
454 | ('layering violation ui in util', r'mercurial/util\.py', '', pyfilters, |
|
465 | ('layering violation ui in util', r'mercurial/util\.py', '', pyfilters, | |
455 | inutilpats), |
|
466 | inutilpats), | |
456 | ('txt', r'.*\.txt$', '', txtfilters, txtpats), |
|
467 | ('txt', r'.*\.txt$', '', txtfilters, txtpats), | |
457 | ('web template', r'mercurial/templates/.*\.tmpl', '', |
|
468 | ('web template', r'mercurial/templates/.*\.tmpl', '', | |
458 | webtemplatefilters, webtemplatepats), |
|
469 | webtemplatefilters, webtemplatepats), | |
|
470 | ('all except for .po', r'.*(?<!\.po)$', '', | |||
|
471 | allfilesfilters, allfilespats), | |||
459 | ] |
|
472 | ] | |
460 |
|
473 | |||
461 | def _preparepats(): |
|
474 | def _preparepats(): | |
462 | for c in checks: |
|
475 | for c in checks: | |
463 | failandwarn = c[-1] |
|
476 | failandwarn = c[-1] | |
464 | for pats in failandwarn: |
|
477 | for pats in failandwarn: | |
465 | for i, pseq in enumerate(pats): |
|
478 | for i, pseq in enumerate(pats): | |
466 | # fix-up regexes for multi-line searches |
|
479 | # fix-up regexes for multi-line searches | |
467 | p = pseq[0] |
|
480 | p = pseq[0] | |
468 | # \s doesn't match \n |
|
481 | # \s doesn't match \n | |
469 | p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p) |
|
482 | p = re.sub(r'(?<!\\)\\s', r'[ \\t]', p) | |
470 | # [^...] doesn't match newline |
|
483 | # [^...] doesn't match newline | |
471 | p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p) |
|
484 | p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p) | |
472 |
|
485 | |||
473 | pats[i] = (re.compile(p, re.MULTILINE),) + pseq[1:] |
|
486 | pats[i] = (re.compile(p, re.MULTILINE),) + pseq[1:] | |
474 | filters = c[3] |
|
487 | filters = c[3] | |
475 | for i, flt in enumerate(filters): |
|
488 | for i, flt in enumerate(filters): | |
476 | filters[i] = re.compile(flt[0]), flt[1] |
|
489 | filters[i] = re.compile(flt[0]), flt[1] | |
477 |
|
490 | |||
478 | class norepeatlogger(object): |
|
491 | class norepeatlogger(object): | |
479 | def __init__(self): |
|
492 | def __init__(self): | |
480 | self._lastseen = None |
|
493 | self._lastseen = None | |
481 |
|
494 | |||
482 | def log(self, fname, lineno, line, msg, blame): |
|
495 | def log(self, fname, lineno, line, msg, blame): | |
483 | """print error related a to given line of a given file. |
|
496 | """print error related a to given line of a given file. | |
484 |
|
497 | |||
485 | The faulty line will also be printed but only once in the case |
|
498 | The faulty line will also be printed but only once in the case | |
486 | of multiple errors. |
|
499 | of multiple errors. | |
487 |
|
500 | |||
488 | :fname: filename |
|
501 | :fname: filename | |
489 | :lineno: line number |
|
502 | :lineno: line number | |
490 | :line: actual content of the line |
|
503 | :line: actual content of the line | |
491 | :msg: error message |
|
504 | :msg: error message | |
492 | """ |
|
505 | """ | |
493 | msgid = fname, lineno, line |
|
506 | msgid = fname, lineno, line | |
494 | if msgid != self._lastseen: |
|
507 | if msgid != self._lastseen: | |
495 | if blame: |
|
508 | if blame: | |
496 | print("%s:%d (%s):" % (fname, lineno, blame)) |
|
509 | print("%s:%d (%s):" % (fname, lineno, blame)) | |
497 | else: |
|
510 | else: | |
498 | print("%s:%d:" % (fname, lineno)) |
|
511 | print("%s:%d:" % (fname, lineno)) | |
499 | print(" > %s" % line) |
|
512 | print(" > %s" % line) | |
500 | self._lastseen = msgid |
|
513 | self._lastseen = msgid | |
501 | print(" " + msg) |
|
514 | print(" " + msg) | |
502 |
|
515 | |||
503 | _defaultlogger = norepeatlogger() |
|
516 | _defaultlogger = norepeatlogger() | |
504 |
|
517 | |||
505 | def getblame(f): |
|
518 | def getblame(f): | |
506 | lines = [] |
|
519 | lines = [] | |
507 | for l in os.popen('hg annotate -un %s' % f): |
|
520 | for l in os.popen('hg annotate -un %s' % f): | |
508 | start, line = l.split(':', 1) |
|
521 | start, line = l.split(':', 1) | |
509 | user, rev = start.split() |
|
522 | user, rev = start.split() | |
510 | lines.append((line[1:-1], user, rev)) |
|
523 | lines.append((line[1:-1], user, rev)) | |
511 | return lines |
|
524 | return lines | |
512 |
|
525 | |||
513 | def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False, |
|
526 | def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False, | |
514 | blame=False, debug=False, lineno=True): |
|
527 | blame=False, debug=False, lineno=True): | |
515 | """checks style and portability of a given file |
|
528 | """checks style and portability of a given file | |
516 |
|
529 | |||
517 | :f: filepath |
|
530 | :f: filepath | |
518 | :logfunc: function used to report error |
|
531 | :logfunc: function used to report error | |
519 | logfunc(filename, linenumber, linecontent, errormessage) |
|
532 | logfunc(filename, linenumber, linecontent, errormessage) | |
520 | :maxerr: number of error to display before aborting. |
|
533 | :maxerr: number of error to display before aborting. | |
521 | Set to false (default) to report all errors |
|
534 | Set to false (default) to report all errors | |
522 |
|
535 | |||
523 | return True if no error is found, False otherwise. |
|
536 | return True if no error is found, False otherwise. | |
524 | """ |
|
537 | """ | |
525 | blamecache = None |
|
538 | blamecache = None | |
526 | result = True |
|
539 | result = True | |
527 |
|
540 | |||
528 | try: |
|
541 | try: | |
529 | with opentext(f) as fp: |
|
542 | with opentext(f) as fp: | |
530 | try: |
|
543 | try: | |
531 | pre = post = fp.read() |
|
544 | pre = post = fp.read() | |
532 | except UnicodeDecodeError as e: |
|
545 | except UnicodeDecodeError as e: | |
533 | print("%s while reading %s" % (e, f)) |
|
546 | print("%s while reading %s" % (e, f)) | |
534 | return result |
|
547 | return result | |
535 | except IOError as e: |
|
548 | except IOError as e: | |
536 | print("Skipping %s, %s" % (f, str(e).split(':', 1)[0])) |
|
549 | print("Skipping %s, %s" % (f, str(e).split(':', 1)[0])) | |
537 | return result |
|
550 | return result | |
538 |
|
551 | |||
539 | for name, match, magic, filters, pats in checks: |
|
552 | for name, match, magic, filters, pats in checks: | |
|
553 | post = pre # discard filtering result of previous check | |||
540 | if debug: |
|
554 | if debug: | |
541 | print(name, f) |
|
555 | print(name, f) | |
542 | fc = 0 |
|
556 | fc = 0 | |
543 | if not (re.match(match, f) or (magic and re.search(magic, pre))): |
|
557 | if not (re.match(match, f) or (magic and re.search(magic, pre))): | |
544 | if debug: |
|
558 | if debug: | |
545 | print("Skipping %s for %s it doesn't match %s" % ( |
|
559 | print("Skipping %s for %s it doesn't match %s" % ( | |
546 | name, match, f)) |
|
560 | name, match, f)) | |
547 | continue |
|
561 | continue | |
548 | if "no-" "check-code" in pre: |
|
562 | if "no-" "check-code" in pre: | |
549 | # If you're looking at this line, it's because a file has: |
|
563 | # If you're looking at this line, it's because a file has: | |
550 | # no- check- code |
|
564 | # no- check- code | |
551 | # but the reason to output skipping is to make life for |
|
565 | # but the reason to output skipping is to make life for | |
552 | # tests easier. So, instead of writing it with a normal |
|
566 | # tests easier. So, instead of writing it with a normal | |
553 | # spelling, we write it with the expected spelling from |
|
567 | # spelling, we write it with the expected spelling from | |
554 | # tests/test-check-code.t |
|
568 | # tests/test-check-code.t | |
555 | print("Skipping %s it has no-che?k-code (glob)" % f) |
|
569 | print("Skipping %s it has no-che?k-code (glob)" % f) | |
556 | return "Skip" # skip checking this file |
|
570 | return "Skip" # skip checking this file | |
557 | for p, r in filters: |
|
571 | for p, r in filters: | |
558 | post = re.sub(p, r, post) |
|
572 | post = re.sub(p, r, post) | |
559 | nerrs = len(pats[0]) # nerr elements are errors |
|
573 | nerrs = len(pats[0]) # nerr elements are errors | |
560 | if warnings: |
|
574 | if warnings: | |
561 | pats = pats[0] + pats[1] |
|
575 | pats = pats[0] + pats[1] | |
562 | else: |
|
576 | else: | |
563 | pats = pats[0] |
|
577 | pats = pats[0] | |
564 | # print post # uncomment to show filtered version |
|
578 | # print post # uncomment to show filtered version | |
565 |
|
579 | |||
566 | if debug: |
|
580 | if debug: | |
567 | print("Checking %s for %s" % (name, f)) |
|
581 | print("Checking %s for %s" % (name, f)) | |
568 |
|
582 | |||
569 | prelines = None |
|
583 | prelines = None | |
570 | errors = [] |
|
584 | errors = [] | |
571 | for i, pat in enumerate(pats): |
|
585 | for i, pat in enumerate(pats): | |
572 | if len(pat) == 3: |
|
586 | if len(pat) == 3: | |
573 | p, msg, ignore = pat |
|
587 | p, msg, ignore = pat | |
574 | else: |
|
588 | else: | |
575 | p, msg = pat |
|
589 | p, msg = pat | |
576 | ignore = None |
|
590 | ignore = None | |
577 | if i >= nerrs: |
|
591 | if i >= nerrs: | |
578 | msg = "warning: " + msg |
|
592 | msg = "warning: " + msg | |
579 |
|
593 | |||
580 | pos = 0 |
|
594 | pos = 0 | |
581 | n = 0 |
|
595 | n = 0 | |
582 | for m in p.finditer(post): |
|
596 | for m in p.finditer(post): | |
583 | if prelines is None: |
|
597 | if prelines is None: | |
584 | prelines = pre.splitlines() |
|
598 | prelines = pre.splitlines() | |
585 | postlines = post.splitlines(True) |
|
599 | postlines = post.splitlines(True) | |
586 |
|
600 | |||
587 | start = m.start() |
|
601 | start = m.start() | |
588 | while n < len(postlines): |
|
602 | while n < len(postlines): | |
589 | step = len(postlines[n]) |
|
603 | step = len(postlines[n]) | |
590 | if pos + step > start: |
|
604 | if pos + step > start: | |
591 | break |
|
605 | break | |
592 | pos += step |
|
606 | pos += step | |
593 | n += 1 |
|
607 | n += 1 | |
594 | l = prelines[n] |
|
608 | l = prelines[n] | |
595 |
|
609 | |||
596 | if ignore and re.search(ignore, l, re.MULTILINE): |
|
610 | if ignore and re.search(ignore, l, re.MULTILINE): | |
597 | if debug: |
|
611 | if debug: | |
598 | print("Skipping %s for %s:%s (ignore pattern)" % ( |
|
612 | print("Skipping %s for %s:%s (ignore pattern)" % ( | |
599 | name, f, n)) |
|
613 | name, f, n)) | |
600 | continue |
|
614 | continue | |
601 | bd = "" |
|
615 | bd = "" | |
602 | if blame: |
|
616 | if blame: | |
603 | bd = 'working directory' |
|
617 | bd = 'working directory' | |
604 | if not blamecache: |
|
618 | if not blamecache: | |
605 | blamecache = getblame(f) |
|
619 | blamecache = getblame(f) | |
606 | if n < len(blamecache): |
|
620 | if n < len(blamecache): | |
607 | bl, bu, br = blamecache[n] |
|
621 | bl, bu, br = blamecache[n] | |
608 | if bl == l: |
|
622 | if bl == l: | |
609 | bd = '%s@%s' % (bu, br) |
|
623 | bd = '%s@%s' % (bu, br) | |
610 |
|
624 | |||
611 | errors.append((f, lineno and n + 1, l, msg, bd)) |
|
625 | errors.append((f, lineno and n + 1, l, msg, bd)) | |
612 | result = False |
|
626 | result = False | |
613 |
|
627 | |||
614 | errors.sort() |
|
628 | errors.sort() | |
615 | for e in errors: |
|
629 | for e in errors: | |
616 | logfunc(*e) |
|
630 | logfunc(*e) | |
617 | fc += 1 |
|
631 | fc += 1 | |
618 | if maxerr and fc >= maxerr: |
|
632 | if maxerr and fc >= maxerr: | |
619 | print(" (too many errors, giving up)") |
|
633 | print(" (too many errors, giving up)") | |
620 | break |
|
634 | break | |
621 |
|
635 | |||
622 | return result |
|
636 | return result | |
623 |
|
637 | |||
624 | def main(): |
|
638 | def main(): | |
625 | parser = optparse.OptionParser("%prog [options] [files]") |
|
639 | parser = optparse.OptionParser("%prog [options] [files]") | |
626 | parser.add_option("-w", "--warnings", action="store_true", |
|
640 | parser.add_option("-w", "--warnings", action="store_true", | |
627 | help="include warning-level checks") |
|
641 | help="include warning-level checks") | |
628 | parser.add_option("-p", "--per-file", type="int", |
|
642 | parser.add_option("-p", "--per-file", type="int", | |
629 | help="max warnings per file") |
|
643 | help="max warnings per file") | |
630 | parser.add_option("-b", "--blame", action="store_true", |
|
644 | parser.add_option("-b", "--blame", action="store_true", | |
631 | help="use annotate to generate blame info") |
|
645 | help="use annotate to generate blame info") | |
632 | parser.add_option("", "--debug", action="store_true", |
|
646 | parser.add_option("", "--debug", action="store_true", | |
633 | help="show debug information") |
|
647 | help="show debug information") | |
634 | parser.add_option("", "--nolineno", action="store_false", |
|
648 | parser.add_option("", "--nolineno", action="store_false", | |
635 | dest='lineno', help="don't show line numbers") |
|
649 | dest='lineno', help="don't show line numbers") | |
636 |
|
650 | |||
637 | parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False, |
|
651 | parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False, | |
638 | lineno=True) |
|
652 | lineno=True) | |
639 | (options, args) = parser.parse_args() |
|
653 | (options, args) = parser.parse_args() | |
640 |
|
654 | |||
641 | if len(args) == 0: |
|
655 | if len(args) == 0: | |
642 | check = glob.glob("*") |
|
656 | check = glob.glob("*") | |
643 | else: |
|
657 | else: | |
644 | check = args |
|
658 | check = args | |
645 |
|
659 | |||
646 | _preparepats() |
|
660 | _preparepats() | |
647 |
|
661 | |||
648 | ret = 0 |
|
662 | ret = 0 | |
649 | for f in check: |
|
663 | for f in check: | |
650 | if not checkfile(f, maxerr=options.per_file, warnings=options.warnings, |
|
664 | if not checkfile(f, maxerr=options.per_file, warnings=options.warnings, | |
651 | blame=options.blame, debug=options.debug, |
|
665 | blame=options.blame, debug=options.debug, | |
652 | lineno=options.lineno): |
|
666 | lineno=options.lineno): | |
653 | ret = 1 |
|
667 | ret = 1 | |
654 | return ret |
|
668 | return ret | |
655 |
|
669 | |||
656 | if __name__ == "__main__": |
|
670 | if __name__ == "__main__": | |
657 | sys.exit(main()) |
|
671 | sys.exit(main()) |
@@ -1,1103 +1,1103 b'' | |||||
1 | # perf.py - performance test routines |
|
1 | # perf.py - performance test routines | |
2 | '''helper extension to measure performance''' |
|
2 | '''helper extension to measure performance''' | |
3 |
|
3 | |||
4 | # "historical portability" policy of perf.py: |
|
4 | # "historical portability" policy of perf.py: | |
5 | # |
|
5 | # | |
6 | # We have to do: |
|
6 | # We have to do: | |
7 | # - make perf.py "loadable" with as wide Mercurial version as possible |
|
7 | # - make perf.py "loadable" with as wide Mercurial version as possible | |
8 | # This doesn't mean that perf commands work correctly with that Mercurial. |
|
8 | # This doesn't mean that perf commands work correctly with that Mercurial. | |
9 | # BTW, perf.py itself has been available since 1.1 (or eb240755386d). |
|
9 | # BTW, perf.py itself has been available since 1.1 (or eb240755386d). | |
10 | # - make historical perf command work correctly with as wide Mercurial |
|
10 | # - make historical perf command work correctly with as wide Mercurial | |
11 | # version as possible |
|
11 | # version as possible | |
12 | # |
|
12 | # | |
13 | # We have to do, if possible with reasonable cost: |
|
13 | # We have to do, if possible with reasonable cost: | |
14 | # - make recent perf command for historical feature work correctly |
|
14 | # - make recent perf command for historical feature work correctly | |
15 | # with early Mercurial |
|
15 | # with early Mercurial | |
16 | # |
|
16 | # | |
17 | # We don't have to do: |
|
17 | # We don't have to do: | |
18 | # - make perf command for recent feature work correctly with early |
|
18 | # - make perf command for recent feature work correctly with early | |
19 | # Mercurial |
|
19 | # Mercurial | |
20 |
|
20 | |||
21 | from __future__ import absolute_import |
|
21 | from __future__ import absolute_import | |
22 | import functools |
|
22 | import functools | |
23 | import os |
|
23 | import os | |
24 | import random |
|
24 | import random | |
25 | import sys |
|
25 | import sys | |
26 | import time |
|
26 | import time | |
27 | from mercurial import ( |
|
27 | from mercurial import ( | |
28 | changegroup, |
|
28 | changegroup, | |
29 | cmdutil, |
|
29 | cmdutil, | |
30 | commands, |
|
30 | commands, | |
31 | copies, |
|
31 | copies, | |
32 | error, |
|
32 | error, | |
33 | extensions, |
|
33 | extensions, | |
34 | mdiff, |
|
34 | mdiff, | |
35 | merge, |
|
35 | merge, | |
36 | revlog, |
|
36 | revlog, | |
37 | util, |
|
37 | util, | |
38 | ) |
|
38 | ) | |
39 |
|
39 | |||
40 | # for "historical portability": |
|
40 | # for "historical portability": | |
41 | # try to import modules separately (in dict order), and ignore |
|
41 | # try to import modules separately (in dict order), and ignore | |
42 | # failure, because these aren't available with early Mercurial |
|
42 | # failure, because these aren't available with early Mercurial | |
43 | try: |
|
43 | try: | |
44 | from mercurial import branchmap # since 2.5 (or bcee63733aad) |
|
44 | from mercurial import branchmap # since 2.5 (or bcee63733aad) | |
45 | except ImportError: |
|
45 | except ImportError: | |
46 | pass |
|
46 | pass | |
47 | try: |
|
47 | try: | |
48 | from mercurial import obsolete # since 2.3 (or ad0d6c2b3279) |
|
48 | from mercurial import obsolete # since 2.3 (or ad0d6c2b3279) | |
49 | except ImportError: |
|
49 | except ImportError: | |
50 | pass |
|
50 | pass | |
51 | try: |
|
51 | try: | |
52 | from mercurial import repoview # since 2.5 (or 3a6ddacb7198) |
|
52 | from mercurial import repoview # since 2.5 (or 3a6ddacb7198) | |
53 | except ImportError: |
|
53 | except ImportError: | |
54 | pass |
|
54 | pass | |
55 | try: |
|
55 | try: | |
56 | from mercurial import scmutil # since 1.9 (or 8b252e826c68) |
|
56 | from mercurial import scmutil # since 1.9 (or 8b252e826c68) | |
57 | except ImportError: |
|
57 | except ImportError: | |
58 | pass |
|
58 | pass | |
59 |
|
59 | |||
60 | # for "historical portability": |
|
60 | # for "historical portability": | |
61 | # define util.safehasattr forcibly, because util.safehasattr has been |
|
61 | # define util.safehasattr forcibly, because util.safehasattr has been | |
62 | # available since 1.9.3 (or 94b200a11cf7) |
|
62 | # available since 1.9.3 (or 94b200a11cf7) | |
63 | _undefined = object() |
|
63 | _undefined = object() | |
64 | def safehasattr(thing, attr): |
|
64 | def safehasattr(thing, attr): | |
65 | return getattr(thing, attr, _undefined) is not _undefined |
|
65 | return getattr(thing, attr, _undefined) is not _undefined | |
66 | setattr(util, 'safehasattr', safehasattr) |
|
66 | setattr(util, 'safehasattr', safehasattr) | |
67 |
|
67 | |||
68 | # for "historical portability": |
|
68 | # for "historical portability": | |
69 | # use locally defined empty option list, if formatteropts isn't |
|
69 | # use locally defined empty option list, if formatteropts isn't | |
70 | # available, because commands.formatteropts has been available since |
|
70 | # available, because commands.formatteropts has been available since | |
71 | # 3.2 (or 7a7eed5176a4), even though formatting itself has been |
|
71 | # 3.2 (or 7a7eed5176a4), even though formatting itself has been | |
72 | # available since 2.2 (or ae5f92e154d3) |
|
72 | # available since 2.2 (or ae5f92e154d3) | |
73 | formatteropts = getattr(commands, "formatteropts", []) |
|
73 | formatteropts = getattr(commands, "formatteropts", []) | |
74 |
|
74 | |||
75 | # for "historical portability": |
|
75 | # for "historical portability": | |
76 | # use locally defined option list, if debugrevlogopts isn't available, |
|
76 | # use locally defined option list, if debugrevlogopts isn't available, | |
77 | # because commands.debugrevlogopts has been available since 3.7 (or |
|
77 | # because commands.debugrevlogopts has been available since 3.7 (or | |
78 | # 5606f7d0d063), even though cmdutil.openrevlog() has been available |
|
78 | # 5606f7d0d063), even though cmdutil.openrevlog() has been available | |
79 | # since 1.9 (or a79fea6b3e77). |
|
79 | # since 1.9 (or a79fea6b3e77). | |
80 | revlogopts = getattr(commands, "debugrevlogopts", [ |
|
80 | revlogopts = getattr(commands, "debugrevlogopts", [ | |
81 | ('c', 'changelog', False, ('open changelog')), |
|
81 | ('c', 'changelog', False, ('open changelog')), | |
82 | ('m', 'manifest', False, ('open manifest')), |
|
82 | ('m', 'manifest', False, ('open manifest')), | |
83 | ('', 'dir', False, ('open directory manifest')), |
|
83 | ('', 'dir', False, ('open directory manifest')), | |
84 | ]) |
|
84 | ]) | |
85 |
|
85 | |||
86 | cmdtable = {} |
|
86 | cmdtable = {} | |
87 |
|
87 | |||
88 | # for "historical portability": |
|
88 | # for "historical portability": | |
89 | # define parsealiases locally, because cmdutil.parsealiases has been |
|
89 | # define parsealiases locally, because cmdutil.parsealiases has been | |
90 | # available since 1.5 (or 6252852b4332) |
|
90 | # available since 1.5 (or 6252852b4332) | |
91 | def parsealiases(cmd): |
|
91 | def parsealiases(cmd): | |
92 | return cmd.lstrip("^").split("|") |
|
92 | return cmd.lstrip("^").split("|") | |
93 |
|
93 | |||
94 | if safehasattr(cmdutil, 'command'): |
|
94 | if safehasattr(cmdutil, 'command'): | |
95 | import inspect |
|
95 | import inspect | |
96 | command = cmdutil.command(cmdtable) |
|
96 | command = cmdutil.command(cmdtable) | |
97 | if 'norepo' not in inspect.getargspec(command)[0]: |
|
97 | if 'norepo' not in inspect.getargspec(command)[0]: | |
98 | # for "historical portability": |
|
98 | # for "historical portability": | |
99 | # wrap original cmdutil.command, because "norepo" option has |
|
99 | # wrap original cmdutil.command, because "norepo" option has | |
100 | # been available since 3.1 (or 75a96326cecb) |
|
100 | # been available since 3.1 (or 75a96326cecb) | |
101 | _command = command |
|
101 | _command = command | |
102 | def command(name, options=(), synopsis=None, norepo=False): |
|
102 | def command(name, options=(), synopsis=None, norepo=False): | |
103 | if norepo: |
|
103 | if norepo: | |
104 | commands.norepo += ' %s' % ' '.join(parsealiases(name)) |
|
104 | commands.norepo += ' %s' % ' '.join(parsealiases(name)) | |
105 | return _command(name, list(options), synopsis) |
|
105 | return _command(name, list(options), synopsis) | |
106 | else: |
|
106 | else: | |
107 | # for "historical portability": |
|
107 | # for "historical portability": | |
108 | # define "@command" annotation locally, because cmdutil.command |
|
108 | # define "@command" annotation locally, because cmdutil.command | |
109 | # has been available since 1.9 (or 2daa5179e73f) |
|
109 | # has been available since 1.9 (or 2daa5179e73f) | |
110 | def command(name, options=(), synopsis=None, norepo=False): |
|
110 | def command(name, options=(), synopsis=None, norepo=False): | |
111 | def decorator(func): |
|
111 | def decorator(func): | |
112 | if synopsis: |
|
112 | if synopsis: | |
113 | cmdtable[name] = func, list(options), synopsis |
|
113 | cmdtable[name] = func, list(options), synopsis | |
114 | else: |
|
114 | else: | |
115 | cmdtable[name] = func, list(options) |
|
115 | cmdtable[name] = func, list(options) | |
116 | if norepo: |
|
116 | if norepo: | |
117 | commands.norepo += ' %s' % ' '.join(parsealiases(name)) |
|
117 | commands.norepo += ' %s' % ' '.join(parsealiases(name)) | |
118 | return func |
|
118 | return func | |
119 | return decorator |
|
119 | return decorator | |
120 |
|
120 | |||
121 | def getlen(ui): |
|
121 | def getlen(ui): | |
122 | if ui.configbool("perf", "stub"): |
|
122 | if ui.configbool("perf", "stub"): | |
123 | return lambda x: 1 |
|
123 | return lambda x: 1 | |
124 | return len |
|
124 | return len | |
125 |
|
125 | |||
126 | def gettimer(ui, opts=None): |
|
126 | def gettimer(ui, opts=None): | |
127 | """return a timer function and formatter: (timer, formatter) |
|
127 | """return a timer function and formatter: (timer, formatter) | |
128 |
|
128 | |||
129 | This function exists to gather the creation of formatter in a single |
|
129 | This function exists to gather the creation of formatter in a single | |
130 | place instead of duplicating it in all performance commands.""" |
|
130 | place instead of duplicating it in all performance commands.""" | |
131 |
|
131 | |||
132 | # enforce an idle period before execution to counteract power management |
|
132 | # enforce an idle period before execution to counteract power management | |
133 | # experimental config: perf.presleep |
|
133 | # experimental config: perf.presleep | |
134 | time.sleep(getint(ui, "perf", "presleep", 1)) |
|
134 | time.sleep(getint(ui, "perf", "presleep", 1)) | |
135 |
|
135 | |||
136 | if opts is None: |
|
136 | if opts is None: | |
137 | opts = {} |
|
137 | opts = {} | |
138 | # redirect all to stderr |
|
138 | # redirect all to stderr | |
139 | ui = ui.copy() |
|
139 | ui = ui.copy() | |
140 | uifout = safeattrsetter(ui, 'fout', ignoremissing=True) |
|
140 | uifout = safeattrsetter(ui, 'fout', ignoremissing=True) | |
141 | if uifout: |
|
141 | if uifout: | |
142 | # for "historical portability": |
|
142 | # for "historical portability": | |
143 | # ui.fout/ferr have been available since 1.9 (or 4e1ccd4c2b6d) |
|
143 | # ui.fout/ferr have been available since 1.9 (or 4e1ccd4c2b6d) | |
144 | uifout.set(ui.ferr) |
|
144 | uifout.set(ui.ferr) | |
145 |
|
145 | |||
146 | # get a formatter |
|
146 | # get a formatter | |
147 | uiformatter = getattr(ui, 'formatter', None) |
|
147 | uiformatter = getattr(ui, 'formatter', None) | |
148 | if uiformatter: |
|
148 | if uiformatter: | |
149 | fm = uiformatter('perf', opts) |
|
149 | fm = uiformatter('perf', opts) | |
150 | else: |
|
150 | else: | |
151 | # for "historical portability": |
|
151 | # for "historical portability": | |
152 | # define formatter locally, because ui.formatter has been |
|
152 | # define formatter locally, because ui.formatter has been | |
153 | # available since 2.2 (or ae5f92e154d3) |
|
153 | # available since 2.2 (or ae5f92e154d3) | |
154 | from mercurial import node |
|
154 | from mercurial import node | |
155 | class defaultformatter(object): |
|
155 | class defaultformatter(object): | |
156 | """Minimized composition of baseformatter and plainformatter |
|
156 | """Minimized composition of baseformatter and plainformatter | |
157 | """ |
|
157 | """ | |
158 | def __init__(self, ui, topic, opts): |
|
158 | def __init__(self, ui, topic, opts): | |
159 | self._ui = ui |
|
159 | self._ui = ui | |
160 | if ui.debugflag: |
|
160 | if ui.debugflag: | |
161 | self.hexfunc = node.hex |
|
161 | self.hexfunc = node.hex | |
162 | else: |
|
162 | else: | |
163 | self.hexfunc = node.short |
|
163 | self.hexfunc = node.short | |
164 | def __nonzero__(self): |
|
164 | def __nonzero__(self): | |
165 | return False |
|
165 | return False | |
166 | def startitem(self): |
|
166 | def startitem(self): | |
167 | pass |
|
167 | pass | |
168 | def data(self, **data): |
|
168 | def data(self, **data): | |
169 | pass |
|
169 | pass | |
170 | def write(self, fields, deftext, *fielddata, **opts): |
|
170 | def write(self, fields, deftext, *fielddata, **opts): | |
171 | self._ui.write(deftext % fielddata, **opts) |
|
171 | self._ui.write(deftext % fielddata, **opts) | |
172 | def condwrite(self, cond, fields, deftext, *fielddata, **opts): |
|
172 | def condwrite(self, cond, fields, deftext, *fielddata, **opts): | |
173 | if cond: |
|
173 | if cond: | |
174 | self._ui.write(deftext % fielddata, **opts) |
|
174 | self._ui.write(deftext % fielddata, **opts) | |
175 | def plain(self, text, **opts): |
|
175 | def plain(self, text, **opts): | |
176 | self._ui.write(text, **opts) |
|
176 | self._ui.write(text, **opts) | |
177 | def end(self): |
|
177 | def end(self): | |
178 | pass |
|
178 | pass | |
179 | fm = defaultformatter(ui, 'perf', opts) |
|
179 | fm = defaultformatter(ui, 'perf', opts) | |
180 |
|
180 | |||
181 | # stub function, runs code only once instead of in a loop |
|
181 | # stub function, runs code only once instead of in a loop | |
182 | # experimental config: perf.stub |
|
182 | # experimental config: perf.stub | |
183 | if ui.configbool("perf", "stub"): |
|
183 | if ui.configbool("perf", "stub"): | |
184 | return functools.partial(stub_timer, fm), fm |
|
184 | return functools.partial(stub_timer, fm), fm | |
185 | return functools.partial(_timer, fm), fm |
|
185 | return functools.partial(_timer, fm), fm | |
186 |
|
186 | |||
187 | def stub_timer(fm, func, title=None): |
|
187 | def stub_timer(fm, func, title=None): | |
188 | func() |
|
188 | func() | |
189 |
|
189 | |||
190 | def _timer(fm, func, title=None): |
|
190 | def _timer(fm, func, title=None): | |
191 | results = [] |
|
191 | results = [] | |
192 | begin = time.time() |
|
192 | begin = time.time() | |
193 | count = 0 |
|
193 | count = 0 | |
194 | while True: |
|
194 | while True: | |
195 | ostart = os.times() |
|
195 | ostart = os.times() | |
196 | cstart = time.time() |
|
196 | cstart = time.time() | |
197 | r = func() |
|
197 | r = func() | |
198 | cstop = time.time() |
|
198 | cstop = time.time() | |
199 | ostop = os.times() |
|
199 | ostop = os.times() | |
200 | count += 1 |
|
200 | count += 1 | |
201 | a, b = ostart, ostop |
|
201 | a, b = ostart, ostop | |
202 | results.append((cstop - cstart, b[0] - a[0], b[1]-a[1])) |
|
202 | results.append((cstop - cstart, b[0] - a[0], b[1]-a[1])) | |
203 | if cstop - begin > 3 and count >= 100: |
|
203 | if cstop - begin > 3 and count >= 100: | |
204 | break |
|
204 | break | |
205 | if cstop - begin > 10 and count >= 3: |
|
205 | if cstop - begin > 10 and count >= 3: | |
206 | break |
|
206 | break | |
207 |
|
207 | |||
208 | fm.startitem() |
|
208 | fm.startitem() | |
209 |
|
209 | |||
210 | if title: |
|
210 | if title: | |
211 | fm.write('title', '! %s\n', title) |
|
211 | fm.write('title', '! %s\n', title) | |
212 | if r: |
|
212 | if r: | |
213 | fm.write('result', '! result: %s\n', r) |
|
213 | fm.write('result', '! result: %s\n', r) | |
214 | m = min(results) |
|
214 | m = min(results) | |
215 | fm.plain('!') |
|
215 | fm.plain('!') | |
216 | fm.write('wall', ' wall %f', m[0]) |
|
216 | fm.write('wall', ' wall %f', m[0]) | |
217 | fm.write('comb', ' comb %f', m[1] + m[2]) |
|
217 | fm.write('comb', ' comb %f', m[1] + m[2]) | |
218 | fm.write('user', ' user %f', m[1]) |
|
218 | fm.write('user', ' user %f', m[1]) | |
219 | fm.write('sys', ' sys %f', m[2]) |
|
219 | fm.write('sys', ' sys %f', m[2]) | |
220 | fm.write('count', ' (best of %d)', count) |
|
220 | fm.write('count', ' (best of %d)', count) | |
221 | fm.plain('\n') |
|
221 | fm.plain('\n') | |
222 |
|
222 | |||
223 | # utilities for historical portability |
|
223 | # utilities for historical portability | |
224 |
|
224 | |||
225 | def getint(ui, section, name, default): |
|
225 | def getint(ui, section, name, default): | |
226 | # for "historical portability": |
|
226 | # for "historical portability": | |
227 | # ui.configint has been available since 1.9 (or fa2b596db182) |
|
227 | # ui.configint has been available since 1.9 (or fa2b596db182) | |
228 | v = ui.config(section, name, None) |
|
228 | v = ui.config(section, name, None) | |
229 | if v is None: |
|
229 | if v is None: | |
230 | return default |
|
230 | return default | |
231 | try: |
|
231 | try: | |
232 | return int(v) |
|
232 | return int(v) | |
233 | except ValueError: |
|
233 | except ValueError: | |
234 | raise error.ConfigError(("%s.%s is not an integer ('%s')") |
|
234 | raise error.ConfigError(("%s.%s is not an integer ('%s')") | |
235 | % (section, name, v)) |
|
235 | % (section, name, v)) | |
236 |
|
236 | |||
237 | def safeattrsetter(obj, name, ignoremissing=False): |
|
237 | def safeattrsetter(obj, name, ignoremissing=False): | |
238 | """Ensure that 'obj' has 'name' attribute before subsequent setattr |
|
238 | """Ensure that 'obj' has 'name' attribute before subsequent setattr | |
239 |
|
239 | |||
240 | This function is aborted, if 'obj' doesn't have 'name' attribute |
|
240 | This function is aborted, if 'obj' doesn't have 'name' attribute | |
241 | at runtime. This avoids overlooking removal of an attribute, which |
|
241 | at runtime. This avoids overlooking removal of an attribute, which | |
242 | breaks assumption of performance measurement, in the future. |
|
242 | breaks assumption of performance measurement, in the future. | |
243 |
|
243 | |||
244 | This function returns the object to (1) assign a new value, and |
|
244 | This function returns the object to (1) assign a new value, and | |
245 | (2) restore an original value to the attribute. |
|
245 | (2) restore an original value to the attribute. | |
246 |
|
246 | |||
247 | If 'ignoremissing' is true, missing 'name' attribute doesn't cause |
|
247 | If 'ignoremissing' is true, missing 'name' attribute doesn't cause | |
248 | abortion, and this function returns None. This is useful to |
|
248 | abortion, and this function returns None. This is useful to | |
249 | examine an attribute, which isn't ensured in all Mercurial |
|
249 | examine an attribute, which isn't ensured in all Mercurial | |
250 | versions. |
|
250 | versions. | |
251 | """ |
|
251 | """ | |
252 | if not util.safehasattr(obj, name): |
|
252 | if not util.safehasattr(obj, name): | |
253 | if ignoremissing: |
|
253 | if ignoremissing: | |
254 | return None |
|
254 | return None | |
255 | raise error.Abort(("missing attribute %s of %s might break assumption" |
|
255 | raise error.Abort(("missing attribute %s of %s might break assumption" | |
256 | " of performance measurement") % (name, obj)) |
|
256 | " of performance measurement") % (name, obj)) | |
257 |
|
257 | |||
258 | origvalue = getattr(obj, name) |
|
258 | origvalue = getattr(obj, name) | |
259 | class attrutil(object): |
|
259 | class attrutil(object): | |
260 | def set(self, newvalue): |
|
260 | def set(self, newvalue): | |
261 | setattr(obj, name, newvalue) |
|
261 | setattr(obj, name, newvalue) | |
262 | def restore(self): |
|
262 | def restore(self): | |
263 | setattr(obj, name, origvalue) |
|
263 | setattr(obj, name, origvalue) | |
264 |
|
264 | |||
265 | return attrutil() |
|
265 | return attrutil() | |
266 |
|
266 | |||
267 | # utilities to examine each internal API changes |
|
267 | # utilities to examine each internal API changes | |
268 |
|
268 | |||
269 | def getbranchmapsubsettable(): |
|
269 | def getbranchmapsubsettable(): | |
270 | # for "historical portability": |
|
270 | # for "historical portability": | |
271 | # subsettable is defined in: |
|
271 | # subsettable is defined in: | |
272 | # - branchmap since 2.9 (or 175c6fd8cacc) |
|
272 | # - branchmap since 2.9 (or 175c6fd8cacc) | |
273 | # - repoview since 2.5 (or 59a9f18d4587) |
|
273 | # - repoview since 2.5 (or 59a9f18d4587) | |
274 | for mod in (branchmap, repoview): |
|
274 | for mod in (branchmap, repoview): | |
275 | subsettable = getattr(mod, 'subsettable', None) |
|
275 | subsettable = getattr(mod, 'subsettable', None) | |
276 | if subsettable: |
|
276 | if subsettable: | |
277 | return subsettable |
|
277 | return subsettable | |
278 |
|
278 | |||
279 | # bisecting in bcee63733aad::59a9f18d4587 can reach here (both |
|
279 | # bisecting in bcee63733aad::59a9f18d4587 can reach here (both | |
280 | # branchmap and repoview modules exist, but subsettable attribute |
|
280 | # branchmap and repoview modules exist, but subsettable attribute | |
281 | # doesn't) |
|
281 | # doesn't) | |
282 | raise error.Abort(("perfbranchmap not available with this Mercurial"), |
|
282 | raise error.Abort(("perfbranchmap not available with this Mercurial"), | |
283 | hint="use 2.5 or later") |
|
283 | hint="use 2.5 or later") | |
284 |
|
284 | |||
285 | def getsvfs(repo): |
|
285 | def getsvfs(repo): | |
286 | """Return appropriate object to access files under .hg/store |
|
286 | """Return appropriate object to access files under .hg/store | |
287 | """ |
|
287 | """ | |
288 | # for "historical portability": |
|
288 | # for "historical portability": | |
289 | # repo.svfs has been available since 2.3 (or 7034365089bf) |
|
289 | # repo.svfs has been available since 2.3 (or 7034365089bf) | |
290 | svfs = getattr(repo, 'svfs', None) |
|
290 | svfs = getattr(repo, 'svfs', None) | |
291 | if svfs: |
|
291 | if svfs: | |
292 | return svfs |
|
292 | return svfs | |
293 | else: |
|
293 | else: | |
294 | return getattr(repo, 'sopener') |
|
294 | return getattr(repo, 'sopener') | |
295 |
|
295 | |||
296 | def getvfs(repo): |
|
296 | def getvfs(repo): | |
297 | """Return appropriate object to access files under .hg |
|
297 | """Return appropriate object to access files under .hg | |
298 | """ |
|
298 | """ | |
299 | # for "historical portability": |
|
299 | # for "historical portability": | |
300 | # repo.vfs has been available since 2.3 (or 7034365089bf) |
|
300 | # repo.vfs has been available since 2.3 (or 7034365089bf) | |
301 | vfs = getattr(repo, 'vfs', None) |
|
301 | vfs = getattr(repo, 'vfs', None) | |
302 | if vfs: |
|
302 | if vfs: | |
303 | return vfs |
|
303 | return vfs | |
304 | else: |
|
304 | else: | |
305 | return getattr(repo, 'opener') |
|
305 | return getattr(repo, 'opener') | |
306 |
|
306 | |||
307 | def repocleartagscachefunc(repo): |
|
307 | def repocleartagscachefunc(repo): | |
308 | """Return the function to clear tags cache according to repo internal API |
|
308 | """Return the function to clear tags cache according to repo internal API | |
309 | """ |
|
309 | """ | |
310 | if util.safehasattr(repo, '_tagscache'): # since 2.0 (or 9dca7653b525) |
|
310 | if util.safehasattr(repo, '_tagscache'): # since 2.0 (or 9dca7653b525) | |
311 | # in this case, setattr(repo, '_tagscache', None) or so isn't |
|
311 | # in this case, setattr(repo, '_tagscache', None) or so isn't | |
312 | # correct way to clear tags cache, because existing code paths |
|
312 | # correct way to clear tags cache, because existing code paths | |
313 | # expect _tagscache to be a structured object. |
|
313 | # expect _tagscache to be a structured object. | |
314 | def clearcache(): |
|
314 | def clearcache(): | |
315 | # _tagscache has been filteredpropertycache since 2.5 (or |
|
315 | # _tagscache has been filteredpropertycache since 2.5 (or | |
316 | # 98c867ac1330), and delattr() can't work in such case |
|
316 | # 98c867ac1330), and delattr() can't work in such case | |
317 | if '_tagscache' in vars(repo): |
|
317 | if '_tagscache' in vars(repo): | |
318 | del repo.__dict__['_tagscache'] |
|
318 | del repo.__dict__['_tagscache'] | |
319 | return clearcache |
|
319 | return clearcache | |
320 |
|
320 | |||
321 | repotags = safeattrsetter(repo, '_tags', ignoremissing=True) |
|
321 | repotags = safeattrsetter(repo, '_tags', ignoremissing=True) | |
322 | if repotags: # since 1.4 (or 5614a628d173) |
|
322 | if repotags: # since 1.4 (or 5614a628d173) | |
323 | return lambda : repotags.set(None) |
|
323 | return lambda : repotags.set(None) | |
324 |
|
324 | |||
325 | repotagscache = safeattrsetter(repo, 'tagscache', ignoremissing=True) |
|
325 | repotagscache = safeattrsetter(repo, 'tagscache', ignoremissing=True) | |
326 | if repotagscache: # since 0.6 (or d7df759d0e97) |
|
326 | if repotagscache: # since 0.6 (or d7df759d0e97) | |
327 | return lambda : repotagscache.set(None) |
|
327 | return lambda : repotagscache.set(None) | |
328 |
|
328 | |||
329 | # Mercurial earlier than 0.6 (or d7df759d0e97) logically reaches |
|
329 | # Mercurial earlier than 0.6 (or d7df759d0e97) logically reaches | |
330 | # this point, but it isn't so problematic, because: |
|
330 | # this point, but it isn't so problematic, because: | |
331 | # - repo.tags of such Mercurial isn't "callable", and repo.tags() |
|
331 | # - repo.tags of such Mercurial isn't "callable", and repo.tags() | |
332 | # in perftags() causes failure soon |
|
332 | # in perftags() causes failure soon | |
333 | # - perf.py itself has been available since 1.1 (or eb240755386d) |
|
333 | # - perf.py itself has been available since 1.1 (or eb240755386d) | |
334 | raise error.Abort(("tags API of this hg command is unknown")) |
|
334 | raise error.Abort(("tags API of this hg command is unknown")) | |
335 |
|
335 | |||
336 | # perf commands |
|
336 | # perf commands | |
337 |
|
337 | |||
338 | @command('perfwalk', formatteropts) |
|
338 | @command('perfwalk', formatteropts) | |
339 | def perfwalk(ui, repo, *pats, **opts): |
|
339 | def perfwalk(ui, repo, *pats, **opts): | |
340 | timer, fm = gettimer(ui, opts) |
|
340 | timer, fm = gettimer(ui, opts) | |
341 | try: |
|
341 | try: | |
342 | m = scmutil.match(repo[None], pats, {}) |
|
342 | m = scmutil.match(repo[None], pats, {}) | |
343 | timer(lambda: len(list(repo.dirstate.walk(m, [], True, False)))) |
|
343 | timer(lambda: len(list(repo.dirstate.walk(m, [], True, False)))) | |
344 | except Exception: |
|
344 | except Exception: | |
345 | try: |
|
345 | try: | |
346 | m = scmutil.match(repo[None], pats, {}) |
|
346 | m = scmutil.match(repo[None], pats, {}) | |
347 | timer(lambda: len([b for a, b, c in repo.dirstate.statwalk([], m)])) |
|
347 | timer(lambda: len([b for a, b, c in repo.dirstate.statwalk([], m)])) | |
348 | except Exception: |
|
348 | except Exception: | |
349 | timer(lambda: len(list(cmdutil.walk(repo, pats, {})))) |
|
349 | timer(lambda: len(list(cmdutil.walk(repo, pats, {})))) | |
350 | fm.end() |
|
350 | fm.end() | |
351 |
|
351 | |||
352 | @command('perfannotate', formatteropts) |
|
352 | @command('perfannotate', formatteropts) | |
353 | def perfannotate(ui, repo, f, **opts): |
|
353 | def perfannotate(ui, repo, f, **opts): | |
354 | timer, fm = gettimer(ui, opts) |
|
354 | timer, fm = gettimer(ui, opts) | |
355 | fc = repo['.'][f] |
|
355 | fc = repo['.'][f] | |
356 | timer(lambda: len(fc.annotate(True))) |
|
356 | timer(lambda: len(fc.annotate(True))) | |
357 | fm.end() |
|
357 | fm.end() | |
358 |
|
358 | |||
359 | @command('perfstatus', |
|
359 | @command('perfstatus', | |
360 | [('u', 'unknown', False, |
|
360 | [('u', 'unknown', False, | |
361 | 'ask status to look for unknown files')] + formatteropts) |
|
361 | 'ask status to look for unknown files')] + formatteropts) | |
362 | def perfstatus(ui, repo, **opts): |
|
362 | def perfstatus(ui, repo, **opts): | |
363 | #m = match.always(repo.root, repo.getcwd()) |
|
363 | #m = match.always(repo.root, repo.getcwd()) | |
364 | #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, |
|
364 | #timer(lambda: sum(map(len, repo.dirstate.status(m, [], False, False, | |
365 | # False)))) |
|
365 | # False)))) | |
366 | timer, fm = gettimer(ui, opts) |
|
366 | timer, fm = gettimer(ui, opts) | |
367 | timer(lambda: sum(map(len, repo.status(unknown=opts['unknown'])))) |
|
367 | timer(lambda: sum(map(len, repo.status(unknown=opts['unknown'])))) | |
368 | fm.end() |
|
368 | fm.end() | |
369 |
|
369 | |||
370 | @command('perfaddremove', formatteropts) |
|
370 | @command('perfaddremove', formatteropts) | |
371 | def perfaddremove(ui, repo, **opts): |
|
371 | def perfaddremove(ui, repo, **opts): | |
372 | timer, fm = gettimer(ui, opts) |
|
372 | timer, fm = gettimer(ui, opts) | |
373 | try: |
|
373 | try: | |
374 | oldquiet = repo.ui.quiet |
|
374 | oldquiet = repo.ui.quiet | |
375 | repo.ui.quiet = True |
|
375 | repo.ui.quiet = True | |
376 | matcher = scmutil.match(repo[None]) |
|
376 | matcher = scmutil.match(repo[None]) | |
377 | timer(lambda: scmutil.addremove(repo, matcher, "", dry_run=True)) |
|
377 | timer(lambda: scmutil.addremove(repo, matcher, "", dry_run=True)) | |
378 | finally: |
|
378 | finally: | |
379 | repo.ui.quiet = oldquiet |
|
379 | repo.ui.quiet = oldquiet | |
380 | fm.end() |
|
380 | fm.end() | |
381 |
|
381 | |||
382 | def clearcaches(cl): |
|
382 | def clearcaches(cl): | |
383 | # behave somewhat consistently across internal API changes |
|
383 | # behave somewhat consistently across internal API changes | |
384 | if util.safehasattr(cl, 'clearcaches'): |
|
384 | if util.safehasattr(cl, 'clearcaches'): | |
385 | cl.clearcaches() |
|
385 | cl.clearcaches() | |
386 | elif util.safehasattr(cl, '_nodecache'): |
|
386 | elif util.safehasattr(cl, '_nodecache'): | |
387 | from mercurial.node import nullid, nullrev |
|
387 | from mercurial.node import nullid, nullrev | |
388 | cl._nodecache = {nullid: nullrev} |
|
388 | cl._nodecache = {nullid: nullrev} | |
389 | cl._nodepos = None |
|
389 | cl._nodepos = None | |
390 |
|
390 | |||
391 | @command('perfheads', formatteropts) |
|
391 | @command('perfheads', formatteropts) | |
392 | def perfheads(ui, repo, **opts): |
|
392 | def perfheads(ui, repo, **opts): | |
393 | timer, fm = gettimer(ui, opts) |
|
393 | timer, fm = gettimer(ui, opts) | |
394 | cl = repo.changelog |
|
394 | cl = repo.changelog | |
395 | def d(): |
|
395 | def d(): | |
396 | len(cl.headrevs()) |
|
396 | len(cl.headrevs()) | |
397 | clearcaches(cl) |
|
397 | clearcaches(cl) | |
398 | timer(d) |
|
398 | timer(d) | |
399 | fm.end() |
|
399 | fm.end() | |
400 |
|
400 | |||
401 | @command('perftags', formatteropts) |
|
401 | @command('perftags', formatteropts) | |
402 | def perftags(ui, repo, **opts): |
|
402 | def perftags(ui, repo, **opts): | |
403 | import mercurial.changelog |
|
403 | import mercurial.changelog | |
404 | import mercurial.manifest |
|
404 | import mercurial.manifest | |
405 | timer, fm = gettimer(ui, opts) |
|
405 | timer, fm = gettimer(ui, opts) | |
406 | svfs = getsvfs(repo) |
|
406 | svfs = getsvfs(repo) | |
407 | repocleartagscache = repocleartagscachefunc(repo) |
|
407 | repocleartagscache = repocleartagscachefunc(repo) | |
408 | def t(): |
|
408 | def t(): | |
409 | repo.changelog = mercurial.changelog.changelog(svfs) |
|
409 | repo.changelog = mercurial.changelog.changelog(svfs) | |
410 | repo.manifest = mercurial.manifest.manifest(svfs) |
|
410 | repo.manifestlog = mercurial.manifest.manifestlog(svfs, repo) | |
411 | repocleartagscache() |
|
411 | repocleartagscache() | |
412 | return len(repo.tags()) |
|
412 | return len(repo.tags()) | |
413 | timer(t) |
|
413 | timer(t) | |
414 | fm.end() |
|
414 | fm.end() | |
415 |
|
415 | |||
416 | @command('perfancestors', formatteropts) |
|
416 | @command('perfancestors', formatteropts) | |
417 | def perfancestors(ui, repo, **opts): |
|
417 | def perfancestors(ui, repo, **opts): | |
418 | timer, fm = gettimer(ui, opts) |
|
418 | timer, fm = gettimer(ui, opts) | |
419 | heads = repo.changelog.headrevs() |
|
419 | heads = repo.changelog.headrevs() | |
420 | def d(): |
|
420 | def d(): | |
421 | for a in repo.changelog.ancestors(heads): |
|
421 | for a in repo.changelog.ancestors(heads): | |
422 | pass |
|
422 | pass | |
423 | timer(d) |
|
423 | timer(d) | |
424 | fm.end() |
|
424 | fm.end() | |
425 |
|
425 | |||
426 | @command('perfancestorset', formatteropts) |
|
426 | @command('perfancestorset', formatteropts) | |
427 | def perfancestorset(ui, repo, revset, **opts): |
|
427 | def perfancestorset(ui, repo, revset, **opts): | |
428 | timer, fm = gettimer(ui, opts) |
|
428 | timer, fm = gettimer(ui, opts) | |
429 | revs = repo.revs(revset) |
|
429 | revs = repo.revs(revset) | |
430 | heads = repo.changelog.headrevs() |
|
430 | heads = repo.changelog.headrevs() | |
431 | def d(): |
|
431 | def d(): | |
432 | s = repo.changelog.ancestors(heads) |
|
432 | s = repo.changelog.ancestors(heads) | |
433 | for rev in revs: |
|
433 | for rev in revs: | |
434 | rev in s |
|
434 | rev in s | |
435 | timer(d) |
|
435 | timer(d) | |
436 | fm.end() |
|
436 | fm.end() | |
437 |
|
437 | |||
438 | @command('perfchangegroupchangelog', formatteropts + |
|
438 | @command('perfchangegroupchangelog', formatteropts + | |
439 | [('', 'version', '02', 'changegroup version'), |
|
439 | [('', 'version', '02', 'changegroup version'), | |
440 | ('r', 'rev', '', 'revisions to add to changegroup')]) |
|
440 | ('r', 'rev', '', 'revisions to add to changegroup')]) | |
441 | def perfchangegroupchangelog(ui, repo, version='02', rev=None, **opts): |
|
441 | def perfchangegroupchangelog(ui, repo, version='02', rev=None, **opts): | |
442 | """Benchmark producing a changelog group for a changegroup. |
|
442 | """Benchmark producing a changelog group for a changegroup. | |
443 |
|
443 | |||
444 | This measures the time spent processing the changelog during a |
|
444 | This measures the time spent processing the changelog during a | |
445 | bundle operation. This occurs during `hg bundle` and on a server |
|
445 | bundle operation. This occurs during `hg bundle` and on a server | |
446 | processing a `getbundle` wire protocol request (handles clones |
|
446 | processing a `getbundle` wire protocol request (handles clones | |
447 | and pull requests). |
|
447 | and pull requests). | |
448 |
|
448 | |||
449 | By default, all revisions are added to the changegroup. |
|
449 | By default, all revisions are added to the changegroup. | |
450 | """ |
|
450 | """ | |
451 | cl = repo.changelog |
|
451 | cl = repo.changelog | |
452 | revs = [cl.lookup(r) for r in repo.revs(rev or 'all()')] |
|
452 | revs = [cl.lookup(r) for r in repo.revs(rev or 'all()')] | |
453 | bundler = changegroup.getbundler(version, repo) |
|
453 | bundler = changegroup.getbundler(version, repo) | |
454 |
|
454 | |||
455 | def lookup(node): |
|
455 | def lookup(node): | |
456 | # The real bundler reads the revision in order to access the |
|
456 | # The real bundler reads the revision in order to access the | |
457 | # manifest node and files list. Do that here. |
|
457 | # manifest node and files list. Do that here. | |
458 | cl.read(node) |
|
458 | cl.read(node) | |
459 | return node |
|
459 | return node | |
460 |
|
460 | |||
461 | def d(): |
|
461 | def d(): | |
462 | for chunk in bundler.group(revs, cl, lookup): |
|
462 | for chunk in bundler.group(revs, cl, lookup): | |
463 | pass |
|
463 | pass | |
464 |
|
464 | |||
465 | timer, fm = gettimer(ui, opts) |
|
465 | timer, fm = gettimer(ui, opts) | |
466 | timer(d) |
|
466 | timer(d) | |
467 | fm.end() |
|
467 | fm.end() | |
468 |
|
468 | |||
469 | @command('perfdirs', formatteropts) |
|
469 | @command('perfdirs', formatteropts) | |
470 | def perfdirs(ui, repo, **opts): |
|
470 | def perfdirs(ui, repo, **opts): | |
471 | timer, fm = gettimer(ui, opts) |
|
471 | timer, fm = gettimer(ui, opts) | |
472 | dirstate = repo.dirstate |
|
472 | dirstate = repo.dirstate | |
473 | 'a' in dirstate |
|
473 | 'a' in dirstate | |
474 | def d(): |
|
474 | def d(): | |
475 | dirstate.dirs() |
|
475 | dirstate.dirs() | |
476 | del dirstate._dirs |
|
476 | del dirstate._dirs | |
477 | timer(d) |
|
477 | timer(d) | |
478 | fm.end() |
|
478 | fm.end() | |
479 |
|
479 | |||
480 | @command('perfdirstate', formatteropts) |
|
480 | @command('perfdirstate', formatteropts) | |
481 | def perfdirstate(ui, repo, **opts): |
|
481 | def perfdirstate(ui, repo, **opts): | |
482 | timer, fm = gettimer(ui, opts) |
|
482 | timer, fm = gettimer(ui, opts) | |
483 | "a" in repo.dirstate |
|
483 | "a" in repo.dirstate | |
484 | def d(): |
|
484 | def d(): | |
485 | repo.dirstate.invalidate() |
|
485 | repo.dirstate.invalidate() | |
486 | "a" in repo.dirstate |
|
486 | "a" in repo.dirstate | |
487 | timer(d) |
|
487 | timer(d) | |
488 | fm.end() |
|
488 | fm.end() | |
489 |
|
489 | |||
490 | @command('perfdirstatedirs', formatteropts) |
|
490 | @command('perfdirstatedirs', formatteropts) | |
491 | def perfdirstatedirs(ui, repo, **opts): |
|
491 | def perfdirstatedirs(ui, repo, **opts): | |
492 | timer, fm = gettimer(ui, opts) |
|
492 | timer, fm = gettimer(ui, opts) | |
493 | "a" in repo.dirstate |
|
493 | "a" in repo.dirstate | |
494 | def d(): |
|
494 | def d(): | |
495 | "a" in repo.dirstate._dirs |
|
495 | "a" in repo.dirstate._dirs | |
496 | del repo.dirstate._dirs |
|
496 | del repo.dirstate._dirs | |
497 | timer(d) |
|
497 | timer(d) | |
498 | fm.end() |
|
498 | fm.end() | |
499 |
|
499 | |||
500 | @command('perfdirstatefoldmap', formatteropts) |
|
500 | @command('perfdirstatefoldmap', formatteropts) | |
501 | def perfdirstatefoldmap(ui, repo, **opts): |
|
501 | def perfdirstatefoldmap(ui, repo, **opts): | |
502 | timer, fm = gettimer(ui, opts) |
|
502 | timer, fm = gettimer(ui, opts) | |
503 | dirstate = repo.dirstate |
|
503 | dirstate = repo.dirstate | |
504 | 'a' in dirstate |
|
504 | 'a' in dirstate | |
505 | def d(): |
|
505 | def d(): | |
506 | dirstate._filefoldmap.get('a') |
|
506 | dirstate._filefoldmap.get('a') | |
507 | del dirstate._filefoldmap |
|
507 | del dirstate._filefoldmap | |
508 | timer(d) |
|
508 | timer(d) | |
509 | fm.end() |
|
509 | fm.end() | |
510 |
|
510 | |||
511 | @command('perfdirfoldmap', formatteropts) |
|
511 | @command('perfdirfoldmap', formatteropts) | |
512 | def perfdirfoldmap(ui, repo, **opts): |
|
512 | def perfdirfoldmap(ui, repo, **opts): | |
513 | timer, fm = gettimer(ui, opts) |
|
513 | timer, fm = gettimer(ui, opts) | |
514 | dirstate = repo.dirstate |
|
514 | dirstate = repo.dirstate | |
515 | 'a' in dirstate |
|
515 | 'a' in dirstate | |
516 | def d(): |
|
516 | def d(): | |
517 | dirstate._dirfoldmap.get('a') |
|
517 | dirstate._dirfoldmap.get('a') | |
518 | del dirstate._dirfoldmap |
|
518 | del dirstate._dirfoldmap | |
519 | del dirstate._dirs |
|
519 | del dirstate._dirs | |
520 | timer(d) |
|
520 | timer(d) | |
521 | fm.end() |
|
521 | fm.end() | |
522 |
|
522 | |||
523 | @command('perfdirstatewrite', formatteropts) |
|
523 | @command('perfdirstatewrite', formatteropts) | |
524 | def perfdirstatewrite(ui, repo, **opts): |
|
524 | def perfdirstatewrite(ui, repo, **opts): | |
525 | timer, fm = gettimer(ui, opts) |
|
525 | timer, fm = gettimer(ui, opts) | |
526 | ds = repo.dirstate |
|
526 | ds = repo.dirstate | |
527 | "a" in ds |
|
527 | "a" in ds | |
528 | def d(): |
|
528 | def d(): | |
529 | ds._dirty = True |
|
529 | ds._dirty = True | |
530 | ds.write(repo.currenttransaction()) |
|
530 | ds.write(repo.currenttransaction()) | |
531 | timer(d) |
|
531 | timer(d) | |
532 | fm.end() |
|
532 | fm.end() | |
533 |
|
533 | |||
534 | @command('perfmergecalculate', |
|
534 | @command('perfmergecalculate', | |
535 | [('r', 'rev', '.', 'rev to merge against')] + formatteropts) |
|
535 | [('r', 'rev', '.', 'rev to merge against')] + formatteropts) | |
536 | def perfmergecalculate(ui, repo, rev, **opts): |
|
536 | def perfmergecalculate(ui, repo, rev, **opts): | |
537 | timer, fm = gettimer(ui, opts) |
|
537 | timer, fm = gettimer(ui, opts) | |
538 | wctx = repo[None] |
|
538 | wctx = repo[None] | |
539 | rctx = scmutil.revsingle(repo, rev, rev) |
|
539 | rctx = scmutil.revsingle(repo, rev, rev) | |
540 | ancestor = wctx.ancestor(rctx) |
|
540 | ancestor = wctx.ancestor(rctx) | |
541 | # we don't want working dir files to be stat'd in the benchmark, so prime |
|
541 | # we don't want working dir files to be stat'd in the benchmark, so prime | |
542 | # that cache |
|
542 | # that cache | |
543 | wctx.dirty() |
|
543 | wctx.dirty() | |
544 | def d(): |
|
544 | def d(): | |
545 | # acceptremote is True because we don't want prompts in the middle of |
|
545 | # acceptremote is True because we don't want prompts in the middle of | |
546 | # our benchmark |
|
546 | # our benchmark | |
547 | merge.calculateupdates(repo, wctx, rctx, [ancestor], False, False, |
|
547 | merge.calculateupdates(repo, wctx, rctx, [ancestor], False, False, | |
548 | acceptremote=True, followcopies=True) |
|
548 | acceptremote=True, followcopies=True) | |
549 | timer(d) |
|
549 | timer(d) | |
550 | fm.end() |
|
550 | fm.end() | |
551 |
|
551 | |||
552 | @command('perfpathcopies', [], "REV REV") |
|
552 | @command('perfpathcopies', [], "REV REV") | |
553 | def perfpathcopies(ui, repo, rev1, rev2, **opts): |
|
553 | def perfpathcopies(ui, repo, rev1, rev2, **opts): | |
554 | timer, fm = gettimer(ui, opts) |
|
554 | timer, fm = gettimer(ui, opts) | |
555 | ctx1 = scmutil.revsingle(repo, rev1, rev1) |
|
555 | ctx1 = scmutil.revsingle(repo, rev1, rev1) | |
556 | ctx2 = scmutil.revsingle(repo, rev2, rev2) |
|
556 | ctx2 = scmutil.revsingle(repo, rev2, rev2) | |
557 | def d(): |
|
557 | def d(): | |
558 | copies.pathcopies(ctx1, ctx2) |
|
558 | copies.pathcopies(ctx1, ctx2) | |
559 | timer(d) |
|
559 | timer(d) | |
560 | fm.end() |
|
560 | fm.end() | |
561 |
|
561 | |||
562 | @command('perfmanifest', [], 'REV') |
|
562 | @command('perfmanifest', [], 'REV') | |
563 | def perfmanifest(ui, repo, rev, **opts): |
|
563 | def perfmanifest(ui, repo, rev, **opts): | |
564 | timer, fm = gettimer(ui, opts) |
|
564 | timer, fm = gettimer(ui, opts) | |
565 | ctx = scmutil.revsingle(repo, rev, rev) |
|
565 | ctx = scmutil.revsingle(repo, rev, rev) | |
566 | t = ctx.manifestnode() |
|
566 | t = ctx.manifestnode() | |
567 | def d(): |
|
567 | def d(): | |
568 | repo.manifest.clearcaches() |
|
568 | repo.manifest.clearcaches() | |
569 | repo.manifest.read(t) |
|
569 | repo.manifest.read(t) | |
570 | timer(d) |
|
570 | timer(d) | |
571 | fm.end() |
|
571 | fm.end() | |
572 |
|
572 | |||
573 | @command('perfchangeset', formatteropts) |
|
573 | @command('perfchangeset', formatteropts) | |
574 | def perfchangeset(ui, repo, rev, **opts): |
|
574 | def perfchangeset(ui, repo, rev, **opts): | |
575 | timer, fm = gettimer(ui, opts) |
|
575 | timer, fm = gettimer(ui, opts) | |
576 | n = repo[rev].node() |
|
576 | n = repo[rev].node() | |
577 | def d(): |
|
577 | def d(): | |
578 | repo.changelog.read(n) |
|
578 | repo.changelog.read(n) | |
579 | #repo.changelog._cache = None |
|
579 | #repo.changelog._cache = None | |
580 | timer(d) |
|
580 | timer(d) | |
581 | fm.end() |
|
581 | fm.end() | |
582 |
|
582 | |||
583 | @command('perfindex', formatteropts) |
|
583 | @command('perfindex', formatteropts) | |
584 | def perfindex(ui, repo, **opts): |
|
584 | def perfindex(ui, repo, **opts): | |
585 | import mercurial.revlog |
|
585 | import mercurial.revlog | |
586 | timer, fm = gettimer(ui, opts) |
|
586 | timer, fm = gettimer(ui, opts) | |
587 | mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg |
|
587 | mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg | |
588 | n = repo["tip"].node() |
|
588 | n = repo["tip"].node() | |
589 | svfs = getsvfs(repo) |
|
589 | svfs = getsvfs(repo) | |
590 | def d(): |
|
590 | def d(): | |
591 | cl = mercurial.revlog.revlog(svfs, "00changelog.i") |
|
591 | cl = mercurial.revlog.revlog(svfs, "00changelog.i") | |
592 | cl.rev(n) |
|
592 | cl.rev(n) | |
593 | timer(d) |
|
593 | timer(d) | |
594 | fm.end() |
|
594 | fm.end() | |
595 |
|
595 | |||
596 | @command('perfstartup', formatteropts) |
|
596 | @command('perfstartup', formatteropts) | |
597 | def perfstartup(ui, repo, **opts): |
|
597 | def perfstartup(ui, repo, **opts): | |
598 | timer, fm = gettimer(ui, opts) |
|
598 | timer, fm = gettimer(ui, opts) | |
599 | cmd = sys.argv[0] |
|
599 | cmd = sys.argv[0] | |
600 | def d(): |
|
600 | def d(): | |
601 | if os.name != 'nt': |
|
601 | if os.name != 'nt': | |
602 | os.system("HGRCPATH= %s version -q > /dev/null" % cmd) |
|
602 | os.system("HGRCPATH= %s version -q > /dev/null" % cmd) | |
603 | else: |
|
603 | else: | |
604 | os.environ['HGRCPATH'] = '' |
|
604 | os.environ['HGRCPATH'] = '' | |
605 | os.system("%s version -q > NUL" % cmd) |
|
605 | os.system("%s version -q > NUL" % cmd) | |
606 | timer(d) |
|
606 | timer(d) | |
607 | fm.end() |
|
607 | fm.end() | |
608 |
|
608 | |||
609 | @command('perfparents', formatteropts) |
|
609 | @command('perfparents', formatteropts) | |
610 | def perfparents(ui, repo, **opts): |
|
610 | def perfparents(ui, repo, **opts): | |
611 | timer, fm = gettimer(ui, opts) |
|
611 | timer, fm = gettimer(ui, opts) | |
612 | # control the number of commits perfparents iterates over |
|
612 | # control the number of commits perfparents iterates over | |
613 | # experimental config: perf.parentscount |
|
613 | # experimental config: perf.parentscount | |
614 | count = getint(ui, "perf", "parentscount", 1000) |
|
614 | count = getint(ui, "perf", "parentscount", 1000) | |
615 | if len(repo.changelog) < count: |
|
615 | if len(repo.changelog) < count: | |
616 | raise error.Abort("repo needs %d commits for this test" % count) |
|
616 | raise error.Abort("repo needs %d commits for this test" % count) | |
617 | repo = repo.unfiltered() |
|
617 | repo = repo.unfiltered() | |
618 | nl = [repo.changelog.node(i) for i in xrange(count)] |
|
618 | nl = [repo.changelog.node(i) for i in xrange(count)] | |
619 | def d(): |
|
619 | def d(): | |
620 | for n in nl: |
|
620 | for n in nl: | |
621 | repo.changelog.parents(n) |
|
621 | repo.changelog.parents(n) | |
622 | timer(d) |
|
622 | timer(d) | |
623 | fm.end() |
|
623 | fm.end() | |
624 |
|
624 | |||
625 | @command('perfctxfiles', formatteropts) |
|
625 | @command('perfctxfiles', formatteropts) | |
626 | def perfctxfiles(ui, repo, x, **opts): |
|
626 | def perfctxfiles(ui, repo, x, **opts): | |
627 | x = int(x) |
|
627 | x = int(x) | |
628 | timer, fm = gettimer(ui, opts) |
|
628 | timer, fm = gettimer(ui, opts) | |
629 | def d(): |
|
629 | def d(): | |
630 | len(repo[x].files()) |
|
630 | len(repo[x].files()) | |
631 | timer(d) |
|
631 | timer(d) | |
632 | fm.end() |
|
632 | fm.end() | |
633 |
|
633 | |||
634 | @command('perfrawfiles', formatteropts) |
|
634 | @command('perfrawfiles', formatteropts) | |
635 | def perfrawfiles(ui, repo, x, **opts): |
|
635 | def perfrawfiles(ui, repo, x, **opts): | |
636 | x = int(x) |
|
636 | x = int(x) | |
637 | timer, fm = gettimer(ui, opts) |
|
637 | timer, fm = gettimer(ui, opts) | |
638 | cl = repo.changelog |
|
638 | cl = repo.changelog | |
639 | def d(): |
|
639 | def d(): | |
640 | len(cl.read(x)[3]) |
|
640 | len(cl.read(x)[3]) | |
641 | timer(d) |
|
641 | timer(d) | |
642 | fm.end() |
|
642 | fm.end() | |
643 |
|
643 | |||
644 | @command('perflookup', formatteropts) |
|
644 | @command('perflookup', formatteropts) | |
645 | def perflookup(ui, repo, rev, **opts): |
|
645 | def perflookup(ui, repo, rev, **opts): | |
646 | timer, fm = gettimer(ui, opts) |
|
646 | timer, fm = gettimer(ui, opts) | |
647 | timer(lambda: len(repo.lookup(rev))) |
|
647 | timer(lambda: len(repo.lookup(rev))) | |
648 | fm.end() |
|
648 | fm.end() | |
649 |
|
649 | |||
650 | @command('perfrevrange', formatteropts) |
|
650 | @command('perfrevrange', formatteropts) | |
651 | def perfrevrange(ui, repo, *specs, **opts): |
|
651 | def perfrevrange(ui, repo, *specs, **opts): | |
652 | timer, fm = gettimer(ui, opts) |
|
652 | timer, fm = gettimer(ui, opts) | |
653 | revrange = scmutil.revrange |
|
653 | revrange = scmutil.revrange | |
654 | timer(lambda: len(revrange(repo, specs))) |
|
654 | timer(lambda: len(revrange(repo, specs))) | |
655 | fm.end() |
|
655 | fm.end() | |
656 |
|
656 | |||
657 | @command('perfnodelookup', formatteropts) |
|
657 | @command('perfnodelookup', formatteropts) | |
658 | def perfnodelookup(ui, repo, rev, **opts): |
|
658 | def perfnodelookup(ui, repo, rev, **opts): | |
659 | timer, fm = gettimer(ui, opts) |
|
659 | timer, fm = gettimer(ui, opts) | |
660 | import mercurial.revlog |
|
660 | import mercurial.revlog | |
661 | mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg |
|
661 | mercurial.revlog._prereadsize = 2**24 # disable lazy parser in old hg | |
662 | n = repo[rev].node() |
|
662 | n = repo[rev].node() | |
663 | cl = mercurial.revlog.revlog(getsvfs(repo), "00changelog.i") |
|
663 | cl = mercurial.revlog.revlog(getsvfs(repo), "00changelog.i") | |
664 | def d(): |
|
664 | def d(): | |
665 | cl.rev(n) |
|
665 | cl.rev(n) | |
666 | clearcaches(cl) |
|
666 | clearcaches(cl) | |
667 | timer(d) |
|
667 | timer(d) | |
668 | fm.end() |
|
668 | fm.end() | |
669 |
|
669 | |||
670 | @command('perflog', |
|
670 | @command('perflog', | |
671 | [('', 'rename', False, 'ask log to follow renames')] + formatteropts) |
|
671 | [('', 'rename', False, 'ask log to follow renames')] + formatteropts) | |
672 | def perflog(ui, repo, rev=None, **opts): |
|
672 | def perflog(ui, repo, rev=None, **opts): | |
673 | if rev is None: |
|
673 | if rev is None: | |
674 | rev=[] |
|
674 | rev=[] | |
675 | timer, fm = gettimer(ui, opts) |
|
675 | timer, fm = gettimer(ui, opts) | |
676 | ui.pushbuffer() |
|
676 | ui.pushbuffer() | |
677 | timer(lambda: commands.log(ui, repo, rev=rev, date='', user='', |
|
677 | timer(lambda: commands.log(ui, repo, rev=rev, date='', user='', | |
678 | copies=opts.get('rename'))) |
|
678 | copies=opts.get('rename'))) | |
679 | ui.popbuffer() |
|
679 | ui.popbuffer() | |
680 | fm.end() |
|
680 | fm.end() | |
681 |
|
681 | |||
682 | @command('perfmoonwalk', formatteropts) |
|
682 | @command('perfmoonwalk', formatteropts) | |
683 | def perfmoonwalk(ui, repo, **opts): |
|
683 | def perfmoonwalk(ui, repo, **opts): | |
684 | """benchmark walking the changelog backwards |
|
684 | """benchmark walking the changelog backwards | |
685 |
|
685 | |||
686 | This also loads the changelog data for each revision in the changelog. |
|
686 | This also loads the changelog data for each revision in the changelog. | |
687 | """ |
|
687 | """ | |
688 | timer, fm = gettimer(ui, opts) |
|
688 | timer, fm = gettimer(ui, opts) | |
689 | def moonwalk(): |
|
689 | def moonwalk(): | |
690 | for i in xrange(len(repo), -1, -1): |
|
690 | for i in xrange(len(repo), -1, -1): | |
691 | ctx = repo[i] |
|
691 | ctx = repo[i] | |
692 | ctx.branch() # read changelog data (in addition to the index) |
|
692 | ctx.branch() # read changelog data (in addition to the index) | |
693 | timer(moonwalk) |
|
693 | timer(moonwalk) | |
694 | fm.end() |
|
694 | fm.end() | |
695 |
|
695 | |||
696 | @command('perftemplating', formatteropts) |
|
696 | @command('perftemplating', formatteropts) | |
697 | def perftemplating(ui, repo, rev=None, **opts): |
|
697 | def perftemplating(ui, repo, rev=None, **opts): | |
698 | if rev is None: |
|
698 | if rev is None: | |
699 | rev=[] |
|
699 | rev=[] | |
700 | timer, fm = gettimer(ui, opts) |
|
700 | timer, fm = gettimer(ui, opts) | |
701 | ui.pushbuffer() |
|
701 | ui.pushbuffer() | |
702 | timer(lambda: commands.log(ui, repo, rev=rev, date='', user='', |
|
702 | timer(lambda: commands.log(ui, repo, rev=rev, date='', user='', | |
703 | template='{date|shortdate} [{rev}:{node|short}]' |
|
703 | template='{date|shortdate} [{rev}:{node|short}]' | |
704 | ' {author|person}: {desc|firstline}\n')) |
|
704 | ' {author|person}: {desc|firstline}\n')) | |
705 | ui.popbuffer() |
|
705 | ui.popbuffer() | |
706 | fm.end() |
|
706 | fm.end() | |
707 |
|
707 | |||
708 | @command('perfcca', formatteropts) |
|
708 | @command('perfcca', formatteropts) | |
709 | def perfcca(ui, repo, **opts): |
|
709 | def perfcca(ui, repo, **opts): | |
710 | timer, fm = gettimer(ui, opts) |
|
710 | timer, fm = gettimer(ui, opts) | |
711 | timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate)) |
|
711 | timer(lambda: scmutil.casecollisionauditor(ui, False, repo.dirstate)) | |
712 | fm.end() |
|
712 | fm.end() | |
713 |
|
713 | |||
714 | @command('perffncacheload', formatteropts) |
|
714 | @command('perffncacheload', formatteropts) | |
715 | def perffncacheload(ui, repo, **opts): |
|
715 | def perffncacheload(ui, repo, **opts): | |
716 | timer, fm = gettimer(ui, opts) |
|
716 | timer, fm = gettimer(ui, opts) | |
717 | s = repo.store |
|
717 | s = repo.store | |
718 | def d(): |
|
718 | def d(): | |
719 | s.fncache._load() |
|
719 | s.fncache._load() | |
720 | timer(d) |
|
720 | timer(d) | |
721 | fm.end() |
|
721 | fm.end() | |
722 |
|
722 | |||
723 | @command('perffncachewrite', formatteropts) |
|
723 | @command('perffncachewrite', formatteropts) | |
724 | def perffncachewrite(ui, repo, **opts): |
|
724 | def perffncachewrite(ui, repo, **opts): | |
725 | timer, fm = gettimer(ui, opts) |
|
725 | timer, fm = gettimer(ui, opts) | |
726 | s = repo.store |
|
726 | s = repo.store | |
727 | s.fncache._load() |
|
727 | s.fncache._load() | |
728 | lock = repo.lock() |
|
728 | lock = repo.lock() | |
729 | tr = repo.transaction('perffncachewrite') |
|
729 | tr = repo.transaction('perffncachewrite') | |
730 | def d(): |
|
730 | def d(): | |
731 | s.fncache._dirty = True |
|
731 | s.fncache._dirty = True | |
732 | s.fncache.write(tr) |
|
732 | s.fncache.write(tr) | |
733 | timer(d) |
|
733 | timer(d) | |
734 | tr.close() |
|
734 | tr.close() | |
735 | lock.release() |
|
735 | lock.release() | |
736 | fm.end() |
|
736 | fm.end() | |
737 |
|
737 | |||
738 | @command('perffncacheencode', formatteropts) |
|
738 | @command('perffncacheencode', formatteropts) | |
739 | def perffncacheencode(ui, repo, **opts): |
|
739 | def perffncacheencode(ui, repo, **opts): | |
740 | timer, fm = gettimer(ui, opts) |
|
740 | timer, fm = gettimer(ui, opts) | |
741 | s = repo.store |
|
741 | s = repo.store | |
742 | s.fncache._load() |
|
742 | s.fncache._load() | |
743 | def d(): |
|
743 | def d(): | |
744 | for p in s.fncache.entries: |
|
744 | for p in s.fncache.entries: | |
745 | s.encode(p) |
|
745 | s.encode(p) | |
746 | timer(d) |
|
746 | timer(d) | |
747 | fm.end() |
|
747 | fm.end() | |
748 |
|
748 | |||
749 | @command('perfdiffwd', formatteropts) |
|
749 | @command('perfdiffwd', formatteropts) | |
750 | def perfdiffwd(ui, repo, **opts): |
|
750 | def perfdiffwd(ui, repo, **opts): | |
751 | """Profile diff of working directory changes""" |
|
751 | """Profile diff of working directory changes""" | |
752 | timer, fm = gettimer(ui, opts) |
|
752 | timer, fm = gettimer(ui, opts) | |
753 | options = { |
|
753 | options = { | |
754 | 'w': 'ignore_all_space', |
|
754 | 'w': 'ignore_all_space', | |
755 | 'b': 'ignore_space_change', |
|
755 | 'b': 'ignore_space_change', | |
756 | 'B': 'ignore_blank_lines', |
|
756 | 'B': 'ignore_blank_lines', | |
757 | } |
|
757 | } | |
758 |
|
758 | |||
759 | for diffopt in ('', 'w', 'b', 'B', 'wB'): |
|
759 | for diffopt in ('', 'w', 'b', 'B', 'wB'): | |
760 | opts = dict((options[c], '1') for c in diffopt) |
|
760 | opts = dict((options[c], '1') for c in diffopt) | |
761 | def d(): |
|
761 | def d(): | |
762 | ui.pushbuffer() |
|
762 | ui.pushbuffer() | |
763 | commands.diff(ui, repo, **opts) |
|
763 | commands.diff(ui, repo, **opts) | |
764 | ui.popbuffer() |
|
764 | ui.popbuffer() | |
765 | title = 'diffopts: %s' % (diffopt and ('-' + diffopt) or 'none') |
|
765 | title = 'diffopts: %s' % (diffopt and ('-' + diffopt) or 'none') | |
766 | timer(d, title) |
|
766 | timer(d, title) | |
767 | fm.end() |
|
767 | fm.end() | |
768 |
|
768 | |||
769 | @command('perfrevlog', revlogopts + formatteropts + |
|
769 | @command('perfrevlog', revlogopts + formatteropts + | |
770 | [('d', 'dist', 100, 'distance between the revisions'), |
|
770 | [('d', 'dist', 100, 'distance between the revisions'), | |
771 | ('s', 'startrev', 0, 'revision to start reading at'), |
|
771 | ('s', 'startrev', 0, 'revision to start reading at'), | |
772 | ('', 'reverse', False, 'read in reverse')], |
|
772 | ('', 'reverse', False, 'read in reverse')], | |
773 | '-c|-m|FILE') |
|
773 | '-c|-m|FILE') | |
774 | def perfrevlog(ui, repo, file_=None, startrev=0, reverse=False, **opts): |
|
774 | def perfrevlog(ui, repo, file_=None, startrev=0, reverse=False, **opts): | |
775 | """Benchmark reading a series of revisions from a revlog. |
|
775 | """Benchmark reading a series of revisions from a revlog. | |
776 |
|
776 | |||
777 | By default, we read every ``-d/--dist`` revision from 0 to tip of |
|
777 | By default, we read every ``-d/--dist`` revision from 0 to tip of | |
778 | the specified revlog. |
|
778 | the specified revlog. | |
779 |
|
779 | |||
780 | The start revision can be defined via ``-s/--startrev``. |
|
780 | The start revision can be defined via ``-s/--startrev``. | |
781 | """ |
|
781 | """ | |
782 | timer, fm = gettimer(ui, opts) |
|
782 | timer, fm = gettimer(ui, opts) | |
783 | _len = getlen(ui) |
|
783 | _len = getlen(ui) | |
784 |
|
784 | |||
785 | def d(): |
|
785 | def d(): | |
786 | r = cmdutil.openrevlog(repo, 'perfrevlog', file_, opts) |
|
786 | r = cmdutil.openrevlog(repo, 'perfrevlog', file_, opts) | |
787 |
|
787 | |||
788 | startrev = 0 |
|
788 | startrev = 0 | |
789 | endrev = _len(r) |
|
789 | endrev = _len(r) | |
790 | dist = opts['dist'] |
|
790 | dist = opts['dist'] | |
791 |
|
791 | |||
792 | if reverse: |
|
792 | if reverse: | |
793 | startrev, endrev = endrev, startrev |
|
793 | startrev, endrev = endrev, startrev | |
794 | dist = -1 * dist |
|
794 | dist = -1 * dist | |
795 |
|
795 | |||
796 | for x in xrange(startrev, endrev, dist): |
|
796 | for x in xrange(startrev, endrev, dist): | |
797 | r.revision(r.node(x)) |
|
797 | r.revision(r.node(x)) | |
798 |
|
798 | |||
799 | timer(d) |
|
799 | timer(d) | |
800 | fm.end() |
|
800 | fm.end() | |
801 |
|
801 | |||
802 | @command('perfrevlogrevision', revlogopts + formatteropts + |
|
802 | @command('perfrevlogrevision', revlogopts + formatteropts + | |
803 | [('', 'cache', False, 'use caches instead of clearing')], |
|
803 | [('', 'cache', False, 'use caches instead of clearing')], | |
804 | '-c|-m|FILE REV') |
|
804 | '-c|-m|FILE REV') | |
805 | def perfrevlogrevision(ui, repo, file_, rev=None, cache=None, **opts): |
|
805 | def perfrevlogrevision(ui, repo, file_, rev=None, cache=None, **opts): | |
806 | """Benchmark obtaining a revlog revision. |
|
806 | """Benchmark obtaining a revlog revision. | |
807 |
|
807 | |||
808 | Obtaining a revlog revision consists of roughly the following steps: |
|
808 | Obtaining a revlog revision consists of roughly the following steps: | |
809 |
|
809 | |||
810 | 1. Compute the delta chain |
|
810 | 1. Compute the delta chain | |
811 | 2. Obtain the raw chunks for that delta chain |
|
811 | 2. Obtain the raw chunks for that delta chain | |
812 | 3. Decompress each raw chunk |
|
812 | 3. Decompress each raw chunk | |
813 | 4. Apply binary patches to obtain fulltext |
|
813 | 4. Apply binary patches to obtain fulltext | |
814 | 5. Verify hash of fulltext |
|
814 | 5. Verify hash of fulltext | |
815 |
|
815 | |||
816 | This command measures the time spent in each of these phases. |
|
816 | This command measures the time spent in each of these phases. | |
817 | """ |
|
817 | """ | |
818 | if opts.get('changelog') or opts.get('manifest'): |
|
818 | if opts.get('changelog') or opts.get('manifest'): | |
819 | file_, rev = None, file_ |
|
819 | file_, rev = None, file_ | |
820 | elif rev is None: |
|
820 | elif rev is None: | |
821 | raise error.CommandError('perfrevlogrevision', 'invalid arguments') |
|
821 | raise error.CommandError('perfrevlogrevision', 'invalid arguments') | |
822 |
|
822 | |||
823 | r = cmdutil.openrevlog(repo, 'perfrevlogrevision', file_, opts) |
|
823 | r = cmdutil.openrevlog(repo, 'perfrevlogrevision', file_, opts) | |
824 | node = r.lookup(rev) |
|
824 | node = r.lookup(rev) | |
825 | rev = r.rev(node) |
|
825 | rev = r.rev(node) | |
826 |
|
826 | |||
827 | def dodeltachain(rev): |
|
827 | def dodeltachain(rev): | |
828 | if not cache: |
|
828 | if not cache: | |
829 | r.clearcaches() |
|
829 | r.clearcaches() | |
830 | r._deltachain(rev) |
|
830 | r._deltachain(rev) | |
831 |
|
831 | |||
832 | def doread(chain): |
|
832 | def doread(chain): | |
833 | if not cache: |
|
833 | if not cache: | |
834 | r.clearcaches() |
|
834 | r.clearcaches() | |
835 | r._chunkraw(chain[0], chain[-1]) |
|
835 | r._chunkraw(chain[0], chain[-1]) | |
836 |
|
836 | |||
837 | def dodecompress(data, chain): |
|
837 | def dodecompress(data, chain): | |
838 | if not cache: |
|
838 | if not cache: | |
839 | r.clearcaches() |
|
839 | r.clearcaches() | |
840 |
|
840 | |||
841 | start = r.start |
|
841 | start = r.start | |
842 | length = r.length |
|
842 | length = r.length | |
843 | inline = r._inline |
|
843 | inline = r._inline | |
844 | iosize = r._io.size |
|
844 | iosize = r._io.size | |
845 | buffer = util.buffer |
|
845 | buffer = util.buffer | |
846 | offset = start(chain[0]) |
|
846 | offset = start(chain[0]) | |
847 |
|
847 | |||
848 | for rev in chain: |
|
848 | for rev in chain: | |
849 | chunkstart = start(rev) |
|
849 | chunkstart = start(rev) | |
850 | if inline: |
|
850 | if inline: | |
851 | chunkstart += (rev + 1) * iosize |
|
851 | chunkstart += (rev + 1) * iosize | |
852 | chunklength = length(rev) |
|
852 | chunklength = length(rev) | |
853 | b = buffer(data, chunkstart - offset, chunklength) |
|
853 | b = buffer(data, chunkstart - offset, chunklength) | |
854 | revlog.decompress(b) |
|
854 | revlog.decompress(b) | |
855 |
|
855 | |||
856 | def dopatch(text, bins): |
|
856 | def dopatch(text, bins): | |
857 | if not cache: |
|
857 | if not cache: | |
858 | r.clearcaches() |
|
858 | r.clearcaches() | |
859 | mdiff.patches(text, bins) |
|
859 | mdiff.patches(text, bins) | |
860 |
|
860 | |||
861 | def dohash(text): |
|
861 | def dohash(text): | |
862 | if not cache: |
|
862 | if not cache: | |
863 | r.clearcaches() |
|
863 | r.clearcaches() | |
864 | r._checkhash(text, node, rev) |
|
864 | r._checkhash(text, node, rev) | |
865 |
|
865 | |||
866 | def dorevision(): |
|
866 | def dorevision(): | |
867 | if not cache: |
|
867 | if not cache: | |
868 | r.clearcaches() |
|
868 | r.clearcaches() | |
869 | r.revision(node) |
|
869 | r.revision(node) | |
870 |
|
870 | |||
871 | chain = r._deltachain(rev)[0] |
|
871 | chain = r._deltachain(rev)[0] | |
872 | data = r._chunkraw(chain[0], chain[-1])[1] |
|
872 | data = r._chunkraw(chain[0], chain[-1])[1] | |
873 | bins = r._chunks(chain) |
|
873 | bins = r._chunks(chain) | |
874 | text = str(bins[0]) |
|
874 | text = str(bins[0]) | |
875 | bins = bins[1:] |
|
875 | bins = bins[1:] | |
876 | text = mdiff.patches(text, bins) |
|
876 | text = mdiff.patches(text, bins) | |
877 |
|
877 | |||
878 | benches = [ |
|
878 | benches = [ | |
879 | (lambda: dorevision(), 'full'), |
|
879 | (lambda: dorevision(), 'full'), | |
880 | (lambda: dodeltachain(rev), 'deltachain'), |
|
880 | (lambda: dodeltachain(rev), 'deltachain'), | |
881 | (lambda: doread(chain), 'read'), |
|
881 | (lambda: doread(chain), 'read'), | |
882 | (lambda: dodecompress(data, chain), 'decompress'), |
|
882 | (lambda: dodecompress(data, chain), 'decompress'), | |
883 | (lambda: dopatch(text, bins), 'patch'), |
|
883 | (lambda: dopatch(text, bins), 'patch'), | |
884 | (lambda: dohash(text), 'hash'), |
|
884 | (lambda: dohash(text), 'hash'), | |
885 | ] |
|
885 | ] | |
886 |
|
886 | |||
887 | for fn, title in benches: |
|
887 | for fn, title in benches: | |
888 | timer, fm = gettimer(ui, opts) |
|
888 | timer, fm = gettimer(ui, opts) | |
889 | timer(fn, title=title) |
|
889 | timer(fn, title=title) | |
890 | fm.end() |
|
890 | fm.end() | |
891 |
|
891 | |||
892 | @command('perfrevset', |
|
892 | @command('perfrevset', | |
893 | [('C', 'clear', False, 'clear volatile cache between each call.'), |
|
893 | [('C', 'clear', False, 'clear volatile cache between each call.'), | |
894 | ('', 'contexts', False, 'obtain changectx for each revision')] |
|
894 | ('', 'contexts', False, 'obtain changectx for each revision')] | |
895 | + formatteropts, "REVSET") |
|
895 | + formatteropts, "REVSET") | |
896 | def perfrevset(ui, repo, expr, clear=False, contexts=False, **opts): |
|
896 | def perfrevset(ui, repo, expr, clear=False, contexts=False, **opts): | |
897 | """benchmark the execution time of a revset |
|
897 | """benchmark the execution time of a revset | |
898 |
|
898 | |||
899 | Use the --clean option if need to evaluate the impact of build volatile |
|
899 | Use the --clean option if need to evaluate the impact of build volatile | |
900 | revisions set cache on the revset execution. Volatile cache hold filtered |
|
900 | revisions set cache on the revset execution. Volatile cache hold filtered | |
901 | and obsolete related cache.""" |
|
901 | and obsolete related cache.""" | |
902 | timer, fm = gettimer(ui, opts) |
|
902 | timer, fm = gettimer(ui, opts) | |
903 | def d(): |
|
903 | def d(): | |
904 | if clear: |
|
904 | if clear: | |
905 | repo.invalidatevolatilesets() |
|
905 | repo.invalidatevolatilesets() | |
906 | if contexts: |
|
906 | if contexts: | |
907 | for ctx in repo.set(expr): pass |
|
907 | for ctx in repo.set(expr): pass | |
908 | else: |
|
908 | else: | |
909 | for r in repo.revs(expr): pass |
|
909 | for r in repo.revs(expr): pass | |
910 | timer(d) |
|
910 | timer(d) | |
911 | fm.end() |
|
911 | fm.end() | |
912 |
|
912 | |||
913 | @command('perfvolatilesets', formatteropts) |
|
913 | @command('perfvolatilesets', formatteropts) | |
914 | def perfvolatilesets(ui, repo, *names, **opts): |
|
914 | def perfvolatilesets(ui, repo, *names, **opts): | |
915 | """benchmark the computation of various volatile set |
|
915 | """benchmark the computation of various volatile set | |
916 |
|
916 | |||
917 | Volatile set computes element related to filtering and obsolescence.""" |
|
917 | Volatile set computes element related to filtering and obsolescence.""" | |
918 | timer, fm = gettimer(ui, opts) |
|
918 | timer, fm = gettimer(ui, opts) | |
919 | repo = repo.unfiltered() |
|
919 | repo = repo.unfiltered() | |
920 |
|
920 | |||
921 | def getobs(name): |
|
921 | def getobs(name): | |
922 | def d(): |
|
922 | def d(): | |
923 | repo.invalidatevolatilesets() |
|
923 | repo.invalidatevolatilesets() | |
924 | obsolete.getrevs(repo, name) |
|
924 | obsolete.getrevs(repo, name) | |
925 | return d |
|
925 | return d | |
926 |
|
926 | |||
927 | allobs = sorted(obsolete.cachefuncs) |
|
927 | allobs = sorted(obsolete.cachefuncs) | |
928 | if names: |
|
928 | if names: | |
929 | allobs = [n for n in allobs if n in names] |
|
929 | allobs = [n for n in allobs if n in names] | |
930 |
|
930 | |||
931 | for name in allobs: |
|
931 | for name in allobs: | |
932 | timer(getobs(name), title=name) |
|
932 | timer(getobs(name), title=name) | |
933 |
|
933 | |||
934 | def getfiltered(name): |
|
934 | def getfiltered(name): | |
935 | def d(): |
|
935 | def d(): | |
936 | repo.invalidatevolatilesets() |
|
936 | repo.invalidatevolatilesets() | |
937 | repoview.filterrevs(repo, name) |
|
937 | repoview.filterrevs(repo, name) | |
938 | return d |
|
938 | return d | |
939 |
|
939 | |||
940 | allfilter = sorted(repoview.filtertable) |
|
940 | allfilter = sorted(repoview.filtertable) | |
941 | if names: |
|
941 | if names: | |
942 | allfilter = [n for n in allfilter if n in names] |
|
942 | allfilter = [n for n in allfilter if n in names] | |
943 |
|
943 | |||
944 | for name in allfilter: |
|
944 | for name in allfilter: | |
945 | timer(getfiltered(name), title=name) |
|
945 | timer(getfiltered(name), title=name) | |
946 | fm.end() |
|
946 | fm.end() | |
947 |
|
947 | |||
948 | @command('perfbranchmap', |
|
948 | @command('perfbranchmap', | |
949 | [('f', 'full', False, |
|
949 | [('f', 'full', False, | |
950 | 'Includes build time of subset'), |
|
950 | 'Includes build time of subset'), | |
951 | ] + formatteropts) |
|
951 | ] + formatteropts) | |
952 | def perfbranchmap(ui, repo, full=False, **opts): |
|
952 | def perfbranchmap(ui, repo, full=False, **opts): | |
953 | """benchmark the update of a branchmap |
|
953 | """benchmark the update of a branchmap | |
954 |
|
954 | |||
955 | This benchmarks the full repo.branchmap() call with read and write disabled |
|
955 | This benchmarks the full repo.branchmap() call with read and write disabled | |
956 | """ |
|
956 | """ | |
957 | timer, fm = gettimer(ui, opts) |
|
957 | timer, fm = gettimer(ui, opts) | |
958 | def getbranchmap(filtername): |
|
958 | def getbranchmap(filtername): | |
959 | """generate a benchmark function for the filtername""" |
|
959 | """generate a benchmark function for the filtername""" | |
960 | if filtername is None: |
|
960 | if filtername is None: | |
961 | view = repo |
|
961 | view = repo | |
962 | else: |
|
962 | else: | |
963 | view = repo.filtered(filtername) |
|
963 | view = repo.filtered(filtername) | |
964 | def d(): |
|
964 | def d(): | |
965 | if full: |
|
965 | if full: | |
966 | view._branchcaches.clear() |
|
966 | view._branchcaches.clear() | |
967 | else: |
|
967 | else: | |
968 | view._branchcaches.pop(filtername, None) |
|
968 | view._branchcaches.pop(filtername, None) | |
969 | view.branchmap() |
|
969 | view.branchmap() | |
970 | return d |
|
970 | return d | |
971 | # add filter in smaller subset to bigger subset |
|
971 | # add filter in smaller subset to bigger subset | |
972 | possiblefilters = set(repoview.filtertable) |
|
972 | possiblefilters = set(repoview.filtertable) | |
973 | subsettable = getbranchmapsubsettable() |
|
973 | subsettable = getbranchmapsubsettable() | |
974 | allfilters = [] |
|
974 | allfilters = [] | |
975 | while possiblefilters: |
|
975 | while possiblefilters: | |
976 | for name in possiblefilters: |
|
976 | for name in possiblefilters: | |
977 | subset = subsettable.get(name) |
|
977 | subset = subsettable.get(name) | |
978 | if subset not in possiblefilters: |
|
978 | if subset not in possiblefilters: | |
979 | break |
|
979 | break | |
980 | else: |
|
980 | else: | |
981 | assert False, 'subset cycle %s!' % possiblefilters |
|
981 | assert False, 'subset cycle %s!' % possiblefilters | |
982 | allfilters.append(name) |
|
982 | allfilters.append(name) | |
983 | possiblefilters.remove(name) |
|
983 | possiblefilters.remove(name) | |
984 |
|
984 | |||
985 | # warm the cache |
|
985 | # warm the cache | |
986 | if not full: |
|
986 | if not full: | |
987 | for name in allfilters: |
|
987 | for name in allfilters: | |
988 | repo.filtered(name).branchmap() |
|
988 | repo.filtered(name).branchmap() | |
989 | # add unfiltered |
|
989 | # add unfiltered | |
990 | allfilters.append(None) |
|
990 | allfilters.append(None) | |
991 |
|
991 | |||
992 | branchcacheread = safeattrsetter(branchmap, 'read') |
|
992 | branchcacheread = safeattrsetter(branchmap, 'read') | |
993 | branchcachewrite = safeattrsetter(branchmap.branchcache, 'write') |
|
993 | branchcachewrite = safeattrsetter(branchmap.branchcache, 'write') | |
994 | branchcacheread.set(lambda repo: None) |
|
994 | branchcacheread.set(lambda repo: None) | |
995 | branchcachewrite.set(lambda bc, repo: None) |
|
995 | branchcachewrite.set(lambda bc, repo: None) | |
996 | try: |
|
996 | try: | |
997 | for name in allfilters: |
|
997 | for name in allfilters: | |
998 | timer(getbranchmap(name), title=str(name)) |
|
998 | timer(getbranchmap(name), title=str(name)) | |
999 | finally: |
|
999 | finally: | |
1000 | branchcacheread.restore() |
|
1000 | branchcacheread.restore() | |
1001 | branchcachewrite.restore() |
|
1001 | branchcachewrite.restore() | |
1002 | fm.end() |
|
1002 | fm.end() | |
1003 |
|
1003 | |||
1004 | @command('perfloadmarkers') |
|
1004 | @command('perfloadmarkers') | |
1005 | def perfloadmarkers(ui, repo): |
|
1005 | def perfloadmarkers(ui, repo): | |
1006 | """benchmark the time to parse the on-disk markers for a repo |
|
1006 | """benchmark the time to parse the on-disk markers for a repo | |
1007 |
|
1007 | |||
1008 | Result is the number of markers in the repo.""" |
|
1008 | Result is the number of markers in the repo.""" | |
1009 | timer, fm = gettimer(ui) |
|
1009 | timer, fm = gettimer(ui) | |
1010 | svfs = getsvfs(repo) |
|
1010 | svfs = getsvfs(repo) | |
1011 | timer(lambda: len(obsolete.obsstore(svfs))) |
|
1011 | timer(lambda: len(obsolete.obsstore(svfs))) | |
1012 | fm.end() |
|
1012 | fm.end() | |
1013 |
|
1013 | |||
1014 | @command('perflrucachedict', formatteropts + |
|
1014 | @command('perflrucachedict', formatteropts + | |
1015 | [('', 'size', 4, 'size of cache'), |
|
1015 | [('', 'size', 4, 'size of cache'), | |
1016 | ('', 'gets', 10000, 'number of key lookups'), |
|
1016 | ('', 'gets', 10000, 'number of key lookups'), | |
1017 | ('', 'sets', 10000, 'number of key sets'), |
|
1017 | ('', 'sets', 10000, 'number of key sets'), | |
1018 | ('', 'mixed', 10000, 'number of mixed mode operations'), |
|
1018 | ('', 'mixed', 10000, 'number of mixed mode operations'), | |
1019 | ('', 'mixedgetfreq', 50, 'frequency of get vs set ops in mixed mode')], |
|
1019 | ('', 'mixedgetfreq', 50, 'frequency of get vs set ops in mixed mode')], | |
1020 | norepo=True) |
|
1020 | norepo=True) | |
1021 | def perflrucache(ui, size=4, gets=10000, sets=10000, mixed=10000, |
|
1021 | def perflrucache(ui, size=4, gets=10000, sets=10000, mixed=10000, | |
1022 | mixedgetfreq=50, **opts): |
|
1022 | mixedgetfreq=50, **opts): | |
1023 | def doinit(): |
|
1023 | def doinit(): | |
1024 | for i in xrange(10000): |
|
1024 | for i in xrange(10000): | |
1025 | util.lrucachedict(size) |
|
1025 | util.lrucachedict(size) | |
1026 |
|
1026 | |||
1027 | values = [] |
|
1027 | values = [] | |
1028 | for i in xrange(size): |
|
1028 | for i in xrange(size): | |
1029 | values.append(random.randint(0, sys.maxint)) |
|
1029 | values.append(random.randint(0, sys.maxint)) | |
1030 |
|
1030 | |||
1031 | # Get mode fills the cache and tests raw lookup performance with no |
|
1031 | # Get mode fills the cache and tests raw lookup performance with no | |
1032 | # eviction. |
|
1032 | # eviction. | |
1033 | getseq = [] |
|
1033 | getseq = [] | |
1034 | for i in xrange(gets): |
|
1034 | for i in xrange(gets): | |
1035 | getseq.append(random.choice(values)) |
|
1035 | getseq.append(random.choice(values)) | |
1036 |
|
1036 | |||
1037 | def dogets(): |
|
1037 | def dogets(): | |
1038 | d = util.lrucachedict(size) |
|
1038 | d = util.lrucachedict(size) | |
1039 | for v in values: |
|
1039 | for v in values: | |
1040 | d[v] = v |
|
1040 | d[v] = v | |
1041 | for key in getseq: |
|
1041 | for key in getseq: | |
1042 | value = d[key] |
|
1042 | value = d[key] | |
1043 | value # silence pyflakes warning |
|
1043 | value # silence pyflakes warning | |
1044 |
|
1044 | |||
1045 | # Set mode tests insertion speed with cache eviction. |
|
1045 | # Set mode tests insertion speed with cache eviction. | |
1046 | setseq = [] |
|
1046 | setseq = [] | |
1047 | for i in xrange(sets): |
|
1047 | for i in xrange(sets): | |
1048 | setseq.append(random.randint(0, sys.maxint)) |
|
1048 | setseq.append(random.randint(0, sys.maxint)) | |
1049 |
|
1049 | |||
1050 | def dosets(): |
|
1050 | def dosets(): | |
1051 | d = util.lrucachedict(size) |
|
1051 | d = util.lrucachedict(size) | |
1052 | for v in setseq: |
|
1052 | for v in setseq: | |
1053 | d[v] = v |
|
1053 | d[v] = v | |
1054 |
|
1054 | |||
1055 | # Mixed mode randomly performs gets and sets with eviction. |
|
1055 | # Mixed mode randomly performs gets and sets with eviction. | |
1056 | mixedops = [] |
|
1056 | mixedops = [] | |
1057 | for i in xrange(mixed): |
|
1057 | for i in xrange(mixed): | |
1058 | r = random.randint(0, 100) |
|
1058 | r = random.randint(0, 100) | |
1059 | if r < mixedgetfreq: |
|
1059 | if r < mixedgetfreq: | |
1060 | op = 0 |
|
1060 | op = 0 | |
1061 | else: |
|
1061 | else: | |
1062 | op = 1 |
|
1062 | op = 1 | |
1063 |
|
1063 | |||
1064 | mixedops.append((op, random.randint(0, size * 2))) |
|
1064 | mixedops.append((op, random.randint(0, size * 2))) | |
1065 |
|
1065 | |||
1066 | def domixed(): |
|
1066 | def domixed(): | |
1067 | d = util.lrucachedict(size) |
|
1067 | d = util.lrucachedict(size) | |
1068 |
|
1068 | |||
1069 | for op, v in mixedops: |
|
1069 | for op, v in mixedops: | |
1070 | if op == 0: |
|
1070 | if op == 0: | |
1071 | try: |
|
1071 | try: | |
1072 | d[v] |
|
1072 | d[v] | |
1073 | except KeyError: |
|
1073 | except KeyError: | |
1074 | pass |
|
1074 | pass | |
1075 | else: |
|
1075 | else: | |
1076 | d[v] = v |
|
1076 | d[v] = v | |
1077 |
|
1077 | |||
1078 | benches = [ |
|
1078 | benches = [ | |
1079 | (doinit, 'init'), |
|
1079 | (doinit, 'init'), | |
1080 | (dogets, 'gets'), |
|
1080 | (dogets, 'gets'), | |
1081 | (dosets, 'sets'), |
|
1081 | (dosets, 'sets'), | |
1082 | (domixed, 'mixed') |
|
1082 | (domixed, 'mixed') | |
1083 | ] |
|
1083 | ] | |
1084 |
|
1084 | |||
1085 | for fn, title in benches: |
|
1085 | for fn, title in benches: | |
1086 | timer, fm = gettimer(ui, opts) |
|
1086 | timer, fm = gettimer(ui, opts) | |
1087 | timer(fn, title=title) |
|
1087 | timer(fn, title=title) | |
1088 | fm.end() |
|
1088 | fm.end() | |
1089 |
|
1089 | |||
1090 | def uisetup(ui): |
|
1090 | def uisetup(ui): | |
1091 | if (util.safehasattr(cmdutil, 'openrevlog') and |
|
1091 | if (util.safehasattr(cmdutil, 'openrevlog') and | |
1092 | not util.safehasattr(commands, 'debugrevlogopts')): |
|
1092 | not util.safehasattr(commands, 'debugrevlogopts')): | |
1093 | # for "historical portability": |
|
1093 | # for "historical portability": | |
1094 | # In this case, Mercurial should be 1.9 (or a79fea6b3e77) - |
|
1094 | # In this case, Mercurial should be 1.9 (or a79fea6b3e77) - | |
1095 | # 3.7 (or 5606f7d0d063). Therefore, '--dir' option for |
|
1095 | # 3.7 (or 5606f7d0d063). Therefore, '--dir' option for | |
1096 | # openrevlog() should cause failure, because it has been |
|
1096 | # openrevlog() should cause failure, because it has been | |
1097 | # available since 3.5 (or 49c583ca48c4). |
|
1097 | # available since 3.5 (or 49c583ca48c4). | |
1098 | def openrevlog(orig, repo, cmd, file_, opts): |
|
1098 | def openrevlog(orig, repo, cmd, file_, opts): | |
1099 | if opts.get('dir') and not util.safehasattr(repo, 'dirlog'): |
|
1099 | if opts.get('dir') and not util.safehasattr(repo, 'dirlog'): | |
1100 | raise error.Abort("This version doesn't support --dir option", |
|
1100 | raise error.Abort("This version doesn't support --dir option", | |
1101 | hint="use 3.5 or later") |
|
1101 | hint="use 3.5 or later") | |
1102 | return orig(repo, cmd, file_, opts) |
|
1102 | return orig(repo, cmd, file_, opts) | |
1103 | extensions.wrapfunction(cmdutil, 'openrevlog', openrevlog) |
|
1103 | extensions.wrapfunction(cmdutil, 'openrevlog', openrevlog) |
@@ -1,1427 +1,1439 b'' | |||||
1 | # Copyright 2009-2010 Gregory P. Ward |
|
1 | # Copyright 2009-2010 Gregory P. Ward | |
2 | # Copyright 2009-2010 Intelerad Medical Systems Incorporated |
|
2 | # Copyright 2009-2010 Intelerad Medical Systems Incorporated | |
3 | # Copyright 2010-2011 Fog Creek Software |
|
3 | # Copyright 2010-2011 Fog Creek Software | |
4 | # Copyright 2010-2011 Unity Technologies |
|
4 | # Copyright 2010-2011 Unity Technologies | |
5 | # |
|
5 | # | |
6 | # This software may be used and distributed according to the terms of the |
|
6 | # This software may be used and distributed according to the terms of the | |
7 | # GNU General Public License version 2 or any later version. |
|
7 | # GNU General Public License version 2 or any later version. | |
8 |
|
8 | |||
9 | '''Overridden Mercurial commands and functions for the largefiles extension''' |
|
9 | '''Overridden Mercurial commands and functions for the largefiles extension''' | |
10 | from __future__ import absolute_import |
|
10 | from __future__ import absolute_import | |
11 |
|
11 | |||
12 | import copy |
|
12 | import copy | |
13 | import os |
|
13 | import os | |
14 |
|
14 | |||
15 | from mercurial.i18n import _ |
|
15 | from mercurial.i18n import _ | |
16 |
|
16 | |||
17 | from mercurial import ( |
|
17 | from mercurial import ( | |
18 | archival, |
|
18 | archival, | |
19 | cmdutil, |
|
19 | cmdutil, | |
20 | error, |
|
20 | error, | |
21 | hg, |
|
21 | hg, | |
22 | match as matchmod, |
|
22 | match as matchmod, | |
23 | pathutil, |
|
23 | pathutil, | |
24 | registrar, |
|
24 | registrar, | |
25 | revset, |
|
25 | revset, | |
26 | scmutil, |
|
26 | scmutil, | |
27 | util, |
|
27 | util, | |
28 | ) |
|
28 | ) | |
29 |
|
29 | |||
30 | from . import ( |
|
30 | from . import ( | |
31 | lfcommands, |
|
31 | lfcommands, | |
32 | lfutil, |
|
32 | lfutil, | |
33 | storefactory, |
|
33 | storefactory, | |
34 | ) |
|
34 | ) | |
35 |
|
35 | |||
36 | # -- Utility functions: commonly/repeatedly needed functionality --------------- |
|
36 | # -- Utility functions: commonly/repeatedly needed functionality --------------- | |
37 |
|
37 | |||
38 | def composelargefilematcher(match, manifest): |
|
38 | def composelargefilematcher(match, manifest): | |
39 | '''create a matcher that matches only the largefiles in the original |
|
39 | '''create a matcher that matches only the largefiles in the original | |
40 | matcher''' |
|
40 | matcher''' | |
41 | m = copy.copy(match) |
|
41 | m = copy.copy(match) | |
42 | lfile = lambda f: lfutil.standin(f) in manifest |
|
42 | lfile = lambda f: lfutil.standin(f) in manifest | |
43 | m._files = filter(lfile, m._files) |
|
43 | m._files = filter(lfile, m._files) | |
44 | m._fileroots = set(m._files) |
|
44 | m._fileroots = set(m._files) | |
45 | m._always = False |
|
45 | m._always = False | |
46 | origmatchfn = m.matchfn |
|
46 | origmatchfn = m.matchfn | |
47 | m.matchfn = lambda f: lfile(f) and origmatchfn(f) |
|
47 | m.matchfn = lambda f: lfile(f) and origmatchfn(f) | |
48 | return m |
|
48 | return m | |
49 |
|
49 | |||
50 | def composenormalfilematcher(match, manifest, exclude=None): |
|
50 | def composenormalfilematcher(match, manifest, exclude=None): | |
51 | excluded = set() |
|
51 | excluded = set() | |
52 | if exclude is not None: |
|
52 | if exclude is not None: | |
53 | excluded.update(exclude) |
|
53 | excluded.update(exclude) | |
54 |
|
54 | |||
55 | m = copy.copy(match) |
|
55 | m = copy.copy(match) | |
56 | notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in |
|
56 | notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in | |
57 | manifest or f in excluded) |
|
57 | manifest or f in excluded) | |
58 | m._files = filter(notlfile, m._files) |
|
58 | m._files = filter(notlfile, m._files) | |
59 | m._fileroots = set(m._files) |
|
59 | m._fileroots = set(m._files) | |
60 | m._always = False |
|
60 | m._always = False | |
61 | origmatchfn = m.matchfn |
|
61 | origmatchfn = m.matchfn | |
62 | m.matchfn = lambda f: notlfile(f) and origmatchfn(f) |
|
62 | m.matchfn = lambda f: notlfile(f) and origmatchfn(f) | |
63 | return m |
|
63 | return m | |
64 |
|
64 | |||
65 | def installnormalfilesmatchfn(manifest): |
|
65 | def installnormalfilesmatchfn(manifest): | |
66 | '''installmatchfn with a matchfn that ignores all largefiles''' |
|
66 | '''installmatchfn with a matchfn that ignores all largefiles''' | |
67 | def overridematch(ctx, pats=(), opts=None, globbed=False, |
|
67 | def overridematch(ctx, pats=(), opts=None, globbed=False, | |
68 | default='relpath', badfn=None): |
|
68 | default='relpath', badfn=None): | |
69 | if opts is None: |
|
69 | if opts is None: | |
70 | opts = {} |
|
70 | opts = {} | |
71 | match = oldmatch(ctx, pats, opts, globbed, default, badfn=badfn) |
|
71 | match = oldmatch(ctx, pats, opts, globbed, default, badfn=badfn) | |
72 | return composenormalfilematcher(match, manifest) |
|
72 | return composenormalfilematcher(match, manifest) | |
73 | oldmatch = installmatchfn(overridematch) |
|
73 | oldmatch = installmatchfn(overridematch) | |
74 |
|
74 | |||
75 | def installmatchfn(f): |
|
75 | def installmatchfn(f): | |
76 | '''monkey patch the scmutil module with a custom match function. |
|
76 | '''monkey patch the scmutil module with a custom match function. | |
77 | Warning: it is monkey patching the _module_ on runtime! Not thread safe!''' |
|
77 | Warning: it is monkey patching the _module_ on runtime! Not thread safe!''' | |
78 | oldmatch = scmutil.match |
|
78 | oldmatch = scmutil.match | |
79 | setattr(f, 'oldmatch', oldmatch) |
|
79 | setattr(f, 'oldmatch', oldmatch) | |
80 | scmutil.match = f |
|
80 | scmutil.match = f | |
81 | return oldmatch |
|
81 | return oldmatch | |
82 |
|
82 | |||
83 | def restorematchfn(): |
|
83 | def restorematchfn(): | |
84 | '''restores scmutil.match to what it was before installmatchfn |
|
84 | '''restores scmutil.match to what it was before installmatchfn | |
85 | was called. no-op if scmutil.match is its original function. |
|
85 | was called. no-op if scmutil.match is its original function. | |
86 |
|
86 | |||
87 | Note that n calls to installmatchfn will require n calls to |
|
87 | Note that n calls to installmatchfn will require n calls to | |
88 | restore the original matchfn.''' |
|
88 | restore the original matchfn.''' | |
89 | scmutil.match = getattr(scmutil.match, 'oldmatch') |
|
89 | scmutil.match = getattr(scmutil.match, 'oldmatch') | |
90 |
|
90 | |||
91 | def installmatchandpatsfn(f): |
|
91 | def installmatchandpatsfn(f): | |
92 | oldmatchandpats = scmutil.matchandpats |
|
92 | oldmatchandpats = scmutil.matchandpats | |
93 | setattr(f, 'oldmatchandpats', oldmatchandpats) |
|
93 | setattr(f, 'oldmatchandpats', oldmatchandpats) | |
94 | scmutil.matchandpats = f |
|
94 | scmutil.matchandpats = f | |
95 | return oldmatchandpats |
|
95 | return oldmatchandpats | |
96 |
|
96 | |||
97 | def restorematchandpatsfn(): |
|
97 | def restorematchandpatsfn(): | |
98 | '''restores scmutil.matchandpats to what it was before |
|
98 | '''restores scmutil.matchandpats to what it was before | |
99 | installmatchandpatsfn was called. No-op if scmutil.matchandpats |
|
99 | installmatchandpatsfn was called. No-op if scmutil.matchandpats | |
100 | is its original function. |
|
100 | is its original function. | |
101 |
|
101 | |||
102 | Note that n calls to installmatchandpatsfn will require n calls |
|
102 | Note that n calls to installmatchandpatsfn will require n calls | |
103 | to restore the original matchfn.''' |
|
103 | to restore the original matchfn.''' | |
104 | scmutil.matchandpats = getattr(scmutil.matchandpats, 'oldmatchandpats', |
|
104 | scmutil.matchandpats = getattr(scmutil.matchandpats, 'oldmatchandpats', | |
105 | scmutil.matchandpats) |
|
105 | scmutil.matchandpats) | |
106 |
|
106 | |||
107 | def addlargefiles(ui, repo, isaddremove, matcher, **opts): |
|
107 | def addlargefiles(ui, repo, isaddremove, matcher, **opts): | |
108 | large = opts.get('large') |
|
108 | large = opts.get('large') | |
109 | lfsize = lfutil.getminsize( |
|
109 | lfsize = lfutil.getminsize( | |
110 | ui, lfutil.islfilesrepo(repo), opts.get('lfsize')) |
|
110 | ui, lfutil.islfilesrepo(repo), opts.get('lfsize')) | |
111 |
|
111 | |||
112 | lfmatcher = None |
|
112 | lfmatcher = None | |
113 | if lfutil.islfilesrepo(repo): |
|
113 | if lfutil.islfilesrepo(repo): | |
114 | lfpats = ui.configlist(lfutil.longname, 'patterns', default=[]) |
|
114 | lfpats = ui.configlist(lfutil.longname, 'patterns', default=[]) | |
115 | if lfpats: |
|
115 | if lfpats: | |
116 | lfmatcher = matchmod.match(repo.root, '', list(lfpats)) |
|
116 | lfmatcher = matchmod.match(repo.root, '', list(lfpats)) | |
117 |
|
117 | |||
118 | lfnames = [] |
|
118 | lfnames = [] | |
119 | m = matcher |
|
119 | m = matcher | |
120 |
|
120 | |||
121 | wctx = repo[None] |
|
121 | wctx = repo[None] | |
122 | for f in repo.walk(matchmod.badmatch(m, lambda x, y: None)): |
|
122 | for f in repo.walk(matchmod.badmatch(m, lambda x, y: None)): | |
123 | exact = m.exact(f) |
|
123 | exact = m.exact(f) | |
124 | lfile = lfutil.standin(f) in wctx |
|
124 | lfile = lfutil.standin(f) in wctx | |
125 | nfile = f in wctx |
|
125 | nfile = f in wctx | |
126 | exists = lfile or nfile |
|
126 | exists = lfile or nfile | |
127 |
|
127 | |||
128 | # addremove in core gets fancy with the name, add doesn't |
|
128 | # addremove in core gets fancy with the name, add doesn't | |
129 | if isaddremove: |
|
129 | if isaddremove: | |
130 | name = m.uipath(f) |
|
130 | name = m.uipath(f) | |
131 | else: |
|
131 | else: | |
132 | name = m.rel(f) |
|
132 | name = m.rel(f) | |
133 |
|
133 | |||
134 | # Don't warn the user when they attempt to add a normal tracked file. |
|
134 | # Don't warn the user when they attempt to add a normal tracked file. | |
135 | # The normal add code will do that for us. |
|
135 | # The normal add code will do that for us. | |
136 | if exact and exists: |
|
136 | if exact and exists: | |
137 | if lfile: |
|
137 | if lfile: | |
138 | ui.warn(_('%s already a largefile\n') % name) |
|
138 | ui.warn(_('%s already a largefile\n') % name) | |
139 | continue |
|
139 | continue | |
140 |
|
140 | |||
141 | if (exact or not exists) and not lfutil.isstandin(f): |
|
141 | if (exact or not exists) and not lfutil.isstandin(f): | |
142 | # In case the file was removed previously, but not committed |
|
142 | # In case the file was removed previously, but not committed | |
143 | # (issue3507) |
|
143 | # (issue3507) | |
144 | if not repo.wvfs.exists(f): |
|
144 | if not repo.wvfs.exists(f): | |
145 | continue |
|
145 | continue | |
146 |
|
146 | |||
147 | abovemin = (lfsize and |
|
147 | abovemin = (lfsize and | |
148 | repo.wvfs.lstat(f).st_size >= lfsize * 1024 * 1024) |
|
148 | repo.wvfs.lstat(f).st_size >= lfsize * 1024 * 1024) | |
149 | if large or abovemin or (lfmatcher and lfmatcher(f)): |
|
149 | if large or abovemin or (lfmatcher and lfmatcher(f)): | |
150 | lfnames.append(f) |
|
150 | lfnames.append(f) | |
151 | if ui.verbose or not exact: |
|
151 | if ui.verbose or not exact: | |
152 | ui.status(_('adding %s as a largefile\n') % name) |
|
152 | ui.status(_('adding %s as a largefile\n') % name) | |
153 |
|
153 | |||
154 | bad = [] |
|
154 | bad = [] | |
155 |
|
155 | |||
156 | # Need to lock, otherwise there could be a race condition between |
|
156 | # Need to lock, otherwise there could be a race condition between | |
157 | # when standins are created and added to the repo. |
|
157 | # when standins are created and added to the repo. | |
158 | with repo.wlock(): |
|
158 | with repo.wlock(): | |
159 | if not opts.get('dry_run'): |
|
159 | if not opts.get('dry_run'): | |
160 | standins = [] |
|
160 | standins = [] | |
161 | lfdirstate = lfutil.openlfdirstate(ui, repo) |
|
161 | lfdirstate = lfutil.openlfdirstate(ui, repo) | |
162 | for f in lfnames: |
|
162 | for f in lfnames: | |
163 | standinname = lfutil.standin(f) |
|
163 | standinname = lfutil.standin(f) | |
164 | lfutil.writestandin(repo, standinname, hash='', |
|
164 | lfutil.writestandin(repo, standinname, hash='', | |
165 | executable=lfutil.getexecutable(repo.wjoin(f))) |
|
165 | executable=lfutil.getexecutable(repo.wjoin(f))) | |
166 | standins.append(standinname) |
|
166 | standins.append(standinname) | |
167 | if lfdirstate[f] == 'r': |
|
167 | if lfdirstate[f] == 'r': | |
168 | lfdirstate.normallookup(f) |
|
168 | lfdirstate.normallookup(f) | |
169 | else: |
|
169 | else: | |
170 | lfdirstate.add(f) |
|
170 | lfdirstate.add(f) | |
171 | lfdirstate.write() |
|
171 | lfdirstate.write() | |
172 | bad += [lfutil.splitstandin(f) |
|
172 | bad += [lfutil.splitstandin(f) | |
173 | for f in repo[None].add(standins) |
|
173 | for f in repo[None].add(standins) | |
174 | if f in m.files()] |
|
174 | if f in m.files()] | |
175 |
|
175 | |||
176 | added = [f for f in lfnames if f not in bad] |
|
176 | added = [f for f in lfnames if f not in bad] | |
177 | return added, bad |
|
177 | return added, bad | |
178 |
|
178 | |||
179 | def removelargefiles(ui, repo, isaddremove, matcher, **opts): |
|
179 | def removelargefiles(ui, repo, isaddremove, matcher, **opts): | |
180 | after = opts.get('after') |
|
180 | after = opts.get('after') | |
181 | m = composelargefilematcher(matcher, repo[None].manifest()) |
|
181 | m = composelargefilematcher(matcher, repo[None].manifest()) | |
182 | try: |
|
182 | try: | |
183 | repo.lfstatus = True |
|
183 | repo.lfstatus = True | |
184 | s = repo.status(match=m, clean=not isaddremove) |
|
184 | s = repo.status(match=m, clean=not isaddremove) | |
185 | finally: |
|
185 | finally: | |
186 | repo.lfstatus = False |
|
186 | repo.lfstatus = False | |
187 | manifest = repo[None].manifest() |
|
187 | manifest = repo[None].manifest() | |
188 | modified, added, deleted, clean = [[f for f in list |
|
188 | modified, added, deleted, clean = [[f for f in list | |
189 | if lfutil.standin(f) in manifest] |
|
189 | if lfutil.standin(f) in manifest] | |
190 | for list in (s.modified, s.added, |
|
190 | for list in (s.modified, s.added, | |
191 | s.deleted, s.clean)] |
|
191 | s.deleted, s.clean)] | |
192 |
|
192 | |||
193 | def warn(files, msg): |
|
193 | def warn(files, msg): | |
194 | for f in files: |
|
194 | for f in files: | |
195 | ui.warn(msg % m.rel(f)) |
|
195 | ui.warn(msg % m.rel(f)) | |
196 | return int(len(files) > 0) |
|
196 | return int(len(files) > 0) | |
197 |
|
197 | |||
198 | result = 0 |
|
198 | result = 0 | |
199 |
|
199 | |||
200 | if after: |
|
200 | if after: | |
201 | remove = deleted |
|
201 | remove = deleted | |
202 | result = warn(modified + added + clean, |
|
202 | result = warn(modified + added + clean, | |
203 | _('not removing %s: file still exists\n')) |
|
203 | _('not removing %s: file still exists\n')) | |
204 | else: |
|
204 | else: | |
205 | remove = deleted + clean |
|
205 | remove = deleted + clean | |
206 | result = warn(modified, _('not removing %s: file is modified (use -f' |
|
206 | result = warn(modified, _('not removing %s: file is modified (use -f' | |
207 | ' to force removal)\n')) |
|
207 | ' to force removal)\n')) | |
208 | result = warn(added, _('not removing %s: file has been marked for add' |
|
208 | result = warn(added, _('not removing %s: file has been marked for add' | |
209 | ' (use forget to undo)\n')) or result |
|
209 | ' (use forget to undo)\n')) or result | |
210 |
|
210 | |||
211 | # Need to lock because standin files are deleted then removed from the |
|
211 | # Need to lock because standin files are deleted then removed from the | |
212 | # repository and we could race in-between. |
|
212 | # repository and we could race in-between. | |
213 | with repo.wlock(): |
|
213 | with repo.wlock(): | |
214 | lfdirstate = lfutil.openlfdirstate(ui, repo) |
|
214 | lfdirstate = lfutil.openlfdirstate(ui, repo) | |
215 | for f in sorted(remove): |
|
215 | for f in sorted(remove): | |
216 | if ui.verbose or not m.exact(f): |
|
216 | if ui.verbose or not m.exact(f): | |
217 | # addremove in core gets fancy with the name, remove doesn't |
|
217 | # addremove in core gets fancy with the name, remove doesn't | |
218 | if isaddremove: |
|
218 | if isaddremove: | |
219 | name = m.uipath(f) |
|
219 | name = m.uipath(f) | |
220 | else: |
|
220 | else: | |
221 | name = m.rel(f) |
|
221 | name = m.rel(f) | |
222 | ui.status(_('removing %s\n') % name) |
|
222 | ui.status(_('removing %s\n') % name) | |
223 |
|
223 | |||
224 | if not opts.get('dry_run'): |
|
224 | if not opts.get('dry_run'): | |
225 | if not after: |
|
225 | if not after: | |
226 | util.unlinkpath(repo.wjoin(f), ignoremissing=True) |
|
226 | util.unlinkpath(repo.wjoin(f), ignoremissing=True) | |
227 |
|
227 | |||
228 | if opts.get('dry_run'): |
|
228 | if opts.get('dry_run'): | |
229 | return result |
|
229 | return result | |
230 |
|
230 | |||
231 | remove = [lfutil.standin(f) for f in remove] |
|
231 | remove = [lfutil.standin(f) for f in remove] | |
232 | # If this is being called by addremove, let the original addremove |
|
232 | # If this is being called by addremove, let the original addremove | |
233 | # function handle this. |
|
233 | # function handle this. | |
234 | if not isaddremove: |
|
234 | if not isaddremove: | |
235 | for f in remove: |
|
235 | for f in remove: | |
236 | util.unlinkpath(repo.wjoin(f), ignoremissing=True) |
|
236 | util.unlinkpath(repo.wjoin(f), ignoremissing=True) | |
237 | repo[None].forget(remove) |
|
237 | repo[None].forget(remove) | |
238 |
|
238 | |||
239 | for f in remove: |
|
239 | for f in remove: | |
240 | lfutil.synclfdirstate(repo, lfdirstate, lfutil.splitstandin(f), |
|
240 | lfutil.synclfdirstate(repo, lfdirstate, lfutil.splitstandin(f), | |
241 | False) |
|
241 | False) | |
242 |
|
242 | |||
243 | lfdirstate.write() |
|
243 | lfdirstate.write() | |
244 |
|
244 | |||
245 | return result |
|
245 | return result | |
246 |
|
246 | |||
247 | # For overriding mercurial.hgweb.webcommands so that largefiles will |
|
247 | # For overriding mercurial.hgweb.webcommands so that largefiles will | |
248 | # appear at their right place in the manifests. |
|
248 | # appear at their right place in the manifests. | |
249 | def decodepath(orig, path): |
|
249 | def decodepath(orig, path): | |
250 | return lfutil.splitstandin(path) or path |
|
250 | return lfutil.splitstandin(path) or path | |
251 |
|
251 | |||
252 | # -- Wrappers: modify existing commands -------------------------------- |
|
252 | # -- Wrappers: modify existing commands -------------------------------- | |
253 |
|
253 | |||
254 | def overrideadd(orig, ui, repo, *pats, **opts): |
|
254 | def overrideadd(orig, ui, repo, *pats, **opts): | |
255 | if opts.get('normal') and opts.get('large'): |
|
255 | if opts.get('normal') and opts.get('large'): | |
256 | raise error.Abort(_('--normal cannot be used with --large')) |
|
256 | raise error.Abort(_('--normal cannot be used with --large')) | |
257 | return orig(ui, repo, *pats, **opts) |
|
257 | return orig(ui, repo, *pats, **opts) | |
258 |
|
258 | |||
259 | def cmdutiladd(orig, ui, repo, matcher, prefix, explicitonly, **opts): |
|
259 | def cmdutiladd(orig, ui, repo, matcher, prefix, explicitonly, **opts): | |
260 | # The --normal flag short circuits this override |
|
260 | # The --normal flag short circuits this override | |
261 | if opts.get('normal'): |
|
261 | if opts.get('normal'): | |
262 | return orig(ui, repo, matcher, prefix, explicitonly, **opts) |
|
262 | return orig(ui, repo, matcher, prefix, explicitonly, **opts) | |
263 |
|
263 | |||
264 | ladded, lbad = addlargefiles(ui, repo, False, matcher, **opts) |
|
264 | ladded, lbad = addlargefiles(ui, repo, False, matcher, **opts) | |
265 | normalmatcher = composenormalfilematcher(matcher, repo[None].manifest(), |
|
265 | normalmatcher = composenormalfilematcher(matcher, repo[None].manifest(), | |
266 | ladded) |
|
266 | ladded) | |
267 | bad = orig(ui, repo, normalmatcher, prefix, explicitonly, **opts) |
|
267 | bad = orig(ui, repo, normalmatcher, prefix, explicitonly, **opts) | |
268 |
|
268 | |||
269 | bad.extend(f for f in lbad) |
|
269 | bad.extend(f for f in lbad) | |
270 | return bad |
|
270 | return bad | |
271 |
|
271 | |||
272 | def cmdutilremove(orig, ui, repo, matcher, prefix, after, force, subrepos): |
|
272 | def cmdutilremove(orig, ui, repo, matcher, prefix, after, force, subrepos): | |
273 | normalmatcher = composenormalfilematcher(matcher, repo[None].manifest()) |
|
273 | normalmatcher = composenormalfilematcher(matcher, repo[None].manifest()) | |
274 | result = orig(ui, repo, normalmatcher, prefix, after, force, subrepos) |
|
274 | result = orig(ui, repo, normalmatcher, prefix, after, force, subrepos) | |
275 | return removelargefiles(ui, repo, False, matcher, after=after, |
|
275 | return removelargefiles(ui, repo, False, matcher, after=after, | |
276 | force=force) or result |
|
276 | force=force) or result | |
277 |
|
277 | |||
278 | def overridestatusfn(orig, repo, rev2, **opts): |
|
278 | def overridestatusfn(orig, repo, rev2, **opts): | |
279 | try: |
|
279 | try: | |
280 | repo._repo.lfstatus = True |
|
280 | repo._repo.lfstatus = True | |
281 | return orig(repo, rev2, **opts) |
|
281 | return orig(repo, rev2, **opts) | |
282 | finally: |
|
282 | finally: | |
283 | repo._repo.lfstatus = False |
|
283 | repo._repo.lfstatus = False | |
284 |
|
284 | |||
285 | def overridestatus(orig, ui, repo, *pats, **opts): |
|
285 | def overridestatus(orig, ui, repo, *pats, **opts): | |
286 | try: |
|
286 | try: | |
287 | repo.lfstatus = True |
|
287 | repo.lfstatus = True | |
288 | return orig(ui, repo, *pats, **opts) |
|
288 | return orig(ui, repo, *pats, **opts) | |
289 | finally: |
|
289 | finally: | |
290 | repo.lfstatus = False |
|
290 | repo.lfstatus = False | |
291 |
|
291 | |||
292 | def overridedirty(orig, repo, ignoreupdate=False): |
|
292 | def overridedirty(orig, repo, ignoreupdate=False): | |
293 | try: |
|
293 | try: | |
294 | repo._repo.lfstatus = True |
|
294 | repo._repo.lfstatus = True | |
295 | return orig(repo, ignoreupdate) |
|
295 | return orig(repo, ignoreupdate) | |
296 | finally: |
|
296 | finally: | |
297 | repo._repo.lfstatus = False |
|
297 | repo._repo.lfstatus = False | |
298 |
|
298 | |||
299 | def overridelog(orig, ui, repo, *pats, **opts): |
|
299 | def overridelog(orig, ui, repo, *pats, **opts): | |
300 | def overridematchandpats(ctx, pats=(), opts=None, globbed=False, |
|
300 | def overridematchandpats(ctx, pats=(), opts=None, globbed=False, | |
301 | default='relpath', badfn=None): |
|
301 | default='relpath', badfn=None): | |
302 | """Matcher that merges root directory with .hglf, suitable for log. |
|
302 | """Matcher that merges root directory with .hglf, suitable for log. | |
303 | It is still possible to match .hglf directly. |
|
303 | It is still possible to match .hglf directly. | |
304 | For any listed files run log on the standin too. |
|
304 | For any listed files run log on the standin too. | |
305 | matchfn tries both the given filename and with .hglf stripped. |
|
305 | matchfn tries both the given filename and with .hglf stripped. | |
306 | """ |
|
306 | """ | |
307 | if opts is None: |
|
307 | if opts is None: | |
308 | opts = {} |
|
308 | opts = {} | |
309 | matchandpats = oldmatchandpats(ctx, pats, opts, globbed, default, |
|
309 | matchandpats = oldmatchandpats(ctx, pats, opts, globbed, default, | |
310 | badfn=badfn) |
|
310 | badfn=badfn) | |
311 | m, p = copy.copy(matchandpats) |
|
311 | m, p = copy.copy(matchandpats) | |
312 |
|
312 | |||
313 | if m.always(): |
|
313 | if m.always(): | |
314 | # We want to match everything anyway, so there's no benefit trying |
|
314 | # We want to match everything anyway, so there's no benefit trying | |
315 | # to add standins. |
|
315 | # to add standins. | |
316 | return matchandpats |
|
316 | return matchandpats | |
317 |
|
317 | |||
318 | pats = set(p) |
|
318 | pats = set(p) | |
319 |
|
319 | |||
320 | def fixpats(pat, tostandin=lfutil.standin): |
|
320 | def fixpats(pat, tostandin=lfutil.standin): | |
321 | if pat.startswith('set:'): |
|
321 | if pat.startswith('set:'): | |
322 | return pat |
|
322 | return pat | |
323 |
|
323 | |||
324 | kindpat = matchmod._patsplit(pat, None) |
|
324 | kindpat = matchmod._patsplit(pat, None) | |
325 |
|
325 | |||
326 | if kindpat[0] is not None: |
|
326 | if kindpat[0] is not None: | |
327 | return kindpat[0] + ':' + tostandin(kindpat[1]) |
|
327 | return kindpat[0] + ':' + tostandin(kindpat[1]) | |
328 | return tostandin(kindpat[1]) |
|
328 | return tostandin(kindpat[1]) | |
329 |
|
329 | |||
330 | if m._cwd: |
|
330 | if m._cwd: | |
331 | hglf = lfutil.shortname |
|
331 | hglf = lfutil.shortname | |
332 | back = util.pconvert(m.rel(hglf)[:-len(hglf)]) |
|
332 | back = util.pconvert(m.rel(hglf)[:-len(hglf)]) | |
333 |
|
333 | |||
334 | def tostandin(f): |
|
334 | def tostandin(f): | |
335 | # The file may already be a standin, so truncate the back |
|
335 | # The file may already be a standin, so truncate the back | |
336 | # prefix and test before mangling it. This avoids turning |
|
336 | # prefix and test before mangling it. This avoids turning | |
337 | # 'glob:../.hglf/foo*' into 'glob:../.hglf/../.hglf/foo*'. |
|
337 | # 'glob:../.hglf/foo*' into 'glob:../.hglf/../.hglf/foo*'. | |
338 | if f.startswith(back) and lfutil.splitstandin(f[len(back):]): |
|
338 | if f.startswith(back) and lfutil.splitstandin(f[len(back):]): | |
339 | return f |
|
339 | return f | |
340 |
|
340 | |||
341 | # An absolute path is from outside the repo, so truncate the |
|
341 | # An absolute path is from outside the repo, so truncate the | |
342 | # path to the root before building the standin. Otherwise cwd |
|
342 | # path to the root before building the standin. Otherwise cwd | |
343 | # is somewhere in the repo, relative to root, and needs to be |
|
343 | # is somewhere in the repo, relative to root, and needs to be | |
344 | # prepended before building the standin. |
|
344 | # prepended before building the standin. | |
345 | if os.path.isabs(m._cwd): |
|
345 | if os.path.isabs(m._cwd): | |
346 | f = f[len(back):] |
|
346 | f = f[len(back):] | |
347 | else: |
|
347 | else: | |
348 | f = m._cwd + '/' + f |
|
348 | f = m._cwd + '/' + f | |
349 | return back + lfutil.standin(f) |
|
349 | return back + lfutil.standin(f) | |
350 |
|
350 | |||
351 | pats.update(fixpats(f, tostandin) for f in p) |
|
351 | pats.update(fixpats(f, tostandin) for f in p) | |
352 | else: |
|
352 | else: | |
353 | def tostandin(f): |
|
353 | def tostandin(f): | |
354 | if lfutil.splitstandin(f): |
|
354 | if lfutil.splitstandin(f): | |
355 | return f |
|
355 | return f | |
356 | return lfutil.standin(f) |
|
356 | return lfutil.standin(f) | |
357 | pats.update(fixpats(f, tostandin) for f in p) |
|
357 | pats.update(fixpats(f, tostandin) for f in p) | |
358 |
|
358 | |||
359 | for i in range(0, len(m._files)): |
|
359 | for i in range(0, len(m._files)): | |
360 | # Don't add '.hglf' to m.files, since that is already covered by '.' |
|
360 | # Don't add '.hglf' to m.files, since that is already covered by '.' | |
361 | if m._files[i] == '.': |
|
361 | if m._files[i] == '.': | |
362 | continue |
|
362 | continue | |
363 | standin = lfutil.standin(m._files[i]) |
|
363 | standin = lfutil.standin(m._files[i]) | |
364 | # If the "standin" is a directory, append instead of replace to |
|
364 | # If the "standin" is a directory, append instead of replace to | |
365 | # support naming a directory on the command line with only |
|
365 | # support naming a directory on the command line with only | |
366 | # largefiles. The original directory is kept to support normal |
|
366 | # largefiles. The original directory is kept to support normal | |
367 | # files. |
|
367 | # files. | |
368 | if standin in repo[ctx.node()]: |
|
368 | if standin in repo[ctx.node()]: | |
369 | m._files[i] = standin |
|
369 | m._files[i] = standin | |
370 | elif m._files[i] not in repo[ctx.node()] \ |
|
370 | elif m._files[i] not in repo[ctx.node()] \ | |
371 | and repo.wvfs.isdir(standin): |
|
371 | and repo.wvfs.isdir(standin): | |
372 | m._files.append(standin) |
|
372 | m._files.append(standin) | |
373 |
|
373 | |||
374 | m._fileroots = set(m._files) |
|
374 | m._fileroots = set(m._files) | |
375 | m._always = False |
|
375 | m._always = False | |
376 | origmatchfn = m.matchfn |
|
376 | origmatchfn = m.matchfn | |
377 | def lfmatchfn(f): |
|
377 | def lfmatchfn(f): | |
378 | lf = lfutil.splitstandin(f) |
|
378 | lf = lfutil.splitstandin(f) | |
379 | if lf is not None and origmatchfn(lf): |
|
379 | if lf is not None and origmatchfn(lf): | |
380 | return True |
|
380 | return True | |
381 | r = origmatchfn(f) |
|
381 | r = origmatchfn(f) | |
382 | return r |
|
382 | return r | |
383 | m.matchfn = lfmatchfn |
|
383 | m.matchfn = lfmatchfn | |
384 |
|
384 | |||
385 | ui.debug('updated patterns: %s\n' % sorted(pats)) |
|
385 | ui.debug('updated patterns: %s\n' % sorted(pats)) | |
386 | return m, pats |
|
386 | return m, pats | |
387 |
|
387 | |||
388 | # For hg log --patch, the match object is used in two different senses: |
|
388 | # For hg log --patch, the match object is used in two different senses: | |
389 | # (1) to determine what revisions should be printed out, and |
|
389 | # (1) to determine what revisions should be printed out, and | |
390 | # (2) to determine what files to print out diffs for. |
|
390 | # (2) to determine what files to print out diffs for. | |
391 | # The magic matchandpats override should be used for case (1) but not for |
|
391 | # The magic matchandpats override should be used for case (1) but not for | |
392 | # case (2). |
|
392 | # case (2). | |
393 | def overridemakelogfilematcher(repo, pats, opts, badfn=None): |
|
393 | def overridemakelogfilematcher(repo, pats, opts, badfn=None): | |
394 | wctx = repo[None] |
|
394 | wctx = repo[None] | |
395 | match, pats = oldmatchandpats(wctx, pats, opts, badfn=badfn) |
|
395 | match, pats = oldmatchandpats(wctx, pats, opts, badfn=badfn) | |
396 | return lambda rev: match |
|
396 | return lambda rev: match | |
397 |
|
397 | |||
398 | oldmatchandpats = installmatchandpatsfn(overridematchandpats) |
|
398 | oldmatchandpats = installmatchandpatsfn(overridematchandpats) | |
399 | oldmakelogfilematcher = cmdutil._makenofollowlogfilematcher |
|
399 | oldmakelogfilematcher = cmdutil._makenofollowlogfilematcher | |
400 | setattr(cmdutil, '_makenofollowlogfilematcher', overridemakelogfilematcher) |
|
400 | setattr(cmdutil, '_makenofollowlogfilematcher', overridemakelogfilematcher) | |
401 |
|
401 | |||
402 | try: |
|
402 | try: | |
403 | return orig(ui, repo, *pats, **opts) |
|
403 | return orig(ui, repo, *pats, **opts) | |
404 | finally: |
|
404 | finally: | |
405 | restorematchandpatsfn() |
|
405 | restorematchandpatsfn() | |
406 | setattr(cmdutil, '_makenofollowlogfilematcher', oldmakelogfilematcher) |
|
406 | setattr(cmdutil, '_makenofollowlogfilematcher', oldmakelogfilematcher) | |
407 |
|
407 | |||
408 | def overrideverify(orig, ui, repo, *pats, **opts): |
|
408 | def overrideverify(orig, ui, repo, *pats, **opts): | |
409 | large = opts.pop('large', False) |
|
409 | large = opts.pop('large', False) | |
410 | all = opts.pop('lfa', False) |
|
410 | all = opts.pop('lfa', False) | |
411 | contents = opts.pop('lfc', False) |
|
411 | contents = opts.pop('lfc', False) | |
412 |
|
412 | |||
413 | result = orig(ui, repo, *pats, **opts) |
|
413 | result = orig(ui, repo, *pats, **opts) | |
414 | if large or all or contents: |
|
414 | if large or all or contents: | |
415 | result = result or lfcommands.verifylfiles(ui, repo, all, contents) |
|
415 | result = result or lfcommands.verifylfiles(ui, repo, all, contents) | |
416 | return result |
|
416 | return result | |
417 |
|
417 | |||
418 | def overridedebugstate(orig, ui, repo, *pats, **opts): |
|
418 | def overridedebugstate(orig, ui, repo, *pats, **opts): | |
419 | large = opts.pop('large', False) |
|
419 | large = opts.pop('large', False) | |
420 | if large: |
|
420 | if large: | |
421 | class fakerepo(object): |
|
421 | class fakerepo(object): | |
422 | dirstate = lfutil.openlfdirstate(ui, repo) |
|
422 | dirstate = lfutil.openlfdirstate(ui, repo) | |
423 | orig(ui, fakerepo, *pats, **opts) |
|
423 | orig(ui, fakerepo, *pats, **opts) | |
424 | else: |
|
424 | else: | |
425 | orig(ui, repo, *pats, **opts) |
|
425 | orig(ui, repo, *pats, **opts) | |
426 |
|
426 | |||
427 | # Before starting the manifest merge, merge.updates will call |
|
427 | # Before starting the manifest merge, merge.updates will call | |
428 | # _checkunknownfile to check if there are any files in the merged-in |
|
428 | # _checkunknownfile to check if there are any files in the merged-in | |
429 | # changeset that collide with unknown files in the working copy. |
|
429 | # changeset that collide with unknown files in the working copy. | |
430 | # |
|
430 | # | |
431 | # The largefiles are seen as unknown, so this prevents us from merging |
|
431 | # The largefiles are seen as unknown, so this prevents us from merging | |
432 | # in a file 'foo' if we already have a largefile with the same name. |
|
432 | # in a file 'foo' if we already have a largefile with the same name. | |
433 | # |
|
433 | # | |
434 | # The overridden function filters the unknown files by removing any |
|
434 | # The overridden function filters the unknown files by removing any | |
435 | # largefiles. This makes the merge proceed and we can then handle this |
|
435 | # largefiles. This makes the merge proceed and we can then handle this | |
436 | # case further in the overridden calculateupdates function below. |
|
436 | # case further in the overridden calculateupdates function below. | |
437 | def overridecheckunknownfile(origfn, repo, wctx, mctx, f, f2=None): |
|
437 | def overridecheckunknownfile(origfn, repo, wctx, mctx, f, f2=None): | |
438 | if lfutil.standin(repo.dirstate.normalize(f)) in wctx: |
|
438 | if lfutil.standin(repo.dirstate.normalize(f)) in wctx: | |
439 | return False |
|
439 | return False | |
440 | return origfn(repo, wctx, mctx, f, f2) |
|
440 | return origfn(repo, wctx, mctx, f, f2) | |
441 |
|
441 | |||
442 | # The manifest merge handles conflicts on the manifest level. We want |
|
442 | # The manifest merge handles conflicts on the manifest level. We want | |
443 | # to handle changes in largefile-ness of files at this level too. |
|
443 | # to handle changes in largefile-ness of files at this level too. | |
444 | # |
|
444 | # | |
445 | # The strategy is to run the original calculateupdates and then process |
|
445 | # The strategy is to run the original calculateupdates and then process | |
446 | # the action list it outputs. There are two cases we need to deal with: |
|
446 | # the action list it outputs. There are two cases we need to deal with: | |
447 | # |
|
447 | # | |
448 | # 1. Normal file in p1, largefile in p2. Here the largefile is |
|
448 | # 1. Normal file in p1, largefile in p2. Here the largefile is | |
449 | # detected via its standin file, which will enter the working copy |
|
449 | # detected via its standin file, which will enter the working copy | |
450 | # with a "get" action. It is not "merge" since the standin is all |
|
450 | # with a "get" action. It is not "merge" since the standin is all | |
451 | # Mercurial is concerned with at this level -- the link to the |
|
451 | # Mercurial is concerned with at this level -- the link to the | |
452 | # existing normal file is not relevant here. |
|
452 | # existing normal file is not relevant here. | |
453 | # |
|
453 | # | |
454 | # 2. Largefile in p1, normal file in p2. Here we get a "merge" action |
|
454 | # 2. Largefile in p1, normal file in p2. Here we get a "merge" action | |
455 | # since the largefile will be present in the working copy and |
|
455 | # since the largefile will be present in the working copy and | |
456 | # different from the normal file in p2. Mercurial therefore |
|
456 | # different from the normal file in p2. Mercurial therefore | |
457 | # triggers a merge action. |
|
457 | # triggers a merge action. | |
458 | # |
|
458 | # | |
459 | # In both cases, we prompt the user and emit new actions to either |
|
459 | # In both cases, we prompt the user and emit new actions to either | |
460 | # remove the standin (if the normal file was kept) or to remove the |
|
460 | # remove the standin (if the normal file was kept) or to remove the | |
461 | # normal file and get the standin (if the largefile was kept). The |
|
461 | # normal file and get the standin (if the largefile was kept). The | |
462 | # default prompt answer is to use the largefile version since it was |
|
462 | # default prompt answer is to use the largefile version since it was | |
463 | # presumably changed on purpose. |
|
463 | # presumably changed on purpose. | |
464 | # |
|
464 | # | |
465 | # Finally, the merge.applyupdates function will then take care of |
|
465 | # Finally, the merge.applyupdates function will then take care of | |
466 | # writing the files into the working copy and lfcommands.updatelfiles |
|
466 | # writing the files into the working copy and lfcommands.updatelfiles | |
467 | # will update the largefiles. |
|
467 | # will update the largefiles. | |
468 | def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force, |
|
468 | def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force, | |
469 | acceptremote, *args, **kwargs): |
|
469 | acceptremote, *args, **kwargs): | |
470 | overwrite = force and not branchmerge |
|
470 | overwrite = force and not branchmerge | |
471 | actions, diverge, renamedelete = origfn( |
|
471 | actions, diverge, renamedelete = origfn( | |
472 | repo, p1, p2, pas, branchmerge, force, acceptremote, *args, **kwargs) |
|
472 | repo, p1, p2, pas, branchmerge, force, acceptremote, *args, **kwargs) | |
473 |
|
473 | |||
474 | if overwrite: |
|
474 | if overwrite: | |
475 | return actions, diverge, renamedelete |
|
475 | return actions, diverge, renamedelete | |
476 |
|
476 | |||
477 | # Convert to dictionary with filename as key and action as value. |
|
477 | # Convert to dictionary with filename as key and action as value. | |
478 | lfiles = set() |
|
478 | lfiles = set() | |
479 | for f in actions: |
|
479 | for f in actions: | |
480 | splitstandin = lfutil.splitstandin(f) |
|
480 | splitstandin = lfutil.splitstandin(f) | |
481 | if splitstandin in p1: |
|
481 | if splitstandin in p1: | |
482 | lfiles.add(splitstandin) |
|
482 | lfiles.add(splitstandin) | |
483 | elif lfutil.standin(f) in p1: |
|
483 | elif lfutil.standin(f) in p1: | |
484 | lfiles.add(f) |
|
484 | lfiles.add(f) | |
485 |
|
485 | |||
486 | for lfile in sorted(lfiles): |
|
486 | for lfile in sorted(lfiles): | |
487 | standin = lfutil.standin(lfile) |
|
487 | standin = lfutil.standin(lfile) | |
488 | (lm, largs, lmsg) = actions.get(lfile, (None, None, None)) |
|
488 | (lm, largs, lmsg) = actions.get(lfile, (None, None, None)) | |
489 | (sm, sargs, smsg) = actions.get(standin, (None, None, None)) |
|
489 | (sm, sargs, smsg) = actions.get(standin, (None, None, None)) | |
490 | if sm in ('g', 'dc') and lm != 'r': |
|
490 | if sm in ('g', 'dc') and lm != 'r': | |
491 | if sm == 'dc': |
|
491 | if sm == 'dc': | |
492 | f1, f2, fa, move, anc = sargs |
|
492 | f1, f2, fa, move, anc = sargs | |
493 | sargs = (p2[f2].flags(), False) |
|
493 | sargs = (p2[f2].flags(), False) | |
494 | # Case 1: normal file in the working copy, largefile in |
|
494 | # Case 1: normal file in the working copy, largefile in | |
495 | # the second parent |
|
495 | # the second parent | |
496 | usermsg = _('remote turned local normal file %s into a largefile\n' |
|
496 | usermsg = _('remote turned local normal file %s into a largefile\n' | |
497 | 'use (l)argefile or keep (n)ormal file?' |
|
497 | 'use (l)argefile or keep (n)ormal file?' | |
498 | '$$ &Largefile $$ &Normal file') % lfile |
|
498 | '$$ &Largefile $$ &Normal file') % lfile | |
499 | if repo.ui.promptchoice(usermsg, 0) == 0: # pick remote largefile |
|
499 | if repo.ui.promptchoice(usermsg, 0) == 0: # pick remote largefile | |
500 | actions[lfile] = ('r', None, 'replaced by standin') |
|
500 | actions[lfile] = ('r', None, 'replaced by standin') | |
501 | actions[standin] = ('g', sargs, 'replaces standin') |
|
501 | actions[standin] = ('g', sargs, 'replaces standin') | |
502 | else: # keep local normal file |
|
502 | else: # keep local normal file | |
503 | actions[lfile] = ('k', None, 'replaces standin') |
|
503 | actions[lfile] = ('k', None, 'replaces standin') | |
504 | if branchmerge: |
|
504 | if branchmerge: | |
505 | actions[standin] = ('k', None, 'replaced by non-standin') |
|
505 | actions[standin] = ('k', None, 'replaced by non-standin') | |
506 | else: |
|
506 | else: | |
507 | actions[standin] = ('r', None, 'replaced by non-standin') |
|
507 | actions[standin] = ('r', None, 'replaced by non-standin') | |
508 | elif lm in ('g', 'dc') and sm != 'r': |
|
508 | elif lm in ('g', 'dc') and sm != 'r': | |
509 | if lm == 'dc': |
|
509 | if lm == 'dc': | |
510 | f1, f2, fa, move, anc = largs |
|
510 | f1, f2, fa, move, anc = largs | |
511 | largs = (p2[f2].flags(), False) |
|
511 | largs = (p2[f2].flags(), False) | |
512 | # Case 2: largefile in the working copy, normal file in |
|
512 | # Case 2: largefile in the working copy, normal file in | |
513 | # the second parent |
|
513 | # the second parent | |
514 | usermsg = _('remote turned local largefile %s into a normal file\n' |
|
514 | usermsg = _('remote turned local largefile %s into a normal file\n' | |
515 | 'keep (l)argefile or use (n)ormal file?' |
|
515 | 'keep (l)argefile or use (n)ormal file?' | |
516 | '$$ &Largefile $$ &Normal file') % lfile |
|
516 | '$$ &Largefile $$ &Normal file') % lfile | |
517 | if repo.ui.promptchoice(usermsg, 0) == 0: # keep local largefile |
|
517 | if repo.ui.promptchoice(usermsg, 0) == 0: # keep local largefile | |
518 | if branchmerge: |
|
518 | if branchmerge: | |
519 | # largefile can be restored from standin safely |
|
519 | # largefile can be restored from standin safely | |
520 | actions[lfile] = ('k', None, 'replaced by standin') |
|
520 | actions[lfile] = ('k', None, 'replaced by standin') | |
521 | actions[standin] = ('k', None, 'replaces standin') |
|
521 | actions[standin] = ('k', None, 'replaces standin') | |
522 | else: |
|
522 | else: | |
523 | # "lfile" should be marked as "removed" without |
|
523 | # "lfile" should be marked as "removed" without | |
524 | # removal of itself |
|
524 | # removal of itself | |
525 | actions[lfile] = ('lfmr', None, |
|
525 | actions[lfile] = ('lfmr', None, | |
526 | 'forget non-standin largefile') |
|
526 | 'forget non-standin largefile') | |
527 |
|
527 | |||
528 | # linear-merge should treat this largefile as 're-added' |
|
528 | # linear-merge should treat this largefile as 're-added' | |
529 | actions[standin] = ('a', None, 'keep standin') |
|
529 | actions[standin] = ('a', None, 'keep standin') | |
530 | else: # pick remote normal file |
|
530 | else: # pick remote normal file | |
531 | actions[lfile] = ('g', largs, 'replaces standin') |
|
531 | actions[lfile] = ('g', largs, 'replaces standin') | |
532 | actions[standin] = ('r', None, 'replaced by non-standin') |
|
532 | actions[standin] = ('r', None, 'replaced by non-standin') | |
533 |
|
533 | |||
534 | return actions, diverge, renamedelete |
|
534 | return actions, diverge, renamedelete | |
535 |
|
535 | |||
536 | def mergerecordupdates(orig, repo, actions, branchmerge): |
|
536 | def mergerecordupdates(orig, repo, actions, branchmerge): | |
537 | if 'lfmr' in actions: |
|
537 | if 'lfmr' in actions: | |
538 | lfdirstate = lfutil.openlfdirstate(repo.ui, repo) |
|
538 | lfdirstate = lfutil.openlfdirstate(repo.ui, repo) | |
539 | for lfile, args, msg in actions['lfmr']: |
|
539 | for lfile, args, msg in actions['lfmr']: | |
540 | # this should be executed before 'orig', to execute 'remove' |
|
540 | # this should be executed before 'orig', to execute 'remove' | |
541 | # before all other actions |
|
541 | # before all other actions | |
542 | repo.dirstate.remove(lfile) |
|
542 | repo.dirstate.remove(lfile) | |
543 | # make sure lfile doesn't get synclfdirstate'd as normal |
|
543 | # make sure lfile doesn't get synclfdirstate'd as normal | |
544 | lfdirstate.add(lfile) |
|
544 | lfdirstate.add(lfile) | |
545 | lfdirstate.write() |
|
545 | lfdirstate.write() | |
546 |
|
546 | |||
547 | return orig(repo, actions, branchmerge) |
|
547 | return orig(repo, actions, branchmerge) | |
548 |
|
548 | |||
549 | # Override filemerge to prompt the user about how they wish to merge |
|
549 | # Override filemerge to prompt the user about how they wish to merge | |
550 | # largefiles. This will handle identical edits without prompting the user. |
|
550 | # largefiles. This will handle identical edits without prompting the user. | |
551 | def overridefilemerge(origfn, premerge, repo, mynode, orig, fcd, fco, fca, |
|
551 | def overridefilemerge(origfn, premerge, repo, mynode, orig, fcd, fco, fca, | |
552 | labels=None): |
|
552 | labels=None): | |
553 | if not lfutil.isstandin(orig) or fcd.isabsent() or fco.isabsent(): |
|
553 | if not lfutil.isstandin(orig) or fcd.isabsent() or fco.isabsent(): | |
554 | return origfn(premerge, repo, mynode, orig, fcd, fco, fca, |
|
554 | return origfn(premerge, repo, mynode, orig, fcd, fco, fca, | |
555 | labels=labels) |
|
555 | labels=labels) | |
556 |
|
556 | |||
557 | ahash = fca.data().strip().lower() |
|
557 | ahash = fca.data().strip().lower() | |
558 | dhash = fcd.data().strip().lower() |
|
558 | dhash = fcd.data().strip().lower() | |
559 | ohash = fco.data().strip().lower() |
|
559 | ohash = fco.data().strip().lower() | |
560 | if (ohash != ahash and |
|
560 | if (ohash != ahash and | |
561 | ohash != dhash and |
|
561 | ohash != dhash and | |
562 | (dhash == ahash or |
|
562 | (dhash == ahash or | |
563 | repo.ui.promptchoice( |
|
563 | repo.ui.promptchoice( | |
564 | _('largefile %s has a merge conflict\nancestor was %s\n' |
|
564 | _('largefile %s has a merge conflict\nancestor was %s\n' | |
565 | 'keep (l)ocal %s or\ntake (o)ther %s?' |
|
565 | 'keep (l)ocal %s or\ntake (o)ther %s?' | |
566 | '$$ &Local $$ &Other') % |
|
566 | '$$ &Local $$ &Other') % | |
567 | (lfutil.splitstandin(orig), ahash, dhash, ohash), |
|
567 | (lfutil.splitstandin(orig), ahash, dhash, ohash), | |
568 | 0) == 1)): |
|
568 | 0) == 1)): | |
569 | repo.wwrite(fcd.path(), fco.data(), fco.flags()) |
|
569 | repo.wwrite(fcd.path(), fco.data(), fco.flags()) | |
570 | return True, 0, False |
|
570 | return True, 0, False | |
571 |
|
571 | |||
572 | def copiespathcopies(orig, ctx1, ctx2, match=None): |
|
572 | def copiespathcopies(orig, ctx1, ctx2, match=None): | |
573 | copies = orig(ctx1, ctx2, match=match) |
|
573 | copies = orig(ctx1, ctx2, match=match) | |
574 | updated = {} |
|
574 | updated = {} | |
575 |
|
575 | |||
576 | for k, v in copies.iteritems(): |
|
576 | for k, v in copies.iteritems(): | |
577 | updated[lfutil.splitstandin(k) or k] = lfutil.splitstandin(v) or v |
|
577 | updated[lfutil.splitstandin(k) or k] = lfutil.splitstandin(v) or v | |
578 |
|
578 | |||
579 | return updated |
|
579 | return updated | |
580 |
|
580 | |||
581 | # Copy first changes the matchers to match standins instead of |
|
581 | # Copy first changes the matchers to match standins instead of | |
582 | # largefiles. Then it overrides util.copyfile in that function it |
|
582 | # largefiles. Then it overrides util.copyfile in that function it | |
583 | # checks if the destination largefile already exists. It also keeps a |
|
583 | # checks if the destination largefile already exists. It also keeps a | |
584 | # list of copied files so that the largefiles can be copied and the |
|
584 | # list of copied files so that the largefiles can be copied and the | |
585 | # dirstate updated. |
|
585 | # dirstate updated. | |
586 | def overridecopy(orig, ui, repo, pats, opts, rename=False): |
|
586 | def overridecopy(orig, ui, repo, pats, opts, rename=False): | |
587 | # doesn't remove largefile on rename |
|
587 | # doesn't remove largefile on rename | |
588 | if len(pats) < 2: |
|
588 | if len(pats) < 2: | |
589 | # this isn't legal, let the original function deal with it |
|
589 | # this isn't legal, let the original function deal with it | |
590 | return orig(ui, repo, pats, opts, rename) |
|
590 | return orig(ui, repo, pats, opts, rename) | |
591 |
|
591 | |||
592 | # This could copy both lfiles and normal files in one command, |
|
592 | # This could copy both lfiles and normal files in one command, | |
593 | # but we don't want to do that. First replace their matcher to |
|
593 | # but we don't want to do that. First replace their matcher to | |
594 | # only match normal files and run it, then replace it to just |
|
594 | # only match normal files and run it, then replace it to just | |
595 | # match largefiles and run it again. |
|
595 | # match largefiles and run it again. | |
596 | nonormalfiles = False |
|
596 | nonormalfiles = False | |
597 | nolfiles = False |
|
597 | nolfiles = False | |
598 | installnormalfilesmatchfn(repo[None].manifest()) |
|
598 | installnormalfilesmatchfn(repo[None].manifest()) | |
599 | try: |
|
599 | try: | |
600 | result = orig(ui, repo, pats, opts, rename) |
|
600 | result = orig(ui, repo, pats, opts, rename) | |
601 | except error.Abort as e: |
|
601 | except error.Abort as e: | |
602 | if str(e) != _('no files to copy'): |
|
602 | if str(e) != _('no files to copy'): | |
603 | raise e |
|
603 | raise e | |
604 | else: |
|
604 | else: | |
605 | nonormalfiles = True |
|
605 | nonormalfiles = True | |
606 | result = 0 |
|
606 | result = 0 | |
607 | finally: |
|
607 | finally: | |
608 | restorematchfn() |
|
608 | restorematchfn() | |
609 |
|
609 | |||
610 | # The first rename can cause our current working directory to be removed. |
|
610 | # The first rename can cause our current working directory to be removed. | |
611 | # In that case there is nothing left to copy/rename so just quit. |
|
611 | # In that case there is nothing left to copy/rename so just quit. | |
612 | try: |
|
612 | try: | |
613 | repo.getcwd() |
|
613 | repo.getcwd() | |
614 | except OSError: |
|
614 | except OSError: | |
615 | return result |
|
615 | return result | |
616 |
|
616 | |||
617 | def makestandin(relpath): |
|
617 | def makestandin(relpath): | |
618 | path = pathutil.canonpath(repo.root, repo.getcwd(), relpath) |
|
618 | path = pathutil.canonpath(repo.root, repo.getcwd(), relpath) | |
619 | return repo.wvfs.join(lfutil.standin(path)) |
|
619 | return repo.wvfs.join(lfutil.standin(path)) | |
620 |
|
620 | |||
621 | fullpats = scmutil.expandpats(pats) |
|
621 | fullpats = scmutil.expandpats(pats) | |
622 | dest = fullpats[-1] |
|
622 | dest = fullpats[-1] | |
623 |
|
623 | |||
624 | if os.path.isdir(dest): |
|
624 | if os.path.isdir(dest): | |
625 | if not os.path.isdir(makestandin(dest)): |
|
625 | if not os.path.isdir(makestandin(dest)): | |
626 | os.makedirs(makestandin(dest)) |
|
626 | os.makedirs(makestandin(dest)) | |
627 |
|
627 | |||
628 | try: |
|
628 | try: | |
629 | # When we call orig below it creates the standins but we don't add |
|
629 | # When we call orig below it creates the standins but we don't add | |
630 | # them to the dir state until later so lock during that time. |
|
630 | # them to the dir state until later so lock during that time. | |
631 | wlock = repo.wlock() |
|
631 | wlock = repo.wlock() | |
632 |
|
632 | |||
633 | manifest = repo[None].manifest() |
|
633 | manifest = repo[None].manifest() | |
634 | def overridematch(ctx, pats=(), opts=None, globbed=False, |
|
634 | def overridematch(ctx, pats=(), opts=None, globbed=False, | |
635 | default='relpath', badfn=None): |
|
635 | default='relpath', badfn=None): | |
636 | if opts is None: |
|
636 | if opts is None: | |
637 | opts = {} |
|
637 | opts = {} | |
638 | newpats = [] |
|
638 | newpats = [] | |
639 | # The patterns were previously mangled to add the standin |
|
639 | # The patterns were previously mangled to add the standin | |
640 | # directory; we need to remove that now |
|
640 | # directory; we need to remove that now | |
641 | for pat in pats: |
|
641 | for pat in pats: | |
642 | if matchmod.patkind(pat) is None and lfutil.shortname in pat: |
|
642 | if matchmod.patkind(pat) is None and lfutil.shortname in pat: | |
643 | newpats.append(pat.replace(lfutil.shortname, '')) |
|
643 | newpats.append(pat.replace(lfutil.shortname, '')) | |
644 | else: |
|
644 | else: | |
645 | newpats.append(pat) |
|
645 | newpats.append(pat) | |
646 | match = oldmatch(ctx, newpats, opts, globbed, default, badfn=badfn) |
|
646 | match = oldmatch(ctx, newpats, opts, globbed, default, badfn=badfn) | |
647 | m = copy.copy(match) |
|
647 | m = copy.copy(match) | |
648 | lfile = lambda f: lfutil.standin(f) in manifest |
|
648 | lfile = lambda f: lfutil.standin(f) in manifest | |
649 | m._files = [lfutil.standin(f) for f in m._files if lfile(f)] |
|
649 | m._files = [lfutil.standin(f) for f in m._files if lfile(f)] | |
650 | m._fileroots = set(m._files) |
|
650 | m._fileroots = set(m._files) | |
651 | origmatchfn = m.matchfn |
|
651 | origmatchfn = m.matchfn | |
652 | m.matchfn = lambda f: (lfutil.isstandin(f) and |
|
652 | m.matchfn = lambda f: (lfutil.isstandin(f) and | |
653 | (f in manifest) and |
|
653 | (f in manifest) and | |
654 | origmatchfn(lfutil.splitstandin(f)) or |
|
654 | origmatchfn(lfutil.splitstandin(f)) or | |
655 | None) |
|
655 | None) | |
656 | return m |
|
656 | return m | |
657 | oldmatch = installmatchfn(overridematch) |
|
657 | oldmatch = installmatchfn(overridematch) | |
658 | listpats = [] |
|
658 | listpats = [] | |
659 | for pat in pats: |
|
659 | for pat in pats: | |
660 | if matchmod.patkind(pat) is not None: |
|
660 | if matchmod.patkind(pat) is not None: | |
661 | listpats.append(pat) |
|
661 | listpats.append(pat) | |
662 | else: |
|
662 | else: | |
663 | listpats.append(makestandin(pat)) |
|
663 | listpats.append(makestandin(pat)) | |
664 |
|
664 | |||
665 | try: |
|
665 | try: | |
666 | origcopyfile = util.copyfile |
|
666 | origcopyfile = util.copyfile | |
667 | copiedfiles = [] |
|
667 | copiedfiles = [] | |
668 | def overridecopyfile(src, dest): |
|
668 | def overridecopyfile(src, dest): | |
669 | if (lfutil.shortname in src and |
|
669 | if (lfutil.shortname in src and | |
670 | dest.startswith(repo.wjoin(lfutil.shortname))): |
|
670 | dest.startswith(repo.wjoin(lfutil.shortname))): | |
671 | destlfile = dest.replace(lfutil.shortname, '') |
|
671 | destlfile = dest.replace(lfutil.shortname, '') | |
672 | if not opts['force'] and os.path.exists(destlfile): |
|
672 | if not opts['force'] and os.path.exists(destlfile): | |
673 | raise IOError('', |
|
673 | raise IOError('', | |
674 | _('destination largefile already exists')) |
|
674 | _('destination largefile already exists')) | |
675 | copiedfiles.append((src, dest)) |
|
675 | copiedfiles.append((src, dest)) | |
676 | origcopyfile(src, dest) |
|
676 | origcopyfile(src, dest) | |
677 |
|
677 | |||
678 | util.copyfile = overridecopyfile |
|
678 | util.copyfile = overridecopyfile | |
679 | result += orig(ui, repo, listpats, opts, rename) |
|
679 | result += orig(ui, repo, listpats, opts, rename) | |
680 | finally: |
|
680 | finally: | |
681 | util.copyfile = origcopyfile |
|
681 | util.copyfile = origcopyfile | |
682 |
|
682 | |||
683 | lfdirstate = lfutil.openlfdirstate(ui, repo) |
|
683 | lfdirstate = lfutil.openlfdirstate(ui, repo) | |
684 | for (src, dest) in copiedfiles: |
|
684 | for (src, dest) in copiedfiles: | |
685 | if (lfutil.shortname in src and |
|
685 | if (lfutil.shortname in src and | |
686 | dest.startswith(repo.wjoin(lfutil.shortname))): |
|
686 | dest.startswith(repo.wjoin(lfutil.shortname))): | |
687 | srclfile = src.replace(repo.wjoin(lfutil.standin('')), '') |
|
687 | srclfile = src.replace(repo.wjoin(lfutil.standin('')), '') | |
688 | destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '') |
|
688 | destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '') | |
689 | destlfiledir = repo.wvfs.dirname(repo.wjoin(destlfile)) or '.' |
|
689 | destlfiledir = repo.wvfs.dirname(repo.wjoin(destlfile)) or '.' | |
690 | if not os.path.isdir(destlfiledir): |
|
690 | if not os.path.isdir(destlfiledir): | |
691 | os.makedirs(destlfiledir) |
|
691 | os.makedirs(destlfiledir) | |
692 | if rename: |
|
692 | if rename: | |
693 | os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile)) |
|
693 | os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile)) | |
694 |
|
694 | |||
695 | # The file is gone, but this deletes any empty parent |
|
695 | # The file is gone, but this deletes any empty parent | |
696 | # directories as a side-effect. |
|
696 | # directories as a side-effect. | |
697 | util.unlinkpath(repo.wjoin(srclfile), True) |
|
697 | util.unlinkpath(repo.wjoin(srclfile), True) | |
698 | lfdirstate.remove(srclfile) |
|
698 | lfdirstate.remove(srclfile) | |
699 | else: |
|
699 | else: | |
700 | util.copyfile(repo.wjoin(srclfile), |
|
700 | util.copyfile(repo.wjoin(srclfile), | |
701 | repo.wjoin(destlfile)) |
|
701 | repo.wjoin(destlfile)) | |
702 |
|
702 | |||
703 | lfdirstate.add(destlfile) |
|
703 | lfdirstate.add(destlfile) | |
704 | lfdirstate.write() |
|
704 | lfdirstate.write() | |
705 | except error.Abort as e: |
|
705 | except error.Abort as e: | |
706 | if str(e) != _('no files to copy'): |
|
706 | if str(e) != _('no files to copy'): | |
707 | raise e |
|
707 | raise e | |
708 | else: |
|
708 | else: | |
709 | nolfiles = True |
|
709 | nolfiles = True | |
710 | finally: |
|
710 | finally: | |
711 | restorematchfn() |
|
711 | restorematchfn() | |
712 | wlock.release() |
|
712 | wlock.release() | |
713 |
|
713 | |||
714 | if nolfiles and nonormalfiles: |
|
714 | if nolfiles and nonormalfiles: | |
715 | raise error.Abort(_('no files to copy')) |
|
715 | raise error.Abort(_('no files to copy')) | |
716 |
|
716 | |||
717 | return result |
|
717 | return result | |
718 |
|
718 | |||
719 | # When the user calls revert, we have to be careful to not revert any |
|
719 | # When the user calls revert, we have to be careful to not revert any | |
720 | # changes to other largefiles accidentally. This means we have to keep |
|
720 | # changes to other largefiles accidentally. This means we have to keep | |
721 | # track of the largefiles that are being reverted so we only pull down |
|
721 | # track of the largefiles that are being reverted so we only pull down | |
722 | # the necessary largefiles. |
|
722 | # the necessary largefiles. | |
723 | # |
|
723 | # | |
724 | # Standins are only updated (to match the hash of largefiles) before |
|
724 | # Standins are only updated (to match the hash of largefiles) before | |
725 | # commits. Update the standins then run the original revert, changing |
|
725 | # commits. Update the standins then run the original revert, changing | |
726 | # the matcher to hit standins instead of largefiles. Based on the |
|
726 | # the matcher to hit standins instead of largefiles. Based on the | |
727 | # resulting standins update the largefiles. |
|
727 | # resulting standins update the largefiles. | |
728 | def overriderevert(orig, ui, repo, ctx, parents, *pats, **opts): |
|
728 | def overriderevert(orig, ui, repo, ctx, parents, *pats, **opts): | |
729 | # Because we put the standins in a bad state (by updating them) |
|
729 | # Because we put the standins in a bad state (by updating them) | |
730 | # and then return them to a correct state we need to lock to |
|
730 | # and then return them to a correct state we need to lock to | |
731 | # prevent others from changing them in their incorrect state. |
|
731 | # prevent others from changing them in their incorrect state. | |
732 | with repo.wlock(): |
|
732 | with repo.wlock(): | |
733 | lfdirstate = lfutil.openlfdirstate(ui, repo) |
|
733 | lfdirstate = lfutil.openlfdirstate(ui, repo) | |
734 | s = lfutil.lfdirstatestatus(lfdirstate, repo) |
|
734 | s = lfutil.lfdirstatestatus(lfdirstate, repo) | |
735 | lfdirstate.write() |
|
735 | lfdirstate.write() | |
736 | for lfile in s.modified: |
|
736 | for lfile in s.modified: | |
737 | lfutil.updatestandin(repo, lfutil.standin(lfile)) |
|
737 | lfutil.updatestandin(repo, lfutil.standin(lfile)) | |
738 | for lfile in s.deleted: |
|
738 | for lfile in s.deleted: | |
739 | if (repo.wvfs.exists(lfutil.standin(lfile))): |
|
739 | if (repo.wvfs.exists(lfutil.standin(lfile))): | |
740 | repo.wvfs.unlink(lfutil.standin(lfile)) |
|
740 | repo.wvfs.unlink(lfutil.standin(lfile)) | |
741 |
|
741 | |||
742 | oldstandins = lfutil.getstandinsstate(repo) |
|
742 | oldstandins = lfutil.getstandinsstate(repo) | |
743 |
|
743 | |||
744 | def overridematch(mctx, pats=(), opts=None, globbed=False, |
|
744 | def overridematch(mctx, pats=(), opts=None, globbed=False, | |
745 | default='relpath', badfn=None): |
|
745 | default='relpath', badfn=None): | |
746 | if opts is None: |
|
746 | if opts is None: | |
747 | opts = {} |
|
747 | opts = {} | |
748 | match = oldmatch(mctx, pats, opts, globbed, default, badfn=badfn) |
|
748 | match = oldmatch(mctx, pats, opts, globbed, default, badfn=badfn) | |
749 | m = copy.copy(match) |
|
749 | m = copy.copy(match) | |
750 |
|
750 | |||
751 | # revert supports recursing into subrepos, and though largefiles |
|
751 | # revert supports recursing into subrepos, and though largefiles | |
752 | # currently doesn't work correctly in that case, this match is |
|
752 | # currently doesn't work correctly in that case, this match is | |
753 | # called, so the lfdirstate above may not be the correct one for |
|
753 | # called, so the lfdirstate above may not be the correct one for | |
754 | # this invocation of match. |
|
754 | # this invocation of match. | |
755 | lfdirstate = lfutil.openlfdirstate(mctx.repo().ui, mctx.repo(), |
|
755 | lfdirstate = lfutil.openlfdirstate(mctx.repo().ui, mctx.repo(), | |
756 | False) |
|
756 | False) | |
757 |
|
757 | |||
758 | def tostandin(f): |
|
758 | def tostandin(f): | |
759 | standin = lfutil.standin(f) |
|
759 | standin = lfutil.standin(f) | |
760 | if standin in ctx or standin in mctx: |
|
760 | if standin in ctx or standin in mctx: | |
761 | return standin |
|
761 | return standin | |
762 | elif standin in repo[None] or lfdirstate[f] == 'r': |
|
762 | elif standin in repo[None] or lfdirstate[f] == 'r': | |
763 | return None |
|
763 | return None | |
764 | return f |
|
764 | return f | |
765 | m._files = [tostandin(f) for f in m._files] |
|
765 | m._files = [tostandin(f) for f in m._files] | |
766 | m._files = [f for f in m._files if f is not None] |
|
766 | m._files = [f for f in m._files if f is not None] | |
767 | m._fileroots = set(m._files) |
|
767 | m._fileroots = set(m._files) | |
768 | origmatchfn = m.matchfn |
|
768 | origmatchfn = m.matchfn | |
769 | def matchfn(f): |
|
769 | def matchfn(f): | |
770 | if lfutil.isstandin(f): |
|
770 | if lfutil.isstandin(f): | |
771 | return (origmatchfn(lfutil.splitstandin(f)) and |
|
771 | return (origmatchfn(lfutil.splitstandin(f)) and | |
772 | (f in ctx or f in mctx)) |
|
772 | (f in ctx or f in mctx)) | |
773 | return origmatchfn(f) |
|
773 | return origmatchfn(f) | |
774 | m.matchfn = matchfn |
|
774 | m.matchfn = matchfn | |
775 | return m |
|
775 | return m | |
776 | oldmatch = installmatchfn(overridematch) |
|
776 | oldmatch = installmatchfn(overridematch) | |
777 | try: |
|
777 | try: | |
778 | orig(ui, repo, ctx, parents, *pats, **opts) |
|
778 | orig(ui, repo, ctx, parents, *pats, **opts) | |
779 | finally: |
|
779 | finally: | |
780 | restorematchfn() |
|
780 | restorematchfn() | |
781 |
|
781 | |||
782 | newstandins = lfutil.getstandinsstate(repo) |
|
782 | newstandins = lfutil.getstandinsstate(repo) | |
783 | filelist = lfutil.getlfilestoupdate(oldstandins, newstandins) |
|
783 | filelist = lfutil.getlfilestoupdate(oldstandins, newstandins) | |
784 | # lfdirstate should be 'normallookup'-ed for updated files, |
|
784 | # lfdirstate should be 'normallookup'-ed for updated files, | |
785 | # because reverting doesn't touch dirstate for 'normal' files |
|
785 | # because reverting doesn't touch dirstate for 'normal' files | |
786 | # when target revision is explicitly specified: in such case, |
|
786 | # when target revision is explicitly specified: in such case, | |
787 | # 'n' and valid timestamp in dirstate doesn't ensure 'clean' |
|
787 | # 'n' and valid timestamp in dirstate doesn't ensure 'clean' | |
788 | # of target (standin) file. |
|
788 | # of target (standin) file. | |
789 | lfcommands.updatelfiles(ui, repo, filelist, printmessage=False, |
|
789 | lfcommands.updatelfiles(ui, repo, filelist, printmessage=False, | |
790 | normallookup=True) |
|
790 | normallookup=True) | |
791 |
|
791 | |||
792 | # after pulling changesets, we need to take some extra care to get |
|
792 | # after pulling changesets, we need to take some extra care to get | |
793 | # largefiles updated remotely |
|
793 | # largefiles updated remotely | |
794 | def overridepull(orig, ui, repo, source=None, **opts): |
|
794 | def overridepull(orig, ui, repo, source=None, **opts): | |
795 | revsprepull = len(repo) |
|
795 | revsprepull = len(repo) | |
796 | if not source: |
|
796 | if not source: | |
797 | source = 'default' |
|
797 | source = 'default' | |
798 | repo.lfpullsource = source |
|
798 | repo.lfpullsource = source | |
799 | result = orig(ui, repo, source, **opts) |
|
799 | result = orig(ui, repo, source, **opts) | |
800 | revspostpull = len(repo) |
|
800 | revspostpull = len(repo) | |
801 | lfrevs = opts.get('lfrev', []) |
|
801 | lfrevs = opts.get('lfrev', []) | |
802 | if opts.get('all_largefiles'): |
|
802 | if opts.get('all_largefiles'): | |
803 | lfrevs.append('pulled()') |
|
803 | lfrevs.append('pulled()') | |
804 | if lfrevs and revspostpull > revsprepull: |
|
804 | if lfrevs and revspostpull > revsprepull: | |
805 | numcached = 0 |
|
805 | numcached = 0 | |
806 | repo.firstpulled = revsprepull # for pulled() revset expression |
|
806 | repo.firstpulled = revsprepull # for pulled() revset expression | |
807 | try: |
|
807 | try: | |
808 | for rev in scmutil.revrange(repo, lfrevs): |
|
808 | for rev in scmutil.revrange(repo, lfrevs): | |
809 | ui.note(_('pulling largefiles for revision %s\n') % rev) |
|
809 | ui.note(_('pulling largefiles for revision %s\n') % rev) | |
810 | (cached, missing) = lfcommands.cachelfiles(ui, repo, rev) |
|
810 | (cached, missing) = lfcommands.cachelfiles(ui, repo, rev) | |
811 | numcached += len(cached) |
|
811 | numcached += len(cached) | |
812 | finally: |
|
812 | finally: | |
813 | del repo.firstpulled |
|
813 | del repo.firstpulled | |
814 | ui.status(_("%d largefiles cached\n") % numcached) |
|
814 | ui.status(_("%d largefiles cached\n") % numcached) | |
815 | return result |
|
815 | return result | |
816 |
|
816 | |||
817 | def overridepush(orig, ui, repo, *args, **kwargs): |
|
817 | def overridepush(orig, ui, repo, *args, **kwargs): | |
818 | """Override push command and store --lfrev parameters in opargs""" |
|
818 | """Override push command and store --lfrev parameters in opargs""" | |
819 | lfrevs = kwargs.pop('lfrev', None) |
|
819 | lfrevs = kwargs.pop('lfrev', None) | |
820 | if lfrevs: |
|
820 | if lfrevs: | |
821 | opargs = kwargs.setdefault('opargs', {}) |
|
821 | opargs = kwargs.setdefault('opargs', {}) | |
822 | opargs['lfrevs'] = scmutil.revrange(repo, lfrevs) |
|
822 | opargs['lfrevs'] = scmutil.revrange(repo, lfrevs) | |
823 | return orig(ui, repo, *args, **kwargs) |
|
823 | return orig(ui, repo, *args, **kwargs) | |
824 |
|
824 | |||
825 | def exchangepushoperation(orig, *args, **kwargs): |
|
825 | def exchangepushoperation(orig, *args, **kwargs): | |
826 | """Override pushoperation constructor and store lfrevs parameter""" |
|
826 | """Override pushoperation constructor and store lfrevs parameter""" | |
827 | lfrevs = kwargs.pop('lfrevs', None) |
|
827 | lfrevs = kwargs.pop('lfrevs', None) | |
828 | pushop = orig(*args, **kwargs) |
|
828 | pushop = orig(*args, **kwargs) | |
829 | pushop.lfrevs = lfrevs |
|
829 | pushop.lfrevs = lfrevs | |
830 | return pushop |
|
830 | return pushop | |
831 |
|
831 | |||
832 | revsetpredicate = registrar.revsetpredicate() |
|
832 | revsetpredicate = registrar.revsetpredicate() | |
833 |
|
833 | |||
834 | @revsetpredicate('pulled()') |
|
834 | @revsetpredicate('pulled()') | |
835 | def pulledrevsetsymbol(repo, subset, x): |
|
835 | def pulledrevsetsymbol(repo, subset, x): | |
836 | """Changesets that just has been pulled. |
|
836 | """Changesets that just has been pulled. | |
837 |
|
837 | |||
838 | Only available with largefiles from pull --lfrev expressions. |
|
838 | Only available with largefiles from pull --lfrev expressions. | |
839 |
|
839 | |||
840 | .. container:: verbose |
|
840 | .. container:: verbose | |
841 |
|
841 | |||
842 | Some examples: |
|
842 | Some examples: | |
843 |
|
843 | |||
844 | - pull largefiles for all new changesets:: |
|
844 | - pull largefiles for all new changesets:: | |
845 |
|
845 | |||
846 | hg pull -lfrev "pulled()" |
|
846 | hg pull -lfrev "pulled()" | |
847 |
|
847 | |||
848 | - pull largefiles for all new branch heads:: |
|
848 | - pull largefiles for all new branch heads:: | |
849 |
|
849 | |||
850 | hg pull -lfrev "head(pulled()) and not closed()" |
|
850 | hg pull -lfrev "head(pulled()) and not closed()" | |
851 |
|
851 | |||
852 | """ |
|
852 | """ | |
853 |
|
853 | |||
854 | try: |
|
854 | try: | |
855 | firstpulled = repo.firstpulled |
|
855 | firstpulled = repo.firstpulled | |
856 | except AttributeError: |
|
856 | except AttributeError: | |
857 | raise error.Abort(_("pulled() only available in --lfrev")) |
|
857 | raise error.Abort(_("pulled() only available in --lfrev")) | |
858 | return revset.baseset([r for r in subset if r >= firstpulled]) |
|
858 | return revset.baseset([r for r in subset if r >= firstpulled]) | |
859 |
|
859 | |||
860 | def overrideclone(orig, ui, source, dest=None, **opts): |
|
860 | def overrideclone(orig, ui, source, dest=None, **opts): | |
861 | d = dest |
|
861 | d = dest | |
862 | if d is None: |
|
862 | if d is None: | |
863 | d = hg.defaultdest(source) |
|
863 | d = hg.defaultdest(source) | |
864 | if opts.get('all_largefiles') and not hg.islocal(d): |
|
864 | if opts.get('all_largefiles') and not hg.islocal(d): | |
865 | raise error.Abort(_( |
|
865 | raise error.Abort(_( | |
866 | '--all-largefiles is incompatible with non-local destination %s') % |
|
866 | '--all-largefiles is incompatible with non-local destination %s') % | |
867 | d) |
|
867 | d) | |
868 |
|
868 | |||
869 | return orig(ui, source, dest, **opts) |
|
869 | return orig(ui, source, dest, **opts) | |
870 |
|
870 | |||
871 | def hgclone(orig, ui, opts, *args, **kwargs): |
|
871 | def hgclone(orig, ui, opts, *args, **kwargs): | |
872 | result = orig(ui, opts, *args, **kwargs) |
|
872 | result = orig(ui, opts, *args, **kwargs) | |
873 |
|
873 | |||
874 | if result is not None: |
|
874 | if result is not None: | |
875 | sourcerepo, destrepo = result |
|
875 | sourcerepo, destrepo = result | |
876 | repo = destrepo.local() |
|
876 | repo = destrepo.local() | |
877 |
|
877 | |||
878 | # When cloning to a remote repo (like through SSH), no repo is available |
|
878 | # When cloning to a remote repo (like through SSH), no repo is available | |
879 | # from the peer. Therefore the largefiles can't be downloaded and the |
|
879 | # from the peer. Therefore the largefiles can't be downloaded and the | |
880 | # hgrc can't be updated. |
|
880 | # hgrc can't be updated. | |
881 | if not repo: |
|
881 | if not repo: | |
882 | return result |
|
882 | return result | |
883 |
|
883 | |||
884 | # If largefiles is required for this repo, permanently enable it locally |
|
884 | # If largefiles is required for this repo, permanently enable it locally | |
885 | if 'largefiles' in repo.requirements: |
|
885 | if 'largefiles' in repo.requirements: | |
886 | with repo.vfs('hgrc', 'a', text=True) as fp: |
|
886 | with repo.vfs('hgrc', 'a', text=True) as fp: | |
887 | fp.write('\n[extensions]\nlargefiles=\n') |
|
887 | fp.write('\n[extensions]\nlargefiles=\n') | |
888 |
|
888 | |||
889 | # Caching is implicitly limited to 'rev' option, since the dest repo was |
|
889 | # Caching is implicitly limited to 'rev' option, since the dest repo was | |
890 | # truncated at that point. The user may expect a download count with |
|
890 | # truncated at that point. The user may expect a download count with | |
891 | # this option, so attempt whether or not this is a largefile repo. |
|
891 | # this option, so attempt whether or not this is a largefile repo. | |
892 | if opts.get('all_largefiles'): |
|
892 | if opts.get('all_largefiles'): | |
893 | success, missing = lfcommands.downloadlfiles(ui, repo, None) |
|
893 | success, missing = lfcommands.downloadlfiles(ui, repo, None) | |
894 |
|
894 | |||
895 | if missing != 0: |
|
895 | if missing != 0: | |
896 | return None |
|
896 | return None | |
897 |
|
897 | |||
898 | return result |
|
898 | return result | |
899 |
|
899 | |||
900 | def overriderebase(orig, ui, repo, **opts): |
|
900 | def overriderebase(orig, ui, repo, **opts): | |
901 | if not util.safehasattr(repo, '_largefilesenabled'): |
|
901 | if not util.safehasattr(repo, '_largefilesenabled'): | |
902 | return orig(ui, repo, **opts) |
|
902 | return orig(ui, repo, **opts) | |
903 |
|
903 | |||
904 | resuming = opts.get('continue') |
|
904 | resuming = opts.get('continue') | |
905 | repo._lfcommithooks.append(lfutil.automatedcommithook(resuming)) |
|
905 | repo._lfcommithooks.append(lfutil.automatedcommithook(resuming)) | |
906 | repo._lfstatuswriters.append(lambda *msg, **opts: None) |
|
906 | repo._lfstatuswriters.append(lambda *msg, **opts: None) | |
907 | try: |
|
907 | try: | |
908 | return orig(ui, repo, **opts) |
|
908 | return orig(ui, repo, **opts) | |
909 | finally: |
|
909 | finally: | |
910 | repo._lfstatuswriters.pop() |
|
910 | repo._lfstatuswriters.pop() | |
911 | repo._lfcommithooks.pop() |
|
911 | repo._lfcommithooks.pop() | |
912 |
|
912 | |||
913 | def overridearchivecmd(orig, ui, repo, dest, **opts): |
|
913 | def overridearchivecmd(orig, ui, repo, dest, **opts): | |
914 | repo.unfiltered().lfstatus = True |
|
914 | repo.unfiltered().lfstatus = True | |
915 |
|
915 | |||
916 | try: |
|
916 | try: | |
917 | return orig(ui, repo.unfiltered(), dest, **opts) |
|
917 | return orig(ui, repo.unfiltered(), dest, **opts) | |
918 | finally: |
|
918 | finally: | |
919 | repo.unfiltered().lfstatus = False |
|
919 | repo.unfiltered().lfstatus = False | |
920 |
|
920 | |||
921 | def hgwebarchive(orig, web, req, tmpl): |
|
921 | def hgwebarchive(orig, web, req, tmpl): | |
922 | web.repo.lfstatus = True |
|
922 | web.repo.lfstatus = True | |
923 |
|
923 | |||
924 | try: |
|
924 | try: | |
925 | return orig(web, req, tmpl) |
|
925 | return orig(web, req, tmpl) | |
926 | finally: |
|
926 | finally: | |
927 | web.repo.lfstatus = False |
|
927 | web.repo.lfstatus = False | |
928 |
|
928 | |||
929 | def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None, |
|
929 | def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None, | |
930 | prefix='', mtime=None, subrepos=None): |
|
930 | prefix='', mtime=None, subrepos=None): | |
931 | # For some reason setting repo.lfstatus in hgwebarchive only changes the |
|
931 | # For some reason setting repo.lfstatus in hgwebarchive only changes the | |
932 | # unfiltered repo's attr, so check that as well. |
|
932 | # unfiltered repo's attr, so check that as well. | |
933 | if not repo.lfstatus and not repo.unfiltered().lfstatus: |
|
933 | if not repo.lfstatus and not repo.unfiltered().lfstatus: | |
934 | return orig(repo, dest, node, kind, decode, matchfn, prefix, mtime, |
|
934 | return orig(repo, dest, node, kind, decode, matchfn, prefix, mtime, | |
935 | subrepos) |
|
935 | subrepos) | |
936 |
|
936 | |||
937 | # No need to lock because we are only reading history and |
|
937 | # No need to lock because we are only reading history and | |
938 | # largefile caches, neither of which are modified. |
|
938 | # largefile caches, neither of which are modified. | |
939 | if node is not None: |
|
939 | if node is not None: | |
940 | lfcommands.cachelfiles(repo.ui, repo, node) |
|
940 | lfcommands.cachelfiles(repo.ui, repo, node) | |
941 |
|
941 | |||
942 | if kind not in archival.archivers: |
|
942 | if kind not in archival.archivers: | |
943 | raise error.Abort(_("unknown archive type '%s'") % kind) |
|
943 | raise error.Abort(_("unknown archive type '%s'") % kind) | |
944 |
|
944 | |||
945 | ctx = repo[node] |
|
945 | ctx = repo[node] | |
946 |
|
946 | |||
947 | if kind == 'files': |
|
947 | if kind == 'files': | |
948 | if prefix: |
|
948 | if prefix: | |
949 | raise error.Abort( |
|
949 | raise error.Abort( | |
950 | _('cannot give prefix when archiving to files')) |
|
950 | _('cannot give prefix when archiving to files')) | |
951 | else: |
|
951 | else: | |
952 | prefix = archival.tidyprefix(dest, kind, prefix) |
|
952 | prefix = archival.tidyprefix(dest, kind, prefix) | |
953 |
|
953 | |||
954 | def write(name, mode, islink, getdata): |
|
954 | def write(name, mode, islink, getdata): | |
955 | if matchfn and not matchfn(name): |
|
955 | if matchfn and not matchfn(name): | |
956 | return |
|
956 | return | |
957 | data = getdata() |
|
957 | data = getdata() | |
958 | if decode: |
|
958 | if decode: | |
959 | data = repo.wwritedata(name, data) |
|
959 | data = repo.wwritedata(name, data) | |
960 | archiver.addfile(prefix + name, mode, islink, data) |
|
960 | archiver.addfile(prefix + name, mode, islink, data) | |
961 |
|
961 | |||
962 | archiver = archival.archivers[kind](dest, mtime or ctx.date()[0]) |
|
962 | archiver = archival.archivers[kind](dest, mtime or ctx.date()[0]) | |
963 |
|
963 | |||
964 | if repo.ui.configbool("ui", "archivemeta", True): |
|
964 | if repo.ui.configbool("ui", "archivemeta", True): | |
965 | write('.hg_archival.txt', 0o644, False, |
|
965 | write('.hg_archival.txt', 0o644, False, | |
966 | lambda: archival.buildmetadata(ctx)) |
|
966 | lambda: archival.buildmetadata(ctx)) | |
967 |
|
967 | |||
968 | for f in ctx: |
|
968 | for f in ctx: | |
969 | ff = ctx.flags(f) |
|
969 | ff = ctx.flags(f) | |
970 | getdata = ctx[f].data |
|
970 | getdata = ctx[f].data | |
971 | if lfutil.isstandin(f): |
|
971 | if lfutil.isstandin(f): | |
972 | if node is not None: |
|
972 | if node is not None: | |
973 | path = lfutil.findfile(repo, getdata().strip()) |
|
973 | path = lfutil.findfile(repo, getdata().strip()) | |
974 |
|
974 | |||
975 | if path is None: |
|
975 | if path is None: | |
976 | raise error.Abort( |
|
976 | raise error.Abort( | |
977 | _('largefile %s not found in repo store or system cache') |
|
977 | _('largefile %s not found in repo store or system cache') | |
978 | % lfutil.splitstandin(f)) |
|
978 | % lfutil.splitstandin(f)) | |
979 | else: |
|
979 | else: | |
980 | path = lfutil.splitstandin(f) |
|
980 | path = lfutil.splitstandin(f) | |
981 |
|
981 | |||
982 | f = lfutil.splitstandin(f) |
|
982 | f = lfutil.splitstandin(f) | |
983 |
|
983 | |||
984 | getdata = lambda: util.readfile(path) |
|
984 | getdata = lambda: util.readfile(path) | |
985 | write(f, 'x' in ff and 0o755 or 0o644, 'l' in ff, getdata) |
|
985 | write(f, 'x' in ff and 0o755 or 0o644, 'l' in ff, getdata) | |
986 |
|
986 | |||
987 | if subrepos: |
|
987 | if subrepos: | |
988 | for subpath in sorted(ctx.substate): |
|
988 | for subpath in sorted(ctx.substate): | |
989 | sub = ctx.workingsub(subpath) |
|
989 | sub = ctx.workingsub(subpath) | |
990 | submatch = matchmod.subdirmatcher(subpath, matchfn) |
|
990 | submatch = matchmod.subdirmatcher(subpath, matchfn) | |
991 | sub._repo.lfstatus = True |
|
991 | sub._repo.lfstatus = True | |
992 | sub.archive(archiver, prefix, submatch) |
|
992 | sub.archive(archiver, prefix, submatch) | |
993 |
|
993 | |||
994 | archiver.done() |
|
994 | archiver.done() | |
995 |
|
995 | |||
996 | def hgsubrepoarchive(orig, repo, archiver, prefix, match=None): |
|
996 | def hgsubrepoarchive(orig, repo, archiver, prefix, match=None): | |
997 | if not repo._repo.lfstatus: |
|
997 | if not repo._repo.lfstatus: | |
998 | return orig(repo, archiver, prefix, match) |
|
998 | return orig(repo, archiver, prefix, match) | |
999 |
|
999 | |||
1000 | repo._get(repo._state + ('hg',)) |
|
1000 | repo._get(repo._state + ('hg',)) | |
1001 | rev = repo._state[1] |
|
1001 | rev = repo._state[1] | |
1002 | ctx = repo._repo[rev] |
|
1002 | ctx = repo._repo[rev] | |
1003 |
|
1003 | |||
1004 | if ctx.node() is not None: |
|
1004 | if ctx.node() is not None: | |
1005 | lfcommands.cachelfiles(repo.ui, repo._repo, ctx.node()) |
|
1005 | lfcommands.cachelfiles(repo.ui, repo._repo, ctx.node()) | |
1006 |
|
1006 | |||
1007 | def write(name, mode, islink, getdata): |
|
1007 | def write(name, mode, islink, getdata): | |
1008 | # At this point, the standin has been replaced with the largefile name, |
|
1008 | # At this point, the standin has been replaced with the largefile name, | |
1009 | # so the normal matcher works here without the lfutil variants. |
|
1009 | # so the normal matcher works here without the lfutil variants. | |
1010 | if match and not match(f): |
|
1010 | if match and not match(f): | |
1011 | return |
|
1011 | return | |
1012 | data = getdata() |
|
1012 | data = getdata() | |
1013 |
|
1013 | |||
1014 | archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data) |
|
1014 | archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data) | |
1015 |
|
1015 | |||
1016 | for f in ctx: |
|
1016 | for f in ctx: | |
1017 | ff = ctx.flags(f) |
|
1017 | ff = ctx.flags(f) | |
1018 | getdata = ctx[f].data |
|
1018 | getdata = ctx[f].data | |
1019 | if lfutil.isstandin(f): |
|
1019 | if lfutil.isstandin(f): | |
1020 | if ctx.node() is not None: |
|
1020 | if ctx.node() is not None: | |
1021 | path = lfutil.findfile(repo._repo, getdata().strip()) |
|
1021 | path = lfutil.findfile(repo._repo, getdata().strip()) | |
1022 |
|
1022 | |||
1023 | if path is None: |
|
1023 | if path is None: | |
1024 | raise error.Abort( |
|
1024 | raise error.Abort( | |
1025 | _('largefile %s not found in repo store or system cache') |
|
1025 | _('largefile %s not found in repo store or system cache') | |
1026 | % lfutil.splitstandin(f)) |
|
1026 | % lfutil.splitstandin(f)) | |
1027 | else: |
|
1027 | else: | |
1028 | path = lfutil.splitstandin(f) |
|
1028 | path = lfutil.splitstandin(f) | |
1029 |
|
1029 | |||
1030 | f = lfutil.splitstandin(f) |
|
1030 | f = lfutil.splitstandin(f) | |
1031 |
|
1031 | |||
1032 | getdata = lambda: util.readfile(os.path.join(prefix, path)) |
|
1032 | getdata = lambda: util.readfile(os.path.join(prefix, path)) | |
1033 |
|
1033 | |||
1034 | write(f, 'x' in ff and 0o755 or 0o644, 'l' in ff, getdata) |
|
1034 | write(f, 'x' in ff and 0o755 or 0o644, 'l' in ff, getdata) | |
1035 |
|
1035 | |||
1036 | for subpath in sorted(ctx.substate): |
|
1036 | for subpath in sorted(ctx.substate): | |
1037 | sub = ctx.workingsub(subpath) |
|
1037 | sub = ctx.workingsub(subpath) | |
1038 | submatch = matchmod.subdirmatcher(subpath, match) |
|
1038 | submatch = matchmod.subdirmatcher(subpath, match) | |
1039 | sub._repo.lfstatus = True |
|
1039 | sub._repo.lfstatus = True | |
1040 | sub.archive(archiver, prefix + repo._path + '/', submatch) |
|
1040 | sub.archive(archiver, prefix + repo._path + '/', submatch) | |
1041 |
|
1041 | |||
1042 | # If a largefile is modified, the change is not reflected in its |
|
1042 | # If a largefile is modified, the change is not reflected in its | |
1043 | # standin until a commit. cmdutil.bailifchanged() raises an exception |
|
1043 | # standin until a commit. cmdutil.bailifchanged() raises an exception | |
1044 | # if the repo has uncommitted changes. Wrap it to also check if |
|
1044 | # if the repo has uncommitted changes. Wrap it to also check if | |
1045 | # largefiles were changed. This is used by bisect, backout and fetch. |
|
1045 | # largefiles were changed. This is used by bisect, backout and fetch. | |
1046 | def overridebailifchanged(orig, repo, *args, **kwargs): |
|
1046 | def overridebailifchanged(orig, repo, *args, **kwargs): | |
1047 | orig(repo, *args, **kwargs) |
|
1047 | orig(repo, *args, **kwargs) | |
1048 | repo.lfstatus = True |
|
1048 | repo.lfstatus = True | |
1049 | s = repo.status() |
|
1049 | s = repo.status() | |
1050 | repo.lfstatus = False |
|
1050 | repo.lfstatus = False | |
1051 | if s.modified or s.added or s.removed or s.deleted: |
|
1051 | if s.modified or s.added or s.removed or s.deleted: | |
1052 | raise error.Abort(_('uncommitted changes')) |
|
1052 | raise error.Abort(_('uncommitted changes')) | |
1053 |
|
1053 | |||
1054 | def postcommitstatus(orig, repo, *args, **kwargs): |
|
1054 | def postcommitstatus(orig, repo, *args, **kwargs): | |
1055 | repo.lfstatus = True |
|
1055 | repo.lfstatus = True | |
1056 | try: |
|
1056 | try: | |
1057 | return orig(repo, *args, **kwargs) |
|
1057 | return orig(repo, *args, **kwargs) | |
1058 | finally: |
|
1058 | finally: | |
1059 | repo.lfstatus = False |
|
1059 | repo.lfstatus = False | |
1060 |
|
1060 | |||
1061 | def cmdutilforget(orig, ui, repo, match, prefix, explicitonly): |
|
1061 | def cmdutilforget(orig, ui, repo, match, prefix, explicitonly): | |
1062 | normalmatcher = composenormalfilematcher(match, repo[None].manifest()) |
|
1062 | normalmatcher = composenormalfilematcher(match, repo[None].manifest()) | |
1063 | bad, forgot = orig(ui, repo, normalmatcher, prefix, explicitonly) |
|
1063 | bad, forgot = orig(ui, repo, normalmatcher, prefix, explicitonly) | |
1064 | m = composelargefilematcher(match, repo[None].manifest()) |
|
1064 | m = composelargefilematcher(match, repo[None].manifest()) | |
1065 |
|
1065 | |||
1066 | try: |
|
1066 | try: | |
1067 | repo.lfstatus = True |
|
1067 | repo.lfstatus = True | |
1068 | s = repo.status(match=m, clean=True) |
|
1068 | s = repo.status(match=m, clean=True) | |
1069 | finally: |
|
1069 | finally: | |
1070 | repo.lfstatus = False |
|
1070 | repo.lfstatus = False | |
1071 | forget = sorted(s.modified + s.added + s.deleted + s.clean) |
|
1071 | forget = sorted(s.modified + s.added + s.deleted + s.clean) | |
1072 | forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()] |
|
1072 | forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()] | |
1073 |
|
1073 | |||
1074 | for f in forget: |
|
1074 | for f in forget: | |
1075 | if lfutil.standin(f) not in repo.dirstate and not \ |
|
1075 | if lfutil.standin(f) not in repo.dirstate and not \ | |
1076 | repo.wvfs.isdir(lfutil.standin(f)): |
|
1076 | repo.wvfs.isdir(lfutil.standin(f)): | |
1077 | ui.warn(_('not removing %s: file is already untracked\n') |
|
1077 | ui.warn(_('not removing %s: file is already untracked\n') | |
1078 | % m.rel(f)) |
|
1078 | % m.rel(f)) | |
1079 | bad.append(f) |
|
1079 | bad.append(f) | |
1080 |
|
1080 | |||
1081 | for f in forget: |
|
1081 | for f in forget: | |
1082 | if ui.verbose or not m.exact(f): |
|
1082 | if ui.verbose or not m.exact(f): | |
1083 | ui.status(_('removing %s\n') % m.rel(f)) |
|
1083 | ui.status(_('removing %s\n') % m.rel(f)) | |
1084 |
|
1084 | |||
1085 | # Need to lock because standin files are deleted then removed from the |
|
1085 | # Need to lock because standin files are deleted then removed from the | |
1086 | # repository and we could race in-between. |
|
1086 | # repository and we could race in-between. | |
1087 | with repo.wlock(): |
|
1087 | with repo.wlock(): | |
1088 | lfdirstate = lfutil.openlfdirstate(ui, repo) |
|
1088 | lfdirstate = lfutil.openlfdirstate(ui, repo) | |
1089 | for f in forget: |
|
1089 | for f in forget: | |
1090 | if lfdirstate[f] == 'a': |
|
1090 | if lfdirstate[f] == 'a': | |
1091 | lfdirstate.drop(f) |
|
1091 | lfdirstate.drop(f) | |
1092 | else: |
|
1092 | else: | |
1093 | lfdirstate.remove(f) |
|
1093 | lfdirstate.remove(f) | |
1094 | lfdirstate.write() |
|
1094 | lfdirstate.write() | |
1095 | standins = [lfutil.standin(f) for f in forget] |
|
1095 | standins = [lfutil.standin(f) for f in forget] | |
1096 | for f in standins: |
|
1096 | for f in standins: | |
1097 | util.unlinkpath(repo.wjoin(f), ignoremissing=True) |
|
1097 | util.unlinkpath(repo.wjoin(f), ignoremissing=True) | |
1098 | rejected = repo[None].forget(standins) |
|
1098 | rejected = repo[None].forget(standins) | |
1099 |
|
1099 | |||
1100 | bad.extend(f for f in rejected if f in m.files()) |
|
1100 | bad.extend(f for f in rejected if f in m.files()) | |
1101 | forgot.extend(f for f in forget if f not in rejected) |
|
1101 | forgot.extend(f for f in forget if f not in rejected) | |
1102 | return bad, forgot |
|
1102 | return bad, forgot | |
1103 |
|
1103 | |||
1104 | def _getoutgoings(repo, other, missing, addfunc): |
|
1104 | def _getoutgoings(repo, other, missing, addfunc): | |
1105 | """get pairs of filename and largefile hash in outgoing revisions |
|
1105 | """get pairs of filename and largefile hash in outgoing revisions | |
1106 | in 'missing'. |
|
1106 | in 'missing'. | |
1107 |
|
1107 | |||
1108 | largefiles already existing on 'other' repository are ignored. |
|
1108 | largefiles already existing on 'other' repository are ignored. | |
1109 |
|
1109 | |||
1110 | 'addfunc' is invoked with each unique pairs of filename and |
|
1110 | 'addfunc' is invoked with each unique pairs of filename and | |
1111 | largefile hash value. |
|
1111 | largefile hash value. | |
1112 | """ |
|
1112 | """ | |
1113 | knowns = set() |
|
1113 | knowns = set() | |
1114 | lfhashes = set() |
|
1114 | lfhashes = set() | |
1115 | def dedup(fn, lfhash): |
|
1115 | def dedup(fn, lfhash): | |
1116 | k = (fn, lfhash) |
|
1116 | k = (fn, lfhash) | |
1117 | if k not in knowns: |
|
1117 | if k not in knowns: | |
1118 | knowns.add(k) |
|
1118 | knowns.add(k) | |
1119 | lfhashes.add(lfhash) |
|
1119 | lfhashes.add(lfhash) | |
1120 | lfutil.getlfilestoupload(repo, missing, dedup) |
|
1120 | lfutil.getlfilestoupload(repo, missing, dedup) | |
1121 | if lfhashes: |
|
1121 | if lfhashes: | |
1122 | lfexists = storefactory.openstore(repo, other).exists(lfhashes) |
|
1122 | lfexists = storefactory.openstore(repo, other).exists(lfhashes) | |
1123 | for fn, lfhash in knowns: |
|
1123 | for fn, lfhash in knowns: | |
1124 | if not lfexists[lfhash]: # lfhash doesn't exist on "other" |
|
1124 | if not lfexists[lfhash]: # lfhash doesn't exist on "other" | |
1125 | addfunc(fn, lfhash) |
|
1125 | addfunc(fn, lfhash) | |
1126 |
|
1126 | |||
1127 | def outgoinghook(ui, repo, other, opts, missing): |
|
1127 | def outgoinghook(ui, repo, other, opts, missing): | |
1128 | if opts.pop('large', None): |
|
1128 | if opts.pop('large', None): | |
1129 | lfhashes = set() |
|
1129 | lfhashes = set() | |
1130 | if ui.debugflag: |
|
1130 | if ui.debugflag: | |
1131 | toupload = {} |
|
1131 | toupload = {} | |
1132 | def addfunc(fn, lfhash): |
|
1132 | def addfunc(fn, lfhash): | |
1133 | if fn not in toupload: |
|
1133 | if fn not in toupload: | |
1134 | toupload[fn] = [] |
|
1134 | toupload[fn] = [] | |
1135 | toupload[fn].append(lfhash) |
|
1135 | toupload[fn].append(lfhash) | |
1136 | lfhashes.add(lfhash) |
|
1136 | lfhashes.add(lfhash) | |
1137 | def showhashes(fn): |
|
1137 | def showhashes(fn): | |
1138 | for lfhash in sorted(toupload[fn]): |
|
1138 | for lfhash in sorted(toupload[fn]): | |
1139 | ui.debug(' %s\n' % (lfhash)) |
|
1139 | ui.debug(' %s\n' % (lfhash)) | |
1140 | else: |
|
1140 | else: | |
1141 | toupload = set() |
|
1141 | toupload = set() | |
1142 | def addfunc(fn, lfhash): |
|
1142 | def addfunc(fn, lfhash): | |
1143 | toupload.add(fn) |
|
1143 | toupload.add(fn) | |
1144 | lfhashes.add(lfhash) |
|
1144 | lfhashes.add(lfhash) | |
1145 | def showhashes(fn): |
|
1145 | def showhashes(fn): | |
1146 | pass |
|
1146 | pass | |
1147 | _getoutgoings(repo, other, missing, addfunc) |
|
1147 | _getoutgoings(repo, other, missing, addfunc) | |
1148 |
|
1148 | |||
1149 | if not toupload: |
|
1149 | if not toupload: | |
1150 | ui.status(_('largefiles: no files to upload\n')) |
|
1150 | ui.status(_('largefiles: no files to upload\n')) | |
1151 | else: |
|
1151 | else: | |
1152 | ui.status(_('largefiles to upload (%d entities):\n') |
|
1152 | ui.status(_('largefiles to upload (%d entities):\n') | |
1153 | % (len(lfhashes))) |
|
1153 | % (len(lfhashes))) | |
1154 | for file in sorted(toupload): |
|
1154 | for file in sorted(toupload): | |
1155 | ui.status(lfutil.splitstandin(file) + '\n') |
|
1155 | ui.status(lfutil.splitstandin(file) + '\n') | |
1156 | showhashes(file) |
|
1156 | showhashes(file) | |
1157 | ui.status('\n') |
|
1157 | ui.status('\n') | |
1158 |
|
1158 | |||
1159 | def summaryremotehook(ui, repo, opts, changes): |
|
1159 | def summaryremotehook(ui, repo, opts, changes): | |
1160 | largeopt = opts.get('large', False) |
|
1160 | largeopt = opts.get('large', False) | |
1161 | if changes is None: |
|
1161 | if changes is None: | |
1162 | if largeopt: |
|
1162 | if largeopt: | |
1163 | return (False, True) # only outgoing check is needed |
|
1163 | return (False, True) # only outgoing check is needed | |
1164 | else: |
|
1164 | else: | |
1165 | return (False, False) |
|
1165 | return (False, False) | |
1166 | elif largeopt: |
|
1166 | elif largeopt: | |
1167 | url, branch, peer, outgoing = changes[1] |
|
1167 | url, branch, peer, outgoing = changes[1] | |
1168 | if peer is None: |
|
1168 | if peer is None: | |
1169 | # i18n: column positioning for "hg summary" |
|
1169 | # i18n: column positioning for "hg summary" | |
1170 | ui.status(_('largefiles: (no remote repo)\n')) |
|
1170 | ui.status(_('largefiles: (no remote repo)\n')) | |
1171 | return |
|
1171 | return | |
1172 |
|
1172 | |||
1173 | toupload = set() |
|
1173 | toupload = set() | |
1174 | lfhashes = set() |
|
1174 | lfhashes = set() | |
1175 | def addfunc(fn, lfhash): |
|
1175 | def addfunc(fn, lfhash): | |
1176 | toupload.add(fn) |
|
1176 | toupload.add(fn) | |
1177 | lfhashes.add(lfhash) |
|
1177 | lfhashes.add(lfhash) | |
1178 | _getoutgoings(repo, peer, outgoing.missing, addfunc) |
|
1178 | _getoutgoings(repo, peer, outgoing.missing, addfunc) | |
1179 |
|
1179 | |||
1180 | if not toupload: |
|
1180 | if not toupload: | |
1181 | # i18n: column positioning for "hg summary" |
|
1181 | # i18n: column positioning for "hg summary" | |
1182 | ui.status(_('largefiles: (no files to upload)\n')) |
|
1182 | ui.status(_('largefiles: (no files to upload)\n')) | |
1183 | else: |
|
1183 | else: | |
1184 | # i18n: column positioning for "hg summary" |
|
1184 | # i18n: column positioning for "hg summary" | |
1185 | ui.status(_('largefiles: %d entities for %d files to upload\n') |
|
1185 | ui.status(_('largefiles: %d entities for %d files to upload\n') | |
1186 | % (len(lfhashes), len(toupload))) |
|
1186 | % (len(lfhashes), len(toupload))) | |
1187 |
|
1187 | |||
1188 | def overridesummary(orig, ui, repo, *pats, **opts): |
|
1188 | def overridesummary(orig, ui, repo, *pats, **opts): | |
1189 | try: |
|
1189 | try: | |
1190 | repo.lfstatus = True |
|
1190 | repo.lfstatus = True | |
1191 | orig(ui, repo, *pats, **opts) |
|
1191 | orig(ui, repo, *pats, **opts) | |
1192 | finally: |
|
1192 | finally: | |
1193 | repo.lfstatus = False |
|
1193 | repo.lfstatus = False | |
1194 |
|
1194 | |||
1195 | def scmutiladdremove(orig, repo, matcher, prefix, opts=None, dry_run=None, |
|
1195 | def scmutiladdremove(orig, repo, matcher, prefix, opts=None, dry_run=None, | |
1196 | similarity=None): |
|
1196 | similarity=None): | |
1197 | if opts is None: |
|
1197 | if opts is None: | |
1198 | opts = {} |
|
1198 | opts = {} | |
1199 | if not lfutil.islfilesrepo(repo): |
|
1199 | if not lfutil.islfilesrepo(repo): | |
1200 | return orig(repo, matcher, prefix, opts, dry_run, similarity) |
|
1200 | return orig(repo, matcher, prefix, opts, dry_run, similarity) | |
1201 | # Get the list of missing largefiles so we can remove them |
|
1201 | # Get the list of missing largefiles so we can remove them | |
1202 | lfdirstate = lfutil.openlfdirstate(repo.ui, repo) |
|
1202 | lfdirstate = lfutil.openlfdirstate(repo.ui, repo) | |
1203 | unsure, s = lfdirstate.status(matchmod.always(repo.root, repo.getcwd()), [], |
|
1203 | unsure, s = lfdirstate.status(matchmod.always(repo.root, repo.getcwd()), [], | |
1204 | False, False, False) |
|
1204 | False, False, False) | |
1205 |
|
1205 | |||
1206 | # Call into the normal remove code, but the removing of the standin, we want |
|
1206 | # Call into the normal remove code, but the removing of the standin, we want | |
1207 | # to have handled by original addremove. Monkey patching here makes sure |
|
1207 | # to have handled by original addremove. Monkey patching here makes sure | |
1208 | # we don't remove the standin in the largefiles code, preventing a very |
|
1208 | # we don't remove the standin in the largefiles code, preventing a very | |
1209 | # confused state later. |
|
1209 | # confused state later. | |
1210 | if s.deleted: |
|
1210 | if s.deleted: | |
1211 | m = copy.copy(matcher) |
|
1211 | m = copy.copy(matcher) | |
1212 |
|
1212 | |||
1213 | # The m._files and m._map attributes are not changed to the deleted list |
|
1213 | # The m._files and m._map attributes are not changed to the deleted list | |
1214 | # because that affects the m.exact() test, which in turn governs whether |
|
1214 | # because that affects the m.exact() test, which in turn governs whether | |
1215 | # or not the file name is printed, and how. Simply limit the original |
|
1215 | # or not the file name is printed, and how. Simply limit the original | |
1216 | # matches to those in the deleted status list. |
|
1216 | # matches to those in the deleted status list. | |
1217 | matchfn = m.matchfn |
|
1217 | matchfn = m.matchfn | |
1218 | m.matchfn = lambda f: f in s.deleted and matchfn(f) |
|
1218 | m.matchfn = lambda f: f in s.deleted and matchfn(f) | |
1219 |
|
1219 | |||
1220 | removelargefiles(repo.ui, repo, True, m, **opts) |
|
1220 | removelargefiles(repo.ui, repo, True, m, **opts) | |
1221 | # Call into the normal add code, and any files that *should* be added as |
|
1221 | # Call into the normal add code, and any files that *should* be added as | |
1222 | # largefiles will be |
|
1222 | # largefiles will be | |
1223 | added, bad = addlargefiles(repo.ui, repo, True, matcher, **opts) |
|
1223 | added, bad = addlargefiles(repo.ui, repo, True, matcher, **opts) | |
1224 | # Now that we've handled largefiles, hand off to the original addremove |
|
1224 | # Now that we've handled largefiles, hand off to the original addremove | |
1225 | # function to take care of the rest. Make sure it doesn't do anything with |
|
1225 | # function to take care of the rest. Make sure it doesn't do anything with | |
1226 | # largefiles by passing a matcher that will ignore them. |
|
1226 | # largefiles by passing a matcher that will ignore them. | |
1227 | matcher = composenormalfilematcher(matcher, repo[None].manifest(), added) |
|
1227 | matcher = composenormalfilematcher(matcher, repo[None].manifest(), added) | |
1228 | return orig(repo, matcher, prefix, opts, dry_run, similarity) |
|
1228 | return orig(repo, matcher, prefix, opts, dry_run, similarity) | |
1229 |
|
1229 | |||
1230 | # Calling purge with --all will cause the largefiles to be deleted. |
|
1230 | # Calling purge with --all will cause the largefiles to be deleted. | |
1231 | # Override repo.status to prevent this from happening. |
|
1231 | # Override repo.status to prevent this from happening. | |
1232 | def overridepurge(orig, ui, repo, *dirs, **opts): |
|
1232 | def overridepurge(orig, ui, repo, *dirs, **opts): | |
1233 | # XXX Monkey patching a repoview will not work. The assigned attribute will |
|
1233 | # XXX Monkey patching a repoview will not work. The assigned attribute will | |
1234 | # be set on the unfiltered repo, but we will only lookup attributes in the |
|
1234 | # be set on the unfiltered repo, but we will only lookup attributes in the | |
1235 | # unfiltered repo if the lookup in the repoview object itself fails. As the |
|
1235 | # unfiltered repo if the lookup in the repoview object itself fails. As the | |
1236 | # monkey patched method exists on the repoview class the lookup will not |
|
1236 | # monkey patched method exists on the repoview class the lookup will not | |
1237 | # fail. As a result, the original version will shadow the monkey patched |
|
1237 | # fail. As a result, the original version will shadow the monkey patched | |
1238 | # one, defeating the monkey patch. |
|
1238 | # one, defeating the monkey patch. | |
1239 | # |
|
1239 | # | |
1240 | # As a work around we use an unfiltered repo here. We should do something |
|
1240 | # As a work around we use an unfiltered repo here. We should do something | |
1241 | # cleaner instead. |
|
1241 | # cleaner instead. | |
1242 | repo = repo.unfiltered() |
|
1242 | repo = repo.unfiltered() | |
1243 | oldstatus = repo.status |
|
1243 | oldstatus = repo.status | |
1244 | def overridestatus(node1='.', node2=None, match=None, ignored=False, |
|
1244 | def overridestatus(node1='.', node2=None, match=None, ignored=False, | |
1245 | clean=False, unknown=False, listsubrepos=False): |
|
1245 | clean=False, unknown=False, listsubrepos=False): | |
1246 | r = oldstatus(node1, node2, match, ignored, clean, unknown, |
|
1246 | r = oldstatus(node1, node2, match, ignored, clean, unknown, | |
1247 | listsubrepos) |
|
1247 | listsubrepos) | |
1248 | lfdirstate = lfutil.openlfdirstate(ui, repo) |
|
1248 | lfdirstate = lfutil.openlfdirstate(ui, repo) | |
1249 | unknown = [f for f in r.unknown if lfdirstate[f] == '?'] |
|
1249 | unknown = [f for f in r.unknown if lfdirstate[f] == '?'] | |
1250 | ignored = [f for f in r.ignored if lfdirstate[f] == '?'] |
|
1250 | ignored = [f for f in r.ignored if lfdirstate[f] == '?'] | |
1251 | return scmutil.status(r.modified, r.added, r.removed, r.deleted, |
|
1251 | return scmutil.status(r.modified, r.added, r.removed, r.deleted, | |
1252 | unknown, ignored, r.clean) |
|
1252 | unknown, ignored, r.clean) | |
1253 | repo.status = overridestatus |
|
1253 | repo.status = overridestatus | |
1254 | orig(ui, repo, *dirs, **opts) |
|
1254 | orig(ui, repo, *dirs, **opts) | |
1255 | repo.status = oldstatus |
|
1255 | repo.status = oldstatus | |
1256 | def overriderollback(orig, ui, repo, **opts): |
|
1256 | def overriderollback(orig, ui, repo, **opts): | |
1257 | with repo.wlock(): |
|
1257 | with repo.wlock(): | |
1258 | before = repo.dirstate.parents() |
|
1258 | before = repo.dirstate.parents() | |
1259 | orphans = set(f for f in repo.dirstate |
|
1259 | orphans = set(f for f in repo.dirstate | |
1260 | if lfutil.isstandin(f) and repo.dirstate[f] != 'r') |
|
1260 | if lfutil.isstandin(f) and repo.dirstate[f] != 'r') | |
1261 | result = orig(ui, repo, **opts) |
|
1261 | result = orig(ui, repo, **opts) | |
1262 | after = repo.dirstate.parents() |
|
1262 | after = repo.dirstate.parents() | |
1263 | if before == after: |
|
1263 | if before == after: | |
1264 | return result # no need to restore standins |
|
1264 | return result # no need to restore standins | |
1265 |
|
1265 | |||
1266 | pctx = repo['.'] |
|
1266 | pctx = repo['.'] | |
1267 | for f in repo.dirstate: |
|
1267 | for f in repo.dirstate: | |
1268 | if lfutil.isstandin(f): |
|
1268 | if lfutil.isstandin(f): | |
1269 | orphans.discard(f) |
|
1269 | orphans.discard(f) | |
1270 | if repo.dirstate[f] == 'r': |
|
1270 | if repo.dirstate[f] == 'r': | |
1271 | repo.wvfs.unlinkpath(f, ignoremissing=True) |
|
1271 | repo.wvfs.unlinkpath(f, ignoremissing=True) | |
1272 | elif f in pctx: |
|
1272 | elif f in pctx: | |
1273 | fctx = pctx[f] |
|
1273 | fctx = pctx[f] | |
1274 | repo.wwrite(f, fctx.data(), fctx.flags()) |
|
1274 | repo.wwrite(f, fctx.data(), fctx.flags()) | |
1275 | else: |
|
1275 | else: | |
1276 | # content of standin is not so important in 'a', |
|
1276 | # content of standin is not so important in 'a', | |
1277 | # 'm' or 'n' (coming from the 2nd parent) cases |
|
1277 | # 'm' or 'n' (coming from the 2nd parent) cases | |
1278 | lfutil.writestandin(repo, f, '', False) |
|
1278 | lfutil.writestandin(repo, f, '', False) | |
1279 | for standin in orphans: |
|
1279 | for standin in orphans: | |
1280 | repo.wvfs.unlinkpath(standin, ignoremissing=True) |
|
1280 | repo.wvfs.unlinkpath(standin, ignoremissing=True) | |
1281 |
|
1281 | |||
1282 | lfdirstate = lfutil.openlfdirstate(ui, repo) |
|
1282 | lfdirstate = lfutil.openlfdirstate(ui, repo) | |
1283 | orphans = set(lfdirstate) |
|
1283 | orphans = set(lfdirstate) | |
1284 | lfiles = lfutil.listlfiles(repo) |
|
1284 | lfiles = lfutil.listlfiles(repo) | |
1285 | for file in lfiles: |
|
1285 | for file in lfiles: | |
1286 | lfutil.synclfdirstate(repo, lfdirstate, file, True) |
|
1286 | lfutil.synclfdirstate(repo, lfdirstate, file, True) | |
1287 | orphans.discard(file) |
|
1287 | orphans.discard(file) | |
1288 | for lfile in orphans: |
|
1288 | for lfile in orphans: | |
1289 | lfdirstate.drop(lfile) |
|
1289 | lfdirstate.drop(lfile) | |
1290 | lfdirstate.write() |
|
1290 | lfdirstate.write() | |
1291 | return result |
|
1291 | return result | |
1292 |
|
1292 | |||
1293 | def overridetransplant(orig, ui, repo, *revs, **opts): |
|
1293 | def overridetransplant(orig, ui, repo, *revs, **opts): | |
1294 | resuming = opts.get('continue') |
|
1294 | resuming = opts.get('continue') | |
1295 | repo._lfcommithooks.append(lfutil.automatedcommithook(resuming)) |
|
1295 | repo._lfcommithooks.append(lfutil.automatedcommithook(resuming)) | |
1296 | repo._lfstatuswriters.append(lambda *msg, **opts: None) |
|
1296 | repo._lfstatuswriters.append(lambda *msg, **opts: None) | |
1297 | try: |
|
1297 | try: | |
1298 | result = orig(ui, repo, *revs, **opts) |
|
1298 | result = orig(ui, repo, *revs, **opts) | |
1299 | finally: |
|
1299 | finally: | |
1300 | repo._lfstatuswriters.pop() |
|
1300 | repo._lfstatuswriters.pop() | |
1301 | repo._lfcommithooks.pop() |
|
1301 | repo._lfcommithooks.pop() | |
1302 | return result |
|
1302 | return result | |
1303 |
|
1303 | |||
1304 | def overridecat(orig, ui, repo, file1, *pats, **opts): |
|
1304 | def overridecat(orig, ui, repo, file1, *pats, **opts): | |
1305 | ctx = scmutil.revsingle(repo, opts.get('rev')) |
|
1305 | ctx = scmutil.revsingle(repo, opts.get('rev')) | |
1306 | err = 1 |
|
1306 | err = 1 | |
1307 | notbad = set() |
|
1307 | notbad = set() | |
1308 | m = scmutil.match(ctx, (file1,) + pats, opts) |
|
1308 | m = scmutil.match(ctx, (file1,) + pats, opts) | |
1309 | origmatchfn = m.matchfn |
|
1309 | origmatchfn = m.matchfn | |
1310 | def lfmatchfn(f): |
|
1310 | def lfmatchfn(f): | |
1311 | if origmatchfn(f): |
|
1311 | if origmatchfn(f): | |
1312 | return True |
|
1312 | return True | |
1313 | lf = lfutil.splitstandin(f) |
|
1313 | lf = lfutil.splitstandin(f) | |
1314 | if lf is None: |
|
1314 | if lf is None: | |
1315 | return False |
|
1315 | return False | |
1316 | notbad.add(lf) |
|
1316 | notbad.add(lf) | |
1317 | return origmatchfn(lf) |
|
1317 | return origmatchfn(lf) | |
1318 | m.matchfn = lfmatchfn |
|
1318 | m.matchfn = lfmatchfn | |
1319 | origbadfn = m.bad |
|
1319 | origbadfn = m.bad | |
1320 | def lfbadfn(f, msg): |
|
1320 | def lfbadfn(f, msg): | |
1321 | if not f in notbad: |
|
1321 | if not f in notbad: | |
1322 | origbadfn(f, msg) |
|
1322 | origbadfn(f, msg) | |
1323 | m.bad = lfbadfn |
|
1323 | m.bad = lfbadfn | |
1324 |
|
1324 | |||
1325 | origvisitdirfn = m.visitdir |
|
1325 | origvisitdirfn = m.visitdir | |
1326 | def lfvisitdirfn(dir): |
|
1326 | def lfvisitdirfn(dir): | |
1327 | if dir == lfutil.shortname: |
|
1327 | if dir == lfutil.shortname: | |
1328 | return True |
|
1328 | return True | |
1329 | ret = origvisitdirfn(dir) |
|
1329 | ret = origvisitdirfn(dir) | |
1330 | if ret: |
|
1330 | if ret: | |
1331 | return ret |
|
1331 | return ret | |
1332 | lf = lfutil.splitstandin(dir) |
|
1332 | lf = lfutil.splitstandin(dir) | |
1333 | if lf is None: |
|
1333 | if lf is None: | |
1334 | return False |
|
1334 | return False | |
1335 | return origvisitdirfn(lf) |
|
1335 | return origvisitdirfn(lf) | |
1336 | m.visitdir = lfvisitdirfn |
|
1336 | m.visitdir = lfvisitdirfn | |
1337 |
|
1337 | |||
1338 | for f in ctx.walk(m): |
|
1338 | for f in ctx.walk(m): | |
1339 | with cmdutil.makefileobj(repo, opts.get('output'), ctx.node(), |
|
1339 | with cmdutil.makefileobj(repo, opts.get('output'), ctx.node(), | |
1340 | pathname=f) as fp: |
|
1340 | pathname=f) as fp: | |
1341 | lf = lfutil.splitstandin(f) |
|
1341 | lf = lfutil.splitstandin(f) | |
1342 | if lf is None or origmatchfn(f): |
|
1342 | if lf is None or origmatchfn(f): | |
1343 | # duplicating unreachable code from commands.cat |
|
1343 | # duplicating unreachable code from commands.cat | |
1344 | data = ctx[f].data() |
|
1344 | data = ctx[f].data() | |
1345 | if opts.get('decode'): |
|
1345 | if opts.get('decode'): | |
1346 | data = repo.wwritedata(f, data) |
|
1346 | data = repo.wwritedata(f, data) | |
1347 | fp.write(data) |
|
1347 | fp.write(data) | |
1348 | else: |
|
1348 | else: | |
1349 | hash = lfutil.readstandin(repo, lf, ctx.rev()) |
|
1349 | hash = lfutil.readstandin(repo, lf, ctx.rev()) | |
1350 | if not lfutil.inusercache(repo.ui, hash): |
|
1350 | if not lfutil.inusercache(repo.ui, hash): | |
1351 | store = storefactory.openstore(repo) |
|
1351 | store = storefactory.openstore(repo) | |
1352 | success, missing = store.get([(lf, hash)]) |
|
1352 | success, missing = store.get([(lf, hash)]) | |
1353 | if len(success) != 1: |
|
1353 | if len(success) != 1: | |
1354 | raise error.Abort( |
|
1354 | raise error.Abort( | |
1355 | _('largefile %s is not in cache and could not be ' |
|
1355 | _('largefile %s is not in cache and could not be ' | |
1356 | 'downloaded') % lf) |
|
1356 | 'downloaded') % lf) | |
1357 | path = lfutil.usercachepath(repo.ui, hash) |
|
1357 | path = lfutil.usercachepath(repo.ui, hash) | |
1358 | with open(path, "rb") as fpin: |
|
1358 | with open(path, "rb") as fpin: | |
1359 | for chunk in util.filechunkiter(fpin): |
|
1359 | for chunk in util.filechunkiter(fpin): | |
1360 | fp.write(chunk) |
|
1360 | fp.write(chunk) | |
1361 | err = 0 |
|
1361 | err = 0 | |
1362 | return err |
|
1362 | return err | |
1363 |
|
1363 | |||
1364 | def mergeupdate(orig, repo, node, branchmerge, force, |
|
1364 | def mergeupdate(orig, repo, node, branchmerge, force, | |
1365 | *args, **kwargs): |
|
1365 | *args, **kwargs): | |
1366 | matcher = kwargs.get('matcher', None) |
|
1366 | matcher = kwargs.get('matcher', None) | |
1367 | # note if this is a partial update |
|
1367 | # note if this is a partial update | |
1368 | partial = matcher and not matcher.always() |
|
1368 | partial = matcher and not matcher.always() | |
1369 | with repo.wlock(): |
|
1369 | with repo.wlock(): | |
1370 | # branch | | | |
|
1370 | # branch | | | | |
1371 | # merge | force | partial | action |
|
1371 | # merge | force | partial | action | |
1372 | # -------+-------+---------+-------------- |
|
1372 | # -------+-------+---------+-------------- | |
1373 | # x | x | x | linear-merge |
|
1373 | # x | x | x | linear-merge | |
1374 | # o | x | x | branch-merge |
|
1374 | # o | x | x | branch-merge | |
1375 | # x | o | x | overwrite (as clean update) |
|
1375 | # x | o | x | overwrite (as clean update) | |
1376 | # o | o | x | force-branch-merge (*1) |
|
1376 | # o | o | x | force-branch-merge (*1) | |
1377 | # x | x | o | (*) |
|
1377 | # x | x | o | (*) | |
1378 | # o | x | o | (*) |
|
1378 | # o | x | o | (*) | |
1379 | # x | o | o | overwrite (as revert) |
|
1379 | # x | o | o | overwrite (as revert) | |
1380 | # o | o | o | (*) |
|
1380 | # o | o | o | (*) | |
1381 | # |
|
1381 | # | |
1382 | # (*) don't care |
|
1382 | # (*) don't care | |
1383 | # (*1) deprecated, but used internally (e.g: "rebase --collapse") |
|
1383 | # (*1) deprecated, but used internally (e.g: "rebase --collapse") | |
1384 |
|
1384 | |||
1385 | lfdirstate = lfutil.openlfdirstate(repo.ui, repo) |
|
1385 | lfdirstate = lfutil.openlfdirstate(repo.ui, repo) | |
1386 | unsure, s = lfdirstate.status(matchmod.always(repo.root, |
|
1386 | unsure, s = lfdirstate.status(matchmod.always(repo.root, | |
1387 | repo.getcwd()), |
|
1387 | repo.getcwd()), | |
1388 |
[], False, |
|
1388 | [], False, True, False) | |
|
1389 | oldclean = set(s.clean) | |||
1389 | pctx = repo['.'] |
|
1390 | pctx = repo['.'] | |
1390 | for lfile in unsure + s.modified: |
|
1391 | for lfile in unsure + s.modified: | |
1391 | lfileabs = repo.wvfs.join(lfile) |
|
1392 | lfileabs = repo.wvfs.join(lfile) | |
1392 | if not repo.wvfs.exists(lfileabs): |
|
1393 | if not repo.wvfs.exists(lfileabs): | |
1393 | continue |
|
1394 | continue | |
1394 | lfhash = lfutil.hashrepofile(repo, lfile) |
|
1395 | lfhash = lfutil.hashrepofile(repo, lfile) | |
1395 | standin = lfutil.standin(lfile) |
|
1396 | standin = lfutil.standin(lfile) | |
1396 | lfutil.writestandin(repo, standin, lfhash, |
|
1397 | lfutil.writestandin(repo, standin, lfhash, | |
1397 | lfutil.getexecutable(lfileabs)) |
|
1398 | lfutil.getexecutable(lfileabs)) | |
1398 | if (standin in pctx and |
|
1399 | if (standin in pctx and | |
1399 | lfhash == lfutil.readstandin(repo, lfile, '.')): |
|
1400 | lfhash == lfutil.readstandin(repo, lfile, '.')): | |
1400 |
|
|
1401 | oldclean.add(lfile) | |
1401 | for lfile in s.added: |
|
1402 | for lfile in s.added: | |
1402 | lfutil.updatestandin(repo, lfutil.standin(lfile)) |
|
1403 | lfutil.updatestandin(repo, lfutil.standin(lfile)) | |
|
1404 | # mark all clean largefiles as dirty, just in case the update gets | |||
|
1405 | # interrupted before largefiles and lfdirstate are synchronized | |||
|
1406 | for lfile in oldclean: | |||
|
1407 | lfdirstate.normallookup(lfile) | |||
1403 | lfdirstate.write() |
|
1408 | lfdirstate.write() | |
1404 |
|
1409 | |||
1405 | oldstandins = lfutil.getstandinsstate(repo) |
|
1410 | oldstandins = lfutil.getstandinsstate(repo) | |
1406 |
|
1411 | |||
1407 | result = orig(repo, node, branchmerge, force, *args, **kwargs) |
|
1412 | result = orig(repo, node, branchmerge, force, *args, **kwargs) | |
1408 |
|
1413 | |||
1409 | newstandins = lfutil.getstandinsstate(repo) |
|
1414 | newstandins = lfutil.getstandinsstate(repo) | |
1410 | filelist = lfutil.getlfilestoupdate(oldstandins, newstandins) |
|
1415 | filelist = lfutil.getlfilestoupdate(oldstandins, newstandins) | |
|
1416 | ||||
|
1417 | # to avoid leaving all largefiles as dirty and thus rehash them, mark | |||
|
1418 | # all the ones that didn't change as clean | |||
|
1419 | for lfile in oldclean.difference(filelist): | |||
|
1420 | lfdirstate.normal(lfile) | |||
|
1421 | lfdirstate.write() | |||
|
1422 | ||||
1411 | if branchmerge or force or partial: |
|
1423 | if branchmerge or force or partial: | |
1412 | filelist.extend(s.deleted + s.removed) |
|
1424 | filelist.extend(s.deleted + s.removed) | |
1413 |
|
1425 | |||
1414 | lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, |
|
1426 | lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, | |
1415 | normallookup=partial) |
|
1427 | normallookup=partial) | |
1416 |
|
1428 | |||
1417 | return result |
|
1429 | return result | |
1418 |
|
1430 | |||
1419 | def scmutilmarktouched(orig, repo, files, *args, **kwargs): |
|
1431 | def scmutilmarktouched(orig, repo, files, *args, **kwargs): | |
1420 | result = orig(repo, files, *args, **kwargs) |
|
1432 | result = orig(repo, files, *args, **kwargs) | |
1421 |
|
1433 | |||
1422 | filelist = [lfutil.splitstandin(f) for f in files if lfutil.isstandin(f)] |
|
1434 | filelist = [lfutil.splitstandin(f) for f in files if lfutil.isstandin(f)] | |
1423 | if filelist: |
|
1435 | if filelist: | |
1424 | lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, |
|
1436 | lfcommands.updatelfiles(repo.ui, repo, filelist=filelist, | |
1425 | printmessage=False, normallookup=True) |
|
1437 | printmessage=False, normallookup=True) | |
1426 |
|
1438 | |||
1427 | return result |
|
1439 | return result |
@@ -1,385 +1,389 b'' | |||||
1 | # Copyright 2009-2010 Gregory P. Ward |
|
1 | # Copyright 2009-2010 Gregory P. Ward | |
2 | # Copyright 2009-2010 Intelerad Medical Systems Incorporated |
|
2 | # Copyright 2009-2010 Intelerad Medical Systems Incorporated | |
3 | # Copyright 2010-2011 Fog Creek Software |
|
3 | # Copyright 2010-2011 Fog Creek Software | |
4 | # Copyright 2010-2011 Unity Technologies |
|
4 | # Copyright 2010-2011 Unity Technologies | |
5 | # |
|
5 | # | |
6 | # This software may be used and distributed according to the terms of the |
|
6 | # This software may be used and distributed according to the terms of the | |
7 | # GNU General Public License version 2 or any later version. |
|
7 | # GNU General Public License version 2 or any later version. | |
8 |
|
8 | |||
9 | '''setup for largefiles repositories: reposetup''' |
|
9 | '''setup for largefiles repositories: reposetup''' | |
10 | from __future__ import absolute_import |
|
10 | from __future__ import absolute_import | |
11 |
|
11 | |||
12 | import copy |
|
12 | import copy | |
13 |
|
13 | |||
14 | from mercurial.i18n import _ |
|
14 | from mercurial.i18n import _ | |
15 |
|
15 | |||
16 | from mercurial import ( |
|
16 | from mercurial import ( | |
17 | error, |
|
17 | error, | |
18 | localrepo, |
|
18 | localrepo, | |
19 | match as matchmod, |
|
19 | match as matchmod, | |
20 | scmutil, |
|
20 | scmutil, | |
21 | ) |
|
21 | ) | |
22 |
|
22 | |||
23 | from . import ( |
|
23 | from . import ( | |
24 | lfcommands, |
|
24 | lfcommands, | |
25 | lfutil, |
|
25 | lfutil, | |
26 | ) |
|
26 | ) | |
27 |
|
27 | |||
28 | def reposetup(ui, repo): |
|
28 | def reposetup(ui, repo): | |
29 | # wire repositories should be given new wireproto functions |
|
29 | # wire repositories should be given new wireproto functions | |
30 | # by "proto.wirereposetup()" via "hg.wirepeersetupfuncs" |
|
30 | # by "proto.wirereposetup()" via "hg.wirepeersetupfuncs" | |
31 | if not repo.local(): |
|
31 | if not repo.local(): | |
32 | return |
|
32 | return | |
33 |
|
33 | |||
34 | class lfilesrepo(repo.__class__): |
|
34 | class lfilesrepo(repo.__class__): | |
35 | # the mark to examine whether "repo" object enables largefiles or not |
|
35 | # the mark to examine whether "repo" object enables largefiles or not | |
36 | _largefilesenabled = True |
|
36 | _largefilesenabled = True | |
37 |
|
37 | |||
38 | lfstatus = False |
|
38 | lfstatus = False | |
39 | def status_nolfiles(self, *args, **kwargs): |
|
39 | def status_nolfiles(self, *args, **kwargs): | |
40 | return super(lfilesrepo, self).status(*args, **kwargs) |
|
40 | return super(lfilesrepo, self).status(*args, **kwargs) | |
41 |
|
41 | |||
42 | # When lfstatus is set, return a context that gives the names |
|
42 | # When lfstatus is set, return a context that gives the names | |
43 | # of largefiles instead of their corresponding standins and |
|
43 | # of largefiles instead of their corresponding standins and | |
44 | # identifies the largefiles as always binary, regardless of |
|
44 | # identifies the largefiles as always binary, regardless of | |
45 | # their actual contents. |
|
45 | # their actual contents. | |
46 | def __getitem__(self, changeid): |
|
46 | def __getitem__(self, changeid): | |
47 | ctx = super(lfilesrepo, self).__getitem__(changeid) |
|
47 | ctx = super(lfilesrepo, self).__getitem__(changeid) | |
48 | if self.lfstatus: |
|
48 | if self.lfstatus: | |
49 | class lfilesctx(ctx.__class__): |
|
49 | class lfilesctx(ctx.__class__): | |
50 | def files(self): |
|
50 | def files(self): | |
51 | filenames = super(lfilesctx, self).files() |
|
51 | filenames = super(lfilesctx, self).files() | |
52 | return [lfutil.splitstandin(f) or f for f in filenames] |
|
52 | return [lfutil.splitstandin(f) or f for f in filenames] | |
53 | def manifest(self): |
|
53 | def manifest(self): | |
54 | man1 = super(lfilesctx, self).manifest() |
|
54 | man1 = super(lfilesctx, self).manifest() | |
55 | class lfilesmanifest(man1.__class__): |
|
55 | class lfilesmanifest(man1.__class__): | |
56 | def __contains__(self, filename): |
|
56 | def __contains__(self, filename): | |
57 | orig = super(lfilesmanifest, self).__contains__ |
|
57 | orig = super(lfilesmanifest, self).__contains__ | |
58 | return (orig(filename) or |
|
58 | return (orig(filename) or | |
59 | orig(lfutil.standin(filename))) |
|
59 | orig(lfutil.standin(filename))) | |
60 | man1.__class__ = lfilesmanifest |
|
60 | man1.__class__ = lfilesmanifest | |
61 | return man1 |
|
61 | return man1 | |
62 | def filectx(self, path, fileid=None, filelog=None): |
|
62 | def filectx(self, path, fileid=None, filelog=None): | |
63 | orig = super(lfilesctx, self).filectx |
|
63 | orig = super(lfilesctx, self).filectx | |
64 | try: |
|
64 | try: | |
65 | if filelog is not None: |
|
65 | if filelog is not None: | |
66 | result = orig(path, fileid, filelog) |
|
66 | result = orig(path, fileid, filelog) | |
67 | else: |
|
67 | else: | |
68 | result = orig(path, fileid) |
|
68 | result = orig(path, fileid) | |
69 | except error.LookupError: |
|
69 | except error.LookupError: | |
70 | # Adding a null character will cause Mercurial to |
|
70 | # Adding a null character will cause Mercurial to | |
71 | # identify this as a binary file. |
|
71 | # identify this as a binary file. | |
72 | if filelog is not None: |
|
72 | if filelog is not None: | |
73 | result = orig(lfutil.standin(path), fileid, |
|
73 | result = orig(lfutil.standin(path), fileid, | |
74 | filelog) |
|
74 | filelog) | |
75 | else: |
|
75 | else: | |
76 | result = orig(lfutil.standin(path), fileid) |
|
76 | result = orig(lfutil.standin(path), fileid) | |
77 | olddata = result.data |
|
77 | olddata = result.data | |
78 | result.data = lambda: olddata() + '\0' |
|
78 | result.data = lambda: olddata() + '\0' | |
79 | return result |
|
79 | return result | |
80 | ctx.__class__ = lfilesctx |
|
80 | ctx.__class__ = lfilesctx | |
81 | return ctx |
|
81 | return ctx | |
82 |
|
82 | |||
83 | # Figure out the status of big files and insert them into the |
|
83 | # Figure out the status of big files and insert them into the | |
84 | # appropriate list in the result. Also removes standin files |
|
84 | # appropriate list in the result. Also removes standin files | |
85 | # from the listing. Revert to the original status if |
|
85 | # from the listing. Revert to the original status if | |
86 | # self.lfstatus is False. |
|
86 | # self.lfstatus is False. | |
87 | # XXX large file status is buggy when used on repo proxy. |
|
87 | # XXX large file status is buggy when used on repo proxy. | |
88 | # XXX this needs to be investigated. |
|
88 | # XXX this needs to be investigated. | |
89 | @localrepo.unfilteredmethod |
|
89 | @localrepo.unfilteredmethod | |
90 | def status(self, node1='.', node2=None, match=None, ignored=False, |
|
90 | def status(self, node1='.', node2=None, match=None, ignored=False, | |
91 | clean=False, unknown=False, listsubrepos=False): |
|
91 | clean=False, unknown=False, listsubrepos=False): | |
92 | listignored, listclean, listunknown = ignored, clean, unknown |
|
92 | listignored, listclean, listunknown = ignored, clean, unknown | |
93 | orig = super(lfilesrepo, self).status |
|
93 | orig = super(lfilesrepo, self).status | |
94 | if not self.lfstatus: |
|
94 | if not self.lfstatus: | |
95 | return orig(node1, node2, match, listignored, listclean, |
|
95 | return orig(node1, node2, match, listignored, listclean, | |
96 | listunknown, listsubrepos) |
|
96 | listunknown, listsubrepos) | |
97 |
|
97 | |||
98 | # some calls in this function rely on the old version of status |
|
98 | # some calls in this function rely on the old version of status | |
99 | self.lfstatus = False |
|
99 | self.lfstatus = False | |
100 | ctx1 = self[node1] |
|
100 | ctx1 = self[node1] | |
101 | ctx2 = self[node2] |
|
101 | ctx2 = self[node2] | |
102 | working = ctx2.rev() is None |
|
102 | working = ctx2.rev() is None | |
103 | parentworking = working and ctx1 == self['.'] |
|
103 | parentworking = working and ctx1 == self['.'] | |
104 |
|
104 | |||
105 | if match is None: |
|
105 | if match is None: | |
106 | match = matchmod.always(self.root, self.getcwd()) |
|
106 | match = matchmod.always(self.root, self.getcwd()) | |
107 |
|
107 | |||
108 | wlock = None |
|
108 | wlock = None | |
109 | try: |
|
109 | try: | |
110 | try: |
|
110 | try: | |
111 | # updating the dirstate is optional |
|
111 | # updating the dirstate is optional | |
112 | # so we don't wait on the lock |
|
112 | # so we don't wait on the lock | |
113 | wlock = self.wlock(False) |
|
113 | wlock = self.wlock(False) | |
114 | except error.LockError: |
|
114 | except error.LockError: | |
115 | pass |
|
115 | pass | |
116 |
|
116 | |||
117 | # First check if paths or patterns were specified on the |
|
117 | # First check if paths or patterns were specified on the | |
118 | # command line. If there were, and they don't match any |
|
118 | # command line. If there were, and they don't match any | |
119 | # largefiles, we should just bail here and let super |
|
119 | # largefiles, we should just bail here and let super | |
120 | # handle it -- thus gaining a big performance boost. |
|
120 | # handle it -- thus gaining a big performance boost. | |
121 | lfdirstate = lfutil.openlfdirstate(ui, self) |
|
121 | lfdirstate = lfutil.openlfdirstate(ui, self) | |
122 | if not match.always(): |
|
122 | if not match.always(): | |
123 | for f in lfdirstate: |
|
123 | for f in lfdirstate: | |
124 | if match(f): |
|
124 | if match(f): | |
125 | break |
|
125 | break | |
126 | else: |
|
126 | else: | |
127 | return orig(node1, node2, match, listignored, listclean, |
|
127 | return orig(node1, node2, match, listignored, listclean, | |
128 | listunknown, listsubrepos) |
|
128 | listunknown, listsubrepos) | |
129 |
|
129 | |||
130 | # Create a copy of match that matches standins instead |
|
130 | # Create a copy of match that matches standins instead | |
131 | # of largefiles. |
|
131 | # of largefiles. | |
132 | def tostandins(files): |
|
132 | def tostandins(files): | |
133 | if not working: |
|
133 | if not working: | |
134 | return files |
|
134 | return files | |
135 | newfiles = [] |
|
135 | newfiles = [] | |
136 | dirstate = self.dirstate |
|
136 | dirstate = self.dirstate | |
137 | for f in files: |
|
137 | for f in files: | |
138 | sf = lfutil.standin(f) |
|
138 | sf = lfutil.standin(f) | |
139 | if sf in dirstate: |
|
139 | if sf in dirstate: | |
140 | newfiles.append(sf) |
|
140 | newfiles.append(sf) | |
141 | elif sf in dirstate.dirs(): |
|
141 | elif sf in dirstate.dirs(): | |
142 | # Directory entries could be regular or |
|
142 | # Directory entries could be regular or | |
143 | # standin, check both |
|
143 | # standin, check both | |
144 | newfiles.extend((f, sf)) |
|
144 | newfiles.extend((f, sf)) | |
145 | else: |
|
145 | else: | |
146 | newfiles.append(f) |
|
146 | newfiles.append(f) | |
147 | return newfiles |
|
147 | return newfiles | |
148 |
|
148 | |||
149 | m = copy.copy(match) |
|
149 | m = copy.copy(match) | |
150 | m._files = tostandins(m._files) |
|
150 | m._files = tostandins(m._files) | |
151 |
|
151 | |||
152 | result = orig(node1, node2, m, ignored, clean, unknown, |
|
152 | result = orig(node1, node2, m, ignored, clean, unknown, | |
153 | listsubrepos) |
|
153 | listsubrepos) | |
154 | if working: |
|
154 | if working: | |
155 |
|
155 | |||
156 | def sfindirstate(f): |
|
156 | def sfindirstate(f): | |
157 | sf = lfutil.standin(f) |
|
157 | sf = lfutil.standin(f) | |
158 | dirstate = self.dirstate |
|
158 | dirstate = self.dirstate | |
159 | return sf in dirstate or sf in dirstate.dirs() |
|
159 | return sf in dirstate or sf in dirstate.dirs() | |
160 |
|
160 | |||
161 | match._files = [f for f in match._files |
|
161 | match._files = [f for f in match._files | |
162 | if sfindirstate(f)] |
|
162 | if sfindirstate(f)] | |
163 | # Don't waste time getting the ignored and unknown |
|
163 | # Don't waste time getting the ignored and unknown | |
164 | # files from lfdirstate |
|
164 | # files from lfdirstate | |
165 | unsure, s = lfdirstate.status(match, [], False, listclean, |
|
165 | unsure, s = lfdirstate.status(match, [], False, listclean, | |
166 | False) |
|
166 | False) | |
167 |
(modified, added, removed, clean) = ( |
|
167 | (modified, added, removed, deleted, clean) = ( | |
168 | s.removed, s.clean) |
|
168 | s.modified, s.added, s.removed, s.deleted, s.clean) | |
169 | if parentworking: |
|
169 | if parentworking: | |
170 | for lfile in unsure: |
|
170 | for lfile in unsure: | |
171 | standin = lfutil.standin(lfile) |
|
171 | standin = lfutil.standin(lfile) | |
172 | if standin not in ctx1: |
|
172 | if standin not in ctx1: | |
173 | # from second parent |
|
173 | # from second parent | |
174 | modified.append(lfile) |
|
174 | modified.append(lfile) | |
175 | elif ctx1[standin].data().strip() \ |
|
175 | elif ctx1[standin].data().strip() \ | |
176 | != lfutil.hashfile(self.wjoin(lfile)): |
|
176 | != lfutil.hashfile(self.wjoin(lfile)): | |
177 | modified.append(lfile) |
|
177 | modified.append(lfile) | |
178 | else: |
|
178 | else: | |
179 | if listclean: |
|
179 | if listclean: | |
180 | clean.append(lfile) |
|
180 | clean.append(lfile) | |
181 | lfdirstate.normal(lfile) |
|
181 | lfdirstate.normal(lfile) | |
182 | else: |
|
182 | else: | |
183 | tocheck = unsure + modified + added + clean |
|
183 | tocheck = unsure + modified + added + clean | |
184 | modified, added, clean = [], [], [] |
|
184 | modified, added, clean = [], [], [] | |
185 | checkexec = self.dirstate._checkexec |
|
185 | checkexec = self.dirstate._checkexec | |
186 |
|
186 | |||
187 | for lfile in tocheck: |
|
187 | for lfile in tocheck: | |
188 | standin = lfutil.standin(lfile) |
|
188 | standin = lfutil.standin(lfile) | |
189 | if standin in ctx1: |
|
189 | if standin in ctx1: | |
190 | abslfile = self.wjoin(lfile) |
|
190 | abslfile = self.wjoin(lfile) | |
191 | if ((ctx1[standin].data().strip() != |
|
191 | if ((ctx1[standin].data().strip() != | |
192 | lfutil.hashfile(abslfile)) or |
|
192 | lfutil.hashfile(abslfile)) or | |
193 | (checkexec and |
|
193 | (checkexec and | |
194 | ('x' in ctx1.flags(standin)) != |
|
194 | ('x' in ctx1.flags(standin)) != | |
195 | bool(lfutil.getexecutable(abslfile)))): |
|
195 | bool(lfutil.getexecutable(abslfile)))): | |
196 | modified.append(lfile) |
|
196 | modified.append(lfile) | |
197 | elif listclean: |
|
197 | elif listclean: | |
198 | clean.append(lfile) |
|
198 | clean.append(lfile) | |
199 | else: |
|
199 | else: | |
200 | added.append(lfile) |
|
200 | added.append(lfile) | |
201 |
|
201 | |||
202 | # at this point, 'removed' contains largefiles |
|
202 | # at this point, 'removed' contains largefiles | |
203 | # marked as 'R' in the working context. |
|
203 | # marked as 'R' in the working context. | |
204 | # then, largefiles not managed also in the target |
|
204 | # then, largefiles not managed also in the target | |
205 | # context should be excluded from 'removed'. |
|
205 | # context should be excluded from 'removed'. | |
206 | removed = [lfile for lfile in removed |
|
206 | removed = [lfile for lfile in removed | |
207 | if lfutil.standin(lfile) in ctx1] |
|
207 | if lfutil.standin(lfile) in ctx1] | |
208 |
|
208 | |||
209 |
# Standins no longer found in lfdirstate ha |
|
209 | # Standins no longer found in lfdirstate have been deleted | |
210 | # removed |
|
|||
211 | for standin in ctx1.walk(lfutil.getstandinmatcher(self)): |
|
210 | for standin in ctx1.walk(lfutil.getstandinmatcher(self)): | |
212 | lfile = lfutil.splitstandin(standin) |
|
211 | lfile = lfutil.splitstandin(standin) | |
213 | if not match(lfile): |
|
212 | if not match(lfile): | |
214 | continue |
|
213 | continue | |
215 | if lfile not in lfdirstate: |
|
214 | if lfile not in lfdirstate: | |
216 |
|
|
215 | deleted.append(lfile) | |
|
216 | # Sync "largefile has been removed" back to the | |||
|
217 | # standin. Removing a file as a side effect of | |||
|
218 | # running status is gross, but the alternatives (if | |||
|
219 | # any) are worse. | |||
|
220 | self.wvfs.unlinkpath(standin, ignoremissing=True) | |||
217 |
|
221 | |||
218 | # Filter result lists |
|
222 | # Filter result lists | |
219 | result = list(result) |
|
223 | result = list(result) | |
220 |
|
224 | |||
221 | # Largefiles are not really removed when they're |
|
225 | # Largefiles are not really removed when they're | |
222 | # still in the normal dirstate. Likewise, normal |
|
226 | # still in the normal dirstate. Likewise, normal | |
223 | # files are not really removed if they are still in |
|
227 | # files are not really removed if they are still in | |
224 | # lfdirstate. This happens in merges where files |
|
228 | # lfdirstate. This happens in merges where files | |
225 | # change type. |
|
229 | # change type. | |
226 | removed = [f for f in removed |
|
230 | removed = [f for f in removed | |
227 | if f not in self.dirstate] |
|
231 | if f not in self.dirstate] | |
228 | result[2] = [f for f in result[2] |
|
232 | result[2] = [f for f in result[2] | |
229 | if f not in lfdirstate] |
|
233 | if f not in lfdirstate] | |
230 |
|
234 | |||
231 | lfiles = set(lfdirstate._map) |
|
235 | lfiles = set(lfdirstate._map) | |
232 | # Unknown files |
|
236 | # Unknown files | |
233 | result[4] = set(result[4]).difference(lfiles) |
|
237 | result[4] = set(result[4]).difference(lfiles) | |
234 | # Ignored files |
|
238 | # Ignored files | |
235 | result[5] = set(result[5]).difference(lfiles) |
|
239 | result[5] = set(result[5]).difference(lfiles) | |
236 | # combine normal files and largefiles |
|
240 | # combine normal files and largefiles | |
237 | normals = [[fn for fn in filelist |
|
241 | normals = [[fn for fn in filelist | |
238 | if not lfutil.isstandin(fn)] |
|
242 | if not lfutil.isstandin(fn)] | |
239 | for filelist in result] |
|
243 | for filelist in result] | |
240 |
lfstatus = (modified, added, removed, |
|
244 | lfstatus = (modified, added, removed, deleted, [], [], | |
241 | clean) |
|
245 | clean) | |
242 | result = [sorted(list1 + list2) |
|
246 | result = [sorted(list1 + list2) | |
243 | for (list1, list2) in zip(normals, lfstatus)] |
|
247 | for (list1, list2) in zip(normals, lfstatus)] | |
244 | else: # not against working directory |
|
248 | else: # not against working directory | |
245 | result = [[lfutil.splitstandin(f) or f for f in items] |
|
249 | result = [[lfutil.splitstandin(f) or f for f in items] | |
246 | for items in result] |
|
250 | for items in result] | |
247 |
|
251 | |||
248 | if wlock: |
|
252 | if wlock: | |
249 | lfdirstate.write() |
|
253 | lfdirstate.write() | |
250 |
|
254 | |||
251 | finally: |
|
255 | finally: | |
252 | if wlock: |
|
256 | if wlock: | |
253 | wlock.release() |
|
257 | wlock.release() | |
254 |
|
258 | |||
255 | self.lfstatus = True |
|
259 | self.lfstatus = True | |
256 | return scmutil.status(*result) |
|
260 | return scmutil.status(*result) | |
257 |
|
261 | |||
258 | def commitctx(self, ctx, *args, **kwargs): |
|
262 | def commitctx(self, ctx, *args, **kwargs): | |
259 | node = super(lfilesrepo, self).commitctx(ctx, *args, **kwargs) |
|
263 | node = super(lfilesrepo, self).commitctx(ctx, *args, **kwargs) | |
260 | class lfilesctx(ctx.__class__): |
|
264 | class lfilesctx(ctx.__class__): | |
261 | def markcommitted(self, node): |
|
265 | def markcommitted(self, node): | |
262 | orig = super(lfilesctx, self).markcommitted |
|
266 | orig = super(lfilesctx, self).markcommitted | |
263 | return lfutil.markcommitted(orig, self, node) |
|
267 | return lfutil.markcommitted(orig, self, node) | |
264 | ctx.__class__ = lfilesctx |
|
268 | ctx.__class__ = lfilesctx | |
265 | return node |
|
269 | return node | |
266 |
|
270 | |||
267 | # Before commit, largefile standins have not had their |
|
271 | # Before commit, largefile standins have not had their | |
268 | # contents updated to reflect the hash of their largefile. |
|
272 | # contents updated to reflect the hash of their largefile. | |
269 | # Do that here. |
|
273 | # Do that here. | |
270 | def commit(self, text="", user=None, date=None, match=None, |
|
274 | def commit(self, text="", user=None, date=None, match=None, | |
271 | force=False, editor=False, extra={}): |
|
275 | force=False, editor=False, extra={}): | |
272 | orig = super(lfilesrepo, self).commit |
|
276 | orig = super(lfilesrepo, self).commit | |
273 |
|
277 | |||
274 | with self.wlock(): |
|
278 | with self.wlock(): | |
275 | lfcommithook = self._lfcommithooks[-1] |
|
279 | lfcommithook = self._lfcommithooks[-1] | |
276 | match = lfcommithook(self, match) |
|
280 | match = lfcommithook(self, match) | |
277 | result = orig(text=text, user=user, date=date, match=match, |
|
281 | result = orig(text=text, user=user, date=date, match=match, | |
278 | force=force, editor=editor, extra=extra) |
|
282 | force=force, editor=editor, extra=extra) | |
279 | return result |
|
283 | return result | |
280 |
|
284 | |||
281 | def push(self, remote, force=False, revs=None, newbranch=False): |
|
285 | def push(self, remote, force=False, revs=None, newbranch=False): | |
282 | if remote.local(): |
|
286 | if remote.local(): | |
283 | missing = set(self.requirements) - remote.local().supported |
|
287 | missing = set(self.requirements) - remote.local().supported | |
284 | if missing: |
|
288 | if missing: | |
285 | msg = _("required features are not" |
|
289 | msg = _("required features are not" | |
286 | " supported in the destination:" |
|
290 | " supported in the destination:" | |
287 | " %s") % (', '.join(sorted(missing))) |
|
291 | " %s") % (', '.join(sorted(missing))) | |
288 | raise error.Abort(msg) |
|
292 | raise error.Abort(msg) | |
289 | return super(lfilesrepo, self).push(remote, force=force, revs=revs, |
|
293 | return super(lfilesrepo, self).push(remote, force=force, revs=revs, | |
290 | newbranch=newbranch) |
|
294 | newbranch=newbranch) | |
291 |
|
295 | |||
292 | # TODO: _subdirlfs should be moved into "lfutil.py", because |
|
296 | # TODO: _subdirlfs should be moved into "lfutil.py", because | |
293 | # it is referred only from "lfutil.updatestandinsbymatch" |
|
297 | # it is referred only from "lfutil.updatestandinsbymatch" | |
294 | def _subdirlfs(self, files, lfiles): |
|
298 | def _subdirlfs(self, files, lfiles): | |
295 | ''' |
|
299 | ''' | |
296 | Adjust matched file list |
|
300 | Adjust matched file list | |
297 | If we pass a directory to commit whose only committable files |
|
301 | If we pass a directory to commit whose only committable files | |
298 | are largefiles, the core commit code aborts before finding |
|
302 | are largefiles, the core commit code aborts before finding | |
299 | the largefiles. |
|
303 | the largefiles. | |
300 | So we do the following: |
|
304 | So we do the following: | |
301 | For directories that only have largefiles as matches, |
|
305 | For directories that only have largefiles as matches, | |
302 | we explicitly add the largefiles to the match list and remove |
|
306 | we explicitly add the largefiles to the match list and remove | |
303 | the directory. |
|
307 | the directory. | |
304 | In other cases, we leave the match list unmodified. |
|
308 | In other cases, we leave the match list unmodified. | |
305 | ''' |
|
309 | ''' | |
306 | actualfiles = [] |
|
310 | actualfiles = [] | |
307 | dirs = [] |
|
311 | dirs = [] | |
308 | regulars = [] |
|
312 | regulars = [] | |
309 |
|
313 | |||
310 | for f in files: |
|
314 | for f in files: | |
311 | if lfutil.isstandin(f + '/'): |
|
315 | if lfutil.isstandin(f + '/'): | |
312 | raise error.Abort( |
|
316 | raise error.Abort( | |
313 | _('file "%s" is a largefile standin') % f, |
|
317 | _('file "%s" is a largefile standin') % f, | |
314 | hint=('commit the largefile itself instead')) |
|
318 | hint=('commit the largefile itself instead')) | |
315 | # Scan directories |
|
319 | # Scan directories | |
316 | if self.wvfs.isdir(f): |
|
320 | if self.wvfs.isdir(f): | |
317 | dirs.append(f) |
|
321 | dirs.append(f) | |
318 | else: |
|
322 | else: | |
319 | regulars.append(f) |
|
323 | regulars.append(f) | |
320 |
|
324 | |||
321 | for f in dirs: |
|
325 | for f in dirs: | |
322 | matcheddir = False |
|
326 | matcheddir = False | |
323 | d = self.dirstate.normalize(f) + '/' |
|
327 | d = self.dirstate.normalize(f) + '/' | |
324 | # Check for matched normal files |
|
328 | # Check for matched normal files | |
325 | for mf in regulars: |
|
329 | for mf in regulars: | |
326 | if self.dirstate.normalize(mf).startswith(d): |
|
330 | if self.dirstate.normalize(mf).startswith(d): | |
327 | actualfiles.append(f) |
|
331 | actualfiles.append(f) | |
328 | matcheddir = True |
|
332 | matcheddir = True | |
329 | break |
|
333 | break | |
330 | if not matcheddir: |
|
334 | if not matcheddir: | |
331 | # If no normal match, manually append |
|
335 | # If no normal match, manually append | |
332 | # any matching largefiles |
|
336 | # any matching largefiles | |
333 | for lf in lfiles: |
|
337 | for lf in lfiles: | |
334 | if self.dirstate.normalize(lf).startswith(d): |
|
338 | if self.dirstate.normalize(lf).startswith(d): | |
335 | actualfiles.append(lf) |
|
339 | actualfiles.append(lf) | |
336 | if not matcheddir: |
|
340 | if not matcheddir: | |
337 | # There may still be normal files in the dir, so |
|
341 | # There may still be normal files in the dir, so | |
338 | # add a directory to the list, which |
|
342 | # add a directory to the list, which | |
339 | # forces status/dirstate to walk all files and |
|
343 | # forces status/dirstate to walk all files and | |
340 | # call the match function on the matcher, even |
|
344 | # call the match function on the matcher, even | |
341 | # on case sensitive filesystems. |
|
345 | # on case sensitive filesystems. | |
342 | actualfiles.append('.') |
|
346 | actualfiles.append('.') | |
343 | matcheddir = True |
|
347 | matcheddir = True | |
344 | # Nothing in dir, so readd it |
|
348 | # Nothing in dir, so readd it | |
345 | # and let commit reject it |
|
349 | # and let commit reject it | |
346 | if not matcheddir: |
|
350 | if not matcheddir: | |
347 | actualfiles.append(f) |
|
351 | actualfiles.append(f) | |
348 |
|
352 | |||
349 | # Always add normal files |
|
353 | # Always add normal files | |
350 | actualfiles += regulars |
|
354 | actualfiles += regulars | |
351 | return actualfiles |
|
355 | return actualfiles | |
352 |
|
356 | |||
353 | repo.__class__ = lfilesrepo |
|
357 | repo.__class__ = lfilesrepo | |
354 |
|
358 | |||
355 | # stack of hooks being executed before committing. |
|
359 | # stack of hooks being executed before committing. | |
356 | # only last element ("_lfcommithooks[-1]") is used for each committing. |
|
360 | # only last element ("_lfcommithooks[-1]") is used for each committing. | |
357 | repo._lfcommithooks = [lfutil.updatestandinsbymatch] |
|
361 | repo._lfcommithooks = [lfutil.updatestandinsbymatch] | |
358 |
|
362 | |||
359 | # Stack of status writer functions taking "*msg, **opts" arguments |
|
363 | # Stack of status writer functions taking "*msg, **opts" arguments | |
360 | # like "ui.status()". Only last element ("_lfstatuswriters[-1]") |
|
364 | # like "ui.status()". Only last element ("_lfstatuswriters[-1]") | |
361 | # is used to write status out. |
|
365 | # is used to write status out. | |
362 | repo._lfstatuswriters = [ui.status] |
|
366 | repo._lfstatuswriters = [ui.status] | |
363 |
|
367 | |||
364 | def prepushoutgoinghook(pushop): |
|
368 | def prepushoutgoinghook(pushop): | |
365 | """Push largefiles for pushop before pushing revisions.""" |
|
369 | """Push largefiles for pushop before pushing revisions.""" | |
366 | lfrevs = pushop.lfrevs |
|
370 | lfrevs = pushop.lfrevs | |
367 | if lfrevs is None: |
|
371 | if lfrevs is None: | |
368 | lfrevs = pushop.outgoing.missing |
|
372 | lfrevs = pushop.outgoing.missing | |
369 | if lfrevs: |
|
373 | if lfrevs: | |
370 | toupload = set() |
|
374 | toupload = set() | |
371 | addfunc = lambda fn, lfhash: toupload.add(lfhash) |
|
375 | addfunc = lambda fn, lfhash: toupload.add(lfhash) | |
372 | lfutil.getlfilestoupload(pushop.repo, lfrevs, |
|
376 | lfutil.getlfilestoupload(pushop.repo, lfrevs, | |
373 | addfunc) |
|
377 | addfunc) | |
374 | lfcommands.uploadlfiles(ui, pushop.repo, pushop.remote, toupload) |
|
378 | lfcommands.uploadlfiles(ui, pushop.repo, pushop.remote, toupload) | |
375 | repo.prepushoutgoinghooks.add("largefiles", prepushoutgoinghook) |
|
379 | repo.prepushoutgoinghooks.add("largefiles", prepushoutgoinghook) | |
376 |
|
380 | |||
377 | def checkrequireslfiles(ui, repo, **kwargs): |
|
381 | def checkrequireslfiles(ui, repo, **kwargs): | |
378 | if 'largefiles' not in repo.requirements and any( |
|
382 | if 'largefiles' not in repo.requirements and any( | |
379 | lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()): |
|
383 | lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()): | |
380 | repo.requirements.add('largefiles') |
|
384 | repo.requirements.add('largefiles') | |
381 | repo._writerequirements() |
|
385 | repo._writerequirements() | |
382 |
|
386 | |||
383 | ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles, |
|
387 | ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles, | |
384 | 'largefiles') |
|
388 | 'largefiles') | |
385 | ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles, 'largefiles') |
|
389 | ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles, 'largefiles') |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: modified file |
|
NO CONTENT: modified file | ||
The requested commit or file is too big and content was truncated. Show full diff |
General Comments 0
You need to be logged in to leave comments.
Login now