##// END OF EJS Templates
merge with stable
Matt Mackall -
r23426:19ebd2f8 merge default
parent child Browse files
Show More

The requested changes are too big and content was truncated. Show full diff

1 NO CONTENT: new file 100644
NO CONTENT: new file 100644
The requested commit or file is too big and content was truncated. Show full diff
@@ -1,99 +1,100
1 35fb62a3a673d5322f6274a44ba6456e5e4b3b37 0 iD8DBQBEYmO2ywK+sNU5EO8RAnaYAKCO7x15xUn5mnhqWNXqk/ehlhRt2QCfRDfY0LrUq2q4oK/KypuJYPHgq1A=
1 35fb62a3a673d5322f6274a44ba6456e5e4b3b37 0 iD8DBQBEYmO2ywK+sNU5EO8RAnaYAKCO7x15xUn5mnhqWNXqk/ehlhRt2QCfRDfY0LrUq2q4oK/KypuJYPHgq1A=
2 2be3001847cb18a23c403439d9e7d0ace30804e9 0 iD8DBQBExUbjywK+sNU5EO8RAhzxAKCtyHAQUzcTSZTqlfJ0by6vhREwWQCghaQFHfkfN0l9/40EowNhuMOKnJk=
2 2be3001847cb18a23c403439d9e7d0ace30804e9 0 iD8DBQBExUbjywK+sNU5EO8RAhzxAKCtyHAQUzcTSZTqlfJ0by6vhREwWQCghaQFHfkfN0l9/40EowNhuMOKnJk=
3 36a957364b1b89c150f2d0e60a99befe0ee08bd3 0 iD8DBQBFfL2QywK+sNU5EO8RAjYFAKCoGlaWRTeMsjdmxAjUYx6diZxOBwCfY6IpBYsKvPTwB3oktnPt5Rmrlys=
3 36a957364b1b89c150f2d0e60a99befe0ee08bd3 0 iD8DBQBFfL2QywK+sNU5EO8RAjYFAKCoGlaWRTeMsjdmxAjUYx6diZxOBwCfY6IpBYsKvPTwB3oktnPt5Rmrlys=
4 27230c29bfec36d5540fbe1c976810aefecfd1d2 0 iD8DBQBFheweywK+sNU5EO8RAt7VAKCrqJQWT2/uo2RWf0ZI4bLp6v82jACgjrMdsaTbxRsypcmEsdPhlG6/8F4=
4 27230c29bfec36d5540fbe1c976810aefecfd1d2 0 iD8DBQBFheweywK+sNU5EO8RAt7VAKCrqJQWT2/uo2RWf0ZI4bLp6v82jACgjrMdsaTbxRsypcmEsdPhlG6/8F4=
5 fb4b6d5fe100b0886f8bc3d6731ec0e5ed5c4694 0 iD8DBQBGgHicywK+sNU5EO8RAgNxAJ0VG8ixAaeudx4sZbhngI1syu49HQCeNUJQfWBgA8bkJ2pvsFpNxwYaX3I=
5 fb4b6d5fe100b0886f8bc3d6731ec0e5ed5c4694 0 iD8DBQBGgHicywK+sNU5EO8RAgNxAJ0VG8ixAaeudx4sZbhngI1syu49HQCeNUJQfWBgA8bkJ2pvsFpNxwYaX3I=
6 23889160905a1b09fffe1c07378e9fc1827606eb 0 iD8DBQBHGTzoywK+sNU5EO8RAr/UAJ0Y8s4jQtzgS+G9vM8z6CWBThZ8fwCcCT5XDj2XwxKkz/0s6UELwjsO3LU=
6 23889160905a1b09fffe1c07378e9fc1827606eb 0 iD8DBQBHGTzoywK+sNU5EO8RAr/UAJ0Y8s4jQtzgS+G9vM8z6CWBThZ8fwCcCT5XDj2XwxKkz/0s6UELwjsO3LU=
7 bae2e9c838e90a393bae3973a7850280413e091a 0 iD8DBQBH6DO5ywK+sNU5EO8RAsfrAJ0e4r9c9GF/MJsM7Xjd3NesLRC3+ACffj6+6HXdZf8cswAoFPO+DY00oD0=
7 bae2e9c838e90a393bae3973a7850280413e091a 0 iD8DBQBH6DO5ywK+sNU5EO8RAsfrAJ0e4r9c9GF/MJsM7Xjd3NesLRC3+ACffj6+6HXdZf8cswAoFPO+DY00oD0=
8 d5cbbe2c49cee22a9fbeb9ea41daa0ac4e26b846 0 iD8DBQBINdwsywK+sNU5EO8RAjIUAKCPmlFJSpsPAAUKF+iNHAwVnwmzeQCdEXrL27CWclXuUKdbQC8De7LICtE=
8 d5cbbe2c49cee22a9fbeb9ea41daa0ac4e26b846 0 iD8DBQBINdwsywK+sNU5EO8RAjIUAKCPmlFJSpsPAAUKF+iNHAwVnwmzeQCdEXrL27CWclXuUKdbQC8De7LICtE=
9 d2375bbee6d47e62ba8e415c86e83a465dc4dce9 0 iD8DBQBIo1wpywK+sNU5EO8RAmRNAJ94x3OFt6blbqu/yBoypm/AJ44fuACfUaldXcV5z9tht97hSp22DVTEPGc=
9 d2375bbee6d47e62ba8e415c86e83a465dc4dce9 0 iD8DBQBIo1wpywK+sNU5EO8RAmRNAJ94x3OFt6blbqu/yBoypm/AJ44fuACfUaldXcV5z9tht97hSp22DVTEPGc=
10 2a67430f92f15ea5159c26b09ec4839a0c549a26 0 iEYEABECAAYFAkk1hykACgkQywK+sNU5EO85QACeNJNUanjc2tl4wUoPHNuv+lSj0ZMAoIm93wSTc/feyYnO2YCaQ1iyd9Nu
10 2a67430f92f15ea5159c26b09ec4839a0c549a26 0 iEYEABECAAYFAkk1hykACgkQywK+sNU5EO85QACeNJNUanjc2tl4wUoPHNuv+lSj0ZMAoIm93wSTc/feyYnO2YCaQ1iyd9Nu
11 3773e510d433969e277b1863c317b674cbee2065 0 iEYEABECAAYFAklNbbAACgkQywK+sNU5EO8o+gCfeb2/lfIJZMvyDA1m+G1CsBAxfFsAoIa6iAMG8SBY7hW1Q85Yf/LXEvaE
11 3773e510d433969e277b1863c317b674cbee2065 0 iEYEABECAAYFAklNbbAACgkQywK+sNU5EO8o+gCfeb2/lfIJZMvyDA1m+G1CsBAxfFsAoIa6iAMG8SBY7hW1Q85Yf/LXEvaE
12 11a4eb81fb4f4742451591489e2797dc47903277 0 iEYEABECAAYFAklcAnsACgkQywK+sNU5EO+uXwCbBVHNNsLy1g7BlAyQJwadYVyHOXoAoKvtAVO71+bv7EbVoukwTzT+P4Sx
12 11a4eb81fb4f4742451591489e2797dc47903277 0 iEYEABECAAYFAklcAnsACgkQywK+sNU5EO+uXwCbBVHNNsLy1g7BlAyQJwadYVyHOXoAoKvtAVO71+bv7EbVoukwTzT+P4Sx
13 11efa41037e280d08cfb07c09ad485df30fb0ea8 0 iEYEABECAAYFAkmvJRQACgkQywK+sNU5EO9XZwCeLMgDgPSMWMm6vgjL4lDs2pEc5+0AnRxfiFbpbBfuEFTqKz9nbzeyoBlx
13 11efa41037e280d08cfb07c09ad485df30fb0ea8 0 iEYEABECAAYFAkmvJRQACgkQywK+sNU5EO9XZwCeLMgDgPSMWMm6vgjL4lDs2pEc5+0AnRxfiFbpbBfuEFTqKz9nbzeyoBlx
14 02981000012e3adf40c4849bd7b3d5618f9ce82d 0 iEYEABECAAYFAknEH3wACgkQywK+sNU5EO+uXwCeI+LbLMmhjU1lKSfU3UWJHjjUC7oAoIZLvYDGOL/tNZFUuatc3RnZ2eje
14 02981000012e3adf40c4849bd7b3d5618f9ce82d 0 iEYEABECAAYFAknEH3wACgkQywK+sNU5EO+uXwCeI+LbLMmhjU1lKSfU3UWJHjjUC7oAoIZLvYDGOL/tNZFUuatc3RnZ2eje
15 196d40e7c885fa6e95f89134809b3ec7bdbca34b 0 iEYEABECAAYFAkpL2X4ACgkQywK+sNU5EO9FOwCfXJycjyKJXsvQqKkHrglwOQhEKS4An36GfKzptfN8b1qNc3+ya/5c2WOM
15 196d40e7c885fa6e95f89134809b3ec7bdbca34b 0 iEYEABECAAYFAkpL2X4ACgkQywK+sNU5EO9FOwCfXJycjyKJXsvQqKkHrglwOQhEKS4An36GfKzptfN8b1qNc3+ya/5c2WOM
16 3ef6c14a1e8e83a31226f5881b7fe6095bbfa6f6 0 iEYEABECAAYFAkpopLIACgkQywK+sNU5EO8QSgCfZ0ztsd071rOa2lhmp9Fyue/WoI0AoLTei80/xrhRlB8L/rZEf2KBl8dA
16 3ef6c14a1e8e83a31226f5881b7fe6095bbfa6f6 0 iEYEABECAAYFAkpopLIACgkQywK+sNU5EO8QSgCfZ0ztsd071rOa2lhmp9Fyue/WoI0AoLTei80/xrhRlB8L/rZEf2KBl8dA
17 31ec469f9b556f11819937cf68ee53f2be927ebf 0 iEYEABECAAYFAksBuxAACgkQywK+sNU5EO+mBwCfagB+A0txzWZ6dRpug3LEoK7Z1QsAoKpbk8vsLjv6/oRDicSk/qBu33+m
17 31ec469f9b556f11819937cf68ee53f2be927ebf 0 iEYEABECAAYFAksBuxAACgkQywK+sNU5EO+mBwCfagB+A0txzWZ6dRpug3LEoK7Z1QsAoKpbk8vsLjv6/oRDicSk/qBu33+m
18 439d7ea6fe3aa4ab9ec274a68846779153789de9 0 iEYEABECAAYFAksVw0kACgkQywK+sNU5EO/oZwCfdfBEkgp38xq6wN2F4nj+SzofrJIAnjmxt04vaJSeOOeHylHvk6lzuQsw
18 439d7ea6fe3aa4ab9ec274a68846779153789de9 0 iEYEABECAAYFAksVw0kACgkQywK+sNU5EO/oZwCfdfBEkgp38xq6wN2F4nj+SzofrJIAnjmxt04vaJSeOOeHylHvk6lzuQsw
19 296a0b14a68621f6990c54fdba0083f6f20935bf 0 iEYEABECAAYFAks+jCoACgkQywK+sNU5EO9J8wCeMUGF9E/gS2UBsqIz56WS4HMPRPUAoI5J95mwEIK8Clrl7qFRidNI6APq
19 296a0b14a68621f6990c54fdba0083f6f20935bf 0 iEYEABECAAYFAks+jCoACgkQywK+sNU5EO9J8wCeMUGF9E/gS2UBsqIz56WS4HMPRPUAoI5J95mwEIK8Clrl7qFRidNI6APq
20 4aa619c4c2c09907034d9824ebb1dd0e878206eb 0 iEYEABECAAYFAktm9IsACgkQywK+sNU5EO9XGgCgk4HclRQhexEtooPE5GcUCdB6M8EAn2ptOhMVbIoO+JncA+tNACPFXh0O
20 4aa619c4c2c09907034d9824ebb1dd0e878206eb 0 iEYEABECAAYFAktm9IsACgkQywK+sNU5EO9XGgCgk4HclRQhexEtooPE5GcUCdB6M8EAn2ptOhMVbIoO+JncA+tNACPFXh0O
21 ff2704a8ded37fbebd8b6eb5ec733731d725da8a 0 iEYEABECAAYFAkuRoSQACgkQywK+sNU5EO//3QCeJDc5r2uFyFCtAlpSA27DEE5rrxAAn2FSwTy9fhrB3QAdDQlwkEZcQzDh
21 ff2704a8ded37fbebd8b6eb5ec733731d725da8a 0 iEYEABECAAYFAkuRoSQACgkQywK+sNU5EO//3QCeJDc5r2uFyFCtAlpSA27DEE5rrxAAn2FSwTy9fhrB3QAdDQlwkEZcQzDh
22 2b01dab594167bc0dd33331dbaa6dca3dca1b3aa 0 iEYEABECAAYFAku1IwIACgkQywK+sNU5EO9MjgCdHLVwkTZlNHxhcznZKBL1rjN+J7cAoLLWi9LTL6f/TgBaPSKOy1ublbaW
22 2b01dab594167bc0dd33331dbaa6dca3dca1b3aa 0 iEYEABECAAYFAku1IwIACgkQywK+sNU5EO9MjgCdHLVwkTZlNHxhcznZKBL1rjN+J7cAoLLWi9LTL6f/TgBaPSKOy1ublbaW
23 39f725929f0c48c5fb3b90c071fc3066012456ca 0 iEYEABECAAYFAkvclvsACgkQywK+sNU5EO9FSwCeL9i5x8ALW/LE5+lCX6MFEAe4MhwAn1ev5o6SX6GrNdDfKweiemfO2VBk
23 39f725929f0c48c5fb3b90c071fc3066012456ca 0 iEYEABECAAYFAkvclvsACgkQywK+sNU5EO9FSwCeL9i5x8ALW/LE5+lCX6MFEAe4MhwAn1ev5o6SX6GrNdDfKweiemfO2VBk
24 fdcf80f26604f233dc4d8f0a5ef9d7470e317e8a 0 iEYEABECAAYFAkvsKTkACgkQywK+sNU5EO9qEACgiSiRGvTG2vXGJ65tUSOIYihTuFAAnRzRIqEVSw8M8/RGeUXRps0IzaCO
24 fdcf80f26604f233dc4d8f0a5ef9d7470e317e8a 0 iEYEABECAAYFAkvsKTkACgkQywK+sNU5EO9qEACgiSiRGvTG2vXGJ65tUSOIYihTuFAAnRzRIqEVSw8M8/RGeUXRps0IzaCO
25 24fe2629c6fd0c74c90bd066e77387c2b02e8437 0 iEYEABECAAYFAkwFLRsACgkQywK+sNU5EO+pJACgp13tPI+pbwKZV+LeMjcQ4H6tCZYAoJebzhd6a8yYx6qiwpJxA9BXZNXy
25 24fe2629c6fd0c74c90bd066e77387c2b02e8437 0 iEYEABECAAYFAkwFLRsACgkQywK+sNU5EO+pJACgp13tPI+pbwKZV+LeMjcQ4H6tCZYAoJebzhd6a8yYx6qiwpJxA9BXZNXy
26 f786fc4b8764cd2a5526d259cf2f94d8a66924d9 0 iEYEABECAAYFAkwsyxcACgkQywK+sNU5EO+crACfUpNAF57PmClkSri9nJcBjb2goN4AniPCNaKvnki7TnUsi1u2oxltpKKL
26 f786fc4b8764cd2a5526d259cf2f94d8a66924d9 0 iEYEABECAAYFAkwsyxcACgkQywK+sNU5EO+crACfUpNAF57PmClkSri9nJcBjb2goN4AniPCNaKvnki7TnUsi1u2oxltpKKL
27 bf1774d95bde614af3956d92b20e2a0c68c5fec7 0 iEYEABECAAYFAkxVwccACgkQywK+sNU5EO+oFQCeJzwZ+we1fIIyBGCddHceOUAN++cAnjvT6A8ZWW0zV21NXIFF1qQmjxJd
27 bf1774d95bde614af3956d92b20e2a0c68c5fec7 0 iEYEABECAAYFAkxVwccACgkQywK+sNU5EO+oFQCeJzwZ+we1fIIyBGCddHceOUAN++cAnjvT6A8ZWW0zV21NXIFF1qQmjxJd
28 c00f03a4982e467fb6b6bd45908767db6df4771d 0 iEYEABECAAYFAkxXDqsACgkQywK+sNU5EO/GJACfT9Rz4hZOxPQEs91JwtmfjevO84gAmwSmtfo5mmWSm8gtTUebCcdTv0Kf
28 c00f03a4982e467fb6b6bd45908767db6df4771d 0 iEYEABECAAYFAkxXDqsACgkQywK+sNU5EO/GJACfT9Rz4hZOxPQEs91JwtmfjevO84gAmwSmtfo5mmWSm8gtTUebCcdTv0Kf
29 ff5cec76b1c5b6be9c3bb923aae8c3c6d079d6b9 0 iD8DBQBMdo+qywK+sNU5EO8RAqQpAJ975BL2CCAiWMz9SXthNQ9xG181IwCgp4O+KViHPkufZVFn2aTKMNvcr1A=
29 ff5cec76b1c5b6be9c3bb923aae8c3c6d079d6b9 0 iD8DBQBMdo+qywK+sNU5EO8RAqQpAJ975BL2CCAiWMz9SXthNQ9xG181IwCgp4O+KViHPkufZVFn2aTKMNvcr1A=
30 93d8bff78c96fe7e33237b257558ee97290048a4 0 iD8DBQBMpfvdywK+sNU5EO8RAsxVAJ0UaL1XB51C76JUBhafc9GBefuMxwCdEWkTOzwvE0SarJBe9i008jhbqW4=
30 93d8bff78c96fe7e33237b257558ee97290048a4 0 iD8DBQBMpfvdywK+sNU5EO8RAsxVAJ0UaL1XB51C76JUBhafc9GBefuMxwCdEWkTOzwvE0SarJBe9i008jhbqW4=
31 333421b9e0f96c7bc788e5667c146a58a9440a55 0 iD8DBQBMz0HOywK+sNU5EO8RAlsEAJ0USh6yOG7OrWkADGunVt9QimBQnwCbBqeMnKgSbwEw8jZwE3Iz1mdrYlo=
31 333421b9e0f96c7bc788e5667c146a58a9440a55 0 iD8DBQBMz0HOywK+sNU5EO8RAlsEAJ0USh6yOG7OrWkADGunVt9QimBQnwCbBqeMnKgSbwEw8jZwE3Iz1mdrYlo=
32 4438875ec01bd0fc32be92b0872eb6daeed4d44f 0 iD8DBQBM4WYUywK+sNU5EO8RAhCVAJ0dJswachwFAHALmk1x0RJehxzqPQCbBNskP9n/X689jB+btNTZTyKU/fw=
32 4438875ec01bd0fc32be92b0872eb6daeed4d44f 0 iD8DBQBM4WYUywK+sNU5EO8RAhCVAJ0dJswachwFAHALmk1x0RJehxzqPQCbBNskP9n/X689jB+btNTZTyKU/fw=
33 6aff4f144ad356311318b0011df0bb21f2c97429 0 iD8DBQBM9uxXywK+sNU5EO8RAv+4AKCDj4qKP16GdPaq1tP6BUwpM/M1OACfRyzLPp/qiiN8xJTWoWYSe/XjJug=
33 6aff4f144ad356311318b0011df0bb21f2c97429 0 iD8DBQBM9uxXywK+sNU5EO8RAv+4AKCDj4qKP16GdPaq1tP6BUwpM/M1OACfRyzLPp/qiiN8xJTWoWYSe/XjJug=
34 e3bf16703e2601de99e563cdb3a5d50b64e6d320 0 iD8DBQBNH8WqywK+sNU5EO8RAiQTAJ9sBO+TeiGro4si77VVaQaA6jcRUgCfSA28dBbjj0oFoQwvPoZjANiZBH8=
34 e3bf16703e2601de99e563cdb3a5d50b64e6d320 0 iD8DBQBNH8WqywK+sNU5EO8RAiQTAJ9sBO+TeiGro4si77VVaQaA6jcRUgCfSA28dBbjj0oFoQwvPoZjANiZBH8=
35 a6c855c32ea081da3c3b8ff628f1847ff271482f 0 iD8DBQBNSJJ+ywK+sNU5EO8RAoJaAKCweDEF70fu+r1Zn7pYDXdlk5RuSgCeO9gK/eit8Lin/1n3pO7aYguFLok=
35 a6c855c32ea081da3c3b8ff628f1847ff271482f 0 iD8DBQBNSJJ+ywK+sNU5EO8RAoJaAKCweDEF70fu+r1Zn7pYDXdlk5RuSgCeO9gK/eit8Lin/1n3pO7aYguFLok=
36 2b2155623ee2559caf288fd333f30475966c4525 0 iD8DBQBNSJeBywK+sNU5EO8RAm1KAJ4hW9Cm9nHaaGJguchBaPLlAr+O3wCgqgmMok8bdAS06N6PL60PSTM//Gg=
36 2b2155623ee2559caf288fd333f30475966c4525 0 iD8DBQBNSJeBywK+sNU5EO8RAm1KAJ4hW9Cm9nHaaGJguchBaPLlAr+O3wCgqgmMok8bdAS06N6PL60PSTM//Gg=
37 2616325766e3504c8ae7c84bd15ee610901fe91d 0 iD8DBQBNbWy9ywK+sNU5EO8RAlWCAJ4mW8HbzjJj9GpK98muX7k+7EvEHwCfaTLbC/DH3QEsZBhEP+M8tzL6RU4=
37 2616325766e3504c8ae7c84bd15ee610901fe91d 0 iD8DBQBNbWy9ywK+sNU5EO8RAlWCAJ4mW8HbzjJj9GpK98muX7k+7EvEHwCfaTLbC/DH3QEsZBhEP+M8tzL6RU4=
38 aa1f3be38ab127280761889d2dca906ca465b5f4 0 iD8DBQBNeQq7ywK+sNU5EO8RAlEOAJ4tlEDdetE9lKfjGgjbkcR8PrC3egCfXCfF3qNVvU/2YYjpgvRwevjvDy0=
38 aa1f3be38ab127280761889d2dca906ca465b5f4 0 iD8DBQBNeQq7ywK+sNU5EO8RAlEOAJ4tlEDdetE9lKfjGgjbkcR8PrC3egCfXCfF3qNVvU/2YYjpgvRwevjvDy0=
39 b032bec2c0a651ca0ddecb65714bfe6770f67d70 0 iD8DBQBNlg5kywK+sNU5EO8RAnGEAJ9gmEx6MfaR4XcG2m/93vwtfyzs3gCgltzx8/YdHPwqDwRX/WbpYgi33is=
39 b032bec2c0a651ca0ddecb65714bfe6770f67d70 0 iD8DBQBNlg5kywK+sNU5EO8RAnGEAJ9gmEx6MfaR4XcG2m/93vwtfyzs3gCgltzx8/YdHPwqDwRX/WbpYgi33is=
40 3cb1e95676ad089596bd81d0937cad37d6e3b7fb 0 iD8DBQBNvTy4ywK+sNU5EO8RAmp8AJ9QnxK4jTJ7G722MyeBxf0UXEdGwACgtlM7BKtNQfbEH/fOW5y+45W88VI=
40 3cb1e95676ad089596bd81d0937cad37d6e3b7fb 0 iD8DBQBNvTy4ywK+sNU5EO8RAmp8AJ9QnxK4jTJ7G722MyeBxf0UXEdGwACgtlM7BKtNQfbEH/fOW5y+45W88VI=
41 733af5d9f6b22387913e1d11350fb8cb7c1487dd 0 iD8DBQBN5q/8ywK+sNU5EO8RArRGAKCNGT94GKIYtSuwZ57z1sQbcw6uLACfffpbMV4NAPMl8womAwg+7ZPKnIU=
41 733af5d9f6b22387913e1d11350fb8cb7c1487dd 0 iD8DBQBN5q/8ywK+sNU5EO8RArRGAKCNGT94GKIYtSuwZ57z1sQbcw6uLACfffpbMV4NAPMl8womAwg+7ZPKnIU=
42 de9eb6b1da4fc522b1cab16d86ca166204c24f25 0 iD8DBQBODhfhywK+sNU5EO8RAr2+AJ4ugbAj8ae8/K0bYZzx3sascIAg1QCeK3b+zbbVVqd3b7CDpwFnaX8kTd4=
42 de9eb6b1da4fc522b1cab16d86ca166204c24f25 0 iD8DBQBODhfhywK+sNU5EO8RAr2+AJ4ugbAj8ae8/K0bYZzx3sascIAg1QCeK3b+zbbVVqd3b7CDpwFnaX8kTd4=
43 4a43e23b8c55b4566b8200bf69fe2158485a2634 0 iD8DBQBONzIMywK+sNU5EO8RAj5SAJ0aPS3+JHnyI6bHB2Fl0LImbDmagwCdGbDLp1S7TFobxXudOH49bX45Iik=
43 4a43e23b8c55b4566b8200bf69fe2158485a2634 0 iD8DBQBONzIMywK+sNU5EO8RAj5SAJ0aPS3+JHnyI6bHB2Fl0LImbDmagwCdGbDLp1S7TFobxXudOH49bX45Iik=
44 d629f1e89021103f1753addcef6b310e4435b184 0 iD8DBQBOWAsBywK+sNU5EO8RAht4AJwJl9oNFopuGkj5m8aKuf7bqPkoAQCeNrEm7UhFsZKYT5iUOjnMV7s2LaM=
44 d629f1e89021103f1753addcef6b310e4435b184 0 iD8DBQBOWAsBywK+sNU5EO8RAht4AJwJl9oNFopuGkj5m8aKuf7bqPkoAQCeNrEm7UhFsZKYT5iUOjnMV7s2LaM=
45 351a9292e430e35766c552066ed3e87c557b803b 0 iD8DBQBOh3zUywK+sNU5EO8RApFMAKCD3Y/u3avDFndznwqfG5UeTHMlvACfUivPIVQZyDZnhZMq0UhC6zhCEQg=
45 351a9292e430e35766c552066ed3e87c557b803b 0 iD8DBQBOh3zUywK+sNU5EO8RApFMAKCD3Y/u3avDFndznwqfG5UeTHMlvACfUivPIVQZyDZnhZMq0UhC6zhCEQg=
46 384082750f2c51dc917d85a7145748330fa6ef4d 0 iD8DBQBOmd+OywK+sNU5EO8RAgDgAJ9V/X+G7VLwhTpHrZNiOHabzSyzYQCdE2kKfIevJUYB9QLAWCWP6DPwrwI=
46 384082750f2c51dc917d85a7145748330fa6ef4d 0 iD8DBQBOmd+OywK+sNU5EO8RAgDgAJ9V/X+G7VLwhTpHrZNiOHabzSyzYQCdE2kKfIevJUYB9QLAWCWP6DPwrwI=
47 41453d55b481ddfcc1dacb445179649e24ca861d 0 iD8DBQBOsFhpywK+sNU5EO8RAqM6AKCyfxUae3/zLuiLdQz+JR78690eMACfQ6JTBQib4AbE+rUDdkeFYg9K/+4=
47 41453d55b481ddfcc1dacb445179649e24ca861d 0 iD8DBQBOsFhpywK+sNU5EO8RAqM6AKCyfxUae3/zLuiLdQz+JR78690eMACfQ6JTBQib4AbE+rUDdkeFYg9K/+4=
48 195dbd1cef0c2f9f8bcf4ea303238105f716bda3 0 iD8DBQBO1/fWywK+sNU5EO8RAmoPAKCR5lpv1D6JLURHD8KVLSV4GRVEBgCgnd0Sy78ligNfqAMafmACRDvj7vo=
48 195dbd1cef0c2f9f8bcf4ea303238105f716bda3 0 iD8DBQBO1/fWywK+sNU5EO8RAmoPAKCR5lpv1D6JLURHD8KVLSV4GRVEBgCgnd0Sy78ligNfqAMafmACRDvj7vo=
49 6344043924497cd06d781d9014c66802285072e4 0 iD8DBQBPALgmywK+sNU5EO8RAlfhAJ9nYOdWnhfVDHYtDTJAyJtXBAQS9wCgnefoSQt7QABkbGxM+Q85UYEBuD0=
49 6344043924497cd06d781d9014c66802285072e4 0 iD8DBQBPALgmywK+sNU5EO8RAlfhAJ9nYOdWnhfVDHYtDTJAyJtXBAQS9wCgnefoSQt7QABkbGxM+Q85UYEBuD0=
50 db33555eafeaf9df1e18950e29439eaa706d399b 0 iD8DBQBPGdzxywK+sNU5EO8RAppkAJ9jOXhUVE/97CPgiMA0pMGiIYnesQCfengAszcBiSiKGugiI8Okc9ghU+Y=
50 db33555eafeaf9df1e18950e29439eaa706d399b 0 iD8DBQBPGdzxywK+sNU5EO8RAppkAJ9jOXhUVE/97CPgiMA0pMGiIYnesQCfengAszcBiSiKGugiI8Okc9ghU+Y=
51 2aa5b51f310fb3befd26bed99c02267f5c12c734 0 iD8DBQBPKZ9bywK+sNU5EO8RAt1TAJ45r1eJ0YqSkInzrrayg4TVCh0SnQCgm0GA/Ua74jnnDwVQ60lAwROuz1Q=
51 2aa5b51f310fb3befd26bed99c02267f5c12c734 0 iD8DBQBPKZ9bywK+sNU5EO8RAt1TAJ45r1eJ0YqSkInzrrayg4TVCh0SnQCgm0GA/Ua74jnnDwVQ60lAwROuz1Q=
52 53e2cd303ecf8ca7c7eeebd785c34e5ed6b0f4a4 0 iD8DBQBPT/fvywK+sNU5EO8RAnfYAKCn7d0vwqIb100YfWm1F7nFD5B+FACeM02YHpQLSNsztrBCObtqcnfod7Q=
52 53e2cd303ecf8ca7c7eeebd785c34e5ed6b0f4a4 0 iD8DBQBPT/fvywK+sNU5EO8RAnfYAKCn7d0vwqIb100YfWm1F7nFD5B+FACeM02YHpQLSNsztrBCObtqcnfod7Q=
53 b9bd95e61b49c221c4cca24e6da7c946fc02f992 0 iD8DBQBPeLsIywK+sNU5EO8RAvpNAKCtKe2gitz8dYn52IRF0hFOPCR7AQCfRJL/RWCFweu2T1vH/mUOCf8SXXc=
53 b9bd95e61b49c221c4cca24e6da7c946fc02f992 0 iD8DBQBPeLsIywK+sNU5EO8RAvpNAKCtKe2gitz8dYn52IRF0hFOPCR7AQCfRJL/RWCFweu2T1vH/mUOCf8SXXc=
54 d9e2f09d5488c395ae9ddbb320ceacd24757e055 0 iD8DBQBPju/dywK+sNU5EO8RArBYAJ9xtifdbk+hCOJO8OZa4JfHX8OYZQCeKPMBaBWiT8N/WHoOm1XU0q+iono=
54 d9e2f09d5488c395ae9ddbb320ceacd24757e055 0 iD8DBQBPju/dywK+sNU5EO8RArBYAJ9xtifdbk+hCOJO8OZa4JfHX8OYZQCeKPMBaBWiT8N/WHoOm1XU0q+iono=
55 00182b3d087909e3c3ae44761efecdde8f319ef3 0 iD8DBQBPoFhIywK+sNU5EO8RAhzhAKCBj1n2jxPTkZNJJ5pSp3soa+XHIgCgsZZpAQxOpXwCp0eCdNGe0+pmxmg=
55 00182b3d087909e3c3ae44761efecdde8f319ef3 0 iD8DBQBPoFhIywK+sNU5EO8RAhzhAKCBj1n2jxPTkZNJJ5pSp3soa+XHIgCgsZZpAQxOpXwCp0eCdNGe0+pmxmg=
56 5983de86462c5a9f42a3ad0f5e90ce5b1d221d25 0 iD8DBQBPovNWywK+sNU5EO8RAhgiAJ980T91FdPTRMmVONDhpkMsZwVIMACgg3bKvoWSeuCW28llUhAJtUjrMv0=
56 5983de86462c5a9f42a3ad0f5e90ce5b1d221d25 0 iD8DBQBPovNWywK+sNU5EO8RAhgiAJ980T91FdPTRMmVONDhpkMsZwVIMACgg3bKvoWSeuCW28llUhAJtUjrMv0=
57 85a358df5bbbe404ca25730c9c459b34263441dc 0 iD8DBQBPyZsWywK+sNU5EO8RAnpLAJ48qrGDJRT+pteS0mSQ11haqHstPwCdG4ccGbk+0JHb7aNy8/NRGAOqn9w=
57 85a358df5bbbe404ca25730c9c459b34263441dc 0 iD8DBQBPyZsWywK+sNU5EO8RAnpLAJ48qrGDJRT+pteS0mSQ11haqHstPwCdG4ccGbk+0JHb7aNy8/NRGAOqn9w=
58 b013baa3898e117959984fc64c29d8c784d2f28b 0 iD8DBQBP8QOPywK+sNU5EO8RAqimAKCFRSx0lvG6y8vne2IhNG062Hn0dACeMLI5/zhpWpHBIVeAAquYfx2XFeA=
58 b013baa3898e117959984fc64c29d8c784d2f28b 0 iD8DBQBP8QOPywK+sNU5EO8RAqimAKCFRSx0lvG6y8vne2IhNG062Hn0dACeMLI5/zhpWpHBIVeAAquYfx2XFeA=
59 7f5094bb3f423fc799e471aac2aee81a7ce57a0b 0 iD8DBQBQGiL8ywK+sNU5EO8RAq5oAJ4rMMCPx6O+OuzNXVOexogedWz/QgCeIiIxLd76I4pXO48tdXhr0hQcBuM=
59 7f5094bb3f423fc799e471aac2aee81a7ce57a0b 0 iD8DBQBQGiL8ywK+sNU5EO8RAq5oAJ4rMMCPx6O+OuzNXVOexogedWz/QgCeIiIxLd76I4pXO48tdXhr0hQcBuM=
60 072209ae4ddb654eb2d5fd35bff358c738414432 0 iD8DBQBQQkq0ywK+sNU5EO8RArDTAJ9nk5CySnNAjAXYvqvx4uWCw9ThZwCgqmFRehH/l+oTwj3f8nw8u8qTCdc=
60 072209ae4ddb654eb2d5fd35bff358c738414432 0 iD8DBQBQQkq0ywK+sNU5EO8RArDTAJ9nk5CySnNAjAXYvqvx4uWCw9ThZwCgqmFRehH/l+oTwj3f8nw8u8qTCdc=
61 b3f0f9a39c4e1d0250048cd803ab03542d6f140a 0 iD8DBQBQamltywK+sNU5EO8RAlsqAJ4qF/m6aFu4mJCOKTiAP5RvZFK02ACfawYShUZO6OXEFfveU0aAxDR0M1k=
61 b3f0f9a39c4e1d0250048cd803ab03542d6f140a 0 iD8DBQBQamltywK+sNU5EO8RAlsqAJ4qF/m6aFu4mJCOKTiAP5RvZFK02ACfawYShUZO6OXEFfveU0aAxDR0M1k=
62 d118a4f4fd16d9b558ec3f3e87bfee772861d2b7 0 iD8DBQBQgPV5ywK+sNU5EO8RArylAJ0abcx5NlDjyv3ZDWpAfRIHyRsJtQCgn4TMuEayqgxzrvadQZHdTEU2g38=
62 d118a4f4fd16d9b558ec3f3e87bfee772861d2b7 0 iD8DBQBQgPV5ywK+sNU5EO8RArylAJ0abcx5NlDjyv3ZDWpAfRIHyRsJtQCgn4TMuEayqgxzrvadQZHdTEU2g38=
63 195ad823b5d58c68903a6153a25e3fb4ed25239d 0 iD8DBQBQkuT9ywK+sNU5EO8RAhB4AKCeerItoK2Jipm2cVf4euGofAa/WACeJj3TVd4pFILpb+ogj7ebweFLJi0=
63 195ad823b5d58c68903a6153a25e3fb4ed25239d 0 iD8DBQBQkuT9ywK+sNU5EO8RAhB4AKCeerItoK2Jipm2cVf4euGofAa/WACeJj3TVd4pFILpb+ogj7ebweFLJi0=
64 0c10cf8191469e7c3c8844922e17e71a176cb7cb 0 iD8DBQBQvQWoywK+sNU5EO8RAnq3AJoCn98u4geFx5YaQaeh99gFhCd7bQCgjoBwBSUyOvGd0yBy60E3Vv3VZhM=
64 0c10cf8191469e7c3c8844922e17e71a176cb7cb 0 iD8DBQBQvQWoywK+sNU5EO8RAnq3AJoCn98u4geFx5YaQaeh99gFhCd7bQCgjoBwBSUyOvGd0yBy60E3Vv3VZhM=
65 a4765077b65e6ae29ba42bab7834717b5072d5ba 0 iD8DBQBQ486sywK+sNU5EO8RAhmJAJ90aLfLKZhmcZN7kqphigQJxiFOQACeJ5IUZxjGKH4xzi3MrgIcx9n+dB0=
65 a4765077b65e6ae29ba42bab7834717b5072d5ba 0 iD8DBQBQ486sywK+sNU5EO8RAhmJAJ90aLfLKZhmcZN7kqphigQJxiFOQACeJ5IUZxjGKH4xzi3MrgIcx9n+dB0=
66 f5fbe15ca7449f2c9a3cf817c86d0ae68b307214 0 iD8DBQBQ+yuYywK+sNU5EO8RAm9JAJoD/UciWvpGeKBcpGtZJBFJVcL/HACghDXSgQ+xQDjB+6uGrdgAQsRR1Lg=
66 f5fbe15ca7449f2c9a3cf817c86d0ae68b307214 0 iD8DBQBQ+yuYywK+sNU5EO8RAm9JAJoD/UciWvpGeKBcpGtZJBFJVcL/HACghDXSgQ+xQDjB+6uGrdgAQsRR1Lg=
67 a6088c05e43a8aee0472ca3a4f6f8d7dd914ebbf 0 iD8DBQBRDDROywK+sNU5EO8RAh75AJ9uJCGoCWnP0Lv/+XuYs4hvUl+sAgCcD36QgAnuw8IQXrvv684BAXAnHcA=
67 a6088c05e43a8aee0472ca3a4f6f8d7dd914ebbf 0 iD8DBQBRDDROywK+sNU5EO8RAh75AJ9uJCGoCWnP0Lv/+XuYs4hvUl+sAgCcD36QgAnuw8IQXrvv684BAXAnHcA=
68 7511d4df752e61fe7ae4f3682e0a0008573b0402 0 iD8DBQBRFYaoywK+sNU5EO8RAuErAJoDyhXn+lptU3+AevVdwAIeNFyR2gCdHzPHyWd+JDeWCUR+pSOBi8O2ppM=
68 7511d4df752e61fe7ae4f3682e0a0008573b0402 0 iD8DBQBRFYaoywK+sNU5EO8RAuErAJoDyhXn+lptU3+AevVdwAIeNFyR2gCdHzPHyWd+JDeWCUR+pSOBi8O2ppM=
69 5b7175377babacce80a6c1e12366d8032a6d4340 0 iD8DBQBRMCYgywK+sNU5EO8RAq1/AKCWKlt9ysibyQgYwoxxIOZv5J8rpwCcDSHQaaf1fFZUTnQsOePwcM2Y/Sg=
69 5b7175377babacce80a6c1e12366d8032a6d4340 0 iD8DBQBRMCYgywK+sNU5EO8RAq1/AKCWKlt9ysibyQgYwoxxIOZv5J8rpwCcDSHQaaf1fFZUTnQsOePwcM2Y/Sg=
70 50c922c1b5145dab8baefefb0437d363b6a6c21c 0 iD8DBQBRWnUnywK+sNU5EO8RAuQRAJwM42cJqJPeqJ0jVNdMqKMDqr4dSACeP0cRVGz1gitMuV0x8f3mrZrqc7I=
70 50c922c1b5145dab8baefefb0437d363b6a6c21c 0 iD8DBQBRWnUnywK+sNU5EO8RAuQRAJwM42cJqJPeqJ0jVNdMqKMDqr4dSACeP0cRVGz1gitMuV0x8f3mrZrqc7I=
71 8a7bd2dccd44ed571afe7424cd7f95594f27c092 0 iD8DBQBRXfBvywK+sNU5EO8RAn+LAKCsMmflbuXjYRxlzFwId5ptm8TZcwCdGkyLbZcASBOkzQUm/WW1qfknJHU=
71 8a7bd2dccd44ed571afe7424cd7f95594f27c092 0 iD8DBQBRXfBvywK+sNU5EO8RAn+LAKCsMmflbuXjYRxlzFwId5ptm8TZcwCdGkyLbZcASBOkzQUm/WW1qfknJHU=
72 292cd385856d98bacb2c3086f8897bc660c2beea 0 iD8DBQBRcM0BywK+sNU5EO8RAjp4AKCJBykQbvXhKuvLSMxKx3a2TBiXcACfbr/kLg5GlZTF/XDPmY+PyHgI/GM=
72 292cd385856d98bacb2c3086f8897bc660c2beea 0 iD8DBQBRcM0BywK+sNU5EO8RAjp4AKCJBykQbvXhKuvLSMxKx3a2TBiXcACfbr/kLg5GlZTF/XDPmY+PyHgI/GM=
73 23f785b38af38d2fca6b8f3db56b8007a84cd73a 0 iD8DBQBRgZwNywK+sNU5EO8RAmO4AJ4u2ILGuimRP6MJgE2t65LZ5dAdkACgiENEstIdrlFC80p+sWKD81kKIYI=
73 23f785b38af38d2fca6b8f3db56b8007a84cd73a 0 iD8DBQBRgZwNywK+sNU5EO8RAmO4AJ4u2ILGuimRP6MJgE2t65LZ5dAdkACgiENEstIdrlFC80p+sWKD81kKIYI=
74 ddc7a6be20212d18f3e27d9d7e6f079a66d96f21 0 iD8DBQBRkswvywK+sNU5EO8RAiYYAJsHTHyHbJeAgmGvBTmDrfcKu4doUgCeLm7eGBjx7yAPUvEtxef8rAkQmXI=
74 ddc7a6be20212d18f3e27d9d7e6f079a66d96f21 0 iD8DBQBRkswvywK+sNU5EO8RAiYYAJsHTHyHbJeAgmGvBTmDrfcKu4doUgCeLm7eGBjx7yAPUvEtxef8rAkQmXI=
75 cceaf7af4c9e9e6fa2dbfdcfe9856c5da69c4ffd 0 iD8DBQBRqnFLywK+sNU5EO8RAsWNAJ9RR6t+y1DLFc2HeH0eN9VfZAKF9gCeJ8ezvhtKq/LMs0/nvcgKQc/d5jk=
75 cceaf7af4c9e9e6fa2dbfdcfe9856c5da69c4ffd 0 iD8DBQBRqnFLywK+sNU5EO8RAsWNAJ9RR6t+y1DLFc2HeH0eN9VfZAKF9gCeJ8ezvhtKq/LMs0/nvcgKQc/d5jk=
76 009794acc6e37a650f0fae37872e733382ac1c0c 0 iD8DBQBR0guxywK+sNU5EO8RArNkAKCq9pMihVzP8Os5kCmgbWpe5C37wgCgqzuPZTHvAsXF5wTyaSTMVa9Ccq4=
76 009794acc6e37a650f0fae37872e733382ac1c0c 0 iD8DBQBR0guxywK+sNU5EO8RArNkAKCq9pMihVzP8Os5kCmgbWpe5C37wgCgqzuPZTHvAsXF5wTyaSTMVa9Ccq4=
77 f0d7721d7322dcfb5af33599c2543f27335334bb 0 iD8DBQBR8taaywK+sNU5EO8RAqeEAJ4idDhhDuEsgsUjeQgWNj498matHACfT67gSF5w0ylsrBx1Hb52HkGXDm0=
77 f0d7721d7322dcfb5af33599c2543f27335334bb 0 iD8DBQBR8taaywK+sNU5EO8RAqeEAJ4idDhhDuEsgsUjeQgWNj498matHACfT67gSF5w0ylsrBx1Hb52HkGXDm0=
78 f37b5a17e6a0ee17afde2cdde5393dd74715fb58 0 iD8DBQBR+ymFywK+sNU5EO8RAuSdAJkBMcd9DAZ3rWE9WGKPm2YZ8LBoXACfXn/wbEsVy7ZgJoUwiWmHSnQaWCI=
78 f37b5a17e6a0ee17afde2cdde5393dd74715fb58 0 iD8DBQBR+ymFywK+sNU5EO8RAuSdAJkBMcd9DAZ3rWE9WGKPm2YZ8LBoXACfXn/wbEsVy7ZgJoUwiWmHSnQaWCI=
79 335a558f81dc73afeab4d7be63617392b130117f 0 iQIVAwUAUiZrIyBXgaxoKi1yAQK2iw//cquNqqSkc8Re5/TZT9I6NH+lh6DbOKjJP0Xl1Wqq0K+KSIUgZG4G32ovaEb2l5X0uY+3unRPiZ0ebl0YSw4Fb2ZiPIADXLBTOYRrY2Wwd3tpJeGI6wEgZt3SfcITV/g7NJrCjT3FlYoSOIayrExM80InSdcEM0Q3Rx6HKzY2acyxzgZeAtAW5ohFvHilSvY6p5Gcm4+QptMxvw45GPdreUmjeXZxNXNXZ8P+MjMz/QJbai/N7PjmK8lqnhkBsT48Ng/KhhmOkGntNJ2/ImBWLFGcWngSvJ7sfWwnyhndvGhe0Hq1NcCf7I8TjNDxU5TR+m+uW7xjXdLoDbUjBdX4sKXnh8ZjbYiODKBOrrDq25cf8nA/tnpKyE/qsVy60kOk6loY4XKiYmn1V49Ta0emmDx0hqo3HgxHHsHX0NDnGdWGol7cPRET0RzVobKq1A0jnrhPooWidvLh9bPzLonrWDo+ib+DuySoRkuYUK4pgZJ2mbg6daFOBEZygkSyRB8bo1UQUP7EgQDrWe4khb/5GHEfDkrQz3qu/sXvc0Ir1mOUWBFPHC2DjjCn/oMJuUkG1SwM8l2Bfv7h67ssES6YQ2+RjOix4yid7EXS/Ogl45PzCIPSI5+BbNs10JhE0w5uErBHlF53EDTe/TSLc+GU6DB6PP6dH912Njdr3jpNSUQ=
79 335a558f81dc73afeab4d7be63617392b130117f 0 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
@@ -1,112 +1,113
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
@@ -1,1287 +1,1303
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
10
11 import os
11 import os
12 import copy
12 import copy
13
13
14 from mercurial import hg, util, cmdutil, scmutil, match as match_, \
14 from mercurial import hg, util, cmdutil, scmutil, match as match_, \
15 archival, pathutil, revset
15 archival, pathutil, revset
16 from mercurial.i18n import _
16 from mercurial.i18n import _
17 from mercurial.node import hex
17 from mercurial.node import hex
18
18
19 import lfutil
19 import lfutil
20 import lfcommands
20 import lfcommands
21 import basestore
21 import basestore
22
22
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
23 # -- Utility functions: commonly/repeatedly needed functionality ---------------
24
24
25 def installnormalfilesmatchfn(manifest):
25 def installnormalfilesmatchfn(manifest):
26 '''installmatchfn with a matchfn that ignores all largefiles'''
26 '''installmatchfn with a matchfn that ignores all largefiles'''
27 def overridematch(ctx, pats=[], opts={}, globbed=False,
27 def overridematch(ctx, pats=[], opts={}, globbed=False,
28 default='relpath'):
28 default='relpath'):
29 match = oldmatch(ctx, pats, opts, globbed, default)
29 match = oldmatch(ctx, pats, opts, globbed, default)
30 m = copy.copy(match)
30 m = copy.copy(match)
31 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
31 notlfile = lambda f: not (lfutil.isstandin(f) or lfutil.standin(f) in
32 manifest)
32 manifest)
33 m._files = filter(notlfile, m._files)
33 m._files = filter(notlfile, m._files)
34 m._fmap = set(m._files)
34 m._fmap = set(m._files)
35 m._always = False
35 m._always = False
36 origmatchfn = m.matchfn
36 origmatchfn = m.matchfn
37 m.matchfn = lambda f: notlfile(f) and origmatchfn(f)
37 m.matchfn = lambda f: notlfile(f) and origmatchfn(f)
38 return m
38 return m
39 oldmatch = installmatchfn(overridematch)
39 oldmatch = installmatchfn(overridematch)
40
40
41 def installmatchfn(f):
41 def installmatchfn(f):
42 '''monkey patch the scmutil module with a custom match function.
42 '''monkey patch the scmutil module with a custom match function.
43 Warning: it is monkey patching the _module_ on runtime! Not thread safe!'''
43 Warning: it is monkey patching the _module_ on runtime! Not thread safe!'''
44 oldmatch = scmutil.match
44 oldmatch = scmutil.match
45 setattr(f, 'oldmatch', oldmatch)
45 setattr(f, 'oldmatch', oldmatch)
46 scmutil.match = f
46 scmutil.match = f
47 return oldmatch
47 return oldmatch
48
48
49 def restorematchfn():
49 def restorematchfn():
50 '''restores scmutil.match to what it was before installmatchfn
50 '''restores scmutil.match to what it was before installmatchfn
51 was called. no-op if scmutil.match is its original function.
51 was called. no-op if scmutil.match is its original function.
52
52
53 Note that n calls to installmatchfn will require n calls to
53 Note that n calls to installmatchfn will require n calls to
54 restore matchfn to reverse'''
54 restore matchfn to reverse'''
55 scmutil.match = getattr(scmutil.match, 'oldmatch')
55 scmutil.match = getattr(scmutil.match, 'oldmatch')
56
56
57 def installmatchandpatsfn(f):
57 def installmatchandpatsfn(f):
58 oldmatchandpats = scmutil.matchandpats
58 oldmatchandpats = scmutil.matchandpats
59 setattr(f, 'oldmatchandpats', oldmatchandpats)
59 setattr(f, 'oldmatchandpats', oldmatchandpats)
60 scmutil.matchandpats = f
60 scmutil.matchandpats = f
61 return oldmatchandpats
61 return oldmatchandpats
62
62
63 def restorematchandpatsfn():
63 def restorematchandpatsfn():
64 '''restores scmutil.matchandpats to what it was before
64 '''restores scmutil.matchandpats to what it was before
65 installmatchandpatsfn was called. No-op if scmutil.matchandpats
65 installmatchandpatsfn was called. No-op if scmutil.matchandpats
66 is its original function.
66 is its original function.
67
67
68 Note that n calls to installmatchandpatsfn will require n calls
68 Note that n calls to installmatchandpatsfn will require n calls
69 to restore matchfn to reverse'''
69 to restore matchfn to reverse'''
70 scmutil.matchandpats = getattr(scmutil.matchandpats, 'oldmatchandpats',
70 scmutil.matchandpats = getattr(scmutil.matchandpats, 'oldmatchandpats',
71 scmutil.matchandpats)
71 scmutil.matchandpats)
72
72
73 def addlargefiles(ui, repo, *pats, **opts):
73 def addlargefiles(ui, repo, *pats, **opts):
74 large = opts.pop('large', None)
74 large = opts.pop('large', None)
75 lfsize = lfutil.getminsize(
75 lfsize = lfutil.getminsize(
76 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
76 ui, lfutil.islfilesrepo(repo), opts.pop('lfsize', None))
77
77
78 lfmatcher = None
78 lfmatcher = None
79 if lfutil.islfilesrepo(repo):
79 if lfutil.islfilesrepo(repo):
80 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
80 lfpats = ui.configlist(lfutil.longname, 'patterns', default=[])
81 if lfpats:
81 if lfpats:
82 lfmatcher = match_.match(repo.root, '', list(lfpats))
82 lfmatcher = match_.match(repo.root, '', list(lfpats))
83
83
84 lfnames = []
84 lfnames = []
85 m = scmutil.match(repo[None], pats, opts)
85 m = scmutil.match(repo[None], pats, opts)
86 m.bad = lambda x, y: None
86 m.bad = lambda x, y: None
87 wctx = repo[None]
87 wctx = repo[None]
88 for f in repo.walk(m):
88 for f in repo.walk(m):
89 exact = m.exact(f)
89 exact = m.exact(f)
90 lfile = lfutil.standin(f) in wctx
90 lfile = lfutil.standin(f) in wctx
91 nfile = f in wctx
91 nfile = f in wctx
92 exists = lfile or nfile
92 exists = lfile or nfile
93
93
94 # Don't warn the user when they attempt to add a normal tracked file.
94 # Don't warn the user when they attempt to add a normal tracked file.
95 # The normal add code will do that for us.
95 # The normal add code will do that for us.
96 if exact and exists:
96 if exact and exists:
97 if lfile:
97 if lfile:
98 ui.warn(_('%s already a largefile\n') % f)
98 ui.warn(_('%s already a largefile\n') % f)
99 continue
99 continue
100
100
101 if (exact or not exists) and not lfutil.isstandin(f):
101 if (exact or not exists) and not lfutil.isstandin(f):
102 wfile = repo.wjoin(f)
102 wfile = repo.wjoin(f)
103
103
104 # In case the file was removed previously, but not committed
104 # In case the file was removed previously, but not committed
105 # (issue3507)
105 # (issue3507)
106 if not os.path.exists(wfile):
106 if not os.path.exists(wfile):
107 continue
107 continue
108
108
109 abovemin = (lfsize and
109 abovemin = (lfsize and
110 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
110 os.lstat(wfile).st_size >= lfsize * 1024 * 1024)
111 if large or abovemin or (lfmatcher and lfmatcher(f)):
111 if large or abovemin or (lfmatcher and lfmatcher(f)):
112 lfnames.append(f)
112 lfnames.append(f)
113 if ui.verbose or not exact:
113 if ui.verbose or not exact:
114 ui.status(_('adding %s as a largefile\n') % m.rel(f))
114 ui.status(_('adding %s as a largefile\n') % m.rel(f))
115
115
116 bad = []
116 bad = []
117
117
118 # Need to lock, otherwise there could be a race condition between
118 # Need to lock, otherwise there could be a race condition between
119 # when standins are created and added to the repo.
119 # when standins are created and added to the repo.
120 wlock = repo.wlock()
120 wlock = repo.wlock()
121 try:
121 try:
122 if not opts.get('dry_run'):
122 if not opts.get('dry_run'):
123 standins = []
123 standins = []
124 lfdirstate = lfutil.openlfdirstate(ui, repo)
124 lfdirstate = lfutil.openlfdirstate(ui, repo)
125 for f in lfnames:
125 for f in lfnames:
126 standinname = lfutil.standin(f)
126 standinname = lfutil.standin(f)
127 lfutil.writestandin(repo, standinname, hash='',
127 lfutil.writestandin(repo, standinname, hash='',
128 executable=lfutil.getexecutable(repo.wjoin(f)))
128 executable=lfutil.getexecutable(repo.wjoin(f)))
129 standins.append(standinname)
129 standins.append(standinname)
130 if lfdirstate[f] == 'r':
130 if lfdirstate[f] == 'r':
131 lfdirstate.normallookup(f)
131 lfdirstate.normallookup(f)
132 else:
132 else:
133 lfdirstate.add(f)
133 lfdirstate.add(f)
134 lfdirstate.write()
134 lfdirstate.write()
135 bad += [lfutil.splitstandin(f)
135 bad += [lfutil.splitstandin(f)
136 for f in repo[None].add(standins)
136 for f in repo[None].add(standins)
137 if f in m.files()]
137 if f in m.files()]
138 finally:
138 finally:
139 wlock.release()
139 wlock.release()
140 return bad
140 return bad
141
141
142 def removelargefiles(ui, repo, isaddremove, *pats, **opts):
142 def removelargefiles(ui, repo, isaddremove, *pats, **opts):
143 after = opts.get('after')
143 after = opts.get('after')
144 if not pats and not after:
144 if not pats and not after:
145 raise util.Abort(_('no files specified'))
145 raise util.Abort(_('no files specified'))
146 m = scmutil.match(repo[None], pats, opts)
146 m = scmutil.match(repo[None], pats, opts)
147 try:
147 try:
148 repo.lfstatus = True
148 repo.lfstatus = True
149 s = repo.status(match=m, clean=True)
149 s = repo.status(match=m, clean=True)
150 finally:
150 finally:
151 repo.lfstatus = False
151 repo.lfstatus = False
152 manifest = repo[None].manifest()
152 manifest = repo[None].manifest()
153 modified, added, deleted, clean = [[f for f in list
153 modified, added, deleted, clean = [[f for f in list
154 if lfutil.standin(f) in manifest]
154 if lfutil.standin(f) in manifest]
155 for list in (s.modified, s.added,
155 for list in (s.modified, s.added,
156 s.deleted, s.clean)]
156 s.deleted, s.clean)]
157
157
158 def warn(files, msg):
158 def warn(files, msg):
159 for f in files:
159 for f in files:
160 ui.warn(msg % m.rel(f))
160 ui.warn(msg % m.rel(f))
161 return int(len(files) > 0)
161 return int(len(files) > 0)
162
162
163 result = 0
163 result = 0
164
164
165 if after:
165 if after:
166 remove = deleted
166 remove = deleted
167 result = warn(modified + added + clean,
167 result = warn(modified + added + clean,
168 _('not removing %s: file still exists\n'))
168 _('not removing %s: file still exists\n'))
169 else:
169 else:
170 remove = deleted + clean
170 remove = deleted + clean
171 result = warn(modified, _('not removing %s: file is modified (use -f'
171 result = warn(modified, _('not removing %s: file is modified (use -f'
172 ' to force removal)\n'))
172 ' to force removal)\n'))
173 result = warn(added, _('not removing %s: file has been marked for add'
173 result = warn(added, _('not removing %s: file has been marked for add'
174 ' (use forget to undo)\n')) or result
174 ' (use forget to undo)\n')) or result
175
175
176 for f in sorted(remove):
176 for f in sorted(remove):
177 if ui.verbose or not m.exact(f):
177 if ui.verbose or not m.exact(f):
178 ui.status(_('removing %s\n') % m.rel(f))
178 ui.status(_('removing %s\n') % m.rel(f))
179
179
180 # Need to lock because standin files are deleted then removed from the
180 # Need to lock because standin files are deleted then removed from the
181 # repository and we could race in-between.
181 # repository and we could race in-between.
182 wlock = repo.wlock()
182 wlock = repo.wlock()
183 try:
183 try:
184 lfdirstate = lfutil.openlfdirstate(ui, repo)
184 lfdirstate = lfutil.openlfdirstate(ui, repo)
185 for f in remove:
185 for f in remove:
186 if not after:
186 if not after:
187 # If this is being called by addremove, notify the user that we
187 # If this is being called by addremove, notify the user that we
188 # are removing the file.
188 # are removing the file.
189 if isaddremove:
189 if isaddremove:
190 ui.status(_('removing %s\n') % f)
190 ui.status(_('removing %s\n') % f)
191 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
191 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
192 lfdirstate.remove(f)
192 lfdirstate.remove(f)
193 lfdirstate.write()
193 lfdirstate.write()
194 remove = [lfutil.standin(f) for f in remove]
194 remove = [lfutil.standin(f) for f in remove]
195 # If this is being called by addremove, let the original addremove
195 # If this is being called by addremove, let the original addremove
196 # function handle this.
196 # function handle this.
197 if not isaddremove:
197 if not isaddremove:
198 for f in remove:
198 for f in remove:
199 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
199 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
200 repo[None].forget(remove)
200 repo[None].forget(remove)
201 finally:
201 finally:
202 wlock.release()
202 wlock.release()
203
203
204 return result
204 return result
205
205
206 # For overriding mercurial.hgweb.webcommands so that largefiles will
206 # For overriding mercurial.hgweb.webcommands so that largefiles will
207 # appear at their right place in the manifests.
207 # appear at their right place in the manifests.
208 def decodepath(orig, path):
208 def decodepath(orig, path):
209 return lfutil.splitstandin(path) or path
209 return lfutil.splitstandin(path) or path
210
210
211 # -- Wrappers: modify existing commands --------------------------------
211 # -- Wrappers: modify existing commands --------------------------------
212
212
213 # Add works by going through the files that the user wanted to add and
213 # Add works by going through the files that the user wanted to add and
214 # checking if they should be added as largefiles. Then it makes a new
214 # checking if they should be added as largefiles. Then it makes a new
215 # matcher which matches only the normal files and runs the original
215 # matcher which matches only the normal files and runs the original
216 # version of add.
216 # version of add.
217 def overrideadd(orig, ui, repo, *pats, **opts):
217 def overrideadd(orig, ui, repo, *pats, **opts):
218 normal = opts.pop('normal')
218 normal = opts.pop('normal')
219 if normal:
219 if normal:
220 if opts.get('large'):
220 if opts.get('large'):
221 raise util.Abort(_('--normal cannot be used with --large'))
221 raise util.Abort(_('--normal cannot be used with --large'))
222 return orig(ui, repo, *pats, **opts)
222 return orig(ui, repo, *pats, **opts)
223 bad = addlargefiles(ui, repo, *pats, **opts)
223 bad = addlargefiles(ui, repo, *pats, **opts)
224 installnormalfilesmatchfn(repo[None].manifest())
224 installnormalfilesmatchfn(repo[None].manifest())
225 result = orig(ui, repo, *pats, **opts)
225 result = orig(ui, repo, *pats, **opts)
226 restorematchfn()
226 restorematchfn()
227
227
228 return (result == 1 or bad) and 1 or 0
228 return (result == 1 or bad) and 1 or 0
229
229
230 def overrideremove(orig, ui, repo, *pats, **opts):
230 def overrideremove(orig, ui, repo, *pats, **opts):
231 installnormalfilesmatchfn(repo[None].manifest())
231 installnormalfilesmatchfn(repo[None].manifest())
232 result = orig(ui, repo, *pats, **opts)
232 result = orig(ui, repo, *pats, **opts)
233 restorematchfn()
233 restorematchfn()
234 return removelargefiles(ui, repo, False, *pats, **opts) or result
234 return removelargefiles(ui, repo, False, *pats, **opts) or result
235
235
236 def overridestatusfn(orig, repo, rev2, **opts):
236 def overridestatusfn(orig, repo, rev2, **opts):
237 try:
237 try:
238 repo._repo.lfstatus = True
238 repo._repo.lfstatus = True
239 return orig(repo, rev2, **opts)
239 return orig(repo, rev2, **opts)
240 finally:
240 finally:
241 repo._repo.lfstatus = False
241 repo._repo.lfstatus = False
242
242
243 def overridestatus(orig, ui, repo, *pats, **opts):
243 def overridestatus(orig, ui, repo, *pats, **opts):
244 try:
244 try:
245 repo.lfstatus = True
245 repo.lfstatus = True
246 return orig(ui, repo, *pats, **opts)
246 return orig(ui, repo, *pats, **opts)
247 finally:
247 finally:
248 repo.lfstatus = False
248 repo.lfstatus = False
249
249
250 def overridedirty(orig, repo, ignoreupdate=False):
250 def overridedirty(orig, repo, ignoreupdate=False):
251 try:
251 try:
252 repo._repo.lfstatus = True
252 repo._repo.lfstatus = True
253 return orig(repo, ignoreupdate)
253 return orig(repo, ignoreupdate)
254 finally:
254 finally:
255 repo._repo.lfstatus = False
255 repo._repo.lfstatus = False
256
256
257 def overridelog(orig, ui, repo, *pats, **opts):
257 def overridelog(orig, ui, repo, *pats, **opts):
258 def overridematchandpats(ctx, pats=[], opts={}, globbed=False,
258 def overridematchandpats(ctx, pats=[], opts={}, globbed=False,
259 default='relpath'):
259 default='relpath'):
260 """Matcher that merges root directory with .hglf, suitable for log.
260 """Matcher that merges root directory with .hglf, suitable for log.
261 It is still possible to match .hglf directly.
261 It is still possible to match .hglf directly.
262 For any listed files run log on the standin too.
262 For any listed files run log on the standin too.
263 matchfn tries both the given filename and with .hglf stripped.
263 matchfn tries both the given filename and with .hglf stripped.
264 """
264 """
265 matchandpats = oldmatchandpats(ctx, pats, opts, globbed, default)
265 matchandpats = oldmatchandpats(ctx, pats, opts, globbed, default)
266 m, p = copy.copy(matchandpats)
266 m, p = copy.copy(matchandpats)
267
267
268 if m.always():
268 if m.always():
269 # We want to match everything anyway, so there's no benefit trying
269 # We want to match everything anyway, so there's no benefit trying
270 # to add standins.
270 # to add standins.
271 return matchandpats
271 return matchandpats
272
272
273 pats = set(p)
273 pats = set(p)
274 # TODO: handling of patterns in both cases below
274 # TODO: handling of patterns in both cases below
275 if m._cwd:
275 if m._cwd:
276 if os.path.isabs(m._cwd):
276 if os.path.isabs(m._cwd):
277 # TODO: handle largefile magic when invoked from other cwd
277 # TODO: handle largefile magic when invoked from other cwd
278 return matchandpats
278 return matchandpats
279 back = (m._cwd.count('/') + 1) * '../'
279 back = (m._cwd.count('/') + 1) * '../'
280 pats.update(back + lfutil.standin(m._cwd + '/' + f) for f in p)
280 pats.update(back + lfutil.standin(m._cwd + '/' + f) for f in p)
281 else:
281 else:
282 pats.update(lfutil.standin(f) for f in p)
282 pats.update(lfutil.standin(f) for f in p)
283
283
284 for i in range(0, len(m._files)):
284 for i in range(0, len(m._files)):
285 standin = lfutil.standin(m._files[i])
285 standin = lfutil.standin(m._files[i])
286 if standin in repo[ctx.node()]:
286 if standin in repo[ctx.node()]:
287 m._files[i] = standin
287 m._files[i] = standin
288 elif m._files[i] not in repo[ctx.node()]:
288 elif m._files[i] not in repo[ctx.node()]:
289 m._files.append(standin)
289 m._files.append(standin)
290 pats.add(standin)
290 pats.add(standin)
291
291
292 m._fmap = set(m._files)
292 m._fmap = set(m._files)
293 m._always = False
293 m._always = False
294 origmatchfn = m.matchfn
294 origmatchfn = m.matchfn
295 def lfmatchfn(f):
295 def lfmatchfn(f):
296 lf = lfutil.splitstandin(f)
296 lf = lfutil.splitstandin(f)
297 if lf is not None and origmatchfn(lf):
297 if lf is not None and origmatchfn(lf):
298 return True
298 return True
299 r = origmatchfn(f)
299 r = origmatchfn(f)
300 return r
300 return r
301 m.matchfn = lfmatchfn
301 m.matchfn = lfmatchfn
302
302
303 return m, pats
303 return m, pats
304
304
305 # For hg log --patch, the match object is used in two different senses:
305 # For hg log --patch, the match object is used in two different senses:
306 # (1) to determine what revisions should be printed out, and
306 # (1) to determine what revisions should be printed out, and
307 # (2) to determine what files to print out diffs for.
307 # (2) to determine what files to print out diffs for.
308 # The magic matchandpats override should be used for case (1) but not for
308 # The magic matchandpats override should be used for case (1) but not for
309 # case (2).
309 # case (2).
310 def overridemakelogfilematcher(repo, pats, opts):
310 def overridemakelogfilematcher(repo, pats, opts):
311 pctx = repo[None]
311 pctx = repo[None]
312 match, pats = oldmatchandpats(pctx, pats, opts)
312 match, pats = oldmatchandpats(pctx, pats, opts)
313 return lambda rev: match
313 return lambda rev: match
314
314
315 oldmatchandpats = installmatchandpatsfn(overridematchandpats)
315 oldmatchandpats = installmatchandpatsfn(overridematchandpats)
316 oldmakelogfilematcher = cmdutil._makenofollowlogfilematcher
316 oldmakelogfilematcher = cmdutil._makenofollowlogfilematcher
317 setattr(cmdutil, '_makenofollowlogfilematcher', overridemakelogfilematcher)
317 setattr(cmdutil, '_makenofollowlogfilematcher', overridemakelogfilematcher)
318
318
319 try:
319 try:
320 return orig(ui, repo, *pats, **opts)
320 return orig(ui, repo, *pats, **opts)
321 finally:
321 finally:
322 restorematchandpatsfn()
322 restorematchandpatsfn()
323 setattr(cmdutil, '_makenofollowlogfilematcher', oldmakelogfilematcher)
323 setattr(cmdutil, '_makenofollowlogfilematcher', oldmakelogfilematcher)
324
324
325 def overrideverify(orig, ui, repo, *pats, **opts):
325 def overrideverify(orig, ui, repo, *pats, **opts):
326 large = opts.pop('large', False)
326 large = opts.pop('large', False)
327 all = opts.pop('lfa', False)
327 all = opts.pop('lfa', False)
328 contents = opts.pop('lfc', False)
328 contents = opts.pop('lfc', False)
329
329
330 result = orig(ui, repo, *pats, **opts)
330 result = orig(ui, repo, *pats, **opts)
331 if large or all or contents:
331 if large or all or contents:
332 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
332 result = result or lfcommands.verifylfiles(ui, repo, all, contents)
333 return result
333 return result
334
334
335 def overridedebugstate(orig, ui, repo, *pats, **opts):
335 def overridedebugstate(orig, ui, repo, *pats, **opts):
336 large = opts.pop('large', False)
336 large = opts.pop('large', False)
337 if large:
337 if large:
338 class fakerepo(object):
338 class fakerepo(object):
339 dirstate = lfutil.openlfdirstate(ui, repo)
339 dirstate = lfutil.openlfdirstate(ui, repo)
340 orig(ui, fakerepo, *pats, **opts)
340 orig(ui, fakerepo, *pats, **opts)
341 else:
341 else:
342 orig(ui, repo, *pats, **opts)
342 orig(ui, repo, *pats, **opts)
343
343
344 # Override needs to refresh standins so that update's normal merge
344 # Override needs to refresh standins so that update's normal merge
345 # will go through properly. Then the other update hook (overriding repo.update)
345 # will go through properly. Then the other update hook (overriding repo.update)
346 # will get the new files. Filemerge is also overridden so that the merge
346 # will get the new files. Filemerge is also overridden so that the merge
347 # will merge standins correctly.
347 # will merge standins correctly.
348 def overrideupdate(orig, ui, repo, *pats, **opts):
348 def overrideupdate(orig, ui, repo, *pats, **opts):
349 # Need to lock between the standins getting updated and their
349 # Need to lock between the standins getting updated and their
350 # largefiles getting updated
350 # largefiles getting updated
351 wlock = repo.wlock()
351 wlock = repo.wlock()
352 try:
352 try:
353 if opts['check']:
353 if opts['check']:
354 lfdirstate = lfutil.openlfdirstate(ui, repo)
354 lfdirstate = lfutil.openlfdirstate(ui, repo)
355 unsure, s = lfdirstate.status(
355 unsure, s = lfdirstate.status(
356 match_.always(repo.root, repo.getcwd()),
356 match_.always(repo.root, repo.getcwd()),
357 [], False, False, False)
357 [], False, False, False)
358
358
359 mod = len(s.modified) > 0
359 mod = len(s.modified) > 0
360 for lfile in unsure:
360 for lfile in unsure:
361 standin = lfutil.standin(lfile)
361 standin = lfutil.standin(lfile)
362 if repo['.'][standin].data().strip() != \
362 if repo['.'][standin].data().strip() != \
363 lfutil.hashfile(repo.wjoin(lfile)):
363 lfutil.hashfile(repo.wjoin(lfile)):
364 mod = True
364 mod = True
365 else:
365 else:
366 lfdirstate.normal(lfile)
366 lfdirstate.normal(lfile)
367 lfdirstate.write()
367 lfdirstate.write()
368 if mod:
368 if mod:
369 raise util.Abort(_('uncommitted changes'))
369 raise util.Abort(_('uncommitted changes'))
370 return orig(ui, repo, *pats, **opts)
370 return orig(ui, repo, *pats, **opts)
371 finally:
371 finally:
372 wlock.release()
372 wlock.release()
373
373
374 # Before starting the manifest merge, merge.updates will call
374 # Before starting the manifest merge, merge.updates will call
375 # checkunknown to check if there are any files in the merged-in
375 # checkunknown to check if there are any files in the merged-in
376 # changeset that collide with unknown files in the working copy.
376 # changeset that collide with unknown files in the working copy.
377 #
377 #
378 # The largefiles are seen as unknown, so this prevents us from merging
378 # The largefiles are seen as unknown, so this prevents us from merging
379 # in a file 'foo' if we already have a largefile with the same name.
379 # in a file 'foo' if we already have a largefile with the same name.
380 #
380 #
381 # The overridden function filters the unknown files by removing any
381 # The overridden function filters the unknown files by removing any
382 # largefiles. This makes the merge proceed and we can then handle this
382 # largefiles. This makes the merge proceed and we can then handle this
383 # case further in the overridden calculateupdates function below.
383 # case further in the overridden calculateupdates function below.
384 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
384 def overridecheckunknownfile(origfn, repo, wctx, mctx, f):
385 if lfutil.standin(repo.dirstate.normalize(f)) in wctx:
385 if lfutil.standin(repo.dirstate.normalize(f)) in wctx:
386 return False
386 return False
387 return origfn(repo, wctx, mctx, f)
387 return origfn(repo, wctx, mctx, f)
388
388
389 # The manifest merge handles conflicts on the manifest level. We want
389 # The manifest merge handles conflicts on the manifest level. We want
390 # to handle changes in largefile-ness of files at this level too.
390 # to handle changes in largefile-ness of files at this level too.
391 #
391 #
392 # The strategy is to run the original calculateupdates and then process
392 # The strategy is to run the original calculateupdates and then process
393 # the action list it outputs. There are two cases we need to deal with:
393 # the action list it outputs. There are two cases we need to deal with:
394 #
394 #
395 # 1. Normal file in p1, largefile in p2. Here the largefile is
395 # 1. Normal file in p1, largefile in p2. Here the largefile is
396 # detected via its standin file, which will enter the working copy
396 # detected via its standin file, which will enter the working copy
397 # with a "get" action. It is not "merge" since the standin is all
397 # with a "get" action. It is not "merge" since the standin is all
398 # Mercurial is concerned with at this level -- the link to the
398 # Mercurial is concerned with at this level -- the link to the
399 # existing normal file is not relevant here.
399 # existing normal file is not relevant here.
400 #
400 #
401 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
401 # 2. Largefile in p1, normal file in p2. Here we get a "merge" action
402 # since the largefile will be present in the working copy and
402 # since the largefile will be present in the working copy and
403 # different from the normal file in p2. Mercurial therefore
403 # different from the normal file in p2. Mercurial therefore
404 # triggers a merge action.
404 # triggers a merge action.
405 #
405 #
406 # In both cases, we prompt the user and emit new actions to either
406 # In both cases, we prompt the user and emit new actions to either
407 # remove the standin (if the normal file was kept) or to remove the
407 # remove the standin (if the normal file was kept) or to remove the
408 # normal file and get the standin (if the largefile was kept). The
408 # normal file and get the standin (if the largefile was kept). The
409 # default prompt answer is to use the largefile version since it was
409 # default prompt answer is to use the largefile version since it was
410 # presumably changed on purpose.
410 # presumably changed on purpose.
411 #
411 #
412 # Finally, the merge.applyupdates function will then take care of
412 # Finally, the merge.applyupdates function will then take care of
413 # writing the files into the working copy and lfcommands.updatelfiles
413 # writing the files into the working copy and lfcommands.updatelfiles
414 # will update the largefiles.
414 # will update the largefiles.
415 def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force,
415 def overridecalculateupdates(origfn, repo, p1, p2, pas, branchmerge, force,
416 partial, acceptremote, followcopies):
416 partial, acceptremote, followcopies):
417 overwrite = force and not branchmerge
417 overwrite = force and not branchmerge
418 actions = origfn(repo, p1, p2, pas, branchmerge, force, partial,
418 actions = origfn(repo, p1, p2, pas, branchmerge, force, partial,
419 acceptremote, followcopies)
419 acceptremote, followcopies)
420
420
421 if overwrite:
421 if overwrite:
422 return actions
422 return actions
423
423
424 removes = set(a[0] for a in actions['r'])
424 removes = set(a[0] for a in actions['r'])
425
425
426 newglist = []
426 newglist = []
427 lfmr = [] # LargeFiles: Mark as Removed
427 lfmr = [] # LargeFiles: Mark as Removed
428 for action in actions['g']:
428 for action in actions['g']:
429 f, args, msg = action
429 f, args, msg = action
430 splitstandin = f and lfutil.splitstandin(f)
430 splitstandin = f and lfutil.splitstandin(f)
431 if (splitstandin is not None and
431 if (splitstandin is not None and
432 splitstandin in p1 and splitstandin not in removes):
432 splitstandin in p1 and splitstandin not in removes):
433 # Case 1: normal file in the working copy, largefile in
433 # Case 1: normal file in the working copy, largefile in
434 # the second parent
434 # the second parent
435 lfile = splitstandin
435 lfile = splitstandin
436 standin = f
436 standin = f
437 msg = _('remote turned local normal file %s into a largefile\n'
437 msg = _('remote turned local normal file %s into a largefile\n'
438 'use (l)argefile or keep (n)ormal file?'
438 'use (l)argefile or keep (n)ormal file?'
439 '$$ &Largefile $$ &Normal file') % lfile
439 '$$ &Largefile $$ &Normal file') % lfile
440 if repo.ui.promptchoice(msg, 0) == 0:
440 if (# local has unchanged normal file, pick remote largefile
441 pas and lfile in pas[0] and
442 not pas[0][lfile].cmp(p1[lfile]) or
443 # if remote has unchanged largefile, pick local normal file
444 not (pas and standin in pas[0] and
445 not pas[0][standin].cmp(p2[standin])) and
446 # else, prompt
447 repo.ui.promptchoice(msg, 0) == 0
448 ): # pick remote largefile
441 actions['r'].append((lfile, None, msg))
449 actions['r'].append((lfile, None, msg))
442 newglist.append((standin, (p2.flags(standin),), msg))
450 newglist.append((standin, (p2.flags(standin),), msg))
443 else:
451 else: # keep local normal file
444 actions['r'].append((standin, None, msg))
452 actions['r'].append((standin, None, msg))
445 elif lfutil.standin(f) in p1 and lfutil.standin(f) not in removes:
453 elif lfutil.standin(f) in p1 and lfutil.standin(f) not in removes:
446 # Case 2: largefile in the working copy, normal file in
454 # Case 2: largefile in the working copy, normal file in
447 # the second parent
455 # the second parent
448 standin = lfutil.standin(f)
456 standin = lfutil.standin(f)
449 lfile = f
457 lfile = f
450 msg = _('remote turned local largefile %s into a normal file\n'
458 msg = _('remote turned local largefile %s into a normal file\n'
451 'keep (l)argefile or use (n)ormal file?'
459 'keep (l)argefile or use (n)ormal file?'
452 '$$ &Largefile $$ &Normal file') % lfile
460 '$$ &Largefile $$ &Normal file') % lfile
453 if repo.ui.promptchoice(msg, 0) == 0:
461 if (# if remote has unchanged normal file, pick local largefile
462 pas and f in pas[0] and
463 not pas[0][f].cmp(p2[f]) or
464 # if local has unchanged largefile, pick remote normal file
465 not (pas and standin in pas[0] and
466 not pas[0][standin].cmp(p1[standin])) and
467 # else, prompt
468 repo.ui.promptchoice(msg, 0) == 0
469 ): # keep local largefile
454 if branchmerge:
470 if branchmerge:
455 # largefile can be restored from standin safely
471 # largefile can be restored from standin safely
456 actions['r'].append((lfile, None, msg))
472 actions['r'].append((lfile, None, msg))
457 else:
473 else:
458 # "lfile" should be marked as "removed" without
474 # "lfile" should be marked as "removed" without
459 # removal of itself
475 # removal of itself
460 lfmr.append((lfile, None, msg))
476 lfmr.append((lfile, None, msg))
461
477
462 # linear-merge should treat this largefile as 're-added'
478 # linear-merge should treat this largefile as 're-added'
463 actions['a'].append((standin, None, msg))
479 actions['a'].append((standin, None, msg))
464 else:
480 else: # pick remote normal file
465 actions['r'].append((standin, None, msg))
481 actions['r'].append((standin, None, msg))
466 newglist.append((lfile, (p2.flags(lfile),), msg))
482 newglist.append((lfile, (p2.flags(lfile),), msg))
467 else:
483 else:
468 newglist.append(action)
484 newglist.append(action)
469
485
470 newglist.sort()
486 newglist.sort()
471 actions['g'] = newglist
487 actions['g'] = newglist
472 if lfmr:
488 if lfmr:
473 lfmr.sort()
489 lfmr.sort()
474 actions['lfmr'] = lfmr
490 actions['lfmr'] = lfmr
475
491
476 return actions
492 return actions
477
493
478 def mergerecordupdates(orig, repo, actions, branchmerge):
494 def mergerecordupdates(orig, repo, actions, branchmerge):
479 if 'lfmr' in actions:
495 if 'lfmr' in actions:
480 # this should be executed before 'orig', to execute 'remove'
496 # this should be executed before 'orig', to execute 'remove'
481 # before all other actions
497 # before all other actions
482 for lfile, args, msg in actions['lfmr']:
498 for lfile, args, msg in actions['lfmr']:
483 repo.dirstate.remove(lfile)
499 repo.dirstate.remove(lfile)
484
500
485 return orig(repo, actions, branchmerge)
501 return orig(repo, actions, branchmerge)
486
502
487
503
488 # Override filemerge to prompt the user about how they wish to merge
504 # Override filemerge to prompt the user about how they wish to merge
489 # largefiles. This will handle identical edits without prompting the user.
505 # largefiles. This will handle identical edits without prompting the user.
490 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca, labels=None):
506 def overridefilemerge(origfn, repo, mynode, orig, fcd, fco, fca, labels=None):
491 if not lfutil.isstandin(orig):
507 if not lfutil.isstandin(orig):
492 return origfn(repo, mynode, orig, fcd, fco, fca, labels=labels)
508 return origfn(repo, mynode, orig, fcd, fco, fca, labels=labels)
493
509
494 ahash = fca.data().strip().lower()
510 ahash = fca.data().strip().lower()
495 dhash = fcd.data().strip().lower()
511 dhash = fcd.data().strip().lower()
496 ohash = fco.data().strip().lower()
512 ohash = fco.data().strip().lower()
497 if (ohash != ahash and
513 if (ohash != ahash and
498 ohash != dhash and
514 ohash != dhash and
499 (dhash == ahash or
515 (dhash == ahash or
500 repo.ui.promptchoice(
516 repo.ui.promptchoice(
501 _('largefile %s has a merge conflict\nancestor was %s\n'
517 _('largefile %s has a merge conflict\nancestor was %s\n'
502 'keep (l)ocal %s or\ntake (o)ther %s?'
518 'keep (l)ocal %s or\ntake (o)ther %s?'
503 '$$ &Local $$ &Other') %
519 '$$ &Local $$ &Other') %
504 (lfutil.splitstandin(orig), ahash, dhash, ohash),
520 (lfutil.splitstandin(orig), ahash, dhash, ohash),
505 0) == 1)):
521 0) == 1)):
506 repo.wwrite(fcd.path(), fco.data(), fco.flags())
522 repo.wwrite(fcd.path(), fco.data(), fco.flags())
507 return 0
523 return 0
508
524
509 # Copy first changes the matchers to match standins instead of
525 # Copy first changes the matchers to match standins instead of
510 # largefiles. Then it overrides util.copyfile in that function it
526 # largefiles. Then it overrides util.copyfile in that function it
511 # checks if the destination largefile already exists. It also keeps a
527 # checks if the destination largefile already exists. It also keeps a
512 # list of copied files so that the largefiles can be copied and the
528 # list of copied files so that the largefiles can be copied and the
513 # dirstate updated.
529 # dirstate updated.
514 def overridecopy(orig, ui, repo, pats, opts, rename=False):
530 def overridecopy(orig, ui, repo, pats, opts, rename=False):
515 # doesn't remove largefile on rename
531 # doesn't remove largefile on rename
516 if len(pats) < 2:
532 if len(pats) < 2:
517 # this isn't legal, let the original function deal with it
533 # this isn't legal, let the original function deal with it
518 return orig(ui, repo, pats, opts, rename)
534 return orig(ui, repo, pats, opts, rename)
519
535
520 def makestandin(relpath):
536 def makestandin(relpath):
521 path = pathutil.canonpath(repo.root, repo.getcwd(), relpath)
537 path = pathutil.canonpath(repo.root, repo.getcwd(), relpath)
522 return os.path.join(repo.wjoin(lfutil.standin(path)))
538 return os.path.join(repo.wjoin(lfutil.standin(path)))
523
539
524 fullpats = scmutil.expandpats(pats)
540 fullpats = scmutil.expandpats(pats)
525 dest = fullpats[-1]
541 dest = fullpats[-1]
526
542
527 if os.path.isdir(dest):
543 if os.path.isdir(dest):
528 if not os.path.isdir(makestandin(dest)):
544 if not os.path.isdir(makestandin(dest)):
529 os.makedirs(makestandin(dest))
545 os.makedirs(makestandin(dest))
530 # This could copy both lfiles and normal files in one command,
546 # This could copy both lfiles and normal files in one command,
531 # but we don't want to do that. First replace their matcher to
547 # but we don't want to do that. First replace their matcher to
532 # only match normal files and run it, then replace it to just
548 # only match normal files and run it, then replace it to just
533 # match largefiles and run it again.
549 # match largefiles and run it again.
534 nonormalfiles = False
550 nonormalfiles = False
535 nolfiles = False
551 nolfiles = False
536 installnormalfilesmatchfn(repo[None].manifest())
552 installnormalfilesmatchfn(repo[None].manifest())
537 try:
553 try:
538 try:
554 try:
539 result = orig(ui, repo, pats, opts, rename)
555 result = orig(ui, repo, pats, opts, rename)
540 except util.Abort, e:
556 except util.Abort, e:
541 if str(e) != _('no files to copy'):
557 if str(e) != _('no files to copy'):
542 raise e
558 raise e
543 else:
559 else:
544 nonormalfiles = True
560 nonormalfiles = True
545 result = 0
561 result = 0
546 finally:
562 finally:
547 restorematchfn()
563 restorematchfn()
548
564
549 # The first rename can cause our current working directory to be removed.
565 # The first rename can cause our current working directory to be removed.
550 # In that case there is nothing left to copy/rename so just quit.
566 # In that case there is nothing left to copy/rename so just quit.
551 try:
567 try:
552 repo.getcwd()
568 repo.getcwd()
553 except OSError:
569 except OSError:
554 return result
570 return result
555
571
556 try:
572 try:
557 try:
573 try:
558 # When we call orig below it creates the standins but we don't add
574 # When we call orig below it creates the standins but we don't add
559 # them to the dir state until later so lock during that time.
575 # them to the dir state until later so lock during that time.
560 wlock = repo.wlock()
576 wlock = repo.wlock()
561
577
562 manifest = repo[None].manifest()
578 manifest = repo[None].manifest()
563 def overridematch(ctx, pats=[], opts={}, globbed=False,
579 def overridematch(ctx, pats=[], opts={}, globbed=False,
564 default='relpath'):
580 default='relpath'):
565 newpats = []
581 newpats = []
566 # The patterns were previously mangled to add the standin
582 # The patterns were previously mangled to add the standin
567 # directory; we need to remove that now
583 # directory; we need to remove that now
568 for pat in pats:
584 for pat in pats:
569 if match_.patkind(pat) is None and lfutil.shortname in pat:
585 if match_.patkind(pat) is None and lfutil.shortname in pat:
570 newpats.append(pat.replace(lfutil.shortname, ''))
586 newpats.append(pat.replace(lfutil.shortname, ''))
571 else:
587 else:
572 newpats.append(pat)
588 newpats.append(pat)
573 match = oldmatch(ctx, newpats, opts, globbed, default)
589 match = oldmatch(ctx, newpats, opts, globbed, default)
574 m = copy.copy(match)
590 m = copy.copy(match)
575 lfile = lambda f: lfutil.standin(f) in manifest
591 lfile = lambda f: lfutil.standin(f) in manifest
576 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
592 m._files = [lfutil.standin(f) for f in m._files if lfile(f)]
577 m._fmap = set(m._files)
593 m._fmap = set(m._files)
578 origmatchfn = m.matchfn
594 origmatchfn = m.matchfn
579 m.matchfn = lambda f: (lfutil.isstandin(f) and
595 m.matchfn = lambda f: (lfutil.isstandin(f) and
580 (f in manifest) and
596 (f in manifest) and
581 origmatchfn(lfutil.splitstandin(f)) or
597 origmatchfn(lfutil.splitstandin(f)) or
582 None)
598 None)
583 return m
599 return m
584 oldmatch = installmatchfn(overridematch)
600 oldmatch = installmatchfn(overridematch)
585 listpats = []
601 listpats = []
586 for pat in pats:
602 for pat in pats:
587 if match_.patkind(pat) is not None:
603 if match_.patkind(pat) is not None:
588 listpats.append(pat)
604 listpats.append(pat)
589 else:
605 else:
590 listpats.append(makestandin(pat))
606 listpats.append(makestandin(pat))
591
607
592 try:
608 try:
593 origcopyfile = util.copyfile
609 origcopyfile = util.copyfile
594 copiedfiles = []
610 copiedfiles = []
595 def overridecopyfile(src, dest):
611 def overridecopyfile(src, dest):
596 if (lfutil.shortname in src and
612 if (lfutil.shortname in src and
597 dest.startswith(repo.wjoin(lfutil.shortname))):
613 dest.startswith(repo.wjoin(lfutil.shortname))):
598 destlfile = dest.replace(lfutil.shortname, '')
614 destlfile = dest.replace(lfutil.shortname, '')
599 if not opts['force'] and os.path.exists(destlfile):
615 if not opts['force'] and os.path.exists(destlfile):
600 raise IOError('',
616 raise IOError('',
601 _('destination largefile already exists'))
617 _('destination largefile already exists'))
602 copiedfiles.append((src, dest))
618 copiedfiles.append((src, dest))
603 origcopyfile(src, dest)
619 origcopyfile(src, dest)
604
620
605 util.copyfile = overridecopyfile
621 util.copyfile = overridecopyfile
606 result += orig(ui, repo, listpats, opts, rename)
622 result += orig(ui, repo, listpats, opts, rename)
607 finally:
623 finally:
608 util.copyfile = origcopyfile
624 util.copyfile = origcopyfile
609
625
610 lfdirstate = lfutil.openlfdirstate(ui, repo)
626 lfdirstate = lfutil.openlfdirstate(ui, repo)
611 for (src, dest) in copiedfiles:
627 for (src, dest) in copiedfiles:
612 if (lfutil.shortname in src and
628 if (lfutil.shortname in src and
613 dest.startswith(repo.wjoin(lfutil.shortname))):
629 dest.startswith(repo.wjoin(lfutil.shortname))):
614 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
630 srclfile = src.replace(repo.wjoin(lfutil.standin('')), '')
615 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
631 destlfile = dest.replace(repo.wjoin(lfutil.standin('')), '')
616 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
632 destlfiledir = os.path.dirname(repo.wjoin(destlfile)) or '.'
617 if not os.path.isdir(destlfiledir):
633 if not os.path.isdir(destlfiledir):
618 os.makedirs(destlfiledir)
634 os.makedirs(destlfiledir)
619 if rename:
635 if rename:
620 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
636 os.rename(repo.wjoin(srclfile), repo.wjoin(destlfile))
621
637
622 # The file is gone, but this deletes any empty parent
638 # The file is gone, but this deletes any empty parent
623 # directories as a side-effect.
639 # directories as a side-effect.
624 util.unlinkpath(repo.wjoin(srclfile), True)
640 util.unlinkpath(repo.wjoin(srclfile), True)
625 lfdirstate.remove(srclfile)
641 lfdirstate.remove(srclfile)
626 else:
642 else:
627 util.copyfile(repo.wjoin(srclfile),
643 util.copyfile(repo.wjoin(srclfile),
628 repo.wjoin(destlfile))
644 repo.wjoin(destlfile))
629
645
630 lfdirstate.add(destlfile)
646 lfdirstate.add(destlfile)
631 lfdirstate.write()
647 lfdirstate.write()
632 except util.Abort, e:
648 except util.Abort, e:
633 if str(e) != _('no files to copy'):
649 if str(e) != _('no files to copy'):
634 raise e
650 raise e
635 else:
651 else:
636 nolfiles = True
652 nolfiles = True
637 finally:
653 finally:
638 restorematchfn()
654 restorematchfn()
639 wlock.release()
655 wlock.release()
640
656
641 if nolfiles and nonormalfiles:
657 if nolfiles and nonormalfiles:
642 raise util.Abort(_('no files to copy'))
658 raise util.Abort(_('no files to copy'))
643
659
644 return result
660 return result
645
661
646 # When the user calls revert, we have to be careful to not revert any
662 # When the user calls revert, we have to be careful to not revert any
647 # changes to other largefiles accidentally. This means we have to keep
663 # changes to other largefiles accidentally. This means we have to keep
648 # track of the largefiles that are being reverted so we only pull down
664 # track of the largefiles that are being reverted so we only pull down
649 # the necessary largefiles.
665 # the necessary largefiles.
650 #
666 #
651 # Standins are only updated (to match the hash of largefiles) before
667 # Standins are only updated (to match the hash of largefiles) before
652 # commits. Update the standins then run the original revert, changing
668 # commits. Update the standins then run the original revert, changing
653 # the matcher to hit standins instead of largefiles. Based on the
669 # the matcher to hit standins instead of largefiles. Based on the
654 # resulting standins update the largefiles.
670 # resulting standins update the largefiles.
655 def overriderevert(orig, ui, repo, *pats, **opts):
671 def overriderevert(orig, ui, repo, *pats, **opts):
656 # Because we put the standins in a bad state (by updating them)
672 # Because we put the standins in a bad state (by updating them)
657 # and then return them to a correct state we need to lock to
673 # and then return them to a correct state we need to lock to
658 # prevent others from changing them in their incorrect state.
674 # prevent others from changing them in their incorrect state.
659 wlock = repo.wlock()
675 wlock = repo.wlock()
660 try:
676 try:
661 lfdirstate = lfutil.openlfdirstate(ui, repo)
677 lfdirstate = lfutil.openlfdirstate(ui, repo)
662 s = lfutil.lfdirstatestatus(lfdirstate, repo)
678 s = lfutil.lfdirstatestatus(lfdirstate, repo)
663 lfdirstate.write()
679 lfdirstate.write()
664 for lfile in s.modified:
680 for lfile in s.modified:
665 lfutil.updatestandin(repo, lfutil.standin(lfile))
681 lfutil.updatestandin(repo, lfutil.standin(lfile))
666 for lfile in s.deleted:
682 for lfile in s.deleted:
667 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
683 if (os.path.exists(repo.wjoin(lfutil.standin(lfile)))):
668 os.unlink(repo.wjoin(lfutil.standin(lfile)))
684 os.unlink(repo.wjoin(lfutil.standin(lfile)))
669
685
670 oldstandins = lfutil.getstandinsstate(repo)
686 oldstandins = lfutil.getstandinsstate(repo)
671
687
672 def overridematch(ctx, pats=[], opts={}, globbed=False,
688 def overridematch(ctx, pats=[], opts={}, globbed=False,
673 default='relpath'):
689 default='relpath'):
674 match = oldmatch(ctx, pats, opts, globbed, default)
690 match = oldmatch(ctx, pats, opts, globbed, default)
675 m = copy.copy(match)
691 m = copy.copy(match)
676 def tostandin(f):
692 def tostandin(f):
677 if lfutil.standin(f) in ctx:
693 if lfutil.standin(f) in ctx:
678 return lfutil.standin(f)
694 return lfutil.standin(f)
679 elif lfutil.standin(f) in repo[None]:
695 elif lfutil.standin(f) in repo[None]:
680 return None
696 return None
681 return f
697 return f
682 m._files = [tostandin(f) for f in m._files]
698 m._files = [tostandin(f) for f in m._files]
683 m._files = [f for f in m._files if f is not None]
699 m._files = [f for f in m._files if f is not None]
684 m._fmap = set(m._files)
700 m._fmap = set(m._files)
685 origmatchfn = m.matchfn
701 origmatchfn = m.matchfn
686 def matchfn(f):
702 def matchfn(f):
687 if lfutil.isstandin(f):
703 if lfutil.isstandin(f):
688 return (origmatchfn(lfutil.splitstandin(f)) and
704 return (origmatchfn(lfutil.splitstandin(f)) and
689 (f in repo[None] or f in ctx))
705 (f in repo[None] or f in ctx))
690 return origmatchfn(f)
706 return origmatchfn(f)
691 m.matchfn = matchfn
707 m.matchfn = matchfn
692 return m
708 return m
693 oldmatch = installmatchfn(overridematch)
709 oldmatch = installmatchfn(overridematch)
694 try:
710 try:
695 orig(ui, repo, *pats, **opts)
711 orig(ui, repo, *pats, **opts)
696 finally:
712 finally:
697 restorematchfn()
713 restorematchfn()
698
714
699 newstandins = lfutil.getstandinsstate(repo)
715 newstandins = lfutil.getstandinsstate(repo)
700 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
716 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
701 # lfdirstate should be 'normallookup'-ed for updated files,
717 # lfdirstate should be 'normallookup'-ed for updated files,
702 # because reverting doesn't touch dirstate for 'normal' files
718 # because reverting doesn't touch dirstate for 'normal' files
703 # when target revision is explicitly specified: in such case,
719 # when target revision is explicitly specified: in such case,
704 # 'n' and valid timestamp in dirstate doesn't ensure 'clean'
720 # 'n' and valid timestamp in dirstate doesn't ensure 'clean'
705 # of target (standin) file.
721 # of target (standin) file.
706 lfcommands.updatelfiles(ui, repo, filelist, printmessage=False,
722 lfcommands.updatelfiles(ui, repo, filelist, printmessage=False,
707 normallookup=True)
723 normallookup=True)
708
724
709 finally:
725 finally:
710 wlock.release()
726 wlock.release()
711
727
712 # after pulling changesets, we need to take some extra care to get
728 # after pulling changesets, we need to take some extra care to get
713 # largefiles updated remotely
729 # largefiles updated remotely
714 def overridepull(orig, ui, repo, source=None, **opts):
730 def overridepull(orig, ui, repo, source=None, **opts):
715 revsprepull = len(repo)
731 revsprepull = len(repo)
716 if not source:
732 if not source:
717 source = 'default'
733 source = 'default'
718 repo.lfpullsource = source
734 repo.lfpullsource = source
719 result = orig(ui, repo, source, **opts)
735 result = orig(ui, repo, source, **opts)
720 revspostpull = len(repo)
736 revspostpull = len(repo)
721 lfrevs = opts.get('lfrev', [])
737 lfrevs = opts.get('lfrev', [])
722 if opts.get('all_largefiles'):
738 if opts.get('all_largefiles'):
723 lfrevs.append('pulled()')
739 lfrevs.append('pulled()')
724 if lfrevs and revspostpull > revsprepull:
740 if lfrevs and revspostpull > revsprepull:
725 numcached = 0
741 numcached = 0
726 repo.firstpulled = revsprepull # for pulled() revset expression
742 repo.firstpulled = revsprepull # for pulled() revset expression
727 try:
743 try:
728 for rev in scmutil.revrange(repo, lfrevs):
744 for rev in scmutil.revrange(repo, lfrevs):
729 ui.note(_('pulling largefiles for revision %s\n') % rev)
745 ui.note(_('pulling largefiles for revision %s\n') % rev)
730 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev)
746 (cached, missing) = lfcommands.cachelfiles(ui, repo, rev)
731 numcached += len(cached)
747 numcached += len(cached)
732 finally:
748 finally:
733 del repo.firstpulled
749 del repo.firstpulled
734 ui.status(_("%d largefiles cached\n") % numcached)
750 ui.status(_("%d largefiles cached\n") % numcached)
735 return result
751 return result
736
752
737 def pulledrevsetsymbol(repo, subset, x):
753 def pulledrevsetsymbol(repo, subset, x):
738 """``pulled()``
754 """``pulled()``
739 Changesets that just has been pulled.
755 Changesets that just has been pulled.
740
756
741 Only available with largefiles from pull --lfrev expressions.
757 Only available with largefiles from pull --lfrev expressions.
742
758
743 .. container:: verbose
759 .. container:: verbose
744
760
745 Some examples:
761 Some examples:
746
762
747 - pull largefiles for all new changesets::
763 - pull largefiles for all new changesets::
748
764
749 hg pull -lfrev "pulled()"
765 hg pull -lfrev "pulled()"
750
766
751 - pull largefiles for all new branch heads::
767 - pull largefiles for all new branch heads::
752
768
753 hg pull -lfrev "head(pulled()) and not closed()"
769 hg pull -lfrev "head(pulled()) and not closed()"
754
770
755 """
771 """
756
772
757 try:
773 try:
758 firstpulled = repo.firstpulled
774 firstpulled = repo.firstpulled
759 except AttributeError:
775 except AttributeError:
760 raise util.Abort(_("pulled() only available in --lfrev"))
776 raise util.Abort(_("pulled() only available in --lfrev"))
761 return revset.baseset([r for r in subset if r >= firstpulled])
777 return revset.baseset([r for r in subset if r >= firstpulled])
762
778
763 def overrideclone(orig, ui, source, dest=None, **opts):
779 def overrideclone(orig, ui, source, dest=None, **opts):
764 d = dest
780 d = dest
765 if d is None:
781 if d is None:
766 d = hg.defaultdest(source)
782 d = hg.defaultdest(source)
767 if opts.get('all_largefiles') and not hg.islocal(d):
783 if opts.get('all_largefiles') and not hg.islocal(d):
768 raise util.Abort(_(
784 raise util.Abort(_(
769 '--all-largefiles is incompatible with non-local destination %s') %
785 '--all-largefiles is incompatible with non-local destination %s') %
770 d)
786 d)
771
787
772 return orig(ui, source, dest, **opts)
788 return orig(ui, source, dest, **opts)
773
789
774 def hgclone(orig, ui, opts, *args, **kwargs):
790 def hgclone(orig, ui, opts, *args, **kwargs):
775 result = orig(ui, opts, *args, **kwargs)
791 result = orig(ui, opts, *args, **kwargs)
776
792
777 if result is not None:
793 if result is not None:
778 sourcerepo, destrepo = result
794 sourcerepo, destrepo = result
779 repo = destrepo.local()
795 repo = destrepo.local()
780
796
781 # Caching is implicitly limited to 'rev' option, since the dest repo was
797 # Caching is implicitly limited to 'rev' option, since the dest repo was
782 # truncated at that point. The user may expect a download count with
798 # truncated at that point. The user may expect a download count with
783 # this option, so attempt whether or not this is a largefile repo.
799 # this option, so attempt whether or not this is a largefile repo.
784 if opts.get('all_largefiles'):
800 if opts.get('all_largefiles'):
785 success, missing = lfcommands.downloadlfiles(ui, repo, None)
801 success, missing = lfcommands.downloadlfiles(ui, repo, None)
786
802
787 if missing != 0:
803 if missing != 0:
788 return None
804 return None
789
805
790 return result
806 return result
791
807
792 def overriderebase(orig, ui, repo, **opts):
808 def overriderebase(orig, ui, repo, **opts):
793 resuming = opts.get('continue')
809 resuming = opts.get('continue')
794 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
810 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
795 repo._lfstatuswriters.append(lambda *msg, **opts: None)
811 repo._lfstatuswriters.append(lambda *msg, **opts: None)
796 try:
812 try:
797 return orig(ui, repo, **opts)
813 return orig(ui, repo, **opts)
798 finally:
814 finally:
799 repo._lfstatuswriters.pop()
815 repo._lfstatuswriters.pop()
800 repo._lfcommithooks.pop()
816 repo._lfcommithooks.pop()
801
817
802 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
818 def overridearchive(orig, repo, dest, node, kind, decode=True, matchfn=None,
803 prefix=None, mtime=None, subrepos=None):
819 prefix=None, mtime=None, subrepos=None):
804 # No need to lock because we are only reading history and
820 # No need to lock because we are only reading history and
805 # largefile caches, neither of which are modified.
821 # largefile caches, neither of which are modified.
806 lfcommands.cachelfiles(repo.ui, repo, node)
822 lfcommands.cachelfiles(repo.ui, repo, node)
807
823
808 if kind not in archival.archivers:
824 if kind not in archival.archivers:
809 raise util.Abort(_("unknown archive type '%s'") % kind)
825 raise util.Abort(_("unknown archive type '%s'") % kind)
810
826
811 ctx = repo[node]
827 ctx = repo[node]
812
828
813 if kind == 'files':
829 if kind == 'files':
814 if prefix:
830 if prefix:
815 raise util.Abort(
831 raise util.Abort(
816 _('cannot give prefix when archiving to files'))
832 _('cannot give prefix when archiving to files'))
817 else:
833 else:
818 prefix = archival.tidyprefix(dest, kind, prefix)
834 prefix = archival.tidyprefix(dest, kind, prefix)
819
835
820 def write(name, mode, islink, getdata):
836 def write(name, mode, islink, getdata):
821 if matchfn and not matchfn(name):
837 if matchfn and not matchfn(name):
822 return
838 return
823 data = getdata()
839 data = getdata()
824 if decode:
840 if decode:
825 data = repo.wwritedata(name, data)
841 data = repo.wwritedata(name, data)
826 archiver.addfile(prefix + name, mode, islink, data)
842 archiver.addfile(prefix + name, mode, islink, data)
827
843
828 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
844 archiver = archival.archivers[kind](dest, mtime or ctx.date()[0])
829
845
830 if repo.ui.configbool("ui", "archivemeta", True):
846 if repo.ui.configbool("ui", "archivemeta", True):
831 def metadata():
847 def metadata():
832 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
848 base = 'repo: %s\nnode: %s\nbranch: %s\n' % (
833 hex(repo.changelog.node(0)), hex(node), ctx.branch())
849 hex(repo.changelog.node(0)), hex(node), ctx.branch())
834
850
835 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
851 tags = ''.join('tag: %s\n' % t for t in ctx.tags()
836 if repo.tagtype(t) == 'global')
852 if repo.tagtype(t) == 'global')
837 if not tags:
853 if not tags:
838 repo.ui.pushbuffer()
854 repo.ui.pushbuffer()
839 opts = {'template': '{latesttag}\n{latesttagdistance}',
855 opts = {'template': '{latesttag}\n{latesttagdistance}',
840 'style': '', 'patch': None, 'git': None}
856 'style': '', 'patch': None, 'git': None}
841 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
857 cmdutil.show_changeset(repo.ui, repo, opts).show(ctx)
842 ltags, dist = repo.ui.popbuffer().split('\n')
858 ltags, dist = repo.ui.popbuffer().split('\n')
843 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
859 tags = ''.join('latesttag: %s\n' % t for t in ltags.split(':'))
844 tags += 'latesttagdistance: %s\n' % dist
860 tags += 'latesttagdistance: %s\n' % dist
845
861
846 return base + tags
862 return base + tags
847
863
848 write('.hg_archival.txt', 0644, False, metadata)
864 write('.hg_archival.txt', 0644, False, metadata)
849
865
850 for f in ctx:
866 for f in ctx:
851 ff = ctx.flags(f)
867 ff = ctx.flags(f)
852 getdata = ctx[f].data
868 getdata = ctx[f].data
853 if lfutil.isstandin(f):
869 if lfutil.isstandin(f):
854 path = lfutil.findfile(repo, getdata().strip())
870 path = lfutil.findfile(repo, getdata().strip())
855 if path is None:
871 if path is None:
856 raise util.Abort(
872 raise util.Abort(
857 _('largefile %s not found in repo store or system cache')
873 _('largefile %s not found in repo store or system cache')
858 % lfutil.splitstandin(f))
874 % lfutil.splitstandin(f))
859 f = lfutil.splitstandin(f)
875 f = lfutil.splitstandin(f)
860
876
861 def getdatafn():
877 def getdatafn():
862 fd = None
878 fd = None
863 try:
879 try:
864 fd = open(path, 'rb')
880 fd = open(path, 'rb')
865 return fd.read()
881 return fd.read()
866 finally:
882 finally:
867 if fd:
883 if fd:
868 fd.close()
884 fd.close()
869
885
870 getdata = getdatafn
886 getdata = getdatafn
871 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
887 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
872
888
873 if subrepos:
889 if subrepos:
874 for subpath in sorted(ctx.substate):
890 for subpath in sorted(ctx.substate):
875 sub = ctx.sub(subpath)
891 sub = ctx.sub(subpath)
876 submatch = match_.narrowmatcher(subpath, matchfn)
892 submatch = match_.narrowmatcher(subpath, matchfn)
877 sub.archive(repo.ui, archiver, prefix, submatch)
893 sub.archive(repo.ui, archiver, prefix, submatch)
878
894
879 archiver.done()
895 archiver.done()
880
896
881 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
897 def hgsubrepoarchive(orig, repo, ui, archiver, prefix, match=None):
882 repo._get(repo._state + ('hg',))
898 repo._get(repo._state + ('hg',))
883 rev = repo._state[1]
899 rev = repo._state[1]
884 ctx = repo._repo[rev]
900 ctx = repo._repo[rev]
885
901
886 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
902 lfcommands.cachelfiles(ui, repo._repo, ctx.node())
887
903
888 def write(name, mode, islink, getdata):
904 def write(name, mode, islink, getdata):
889 # At this point, the standin has been replaced with the largefile name,
905 # At this point, the standin has been replaced with the largefile name,
890 # so the normal matcher works here without the lfutil variants.
906 # so the normal matcher works here without the lfutil variants.
891 if match and not match(f):
907 if match and not match(f):
892 return
908 return
893 data = getdata()
909 data = getdata()
894
910
895 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
911 archiver.addfile(prefix + repo._path + '/' + name, mode, islink, data)
896
912
897 for f in ctx:
913 for f in ctx:
898 ff = ctx.flags(f)
914 ff = ctx.flags(f)
899 getdata = ctx[f].data
915 getdata = ctx[f].data
900 if lfutil.isstandin(f):
916 if lfutil.isstandin(f):
901 path = lfutil.findfile(repo._repo, getdata().strip())
917 path = lfutil.findfile(repo._repo, getdata().strip())
902 if path is None:
918 if path is None:
903 raise util.Abort(
919 raise util.Abort(
904 _('largefile %s not found in repo store or system cache')
920 _('largefile %s not found in repo store or system cache')
905 % lfutil.splitstandin(f))
921 % lfutil.splitstandin(f))
906 f = lfutil.splitstandin(f)
922 f = lfutil.splitstandin(f)
907
923
908 def getdatafn():
924 def getdatafn():
909 fd = None
925 fd = None
910 try:
926 try:
911 fd = open(os.path.join(prefix, path), 'rb')
927 fd = open(os.path.join(prefix, path), 'rb')
912 return fd.read()
928 return fd.read()
913 finally:
929 finally:
914 if fd:
930 if fd:
915 fd.close()
931 fd.close()
916
932
917 getdata = getdatafn
933 getdata = getdatafn
918
934
919 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
935 write(f, 'x' in ff and 0755 or 0644, 'l' in ff, getdata)
920
936
921 for subpath in sorted(ctx.substate):
937 for subpath in sorted(ctx.substate):
922 sub = ctx.sub(subpath)
938 sub = ctx.sub(subpath)
923 submatch = match_.narrowmatcher(subpath, match)
939 submatch = match_.narrowmatcher(subpath, match)
924 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
940 sub.archive(ui, archiver, os.path.join(prefix, repo._path) + '/',
925 submatch)
941 submatch)
926
942
927 # If a largefile is modified, the change is not reflected in its
943 # If a largefile is modified, the change is not reflected in its
928 # standin until a commit. cmdutil.bailifchanged() raises an exception
944 # standin until a commit. cmdutil.bailifchanged() raises an exception
929 # if the repo has uncommitted changes. Wrap it to also check if
945 # if the repo has uncommitted changes. Wrap it to also check if
930 # largefiles were changed. This is used by bisect and backout.
946 # largefiles were changed. This is used by bisect and backout.
931 def overridebailifchanged(orig, repo):
947 def overridebailifchanged(orig, repo):
932 orig(repo)
948 orig(repo)
933 repo.lfstatus = True
949 repo.lfstatus = True
934 s = repo.status()
950 s = repo.status()
935 repo.lfstatus = False
951 repo.lfstatus = False
936 if s.modified or s.added or s.removed or s.deleted:
952 if s.modified or s.added or s.removed or s.deleted:
937 raise util.Abort(_('uncommitted changes'))
953 raise util.Abort(_('uncommitted changes'))
938
954
939 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
955 # Fetch doesn't use cmdutil.bailifchanged so override it to add the check
940 def overridefetch(orig, ui, repo, *pats, **opts):
956 def overridefetch(orig, ui, repo, *pats, **opts):
941 repo.lfstatus = True
957 repo.lfstatus = True
942 s = repo.status()
958 s = repo.status()
943 repo.lfstatus = False
959 repo.lfstatus = False
944 if s.modified or s.added or s.removed or s.deleted:
960 if s.modified or s.added or s.removed or s.deleted:
945 raise util.Abort(_('uncommitted changes'))
961 raise util.Abort(_('uncommitted changes'))
946 return orig(ui, repo, *pats, **opts)
962 return orig(ui, repo, *pats, **opts)
947
963
948 def overrideforget(orig, ui, repo, *pats, **opts):
964 def overrideforget(orig, ui, repo, *pats, **opts):
949 installnormalfilesmatchfn(repo[None].manifest())
965 installnormalfilesmatchfn(repo[None].manifest())
950 result = orig(ui, repo, *pats, **opts)
966 result = orig(ui, repo, *pats, **opts)
951 restorematchfn()
967 restorematchfn()
952 m = scmutil.match(repo[None], pats, opts)
968 m = scmutil.match(repo[None], pats, opts)
953
969
954 try:
970 try:
955 repo.lfstatus = True
971 repo.lfstatus = True
956 s = repo.status(match=m, clean=True)
972 s = repo.status(match=m, clean=True)
957 finally:
973 finally:
958 repo.lfstatus = False
974 repo.lfstatus = False
959 forget = sorted(s.modified + s.added + s.deleted + s.clean)
975 forget = sorted(s.modified + s.added + s.deleted + s.clean)
960 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
976 forget = [f for f in forget if lfutil.standin(f) in repo[None].manifest()]
961
977
962 for f in forget:
978 for f in forget:
963 if lfutil.standin(f) not in repo.dirstate and not \
979 if lfutil.standin(f) not in repo.dirstate and not \
964 os.path.isdir(m.rel(lfutil.standin(f))):
980 os.path.isdir(m.rel(lfutil.standin(f))):
965 ui.warn(_('not removing %s: file is already untracked\n')
981 ui.warn(_('not removing %s: file is already untracked\n')
966 % m.rel(f))
982 % m.rel(f))
967 result = 1
983 result = 1
968
984
969 for f in forget:
985 for f in forget:
970 if ui.verbose or not m.exact(f):
986 if ui.verbose or not m.exact(f):
971 ui.status(_('removing %s\n') % m.rel(f))
987 ui.status(_('removing %s\n') % m.rel(f))
972
988
973 # Need to lock because standin files are deleted then removed from the
989 # Need to lock because standin files are deleted then removed from the
974 # repository and we could race in-between.
990 # repository and we could race in-between.
975 wlock = repo.wlock()
991 wlock = repo.wlock()
976 try:
992 try:
977 lfdirstate = lfutil.openlfdirstate(ui, repo)
993 lfdirstate = lfutil.openlfdirstate(ui, repo)
978 for f in forget:
994 for f in forget:
979 if lfdirstate[f] == 'a':
995 if lfdirstate[f] == 'a':
980 lfdirstate.drop(f)
996 lfdirstate.drop(f)
981 else:
997 else:
982 lfdirstate.remove(f)
998 lfdirstate.remove(f)
983 lfdirstate.write()
999 lfdirstate.write()
984 standins = [lfutil.standin(f) for f in forget]
1000 standins = [lfutil.standin(f) for f in forget]
985 for f in standins:
1001 for f in standins:
986 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1002 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
987 repo[None].forget(standins)
1003 repo[None].forget(standins)
988 finally:
1004 finally:
989 wlock.release()
1005 wlock.release()
990
1006
991 return result
1007 return result
992
1008
993 def _getoutgoings(repo, other, missing, addfunc):
1009 def _getoutgoings(repo, other, missing, addfunc):
994 """get pairs of filename and largefile hash in outgoing revisions
1010 """get pairs of filename and largefile hash in outgoing revisions
995 in 'missing'.
1011 in 'missing'.
996
1012
997 largefiles already existing on 'other' repository are ignored.
1013 largefiles already existing on 'other' repository are ignored.
998
1014
999 'addfunc' is invoked with each unique pairs of filename and
1015 'addfunc' is invoked with each unique pairs of filename and
1000 largefile hash value.
1016 largefile hash value.
1001 """
1017 """
1002 knowns = set()
1018 knowns = set()
1003 lfhashes = set()
1019 lfhashes = set()
1004 def dedup(fn, lfhash):
1020 def dedup(fn, lfhash):
1005 k = (fn, lfhash)
1021 k = (fn, lfhash)
1006 if k not in knowns:
1022 if k not in knowns:
1007 knowns.add(k)
1023 knowns.add(k)
1008 lfhashes.add(lfhash)
1024 lfhashes.add(lfhash)
1009 lfutil.getlfilestoupload(repo, missing, dedup)
1025 lfutil.getlfilestoupload(repo, missing, dedup)
1010 if lfhashes:
1026 if lfhashes:
1011 lfexists = basestore._openstore(repo, other).exists(lfhashes)
1027 lfexists = basestore._openstore(repo, other).exists(lfhashes)
1012 for fn, lfhash in knowns:
1028 for fn, lfhash in knowns:
1013 if not lfexists[lfhash]: # lfhash doesn't exist on "other"
1029 if not lfexists[lfhash]: # lfhash doesn't exist on "other"
1014 addfunc(fn, lfhash)
1030 addfunc(fn, lfhash)
1015
1031
1016 def outgoinghook(ui, repo, other, opts, missing):
1032 def outgoinghook(ui, repo, other, opts, missing):
1017 if opts.pop('large', None):
1033 if opts.pop('large', None):
1018 lfhashes = set()
1034 lfhashes = set()
1019 if ui.debugflag:
1035 if ui.debugflag:
1020 toupload = {}
1036 toupload = {}
1021 def addfunc(fn, lfhash):
1037 def addfunc(fn, lfhash):
1022 if fn not in toupload:
1038 if fn not in toupload:
1023 toupload[fn] = []
1039 toupload[fn] = []
1024 toupload[fn].append(lfhash)
1040 toupload[fn].append(lfhash)
1025 lfhashes.add(lfhash)
1041 lfhashes.add(lfhash)
1026 def showhashes(fn):
1042 def showhashes(fn):
1027 for lfhash in sorted(toupload[fn]):
1043 for lfhash in sorted(toupload[fn]):
1028 ui.debug(' %s\n' % (lfhash))
1044 ui.debug(' %s\n' % (lfhash))
1029 else:
1045 else:
1030 toupload = set()
1046 toupload = set()
1031 def addfunc(fn, lfhash):
1047 def addfunc(fn, lfhash):
1032 toupload.add(fn)
1048 toupload.add(fn)
1033 lfhashes.add(lfhash)
1049 lfhashes.add(lfhash)
1034 def showhashes(fn):
1050 def showhashes(fn):
1035 pass
1051 pass
1036 _getoutgoings(repo, other, missing, addfunc)
1052 _getoutgoings(repo, other, missing, addfunc)
1037
1053
1038 if not toupload:
1054 if not toupload:
1039 ui.status(_('largefiles: no files to upload\n'))
1055 ui.status(_('largefiles: no files to upload\n'))
1040 else:
1056 else:
1041 ui.status(_('largefiles to upload (%d entities):\n')
1057 ui.status(_('largefiles to upload (%d entities):\n')
1042 % (len(lfhashes)))
1058 % (len(lfhashes)))
1043 for file in sorted(toupload):
1059 for file in sorted(toupload):
1044 ui.status(lfutil.splitstandin(file) + '\n')
1060 ui.status(lfutil.splitstandin(file) + '\n')
1045 showhashes(file)
1061 showhashes(file)
1046 ui.status('\n')
1062 ui.status('\n')
1047
1063
1048 def summaryremotehook(ui, repo, opts, changes):
1064 def summaryremotehook(ui, repo, opts, changes):
1049 largeopt = opts.get('large', False)
1065 largeopt = opts.get('large', False)
1050 if changes is None:
1066 if changes is None:
1051 if largeopt:
1067 if largeopt:
1052 return (False, True) # only outgoing check is needed
1068 return (False, True) # only outgoing check is needed
1053 else:
1069 else:
1054 return (False, False)
1070 return (False, False)
1055 elif largeopt:
1071 elif largeopt:
1056 url, branch, peer, outgoing = changes[1]
1072 url, branch, peer, outgoing = changes[1]
1057 if peer is None:
1073 if peer is None:
1058 # i18n: column positioning for "hg summary"
1074 # i18n: column positioning for "hg summary"
1059 ui.status(_('largefiles: (no remote repo)\n'))
1075 ui.status(_('largefiles: (no remote repo)\n'))
1060 return
1076 return
1061
1077
1062 toupload = set()
1078 toupload = set()
1063 lfhashes = set()
1079 lfhashes = set()
1064 def addfunc(fn, lfhash):
1080 def addfunc(fn, lfhash):
1065 toupload.add(fn)
1081 toupload.add(fn)
1066 lfhashes.add(lfhash)
1082 lfhashes.add(lfhash)
1067 _getoutgoings(repo, peer, outgoing.missing, addfunc)
1083 _getoutgoings(repo, peer, outgoing.missing, addfunc)
1068
1084
1069 if not toupload:
1085 if not toupload:
1070 # i18n: column positioning for "hg summary"
1086 # i18n: column positioning for "hg summary"
1071 ui.status(_('largefiles: (no files to upload)\n'))
1087 ui.status(_('largefiles: (no files to upload)\n'))
1072 else:
1088 else:
1073 # i18n: column positioning for "hg summary"
1089 # i18n: column positioning for "hg summary"
1074 ui.status(_('largefiles: %d entities for %d files to upload\n')
1090 ui.status(_('largefiles: %d entities for %d files to upload\n')
1075 % (len(lfhashes), len(toupload)))
1091 % (len(lfhashes), len(toupload)))
1076
1092
1077 def overridesummary(orig, ui, repo, *pats, **opts):
1093 def overridesummary(orig, ui, repo, *pats, **opts):
1078 try:
1094 try:
1079 repo.lfstatus = True
1095 repo.lfstatus = True
1080 orig(ui, repo, *pats, **opts)
1096 orig(ui, repo, *pats, **opts)
1081 finally:
1097 finally:
1082 repo.lfstatus = False
1098 repo.lfstatus = False
1083
1099
1084 def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
1100 def scmutiladdremove(orig, repo, pats=[], opts={}, dry_run=None,
1085 similarity=None):
1101 similarity=None):
1086 if not lfutil.islfilesrepo(repo):
1102 if not lfutil.islfilesrepo(repo):
1087 return orig(repo, pats, opts, dry_run, similarity)
1103 return orig(repo, pats, opts, dry_run, similarity)
1088 # Get the list of missing largefiles so we can remove them
1104 # Get the list of missing largefiles so we can remove them
1089 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1105 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1090 unsure, s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [],
1106 unsure, s = lfdirstate.status(match_.always(repo.root, repo.getcwd()), [],
1091 False, False, False)
1107 False, False, False)
1092
1108
1093 # Call into the normal remove code, but the removing of the standin, we want
1109 # Call into the normal remove code, but the removing of the standin, we want
1094 # to have handled by original addremove. Monkey patching here makes sure
1110 # to have handled by original addremove. Monkey patching here makes sure
1095 # we don't remove the standin in the largefiles code, preventing a very
1111 # we don't remove the standin in the largefiles code, preventing a very
1096 # confused state later.
1112 # confused state later.
1097 if s.deleted:
1113 if s.deleted:
1098 m = [repo.wjoin(f) for f in s.deleted]
1114 m = [repo.wjoin(f) for f in s.deleted]
1099 removelargefiles(repo.ui, repo, True, *m, **opts)
1115 removelargefiles(repo.ui, repo, True, *m, **opts)
1100 # Call into the normal add code, and any files that *should* be added as
1116 # Call into the normal add code, and any files that *should* be added as
1101 # largefiles will be
1117 # largefiles will be
1102 addlargefiles(repo.ui, repo, *pats, **opts)
1118 addlargefiles(repo.ui, repo, *pats, **opts)
1103 # Now that we've handled largefiles, hand off to the original addremove
1119 # Now that we've handled largefiles, hand off to the original addremove
1104 # function to take care of the rest. Make sure it doesn't do anything with
1120 # function to take care of the rest. Make sure it doesn't do anything with
1105 # largefiles by installing a matcher that will ignore them.
1121 # largefiles by installing a matcher that will ignore them.
1106 installnormalfilesmatchfn(repo[None].manifest())
1122 installnormalfilesmatchfn(repo[None].manifest())
1107 result = orig(repo, pats, opts, dry_run, similarity)
1123 result = orig(repo, pats, opts, dry_run, similarity)
1108 restorematchfn()
1124 restorematchfn()
1109 return result
1125 return result
1110
1126
1111 # Calling purge with --all will cause the largefiles to be deleted.
1127 # Calling purge with --all will cause the largefiles to be deleted.
1112 # Override repo.status to prevent this from happening.
1128 # Override repo.status to prevent this from happening.
1113 def overridepurge(orig, ui, repo, *dirs, **opts):
1129 def overridepurge(orig, ui, repo, *dirs, **opts):
1114 # XXX large file status is buggy when used on repo proxy.
1130 # XXX large file status is buggy when used on repo proxy.
1115 # XXX this needs to be investigate.
1131 # XXX this needs to be investigate.
1116 repo = repo.unfiltered()
1132 repo = repo.unfiltered()
1117 oldstatus = repo.status
1133 oldstatus = repo.status
1118 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1134 def overridestatus(node1='.', node2=None, match=None, ignored=False,
1119 clean=False, unknown=False, listsubrepos=False):
1135 clean=False, unknown=False, listsubrepos=False):
1120 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1136 r = oldstatus(node1, node2, match, ignored, clean, unknown,
1121 listsubrepos)
1137 listsubrepos)
1122 lfdirstate = lfutil.openlfdirstate(ui, repo)
1138 lfdirstate = lfutil.openlfdirstate(ui, repo)
1123 unknown = [f for f in r.unknown if lfdirstate[f] == '?']
1139 unknown = [f for f in r.unknown if lfdirstate[f] == '?']
1124 ignored = [f for f in r.ignored if lfdirstate[f] == '?']
1140 ignored = [f for f in r.ignored if lfdirstate[f] == '?']
1125 return scmutil.status(r.modified, r.added, r.removed, r.deleted,
1141 return scmutil.status(r.modified, r.added, r.removed, r.deleted,
1126 unknown, ignored, r.clean)
1142 unknown, ignored, r.clean)
1127 repo.status = overridestatus
1143 repo.status = overridestatus
1128 orig(ui, repo, *dirs, **opts)
1144 orig(ui, repo, *dirs, **opts)
1129 repo.status = oldstatus
1145 repo.status = oldstatus
1130 def overriderollback(orig, ui, repo, **opts):
1146 def overriderollback(orig, ui, repo, **opts):
1131 wlock = repo.wlock()
1147 wlock = repo.wlock()
1132 try:
1148 try:
1133 before = repo.dirstate.parents()
1149 before = repo.dirstate.parents()
1134 orphans = set(f for f in repo.dirstate
1150 orphans = set(f for f in repo.dirstate
1135 if lfutil.isstandin(f) and repo.dirstate[f] != 'r')
1151 if lfutil.isstandin(f) and repo.dirstate[f] != 'r')
1136 result = orig(ui, repo, **opts)
1152 result = orig(ui, repo, **opts)
1137 after = repo.dirstate.parents()
1153 after = repo.dirstate.parents()
1138 if before == after:
1154 if before == after:
1139 return result # no need to restore standins
1155 return result # no need to restore standins
1140
1156
1141 pctx = repo['.']
1157 pctx = repo['.']
1142 for f in repo.dirstate:
1158 for f in repo.dirstate:
1143 if lfutil.isstandin(f):
1159 if lfutil.isstandin(f):
1144 orphans.discard(f)
1160 orphans.discard(f)
1145 if repo.dirstate[f] == 'r':
1161 if repo.dirstate[f] == 'r':
1146 repo.wvfs.unlinkpath(f, ignoremissing=True)
1162 repo.wvfs.unlinkpath(f, ignoremissing=True)
1147 elif f in pctx:
1163 elif f in pctx:
1148 fctx = pctx[f]
1164 fctx = pctx[f]
1149 repo.wwrite(f, fctx.data(), fctx.flags())
1165 repo.wwrite(f, fctx.data(), fctx.flags())
1150 else:
1166 else:
1151 # content of standin is not so important in 'a',
1167 # content of standin is not so important in 'a',
1152 # 'm' or 'n' (coming from the 2nd parent) cases
1168 # 'm' or 'n' (coming from the 2nd parent) cases
1153 lfutil.writestandin(repo, f, '', False)
1169 lfutil.writestandin(repo, f, '', False)
1154 for standin in orphans:
1170 for standin in orphans:
1155 repo.wvfs.unlinkpath(standin, ignoremissing=True)
1171 repo.wvfs.unlinkpath(standin, ignoremissing=True)
1156
1172
1157 lfdirstate = lfutil.openlfdirstate(ui, repo)
1173 lfdirstate = lfutil.openlfdirstate(ui, repo)
1158 orphans = set(lfdirstate)
1174 orphans = set(lfdirstate)
1159 lfiles = lfutil.listlfiles(repo)
1175 lfiles = lfutil.listlfiles(repo)
1160 for file in lfiles:
1176 for file in lfiles:
1161 lfutil.synclfdirstate(repo, lfdirstate, file, True)
1177 lfutil.synclfdirstate(repo, lfdirstate, file, True)
1162 orphans.discard(file)
1178 orphans.discard(file)
1163 for lfile in orphans:
1179 for lfile in orphans:
1164 lfdirstate.drop(lfile)
1180 lfdirstate.drop(lfile)
1165 lfdirstate.write()
1181 lfdirstate.write()
1166 finally:
1182 finally:
1167 wlock.release()
1183 wlock.release()
1168 return result
1184 return result
1169
1185
1170 def overridetransplant(orig, ui, repo, *revs, **opts):
1186 def overridetransplant(orig, ui, repo, *revs, **opts):
1171 resuming = opts.get('continue')
1187 resuming = opts.get('continue')
1172 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
1188 repo._lfcommithooks.append(lfutil.automatedcommithook(resuming))
1173 repo._lfstatuswriters.append(lambda *msg, **opts: None)
1189 repo._lfstatuswriters.append(lambda *msg, **opts: None)
1174 try:
1190 try:
1175 result = orig(ui, repo, *revs, **opts)
1191 result = orig(ui, repo, *revs, **opts)
1176 finally:
1192 finally:
1177 repo._lfstatuswriters.pop()
1193 repo._lfstatuswriters.pop()
1178 repo._lfcommithooks.pop()
1194 repo._lfcommithooks.pop()
1179 return result
1195 return result
1180
1196
1181 def overridecat(orig, ui, repo, file1, *pats, **opts):
1197 def overridecat(orig, ui, repo, file1, *pats, **opts):
1182 ctx = scmutil.revsingle(repo, opts.get('rev'))
1198 ctx = scmutil.revsingle(repo, opts.get('rev'))
1183 err = 1
1199 err = 1
1184 notbad = set()
1200 notbad = set()
1185 m = scmutil.match(ctx, (file1,) + pats, opts)
1201 m = scmutil.match(ctx, (file1,) + pats, opts)
1186 origmatchfn = m.matchfn
1202 origmatchfn = m.matchfn
1187 def lfmatchfn(f):
1203 def lfmatchfn(f):
1188 if origmatchfn(f):
1204 if origmatchfn(f):
1189 return True
1205 return True
1190 lf = lfutil.splitstandin(f)
1206 lf = lfutil.splitstandin(f)
1191 if lf is None:
1207 if lf is None:
1192 return False
1208 return False
1193 notbad.add(lf)
1209 notbad.add(lf)
1194 return origmatchfn(lf)
1210 return origmatchfn(lf)
1195 m.matchfn = lfmatchfn
1211 m.matchfn = lfmatchfn
1196 origbadfn = m.bad
1212 origbadfn = m.bad
1197 def lfbadfn(f, msg):
1213 def lfbadfn(f, msg):
1198 if not f in notbad:
1214 if not f in notbad:
1199 origbadfn(f, msg)
1215 origbadfn(f, msg)
1200 m.bad = lfbadfn
1216 m.bad = lfbadfn
1201 for f in ctx.walk(m):
1217 for f in ctx.walk(m):
1202 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1218 fp = cmdutil.makefileobj(repo, opts.get('output'), ctx.node(),
1203 pathname=f)
1219 pathname=f)
1204 lf = lfutil.splitstandin(f)
1220 lf = lfutil.splitstandin(f)
1205 if lf is None or origmatchfn(f):
1221 if lf is None or origmatchfn(f):
1206 # duplicating unreachable code from commands.cat
1222 # duplicating unreachable code from commands.cat
1207 data = ctx[f].data()
1223 data = ctx[f].data()
1208 if opts.get('decode'):
1224 if opts.get('decode'):
1209 data = repo.wwritedata(f, data)
1225 data = repo.wwritedata(f, data)
1210 fp.write(data)
1226 fp.write(data)
1211 else:
1227 else:
1212 hash = lfutil.readstandin(repo, lf, ctx.rev())
1228 hash = lfutil.readstandin(repo, lf, ctx.rev())
1213 if not lfutil.inusercache(repo.ui, hash):
1229 if not lfutil.inusercache(repo.ui, hash):
1214 store = basestore._openstore(repo)
1230 store = basestore._openstore(repo)
1215 success, missing = store.get([(lf, hash)])
1231 success, missing = store.get([(lf, hash)])
1216 if len(success) != 1:
1232 if len(success) != 1:
1217 raise util.Abort(
1233 raise util.Abort(
1218 _('largefile %s is not in cache and could not be '
1234 _('largefile %s is not in cache and could not be '
1219 'downloaded') % lf)
1235 'downloaded') % lf)
1220 path = lfutil.usercachepath(repo.ui, hash)
1236 path = lfutil.usercachepath(repo.ui, hash)
1221 fpin = open(path, "rb")
1237 fpin = open(path, "rb")
1222 for chunk in util.filechunkiter(fpin, 128 * 1024):
1238 for chunk in util.filechunkiter(fpin, 128 * 1024):
1223 fp.write(chunk)
1239 fp.write(chunk)
1224 fpin.close()
1240 fpin.close()
1225 fp.close()
1241 fp.close()
1226 err = 0
1242 err = 0
1227 return err
1243 return err
1228
1244
1229 def mergeupdate(orig, repo, node, branchmerge, force, partial,
1245 def mergeupdate(orig, repo, node, branchmerge, force, partial,
1230 *args, **kwargs):
1246 *args, **kwargs):
1231 wlock = repo.wlock()
1247 wlock = repo.wlock()
1232 try:
1248 try:
1233 # branch | | |
1249 # branch | | |
1234 # merge | force | partial | action
1250 # merge | force | partial | action
1235 # -------+-------+---------+--------------
1251 # -------+-------+---------+--------------
1236 # x | x | x | linear-merge
1252 # x | x | x | linear-merge
1237 # o | x | x | branch-merge
1253 # o | x | x | branch-merge
1238 # x | o | x | overwrite (as clean update)
1254 # x | o | x | overwrite (as clean update)
1239 # o | o | x | force-branch-merge (*1)
1255 # o | o | x | force-branch-merge (*1)
1240 # x | x | o | (*)
1256 # x | x | o | (*)
1241 # o | x | o | (*)
1257 # o | x | o | (*)
1242 # x | o | o | overwrite (as revert)
1258 # x | o | o | overwrite (as revert)
1243 # o | o | o | (*)
1259 # o | o | o | (*)
1244 #
1260 #
1245 # (*) don't care
1261 # (*) don't care
1246 # (*1) deprecated, but used internally (e.g: "rebase --collapse")
1262 # (*1) deprecated, but used internally (e.g: "rebase --collapse")
1247
1263
1248 linearmerge = not branchmerge and not force and not partial
1264 linearmerge = not branchmerge and not force and not partial
1249
1265
1250 if linearmerge or (branchmerge and force and not partial):
1266 if linearmerge or (branchmerge and force and not partial):
1251 # update standins for linear-merge or force-branch-merge,
1267 # update standins for linear-merge or force-branch-merge,
1252 # because largefiles in the working directory may be modified
1268 # because largefiles in the working directory may be modified
1253 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1269 lfdirstate = lfutil.openlfdirstate(repo.ui, repo)
1254 unsure, s = lfdirstate.status(match_.always(repo.root,
1270 unsure, s = lfdirstate.status(match_.always(repo.root,
1255 repo.getcwd()),
1271 repo.getcwd()),
1256 [], False, False, False)
1272 [], False, False, False)
1257 for lfile in unsure + s.modified + s.added:
1273 for lfile in unsure + s.modified + s.added:
1258 lfutil.updatestandin(repo, lfutil.standin(lfile))
1274 lfutil.updatestandin(repo, lfutil.standin(lfile))
1259
1275
1260 if linearmerge:
1276 if linearmerge:
1261 # Only call updatelfiles on the standins that have changed
1277 # Only call updatelfiles on the standins that have changed
1262 # to save time
1278 # to save time
1263 oldstandins = lfutil.getstandinsstate(repo)
1279 oldstandins = lfutil.getstandinsstate(repo)
1264
1280
1265 result = orig(repo, node, branchmerge, force, partial, *args, **kwargs)
1281 result = orig(repo, node, branchmerge, force, partial, *args, **kwargs)
1266
1282
1267 filelist = None
1283 filelist = None
1268 if linearmerge:
1284 if linearmerge:
1269 newstandins = lfutil.getstandinsstate(repo)
1285 newstandins = lfutil.getstandinsstate(repo)
1270 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1286 filelist = lfutil.getlfilestoupdate(oldstandins, newstandins)
1271
1287
1272 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1288 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1273 normallookup=partial)
1289 normallookup=partial)
1274
1290
1275 return result
1291 return result
1276 finally:
1292 finally:
1277 wlock.release()
1293 wlock.release()
1278
1294
1279 def scmutilmarktouched(orig, repo, files, *args, **kwargs):
1295 def scmutilmarktouched(orig, repo, files, *args, **kwargs):
1280 result = orig(repo, files, *args, **kwargs)
1296 result = orig(repo, files, *args, **kwargs)
1281
1297
1282 filelist = [lfutil.splitstandin(f) for f in files if lfutil.isstandin(f)]
1298 filelist = [lfutil.splitstandin(f) for f in files if lfutil.isstandin(f)]
1283 if filelist:
1299 if filelist:
1284 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1300 lfcommands.updatelfiles(repo.ui, repo, filelist=filelist,
1285 printmessage=False, normallookup=True)
1301 printmessage=False, normallookup=True)
1286
1302
1287 return result
1303 return result
@@ -1,3526 +1,3531
1 # mq.py - patch queues for mercurial
1 # mq.py - patch queues for mercurial
2 #
2 #
3 # Copyright 2005, 2006 Chris Mason <mason@suse.com>
3 # Copyright 2005, 2006 Chris Mason <mason@suse.com>
4 #
4 #
5 # This software may be used and distributed according to the terms of the
5 # This software may be used and distributed according to the terms of the
6 # GNU General Public License version 2 or any later version.
6 # GNU General Public License version 2 or any later version.
7
7
8 '''manage a stack of patches
8 '''manage a stack of patches
9
9
10 This extension lets you work with a stack of patches in a Mercurial
10 This extension lets you work with a stack of patches in a Mercurial
11 repository. It manages two stacks of patches - all known patches, and
11 repository. It manages two stacks of patches - all known patches, and
12 applied patches (subset of known patches).
12 applied patches (subset of known patches).
13
13
14 Known patches are represented as patch files in the .hg/patches
14 Known patches are represented as patch files in the .hg/patches
15 directory. Applied patches are both patch files and changesets.
15 directory. Applied patches are both patch files and changesets.
16
16
17 Common tasks (use :hg:`help command` for more details)::
17 Common tasks (use :hg:`help command` for more details)::
18
18
19 create new patch qnew
19 create new patch qnew
20 import existing patch qimport
20 import existing patch qimport
21
21
22 print patch series qseries
22 print patch series qseries
23 print applied patches qapplied
23 print applied patches qapplied
24
24
25 add known patch to applied stack qpush
25 add known patch to applied stack qpush
26 remove patch from applied stack qpop
26 remove patch from applied stack qpop
27 refresh contents of top applied patch qrefresh
27 refresh contents of top applied patch qrefresh
28
28
29 By default, mq will automatically use git patches when required to
29 By default, mq will automatically use git patches when required to
30 avoid losing file mode changes, copy records, binary files or empty
30 avoid losing file mode changes, copy records, binary files or empty
31 files creations or deletions. This behaviour can be configured with::
31 files creations or deletions. This behaviour can be configured with::
32
32
33 [mq]
33 [mq]
34 git = auto/keep/yes/no
34 git = auto/keep/yes/no
35
35
36 If set to 'keep', mq will obey the [diff] section configuration while
36 If set to 'keep', mq will obey the [diff] section configuration while
37 preserving existing git patches upon qrefresh. If set to 'yes' or
37 preserving existing git patches upon qrefresh. If set to 'yes' or
38 'no', mq will override the [diff] section and always generate git or
38 'no', mq will override the [diff] section and always generate git or
39 regular patches, possibly losing data in the second case.
39 regular patches, possibly losing data in the second case.
40
40
41 It may be desirable for mq changesets to be kept in the secret phase (see
41 It may be desirable for mq changesets to be kept in the secret phase (see
42 :hg:`help phases`), which can be enabled with the following setting::
42 :hg:`help phases`), which can be enabled with the following setting::
43
43
44 [mq]
44 [mq]
45 secret = True
45 secret = True
46
46
47 You will by default be managing a patch queue named "patches". You can
47 You will by default be managing a patch queue named "patches". You can
48 create other, independent patch queues with the :hg:`qqueue` command.
48 create other, independent patch queues with the :hg:`qqueue` command.
49
49
50 If the working directory contains uncommitted files, qpush, qpop and
50 If the working directory contains uncommitted files, qpush, qpop and
51 qgoto abort immediately. If -f/--force is used, the changes are
51 qgoto abort immediately. If -f/--force is used, the changes are
52 discarded. Setting::
52 discarded. Setting::
53
53
54 [mq]
54 [mq]
55 keepchanges = True
55 keepchanges = True
56
56
57 make them behave as if --keep-changes were passed, and non-conflicting
57 make them behave as if --keep-changes were passed, and non-conflicting
58 local changes will be tolerated and preserved. If incompatible options
58 local changes will be tolerated and preserved. If incompatible options
59 such as -f/--force or --exact are passed, this setting is ignored.
59 such as -f/--force or --exact are passed, this setting is ignored.
60
60
61 This extension used to provide a strip command. This command now lives
61 This extension used to provide a strip command. This command now lives
62 in the strip extension.
62 in the strip extension.
63 '''
63 '''
64
64
65 from mercurial.i18n import _
65 from mercurial.i18n import _
66 from mercurial.node import bin, hex, short, nullid, nullrev
66 from mercurial.node import bin, hex, short, nullid, nullrev
67 from mercurial.lock import release
67 from mercurial.lock import release
68 from mercurial import commands, cmdutil, hg, scmutil, util, revset
68 from mercurial import commands, cmdutil, hg, scmutil, util, revset
69 from mercurial import extensions, error, phases
69 from mercurial import extensions, error, phases
70 from mercurial import patch as patchmod
70 from mercurial import patch as patchmod
71 from mercurial import localrepo
71 from mercurial import localrepo
72 from mercurial import subrepo
72 from mercurial import subrepo
73 import os, re, errno, shutil
73 import os, re, errno, shutil
74
74
75 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
75 seriesopts = [('s', 'summary', None, _('print first line of patch header'))]
76
76
77 cmdtable = {}
77 cmdtable = {}
78 command = cmdutil.command(cmdtable)
78 command = cmdutil.command(cmdtable)
79 testedwith = 'internal'
79 testedwith = 'internal'
80
80
81 # force load strip extension formerly included in mq and import some utility
81 # force load strip extension formerly included in mq and import some utility
82 try:
82 try:
83 stripext = extensions.find('strip')
83 stripext = extensions.find('strip')
84 except KeyError:
84 except KeyError:
85 # note: load is lazy so we could avoid the try-except,
85 # note: load is lazy so we could avoid the try-except,
86 # but I (marmoute) prefer this explicit code.
86 # but I (marmoute) prefer this explicit code.
87 class dummyui(object):
87 class dummyui(object):
88 def debug(self, msg):
88 def debug(self, msg):
89 pass
89 pass
90 stripext = extensions.load(dummyui(), 'strip', '')
90 stripext = extensions.load(dummyui(), 'strip', '')
91
91
92 strip = stripext.strip
92 strip = stripext.strip
93 checksubstate = stripext.checksubstate
93 checksubstate = stripext.checksubstate
94 checklocalchanges = stripext.checklocalchanges
94 checklocalchanges = stripext.checklocalchanges
95
95
96
96
97 # Patch names looks like unix-file names.
97 # Patch names looks like unix-file names.
98 # They must be joinable with queue directory and result in the patch path.
98 # They must be joinable with queue directory and result in the patch path.
99 normname = util.normpath
99 normname = util.normpath
100
100
101 class statusentry(object):
101 class statusentry(object):
102 def __init__(self, node, name):
102 def __init__(self, node, name):
103 self.node, self.name = node, name
103 self.node, self.name = node, name
104 def __repr__(self):
104 def __repr__(self):
105 return hex(self.node) + ':' + self.name
105 return hex(self.node) + ':' + self.name
106
106
107 # The order of the headers in 'hg export' HG patches:
107 # The order of the headers in 'hg export' HG patches:
108 HGHEADERS = [
108 HGHEADERS = [
109 # '# HG changeset patch',
109 # '# HG changeset patch',
110 '# User ',
110 '# User ',
111 '# Date ',
111 '# Date ',
112 '# ',
112 '# ',
113 '# Branch ',
113 '# Branch ',
114 '# Node ID ',
114 '# Node ID ',
115 '# Parent ', # can occur twice for merges - but that is not relevant for mq
115 '# Parent ', # can occur twice for merges - but that is not relevant for mq
116 '', # all lines after headers 'has' this prefix - simplifies the algorithm
117 ]
116 ]
118
117
119 def inserthgheader(lines, header, value):
118 def inserthgheader(lines, header, value):
120 """Assuming lines contains a HG patch header, add a header line with value.
119 """Assuming lines contains a HG patch header, add a header line with value.
121 >>> try: inserthgheader([], '# Date ', 'z')
120 >>> try: inserthgheader([], '# Date ', 'z')
122 ... except ValueError, inst: print "oops"
121 ... except ValueError, inst: print "oops"
123 oops
122 oops
124 >>> inserthgheader(['# HG changeset patch'], '# Date ', 'z')
123 >>> inserthgheader(['# HG changeset patch'], '# Date ', 'z')
125 ['# HG changeset patch', '# Date z']
124 ['# HG changeset patch', '# Date z']
126 >>> inserthgheader(['# HG changeset patch', ''], '# Date ', 'z')
125 >>> inserthgheader(['# HG changeset patch', ''], '# Date ', 'z')
127 ['# HG changeset patch', '# Date z', '']
126 ['# HG changeset patch', '# Date z', '']
128 >>> inserthgheader(['# HG changeset patch', '# User y'], '# Date ', 'z')
127 >>> inserthgheader(['# HG changeset patch', '# User y'], '# Date ', 'z')
129 ['# HG changeset patch', '# User y', '# Date z']
128 ['# HG changeset patch', '# User y', '# Date z']
129 >>> inserthgheader(['# HG changeset patch', '# Date x', '# User y'],
130 ... '# User ', 'z')
131 ['# HG changeset patch', '# Date x', '# User z']
130 >>> inserthgheader(['# HG changeset patch', '# Date y'], '# Date ', 'z')
132 >>> inserthgheader(['# HG changeset patch', '# Date y'], '# Date ', 'z')
131 ['# HG changeset patch', '# Date z']
133 ['# HG changeset patch', '# Date z']
132 >>> inserthgheader(['# HG changeset patch', '', '# Date y'], '# Date ', 'z')
134 >>> inserthgheader(['# HG changeset patch', '', '# Date y'], '# Date ', 'z')
133 ['# HG changeset patch', '# Date z', '', '# Date y']
135 ['# HG changeset patch', '# Date z', '', '# Date y']
134 >>> inserthgheader(['# HG changeset patch', '# Parent y'], '# Date ', 'z')
136 >>> inserthgheader(['# HG changeset patch', '# Parent y'], '# Date ', 'z')
135 ['# HG changeset patch', '# Date z', '# Parent y']
137 ['# HG changeset patch', '# Date z', '# Parent y']
136 """
138 """
137 start = lines.index('# HG changeset patch') + 1
139 start = lines.index('# HG changeset patch') + 1
138 newindex = HGHEADERS.index(header)
140 newindex = HGHEADERS.index(header)
141 bestpos = len(lines)
139 for i in range(start, len(lines)):
142 for i in range(start, len(lines)):
140 line = lines[i]
143 line = lines[i]
144 if not line.startswith('# '):
145 bestpos = min(bestpos, i)
146 break
141 for lineindex, h in enumerate(HGHEADERS):
147 for lineindex, h in enumerate(HGHEADERS):
142 if line.startswith(h):
148 if line.startswith(h):
143 if lineindex < newindex:
144 break # next line
145 if lineindex == newindex:
149 if lineindex == newindex:
146 lines[i] = header + value
150 lines[i] = header + value
147 else:
148 lines.insert(i, header + value)
149 return lines
151 return lines
150 lines.append(header + value)
152 if lineindex > newindex:
153 bestpos = min(bestpos, i)
154 break # next line
155 lines.insert(bestpos, header + value)
151 return lines
156 return lines
152
157
153 def insertplainheader(lines, header, value):
158 def insertplainheader(lines, header, value):
154 if lines and lines[0] and ':' not in lines[0]:
159 if lines and lines[0] and ':' not in lines[0]:
155 lines.insert(0, '')
160 lines.insert(0, '')
156 lines.insert(0, '%s: %s' % (header, value))
161 lines.insert(0, '%s: %s' % (header, value))
157 return lines
162 return lines
158
163
159 class patchheader(object):
164 class patchheader(object):
160 def __init__(self, pf, plainmode=False):
165 def __init__(self, pf, plainmode=False):
161 def eatdiff(lines):
166 def eatdiff(lines):
162 while lines:
167 while lines:
163 l = lines[-1]
168 l = lines[-1]
164 if (l.startswith("diff -") or
169 if (l.startswith("diff -") or
165 l.startswith("Index:") or
170 l.startswith("Index:") or
166 l.startswith("===========")):
171 l.startswith("===========")):
167 del lines[-1]
172 del lines[-1]
168 else:
173 else:
169 break
174 break
170 def eatempty(lines):
175 def eatempty(lines):
171 while lines:
176 while lines:
172 if not lines[-1].strip():
177 if not lines[-1].strip():
173 del lines[-1]
178 del lines[-1]
174 else:
179 else:
175 break
180 break
176
181
177 message = []
182 message = []
178 comments = []
183 comments = []
179 user = None
184 user = None
180 date = None
185 date = None
181 parent = None
186 parent = None
182 format = None
187 format = None
183 subject = None
188 subject = None
184 branch = None
189 branch = None
185 nodeid = None
190 nodeid = None
186 diffstart = 0
191 diffstart = 0
187
192
188 for line in file(pf):
193 for line in file(pf):
189 line = line.rstrip()
194 line = line.rstrip()
190 if (line.startswith('diff --git')
195 if (line.startswith('diff --git')
191 or (diffstart and line.startswith('+++ '))):
196 or (diffstart and line.startswith('+++ '))):
192 diffstart = 2
197 diffstart = 2
193 break
198 break
194 diffstart = 0 # reset
199 diffstart = 0 # reset
195 if line.startswith("--- "):
200 if line.startswith("--- "):
196 diffstart = 1
201 diffstart = 1
197 continue
202 continue
198 elif format == "hgpatch":
203 elif format == "hgpatch":
199 # parse values when importing the result of an hg export
204 # parse values when importing the result of an hg export
200 if line.startswith("# User "):
205 if line.startswith("# User "):
201 user = line[7:]
206 user = line[7:]
202 elif line.startswith("# Date "):
207 elif line.startswith("# Date "):
203 date = line[7:]
208 date = line[7:]
204 elif line.startswith("# Parent "):
209 elif line.startswith("# Parent "):
205 parent = line[9:].lstrip() # handle double trailing space
210 parent = line[9:].lstrip() # handle double trailing space
206 elif line.startswith("# Branch "):
211 elif line.startswith("# Branch "):
207 branch = line[9:]
212 branch = line[9:]
208 elif line.startswith("# Node ID "):
213 elif line.startswith("# Node ID "):
209 nodeid = line[10:]
214 nodeid = line[10:]
210 elif not line.startswith("# ") and line:
215 elif not line.startswith("# ") and line:
211 message.append(line)
216 message.append(line)
212 format = None
217 format = None
213 elif line == '# HG changeset patch':
218 elif line == '# HG changeset patch':
214 message = []
219 message = []
215 format = "hgpatch"
220 format = "hgpatch"
216 elif (format != "tagdone" and (line.startswith("Subject: ") or
221 elif (format != "tagdone" and (line.startswith("Subject: ") or
217 line.startswith("subject: "))):
222 line.startswith("subject: "))):
218 subject = line[9:]
223 subject = line[9:]
219 format = "tag"
224 format = "tag"
220 elif (format != "tagdone" and (line.startswith("From: ") or
225 elif (format != "tagdone" and (line.startswith("From: ") or
221 line.startswith("from: "))):
226 line.startswith("from: "))):
222 user = line[6:]
227 user = line[6:]
223 format = "tag"
228 format = "tag"
224 elif (format != "tagdone" and (line.startswith("Date: ") or
229 elif (format != "tagdone" and (line.startswith("Date: ") or
225 line.startswith("date: "))):
230 line.startswith("date: "))):
226 date = line[6:]
231 date = line[6:]
227 format = "tag"
232 format = "tag"
228 elif format == "tag" and line == "":
233 elif format == "tag" and line == "":
229 # when looking for tags (subject: from: etc) they
234 # when looking for tags (subject: from: etc) they
230 # end once you find a blank line in the source
235 # end once you find a blank line in the source
231 format = "tagdone"
236 format = "tagdone"
232 elif message or line:
237 elif message or line:
233 message.append(line)
238 message.append(line)
234 comments.append(line)
239 comments.append(line)
235
240
236 eatdiff(message)
241 eatdiff(message)
237 eatdiff(comments)
242 eatdiff(comments)
238 # Remember the exact starting line of the patch diffs before consuming
243 # Remember the exact starting line of the patch diffs before consuming
239 # empty lines, for external use by TortoiseHg and others
244 # empty lines, for external use by TortoiseHg and others
240 self.diffstartline = len(comments)
245 self.diffstartline = len(comments)
241 eatempty(message)
246 eatempty(message)
242 eatempty(comments)
247 eatempty(comments)
243
248
244 # make sure message isn't empty
249 # make sure message isn't empty
245 if format and format.startswith("tag") and subject:
250 if format and format.startswith("tag") and subject:
246 message.insert(0, subject)
251 message.insert(0, subject)
247
252
248 self.message = message
253 self.message = message
249 self.comments = comments
254 self.comments = comments
250 self.user = user
255 self.user = user
251 self.date = date
256 self.date = date
252 self.parent = parent
257 self.parent = parent
253 # nodeid and branch are for external use by TortoiseHg and others
258 # nodeid and branch are for external use by TortoiseHg and others
254 self.nodeid = nodeid
259 self.nodeid = nodeid
255 self.branch = branch
260 self.branch = branch
256 self.haspatch = diffstart > 1
261 self.haspatch = diffstart > 1
257 self.plainmode = (plainmode or
262 self.plainmode = (plainmode or
258 '# HG changeset patch' not in self.comments and
263 '# HG changeset patch' not in self.comments and
259 util.any(c.startswith('Date: ') or
264 util.any(c.startswith('Date: ') or
260 c.startswith('From: ')
265 c.startswith('From: ')
261 for c in self.comments))
266 for c in self.comments))
262
267
263 def setuser(self, user):
268 def setuser(self, user):
264 if not self.updateheader(['From: ', '# User '], user):
269 if not self.updateheader(['From: ', '# User '], user):
265 try:
270 try:
266 inserthgheader(self.comments, '# User ', user)
271 inserthgheader(self.comments, '# User ', user)
267 except ValueError:
272 except ValueError:
268 if self.plainmode:
273 if self.plainmode:
269 insertplainheader(self.comments, 'From', user)
274 insertplainheader(self.comments, 'From', user)
270 else:
275 else:
271 tmp = ['# HG changeset patch', '# User ' + user]
276 tmp = ['# HG changeset patch', '# User ' + user]
272 self.comments = tmp + self.comments
277 self.comments = tmp + self.comments
273 self.user = user
278 self.user = user
274
279
275 def setdate(self, date):
280 def setdate(self, date):
276 if not self.updateheader(['Date: ', '# Date '], date):
281 if not self.updateheader(['Date: ', '# Date '], date):
277 try:
282 try:
278 inserthgheader(self.comments, '# Date ', date)
283 inserthgheader(self.comments, '# Date ', date)
279 except ValueError:
284 except ValueError:
280 if self.plainmode:
285 if self.plainmode:
281 insertplainheader(self.comments, 'Date', date)
286 insertplainheader(self.comments, 'Date', date)
282 else:
287 else:
283 tmp = ['# HG changeset patch', '# Date ' + date]
288 tmp = ['# HG changeset patch', '# Date ' + date]
284 self.comments = tmp + self.comments
289 self.comments = tmp + self.comments
285 self.date = date
290 self.date = date
286
291
287 def setparent(self, parent):
292 def setparent(self, parent):
288 if not (self.updateheader(['# Parent '], parent) or
293 if not (self.updateheader(['# Parent '], parent) or
289 self.updateheader(['# Parent '], parent)):
294 self.updateheader(['# Parent '], parent)):
290 try:
295 try:
291 inserthgheader(self.comments, '# Parent ', parent)
296 inserthgheader(self.comments, '# Parent ', parent)
292 except ValueError:
297 except ValueError:
293 if not self.plainmode:
298 if not self.plainmode:
294 tmp = ['# HG changeset patch', '# Parent ' + parent]
299 tmp = ['# HG changeset patch', '# Parent ' + parent]
295 self.comments = tmp + self.comments
300 self.comments = tmp + self.comments
296 self.parent = parent
301 self.parent = parent
297
302
298 def setmessage(self, message):
303 def setmessage(self, message):
299 if self.comments:
304 if self.comments:
300 self._delmsg()
305 self._delmsg()
301 self.message = [message]
306 self.message = [message]
302 if message:
307 if message:
303 if self.plainmode and self.comments and self.comments[-1]:
308 if self.plainmode and self.comments and self.comments[-1]:
304 self.comments.append('')
309 self.comments.append('')
305 self.comments.append(message)
310 self.comments.append(message)
306
311
307 def updateheader(self, prefixes, new):
312 def updateheader(self, prefixes, new):
308 '''Update all references to a field in the patch header.
313 '''Update all references to a field in the patch header.
309 Return whether the field is present.'''
314 Return whether the field is present.'''
310 res = False
315 res = False
311 for prefix in prefixes:
316 for prefix in prefixes:
312 for i in xrange(len(self.comments)):
317 for i in xrange(len(self.comments)):
313 if self.comments[i].startswith(prefix):
318 if self.comments[i].startswith(prefix):
314 self.comments[i] = prefix + new
319 self.comments[i] = prefix + new
315 res = True
320 res = True
316 break
321 break
317 return res
322 return res
318
323
319 def __str__(self):
324 def __str__(self):
320 s = '\n'.join(self.comments).rstrip()
325 s = '\n'.join(self.comments).rstrip()
321 if not s:
326 if not s:
322 return ''
327 return ''
323 return s + '\n\n'
328 return s + '\n\n'
324
329
325 def _delmsg(self):
330 def _delmsg(self):
326 '''Remove existing message, keeping the rest of the comments fields.
331 '''Remove existing message, keeping the rest of the comments fields.
327 If comments contains 'subject: ', message will prepend
332 If comments contains 'subject: ', message will prepend
328 the field and a blank line.'''
333 the field and a blank line.'''
329 if self.message:
334 if self.message:
330 subj = 'subject: ' + self.message[0].lower()
335 subj = 'subject: ' + self.message[0].lower()
331 for i in xrange(len(self.comments)):
336 for i in xrange(len(self.comments)):
332 if subj == self.comments[i].lower():
337 if subj == self.comments[i].lower():
333 del self.comments[i]
338 del self.comments[i]
334 self.message = self.message[2:]
339 self.message = self.message[2:]
335 break
340 break
336 ci = 0
341 ci = 0
337 for mi in self.message:
342 for mi in self.message:
338 while mi != self.comments[ci]:
343 while mi != self.comments[ci]:
339 ci += 1
344 ci += 1
340 del self.comments[ci]
345 del self.comments[ci]
341
346
342 def newcommit(repo, phase, *args, **kwargs):
347 def newcommit(repo, phase, *args, **kwargs):
343 """helper dedicated to ensure a commit respect mq.secret setting
348 """helper dedicated to ensure a commit respect mq.secret setting
344
349
345 It should be used instead of repo.commit inside the mq source for operation
350 It should be used instead of repo.commit inside the mq source for operation
346 creating new changeset.
351 creating new changeset.
347 """
352 """
348 repo = repo.unfiltered()
353 repo = repo.unfiltered()
349 if phase is None:
354 if phase is None:
350 if repo.ui.configbool('mq', 'secret', False):
355 if repo.ui.configbool('mq', 'secret', False):
351 phase = phases.secret
356 phase = phases.secret
352 if phase is not None:
357 if phase is not None:
353 backup = repo.ui.backupconfig('phases', 'new-commit')
358 backup = repo.ui.backupconfig('phases', 'new-commit')
354 try:
359 try:
355 if phase is not None:
360 if phase is not None:
356 repo.ui.setconfig('phases', 'new-commit', phase, 'mq')
361 repo.ui.setconfig('phases', 'new-commit', phase, 'mq')
357 return repo.commit(*args, **kwargs)
362 return repo.commit(*args, **kwargs)
358 finally:
363 finally:
359 if phase is not None:
364 if phase is not None:
360 repo.ui.restoreconfig(backup)
365 repo.ui.restoreconfig(backup)
361
366
362 class AbortNoCleanup(error.Abort):
367 class AbortNoCleanup(error.Abort):
363 pass
368 pass
364
369
365 class queue(object):
370 class queue(object):
366 def __init__(self, ui, baseui, path, patchdir=None):
371 def __init__(self, ui, baseui, path, patchdir=None):
367 self.basepath = path
372 self.basepath = path
368 try:
373 try:
369 fh = open(os.path.join(path, 'patches.queue'))
374 fh = open(os.path.join(path, 'patches.queue'))
370 cur = fh.read().rstrip()
375 cur = fh.read().rstrip()
371 fh.close()
376 fh.close()
372 if not cur:
377 if not cur:
373 curpath = os.path.join(path, 'patches')
378 curpath = os.path.join(path, 'patches')
374 else:
379 else:
375 curpath = os.path.join(path, 'patches-' + cur)
380 curpath = os.path.join(path, 'patches-' + cur)
376 except IOError:
381 except IOError:
377 curpath = os.path.join(path, 'patches')
382 curpath = os.path.join(path, 'patches')
378 self.path = patchdir or curpath
383 self.path = patchdir or curpath
379 self.opener = scmutil.opener(self.path)
384 self.opener = scmutil.opener(self.path)
380 self.ui = ui
385 self.ui = ui
381 self.baseui = baseui
386 self.baseui = baseui
382 self.applieddirty = False
387 self.applieddirty = False
383 self.seriesdirty = False
388 self.seriesdirty = False
384 self.added = []
389 self.added = []
385 self.seriespath = "series"
390 self.seriespath = "series"
386 self.statuspath = "status"
391 self.statuspath = "status"
387 self.guardspath = "guards"
392 self.guardspath = "guards"
388 self.activeguards = None
393 self.activeguards = None
389 self.guardsdirty = False
394 self.guardsdirty = False
390 # Handle mq.git as a bool with extended values
395 # Handle mq.git as a bool with extended values
391 try:
396 try:
392 gitmode = ui.configbool('mq', 'git', None)
397 gitmode = ui.configbool('mq', 'git', None)
393 if gitmode is None:
398 if gitmode is None:
394 raise error.ConfigError
399 raise error.ConfigError
395 self.gitmode = gitmode and 'yes' or 'no'
400 self.gitmode = gitmode and 'yes' or 'no'
396 except error.ConfigError:
401 except error.ConfigError:
397 self.gitmode = ui.config('mq', 'git', 'auto').lower()
402 self.gitmode = ui.config('mq', 'git', 'auto').lower()
398 self.plainmode = ui.configbool('mq', 'plain', False)
403 self.plainmode = ui.configbool('mq', 'plain', False)
399 self.checkapplied = True
404 self.checkapplied = True
400
405
401 @util.propertycache
406 @util.propertycache
402 def applied(self):
407 def applied(self):
403 def parselines(lines):
408 def parselines(lines):
404 for l in lines:
409 for l in lines:
405 entry = l.split(':', 1)
410 entry = l.split(':', 1)
406 if len(entry) > 1:
411 if len(entry) > 1:
407 n, name = entry
412 n, name = entry
408 yield statusentry(bin(n), name)
413 yield statusentry(bin(n), name)
409 elif l.strip():
414 elif l.strip():
410 self.ui.warn(_('malformated mq status line: %s\n') % entry)
415 self.ui.warn(_('malformated mq status line: %s\n') % entry)
411 # else we ignore empty lines
416 # else we ignore empty lines
412 try:
417 try:
413 lines = self.opener.read(self.statuspath).splitlines()
418 lines = self.opener.read(self.statuspath).splitlines()
414 return list(parselines(lines))
419 return list(parselines(lines))
415 except IOError, e:
420 except IOError, e:
416 if e.errno == errno.ENOENT:
421 if e.errno == errno.ENOENT:
417 return []
422 return []
418 raise
423 raise
419
424
420 @util.propertycache
425 @util.propertycache
421 def fullseries(self):
426 def fullseries(self):
422 try:
427 try:
423 return self.opener.read(self.seriespath).splitlines()
428 return self.opener.read(self.seriespath).splitlines()
424 except IOError, e:
429 except IOError, e:
425 if e.errno == errno.ENOENT:
430 if e.errno == errno.ENOENT:
426 return []
431 return []
427 raise
432 raise
428
433
429 @util.propertycache
434 @util.propertycache
430 def series(self):
435 def series(self):
431 self.parseseries()
436 self.parseseries()
432 return self.series
437 return self.series
433
438
434 @util.propertycache
439 @util.propertycache
435 def seriesguards(self):
440 def seriesguards(self):
436 self.parseseries()
441 self.parseseries()
437 return self.seriesguards
442 return self.seriesguards
438
443
439 def invalidate(self):
444 def invalidate(self):
440 for a in 'applied fullseries series seriesguards'.split():
445 for a in 'applied fullseries series seriesguards'.split():
441 if a in self.__dict__:
446 if a in self.__dict__:
442 delattr(self, a)
447 delattr(self, a)
443 self.applieddirty = False
448 self.applieddirty = False
444 self.seriesdirty = False
449 self.seriesdirty = False
445 self.guardsdirty = False
450 self.guardsdirty = False
446 self.activeguards = None
451 self.activeguards = None
447
452
448 def diffopts(self, opts={}, patchfn=None):
453 def diffopts(self, opts={}, patchfn=None):
449 diffopts = patchmod.diffopts(self.ui, opts)
454 diffopts = patchmod.diffopts(self.ui, opts)
450 if self.gitmode == 'auto':
455 if self.gitmode == 'auto':
451 diffopts.upgrade = True
456 diffopts.upgrade = True
452 elif self.gitmode == 'keep':
457 elif self.gitmode == 'keep':
453 pass
458 pass
454 elif self.gitmode in ('yes', 'no'):
459 elif self.gitmode in ('yes', 'no'):
455 diffopts.git = self.gitmode == 'yes'
460 diffopts.git = self.gitmode == 'yes'
456 else:
461 else:
457 raise util.Abort(_('mq.git option can be auto/keep/yes/no'
462 raise util.Abort(_('mq.git option can be auto/keep/yes/no'
458 ' got %s') % self.gitmode)
463 ' got %s') % self.gitmode)
459 if patchfn:
464 if patchfn:
460 diffopts = self.patchopts(diffopts, patchfn)
465 diffopts = self.patchopts(diffopts, patchfn)
461 return diffopts
466 return diffopts
462
467
463 def patchopts(self, diffopts, *patches):
468 def patchopts(self, diffopts, *patches):
464 """Return a copy of input diff options with git set to true if
469 """Return a copy of input diff options with git set to true if
465 referenced patch is a git patch and should be preserved as such.
470 referenced patch is a git patch and should be preserved as such.
466 """
471 """
467 diffopts = diffopts.copy()
472 diffopts = diffopts.copy()
468 if not diffopts.git and self.gitmode == 'keep':
473 if not diffopts.git and self.gitmode == 'keep':
469 for patchfn in patches:
474 for patchfn in patches:
470 patchf = self.opener(patchfn, 'r')
475 patchf = self.opener(patchfn, 'r')
471 # if the patch was a git patch, refresh it as a git patch
476 # if the patch was a git patch, refresh it as a git patch
472 for line in patchf:
477 for line in patchf:
473 if line.startswith('diff --git'):
478 if line.startswith('diff --git'):
474 diffopts.git = True
479 diffopts.git = True
475 break
480 break
476 patchf.close()
481 patchf.close()
477 return diffopts
482 return diffopts
478
483
479 def join(self, *p):
484 def join(self, *p):
480 return os.path.join(self.path, *p)
485 return os.path.join(self.path, *p)
481
486
482 def findseries(self, patch):
487 def findseries(self, patch):
483 def matchpatch(l):
488 def matchpatch(l):
484 l = l.split('#', 1)[0]
489 l = l.split('#', 1)[0]
485 return l.strip() == patch
490 return l.strip() == patch
486 for index, l in enumerate(self.fullseries):
491 for index, l in enumerate(self.fullseries):
487 if matchpatch(l):
492 if matchpatch(l):
488 return index
493 return index
489 return None
494 return None
490
495
491 guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)')
496 guard_re = re.compile(r'\s?#([-+][^-+# \t\r\n\f][^# \t\r\n\f]*)')
492
497
493 def parseseries(self):
498 def parseseries(self):
494 self.series = []
499 self.series = []
495 self.seriesguards = []
500 self.seriesguards = []
496 for l in self.fullseries:
501 for l in self.fullseries:
497 h = l.find('#')
502 h = l.find('#')
498 if h == -1:
503 if h == -1:
499 patch = l
504 patch = l
500 comment = ''
505 comment = ''
501 elif h == 0:
506 elif h == 0:
502 continue
507 continue
503 else:
508 else:
504 patch = l[:h]
509 patch = l[:h]
505 comment = l[h:]
510 comment = l[h:]
506 patch = patch.strip()
511 patch = patch.strip()
507 if patch:
512 if patch:
508 if patch in self.series:
513 if patch in self.series:
509 raise util.Abort(_('%s appears more than once in %s') %
514 raise util.Abort(_('%s appears more than once in %s') %
510 (patch, self.join(self.seriespath)))
515 (patch, self.join(self.seriespath)))
511 self.series.append(patch)
516 self.series.append(patch)
512 self.seriesguards.append(self.guard_re.findall(comment))
517 self.seriesguards.append(self.guard_re.findall(comment))
513
518
514 def checkguard(self, guard):
519 def checkguard(self, guard):
515 if not guard:
520 if not guard:
516 return _('guard cannot be an empty string')
521 return _('guard cannot be an empty string')
517 bad_chars = '# \t\r\n\f'
522 bad_chars = '# \t\r\n\f'
518 first = guard[0]
523 first = guard[0]
519 if first in '-+':
524 if first in '-+':
520 return (_('guard %r starts with invalid character: %r') %
525 return (_('guard %r starts with invalid character: %r') %
521 (guard, first))
526 (guard, first))
522 for c in bad_chars:
527 for c in bad_chars:
523 if c in guard:
528 if c in guard:
524 return _('invalid character in guard %r: %r') % (guard, c)
529 return _('invalid character in guard %r: %r') % (guard, c)
525
530
526 def setactive(self, guards):
531 def setactive(self, guards):
527 for guard in guards:
532 for guard in guards:
528 bad = self.checkguard(guard)
533 bad = self.checkguard(guard)
529 if bad:
534 if bad:
530 raise util.Abort(bad)
535 raise util.Abort(bad)
531 guards = sorted(set(guards))
536 guards = sorted(set(guards))
532 self.ui.debug('active guards: %s\n' % ' '.join(guards))
537 self.ui.debug('active guards: %s\n' % ' '.join(guards))
533 self.activeguards = guards
538 self.activeguards = guards
534 self.guardsdirty = True
539 self.guardsdirty = True
535
540
536 def active(self):
541 def active(self):
537 if self.activeguards is None:
542 if self.activeguards is None:
538 self.activeguards = []
543 self.activeguards = []
539 try:
544 try:
540 guards = self.opener.read(self.guardspath).split()
545 guards = self.opener.read(self.guardspath).split()
541 except IOError, err:
546 except IOError, err:
542 if err.errno != errno.ENOENT:
547 if err.errno != errno.ENOENT:
543 raise
548 raise
544 guards = []
549 guards = []
545 for i, guard in enumerate(guards):
550 for i, guard in enumerate(guards):
546 bad = self.checkguard(guard)
551 bad = self.checkguard(guard)
547 if bad:
552 if bad:
548 self.ui.warn('%s:%d: %s\n' %
553 self.ui.warn('%s:%d: %s\n' %
549 (self.join(self.guardspath), i + 1, bad))
554 (self.join(self.guardspath), i + 1, bad))
550 else:
555 else:
551 self.activeguards.append(guard)
556 self.activeguards.append(guard)
552 return self.activeguards
557 return self.activeguards
553
558
554 def setguards(self, idx, guards):
559 def setguards(self, idx, guards):
555 for g in guards:
560 for g in guards:
556 if len(g) < 2:
561 if len(g) < 2:
557 raise util.Abort(_('guard %r too short') % g)
562 raise util.Abort(_('guard %r too short') % g)
558 if g[0] not in '-+':
563 if g[0] not in '-+':
559 raise util.Abort(_('guard %r starts with invalid char') % g)
564 raise util.Abort(_('guard %r starts with invalid char') % g)
560 bad = self.checkguard(g[1:])
565 bad = self.checkguard(g[1:])
561 if bad:
566 if bad:
562 raise util.Abort(bad)
567 raise util.Abort(bad)
563 drop = self.guard_re.sub('', self.fullseries[idx])
568 drop = self.guard_re.sub('', self.fullseries[idx])
564 self.fullseries[idx] = drop + ''.join([' #' + g for g in guards])
569 self.fullseries[idx] = drop + ''.join([' #' + g for g in guards])
565 self.parseseries()
570 self.parseseries()
566 self.seriesdirty = True
571 self.seriesdirty = True
567
572
568 def pushable(self, idx):
573 def pushable(self, idx):
569 if isinstance(idx, str):
574 if isinstance(idx, str):
570 idx = self.series.index(idx)
575 idx = self.series.index(idx)
571 patchguards = self.seriesguards[idx]
576 patchguards = self.seriesguards[idx]
572 if not patchguards:
577 if not patchguards:
573 return True, None
578 return True, None
574 guards = self.active()
579 guards = self.active()
575 exactneg = [g for g in patchguards if g[0] == '-' and g[1:] in guards]
580 exactneg = [g for g in patchguards if g[0] == '-' and g[1:] in guards]
576 if exactneg:
581 if exactneg:
577 return False, repr(exactneg[0])
582 return False, repr(exactneg[0])
578 pos = [g for g in patchguards if g[0] == '+']
583 pos = [g for g in patchguards if g[0] == '+']
579 exactpos = [g for g in pos if g[1:] in guards]
584 exactpos = [g for g in pos if g[1:] in guards]
580 if pos:
585 if pos:
581 if exactpos:
586 if exactpos:
582 return True, repr(exactpos[0])
587 return True, repr(exactpos[0])
583 return False, ' '.join(map(repr, pos))
588 return False, ' '.join(map(repr, pos))
584 return True, ''
589 return True, ''
585
590
586 def explainpushable(self, idx, all_patches=False):
591 def explainpushable(self, idx, all_patches=False):
587 write = all_patches and self.ui.write or self.ui.warn
592 write = all_patches and self.ui.write or self.ui.warn
588 if all_patches or self.ui.verbose:
593 if all_patches or self.ui.verbose:
589 if isinstance(idx, str):
594 if isinstance(idx, str):
590 idx = self.series.index(idx)
595 idx = self.series.index(idx)
591 pushable, why = self.pushable(idx)
596 pushable, why = self.pushable(idx)
592 if all_patches and pushable:
597 if all_patches and pushable:
593 if why is None:
598 if why is None:
594 write(_('allowing %s - no guards in effect\n') %
599 write(_('allowing %s - no guards in effect\n') %
595 self.series[idx])
600 self.series[idx])
596 else:
601 else:
597 if not why:
602 if not why:
598 write(_('allowing %s - no matching negative guards\n') %
603 write(_('allowing %s - no matching negative guards\n') %
599 self.series[idx])
604 self.series[idx])
600 else:
605 else:
601 write(_('allowing %s - guarded by %s\n') %
606 write(_('allowing %s - guarded by %s\n') %
602 (self.series[idx], why))
607 (self.series[idx], why))
603 if not pushable:
608 if not pushable:
604 if why:
609 if why:
605 write(_('skipping %s - guarded by %s\n') %
610 write(_('skipping %s - guarded by %s\n') %
606 (self.series[idx], why))
611 (self.series[idx], why))
607 else:
612 else:
608 write(_('skipping %s - no matching guards\n') %
613 write(_('skipping %s - no matching guards\n') %
609 self.series[idx])
614 self.series[idx])
610
615
611 def savedirty(self):
616 def savedirty(self):
612 def writelist(items, path):
617 def writelist(items, path):
613 fp = self.opener(path, 'w')
618 fp = self.opener(path, 'w')
614 for i in items:
619 for i in items:
615 fp.write("%s\n" % i)
620 fp.write("%s\n" % i)
616 fp.close()
621 fp.close()
617 if self.applieddirty:
622 if self.applieddirty:
618 writelist(map(str, self.applied), self.statuspath)
623 writelist(map(str, self.applied), self.statuspath)
619 self.applieddirty = False
624 self.applieddirty = False
620 if self.seriesdirty:
625 if self.seriesdirty:
621 writelist(self.fullseries, self.seriespath)
626 writelist(self.fullseries, self.seriespath)
622 self.seriesdirty = False
627 self.seriesdirty = False
623 if self.guardsdirty:
628 if self.guardsdirty:
624 writelist(self.activeguards, self.guardspath)
629 writelist(self.activeguards, self.guardspath)
625 self.guardsdirty = False
630 self.guardsdirty = False
626 if self.added:
631 if self.added:
627 qrepo = self.qrepo()
632 qrepo = self.qrepo()
628 if qrepo:
633 if qrepo:
629 qrepo[None].add(f for f in self.added if f not in qrepo[None])
634 qrepo[None].add(f for f in self.added if f not in qrepo[None])
630 self.added = []
635 self.added = []
631
636
632 def removeundo(self, repo):
637 def removeundo(self, repo):
633 undo = repo.sjoin('undo')
638 undo = repo.sjoin('undo')
634 if not os.path.exists(undo):
639 if not os.path.exists(undo):
635 return
640 return
636 try:
641 try:
637 os.unlink(undo)
642 os.unlink(undo)
638 except OSError, inst:
643 except OSError, inst:
639 self.ui.warn(_('error removing undo: %s\n') % str(inst))
644 self.ui.warn(_('error removing undo: %s\n') % str(inst))
640
645
641 def backup(self, repo, files, copy=False):
646 def backup(self, repo, files, copy=False):
642 # backup local changes in --force case
647 # backup local changes in --force case
643 for f in sorted(files):
648 for f in sorted(files):
644 absf = repo.wjoin(f)
649 absf = repo.wjoin(f)
645 if os.path.lexists(absf):
650 if os.path.lexists(absf):
646 self.ui.note(_('saving current version of %s as %s\n') %
651 self.ui.note(_('saving current version of %s as %s\n') %
647 (f, f + '.orig'))
652 (f, f + '.orig'))
648 if copy:
653 if copy:
649 util.copyfile(absf, absf + '.orig')
654 util.copyfile(absf, absf + '.orig')
650 else:
655 else:
651 util.rename(absf, absf + '.orig')
656 util.rename(absf, absf + '.orig')
652
657
653 def printdiff(self, repo, diffopts, node1, node2=None, files=None,
658 def printdiff(self, repo, diffopts, node1, node2=None, files=None,
654 fp=None, changes=None, opts={}):
659 fp=None, changes=None, opts={}):
655 stat = opts.get('stat')
660 stat = opts.get('stat')
656 m = scmutil.match(repo[node1], files, opts)
661 m = scmutil.match(repo[node1], files, opts)
657 cmdutil.diffordiffstat(self.ui, repo, diffopts, node1, node2, m,
662 cmdutil.diffordiffstat(self.ui, repo, diffopts, node1, node2, m,
658 changes, stat, fp)
663 changes, stat, fp)
659
664
660 def mergeone(self, repo, mergeq, head, patch, rev, diffopts):
665 def mergeone(self, repo, mergeq, head, patch, rev, diffopts):
661 # first try just applying the patch
666 # first try just applying the patch
662 (err, n) = self.apply(repo, [patch], update_status=False,
667 (err, n) = self.apply(repo, [patch], update_status=False,
663 strict=True, merge=rev)
668 strict=True, merge=rev)
664
669
665 if err == 0:
670 if err == 0:
666 return (err, n)
671 return (err, n)
667
672
668 if n is None:
673 if n is None:
669 raise util.Abort(_("apply failed for patch %s") % patch)
674 raise util.Abort(_("apply failed for patch %s") % patch)
670
675
671 self.ui.warn(_("patch didn't work out, merging %s\n") % patch)
676 self.ui.warn(_("patch didn't work out, merging %s\n") % patch)
672
677
673 # apply failed, strip away that rev and merge.
678 # apply failed, strip away that rev and merge.
674 hg.clean(repo, head)
679 hg.clean(repo, head)
675 strip(self.ui, repo, [n], update=False, backup=False)
680 strip(self.ui, repo, [n], update=False, backup=False)
676
681
677 ctx = repo[rev]
682 ctx = repo[rev]
678 ret = hg.merge(repo, rev)
683 ret = hg.merge(repo, rev)
679 if ret:
684 if ret:
680 raise util.Abort(_("update returned %d") % ret)
685 raise util.Abort(_("update returned %d") % ret)
681 n = newcommit(repo, None, ctx.description(), ctx.user(), force=True)
686 n = newcommit(repo, None, ctx.description(), ctx.user(), force=True)
682 if n is None:
687 if n is None:
683 raise util.Abort(_("repo commit failed"))
688 raise util.Abort(_("repo commit failed"))
684 try:
689 try:
685 ph = patchheader(mergeq.join(patch), self.plainmode)
690 ph = patchheader(mergeq.join(patch), self.plainmode)
686 except Exception:
691 except Exception:
687 raise util.Abort(_("unable to read %s") % patch)
692 raise util.Abort(_("unable to read %s") % patch)
688
693
689 diffopts = self.patchopts(diffopts, patch)
694 diffopts = self.patchopts(diffopts, patch)
690 patchf = self.opener(patch, "w")
695 patchf = self.opener(patch, "w")
691 comments = str(ph)
696 comments = str(ph)
692 if comments:
697 if comments:
693 patchf.write(comments)
698 patchf.write(comments)
694 self.printdiff(repo, diffopts, head, n, fp=patchf)
699 self.printdiff(repo, diffopts, head, n, fp=patchf)
695 patchf.close()
700 patchf.close()
696 self.removeundo(repo)
701 self.removeundo(repo)
697 return (0, n)
702 return (0, n)
698
703
699 def qparents(self, repo, rev=None):
704 def qparents(self, repo, rev=None):
700 """return the mq handled parent or p1
705 """return the mq handled parent or p1
701
706
702 In some case where mq get himself in being the parent of a merge the
707 In some case where mq get himself in being the parent of a merge the
703 appropriate parent may be p2.
708 appropriate parent may be p2.
704 (eg: an in progress merge started with mq disabled)
709 (eg: an in progress merge started with mq disabled)
705
710
706 If no parent are managed by mq, p1 is returned.
711 If no parent are managed by mq, p1 is returned.
707 """
712 """
708 if rev is None:
713 if rev is None:
709 (p1, p2) = repo.dirstate.parents()
714 (p1, p2) = repo.dirstate.parents()
710 if p2 == nullid:
715 if p2 == nullid:
711 return p1
716 return p1
712 if not self.applied:
717 if not self.applied:
713 return None
718 return None
714 return self.applied[-1].node
719 return self.applied[-1].node
715 p1, p2 = repo.changelog.parents(rev)
720 p1, p2 = repo.changelog.parents(rev)
716 if p2 != nullid and p2 in [x.node for x in self.applied]:
721 if p2 != nullid and p2 in [x.node for x in self.applied]:
717 return p2
722 return p2
718 return p1
723 return p1
719
724
720 def mergepatch(self, repo, mergeq, series, diffopts):
725 def mergepatch(self, repo, mergeq, series, diffopts):
721 if not self.applied:
726 if not self.applied:
722 # each of the patches merged in will have two parents. This
727 # each of the patches merged in will have two parents. This
723 # can confuse the qrefresh, qdiff, and strip code because it
728 # can confuse the qrefresh, qdiff, and strip code because it
724 # needs to know which parent is actually in the patch queue.
729 # needs to know which parent is actually in the patch queue.
725 # so, we insert a merge marker with only one parent. This way
730 # so, we insert a merge marker with only one parent. This way
726 # the first patch in the queue is never a merge patch
731 # the first patch in the queue is never a merge patch
727 #
732 #
728 pname = ".hg.patches.merge.marker"
733 pname = ".hg.patches.merge.marker"
729 n = newcommit(repo, None, '[mq]: merge marker', force=True)
734 n = newcommit(repo, None, '[mq]: merge marker', force=True)
730 self.removeundo(repo)
735 self.removeundo(repo)
731 self.applied.append(statusentry(n, pname))
736 self.applied.append(statusentry(n, pname))
732 self.applieddirty = True
737 self.applieddirty = True
733
738
734 head = self.qparents(repo)
739 head = self.qparents(repo)
735
740
736 for patch in series:
741 for patch in series:
737 patch = mergeq.lookup(patch, strict=True)
742 patch = mergeq.lookup(patch, strict=True)
738 if not patch:
743 if not patch:
739 self.ui.warn(_("patch %s does not exist\n") % patch)
744 self.ui.warn(_("patch %s does not exist\n") % patch)
740 return (1, None)
745 return (1, None)
741 pushable, reason = self.pushable(patch)
746 pushable, reason = self.pushable(patch)
742 if not pushable:
747 if not pushable:
743 self.explainpushable(patch, all_patches=True)
748 self.explainpushable(patch, all_patches=True)
744 continue
749 continue
745 info = mergeq.isapplied(patch)
750 info = mergeq.isapplied(patch)
746 if not info:
751 if not info:
747 self.ui.warn(_("patch %s is not applied\n") % patch)
752 self.ui.warn(_("patch %s is not applied\n") % patch)
748 return (1, None)
753 return (1, None)
749 rev = info[1]
754 rev = info[1]
750 err, head = self.mergeone(repo, mergeq, head, patch, rev, diffopts)
755 err, head = self.mergeone(repo, mergeq, head, patch, rev, diffopts)
751 if head:
756 if head:
752 self.applied.append(statusentry(head, patch))
757 self.applied.append(statusentry(head, patch))
753 self.applieddirty = True
758 self.applieddirty = True
754 if err:
759 if err:
755 return (err, head)
760 return (err, head)
756 self.savedirty()
761 self.savedirty()
757 return (0, head)
762 return (0, head)
758
763
759 def patch(self, repo, patchfile):
764 def patch(self, repo, patchfile):
760 '''Apply patchfile to the working directory.
765 '''Apply patchfile to the working directory.
761 patchfile: name of patch file'''
766 patchfile: name of patch file'''
762 files = set()
767 files = set()
763 try:
768 try:
764 fuzz = patchmod.patch(self.ui, repo, patchfile, strip=1,
769 fuzz = patchmod.patch(self.ui, repo, patchfile, strip=1,
765 files=files, eolmode=None)
770 files=files, eolmode=None)
766 return (True, list(files), fuzz)
771 return (True, list(files), fuzz)
767 except Exception, inst:
772 except Exception, inst:
768 self.ui.note(str(inst) + '\n')
773 self.ui.note(str(inst) + '\n')
769 if not self.ui.verbose:
774 if not self.ui.verbose:
770 self.ui.warn(_("patch failed, unable to continue (try -v)\n"))
775 self.ui.warn(_("patch failed, unable to continue (try -v)\n"))
771 self.ui.traceback()
776 self.ui.traceback()
772 return (False, list(files), False)
777 return (False, list(files), False)
773
778
774 def apply(self, repo, series, list=False, update_status=True,
779 def apply(self, repo, series, list=False, update_status=True,
775 strict=False, patchdir=None, merge=None, all_files=None,
780 strict=False, patchdir=None, merge=None, all_files=None,
776 tobackup=None, keepchanges=False):
781 tobackup=None, keepchanges=False):
777 wlock = lock = tr = None
782 wlock = lock = tr = None
778 try:
783 try:
779 wlock = repo.wlock()
784 wlock = repo.wlock()
780 lock = repo.lock()
785 lock = repo.lock()
781 tr = repo.transaction("qpush")
786 tr = repo.transaction("qpush")
782 try:
787 try:
783 ret = self._apply(repo, series, list, update_status,
788 ret = self._apply(repo, series, list, update_status,
784 strict, patchdir, merge, all_files=all_files,
789 strict, patchdir, merge, all_files=all_files,
785 tobackup=tobackup, keepchanges=keepchanges)
790 tobackup=tobackup, keepchanges=keepchanges)
786 tr.close()
791 tr.close()
787 self.savedirty()
792 self.savedirty()
788 return ret
793 return ret
789 except AbortNoCleanup:
794 except AbortNoCleanup:
790 tr.close()
795 tr.close()
791 self.savedirty()
796 self.savedirty()
792 return 2, repo.dirstate.p1()
797 return 2, repo.dirstate.p1()
793 except: # re-raises
798 except: # re-raises
794 try:
799 try:
795 tr.abort()
800 tr.abort()
796 finally:
801 finally:
797 repo.invalidate()
802 repo.invalidate()
798 repo.dirstate.invalidate()
803 repo.dirstate.invalidate()
799 self.invalidate()
804 self.invalidate()
800 raise
805 raise
801 finally:
806 finally:
802 release(tr, lock, wlock)
807 release(tr, lock, wlock)
803 self.removeundo(repo)
808 self.removeundo(repo)
804
809
805 def _apply(self, repo, series, list=False, update_status=True,
810 def _apply(self, repo, series, list=False, update_status=True,
806 strict=False, patchdir=None, merge=None, all_files=None,
811 strict=False, patchdir=None, merge=None, all_files=None,
807 tobackup=None, keepchanges=False):
812 tobackup=None, keepchanges=False):
808 """returns (error, hash)
813 """returns (error, hash)
809
814
810 error = 1 for unable to read, 2 for patch failed, 3 for patch
815 error = 1 for unable to read, 2 for patch failed, 3 for patch
811 fuzz. tobackup is None or a set of files to backup before they
816 fuzz. tobackup is None or a set of files to backup before they
812 are modified by a patch.
817 are modified by a patch.
813 """
818 """
814 # TODO unify with commands.py
819 # TODO unify with commands.py
815 if not patchdir:
820 if not patchdir:
816 patchdir = self.path
821 patchdir = self.path
817 err = 0
822 err = 0
818 n = None
823 n = None
819 for patchname in series:
824 for patchname in series:
820 pushable, reason = self.pushable(patchname)
825 pushable, reason = self.pushable(patchname)
821 if not pushable:
826 if not pushable:
822 self.explainpushable(patchname, all_patches=True)
827 self.explainpushable(patchname, all_patches=True)
823 continue
828 continue
824 self.ui.status(_("applying %s\n") % patchname)
829 self.ui.status(_("applying %s\n") % patchname)
825 pf = os.path.join(patchdir, patchname)
830 pf = os.path.join(patchdir, patchname)
826
831
827 try:
832 try:
828 ph = patchheader(self.join(patchname), self.plainmode)
833 ph = patchheader(self.join(patchname), self.plainmode)
829 except IOError:
834 except IOError:
830 self.ui.warn(_("unable to read %s\n") % patchname)
835 self.ui.warn(_("unable to read %s\n") % patchname)
831 err = 1
836 err = 1
832 break
837 break
833
838
834 message = ph.message
839 message = ph.message
835 if not message:
840 if not message:
836 # The commit message should not be translated
841 # The commit message should not be translated
837 message = "imported patch %s\n" % patchname
842 message = "imported patch %s\n" % patchname
838 else:
843 else:
839 if list:
844 if list:
840 # The commit message should not be translated
845 # The commit message should not be translated
841 message.append("\nimported patch %s" % patchname)
846 message.append("\nimported patch %s" % patchname)
842 message = '\n'.join(message)
847 message = '\n'.join(message)
843
848
844 if ph.haspatch:
849 if ph.haspatch:
845 if tobackup:
850 if tobackup:
846 touched = patchmod.changedfiles(self.ui, repo, pf)
851 touched = patchmod.changedfiles(self.ui, repo, pf)
847 touched = set(touched) & tobackup
852 touched = set(touched) & tobackup
848 if touched and keepchanges:
853 if touched and keepchanges:
849 raise AbortNoCleanup(
854 raise AbortNoCleanup(
850 _("local changes found, refresh first"))
855 _("local changes found, refresh first"))
851 self.backup(repo, touched, copy=True)
856 self.backup(repo, touched, copy=True)
852 tobackup = tobackup - touched
857 tobackup = tobackup - touched
853 (patcherr, files, fuzz) = self.patch(repo, pf)
858 (patcherr, files, fuzz) = self.patch(repo, pf)
854 if all_files is not None:
859 if all_files is not None:
855 all_files.update(files)
860 all_files.update(files)
856 patcherr = not patcherr
861 patcherr = not patcherr
857 else:
862 else:
858 self.ui.warn(_("patch %s is empty\n") % patchname)
863 self.ui.warn(_("patch %s is empty\n") % patchname)
859 patcherr, files, fuzz = 0, [], 0
864 patcherr, files, fuzz = 0, [], 0
860
865
861 if merge and files:
866 if merge and files:
862 # Mark as removed/merged and update dirstate parent info
867 # Mark as removed/merged and update dirstate parent info
863 removed = []
868 removed = []
864 merged = []
869 merged = []
865 for f in files:
870 for f in files:
866 if os.path.lexists(repo.wjoin(f)):
871 if os.path.lexists(repo.wjoin(f)):
867 merged.append(f)
872 merged.append(f)
868 else:
873 else:
869 removed.append(f)
874 removed.append(f)
870 repo.dirstate.beginparentchange()
875 repo.dirstate.beginparentchange()
871 for f in removed:
876 for f in removed:
872 repo.dirstate.remove(f)
877 repo.dirstate.remove(f)
873 for f in merged:
878 for f in merged:
874 repo.dirstate.merge(f)
879 repo.dirstate.merge(f)
875 p1, p2 = repo.dirstate.parents()
880 p1, p2 = repo.dirstate.parents()
876 repo.setparents(p1, merge)
881 repo.setparents(p1, merge)
877 repo.dirstate.endparentchange()
882 repo.dirstate.endparentchange()
878
883
879 if all_files and '.hgsubstate' in all_files:
884 if all_files and '.hgsubstate' in all_files:
880 wctx = repo[None]
885 wctx = repo[None]
881 pctx = repo['.']
886 pctx = repo['.']
882 overwrite = False
887 overwrite = False
883 mergedsubstate = subrepo.submerge(repo, pctx, wctx, wctx,
888 mergedsubstate = subrepo.submerge(repo, pctx, wctx, wctx,
884 overwrite)
889 overwrite)
885 files += mergedsubstate.keys()
890 files += mergedsubstate.keys()
886
891
887 match = scmutil.matchfiles(repo, files or [])
892 match = scmutil.matchfiles(repo, files or [])
888 oldtip = repo['tip']
893 oldtip = repo['tip']
889 n = newcommit(repo, None, message, ph.user, ph.date, match=match,
894 n = newcommit(repo, None, message, ph.user, ph.date, match=match,
890 force=True)
895 force=True)
891 if repo['tip'] == oldtip:
896 if repo['tip'] == oldtip:
892 raise util.Abort(_("qpush exactly duplicates child changeset"))
897 raise util.Abort(_("qpush exactly duplicates child changeset"))
893 if n is None:
898 if n is None:
894 raise util.Abort(_("repository commit failed"))
899 raise util.Abort(_("repository commit failed"))
895
900
896 if update_status:
901 if update_status:
897 self.applied.append(statusentry(n, patchname))
902 self.applied.append(statusentry(n, patchname))
898
903
899 if patcherr:
904 if patcherr:
900 self.ui.warn(_("patch failed, rejects left in working dir\n"))
905 self.ui.warn(_("patch failed, rejects left in working dir\n"))
901 err = 2
906 err = 2
902 break
907 break
903
908
904 if fuzz and strict:
909 if fuzz and strict:
905 self.ui.warn(_("fuzz found when applying patch, stopping\n"))
910 self.ui.warn(_("fuzz found when applying patch, stopping\n"))
906 err = 3
911 err = 3
907 break
912 break
908 return (err, n)
913 return (err, n)
909
914
910 def _cleanup(self, patches, numrevs, keep=False):
915 def _cleanup(self, patches, numrevs, keep=False):
911 if not keep:
916 if not keep:
912 r = self.qrepo()
917 r = self.qrepo()
913 if r:
918 if r:
914 r[None].forget(patches)
919 r[None].forget(patches)
915 for p in patches:
920 for p in patches:
916 try:
921 try:
917 os.unlink(self.join(p))
922 os.unlink(self.join(p))
918 except OSError, inst:
923 except OSError, inst:
919 if inst.errno != errno.ENOENT:
924 if inst.errno != errno.ENOENT:
920 raise
925 raise
921
926
922 qfinished = []
927 qfinished = []
923 if numrevs:
928 if numrevs:
924 qfinished = self.applied[:numrevs]
929 qfinished = self.applied[:numrevs]
925 del self.applied[:numrevs]
930 del self.applied[:numrevs]
926 self.applieddirty = True
931 self.applieddirty = True
927
932
928 unknown = []
933 unknown = []
929
934
930 for (i, p) in sorted([(self.findseries(p), p) for p in patches],
935 for (i, p) in sorted([(self.findseries(p), p) for p in patches],
931 reverse=True):
936 reverse=True):
932 if i is not None:
937 if i is not None:
933 del self.fullseries[i]
938 del self.fullseries[i]
934 else:
939 else:
935 unknown.append(p)
940 unknown.append(p)
936
941
937 if unknown:
942 if unknown:
938 if numrevs:
943 if numrevs:
939 rev = dict((entry.name, entry.node) for entry in qfinished)
944 rev = dict((entry.name, entry.node) for entry in qfinished)
940 for p in unknown:
945 for p in unknown:
941 msg = _('revision %s refers to unknown patches: %s\n')
946 msg = _('revision %s refers to unknown patches: %s\n')
942 self.ui.warn(msg % (short(rev[p]), p))
947 self.ui.warn(msg % (short(rev[p]), p))
943 else:
948 else:
944 msg = _('unknown patches: %s\n')
949 msg = _('unknown patches: %s\n')
945 raise util.Abort(''.join(msg % p for p in unknown))
950 raise util.Abort(''.join(msg % p for p in unknown))
946
951
947 self.parseseries()
952 self.parseseries()
948 self.seriesdirty = True
953 self.seriesdirty = True
949 return [entry.node for entry in qfinished]
954 return [entry.node for entry in qfinished]
950
955
951 def _revpatches(self, repo, revs):
956 def _revpatches(self, repo, revs):
952 firstrev = repo[self.applied[0].node].rev()
957 firstrev = repo[self.applied[0].node].rev()
953 patches = []
958 patches = []
954 for i, rev in enumerate(revs):
959 for i, rev in enumerate(revs):
955
960
956 if rev < firstrev:
961 if rev < firstrev:
957 raise util.Abort(_('revision %d is not managed') % rev)
962 raise util.Abort(_('revision %d is not managed') % rev)
958
963
959 ctx = repo[rev]
964 ctx = repo[rev]
960 base = self.applied[i].node
965 base = self.applied[i].node
961 if ctx.node() != base:
966 if ctx.node() != base:
962 msg = _('cannot delete revision %d above applied patches')
967 msg = _('cannot delete revision %d above applied patches')
963 raise util.Abort(msg % rev)
968 raise util.Abort(msg % rev)
964
969
965 patch = self.applied[i].name
970 patch = self.applied[i].name
966 for fmt in ('[mq]: %s', 'imported patch %s'):
971 for fmt in ('[mq]: %s', 'imported patch %s'):
967 if ctx.description() == fmt % patch:
972 if ctx.description() == fmt % patch:
968 msg = _('patch %s finalized without changeset message\n')
973 msg = _('patch %s finalized without changeset message\n')
969 repo.ui.status(msg % patch)
974 repo.ui.status(msg % patch)
970 break
975 break
971
976
972 patches.append(patch)
977 patches.append(patch)
973 return patches
978 return patches
974
979
975 def finish(self, repo, revs):
980 def finish(self, repo, revs):
976 # Manually trigger phase computation to ensure phasedefaults is
981 # Manually trigger phase computation to ensure phasedefaults is
977 # executed before we remove the patches.
982 # executed before we remove the patches.
978 repo._phasecache
983 repo._phasecache
979 patches = self._revpatches(repo, sorted(revs))
984 patches = self._revpatches(repo, sorted(revs))
980 qfinished = self._cleanup(patches, len(patches))
985 qfinished = self._cleanup(patches, len(patches))
981 if qfinished and repo.ui.configbool('mq', 'secret', False):
986 if qfinished and repo.ui.configbool('mq', 'secret', False):
982 # only use this logic when the secret option is added
987 # only use this logic when the secret option is added
983 oldqbase = repo[qfinished[0]]
988 oldqbase = repo[qfinished[0]]
984 tphase = repo.ui.config('phases', 'new-commit', phases.draft)
989 tphase = repo.ui.config('phases', 'new-commit', phases.draft)
985 if oldqbase.phase() > tphase and oldqbase.p1().phase() <= tphase:
990 if oldqbase.phase() > tphase and oldqbase.p1().phase() <= tphase:
986 tr = repo.transaction('qfinish')
991 tr = repo.transaction('qfinish')
987 try:
992 try:
988 phases.advanceboundary(repo, tr, tphase, qfinished)
993 phases.advanceboundary(repo, tr, tphase, qfinished)
989 tr.close()
994 tr.close()
990 finally:
995 finally:
991 tr.release()
996 tr.release()
992
997
993 def delete(self, repo, patches, opts):
998 def delete(self, repo, patches, opts):
994 if not patches and not opts.get('rev'):
999 if not patches and not opts.get('rev'):
995 raise util.Abort(_('qdelete requires at least one revision or '
1000 raise util.Abort(_('qdelete requires at least one revision or '
996 'patch name'))
1001 'patch name'))
997
1002
998 realpatches = []
1003 realpatches = []
999 for patch in patches:
1004 for patch in patches:
1000 patch = self.lookup(patch, strict=True)
1005 patch = self.lookup(patch, strict=True)
1001 info = self.isapplied(patch)
1006 info = self.isapplied(patch)
1002 if info:
1007 if info:
1003 raise util.Abort(_("cannot delete applied patch %s") % patch)
1008 raise util.Abort(_("cannot delete applied patch %s") % patch)
1004 if patch not in self.series:
1009 if patch not in self.series:
1005 raise util.Abort(_("patch %s not in series file") % patch)
1010 raise util.Abort(_("patch %s not in series file") % patch)
1006 if patch not in realpatches:
1011 if patch not in realpatches:
1007 realpatches.append(patch)
1012 realpatches.append(patch)
1008
1013
1009 numrevs = 0
1014 numrevs = 0
1010 if opts.get('rev'):
1015 if opts.get('rev'):
1011 if not self.applied:
1016 if not self.applied:
1012 raise util.Abort(_('no patches applied'))
1017 raise util.Abort(_('no patches applied'))
1013 revs = scmutil.revrange(repo, opts.get('rev'))
1018 revs = scmutil.revrange(repo, opts.get('rev'))
1014 revs.sort()
1019 revs.sort()
1015 revpatches = self._revpatches(repo, revs)
1020 revpatches = self._revpatches(repo, revs)
1016 realpatches += revpatches
1021 realpatches += revpatches
1017 numrevs = len(revpatches)
1022 numrevs = len(revpatches)
1018
1023
1019 self._cleanup(realpatches, numrevs, opts.get('keep'))
1024 self._cleanup(realpatches, numrevs, opts.get('keep'))
1020
1025
1021 def checktoppatch(self, repo):
1026 def checktoppatch(self, repo):
1022 '''check that working directory is at qtip'''
1027 '''check that working directory is at qtip'''
1023 if self.applied:
1028 if self.applied:
1024 top = self.applied[-1].node
1029 top = self.applied[-1].node
1025 patch = self.applied[-1].name
1030 patch = self.applied[-1].name
1026 if repo.dirstate.p1() != top:
1031 if repo.dirstate.p1() != top:
1027 raise util.Abort(_("working directory revision is not qtip"))
1032 raise util.Abort(_("working directory revision is not qtip"))
1028 return top, patch
1033 return top, patch
1029 return None, None
1034 return None, None
1030
1035
1031 def putsubstate2changes(self, substatestate, changes):
1036 def putsubstate2changes(self, substatestate, changes):
1032 for files in changes[:3]:
1037 for files in changes[:3]:
1033 if '.hgsubstate' in files:
1038 if '.hgsubstate' in files:
1034 return # already listed up
1039 return # already listed up
1035 # not yet listed up
1040 # not yet listed up
1036 if substatestate in 'a?':
1041 if substatestate in 'a?':
1037 changes[1].append('.hgsubstate')
1042 changes[1].append('.hgsubstate')
1038 elif substatestate in 'r':
1043 elif substatestate in 'r':
1039 changes[2].append('.hgsubstate')
1044 changes[2].append('.hgsubstate')
1040 else: # modified
1045 else: # modified
1041 changes[0].append('.hgsubstate')
1046 changes[0].append('.hgsubstate')
1042
1047
1043 def checklocalchanges(self, repo, force=False, refresh=True):
1048 def checklocalchanges(self, repo, force=False, refresh=True):
1044 excsuffix = ''
1049 excsuffix = ''
1045 if refresh:
1050 if refresh:
1046 excsuffix = ', refresh first'
1051 excsuffix = ', refresh first'
1047 # plain versions for i18n tool to detect them
1052 # plain versions for i18n tool to detect them
1048 _("local changes found, refresh first")
1053 _("local changes found, refresh first")
1049 _("local changed subrepos found, refresh first")
1054 _("local changed subrepos found, refresh first")
1050 return checklocalchanges(repo, force, excsuffix)
1055 return checklocalchanges(repo, force, excsuffix)
1051
1056
1052 _reserved = ('series', 'status', 'guards', '.', '..')
1057 _reserved = ('series', 'status', 'guards', '.', '..')
1053 def checkreservedname(self, name):
1058 def checkreservedname(self, name):
1054 if name in self._reserved:
1059 if name in self._reserved:
1055 raise util.Abort(_('"%s" cannot be used as the name of a patch')
1060 raise util.Abort(_('"%s" cannot be used as the name of a patch')
1056 % name)
1061 % name)
1057 for prefix in ('.hg', '.mq'):
1062 for prefix in ('.hg', '.mq'):
1058 if name.startswith(prefix):
1063 if name.startswith(prefix):
1059 raise util.Abort(_('patch name cannot begin with "%s"')
1064 raise util.Abort(_('patch name cannot begin with "%s"')
1060 % prefix)
1065 % prefix)
1061 for c in ('#', ':'):
1066 for c in ('#', ':'):
1062 if c in name:
1067 if c in name:
1063 raise util.Abort(_('"%s" cannot be used in the name of a patch')
1068 raise util.Abort(_('"%s" cannot be used in the name of a patch')
1064 % c)
1069 % c)
1065
1070
1066 def checkpatchname(self, name, force=False):
1071 def checkpatchname(self, name, force=False):
1067 self.checkreservedname(name)
1072 self.checkreservedname(name)
1068 if not force and os.path.exists(self.join(name)):
1073 if not force and os.path.exists(self.join(name)):
1069 if os.path.isdir(self.join(name)):
1074 if os.path.isdir(self.join(name)):
1070 raise util.Abort(_('"%s" already exists as a directory')
1075 raise util.Abort(_('"%s" already exists as a directory')
1071 % name)
1076 % name)
1072 else:
1077 else:
1073 raise util.Abort(_('patch "%s" already exists') % name)
1078 raise util.Abort(_('patch "%s" already exists') % name)
1074
1079
1075 def checkkeepchanges(self, keepchanges, force):
1080 def checkkeepchanges(self, keepchanges, force):
1076 if force and keepchanges:
1081 if force and keepchanges:
1077 raise util.Abort(_('cannot use both --force and --keep-changes'))
1082 raise util.Abort(_('cannot use both --force and --keep-changes'))
1078
1083
1079 def new(self, repo, patchfn, *pats, **opts):
1084 def new(self, repo, patchfn, *pats, **opts):
1080 """options:
1085 """options:
1081 msg: a string or a no-argument function returning a string
1086 msg: a string or a no-argument function returning a string
1082 """
1087 """
1083 msg = opts.get('msg')
1088 msg = opts.get('msg')
1084 edit = opts.get('edit')
1089 edit = opts.get('edit')
1085 editform = opts.get('editform', 'mq.qnew')
1090 editform = opts.get('editform', 'mq.qnew')
1086 user = opts.get('user')
1091 user = opts.get('user')
1087 date = opts.get('date')
1092 date = opts.get('date')
1088 if date:
1093 if date:
1089 date = util.parsedate(date)
1094 date = util.parsedate(date)
1090 diffopts = self.diffopts({'git': opts.get('git')})
1095 diffopts = self.diffopts({'git': opts.get('git')})
1091 if opts.get('checkname', True):
1096 if opts.get('checkname', True):
1092 self.checkpatchname(patchfn)
1097 self.checkpatchname(patchfn)
1093 inclsubs = checksubstate(repo)
1098 inclsubs = checksubstate(repo)
1094 if inclsubs:
1099 if inclsubs:
1095 substatestate = repo.dirstate['.hgsubstate']
1100 substatestate = repo.dirstate['.hgsubstate']
1096 if opts.get('include') or opts.get('exclude') or pats:
1101 if opts.get('include') or opts.get('exclude') or pats:
1097 match = scmutil.match(repo[None], pats, opts)
1102 match = scmutil.match(repo[None], pats, opts)
1098 # detect missing files in pats
1103 # detect missing files in pats
1099 def badfn(f, msg):
1104 def badfn(f, msg):
1100 if f != '.hgsubstate': # .hgsubstate is auto-created
1105 if f != '.hgsubstate': # .hgsubstate is auto-created
1101 raise util.Abort('%s: %s' % (f, msg))
1106 raise util.Abort('%s: %s' % (f, msg))
1102 match.bad = badfn
1107 match.bad = badfn
1103 changes = repo.status(match=match)
1108 changes = repo.status(match=match)
1104 else:
1109 else:
1105 changes = self.checklocalchanges(repo, force=True)
1110 changes = self.checklocalchanges(repo, force=True)
1106 commitfiles = list(inclsubs)
1111 commitfiles = list(inclsubs)
1107 for files in changes[:3]:
1112 for files in changes[:3]:
1108 commitfiles.extend(files)
1113 commitfiles.extend(files)
1109 match = scmutil.matchfiles(repo, commitfiles)
1114 match = scmutil.matchfiles(repo, commitfiles)
1110 if len(repo[None].parents()) > 1:
1115 if len(repo[None].parents()) > 1:
1111 raise util.Abort(_('cannot manage merge changesets'))
1116 raise util.Abort(_('cannot manage merge changesets'))
1112 self.checktoppatch(repo)
1117 self.checktoppatch(repo)
1113 insert = self.fullseriesend()
1118 insert = self.fullseriesend()
1114 wlock = repo.wlock()
1119 wlock = repo.wlock()
1115 try:
1120 try:
1116 try:
1121 try:
1117 # if patch file write fails, abort early
1122 # if patch file write fails, abort early
1118 p = self.opener(patchfn, "w")
1123 p = self.opener(patchfn, "w")
1119 except IOError, e:
1124 except IOError, e:
1120 raise util.Abort(_('cannot write patch "%s": %s')
1125 raise util.Abort(_('cannot write patch "%s": %s')
1121 % (patchfn, e.strerror))
1126 % (patchfn, e.strerror))
1122 try:
1127 try:
1123 defaultmsg = "[mq]: %s" % patchfn
1128 defaultmsg = "[mq]: %s" % patchfn
1124 editor = cmdutil.getcommiteditor(editform=editform)
1129 editor = cmdutil.getcommiteditor(editform=editform)
1125 if edit:
1130 if edit:
1126 def finishdesc(desc):
1131 def finishdesc(desc):
1127 if desc.rstrip():
1132 if desc.rstrip():
1128 return desc
1133 return desc
1129 else:
1134 else:
1130 return defaultmsg
1135 return defaultmsg
1131 # i18n: this message is shown in editor with "HG: " prefix
1136 # i18n: this message is shown in editor with "HG: " prefix
1132 extramsg = _('Leave message empty to use default message.')
1137 extramsg = _('Leave message empty to use default message.')
1133 editor = cmdutil.getcommiteditor(finishdesc=finishdesc,
1138 editor = cmdutil.getcommiteditor(finishdesc=finishdesc,
1134 extramsg=extramsg,
1139 extramsg=extramsg,
1135 editform=editform)
1140 editform=editform)
1136 commitmsg = msg
1141 commitmsg = msg
1137 else:
1142 else:
1138 commitmsg = msg or defaultmsg
1143 commitmsg = msg or defaultmsg
1139
1144
1140 n = newcommit(repo, None, commitmsg, user, date, match=match,
1145 n = newcommit(repo, None, commitmsg, user, date, match=match,
1141 force=True, editor=editor)
1146 force=True, editor=editor)
1142 if n is None:
1147 if n is None:
1143 raise util.Abort(_("repo commit failed"))
1148 raise util.Abort(_("repo commit failed"))
1144 try:
1149 try:
1145 self.fullseries[insert:insert] = [patchfn]
1150 self.fullseries[insert:insert] = [patchfn]
1146 self.applied.append(statusentry(n, patchfn))
1151 self.applied.append(statusentry(n, patchfn))
1147 self.parseseries()
1152 self.parseseries()
1148 self.seriesdirty = True
1153 self.seriesdirty = True
1149 self.applieddirty = True
1154 self.applieddirty = True
1150 nctx = repo[n]
1155 nctx = repo[n]
1151 ph = patchheader(self.join(patchfn), self.plainmode)
1156 ph = patchheader(self.join(patchfn), self.plainmode)
1152 if user:
1157 if user:
1153 ph.setuser(user)
1158 ph.setuser(user)
1154 if date:
1159 if date:
1155 ph.setdate('%s %s' % date)
1160 ph.setdate('%s %s' % date)
1156 ph.setparent(hex(nctx.p1().node()))
1161 ph.setparent(hex(nctx.p1().node()))
1157 msg = nctx.description().strip()
1162 msg = nctx.description().strip()
1158 if msg == defaultmsg.strip():
1163 if msg == defaultmsg.strip():
1159 msg = ''
1164 msg = ''
1160 ph.setmessage(msg)
1165 ph.setmessage(msg)
1161 p.write(str(ph))
1166 p.write(str(ph))
1162 if commitfiles:
1167 if commitfiles:
1163 parent = self.qparents(repo, n)
1168 parent = self.qparents(repo, n)
1164 if inclsubs:
1169 if inclsubs:
1165 self.putsubstate2changes(substatestate, changes)
1170 self.putsubstate2changes(substatestate, changes)
1166 chunks = patchmod.diff(repo, node1=parent, node2=n,
1171 chunks = patchmod.diff(repo, node1=parent, node2=n,
1167 changes=changes, opts=diffopts)
1172 changes=changes, opts=diffopts)
1168 for chunk in chunks:
1173 for chunk in chunks:
1169 p.write(chunk)
1174 p.write(chunk)
1170 p.close()
1175 p.close()
1171 r = self.qrepo()
1176 r = self.qrepo()
1172 if r:
1177 if r:
1173 r[None].add([patchfn])
1178 r[None].add([patchfn])
1174 except: # re-raises
1179 except: # re-raises
1175 repo.rollback()
1180 repo.rollback()
1176 raise
1181 raise
1177 except Exception:
1182 except Exception:
1178 patchpath = self.join(patchfn)
1183 patchpath = self.join(patchfn)
1179 try:
1184 try:
1180 os.unlink(patchpath)
1185 os.unlink(patchpath)
1181 except OSError:
1186 except OSError:
1182 self.ui.warn(_('error unlinking %s\n') % patchpath)
1187 self.ui.warn(_('error unlinking %s\n') % patchpath)
1183 raise
1188 raise
1184 self.removeundo(repo)
1189 self.removeundo(repo)
1185 finally:
1190 finally:
1186 release(wlock)
1191 release(wlock)
1187
1192
1188 def isapplied(self, patch):
1193 def isapplied(self, patch):
1189 """returns (index, rev, patch)"""
1194 """returns (index, rev, patch)"""
1190 for i, a in enumerate(self.applied):
1195 for i, a in enumerate(self.applied):
1191 if a.name == patch:
1196 if a.name == patch:
1192 return (i, a.node, a.name)
1197 return (i, a.node, a.name)
1193 return None
1198 return None
1194
1199
1195 # if the exact patch name does not exist, we try a few
1200 # if the exact patch name does not exist, we try a few
1196 # variations. If strict is passed, we try only #1
1201 # variations. If strict is passed, we try only #1
1197 #
1202 #
1198 # 1) a number (as string) to indicate an offset in the series file
1203 # 1) a number (as string) to indicate an offset in the series file
1199 # 2) a unique substring of the patch name was given
1204 # 2) a unique substring of the patch name was given
1200 # 3) patchname[-+]num to indicate an offset in the series file
1205 # 3) patchname[-+]num to indicate an offset in the series file
1201 def lookup(self, patch, strict=False):
1206 def lookup(self, patch, strict=False):
1202 def partialname(s):
1207 def partialname(s):
1203 if s in self.series:
1208 if s in self.series:
1204 return s
1209 return s
1205 matches = [x for x in self.series if s in x]
1210 matches = [x for x in self.series if s in x]
1206 if len(matches) > 1:
1211 if len(matches) > 1:
1207 self.ui.warn(_('patch name "%s" is ambiguous:\n') % s)
1212 self.ui.warn(_('patch name "%s" is ambiguous:\n') % s)
1208 for m in matches:
1213 for m in matches:
1209 self.ui.warn(' %s\n' % m)
1214 self.ui.warn(' %s\n' % m)
1210 return None
1215 return None
1211 if matches:
1216 if matches:
1212 return matches[0]
1217 return matches[0]
1213 if self.series and self.applied:
1218 if self.series and self.applied:
1214 if s == 'qtip':
1219 if s == 'qtip':
1215 return self.series[self.seriesend(True) - 1]
1220 return self.series[self.seriesend(True) - 1]
1216 if s == 'qbase':
1221 if s == 'qbase':
1217 return self.series[0]
1222 return self.series[0]
1218 return None
1223 return None
1219
1224
1220 if patch in self.series:
1225 if patch in self.series:
1221 return patch
1226 return patch
1222
1227
1223 if not os.path.isfile(self.join(patch)):
1228 if not os.path.isfile(self.join(patch)):
1224 try:
1229 try:
1225 sno = int(patch)
1230 sno = int(patch)
1226 except (ValueError, OverflowError):
1231 except (ValueError, OverflowError):
1227 pass
1232 pass
1228 else:
1233 else:
1229 if -len(self.series) <= sno < len(self.series):
1234 if -len(self.series) <= sno < len(self.series):
1230 return self.series[sno]
1235 return self.series[sno]
1231
1236
1232 if not strict:
1237 if not strict:
1233 res = partialname(patch)
1238 res = partialname(patch)
1234 if res:
1239 if res:
1235 return res
1240 return res
1236 minus = patch.rfind('-')
1241 minus = patch.rfind('-')
1237 if minus >= 0:
1242 if minus >= 0:
1238 res = partialname(patch[:minus])
1243 res = partialname(patch[:minus])
1239 if res:
1244 if res:
1240 i = self.series.index(res)
1245 i = self.series.index(res)
1241 try:
1246 try:
1242 off = int(patch[minus + 1:] or 1)
1247 off = int(patch[minus + 1:] or 1)
1243 except (ValueError, OverflowError):
1248 except (ValueError, OverflowError):
1244 pass
1249 pass
1245 else:
1250 else:
1246 if i - off >= 0:
1251 if i - off >= 0:
1247 return self.series[i - off]
1252 return self.series[i - off]
1248 plus = patch.rfind('+')
1253 plus = patch.rfind('+')
1249 if plus >= 0:
1254 if plus >= 0:
1250 res = partialname(patch[:plus])
1255 res = partialname(patch[:plus])
1251 if res:
1256 if res:
1252 i = self.series.index(res)
1257 i = self.series.index(res)
1253 try:
1258 try:
1254 off = int(patch[plus + 1:] or 1)
1259 off = int(patch[plus + 1:] or 1)
1255 except (ValueError, OverflowError):
1260 except (ValueError, OverflowError):
1256 pass
1261 pass
1257 else:
1262 else:
1258 if i + off < len(self.series):
1263 if i + off < len(self.series):
1259 return self.series[i + off]
1264 return self.series[i + off]
1260 raise util.Abort(_("patch %s not in series") % patch)
1265 raise util.Abort(_("patch %s not in series") % patch)
1261
1266
1262 def push(self, repo, patch=None, force=False, list=False, mergeq=None,
1267 def push(self, repo, patch=None, force=False, list=False, mergeq=None,
1263 all=False, move=False, exact=False, nobackup=False,
1268 all=False, move=False, exact=False, nobackup=False,
1264 keepchanges=False):
1269 keepchanges=False):
1265 self.checkkeepchanges(keepchanges, force)
1270 self.checkkeepchanges(keepchanges, force)
1266 diffopts = self.diffopts()
1271 diffopts = self.diffopts()
1267 wlock = repo.wlock()
1272 wlock = repo.wlock()
1268 try:
1273 try:
1269 heads = []
1274 heads = []
1270 for hs in repo.branchmap().itervalues():
1275 for hs in repo.branchmap().itervalues():
1271 heads.extend(hs)
1276 heads.extend(hs)
1272 if not heads:
1277 if not heads:
1273 heads = [nullid]
1278 heads = [nullid]
1274 if repo.dirstate.p1() not in heads and not exact:
1279 if repo.dirstate.p1() not in heads and not exact:
1275 self.ui.status(_("(working directory not at a head)\n"))
1280 self.ui.status(_("(working directory not at a head)\n"))
1276
1281
1277 if not self.series:
1282 if not self.series:
1278 self.ui.warn(_('no patches in series\n'))
1283 self.ui.warn(_('no patches in series\n'))
1279 return 0
1284 return 0
1280
1285
1281 # Suppose our series file is: A B C and the current 'top'
1286 # Suppose our series file is: A B C and the current 'top'
1282 # patch is B. qpush C should be performed (moving forward)
1287 # patch is B. qpush C should be performed (moving forward)
1283 # qpush B is a NOP (no change) qpush A is an error (can't
1288 # qpush B is a NOP (no change) qpush A is an error (can't
1284 # go backwards with qpush)
1289 # go backwards with qpush)
1285 if patch:
1290 if patch:
1286 patch = self.lookup(patch)
1291 patch = self.lookup(patch)
1287 info = self.isapplied(patch)
1292 info = self.isapplied(patch)
1288 if info and info[0] >= len(self.applied) - 1:
1293 if info and info[0] >= len(self.applied) - 1:
1289 self.ui.warn(
1294 self.ui.warn(
1290 _('qpush: %s is already at the top\n') % patch)
1295 _('qpush: %s is already at the top\n') % patch)
1291 return 0
1296 return 0
1292
1297
1293 pushable, reason = self.pushable(patch)
1298 pushable, reason = self.pushable(patch)
1294 if pushable:
1299 if pushable:
1295 if self.series.index(patch) < self.seriesend():
1300 if self.series.index(patch) < self.seriesend():
1296 raise util.Abort(
1301 raise util.Abort(
1297 _("cannot push to a previous patch: %s") % patch)
1302 _("cannot push to a previous patch: %s") % patch)
1298 else:
1303 else:
1299 if reason:
1304 if reason:
1300 reason = _('guarded by %s') % reason
1305 reason = _('guarded by %s') % reason
1301 else:
1306 else:
1302 reason = _('no matching guards')
1307 reason = _('no matching guards')
1303 self.ui.warn(_("cannot push '%s' - %s\n") % (patch, reason))
1308 self.ui.warn(_("cannot push '%s' - %s\n") % (patch, reason))
1304 return 1
1309 return 1
1305 elif all:
1310 elif all:
1306 patch = self.series[-1]
1311 patch = self.series[-1]
1307 if self.isapplied(patch):
1312 if self.isapplied(patch):
1308 self.ui.warn(_('all patches are currently applied\n'))
1313 self.ui.warn(_('all patches are currently applied\n'))
1309 return 0
1314 return 0
1310
1315
1311 # Following the above example, starting at 'top' of B:
1316 # Following the above example, starting at 'top' of B:
1312 # qpush should be performed (pushes C), but a subsequent
1317 # qpush should be performed (pushes C), but a subsequent
1313 # qpush without an argument is an error (nothing to
1318 # qpush without an argument is an error (nothing to
1314 # apply). This allows a loop of "...while hg qpush..." to
1319 # apply). This allows a loop of "...while hg qpush..." to
1315 # work as it detects an error when done
1320 # work as it detects an error when done
1316 start = self.seriesend()
1321 start = self.seriesend()
1317 if start == len(self.series):
1322 if start == len(self.series):
1318 self.ui.warn(_('patch series already fully applied\n'))
1323 self.ui.warn(_('patch series already fully applied\n'))
1319 return 1
1324 return 1
1320 if not force and not keepchanges:
1325 if not force and not keepchanges:
1321 self.checklocalchanges(repo, refresh=self.applied)
1326 self.checklocalchanges(repo, refresh=self.applied)
1322
1327
1323 if exact:
1328 if exact:
1324 if keepchanges:
1329 if keepchanges:
1325 raise util.Abort(
1330 raise util.Abort(
1326 _("cannot use --exact and --keep-changes together"))
1331 _("cannot use --exact and --keep-changes together"))
1327 if move:
1332 if move:
1328 raise util.Abort(_('cannot use --exact and --move '
1333 raise util.Abort(_('cannot use --exact and --move '
1329 'together'))
1334 'together'))
1330 if self.applied:
1335 if self.applied:
1331 raise util.Abort(_('cannot push --exact with applied '
1336 raise util.Abort(_('cannot push --exact with applied '
1332 'patches'))
1337 'patches'))
1333 root = self.series[start]
1338 root = self.series[start]
1334 target = patchheader(self.join(root), self.plainmode).parent
1339 target = patchheader(self.join(root), self.plainmode).parent
1335 if not target:
1340 if not target:
1336 raise util.Abort(
1341 raise util.Abort(
1337 _("%s does not have a parent recorded") % root)
1342 _("%s does not have a parent recorded") % root)
1338 if not repo[target] == repo['.']:
1343 if not repo[target] == repo['.']:
1339 hg.update(repo, target)
1344 hg.update(repo, target)
1340
1345
1341 if move:
1346 if move:
1342 if not patch:
1347 if not patch:
1343 raise util.Abort(_("please specify the patch to move"))
1348 raise util.Abort(_("please specify the patch to move"))
1344 for fullstart, rpn in enumerate(self.fullseries):
1349 for fullstart, rpn in enumerate(self.fullseries):
1345 # strip markers for patch guards
1350 # strip markers for patch guards
1346 if self.guard_re.split(rpn, 1)[0] == self.series[start]:
1351 if self.guard_re.split(rpn, 1)[0] == self.series[start]:
1347 break
1352 break
1348 for i, rpn in enumerate(self.fullseries[fullstart:]):
1353 for i, rpn in enumerate(self.fullseries[fullstart:]):
1349 # strip markers for patch guards
1354 # strip markers for patch guards
1350 if self.guard_re.split(rpn, 1)[0] == patch:
1355 if self.guard_re.split(rpn, 1)[0] == patch:
1351 break
1356 break
1352 index = fullstart + i
1357 index = fullstart + i
1353 assert index < len(self.fullseries)
1358 assert index < len(self.fullseries)
1354 fullpatch = self.fullseries[index]
1359 fullpatch = self.fullseries[index]
1355 del self.fullseries[index]
1360 del self.fullseries[index]
1356 self.fullseries.insert(fullstart, fullpatch)
1361 self.fullseries.insert(fullstart, fullpatch)
1357 self.parseseries()
1362 self.parseseries()
1358 self.seriesdirty = True
1363 self.seriesdirty = True
1359
1364
1360 self.applieddirty = True
1365 self.applieddirty = True
1361 if start > 0:
1366 if start > 0:
1362 self.checktoppatch(repo)
1367 self.checktoppatch(repo)
1363 if not patch:
1368 if not patch:
1364 patch = self.series[start]
1369 patch = self.series[start]
1365 end = start + 1
1370 end = start + 1
1366 else:
1371 else:
1367 end = self.series.index(patch, start) + 1
1372 end = self.series.index(patch, start) + 1
1368
1373
1369 tobackup = set()
1374 tobackup = set()
1370 if (not nobackup and force) or keepchanges:
1375 if (not nobackup and force) or keepchanges:
1371 status = self.checklocalchanges(repo, force=True)
1376 status = self.checklocalchanges(repo, force=True)
1372 if keepchanges:
1377 if keepchanges:
1373 tobackup.update(status.modified + status.added +
1378 tobackup.update(status.modified + status.added +
1374 status.removed + status.deleted)
1379 status.removed + status.deleted)
1375 else:
1380 else:
1376 tobackup.update(status.modified + status.added)
1381 tobackup.update(status.modified + status.added)
1377
1382
1378 s = self.series[start:end]
1383 s = self.series[start:end]
1379 all_files = set()
1384 all_files = set()
1380 try:
1385 try:
1381 if mergeq:
1386 if mergeq:
1382 ret = self.mergepatch(repo, mergeq, s, diffopts)
1387 ret = self.mergepatch(repo, mergeq, s, diffopts)
1383 else:
1388 else:
1384 ret = self.apply(repo, s, list, all_files=all_files,
1389 ret = self.apply(repo, s, list, all_files=all_files,
1385 tobackup=tobackup, keepchanges=keepchanges)
1390 tobackup=tobackup, keepchanges=keepchanges)
1386 except: # re-raises
1391 except: # re-raises
1387 self.ui.warn(_('cleaning up working directory...'))
1392 self.ui.warn(_('cleaning up working directory...'))
1388 node = repo.dirstate.p1()
1393 node = repo.dirstate.p1()
1389 hg.revert(repo, node, None)
1394 hg.revert(repo, node, None)
1390 # only remove unknown files that we know we touched or
1395 # only remove unknown files that we know we touched or
1391 # created while patching
1396 # created while patching
1392 for f in all_files:
1397 for f in all_files:
1393 if f not in repo.dirstate:
1398 if f not in repo.dirstate:
1394 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1399 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1395 self.ui.warn(_('done\n'))
1400 self.ui.warn(_('done\n'))
1396 raise
1401 raise
1397
1402
1398 if not self.applied:
1403 if not self.applied:
1399 return ret[0]
1404 return ret[0]
1400 top = self.applied[-1].name
1405 top = self.applied[-1].name
1401 if ret[0] and ret[0] > 1:
1406 if ret[0] and ret[0] > 1:
1402 msg = _("errors during apply, please fix and refresh %s\n")
1407 msg = _("errors during apply, please fix and refresh %s\n")
1403 self.ui.write(msg % top)
1408 self.ui.write(msg % top)
1404 else:
1409 else:
1405 self.ui.write(_("now at: %s\n") % top)
1410 self.ui.write(_("now at: %s\n") % top)
1406 return ret[0]
1411 return ret[0]
1407
1412
1408 finally:
1413 finally:
1409 wlock.release()
1414 wlock.release()
1410
1415
1411 def pop(self, repo, patch=None, force=False, update=True, all=False,
1416 def pop(self, repo, patch=None, force=False, update=True, all=False,
1412 nobackup=False, keepchanges=False):
1417 nobackup=False, keepchanges=False):
1413 self.checkkeepchanges(keepchanges, force)
1418 self.checkkeepchanges(keepchanges, force)
1414 wlock = repo.wlock()
1419 wlock = repo.wlock()
1415 try:
1420 try:
1416 if patch:
1421 if patch:
1417 # index, rev, patch
1422 # index, rev, patch
1418 info = self.isapplied(patch)
1423 info = self.isapplied(patch)
1419 if not info:
1424 if not info:
1420 patch = self.lookup(patch)
1425 patch = self.lookup(patch)
1421 info = self.isapplied(patch)
1426 info = self.isapplied(patch)
1422 if not info:
1427 if not info:
1423 raise util.Abort(_("patch %s is not applied") % patch)
1428 raise util.Abort(_("patch %s is not applied") % patch)
1424
1429
1425 if not self.applied:
1430 if not self.applied:
1426 # Allow qpop -a to work repeatedly,
1431 # Allow qpop -a to work repeatedly,
1427 # but not qpop without an argument
1432 # but not qpop without an argument
1428 self.ui.warn(_("no patches applied\n"))
1433 self.ui.warn(_("no patches applied\n"))
1429 return not all
1434 return not all
1430
1435
1431 if all:
1436 if all:
1432 start = 0
1437 start = 0
1433 elif patch:
1438 elif patch:
1434 start = info[0] + 1
1439 start = info[0] + 1
1435 else:
1440 else:
1436 start = len(self.applied) - 1
1441 start = len(self.applied) - 1
1437
1442
1438 if start >= len(self.applied):
1443 if start >= len(self.applied):
1439 self.ui.warn(_("qpop: %s is already at the top\n") % patch)
1444 self.ui.warn(_("qpop: %s is already at the top\n") % patch)
1440 return
1445 return
1441
1446
1442 if not update:
1447 if not update:
1443 parents = repo.dirstate.parents()
1448 parents = repo.dirstate.parents()
1444 rr = [x.node for x in self.applied]
1449 rr = [x.node for x in self.applied]
1445 for p in parents:
1450 for p in parents:
1446 if p in rr:
1451 if p in rr:
1447 self.ui.warn(_("qpop: forcing dirstate update\n"))
1452 self.ui.warn(_("qpop: forcing dirstate update\n"))
1448 update = True
1453 update = True
1449 else:
1454 else:
1450 parents = [p.node() for p in repo[None].parents()]
1455 parents = [p.node() for p in repo[None].parents()]
1451 needupdate = False
1456 needupdate = False
1452 for entry in self.applied[start:]:
1457 for entry in self.applied[start:]:
1453 if entry.node in parents:
1458 if entry.node in parents:
1454 needupdate = True
1459 needupdate = True
1455 break
1460 break
1456 update = needupdate
1461 update = needupdate
1457
1462
1458 tobackup = set()
1463 tobackup = set()
1459 if update:
1464 if update:
1460 s = self.checklocalchanges(repo, force=force or keepchanges)
1465 s = self.checklocalchanges(repo, force=force or keepchanges)
1461 if force:
1466 if force:
1462 if not nobackup:
1467 if not nobackup:
1463 tobackup.update(s.modified + s.added)
1468 tobackup.update(s.modified + s.added)
1464 elif keepchanges:
1469 elif keepchanges:
1465 tobackup.update(s.modified + s.added +
1470 tobackup.update(s.modified + s.added +
1466 s.removed + s.deleted)
1471 s.removed + s.deleted)
1467
1472
1468 self.applieddirty = True
1473 self.applieddirty = True
1469 end = len(self.applied)
1474 end = len(self.applied)
1470 rev = self.applied[start].node
1475 rev = self.applied[start].node
1471
1476
1472 try:
1477 try:
1473 heads = repo.changelog.heads(rev)
1478 heads = repo.changelog.heads(rev)
1474 except error.LookupError:
1479 except error.LookupError:
1475 node = short(rev)
1480 node = short(rev)
1476 raise util.Abort(_('trying to pop unknown node %s') % node)
1481 raise util.Abort(_('trying to pop unknown node %s') % node)
1477
1482
1478 if heads != [self.applied[-1].node]:
1483 if heads != [self.applied[-1].node]:
1479 raise util.Abort(_("popping would remove a revision not "
1484 raise util.Abort(_("popping would remove a revision not "
1480 "managed by this patch queue"))
1485 "managed by this patch queue"))
1481 if not repo[self.applied[-1].node].mutable():
1486 if not repo[self.applied[-1].node].mutable():
1482 raise util.Abort(
1487 raise util.Abort(
1483 _("popping would remove an immutable revision"),
1488 _("popping would remove an immutable revision"),
1484 hint=_('see "hg help phases" for details'))
1489 hint=_('see "hg help phases" for details'))
1485
1490
1486 # we know there are no local changes, so we can make a simplified
1491 # we know there are no local changes, so we can make a simplified
1487 # form of hg.update.
1492 # form of hg.update.
1488 if update:
1493 if update:
1489 qp = self.qparents(repo, rev)
1494 qp = self.qparents(repo, rev)
1490 ctx = repo[qp]
1495 ctx = repo[qp]
1491 m, a, r, d = repo.status(qp, '.')[:4]
1496 m, a, r, d = repo.status(qp, '.')[:4]
1492 if d:
1497 if d:
1493 raise util.Abort(_("deletions found between repo revs"))
1498 raise util.Abort(_("deletions found between repo revs"))
1494
1499
1495 tobackup = set(a + m + r) & tobackup
1500 tobackup = set(a + m + r) & tobackup
1496 if keepchanges and tobackup:
1501 if keepchanges and tobackup:
1497 raise util.Abort(_("local changes found, refresh first"))
1502 raise util.Abort(_("local changes found, refresh first"))
1498 self.backup(repo, tobackup)
1503 self.backup(repo, tobackup)
1499 repo.dirstate.beginparentchange()
1504 repo.dirstate.beginparentchange()
1500 for f in a:
1505 for f in a:
1501 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1506 util.unlinkpath(repo.wjoin(f), ignoremissing=True)
1502 repo.dirstate.drop(f)
1507 repo.dirstate.drop(f)
1503 for f in m + r:
1508 for f in m + r:
1504 fctx = ctx[f]
1509 fctx = ctx[f]
1505 repo.wwrite(f, fctx.data(), fctx.flags())
1510 repo.wwrite(f, fctx.data(), fctx.flags())
1506 repo.dirstate.normal(f)
1511 repo.dirstate.normal(f)
1507 repo.setparents(qp, nullid)
1512 repo.setparents(qp, nullid)
1508 repo.dirstate.endparentchange()
1513 repo.dirstate.endparentchange()
1509 for patch in reversed(self.applied[start:end]):
1514 for patch in reversed(self.applied[start:end]):
1510 self.ui.status(_("popping %s\n") % patch.name)
1515 self.ui.status(_("popping %s\n") % patch.name)
1511 del self.applied[start:end]
1516 del self.applied[start:end]
1512 strip(self.ui, repo, [rev], update=False, backup=False)
1517 strip(self.ui, repo, [rev], update=False, backup=False)
1513 for s, state in repo['.'].substate.items():
1518 for s, state in repo['.'].substate.items():
1514 repo['.'].sub(s).get(state)
1519 repo['.'].sub(s).get(state)
1515 if self.applied:
1520 if self.applied:
1516 self.ui.write(_("now at: %s\n") % self.applied[-1].name)
1521 self.ui.write(_("now at: %s\n") % self.applied[-1].name)
1517 else:
1522 else:
1518 self.ui.write(_("patch queue now empty\n"))
1523 self.ui.write(_("patch queue now empty\n"))
1519 finally:
1524 finally:
1520 wlock.release()
1525 wlock.release()
1521
1526
1522 def diff(self, repo, pats, opts):
1527 def diff(self, repo, pats, opts):
1523 top, patch = self.checktoppatch(repo)
1528 top, patch = self.checktoppatch(repo)
1524 if not top:
1529 if not top:
1525 self.ui.write(_("no patches applied\n"))
1530 self.ui.write(_("no patches applied\n"))
1526 return
1531 return
1527 qp = self.qparents(repo, top)
1532 qp = self.qparents(repo, top)
1528 if opts.get('reverse'):
1533 if opts.get('reverse'):
1529 node1, node2 = None, qp
1534 node1, node2 = None, qp
1530 else:
1535 else:
1531 node1, node2 = qp, None
1536 node1, node2 = qp, None
1532 diffopts = self.diffopts(opts, patch)
1537 diffopts = self.diffopts(opts, patch)
1533 self.printdiff(repo, diffopts, node1, node2, files=pats, opts=opts)
1538 self.printdiff(repo, diffopts, node1, node2, files=pats, opts=opts)
1534
1539
1535 def refresh(self, repo, pats=None, **opts):
1540 def refresh(self, repo, pats=None, **opts):
1536 if not self.applied:
1541 if not self.applied:
1537 self.ui.write(_("no patches applied\n"))
1542 self.ui.write(_("no patches applied\n"))
1538 return 1
1543 return 1
1539 msg = opts.get('msg', '').rstrip()
1544 msg = opts.get('msg', '').rstrip()
1540 edit = opts.get('edit')
1545 edit = opts.get('edit')
1541 editform = opts.get('editform', 'mq.qrefresh')
1546 editform = opts.get('editform', 'mq.qrefresh')
1542 newuser = opts.get('user')
1547 newuser = opts.get('user')
1543 newdate = opts.get('date')
1548 newdate = opts.get('date')
1544 if newdate:
1549 if newdate:
1545 newdate = '%d %d' % util.parsedate(newdate)
1550 newdate = '%d %d' % util.parsedate(newdate)
1546 wlock = repo.wlock()
1551 wlock = repo.wlock()
1547
1552
1548 try:
1553 try:
1549 self.checktoppatch(repo)
1554 self.checktoppatch(repo)
1550 (top, patchfn) = (self.applied[-1].node, self.applied[-1].name)
1555 (top, patchfn) = (self.applied[-1].node, self.applied[-1].name)
1551 if repo.changelog.heads(top) != [top]:
1556 if repo.changelog.heads(top) != [top]:
1552 raise util.Abort(_("cannot refresh a revision with children"))
1557 raise util.Abort(_("cannot refresh a revision with children"))
1553 if not repo[top].mutable():
1558 if not repo[top].mutable():
1554 raise util.Abort(_("cannot refresh immutable revision"),
1559 raise util.Abort(_("cannot refresh immutable revision"),
1555 hint=_('see "hg help phases" for details'))
1560 hint=_('see "hg help phases" for details'))
1556
1561
1557 cparents = repo.changelog.parents(top)
1562 cparents = repo.changelog.parents(top)
1558 patchparent = self.qparents(repo, top)
1563 patchparent = self.qparents(repo, top)
1559
1564
1560 inclsubs = checksubstate(repo, hex(patchparent))
1565 inclsubs = checksubstate(repo, hex(patchparent))
1561 if inclsubs:
1566 if inclsubs:
1562 substatestate = repo.dirstate['.hgsubstate']
1567 substatestate = repo.dirstate['.hgsubstate']
1563
1568
1564 ph = patchheader(self.join(patchfn), self.plainmode)
1569 ph = patchheader(self.join(patchfn), self.plainmode)
1565 diffopts = self.diffopts({'git': opts.get('git')}, patchfn)
1570 diffopts = self.diffopts({'git': opts.get('git')}, patchfn)
1566 if newuser:
1571 if newuser:
1567 ph.setuser(newuser)
1572 ph.setuser(newuser)
1568 if newdate:
1573 if newdate:
1569 ph.setdate(newdate)
1574 ph.setdate(newdate)
1570 ph.setparent(hex(patchparent))
1575 ph.setparent(hex(patchparent))
1571
1576
1572 # only commit new patch when write is complete
1577 # only commit new patch when write is complete
1573 patchf = self.opener(patchfn, 'w', atomictemp=True)
1578 patchf = self.opener(patchfn, 'w', atomictemp=True)
1574
1579
1575 # update the dirstate in place, strip off the qtip commit
1580 # update the dirstate in place, strip off the qtip commit
1576 # and then commit.
1581 # and then commit.
1577 #
1582 #
1578 # this should really read:
1583 # this should really read:
1579 # mm, dd, aa = repo.status(top, patchparent)[:3]
1584 # mm, dd, aa = repo.status(top, patchparent)[:3]
1580 # but we do it backwards to take advantage of manifest/changelog
1585 # but we do it backwards to take advantage of manifest/changelog
1581 # caching against the next repo.status call
1586 # caching against the next repo.status call
1582 mm, aa, dd = repo.status(patchparent, top)[:3]
1587 mm, aa, dd = repo.status(patchparent, top)[:3]
1583 changes = repo.changelog.read(top)
1588 changes = repo.changelog.read(top)
1584 man = repo.manifest.read(changes[0])
1589 man = repo.manifest.read(changes[0])
1585 aaa = aa[:]
1590 aaa = aa[:]
1586 matchfn = scmutil.match(repo[None], pats, opts)
1591 matchfn = scmutil.match(repo[None], pats, opts)
1587 # in short mode, we only diff the files included in the
1592 # in short mode, we only diff the files included in the
1588 # patch already plus specified files
1593 # patch already plus specified files
1589 if opts.get('short'):
1594 if opts.get('short'):
1590 # if amending a patch, we start with existing
1595 # if amending a patch, we start with existing
1591 # files plus specified files - unfiltered
1596 # files plus specified files - unfiltered
1592 match = scmutil.matchfiles(repo, mm + aa + dd + matchfn.files())
1597 match = scmutil.matchfiles(repo, mm + aa + dd + matchfn.files())
1593 # filter with include/exclude options
1598 # filter with include/exclude options
1594 matchfn = scmutil.match(repo[None], opts=opts)
1599 matchfn = scmutil.match(repo[None], opts=opts)
1595 else:
1600 else:
1596 match = scmutil.matchall(repo)
1601 match = scmutil.matchall(repo)
1597 m, a, r, d = repo.status(match=match)[:4]
1602 m, a, r, d = repo.status(match=match)[:4]
1598 mm = set(mm)
1603 mm = set(mm)
1599 aa = set(aa)
1604 aa = set(aa)
1600 dd = set(dd)
1605 dd = set(dd)
1601
1606
1602 # we might end up with files that were added between
1607 # we might end up with files that were added between
1603 # qtip and the dirstate parent, but then changed in the
1608 # qtip and the dirstate parent, but then changed in the
1604 # local dirstate. in this case, we want them to only
1609 # local dirstate. in this case, we want them to only
1605 # show up in the added section
1610 # show up in the added section
1606 for x in m:
1611 for x in m:
1607 if x not in aa:
1612 if x not in aa:
1608 mm.add(x)
1613 mm.add(x)
1609 # we might end up with files added by the local dirstate that
1614 # we might end up with files added by the local dirstate that
1610 # were deleted by the patch. In this case, they should only
1615 # were deleted by the patch. In this case, they should only
1611 # show up in the changed section.
1616 # show up in the changed section.
1612 for x in a:
1617 for x in a:
1613 if x in dd:
1618 if x in dd:
1614 dd.remove(x)
1619 dd.remove(x)
1615 mm.add(x)
1620 mm.add(x)
1616 else:
1621 else:
1617 aa.add(x)
1622 aa.add(x)
1618 # make sure any files deleted in the local dirstate
1623 # make sure any files deleted in the local dirstate
1619 # are not in the add or change column of the patch
1624 # are not in the add or change column of the patch
1620 forget = []
1625 forget = []
1621 for x in d + r:
1626 for x in d + r:
1622 if x in aa:
1627 if x in aa:
1623 aa.remove(x)
1628 aa.remove(x)
1624 forget.append(x)
1629 forget.append(x)
1625 continue
1630 continue
1626 else:
1631 else:
1627 mm.discard(x)
1632 mm.discard(x)
1628 dd.add(x)
1633 dd.add(x)
1629
1634
1630 m = list(mm)
1635 m = list(mm)
1631 r = list(dd)
1636 r = list(dd)
1632 a = list(aa)
1637 a = list(aa)
1633
1638
1634 # create 'match' that includes the files to be recommitted.
1639 # create 'match' that includes the files to be recommitted.
1635 # apply matchfn via repo.status to ensure correct case handling.
1640 # apply matchfn via repo.status to ensure correct case handling.
1636 cm, ca, cr, cd = repo.status(patchparent, match=matchfn)[:4]
1641 cm, ca, cr, cd = repo.status(patchparent, match=matchfn)[:4]
1637 allmatches = set(cm + ca + cr + cd)
1642 allmatches = set(cm + ca + cr + cd)
1638 refreshchanges = [x.intersection(allmatches) for x in (mm, aa, dd)]
1643 refreshchanges = [x.intersection(allmatches) for x in (mm, aa, dd)]
1639
1644
1640 files = set(inclsubs)
1645 files = set(inclsubs)
1641 for x in refreshchanges:
1646 for x in refreshchanges:
1642 files.update(x)
1647 files.update(x)
1643 match = scmutil.matchfiles(repo, files)
1648 match = scmutil.matchfiles(repo, files)
1644
1649
1645 bmlist = repo[top].bookmarks()
1650 bmlist = repo[top].bookmarks()
1646
1651
1647 try:
1652 try:
1648 repo.dirstate.beginparentchange()
1653 repo.dirstate.beginparentchange()
1649 if diffopts.git or diffopts.upgrade:
1654 if diffopts.git or diffopts.upgrade:
1650 copies = {}
1655 copies = {}
1651 for dst in a:
1656 for dst in a:
1652 src = repo.dirstate.copied(dst)
1657 src = repo.dirstate.copied(dst)
1653 # during qfold, the source file for copies may
1658 # during qfold, the source file for copies may
1654 # be removed. Treat this as a simple add.
1659 # be removed. Treat this as a simple add.
1655 if src is not None and src in repo.dirstate:
1660 if src is not None and src in repo.dirstate:
1656 copies.setdefault(src, []).append(dst)
1661 copies.setdefault(src, []).append(dst)
1657 repo.dirstate.add(dst)
1662 repo.dirstate.add(dst)
1658 # remember the copies between patchparent and qtip
1663 # remember the copies between patchparent and qtip
1659 for dst in aaa:
1664 for dst in aaa:
1660 f = repo.file(dst)
1665 f = repo.file(dst)
1661 src = f.renamed(man[dst])
1666 src = f.renamed(man[dst])
1662 if src:
1667 if src:
1663 copies.setdefault(src[0], []).extend(
1668 copies.setdefault(src[0], []).extend(
1664 copies.get(dst, []))
1669 copies.get(dst, []))
1665 if dst in a:
1670 if dst in a:
1666 copies[src[0]].append(dst)
1671 copies[src[0]].append(dst)
1667 # we can't copy a file created by the patch itself
1672 # we can't copy a file created by the patch itself
1668 if dst in copies:
1673 if dst in copies:
1669 del copies[dst]
1674 del copies[dst]
1670 for src, dsts in copies.iteritems():
1675 for src, dsts in copies.iteritems():
1671 for dst in dsts:
1676 for dst in dsts:
1672 repo.dirstate.copy(src, dst)
1677 repo.dirstate.copy(src, dst)
1673 else:
1678 else:
1674 for dst in a:
1679 for dst in a:
1675 repo.dirstate.add(dst)
1680 repo.dirstate.add(dst)
1676 # Drop useless copy information
1681 # Drop useless copy information
1677 for f in list(repo.dirstate.copies()):
1682 for f in list(repo.dirstate.copies()):
1678 repo.dirstate.copy(None, f)
1683 repo.dirstate.copy(None, f)
1679 for f in r:
1684 for f in r:
1680 repo.dirstate.remove(f)
1685 repo.dirstate.remove(f)
1681 # if the patch excludes a modified file, mark that
1686 # if the patch excludes a modified file, mark that
1682 # file with mtime=0 so status can see it.
1687 # file with mtime=0 so status can see it.
1683 mm = []
1688 mm = []
1684 for i in xrange(len(m) - 1, -1, -1):
1689 for i in xrange(len(m) - 1, -1, -1):
1685 if not matchfn(m[i]):
1690 if not matchfn(m[i]):
1686 mm.append(m[i])
1691 mm.append(m[i])
1687 del m[i]
1692 del m[i]
1688 for f in m:
1693 for f in m:
1689 repo.dirstate.normal(f)
1694 repo.dirstate.normal(f)
1690 for f in mm:
1695 for f in mm:
1691 repo.dirstate.normallookup(f)
1696 repo.dirstate.normallookup(f)
1692 for f in forget:
1697 for f in forget:
1693 repo.dirstate.drop(f)
1698 repo.dirstate.drop(f)
1694
1699
1695 user = ph.user or changes[1]
1700 user = ph.user or changes[1]
1696
1701
1697 oldphase = repo[top].phase()
1702 oldphase = repo[top].phase()
1698
1703
1699 # assumes strip can roll itself back if interrupted
1704 # assumes strip can roll itself back if interrupted
1700 repo.setparents(*cparents)
1705 repo.setparents(*cparents)
1701 repo.dirstate.endparentchange()
1706 repo.dirstate.endparentchange()
1702 self.applied.pop()
1707 self.applied.pop()
1703 self.applieddirty = True
1708 self.applieddirty = True
1704 strip(self.ui, repo, [top], update=False, backup=False)
1709 strip(self.ui, repo, [top], update=False, backup=False)
1705 except: # re-raises
1710 except: # re-raises
1706 repo.dirstate.invalidate()
1711 repo.dirstate.invalidate()
1707 raise
1712 raise
1708
1713
1709 try:
1714 try:
1710 # might be nice to attempt to roll back strip after this
1715 # might be nice to attempt to roll back strip after this
1711
1716
1712 defaultmsg = "[mq]: %s" % patchfn
1717 defaultmsg = "[mq]: %s" % patchfn
1713 editor = cmdutil.getcommiteditor(editform=editform)
1718 editor = cmdutil.getcommiteditor(editform=editform)
1714 if edit:
1719 if edit:
1715 def finishdesc(desc):
1720 def finishdesc(desc):
1716 if desc.rstrip():
1721 if desc.rstrip():
1717 ph.setmessage(desc)
1722 ph.setmessage(desc)
1718 return desc
1723 return desc
1719 return defaultmsg
1724 return defaultmsg
1720 # i18n: this message is shown in editor with "HG: " prefix
1725 # i18n: this message is shown in editor with "HG: " prefix
1721 extramsg = _('Leave message empty to use default message.')
1726 extramsg = _('Leave message empty to use default message.')
1722 editor = cmdutil.getcommiteditor(finishdesc=finishdesc,
1727 editor = cmdutil.getcommiteditor(finishdesc=finishdesc,
1723 extramsg=extramsg,
1728 extramsg=extramsg,
1724 editform=editform)
1729 editform=editform)
1725 message = msg or "\n".join(ph.message)
1730 message = msg or "\n".join(ph.message)
1726 elif not msg:
1731 elif not msg:
1727 if not ph.message:
1732 if not ph.message:
1728 message = defaultmsg
1733 message = defaultmsg
1729 else:
1734 else:
1730 message = "\n".join(ph.message)
1735 message = "\n".join(ph.message)
1731 else:
1736 else:
1732 message = msg
1737 message = msg
1733 ph.setmessage(msg)
1738 ph.setmessage(msg)
1734
1739
1735 # Ensure we create a new changeset in the same phase than
1740 # Ensure we create a new changeset in the same phase than
1736 # the old one.
1741 # the old one.
1737 n = newcommit(repo, oldphase, message, user, ph.date,
1742 n = newcommit(repo, oldphase, message, user, ph.date,
1738 match=match, force=True, editor=editor)
1743 match=match, force=True, editor=editor)
1739 # only write patch after a successful commit
1744 # only write patch after a successful commit
1740 c = [list(x) for x in refreshchanges]
1745 c = [list(x) for x in refreshchanges]
1741 if inclsubs:
1746 if inclsubs:
1742 self.putsubstate2changes(substatestate, c)
1747 self.putsubstate2changes(substatestate, c)
1743 chunks = patchmod.diff(repo, patchparent,
1748 chunks = patchmod.diff(repo, patchparent,
1744 changes=c, opts=diffopts)
1749 changes=c, opts=diffopts)
1745 comments = str(ph)
1750 comments = str(ph)
1746 if comments:
1751 if comments:
1747 patchf.write(comments)
1752 patchf.write(comments)
1748 for chunk in chunks:
1753 for chunk in chunks:
1749 patchf.write(chunk)
1754 patchf.write(chunk)
1750 patchf.close()
1755 patchf.close()
1751
1756
1752 marks = repo._bookmarks
1757 marks = repo._bookmarks
1753 for bm in bmlist:
1758 for bm in bmlist:
1754 marks[bm] = n
1759 marks[bm] = n
1755 marks.write()
1760 marks.write()
1756
1761
1757 self.applied.append(statusentry(n, patchfn))
1762 self.applied.append(statusentry(n, patchfn))
1758 except: # re-raises
1763 except: # re-raises
1759 ctx = repo[cparents[0]]
1764 ctx = repo[cparents[0]]
1760 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1765 repo.dirstate.rebuild(ctx.node(), ctx.manifest())
1761 self.savedirty()
1766 self.savedirty()
1762 self.ui.warn(_('refresh interrupted while patch was popped! '
1767 self.ui.warn(_('refresh interrupted while patch was popped! '
1763 '(revert --all, qpush to recover)\n'))
1768 '(revert --all, qpush to recover)\n'))
1764 raise
1769 raise
1765 finally:
1770 finally:
1766 wlock.release()
1771 wlock.release()
1767 self.removeundo(repo)
1772 self.removeundo(repo)
1768
1773
1769 def init(self, repo, create=False):
1774 def init(self, repo, create=False):
1770 if not create and os.path.isdir(self.path):
1775 if not create and os.path.isdir(self.path):
1771 raise util.Abort(_("patch queue directory already exists"))
1776 raise util.Abort(_("patch queue directory already exists"))
1772 try:
1777 try:
1773 os.mkdir(self.path)
1778 os.mkdir(self.path)
1774 except OSError, inst:
1779 except OSError, inst:
1775 if inst.errno != errno.EEXIST or not create:
1780 if inst.errno != errno.EEXIST or not create:
1776 raise
1781 raise
1777 if create:
1782 if create:
1778 return self.qrepo(create=True)
1783 return self.qrepo(create=True)
1779
1784
1780 def unapplied(self, repo, patch=None):
1785 def unapplied(self, repo, patch=None):
1781 if patch and patch not in self.series:
1786 if patch and patch not in self.series:
1782 raise util.Abort(_("patch %s is not in series file") % patch)
1787 raise util.Abort(_("patch %s is not in series file") % patch)
1783 if not patch:
1788 if not patch:
1784 start = self.seriesend()
1789 start = self.seriesend()
1785 else:
1790 else:
1786 start = self.series.index(patch) + 1
1791 start = self.series.index(patch) + 1
1787 unapplied = []
1792 unapplied = []
1788 for i in xrange(start, len(self.series)):
1793 for i in xrange(start, len(self.series)):
1789 pushable, reason = self.pushable(i)
1794 pushable, reason = self.pushable(i)
1790 if pushable:
1795 if pushable:
1791 unapplied.append((i, self.series[i]))
1796 unapplied.append((i, self.series[i]))
1792 self.explainpushable(i)
1797 self.explainpushable(i)
1793 return unapplied
1798 return unapplied
1794
1799
1795 def qseries(self, repo, missing=None, start=0, length=None, status=None,
1800 def qseries(self, repo, missing=None, start=0, length=None, status=None,
1796 summary=False):
1801 summary=False):
1797 def displayname(pfx, patchname, state):
1802 def displayname(pfx, patchname, state):
1798 if pfx:
1803 if pfx:
1799 self.ui.write(pfx)
1804 self.ui.write(pfx)
1800 if summary:
1805 if summary:
1801 ph = patchheader(self.join(patchname), self.plainmode)
1806 ph = patchheader(self.join(patchname), self.plainmode)
1802 msg = ph.message and ph.message[0] or ''
1807 msg = ph.message and ph.message[0] or ''
1803 if self.ui.formatted():
1808 if self.ui.formatted():
1804 width = self.ui.termwidth() - len(pfx) - len(patchname) - 2
1809 width = self.ui.termwidth() - len(pfx) - len(patchname) - 2
1805 if width > 0:
1810 if width > 0:
1806 msg = util.ellipsis(msg, width)
1811 msg = util.ellipsis(msg, width)
1807 else:
1812 else:
1808 msg = ''
1813 msg = ''
1809 self.ui.write(patchname, label='qseries.' + state)
1814 self.ui.write(patchname, label='qseries.' + state)
1810 self.ui.write(': ')
1815 self.ui.write(': ')
1811 self.ui.write(msg, label='qseries.message.' + state)
1816 self.ui.write(msg, label='qseries.message.' + state)
1812 else:
1817 else:
1813 self.ui.write(patchname, label='qseries.' + state)
1818 self.ui.write(patchname, label='qseries.' + state)
1814 self.ui.write('\n')
1819 self.ui.write('\n')
1815
1820
1816 applied = set([p.name for p in self.applied])
1821 applied = set([p.name for p in self.applied])
1817 if length is None:
1822 if length is None:
1818 length = len(self.series) - start
1823 length = len(self.series) - start
1819 if not missing:
1824 if not missing:
1820 if self.ui.verbose:
1825 if self.ui.verbose:
1821 idxwidth = len(str(start + length - 1))
1826 idxwidth = len(str(start + length - 1))
1822 for i in xrange(start, start + length):
1827 for i in xrange(start, start + length):
1823 patch = self.series[i]
1828 patch = self.series[i]
1824 if patch in applied:
1829 if patch in applied:
1825 char, state = 'A', 'applied'
1830 char, state = 'A', 'applied'
1826 elif self.pushable(i)[0]:
1831 elif self.pushable(i)[0]:
1827 char, state = 'U', 'unapplied'
1832 char, state = 'U', 'unapplied'
1828 else:
1833 else:
1829 char, state = 'G', 'guarded'
1834 char, state = 'G', 'guarded'
1830 pfx = ''
1835 pfx = ''
1831 if self.ui.verbose:
1836 if self.ui.verbose:
1832 pfx = '%*d %s ' % (idxwidth, i, char)
1837 pfx = '%*d %s ' % (idxwidth, i, char)
1833 elif status and status != char:
1838 elif status and status != char:
1834 continue
1839 continue
1835 displayname(pfx, patch, state)
1840 displayname(pfx, patch, state)
1836 else:
1841 else:
1837 msng_list = []
1842 msng_list = []
1838 for root, dirs, files in os.walk(self.path):
1843 for root, dirs, files in os.walk(self.path):
1839 d = root[len(self.path) + 1:]
1844 d = root[len(self.path) + 1:]
1840 for f in files:
1845 for f in files:
1841 fl = os.path.join(d, f)
1846 fl = os.path.join(d, f)
1842 if (fl not in self.series and
1847 if (fl not in self.series and
1843 fl not in (self.statuspath, self.seriespath,
1848 fl not in (self.statuspath, self.seriespath,
1844 self.guardspath)
1849 self.guardspath)
1845 and not fl.startswith('.')):
1850 and not fl.startswith('.')):
1846 msng_list.append(fl)
1851 msng_list.append(fl)
1847 for x in sorted(msng_list):
1852 for x in sorted(msng_list):
1848 pfx = self.ui.verbose and ('D ') or ''
1853 pfx = self.ui.verbose and ('D ') or ''
1849 displayname(pfx, x, 'missing')
1854 displayname(pfx, x, 'missing')
1850
1855
1851 def issaveline(self, l):
1856 def issaveline(self, l):
1852 if l.name == '.hg.patches.save.line':
1857 if l.name == '.hg.patches.save.line':
1853 return True
1858 return True
1854
1859
1855 def qrepo(self, create=False):
1860 def qrepo(self, create=False):
1856 ui = self.baseui.copy()
1861 ui = self.baseui.copy()
1857 if create or os.path.isdir(self.join(".hg")):
1862 if create or os.path.isdir(self.join(".hg")):
1858 return hg.repository(ui, path=self.path, create=create)
1863 return hg.repository(ui, path=self.path, create=create)
1859
1864
1860 def restore(self, repo, rev, delete=None, qupdate=None):
1865 def restore(self, repo, rev, delete=None, qupdate=None):
1861 desc = repo[rev].description().strip()
1866 desc = repo[rev].description().strip()
1862 lines = desc.splitlines()
1867 lines = desc.splitlines()
1863 i = 0
1868 i = 0
1864 datastart = None
1869 datastart = None
1865 series = []
1870 series = []
1866 applied = []
1871 applied = []
1867 qpp = None
1872 qpp = None
1868 for i, line in enumerate(lines):
1873 for i, line in enumerate(lines):
1869 if line == 'Patch Data:':
1874 if line == 'Patch Data:':
1870 datastart = i + 1
1875 datastart = i + 1
1871 elif line.startswith('Dirstate:'):
1876 elif line.startswith('Dirstate:'):
1872 l = line.rstrip()
1877 l = line.rstrip()
1873 l = l[10:].split(' ')
1878 l = l[10:].split(' ')
1874 qpp = [bin(x) for x in l]
1879 qpp = [bin(x) for x in l]
1875 elif datastart is not None:
1880 elif datastart is not None:
1876 l = line.rstrip()
1881 l = line.rstrip()
1877 n, name = l.split(':', 1)
1882 n, name = l.split(':', 1)
1878 if n:
1883 if n:
1879 applied.append(statusentry(bin(n), name))
1884 applied.append(statusentry(bin(n), name))
1880 else:
1885 else:
1881 series.append(l)
1886 series.append(l)
1882 if datastart is None:
1887 if datastart is None:
1883 self.ui.warn(_("no saved patch data found\n"))
1888 self.ui.warn(_("no saved patch data found\n"))
1884 return 1
1889 return 1
1885 self.ui.warn(_("restoring status: %s\n") % lines[0])
1890 self.ui.warn(_("restoring status: %s\n") % lines[0])
1886 self.fullseries = series
1891 self.fullseries = series
1887 self.applied = applied
1892 self.applied = applied
1888 self.parseseries()
1893 self.parseseries()
1889 self.seriesdirty = True
1894 self.seriesdirty = True
1890 self.applieddirty = True
1895 self.applieddirty = True
1891 heads = repo.changelog.heads()
1896 heads = repo.changelog.heads()
1892 if delete:
1897 if delete:
1893 if rev not in heads:
1898 if rev not in heads:
1894 self.ui.warn(_("save entry has children, leaving it alone\n"))
1899 self.ui.warn(_("save entry has children, leaving it alone\n"))
1895 else:
1900 else:
1896 self.ui.warn(_("removing save entry %s\n") % short(rev))
1901 self.ui.warn(_("removing save entry %s\n") % short(rev))
1897 pp = repo.dirstate.parents()
1902 pp = repo.dirstate.parents()
1898 if rev in pp:
1903 if rev in pp:
1899 update = True
1904 update = True
1900 else:
1905 else:
1901 update = False
1906 update = False
1902 strip(self.ui, repo, [rev], update=update, backup=False)
1907 strip(self.ui, repo, [rev], update=update, backup=False)
1903 if qpp:
1908 if qpp:
1904 self.ui.warn(_("saved queue repository parents: %s %s\n") %
1909 self.ui.warn(_("saved queue repository parents: %s %s\n") %
1905 (short(qpp[0]), short(qpp[1])))
1910 (short(qpp[0]), short(qpp[1])))
1906 if qupdate:
1911 if qupdate:
1907 self.ui.status(_("updating queue directory\n"))
1912 self.ui.status(_("updating queue directory\n"))
1908 r = self.qrepo()
1913 r = self.qrepo()
1909 if not r:
1914 if not r:
1910 self.ui.warn(_("unable to load queue repository\n"))
1915 self.ui.warn(_("unable to load queue repository\n"))
1911 return 1
1916 return 1
1912 hg.clean(r, qpp[0])
1917 hg.clean(r, qpp[0])
1913
1918
1914 def save(self, repo, msg=None):
1919 def save(self, repo, msg=None):
1915 if not self.applied:
1920 if not self.applied:
1916 self.ui.warn(_("save: no patches applied, exiting\n"))
1921 self.ui.warn(_("save: no patches applied, exiting\n"))
1917 return 1
1922 return 1
1918 if self.issaveline(self.applied[-1]):
1923 if self.issaveline(self.applied[-1]):
1919 self.ui.warn(_("status is already saved\n"))
1924 self.ui.warn(_("status is already saved\n"))
1920 return 1
1925 return 1
1921
1926
1922 if not msg:
1927 if not msg:
1923 msg = _("hg patches saved state")
1928 msg = _("hg patches saved state")
1924 else:
1929 else:
1925 msg = "hg patches: " + msg.rstrip('\r\n')
1930 msg = "hg patches: " + msg.rstrip('\r\n')
1926 r = self.qrepo()
1931 r = self.qrepo()
1927 if r:
1932 if r:
1928 pp = r.dirstate.parents()
1933 pp = r.dirstate.parents()
1929 msg += "\nDirstate: %s %s" % (hex(pp[0]), hex(pp[1]))
1934 msg += "\nDirstate: %s %s" % (hex(pp[0]), hex(pp[1]))
1930 msg += "\n\nPatch Data:\n"
1935 msg += "\n\nPatch Data:\n"
1931 msg += ''.join('%s\n' % x for x in self.applied)
1936 msg += ''.join('%s\n' % x for x in self.applied)
1932 msg += ''.join(':%s\n' % x for x in self.fullseries)
1937 msg += ''.join(':%s\n' % x for x in self.fullseries)
1933 n = repo.commit(msg, force=True)
1938 n = repo.commit(msg, force=True)
1934 if not n:
1939 if not n:
1935 self.ui.warn(_("repo commit failed\n"))
1940 self.ui.warn(_("repo commit failed\n"))
1936 return 1
1941 return 1
1937 self.applied.append(statusentry(n, '.hg.patches.save.line'))
1942 self.applied.append(statusentry(n, '.hg.patches.save.line'))
1938 self.applieddirty = True
1943 self.applieddirty = True
1939 self.removeundo(repo)
1944 self.removeundo(repo)
1940
1945
1941 def fullseriesend(self):
1946 def fullseriesend(self):
1942 if self.applied:
1947 if self.applied:
1943 p = self.applied[-1].name
1948 p = self.applied[-1].name
1944 end = self.findseries(p)
1949 end = self.findseries(p)
1945 if end is None:
1950 if end is None:
1946 return len(self.fullseries)
1951 return len(self.fullseries)
1947 return end + 1
1952 return end + 1
1948 return 0
1953 return 0
1949
1954
1950 def seriesend(self, all_patches=False):
1955 def seriesend(self, all_patches=False):
1951 """If all_patches is False, return the index of the next pushable patch
1956 """If all_patches is False, return the index of the next pushable patch
1952 in the series, or the series length. If all_patches is True, return the
1957 in the series, or the series length. If all_patches is True, return the
1953 index of the first patch past the last applied one.
1958 index of the first patch past the last applied one.
1954 """
1959 """
1955 end = 0
1960 end = 0
1956 def nextpatch(start):
1961 def nextpatch(start):
1957 if all_patches or start >= len(self.series):
1962 if all_patches or start >= len(self.series):
1958 return start
1963 return start
1959 for i in xrange(start, len(self.series)):
1964 for i in xrange(start, len(self.series)):
1960 p, reason = self.pushable(i)
1965 p, reason = self.pushable(i)
1961 if p:
1966 if p:
1962 return i
1967 return i
1963 self.explainpushable(i)
1968 self.explainpushable(i)
1964 return len(self.series)
1969 return len(self.series)
1965 if self.applied:
1970 if self.applied:
1966 p = self.applied[-1].name
1971 p = self.applied[-1].name
1967 try:
1972 try:
1968 end = self.series.index(p)
1973 end = self.series.index(p)
1969 except ValueError:
1974 except ValueError:
1970 return 0
1975 return 0
1971 return nextpatch(end + 1)
1976 return nextpatch(end + 1)
1972 return nextpatch(end)
1977 return nextpatch(end)
1973
1978
1974 def appliedname(self, index):
1979 def appliedname(self, index):
1975 pname = self.applied[index].name
1980 pname = self.applied[index].name
1976 if not self.ui.verbose:
1981 if not self.ui.verbose:
1977 p = pname
1982 p = pname
1978 else:
1983 else:
1979 p = str(self.series.index(pname)) + " " + pname
1984 p = str(self.series.index(pname)) + " " + pname
1980 return p
1985 return p
1981
1986
1982 def qimport(self, repo, files, patchname=None, rev=None, existing=None,
1987 def qimport(self, repo, files, patchname=None, rev=None, existing=None,
1983 force=None, git=False):
1988 force=None, git=False):
1984 def checkseries(patchname):
1989 def checkseries(patchname):
1985 if patchname in self.series:
1990 if patchname in self.series:
1986 raise util.Abort(_('patch %s is already in the series file')
1991 raise util.Abort(_('patch %s is already in the series file')
1987 % patchname)
1992 % patchname)
1988
1993
1989 if rev:
1994 if rev:
1990 if files:
1995 if files:
1991 raise util.Abort(_('option "-r" not valid when importing '
1996 raise util.Abort(_('option "-r" not valid when importing '
1992 'files'))
1997 'files'))
1993 rev = scmutil.revrange(repo, rev)
1998 rev = scmutil.revrange(repo, rev)
1994 rev.sort(reverse=True)
1999 rev.sort(reverse=True)
1995 elif not files:
2000 elif not files:
1996 raise util.Abort(_('no files or revisions specified'))
2001 raise util.Abort(_('no files or revisions specified'))
1997 if (len(files) > 1 or len(rev) > 1) and patchname:
2002 if (len(files) > 1 or len(rev) > 1) and patchname:
1998 raise util.Abort(_('option "-n" not valid when importing multiple '
2003 raise util.Abort(_('option "-n" not valid when importing multiple '
1999 'patches'))
2004 'patches'))
2000 imported = []
2005 imported = []
2001 if rev:
2006 if rev:
2002 # If mq patches are applied, we can only import revisions
2007 # If mq patches are applied, we can only import revisions
2003 # that form a linear path to qbase.
2008 # that form a linear path to qbase.
2004 # Otherwise, they should form a linear path to a head.
2009 # Otherwise, they should form a linear path to a head.
2005 heads = repo.changelog.heads(repo.changelog.node(rev.first()))
2010 heads = repo.changelog.heads(repo.changelog.node(rev.first()))
2006 if len(heads) > 1:
2011 if len(heads) > 1:
2007 raise util.Abort(_('revision %d is the root of more than one '
2012 raise util.Abort(_('revision %d is the root of more than one '
2008 'branch') % rev.last())
2013 'branch') % rev.last())
2009 if self.applied:
2014 if self.applied:
2010 base = repo.changelog.node(rev.first())
2015 base = repo.changelog.node(rev.first())
2011 if base in [n.node for n in self.applied]:
2016 if base in [n.node for n in self.applied]:
2012 raise util.Abort(_('revision %d is already managed')
2017 raise util.Abort(_('revision %d is already managed')
2013 % rev.first())
2018 % rev.first())
2014 if heads != [self.applied[-1].node]:
2019 if heads != [self.applied[-1].node]:
2015 raise util.Abort(_('revision %d is not the parent of '
2020 raise util.Abort(_('revision %d is not the parent of '
2016 'the queue') % rev.first())
2021 'the queue') % rev.first())
2017 base = repo.changelog.rev(self.applied[0].node)
2022 base = repo.changelog.rev(self.applied[0].node)
2018 lastparent = repo.changelog.parentrevs(base)[0]
2023 lastparent = repo.changelog.parentrevs(base)[0]
2019 else:
2024 else:
2020 if heads != [repo.changelog.node(rev.first())]:
2025 if heads != [repo.changelog.node(rev.first())]:
2021 raise util.Abort(_('revision %d has unmanaged children')
2026 raise util.Abort(_('revision %d has unmanaged children')
2022 % rev.first())
2027 % rev.first())
2023 lastparent = None
2028 lastparent = None
2024
2029
2025 diffopts = self.diffopts({'git': git})
2030 diffopts = self.diffopts({'git': git})
2026 tr = repo.transaction('qimport')
2031 tr = repo.transaction('qimport')
2027 try:
2032 try:
2028 for r in rev:
2033 for r in rev:
2029 if not repo[r].mutable():
2034 if not repo[r].mutable():
2030 raise util.Abort(_('revision %d is not mutable') % r,
2035 raise util.Abort(_('revision %d is not mutable') % r,
2031 hint=_('see "hg help phases" '
2036 hint=_('see "hg help phases" '
2032 'for details'))
2037 'for details'))
2033 p1, p2 = repo.changelog.parentrevs(r)
2038 p1, p2 = repo.changelog.parentrevs(r)
2034 n = repo.changelog.node(r)
2039 n = repo.changelog.node(r)
2035 if p2 != nullrev:
2040 if p2 != nullrev:
2036 raise util.Abort(_('cannot import merge revision %d')
2041 raise util.Abort(_('cannot import merge revision %d')
2037 % r)
2042 % r)
2038 if lastparent and lastparent != r:
2043 if lastparent and lastparent != r:
2039 raise util.Abort(_('revision %d is not the parent of '
2044 raise util.Abort(_('revision %d is not the parent of '
2040 '%d')
2045 '%d')
2041 % (r, lastparent))
2046 % (r, lastparent))
2042 lastparent = p1
2047 lastparent = p1
2043
2048
2044 if not patchname:
2049 if not patchname:
2045 patchname = normname('%d.diff' % r)
2050 patchname = normname('%d.diff' % r)
2046 checkseries(patchname)
2051 checkseries(patchname)
2047 self.checkpatchname(patchname, force)
2052 self.checkpatchname(patchname, force)
2048 self.fullseries.insert(0, patchname)
2053 self.fullseries.insert(0, patchname)
2049
2054
2050 patchf = self.opener(patchname, "w")
2055 patchf = self.opener(patchname, "w")
2051 cmdutil.export(repo, [n], fp=patchf, opts=diffopts)
2056 cmdutil.export(repo, [n], fp=patchf, opts=diffopts)
2052 patchf.close()
2057 patchf.close()
2053
2058
2054 se = statusentry(n, patchname)
2059 se = statusentry(n, patchname)
2055 self.applied.insert(0, se)
2060 self.applied.insert(0, se)
2056
2061
2057 self.added.append(patchname)
2062 self.added.append(patchname)
2058 imported.append(patchname)
2063 imported.append(patchname)
2059 patchname = None
2064 patchname = None
2060 if rev and repo.ui.configbool('mq', 'secret', False):
2065 if rev and repo.ui.configbool('mq', 'secret', False):
2061 # if we added anything with --rev, move the secret root
2066 # if we added anything with --rev, move the secret root
2062 phases.retractboundary(repo, tr, phases.secret, [n])
2067 phases.retractboundary(repo, tr, phases.secret, [n])
2063 self.parseseries()
2068 self.parseseries()
2064 self.applieddirty = True
2069 self.applieddirty = True
2065 self.seriesdirty = True
2070 self.seriesdirty = True
2066 tr.close()
2071 tr.close()
2067 finally:
2072 finally:
2068 tr.release()
2073 tr.release()
2069
2074
2070 for i, filename in enumerate(files):
2075 for i, filename in enumerate(files):
2071 if existing:
2076 if existing:
2072 if filename == '-':
2077 if filename == '-':
2073 raise util.Abort(_('-e is incompatible with import from -'))
2078 raise util.Abort(_('-e is incompatible with import from -'))
2074 filename = normname(filename)
2079 filename = normname(filename)
2075 self.checkreservedname(filename)
2080 self.checkreservedname(filename)
2076 if util.url(filename).islocal():
2081 if util.url(filename).islocal():
2077 originpath = self.join(filename)
2082 originpath = self.join(filename)
2078 if not os.path.isfile(originpath):
2083 if not os.path.isfile(originpath):
2079 raise util.Abort(
2084 raise util.Abort(
2080 _("patch %s does not exist") % filename)
2085 _("patch %s does not exist") % filename)
2081
2086
2082 if patchname:
2087 if patchname:
2083 self.checkpatchname(patchname, force)
2088 self.checkpatchname(patchname, force)
2084
2089
2085 self.ui.write(_('renaming %s to %s\n')
2090 self.ui.write(_('renaming %s to %s\n')
2086 % (filename, patchname))
2091 % (filename, patchname))
2087 util.rename(originpath, self.join(patchname))
2092 util.rename(originpath, self.join(patchname))
2088 else:
2093 else:
2089 patchname = filename
2094 patchname = filename
2090
2095
2091 else:
2096 else:
2092 if filename == '-' and not patchname:
2097 if filename == '-' and not patchname:
2093 raise util.Abort(_('need --name to import a patch from -'))
2098 raise util.Abort(_('need --name to import a patch from -'))
2094 elif not patchname:
2099 elif not patchname:
2095 patchname = normname(os.path.basename(filename.rstrip('/')))
2100 patchname = normname(os.path.basename(filename.rstrip('/')))
2096 self.checkpatchname(patchname, force)
2101 self.checkpatchname(patchname, force)
2097 try:
2102 try:
2098 if filename == '-':
2103 if filename == '-':
2099 text = self.ui.fin.read()
2104 text = self.ui.fin.read()
2100 else:
2105 else:
2101 fp = hg.openpath(self.ui, filename)
2106 fp = hg.openpath(self.ui, filename)
2102 text = fp.read()
2107 text = fp.read()
2103 fp.close()
2108 fp.close()
2104 except (OSError, IOError):
2109 except (OSError, IOError):
2105 raise util.Abort(_("unable to read file %s") % filename)
2110 raise util.Abort(_("unable to read file %s") % filename)
2106 patchf = self.opener(patchname, "w")
2111 patchf = self.opener(patchname, "w")
2107 patchf.write(text)
2112 patchf.write(text)
2108 patchf.close()
2113 patchf.close()
2109 if not force:
2114 if not force:
2110 checkseries(patchname)
2115 checkseries(patchname)
2111 if patchname not in self.series:
2116 if patchname not in self.series:
2112 index = self.fullseriesend() + i
2117 index = self.fullseriesend() + i
2113 self.fullseries[index:index] = [patchname]
2118 self.fullseries[index:index] = [patchname]
2114 self.parseseries()
2119 self.parseseries()
2115 self.seriesdirty = True
2120 self.seriesdirty = True
2116 self.ui.warn(_("adding %s to series file\n") % patchname)
2121 self.ui.warn(_("adding %s to series file\n") % patchname)
2117 self.added.append(patchname)
2122 self.added.append(patchname)
2118 imported.append(patchname)
2123 imported.append(patchname)
2119 patchname = None
2124 patchname = None
2120
2125
2121 self.removeundo(repo)
2126 self.removeundo(repo)
2122 return imported
2127 return imported
2123
2128
2124 def fixkeepchangesopts(ui, opts):
2129 def fixkeepchangesopts(ui, opts):
2125 if (not ui.configbool('mq', 'keepchanges') or opts.get('force')
2130 if (not ui.configbool('mq', 'keepchanges') or opts.get('force')
2126 or opts.get('exact')):
2131 or opts.get('exact')):
2127 return opts
2132 return opts
2128 opts = dict(opts)
2133 opts = dict(opts)
2129 opts['keep_changes'] = True
2134 opts['keep_changes'] = True
2130 return opts
2135 return opts
2131
2136
2132 @command("qdelete|qremove|qrm",
2137 @command("qdelete|qremove|qrm",
2133 [('k', 'keep', None, _('keep patch file')),
2138 [('k', 'keep', None, _('keep patch file')),
2134 ('r', 'rev', [],
2139 ('r', 'rev', [],
2135 _('stop managing a revision (DEPRECATED)'), _('REV'))],
2140 _('stop managing a revision (DEPRECATED)'), _('REV'))],
2136 _('hg qdelete [-k] [PATCH]...'))
2141 _('hg qdelete [-k] [PATCH]...'))
2137 def delete(ui, repo, *patches, **opts):
2142 def delete(ui, repo, *patches, **opts):
2138 """remove patches from queue
2143 """remove patches from queue
2139
2144
2140 The patches must not be applied, and at least one patch is required. Exact
2145 The patches must not be applied, and at least one patch is required. Exact
2141 patch identifiers must be given. With -k/--keep, the patch files are
2146 patch identifiers must be given. With -k/--keep, the patch files are
2142 preserved in the patch directory.
2147 preserved in the patch directory.
2143
2148
2144 To stop managing a patch and move it into permanent history,
2149 To stop managing a patch and move it into permanent history,
2145 use the :hg:`qfinish` command."""
2150 use the :hg:`qfinish` command."""
2146 q = repo.mq
2151 q = repo.mq
2147 q.delete(repo, patches, opts)
2152 q.delete(repo, patches, opts)
2148 q.savedirty()
2153 q.savedirty()
2149 return 0
2154 return 0
2150
2155
2151 @command("qapplied",
2156 @command("qapplied",
2152 [('1', 'last', None, _('show only the preceding applied patch'))
2157 [('1', 'last', None, _('show only the preceding applied patch'))
2153 ] + seriesopts,
2158 ] + seriesopts,
2154 _('hg qapplied [-1] [-s] [PATCH]'))
2159 _('hg qapplied [-1] [-s] [PATCH]'))
2155 def applied(ui, repo, patch=None, **opts):
2160 def applied(ui, repo, patch=None, **opts):
2156 """print the patches already applied
2161 """print the patches already applied
2157
2162
2158 Returns 0 on success."""
2163 Returns 0 on success."""
2159
2164
2160 q = repo.mq
2165 q = repo.mq
2161
2166
2162 if patch:
2167 if patch:
2163 if patch not in q.series:
2168 if patch not in q.series:
2164 raise util.Abort(_("patch %s is not in series file") % patch)
2169 raise util.Abort(_("patch %s is not in series file") % patch)
2165 end = q.series.index(patch) + 1
2170 end = q.series.index(patch) + 1
2166 else:
2171 else:
2167 end = q.seriesend(True)
2172 end = q.seriesend(True)
2168
2173
2169 if opts.get('last') and not end:
2174 if opts.get('last') and not end:
2170 ui.write(_("no patches applied\n"))
2175 ui.write(_("no patches applied\n"))
2171 return 1
2176 return 1
2172 elif opts.get('last') and end == 1:
2177 elif opts.get('last') and end == 1:
2173 ui.write(_("only one patch applied\n"))
2178 ui.write(_("only one patch applied\n"))
2174 return 1
2179 return 1
2175 elif opts.get('last'):
2180 elif opts.get('last'):
2176 start = end - 2
2181 start = end - 2
2177 end = 1
2182 end = 1
2178 else:
2183 else:
2179 start = 0
2184 start = 0
2180
2185
2181 q.qseries(repo, length=end, start=start, status='A',
2186 q.qseries(repo, length=end, start=start, status='A',
2182 summary=opts.get('summary'))
2187 summary=opts.get('summary'))
2183
2188
2184
2189
2185 @command("qunapplied",
2190 @command("qunapplied",
2186 [('1', 'first', None, _('show only the first patch'))] + seriesopts,
2191 [('1', 'first', None, _('show only the first patch'))] + seriesopts,
2187 _('hg qunapplied [-1] [-s] [PATCH]'))
2192 _('hg qunapplied [-1] [-s] [PATCH]'))
2188 def unapplied(ui, repo, patch=None, **opts):
2193 def unapplied(ui, repo, patch=None, **opts):
2189 """print the patches not yet applied
2194 """print the patches not yet applied
2190
2195
2191 Returns 0 on success."""
2196 Returns 0 on success."""
2192
2197
2193 q = repo.mq
2198 q = repo.mq
2194 if patch:
2199 if patch:
2195 if patch not in q.series:
2200 if patch not in q.series:
2196 raise util.Abort(_("patch %s is not in series file") % patch)
2201 raise util.Abort(_("patch %s is not in series file") % patch)
2197 start = q.series.index(patch) + 1
2202 start = q.series.index(patch) + 1
2198 else:
2203 else:
2199 start = q.seriesend(True)
2204 start = q.seriesend(True)
2200
2205
2201 if start == len(q.series) and opts.get('first'):
2206 if start == len(q.series) and opts.get('first'):
2202 ui.write(_("all patches applied\n"))
2207 ui.write(_("all patches applied\n"))
2203 return 1
2208 return 1
2204
2209
2205 length = opts.get('first') and 1 or None
2210 length = opts.get('first') and 1 or None
2206 q.qseries(repo, start=start, length=length, status='U',
2211 q.qseries(repo, start=start, length=length, status='U',
2207 summary=opts.get('summary'))
2212 summary=opts.get('summary'))
2208
2213
2209 @command("qimport",
2214 @command("qimport",
2210 [('e', 'existing', None, _('import file in patch directory')),
2215 [('e', 'existing', None, _('import file in patch directory')),
2211 ('n', 'name', '',
2216 ('n', 'name', '',
2212 _('name of patch file'), _('NAME')),
2217 _('name of patch file'), _('NAME')),
2213 ('f', 'force', None, _('overwrite existing files')),
2218 ('f', 'force', None, _('overwrite existing files')),
2214 ('r', 'rev', [],
2219 ('r', 'rev', [],
2215 _('place existing revisions under mq control'), _('REV')),
2220 _('place existing revisions under mq control'), _('REV')),
2216 ('g', 'git', None, _('use git extended diff format')),
2221 ('g', 'git', None, _('use git extended diff format')),
2217 ('P', 'push', None, _('qpush after importing'))],
2222 ('P', 'push', None, _('qpush after importing'))],
2218 _('hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... [FILE]...'))
2223 _('hg qimport [-e] [-n NAME] [-f] [-g] [-P] [-r REV]... [FILE]...'))
2219 def qimport(ui, repo, *filename, **opts):
2224 def qimport(ui, repo, *filename, **opts):
2220 """import a patch or existing changeset
2225 """import a patch or existing changeset
2221
2226
2222 The patch is inserted into the series after the last applied
2227 The patch is inserted into the series after the last applied
2223 patch. If no patches have been applied, qimport prepends the patch
2228 patch. If no patches have been applied, qimport prepends the patch
2224 to the series.
2229 to the series.
2225
2230
2226 The patch will have the same name as its source file unless you
2231 The patch will have the same name as its source file unless you
2227 give it a new one with -n/--name.
2232 give it a new one with -n/--name.
2228
2233
2229 You can register an existing patch inside the patch directory with
2234 You can register an existing patch inside the patch directory with
2230 the -e/--existing flag.
2235 the -e/--existing flag.
2231
2236
2232 With -f/--force, an existing patch of the same name will be
2237 With -f/--force, an existing patch of the same name will be
2233 overwritten.
2238 overwritten.
2234
2239
2235 An existing changeset may be placed under mq control with -r/--rev
2240 An existing changeset may be placed under mq control with -r/--rev
2236 (e.g. qimport --rev . -n patch will place the current revision
2241 (e.g. qimport --rev . -n patch will place the current revision
2237 under mq control). With -g/--git, patches imported with --rev will
2242 under mq control). With -g/--git, patches imported with --rev will
2238 use the git diff format. See the diffs help topic for information
2243 use the git diff format. See the diffs help topic for information
2239 on why this is important for preserving rename/copy information
2244 on why this is important for preserving rename/copy information
2240 and permission changes. Use :hg:`qfinish` to remove changesets
2245 and permission changes. Use :hg:`qfinish` to remove changesets
2241 from mq control.
2246 from mq control.
2242
2247
2243 To import a patch from standard input, pass - as the patch file.
2248 To import a patch from standard input, pass - as the patch file.
2244 When importing from standard input, a patch name must be specified
2249 When importing from standard input, a patch name must be specified
2245 using the --name flag.
2250 using the --name flag.
2246
2251
2247 To import an existing patch while renaming it::
2252 To import an existing patch while renaming it::
2248
2253
2249 hg qimport -e existing-patch -n new-name
2254 hg qimport -e existing-patch -n new-name
2250
2255
2251 Returns 0 if import succeeded.
2256 Returns 0 if import succeeded.
2252 """
2257 """
2253 lock = repo.lock() # cause this may move phase
2258 lock = repo.lock() # cause this may move phase
2254 try:
2259 try:
2255 q = repo.mq
2260 q = repo.mq
2256 try:
2261 try:
2257 imported = q.qimport(
2262 imported = q.qimport(
2258 repo, filename, patchname=opts.get('name'),
2263 repo, filename, patchname=opts.get('name'),
2259 existing=opts.get('existing'), force=opts.get('force'),
2264 existing=opts.get('existing'), force=opts.get('force'),
2260 rev=opts.get('rev'), git=opts.get('git'))
2265 rev=opts.get('rev'), git=opts.get('git'))
2261 finally:
2266 finally:
2262 q.savedirty()
2267 q.savedirty()
2263 finally:
2268 finally:
2264 lock.release()
2269 lock.release()
2265
2270
2266 if imported and opts.get('push') and not opts.get('rev'):
2271 if imported and opts.get('push') and not opts.get('rev'):
2267 return q.push(repo, imported[-1])
2272 return q.push(repo, imported[-1])
2268 return 0
2273 return 0
2269
2274
2270 def qinit(ui, repo, create):
2275 def qinit(ui, repo, create):
2271 """initialize a new queue repository
2276 """initialize a new queue repository
2272
2277
2273 This command also creates a series file for ordering patches, and
2278 This command also creates a series file for ordering patches, and
2274 an mq-specific .hgignore file in the queue repository, to exclude
2279 an mq-specific .hgignore file in the queue repository, to exclude
2275 the status and guards files (these contain mostly transient state).
2280 the status and guards files (these contain mostly transient state).
2276
2281
2277 Returns 0 if initialization succeeded."""
2282 Returns 0 if initialization succeeded."""
2278 q = repo.mq
2283 q = repo.mq
2279 r = q.init(repo, create)
2284 r = q.init(repo, create)
2280 q.savedirty()
2285 q.savedirty()
2281 if r:
2286 if r:
2282 if not os.path.exists(r.wjoin('.hgignore')):
2287 if not os.path.exists(r.wjoin('.hgignore')):
2283 fp = r.wopener('.hgignore', 'w')
2288 fp = r.wopener('.hgignore', 'w')
2284 fp.write('^\\.hg\n')
2289 fp.write('^\\.hg\n')
2285 fp.write('^\\.mq\n')
2290 fp.write('^\\.mq\n')
2286 fp.write('syntax: glob\n')
2291 fp.write('syntax: glob\n')
2287 fp.write('status\n')
2292 fp.write('status\n')
2288 fp.write('guards\n')
2293 fp.write('guards\n')
2289 fp.close()
2294 fp.close()
2290 if not os.path.exists(r.wjoin('series')):
2295 if not os.path.exists(r.wjoin('series')):
2291 r.wopener('series', 'w').close()
2296 r.wopener('series', 'w').close()
2292 r[None].add(['.hgignore', 'series'])
2297 r[None].add(['.hgignore', 'series'])
2293 commands.add(ui, r)
2298 commands.add(ui, r)
2294 return 0
2299 return 0
2295
2300
2296 @command("^qinit",
2301 @command("^qinit",
2297 [('c', 'create-repo', None, _('create queue repository'))],
2302 [('c', 'create-repo', None, _('create queue repository'))],
2298 _('hg qinit [-c]'))
2303 _('hg qinit [-c]'))
2299 def init(ui, repo, **opts):
2304 def init(ui, repo, **opts):
2300 """init a new queue repository (DEPRECATED)
2305 """init a new queue repository (DEPRECATED)
2301
2306
2302 The queue repository is unversioned by default. If
2307 The queue repository is unversioned by default. If
2303 -c/--create-repo is specified, qinit will create a separate nested
2308 -c/--create-repo is specified, qinit will create a separate nested
2304 repository for patches (qinit -c may also be run later to convert
2309 repository for patches (qinit -c may also be run later to convert
2305 an unversioned patch repository into a versioned one). You can use
2310 an unversioned patch repository into a versioned one). You can use
2306 qcommit to commit changes to this queue repository.
2311 qcommit to commit changes to this queue repository.
2307
2312
2308 This command is deprecated. Without -c, it's implied by other relevant
2313 This command is deprecated. Without -c, it's implied by other relevant
2309 commands. With -c, use :hg:`init --mq` instead."""
2314 commands. With -c, use :hg:`init --mq` instead."""
2310 return qinit(ui, repo, create=opts.get('create_repo'))
2315 return qinit(ui, repo, create=opts.get('create_repo'))
2311
2316
2312 @command("qclone",
2317 @command("qclone",
2313 [('', 'pull', None, _('use pull protocol to copy metadata')),
2318 [('', 'pull', None, _('use pull protocol to copy metadata')),
2314 ('U', 'noupdate', None,
2319 ('U', 'noupdate', None,
2315 _('do not update the new working directories')),
2320 _('do not update the new working directories')),
2316 ('', 'uncompressed', None,
2321 ('', 'uncompressed', None,
2317 _('use uncompressed transfer (fast over LAN)')),
2322 _('use uncompressed transfer (fast over LAN)')),
2318 ('p', 'patches', '',
2323 ('p', 'patches', '',
2319 _('location of source patch repository'), _('REPO')),
2324 _('location of source patch repository'), _('REPO')),
2320 ] + commands.remoteopts,
2325 ] + commands.remoteopts,
2321 _('hg qclone [OPTION]... SOURCE [DEST]'),
2326 _('hg qclone [OPTION]... SOURCE [DEST]'),
2322 norepo=True)
2327 norepo=True)
2323 def clone(ui, source, dest=None, **opts):
2328 def clone(ui, source, dest=None, **opts):
2324 '''clone main and patch repository at same time
2329 '''clone main and patch repository at same time
2325
2330
2326 If source is local, destination will have no patches applied. If
2331 If source is local, destination will have no patches applied. If
2327 source is remote, this command can not check if patches are
2332 source is remote, this command can not check if patches are
2328 applied in source, so cannot guarantee that patches are not
2333 applied in source, so cannot guarantee that patches are not
2329 applied in destination. If you clone remote repository, be sure
2334 applied in destination. If you clone remote repository, be sure
2330 before that it has no patches applied.
2335 before that it has no patches applied.
2331
2336
2332 Source patch repository is looked for in <src>/.hg/patches by
2337 Source patch repository is looked for in <src>/.hg/patches by
2333 default. Use -p <url> to change.
2338 default. Use -p <url> to change.
2334
2339
2335 The patch directory must be a nested Mercurial repository, as
2340 The patch directory must be a nested Mercurial repository, as
2336 would be created by :hg:`init --mq`.
2341 would be created by :hg:`init --mq`.
2337
2342
2338 Return 0 on success.
2343 Return 0 on success.
2339 '''
2344 '''
2340 def patchdir(repo):
2345 def patchdir(repo):
2341 """compute a patch repo url from a repo object"""
2346 """compute a patch repo url from a repo object"""
2342 url = repo.url()
2347 url = repo.url()
2343 if url.endswith('/'):
2348 if url.endswith('/'):
2344 url = url[:-1]
2349 url = url[:-1]
2345 return url + '/.hg/patches'
2350 return url + '/.hg/patches'
2346
2351
2347 # main repo (destination and sources)
2352 # main repo (destination and sources)
2348 if dest is None:
2353 if dest is None:
2349 dest = hg.defaultdest(source)
2354 dest = hg.defaultdest(source)
2350 sr = hg.peer(ui, opts, ui.expandpath(source))
2355 sr = hg.peer(ui, opts, ui.expandpath(source))
2351
2356
2352 # patches repo (source only)
2357 # patches repo (source only)
2353 if opts.get('patches'):
2358 if opts.get('patches'):
2354 patchespath = ui.expandpath(opts.get('patches'))
2359 patchespath = ui.expandpath(opts.get('patches'))
2355 else:
2360 else:
2356 patchespath = patchdir(sr)
2361 patchespath = patchdir(sr)
2357 try:
2362 try:
2358 hg.peer(ui, opts, patchespath)
2363 hg.peer(ui, opts, patchespath)
2359 except error.RepoError:
2364 except error.RepoError:
2360 raise util.Abort(_('versioned patch repository not found'
2365 raise util.Abort(_('versioned patch repository not found'
2361 ' (see init --mq)'))
2366 ' (see init --mq)'))
2362 qbase, destrev = None, None
2367 qbase, destrev = None, None
2363 if sr.local():
2368 if sr.local():
2364 repo = sr.local()
2369 repo = sr.local()
2365 if repo.mq.applied and repo[qbase].phase() != phases.secret:
2370 if repo.mq.applied and repo[qbase].phase() != phases.secret:
2366 qbase = repo.mq.applied[0].node
2371 qbase = repo.mq.applied[0].node
2367 if not hg.islocal(dest):
2372 if not hg.islocal(dest):
2368 heads = set(repo.heads())
2373 heads = set(repo.heads())
2369 destrev = list(heads.difference(repo.heads(qbase)))
2374 destrev = list(heads.difference(repo.heads(qbase)))
2370 destrev.append(repo.changelog.parents(qbase)[0])
2375 destrev.append(repo.changelog.parents(qbase)[0])
2371 elif sr.capable('lookup'):
2376 elif sr.capable('lookup'):
2372 try:
2377 try:
2373 qbase = sr.lookup('qbase')
2378 qbase = sr.lookup('qbase')
2374 except error.RepoError:
2379 except error.RepoError:
2375 pass
2380 pass
2376
2381
2377 ui.note(_('cloning main repository\n'))
2382 ui.note(_('cloning main repository\n'))
2378 sr, dr = hg.clone(ui, opts, sr.url(), dest,
2383 sr, dr = hg.clone(ui, opts, sr.url(), dest,
2379 pull=opts.get('pull'),
2384 pull=opts.get('pull'),
2380 rev=destrev,
2385 rev=destrev,
2381 update=False,
2386 update=False,
2382 stream=opts.get('uncompressed'))
2387 stream=opts.get('uncompressed'))
2383
2388
2384 ui.note(_('cloning patch repository\n'))
2389 ui.note(_('cloning patch repository\n'))
2385 hg.clone(ui, opts, opts.get('patches') or patchdir(sr), patchdir(dr),
2390 hg.clone(ui, opts, opts.get('patches') or patchdir(sr), patchdir(dr),
2386 pull=opts.get('pull'), update=not opts.get('noupdate'),
2391 pull=opts.get('pull'), update=not opts.get('noupdate'),
2387 stream=opts.get('uncompressed'))
2392 stream=opts.get('uncompressed'))
2388
2393
2389 if dr.local():
2394 if dr.local():
2390 repo = dr.local()
2395 repo = dr.local()
2391 if qbase:
2396 if qbase:
2392 ui.note(_('stripping applied patches from destination '
2397 ui.note(_('stripping applied patches from destination '
2393 'repository\n'))
2398 'repository\n'))
2394 strip(ui, repo, [qbase], update=False, backup=None)
2399 strip(ui, repo, [qbase], update=False, backup=None)
2395 if not opts.get('noupdate'):
2400 if not opts.get('noupdate'):
2396 ui.note(_('updating destination repository\n'))
2401 ui.note(_('updating destination repository\n'))
2397 hg.update(repo, repo.changelog.tip())
2402 hg.update(repo, repo.changelog.tip())
2398
2403
2399 @command("qcommit|qci",
2404 @command("qcommit|qci",
2400 commands.table["^commit|ci"][1],
2405 commands.table["^commit|ci"][1],
2401 _('hg qcommit [OPTION]... [FILE]...'),
2406 _('hg qcommit [OPTION]... [FILE]...'),
2402 inferrepo=True)
2407 inferrepo=True)
2403 def commit(ui, repo, *pats, **opts):
2408 def commit(ui, repo, *pats, **opts):
2404 """commit changes in the queue repository (DEPRECATED)
2409 """commit changes in the queue repository (DEPRECATED)
2405
2410
2406 This command is deprecated; use :hg:`commit --mq` instead."""
2411 This command is deprecated; use :hg:`commit --mq` instead."""
2407 q = repo.mq
2412 q = repo.mq
2408 r = q.qrepo()
2413 r = q.qrepo()
2409 if not r:
2414 if not r:
2410 raise util.Abort('no queue repository')
2415 raise util.Abort('no queue repository')
2411 commands.commit(r.ui, r, *pats, **opts)
2416 commands.commit(r.ui, r, *pats, **opts)
2412
2417
2413 @command("qseries",
2418 @command("qseries",
2414 [('m', 'missing', None, _('print patches not in series')),
2419 [('m', 'missing', None, _('print patches not in series')),
2415 ] + seriesopts,
2420 ] + seriesopts,
2416 _('hg qseries [-ms]'))
2421 _('hg qseries [-ms]'))
2417 def series(ui, repo, **opts):
2422 def series(ui, repo, **opts):
2418 """print the entire series file
2423 """print the entire series file
2419
2424
2420 Returns 0 on success."""
2425 Returns 0 on success."""
2421 repo.mq.qseries(repo, missing=opts.get('missing'),
2426 repo.mq.qseries(repo, missing=opts.get('missing'),
2422 summary=opts.get('summary'))
2427 summary=opts.get('summary'))
2423 return 0
2428 return 0
2424
2429
2425 @command("qtop", seriesopts, _('hg qtop [-s]'))
2430 @command("qtop", seriesopts, _('hg qtop [-s]'))
2426 def top(ui, repo, **opts):
2431 def top(ui, repo, **opts):
2427 """print the name of the current patch
2432 """print the name of the current patch
2428
2433
2429 Returns 0 on success."""
2434 Returns 0 on success."""
2430 q = repo.mq
2435 q = repo.mq
2431 t = q.applied and q.seriesend(True) or 0
2436 t = q.applied and q.seriesend(True) or 0
2432 if t:
2437 if t:
2433 q.qseries(repo, start=t - 1, length=1, status='A',
2438 q.qseries(repo, start=t - 1, length=1, status='A',
2434 summary=opts.get('summary'))
2439 summary=opts.get('summary'))
2435 else:
2440 else:
2436 ui.write(_("no patches applied\n"))
2441 ui.write(_("no patches applied\n"))
2437 return 1
2442 return 1
2438
2443
2439 @command("qnext", seriesopts, _('hg qnext [-s]'))
2444 @command("qnext", seriesopts, _('hg qnext [-s]'))
2440 def next(ui, repo, **opts):
2445 def next(ui, repo, **opts):
2441 """print the name of the next pushable patch
2446 """print the name of the next pushable patch
2442
2447
2443 Returns 0 on success."""
2448 Returns 0 on success."""
2444 q = repo.mq
2449 q = repo.mq
2445 end = q.seriesend()
2450 end = q.seriesend()
2446 if end == len(q.series):
2451 if end == len(q.series):
2447 ui.write(_("all patches applied\n"))
2452 ui.write(_("all patches applied\n"))
2448 return 1
2453 return 1
2449 q.qseries(repo, start=end, length=1, summary=opts.get('summary'))
2454 q.qseries(repo, start=end, length=1, summary=opts.get('summary'))
2450
2455
2451 @command("qprev", seriesopts, _('hg qprev [-s]'))
2456 @command("qprev", seriesopts, _('hg qprev [-s]'))
2452 def prev(ui, repo, **opts):
2457 def prev(ui, repo, **opts):
2453 """print the name of the preceding applied patch
2458 """print the name of the preceding applied patch
2454
2459
2455 Returns 0 on success."""
2460 Returns 0 on success."""
2456 q = repo.mq
2461 q = repo.mq
2457 l = len(q.applied)
2462 l = len(q.applied)
2458 if l == 1:
2463 if l == 1:
2459 ui.write(_("only one patch applied\n"))
2464 ui.write(_("only one patch applied\n"))
2460 return 1
2465 return 1
2461 if not l:
2466 if not l:
2462 ui.write(_("no patches applied\n"))
2467 ui.write(_("no patches applied\n"))
2463 return 1
2468 return 1
2464 idx = q.series.index(q.applied[-2].name)
2469 idx = q.series.index(q.applied[-2].name)
2465 q.qseries(repo, start=idx, length=1, status='A',
2470 q.qseries(repo, start=idx, length=1, status='A',
2466 summary=opts.get('summary'))
2471 summary=opts.get('summary'))
2467
2472
2468 def setupheaderopts(ui, opts):
2473 def setupheaderopts(ui, opts):
2469 if not opts.get('user') and opts.get('currentuser'):
2474 if not opts.get('user') and opts.get('currentuser'):
2470 opts['user'] = ui.username()
2475 opts['user'] = ui.username()
2471 if not opts.get('date') and opts.get('currentdate'):
2476 if not opts.get('date') and opts.get('currentdate'):
2472 opts['date'] = "%d %d" % util.makedate()
2477 opts['date'] = "%d %d" % util.makedate()
2473
2478
2474 @command("^qnew",
2479 @command("^qnew",
2475 [('e', 'edit', None, _('invoke editor on commit messages')),
2480 [('e', 'edit', None, _('invoke editor on commit messages')),
2476 ('f', 'force', None, _('import uncommitted changes (DEPRECATED)')),
2481 ('f', 'force', None, _('import uncommitted changes (DEPRECATED)')),
2477 ('g', 'git', None, _('use git extended diff format')),
2482 ('g', 'git', None, _('use git extended diff format')),
2478 ('U', 'currentuser', None, _('add "From: <current user>" to patch')),
2483 ('U', 'currentuser', None, _('add "From: <current user>" to patch')),
2479 ('u', 'user', '',
2484 ('u', 'user', '',
2480 _('add "From: <USER>" to patch'), _('USER')),
2485 _('add "From: <USER>" to patch'), _('USER')),
2481 ('D', 'currentdate', None, _('add "Date: <current date>" to patch')),
2486 ('D', 'currentdate', None, _('add "Date: <current date>" to patch')),
2482 ('d', 'date', '',
2487 ('d', 'date', '',
2483 _('add "Date: <DATE>" to patch'), _('DATE'))
2488 _('add "Date: <DATE>" to patch'), _('DATE'))
2484 ] + commands.walkopts + commands.commitopts,
2489 ] + commands.walkopts + commands.commitopts,
2485 _('hg qnew [-e] [-m TEXT] [-l FILE] PATCH [FILE]...'),
2490 _('hg qnew [-e] [-m TEXT] [-l FILE] PATCH [FILE]...'),
2486 inferrepo=True)
2491 inferrepo=True)
2487 def new(ui, repo, patch, *args, **opts):
2492 def new(ui, repo, patch, *args, **opts):
2488 """create a new patch
2493 """create a new patch
2489
2494
2490 qnew creates a new patch on top of the currently-applied patch (if
2495 qnew creates a new patch on top of the currently-applied patch (if
2491 any). The patch will be initialized with any outstanding changes
2496 any). The patch will be initialized with any outstanding changes
2492 in the working directory. You may also use -I/--include,
2497 in the working directory. You may also use -I/--include,
2493 -X/--exclude, and/or a list of files after the patch name to add
2498 -X/--exclude, and/or a list of files after the patch name to add
2494 only changes to matching files to the new patch, leaving the rest
2499 only changes to matching files to the new patch, leaving the rest
2495 as uncommitted modifications.
2500 as uncommitted modifications.
2496
2501
2497 -u/--user and -d/--date can be used to set the (given) user and
2502 -u/--user and -d/--date can be used to set the (given) user and
2498 date, respectively. -U/--currentuser and -D/--currentdate set user
2503 date, respectively. -U/--currentuser and -D/--currentdate set user
2499 to current user and date to current date.
2504 to current user and date to current date.
2500
2505
2501 -e/--edit, -m/--message or -l/--logfile set the patch header as
2506 -e/--edit, -m/--message or -l/--logfile set the patch header as
2502 well as the commit message. If none is specified, the header is
2507 well as the commit message. If none is specified, the header is
2503 empty and the commit message is '[mq]: PATCH'.
2508 empty and the commit message is '[mq]: PATCH'.
2504
2509
2505 Use the -g/--git option to keep the patch in the git extended diff
2510 Use the -g/--git option to keep the patch in the git extended diff
2506 format. Read the diffs help topic for more information on why this
2511 format. Read the diffs help topic for more information on why this
2507 is important for preserving permission changes and copy/rename
2512 is important for preserving permission changes and copy/rename
2508 information.
2513 information.
2509
2514
2510 Returns 0 on successful creation of a new patch.
2515 Returns 0 on successful creation of a new patch.
2511 """
2516 """
2512 msg = cmdutil.logmessage(ui, opts)
2517 msg = cmdutil.logmessage(ui, opts)
2513 q = repo.mq
2518 q = repo.mq
2514 opts['msg'] = msg
2519 opts['msg'] = msg
2515 setupheaderopts(ui, opts)
2520 setupheaderopts(ui, opts)
2516 q.new(repo, patch, *args, **opts)
2521 q.new(repo, patch, *args, **opts)
2517 q.savedirty()
2522 q.savedirty()
2518 return 0
2523 return 0
2519
2524
2520 @command("^qrefresh",
2525 @command("^qrefresh",
2521 [('e', 'edit', None, _('invoke editor on commit messages')),
2526 [('e', 'edit', None, _('invoke editor on commit messages')),
2522 ('g', 'git', None, _('use git extended diff format')),
2527 ('g', 'git', None, _('use git extended diff format')),
2523 ('s', 'short', None,
2528 ('s', 'short', None,
2524 _('refresh only files already in the patch and specified files')),
2529 _('refresh only files already in the patch and specified files')),
2525 ('U', 'currentuser', None,
2530 ('U', 'currentuser', None,
2526 _('add/update author field in patch with current user')),
2531 _('add/update author field in patch with current user')),
2527 ('u', 'user', '',
2532 ('u', 'user', '',
2528 _('add/update author field in patch with given user'), _('USER')),
2533 _('add/update author field in patch with given user'), _('USER')),
2529 ('D', 'currentdate', None,
2534 ('D', 'currentdate', None,
2530 _('add/update date field in patch with current date')),
2535 _('add/update date field in patch with current date')),
2531 ('d', 'date', '',
2536 ('d', 'date', '',
2532 _('add/update date field in patch with given date'), _('DATE'))
2537 _('add/update date field in patch with given date'), _('DATE'))
2533 ] + commands.walkopts + commands.commitopts,
2538 ] + commands.walkopts + commands.commitopts,
2534 _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'),
2539 _('hg qrefresh [-I] [-X] [-e] [-m TEXT] [-l FILE] [-s] [FILE]...'),
2535 inferrepo=True)
2540 inferrepo=True)
2536 def refresh(ui, repo, *pats, **opts):
2541 def refresh(ui, repo, *pats, **opts):
2537 """update the current patch
2542 """update the current patch
2538
2543
2539 If any file patterns are provided, the refreshed patch will
2544 If any file patterns are provided, the refreshed patch will
2540 contain only the modifications that match those patterns; the
2545 contain only the modifications that match those patterns; the
2541 remaining modifications will remain in the working directory.
2546 remaining modifications will remain in the working directory.
2542
2547
2543 If -s/--short is specified, files currently included in the patch
2548 If -s/--short is specified, files currently included in the patch
2544 will be refreshed just like matched files and remain in the patch.
2549 will be refreshed just like matched files and remain in the patch.
2545
2550
2546 If -e/--edit is specified, Mercurial will start your configured editor for
2551 If -e/--edit is specified, Mercurial will start your configured editor for
2547 you to enter a message. In case qrefresh fails, you will find a backup of
2552 you to enter a message. In case qrefresh fails, you will find a backup of
2548 your message in ``.hg/last-message.txt``.
2553 your message in ``.hg/last-message.txt``.
2549
2554
2550 hg add/remove/copy/rename work as usual, though you might want to
2555 hg add/remove/copy/rename work as usual, though you might want to
2551 use git-style patches (-g/--git or [diff] git=1) to track copies
2556 use git-style patches (-g/--git or [diff] git=1) to track copies
2552 and renames. See the diffs help topic for more information on the
2557 and renames. See the diffs help topic for more information on the
2553 git diff format.
2558 git diff format.
2554
2559
2555 Returns 0 on success.
2560 Returns 0 on success.
2556 """
2561 """
2557 q = repo.mq
2562 q = repo.mq
2558 message = cmdutil.logmessage(ui, opts)
2563 message = cmdutil.logmessage(ui, opts)
2559 setupheaderopts(ui, opts)
2564 setupheaderopts(ui, opts)
2560 wlock = repo.wlock()
2565 wlock = repo.wlock()
2561 try:
2566 try:
2562 ret = q.refresh(repo, pats, msg=message, **opts)
2567 ret = q.refresh(repo, pats, msg=message, **opts)
2563 q.savedirty()
2568 q.savedirty()
2564 return ret
2569 return ret
2565 finally:
2570 finally:
2566 wlock.release()
2571 wlock.release()
2567
2572
2568 @command("^qdiff",
2573 @command("^qdiff",
2569 commands.diffopts + commands.diffopts2 + commands.walkopts,
2574 commands.diffopts + commands.diffopts2 + commands.walkopts,
2570 _('hg qdiff [OPTION]... [FILE]...'),
2575 _('hg qdiff [OPTION]... [FILE]...'),
2571 inferrepo=True)
2576 inferrepo=True)
2572 def diff(ui, repo, *pats, **opts):
2577 def diff(ui, repo, *pats, **opts):
2573 """diff of the current patch and subsequent modifications
2578 """diff of the current patch and subsequent modifications
2574
2579
2575 Shows a diff which includes the current patch as well as any
2580 Shows a diff which includes the current patch as well as any
2576 changes which have been made in the working directory since the
2581 changes which have been made in the working directory since the
2577 last refresh (thus showing what the current patch would become
2582 last refresh (thus showing what the current patch would become
2578 after a qrefresh).
2583 after a qrefresh).
2579
2584
2580 Use :hg:`diff` if you only want to see the changes made since the
2585 Use :hg:`diff` if you only want to see the changes made since the
2581 last qrefresh, or :hg:`export qtip` if you want to see changes
2586 last qrefresh, or :hg:`export qtip` if you want to see changes
2582 made by the current patch without including changes made since the
2587 made by the current patch without including changes made since the
2583 qrefresh.
2588 qrefresh.
2584
2589
2585 Returns 0 on success.
2590 Returns 0 on success.
2586 """
2591 """
2587 repo.mq.diff(repo, pats, opts)
2592 repo.mq.diff(repo, pats, opts)
2588 return 0
2593 return 0
2589
2594
2590 @command('qfold',
2595 @command('qfold',
2591 [('e', 'edit', None, _('invoke editor on commit messages')),
2596 [('e', 'edit', None, _('invoke editor on commit messages')),
2592 ('k', 'keep', None, _('keep folded patch files')),
2597 ('k', 'keep', None, _('keep folded patch files')),
2593 ] + commands.commitopts,
2598 ] + commands.commitopts,
2594 _('hg qfold [-e] [-k] [-m TEXT] [-l FILE] PATCH...'))
2599 _('hg qfold [-e] [-k] [-m TEXT] [-l FILE] PATCH...'))
2595 def fold(ui, repo, *files, **opts):
2600 def fold(ui, repo, *files, **opts):
2596 """fold the named patches into the current patch
2601 """fold the named patches into the current patch
2597
2602
2598 Patches must not yet be applied. Each patch will be successively
2603 Patches must not yet be applied. Each patch will be successively
2599 applied to the current patch in the order given. If all the
2604 applied to the current patch in the order given. If all the
2600 patches apply successfully, the current patch will be refreshed
2605 patches apply successfully, the current patch will be refreshed
2601 with the new cumulative patch, and the folded patches will be
2606 with the new cumulative patch, and the folded patches will be
2602 deleted. With -k/--keep, the folded patch files will not be
2607 deleted. With -k/--keep, the folded patch files will not be
2603 removed afterwards.
2608 removed afterwards.
2604
2609
2605 The header for each folded patch will be concatenated with the
2610 The header for each folded patch will be concatenated with the
2606 current patch header, separated by a line of ``* * *``.
2611 current patch header, separated by a line of ``* * *``.
2607
2612
2608 Returns 0 on success."""
2613 Returns 0 on success."""
2609 q = repo.mq
2614 q = repo.mq
2610 if not files:
2615 if not files:
2611 raise util.Abort(_('qfold requires at least one patch name'))
2616 raise util.Abort(_('qfold requires at least one patch name'))
2612 if not q.checktoppatch(repo)[0]:
2617 if not q.checktoppatch(repo)[0]:
2613 raise util.Abort(_('no patches applied'))
2618 raise util.Abort(_('no patches applied'))
2614 q.checklocalchanges(repo)
2619 q.checklocalchanges(repo)
2615
2620
2616 message = cmdutil.logmessage(ui, opts)
2621 message = cmdutil.logmessage(ui, opts)
2617
2622
2618 parent = q.lookup('qtip')
2623 parent = q.lookup('qtip')
2619 patches = []
2624 patches = []
2620 messages = []
2625 messages = []
2621 for f in files:
2626 for f in files:
2622 p = q.lookup(f)
2627 p = q.lookup(f)
2623 if p in patches or p == parent:
2628 if p in patches or p == parent:
2624 ui.warn(_('skipping already folded patch %s\n') % p)
2629 ui.warn(_('skipping already folded patch %s\n') % p)
2625 if q.isapplied(p):
2630 if q.isapplied(p):
2626 raise util.Abort(_('qfold cannot fold already applied patch %s')
2631 raise util.Abort(_('qfold cannot fold already applied patch %s')
2627 % p)
2632 % p)
2628 patches.append(p)
2633 patches.append(p)
2629
2634
2630 for p in patches:
2635 for p in patches:
2631 if not message:
2636 if not message:
2632 ph = patchheader(q.join(p), q.plainmode)
2637 ph = patchheader(q.join(p), q.plainmode)
2633 if ph.message:
2638 if ph.message:
2634 messages.append(ph.message)
2639 messages.append(ph.message)
2635 pf = q.join(p)
2640 pf = q.join(p)
2636 (patchsuccess, files, fuzz) = q.patch(repo, pf)
2641 (patchsuccess, files, fuzz) = q.patch(repo, pf)
2637 if not patchsuccess:
2642 if not patchsuccess:
2638 raise util.Abort(_('error folding patch %s') % p)
2643 raise util.Abort(_('error folding patch %s') % p)
2639
2644
2640 if not message:
2645 if not message:
2641 ph = patchheader(q.join(parent), q.plainmode)
2646 ph = patchheader(q.join(parent), q.plainmode)
2642 message = ph.message
2647 message = ph.message
2643 for msg in messages:
2648 for msg in messages:
2644 if msg:
2649 if msg:
2645 if message:
2650 if message:
2646 message.append('* * *')
2651 message.append('* * *')
2647 message.extend(msg)
2652 message.extend(msg)
2648 message = '\n'.join(message)
2653 message = '\n'.join(message)
2649
2654
2650 diffopts = q.patchopts(q.diffopts(), *patches)
2655 diffopts = q.patchopts(q.diffopts(), *patches)
2651 wlock = repo.wlock()
2656 wlock = repo.wlock()
2652 try:
2657 try:
2653 q.refresh(repo, msg=message, git=diffopts.git, edit=opts.get('edit'),
2658 q.refresh(repo, msg=message, git=diffopts.git, edit=opts.get('edit'),
2654 editform='mq.qfold')
2659 editform='mq.qfold')
2655 q.delete(repo, patches, opts)
2660 q.delete(repo, patches, opts)
2656 q.savedirty()
2661 q.savedirty()
2657 finally:
2662 finally:
2658 wlock.release()
2663 wlock.release()
2659
2664
2660 @command("qgoto",
2665 @command("qgoto",
2661 [('', 'keep-changes', None,
2666 [('', 'keep-changes', None,
2662 _('tolerate non-conflicting local changes')),
2667 _('tolerate non-conflicting local changes')),
2663 ('f', 'force', None, _('overwrite any local changes')),
2668 ('f', 'force', None, _('overwrite any local changes')),
2664 ('', 'no-backup', None, _('do not save backup copies of files'))],
2669 ('', 'no-backup', None, _('do not save backup copies of files'))],
2665 _('hg qgoto [OPTION]... PATCH'))
2670 _('hg qgoto [OPTION]... PATCH'))
2666 def goto(ui, repo, patch, **opts):
2671 def goto(ui, repo, patch, **opts):
2667 '''push or pop patches until named patch is at top of stack
2672 '''push or pop patches until named patch is at top of stack
2668
2673
2669 Returns 0 on success.'''
2674 Returns 0 on success.'''
2670 opts = fixkeepchangesopts(ui, opts)
2675 opts = fixkeepchangesopts(ui, opts)
2671 q = repo.mq
2676 q = repo.mq
2672 patch = q.lookup(patch)
2677 patch = q.lookup(patch)
2673 nobackup = opts.get('no_backup')
2678 nobackup = opts.get('no_backup')
2674 keepchanges = opts.get('keep_changes')
2679 keepchanges = opts.get('keep_changes')
2675 if q.isapplied(patch):
2680 if q.isapplied(patch):
2676 ret = q.pop(repo, patch, force=opts.get('force'), nobackup=nobackup,
2681 ret = q.pop(repo, patch, force=opts.get('force'), nobackup=nobackup,
2677 keepchanges=keepchanges)
2682 keepchanges=keepchanges)
2678 else:
2683 else:
2679 ret = q.push(repo, patch, force=opts.get('force'), nobackup=nobackup,
2684 ret = q.push(repo, patch, force=opts.get('force'), nobackup=nobackup,
2680 keepchanges=keepchanges)
2685 keepchanges=keepchanges)
2681 q.savedirty()
2686 q.savedirty()
2682 return ret
2687 return ret
2683
2688
2684 @command("qguard",
2689 @command("qguard",
2685 [('l', 'list', None, _('list all patches and guards')),
2690 [('l', 'list', None, _('list all patches and guards')),
2686 ('n', 'none', None, _('drop all guards'))],
2691 ('n', 'none', None, _('drop all guards'))],
2687 _('hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]'))
2692 _('hg qguard [-l] [-n] [PATCH] [-- [+GUARD]... [-GUARD]...]'))
2688 def guard(ui, repo, *args, **opts):
2693 def guard(ui, repo, *args, **opts):
2689 '''set or print guards for a patch
2694 '''set or print guards for a patch
2690
2695
2691 Guards control whether a patch can be pushed. A patch with no
2696 Guards control whether a patch can be pushed. A patch with no
2692 guards is always pushed. A patch with a positive guard ("+foo") is
2697 guards is always pushed. A patch with a positive guard ("+foo") is
2693 pushed only if the :hg:`qselect` command has activated it. A patch with
2698 pushed only if the :hg:`qselect` command has activated it. A patch with
2694 a negative guard ("-foo") is never pushed if the :hg:`qselect` command
2699 a negative guard ("-foo") is never pushed if the :hg:`qselect` command
2695 has activated it.
2700 has activated it.
2696
2701
2697 With no arguments, print the currently active guards.
2702 With no arguments, print the currently active guards.
2698 With arguments, set guards for the named patch.
2703 With arguments, set guards for the named patch.
2699
2704
2700 .. note::
2705 .. note::
2701
2706
2702 Specifying negative guards now requires '--'.
2707 Specifying negative guards now requires '--'.
2703
2708
2704 To set guards on another patch::
2709 To set guards on another patch::
2705
2710
2706 hg qguard other.patch -- +2.6.17 -stable
2711 hg qguard other.patch -- +2.6.17 -stable
2707
2712
2708 Returns 0 on success.
2713 Returns 0 on success.
2709 '''
2714 '''
2710 def status(idx):
2715 def status(idx):
2711 guards = q.seriesguards[idx] or ['unguarded']
2716 guards = q.seriesguards[idx] or ['unguarded']
2712 if q.series[idx] in applied:
2717 if q.series[idx] in applied:
2713 state = 'applied'
2718 state = 'applied'
2714 elif q.pushable(idx)[0]:
2719 elif q.pushable(idx)[0]:
2715 state = 'unapplied'
2720 state = 'unapplied'
2716 else:
2721 else:
2717 state = 'guarded'
2722 state = 'guarded'
2718 label = 'qguard.patch qguard.%s qseries.%s' % (state, state)
2723 label = 'qguard.patch qguard.%s qseries.%s' % (state, state)
2719 ui.write('%s: ' % ui.label(q.series[idx], label))
2724 ui.write('%s: ' % ui.label(q.series[idx], label))
2720
2725
2721 for i, guard in enumerate(guards):
2726 for i, guard in enumerate(guards):
2722 if guard.startswith('+'):
2727 if guard.startswith('+'):
2723 ui.write(guard, label='qguard.positive')
2728 ui.write(guard, label='qguard.positive')
2724 elif guard.startswith('-'):
2729 elif guard.startswith('-'):
2725 ui.write(guard, label='qguard.negative')
2730 ui.write(guard, label='qguard.negative')
2726 else:
2731 else:
2727 ui.write(guard, label='qguard.unguarded')
2732 ui.write(guard, label='qguard.unguarded')
2728 if i != len(guards) - 1:
2733 if i != len(guards) - 1:
2729 ui.write(' ')
2734 ui.write(' ')
2730 ui.write('\n')
2735 ui.write('\n')
2731 q = repo.mq
2736 q = repo.mq
2732 applied = set(p.name for p in q.applied)
2737 applied = set(p.name for p in q.applied)
2733 patch = None
2738 patch = None
2734 args = list(args)
2739 args = list(args)
2735 if opts.get('list'):
2740 if opts.get('list'):
2736 if args or opts.get('none'):
2741 if args or opts.get('none'):
2737 raise util.Abort(_('cannot mix -l/--list with options or '
2742 raise util.Abort(_('cannot mix -l/--list with options or '
2738 'arguments'))
2743 'arguments'))
2739 for i in xrange(len(q.series)):
2744 for i in xrange(len(q.series)):
2740 status(i)
2745 status(i)
2741 return
2746 return
2742 if not args or args[0][0:1] in '-+':
2747 if not args or args[0][0:1] in '-+':
2743 if not q.applied:
2748 if not q.applied:
2744 raise util.Abort(_('no patches applied'))
2749 raise util.Abort(_('no patches applied'))
2745 patch = q.applied[-1].name
2750 patch = q.applied[-1].name
2746 if patch is None and args[0][0:1] not in '-+':
2751 if patch is None and args[0][0:1] not in '-+':
2747 patch = args.pop(0)
2752 patch = args.pop(0)
2748 if patch is None:
2753 if patch is None:
2749 raise util.Abort(_('no patch to work with'))
2754 raise util.Abort(_('no patch to work with'))
2750 if args or opts.get('none'):
2755 if args or opts.get('none'):
2751 idx = q.findseries(patch)
2756 idx = q.findseries(patch)
2752 if idx is None:
2757 if idx is None:
2753 raise util.Abort(_('no patch named %s') % patch)
2758 raise util.Abort(_('no patch named %s') % patch)
2754 q.setguards(idx, args)
2759 q.setguards(idx, args)
2755 q.savedirty()
2760 q.savedirty()
2756 else:
2761 else:
2757 status(q.series.index(q.lookup(patch)))
2762 status(q.series.index(q.lookup(patch)))
2758
2763
2759 @command("qheader", [], _('hg qheader [PATCH]'))
2764 @command("qheader", [], _('hg qheader [PATCH]'))
2760 def header(ui, repo, patch=None):
2765 def header(ui, repo, patch=None):
2761 """print the header of the topmost or specified patch
2766 """print the header of the topmost or specified patch
2762
2767
2763 Returns 0 on success."""
2768 Returns 0 on success."""
2764 q = repo.mq
2769 q = repo.mq
2765
2770
2766 if patch:
2771 if patch:
2767 patch = q.lookup(patch)
2772 patch = q.lookup(patch)
2768 else:
2773 else:
2769 if not q.applied:
2774 if not q.applied:
2770 ui.write(_('no patches applied\n'))
2775 ui.write(_('no patches applied\n'))
2771 return 1
2776 return 1
2772 patch = q.lookup('qtip')
2777 patch = q.lookup('qtip')
2773 ph = patchheader(q.join(patch), q.plainmode)
2778 ph = patchheader(q.join(patch), q.plainmode)
2774
2779
2775 ui.write('\n'.join(ph.message) + '\n')
2780 ui.write('\n'.join(ph.message) + '\n')
2776
2781
2777 def lastsavename(path):
2782 def lastsavename(path):
2778 (directory, base) = os.path.split(path)
2783 (directory, base) = os.path.split(path)
2779 names = os.listdir(directory)
2784 names = os.listdir(directory)
2780 namere = re.compile("%s.([0-9]+)" % base)
2785 namere = re.compile("%s.([0-9]+)" % base)
2781 maxindex = None
2786 maxindex = None
2782 maxname = None
2787 maxname = None
2783 for f in names:
2788 for f in names:
2784 m = namere.match(f)
2789 m = namere.match(f)
2785 if m:
2790 if m:
2786 index = int(m.group(1))
2791 index = int(m.group(1))
2787 if maxindex is None or index > maxindex:
2792 if maxindex is None or index > maxindex:
2788 maxindex = index
2793 maxindex = index
2789 maxname = f
2794 maxname = f
2790 if maxname:
2795 if maxname:
2791 return (os.path.join(directory, maxname), maxindex)
2796 return (os.path.join(directory, maxname), maxindex)
2792 return (None, None)
2797 return (None, None)
2793
2798
2794 def savename(path):
2799 def savename(path):
2795 (last, index) = lastsavename(path)
2800 (last, index) = lastsavename(path)
2796 if last is None:
2801 if last is None:
2797 index = 0
2802 index = 0
2798 newpath = path + ".%d" % (index + 1)
2803 newpath = path + ".%d" % (index + 1)
2799 return newpath
2804 return newpath
2800
2805
2801 @command("^qpush",
2806 @command("^qpush",
2802 [('', 'keep-changes', None,
2807 [('', 'keep-changes', None,
2803 _('tolerate non-conflicting local changes')),
2808 _('tolerate non-conflicting local changes')),
2804 ('f', 'force', None, _('apply on top of local changes')),
2809 ('f', 'force', None, _('apply on top of local changes')),
2805 ('e', 'exact', None,
2810 ('e', 'exact', None,
2806 _('apply the target patch to its recorded parent')),
2811 _('apply the target patch to its recorded parent')),
2807 ('l', 'list', None, _('list patch name in commit text')),
2812 ('l', 'list', None, _('list patch name in commit text')),
2808 ('a', 'all', None, _('apply all patches')),
2813 ('a', 'all', None, _('apply all patches')),
2809 ('m', 'merge', None, _('merge from another queue (DEPRECATED)')),
2814 ('m', 'merge', None, _('merge from another queue (DEPRECATED)')),
2810 ('n', 'name', '',
2815 ('n', 'name', '',
2811 _('merge queue name (DEPRECATED)'), _('NAME')),
2816 _('merge queue name (DEPRECATED)'), _('NAME')),
2812 ('', 'move', None,
2817 ('', 'move', None,
2813 _('reorder patch series and apply only the patch')),
2818 _('reorder patch series and apply only the patch')),
2814 ('', 'no-backup', None, _('do not save backup copies of files'))],
2819 ('', 'no-backup', None, _('do not save backup copies of files'))],
2815 _('hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]'))
2820 _('hg qpush [-f] [-l] [-a] [--move] [PATCH | INDEX]'))
2816 def push(ui, repo, patch=None, **opts):
2821 def push(ui, repo, patch=None, **opts):
2817 """push the next patch onto the stack
2822 """push the next patch onto the stack
2818
2823
2819 By default, abort if the working directory contains uncommitted
2824 By default, abort if the working directory contains uncommitted
2820 changes. With --keep-changes, abort only if the uncommitted files
2825 changes. With --keep-changes, abort only if the uncommitted files
2821 overlap with patched files. With -f/--force, backup and patch over
2826 overlap with patched files. With -f/--force, backup and patch over
2822 uncommitted changes.
2827 uncommitted changes.
2823
2828
2824 Return 0 on success.
2829 Return 0 on success.
2825 """
2830 """
2826 q = repo.mq
2831 q = repo.mq
2827 mergeq = None
2832 mergeq = None
2828
2833
2829 opts = fixkeepchangesopts(ui, opts)
2834 opts = fixkeepchangesopts(ui, opts)
2830 if opts.get('merge'):
2835 if opts.get('merge'):
2831 if opts.get('name'):
2836 if opts.get('name'):
2832 newpath = repo.join(opts.get('name'))
2837 newpath = repo.join(opts.get('name'))
2833 else:
2838 else:
2834 newpath, i = lastsavename(q.path)
2839 newpath, i = lastsavename(q.path)
2835 if not newpath:
2840 if not newpath:
2836 ui.warn(_("no saved queues found, please use -n\n"))
2841 ui.warn(_("no saved queues found, please use -n\n"))
2837 return 1
2842 return 1
2838 mergeq = queue(ui, repo.baseui, repo.path, newpath)
2843 mergeq = queue(ui, repo.baseui, repo.path, newpath)
2839 ui.warn(_("merging with queue at: %s\n") % mergeq.path)
2844 ui.warn(_("merging with queue at: %s\n") % mergeq.path)
2840 ret = q.push(repo, patch, force=opts.get('force'), list=opts.get('list'),
2845 ret = q.push(repo, patch, force=opts.get('force'), list=opts.get('list'),
2841 mergeq=mergeq, all=opts.get('all'), move=opts.get('move'),
2846 mergeq=mergeq, all=opts.get('all'), move=opts.get('move'),
2842 exact=opts.get('exact'), nobackup=opts.get('no_backup'),
2847 exact=opts.get('exact'), nobackup=opts.get('no_backup'),
2843 keepchanges=opts.get('keep_changes'))
2848 keepchanges=opts.get('keep_changes'))
2844 return ret
2849 return ret
2845
2850
2846 @command("^qpop",
2851 @command("^qpop",
2847 [('a', 'all', None, _('pop all patches')),
2852 [('a', 'all', None, _('pop all patches')),
2848 ('n', 'name', '',
2853 ('n', 'name', '',
2849 _('queue name to pop (DEPRECATED)'), _('NAME')),
2854 _('queue name to pop (DEPRECATED)'), _('NAME')),
2850 ('', 'keep-changes', None,
2855 ('', 'keep-changes', None,
2851 _('tolerate non-conflicting local changes')),
2856 _('tolerate non-conflicting local changes')),
2852 ('f', 'force', None, _('forget any local changes to patched files')),
2857 ('f', 'force', None, _('forget any local changes to patched files')),
2853 ('', 'no-backup', None, _('do not save backup copies of files'))],
2858 ('', 'no-backup', None, _('do not save backup copies of files'))],
2854 _('hg qpop [-a] [-f] [PATCH | INDEX]'))
2859 _('hg qpop [-a] [-f] [PATCH | INDEX]'))
2855 def pop(ui, repo, patch=None, **opts):
2860 def pop(ui, repo, patch=None, **opts):
2856 """pop the current patch off the stack
2861 """pop the current patch off the stack
2857
2862
2858 Without argument, pops off the top of the patch stack. If given a
2863 Without argument, pops off the top of the patch stack. If given a
2859 patch name, keeps popping off patches until the named patch is at
2864 patch name, keeps popping off patches until the named patch is at
2860 the top of the stack.
2865 the top of the stack.
2861
2866
2862 By default, abort if the working directory contains uncommitted
2867 By default, abort if the working directory contains uncommitted
2863 changes. With --keep-changes, abort only if the uncommitted files
2868 changes. With --keep-changes, abort only if the uncommitted files
2864 overlap with patched files. With -f/--force, backup and discard
2869 overlap with patched files. With -f/--force, backup and discard
2865 changes made to such files.
2870 changes made to such files.
2866
2871
2867 Return 0 on success.
2872 Return 0 on success.
2868 """
2873 """
2869 opts = fixkeepchangesopts(ui, opts)
2874 opts = fixkeepchangesopts(ui, opts)
2870 localupdate = True
2875 localupdate = True
2871 if opts.get('name'):
2876 if opts.get('name'):
2872 q = queue(ui, repo.baseui, repo.path, repo.join(opts.get('name')))
2877 q = queue(ui, repo.baseui, repo.path, repo.join(opts.get('name')))
2873 ui.warn(_('using patch queue: %s\n') % q.path)
2878 ui.warn(_('using patch queue: %s\n') % q.path)
2874 localupdate = False
2879 localupdate = False
2875 else:
2880 else:
2876 q = repo.mq
2881 q = repo.mq
2877 ret = q.pop(repo, patch, force=opts.get('force'), update=localupdate,
2882 ret = q.pop(repo, patch, force=opts.get('force'), update=localupdate,
2878 all=opts.get('all'), nobackup=opts.get('no_backup'),
2883 all=opts.get('all'), nobackup=opts.get('no_backup'),
2879 keepchanges=opts.get('keep_changes'))
2884 keepchanges=opts.get('keep_changes'))
2880 q.savedirty()
2885 q.savedirty()
2881 return ret
2886 return ret
2882
2887
2883 @command("qrename|qmv", [], _('hg qrename PATCH1 [PATCH2]'))
2888 @command("qrename|qmv", [], _('hg qrename PATCH1 [PATCH2]'))
2884 def rename(ui, repo, patch, name=None, **opts):
2889 def rename(ui, repo, patch, name=None, **opts):
2885 """rename a patch
2890 """rename a patch
2886
2891
2887 With one argument, renames the current patch to PATCH1.
2892 With one argument, renames the current patch to PATCH1.
2888 With two arguments, renames PATCH1 to PATCH2.
2893 With two arguments, renames PATCH1 to PATCH2.
2889
2894
2890 Returns 0 on success."""
2895 Returns 0 on success."""
2891 q = repo.mq
2896 q = repo.mq
2892 if not name:
2897 if not name:
2893 name = patch
2898 name = patch
2894 patch = None
2899 patch = None
2895
2900
2896 if patch:
2901 if patch:
2897 patch = q.lookup(patch)
2902 patch = q.lookup(patch)
2898 else:
2903 else:
2899 if not q.applied:
2904 if not q.applied:
2900 ui.write(_('no patches applied\n'))
2905 ui.write(_('no patches applied\n'))
2901 return
2906 return
2902 patch = q.lookup('qtip')
2907 patch = q.lookup('qtip')
2903 absdest = q.join(name)
2908 absdest = q.join(name)
2904 if os.path.isdir(absdest):
2909 if os.path.isdir(absdest):
2905 name = normname(os.path.join(name, os.path.basename(patch)))
2910 name = normname(os.path.join(name, os.path.basename(patch)))
2906 absdest = q.join(name)
2911 absdest = q.join(name)
2907 q.checkpatchname(name)
2912 q.checkpatchname(name)
2908
2913
2909 ui.note(_('renaming %s to %s\n') % (patch, name))
2914 ui.note(_('renaming %s to %s\n') % (patch, name))
2910 i = q.findseries(patch)
2915 i = q.findseries(patch)
2911 guards = q.guard_re.findall(q.fullseries[i])
2916 guards = q.guard_re.findall(q.fullseries[i])
2912 q.fullseries[i] = name + ''.join([' #' + g for g in guards])
2917 q.fullseries[i] = name + ''.join([' #' + g for g in guards])
2913 q.parseseries()
2918 q.parseseries()
2914 q.seriesdirty = True
2919 q.seriesdirty = True
2915
2920
2916 info = q.isapplied(patch)
2921 info = q.isapplied(patch)
2917 if info:
2922 if info:
2918 q.applied[info[0]] = statusentry(info[1], name)
2923 q.applied[info[0]] = statusentry(info[1], name)
2919 q.applieddirty = True
2924 q.applieddirty = True
2920
2925
2921 destdir = os.path.dirname(absdest)
2926 destdir = os.path.dirname(absdest)
2922 if not os.path.isdir(destdir):
2927 if not os.path.isdir(destdir):
2923 os.makedirs(destdir)
2928 os.makedirs(destdir)
2924 util.rename(q.join(patch), absdest)
2929 util.rename(q.join(patch), absdest)
2925 r = q.qrepo()
2930 r = q.qrepo()
2926 if r and patch in r.dirstate:
2931 if r and patch in r.dirstate:
2927 wctx = r[None]
2932 wctx = r[None]
2928 wlock = r.wlock()
2933 wlock = r.wlock()
2929 try:
2934 try:
2930 if r.dirstate[patch] == 'a':
2935 if r.dirstate[patch] == 'a':
2931 r.dirstate.drop(patch)
2936 r.dirstate.drop(patch)
2932 r.dirstate.add(name)
2937 r.dirstate.add(name)
2933 else:
2938 else:
2934 wctx.copy(patch, name)
2939 wctx.copy(patch, name)
2935 wctx.forget([patch])
2940 wctx.forget([patch])
2936 finally:
2941 finally:
2937 wlock.release()
2942 wlock.release()
2938
2943
2939 q.savedirty()
2944 q.savedirty()
2940
2945
2941 @command("qrestore",
2946 @command("qrestore",
2942 [('d', 'delete', None, _('delete save entry')),
2947 [('d', 'delete', None, _('delete save entry')),
2943 ('u', 'update', None, _('update queue working directory'))],
2948 ('u', 'update', None, _('update queue working directory'))],
2944 _('hg qrestore [-d] [-u] REV'))
2949 _('hg qrestore [-d] [-u] REV'))
2945 def restore(ui, repo, rev, **opts):
2950 def restore(ui, repo, rev, **opts):
2946 """restore the queue state saved by a revision (DEPRECATED)
2951 """restore the queue state saved by a revision (DEPRECATED)
2947
2952
2948 This command is deprecated, use :hg:`rebase` instead."""
2953 This command is deprecated, use :hg:`rebase` instead."""
2949 rev = repo.lookup(rev)
2954 rev = repo.lookup(rev)
2950 q = repo.mq
2955 q = repo.mq
2951 q.restore(repo, rev, delete=opts.get('delete'),
2956 q.restore(repo, rev, delete=opts.get('delete'),
2952 qupdate=opts.get('update'))
2957 qupdate=opts.get('update'))
2953 q.savedirty()
2958 q.savedirty()
2954 return 0
2959 return 0
2955
2960
2956 @command("qsave",
2961 @command("qsave",
2957 [('c', 'copy', None, _('copy patch directory')),
2962 [('c', 'copy', None, _('copy patch directory')),
2958 ('n', 'name', '',
2963 ('n', 'name', '',
2959 _('copy directory name'), _('NAME')),
2964 _('copy directory name'), _('NAME')),
2960 ('e', 'empty', None, _('clear queue status file')),
2965 ('e', 'empty', None, _('clear queue status file')),
2961 ('f', 'force', None, _('force copy'))] + commands.commitopts,
2966 ('f', 'force', None, _('force copy'))] + commands.commitopts,
2962 _('hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'))
2967 _('hg qsave [-m TEXT] [-l FILE] [-c] [-n NAME] [-e] [-f]'))
2963 def save(ui, repo, **opts):
2968 def save(ui, repo, **opts):
2964 """save current queue state (DEPRECATED)
2969 """save current queue state (DEPRECATED)
2965
2970
2966 This command is deprecated, use :hg:`rebase` instead."""
2971 This command is deprecated, use :hg:`rebase` instead."""
2967 q = repo.mq
2972 q = repo.mq
2968 message = cmdutil.logmessage(ui, opts)
2973 message = cmdutil.logmessage(ui, opts)
2969 ret = q.save(repo, msg=message)
2974 ret = q.save(repo, msg=message)
2970 if ret:
2975 if ret:
2971 return ret
2976 return ret
2972 q.savedirty() # save to .hg/patches before copying
2977 q.savedirty() # save to .hg/patches before copying
2973 if opts.get('copy'):
2978 if opts.get('copy'):
2974 path = q.path
2979 path = q.path
2975 if opts.get('name'):
2980 if opts.get('name'):
2976 newpath = os.path.join(q.basepath, opts.get('name'))
2981 newpath = os.path.join(q.basepath, opts.get('name'))
2977 if os.path.exists(newpath):
2982 if os.path.exists(newpath):
2978 if not os.path.isdir(newpath):
2983 if not os.path.isdir(newpath):
2979 raise util.Abort(_('destination %s exists and is not '
2984 raise util.Abort(_('destination %s exists and is not '
2980 'a directory') % newpath)
2985 'a directory') % newpath)
2981 if not opts.get('force'):
2986 if not opts.get('force'):
2982 raise util.Abort(_('destination %s exists, '
2987 raise util.Abort(_('destination %s exists, '
2983 'use -f to force') % newpath)
2988 'use -f to force') % newpath)
2984 else:
2989 else:
2985 newpath = savename(path)
2990 newpath = savename(path)
2986 ui.warn(_("copy %s to %s\n") % (path, newpath))
2991 ui.warn(_("copy %s to %s\n") % (path, newpath))
2987 util.copyfiles(path, newpath)
2992 util.copyfiles(path, newpath)
2988 if opts.get('empty'):
2993 if opts.get('empty'):
2989 del q.applied[:]
2994 del q.applied[:]
2990 q.applieddirty = True
2995 q.applieddirty = True
2991 q.savedirty()
2996 q.savedirty()
2992 return 0
2997 return 0
2993
2998
2994
2999
2995 @command("qselect",
3000 @command("qselect",
2996 [('n', 'none', None, _('disable all guards')),
3001 [('n', 'none', None, _('disable all guards')),
2997 ('s', 'series', None, _('list all guards in series file')),
3002 ('s', 'series', None, _('list all guards in series file')),
2998 ('', 'pop', None, _('pop to before first guarded applied patch')),
3003 ('', 'pop', None, _('pop to before first guarded applied patch')),
2999 ('', 'reapply', None, _('pop, then reapply patches'))],
3004 ('', 'reapply', None, _('pop, then reapply patches'))],
3000 _('hg qselect [OPTION]... [GUARD]...'))
3005 _('hg qselect [OPTION]... [GUARD]...'))
3001 def select(ui, repo, *args, **opts):
3006 def select(ui, repo, *args, **opts):
3002 '''set or print guarded patches to push
3007 '''set or print guarded patches to push
3003
3008
3004 Use the :hg:`qguard` command to set or print guards on patch, then use
3009 Use the :hg:`qguard` command to set or print guards on patch, then use
3005 qselect to tell mq which guards to use. A patch will be pushed if
3010 qselect to tell mq which guards to use. A patch will be pushed if
3006 it has no guards or any positive guards match the currently
3011 it has no guards or any positive guards match the currently
3007 selected guard, but will not be pushed if any negative guards
3012 selected guard, but will not be pushed if any negative guards
3008 match the current guard. For example::
3013 match the current guard. For example::
3009
3014
3010 qguard foo.patch -- -stable (negative guard)
3015 qguard foo.patch -- -stable (negative guard)
3011 qguard bar.patch +stable (positive guard)
3016 qguard bar.patch +stable (positive guard)
3012 qselect stable
3017 qselect stable
3013
3018
3014 This activates the "stable" guard. mq will skip foo.patch (because
3019 This activates the "stable" guard. mq will skip foo.patch (because
3015 it has a negative match) but push bar.patch (because it has a
3020 it has a negative match) but push bar.patch (because it has a
3016 positive match).
3021 positive match).
3017
3022
3018 With no arguments, prints the currently active guards.
3023 With no arguments, prints the currently active guards.
3019 With one argument, sets the active guard.
3024 With one argument, sets the active guard.
3020
3025
3021 Use -n/--none to deactivate guards (no other arguments needed).
3026 Use -n/--none to deactivate guards (no other arguments needed).
3022 When no guards are active, patches with positive guards are
3027 When no guards are active, patches with positive guards are
3023 skipped and patches with negative guards are pushed.
3028 skipped and patches with negative guards are pushed.
3024
3029
3025 qselect can change the guards on applied patches. It does not pop
3030 qselect can change the guards on applied patches. It does not pop
3026 guarded patches by default. Use --pop to pop back to the last
3031 guarded patches by default. Use --pop to pop back to the last
3027 applied patch that is not guarded. Use --reapply (which implies
3032 applied patch that is not guarded. Use --reapply (which implies
3028 --pop) to push back to the current patch afterwards, but skip
3033 --pop) to push back to the current patch afterwards, but skip
3029 guarded patches.
3034 guarded patches.
3030
3035
3031 Use -s/--series to print a list of all guards in the series file
3036 Use -s/--series to print a list of all guards in the series file
3032 (no other arguments needed). Use -v for more information.
3037 (no other arguments needed). Use -v for more information.
3033
3038
3034 Returns 0 on success.'''
3039 Returns 0 on success.'''
3035
3040
3036 q = repo.mq
3041 q = repo.mq
3037 guards = q.active()
3042 guards = q.active()
3038 pushable = lambda i: q.pushable(q.applied[i].name)[0]
3043 pushable = lambda i: q.pushable(q.applied[i].name)[0]
3039 if args or opts.get('none'):
3044 if args or opts.get('none'):
3040 old_unapplied = q.unapplied(repo)
3045 old_unapplied = q.unapplied(repo)
3041 old_guarded = [i for i in xrange(len(q.applied)) if not pushable(i)]
3046 old_guarded = [i for i in xrange(len(q.applied)) if not pushable(i)]
3042 q.setactive(args)
3047 q.setactive(args)
3043 q.savedirty()
3048 q.savedirty()
3044 if not args:
3049 if not args:
3045 ui.status(_('guards deactivated\n'))
3050 ui.status(_('guards deactivated\n'))
3046 if not opts.get('pop') and not opts.get('reapply'):
3051 if not opts.get('pop') and not opts.get('reapply'):
3047 unapplied = q.unapplied(repo)
3052 unapplied = q.unapplied(repo)
3048 guarded = [i for i in xrange(len(q.applied)) if not pushable(i)]
3053 guarded = [i for i in xrange(len(q.applied)) if not pushable(i)]
3049 if len(unapplied) != len(old_unapplied):
3054 if len(unapplied) != len(old_unapplied):
3050 ui.status(_('number of unguarded, unapplied patches has '
3055 ui.status(_('number of unguarded, unapplied patches has '
3051 'changed from %d to %d\n') %
3056 'changed from %d to %d\n') %
3052 (len(old_unapplied), len(unapplied)))
3057 (len(old_unapplied), len(unapplied)))
3053 if len(guarded) != len(old_guarded):
3058 if len(guarded) != len(old_guarded):
3054 ui.status(_('number of guarded, applied patches has changed '
3059 ui.status(_('number of guarded, applied patches has changed '
3055 'from %d to %d\n') %
3060 'from %d to %d\n') %
3056 (len(old_guarded), len(guarded)))
3061 (len(old_guarded), len(guarded)))
3057 elif opts.get('series'):
3062 elif opts.get('series'):
3058 guards = {}
3063 guards = {}
3059 noguards = 0
3064 noguards = 0
3060 for gs in q.seriesguards:
3065 for gs in q.seriesguards:
3061 if not gs:
3066 if not gs:
3062 noguards += 1
3067 noguards += 1
3063 for g in gs:
3068 for g in gs:
3064 guards.setdefault(g, 0)
3069 guards.setdefault(g, 0)
3065 guards[g] += 1
3070 guards[g] += 1
3066 if ui.verbose:
3071 if ui.verbose:
3067 guards['NONE'] = noguards
3072 guards['NONE'] = noguards
3068 guards = guards.items()
3073 guards = guards.items()
3069 guards.sort(key=lambda x: x[0][1:])
3074 guards.sort(key=lambda x: x[0][1:])
3070 if guards:
3075 if guards:
3071 ui.note(_('guards in series file:\n'))
3076 ui.note(_('guards in series file:\n'))
3072 for guard, count in guards:
3077 for guard, count in guards:
3073 ui.note('%2d ' % count)
3078 ui.note('%2d ' % count)
3074 ui.write(guard, '\n')
3079 ui.write(guard, '\n')
3075 else:
3080 else:
3076 ui.note(_('no guards in series file\n'))
3081 ui.note(_('no guards in series file\n'))
3077 else:
3082 else:
3078 if guards:
3083 if guards:
3079 ui.note(_('active guards:\n'))
3084 ui.note(_('active guards:\n'))
3080 for g in guards:
3085 for g in guards:
3081 ui.write(g, '\n')
3086 ui.write(g, '\n')
3082 else:
3087 else:
3083 ui.write(_('no active guards\n'))
3088 ui.write(_('no active guards\n'))
3084 reapply = opts.get('reapply') and q.applied and q.applied[-1].name
3089 reapply = opts.get('reapply') and q.applied and q.applied[-1].name
3085 popped = False
3090 popped = False
3086 if opts.get('pop') or opts.get('reapply'):
3091 if opts.get('pop') or opts.get('reapply'):
3087 for i in xrange(len(q.applied)):
3092 for i in xrange(len(q.applied)):
3088 if not pushable(i):
3093 if not pushable(i):
3089 ui.status(_('popping guarded patches\n'))
3094 ui.status(_('popping guarded patches\n'))
3090 popped = True
3095 popped = True
3091 if i == 0:
3096 if i == 0:
3092 q.pop(repo, all=True)
3097 q.pop(repo, all=True)
3093 else:
3098 else:
3094 q.pop(repo, q.applied[i - 1].name)
3099 q.pop(repo, q.applied[i - 1].name)
3095 break
3100 break
3096 if popped:
3101 if popped:
3097 try:
3102 try:
3098 if reapply:
3103 if reapply:
3099 ui.status(_('reapplying unguarded patches\n'))
3104 ui.status(_('reapplying unguarded patches\n'))
3100 q.push(repo, reapply)
3105 q.push(repo, reapply)
3101 finally:
3106 finally:
3102 q.savedirty()
3107 q.savedirty()
3103
3108
3104 @command("qfinish",
3109 @command("qfinish",
3105 [('a', 'applied', None, _('finish all applied changesets'))],
3110 [('a', 'applied', None, _('finish all applied changesets'))],
3106 _('hg qfinish [-a] [REV]...'))
3111 _('hg qfinish [-a] [REV]...'))
3107 def finish(ui, repo, *revrange, **opts):
3112 def finish(ui, repo, *revrange, **opts):
3108 """move applied patches into repository history
3113 """move applied patches into repository history
3109
3114
3110 Finishes the specified revisions (corresponding to applied
3115 Finishes the specified revisions (corresponding to applied
3111 patches) by moving them out of mq control into regular repository
3116 patches) by moving them out of mq control into regular repository
3112 history.
3117 history.
3113
3118
3114 Accepts a revision range or the -a/--applied option. If --applied
3119 Accepts a revision range or the -a/--applied option. If --applied
3115 is specified, all applied mq revisions are removed from mq
3120 is specified, all applied mq revisions are removed from mq
3116 control. Otherwise, the given revisions must be at the base of the
3121 control. Otherwise, the given revisions must be at the base of the
3117 stack of applied patches.
3122 stack of applied patches.
3118
3123
3119 This can be especially useful if your changes have been applied to
3124 This can be especially useful if your changes have been applied to
3120 an upstream repository, or if you are about to push your changes
3125 an upstream repository, or if you are about to push your changes
3121 to upstream.
3126 to upstream.
3122
3127
3123 Returns 0 on success.
3128 Returns 0 on success.
3124 """
3129 """
3125 if not opts.get('applied') and not revrange:
3130 if not opts.get('applied') and not revrange:
3126 raise util.Abort(_('no revisions specified'))
3131 raise util.Abort(_('no revisions specified'))
3127 elif opts.get('applied'):
3132 elif opts.get('applied'):
3128 revrange = ('qbase::qtip',) + revrange
3133 revrange = ('qbase::qtip',) + revrange
3129
3134
3130 q = repo.mq
3135 q = repo.mq
3131 if not q.applied:
3136 if not q.applied:
3132 ui.status(_('no patches applied\n'))
3137 ui.status(_('no patches applied\n'))
3133 return 0
3138 return 0
3134
3139
3135 revs = scmutil.revrange(repo, revrange)
3140 revs = scmutil.revrange(repo, revrange)
3136 if repo['.'].rev() in revs and repo[None].files():
3141 if repo['.'].rev() in revs and repo[None].files():
3137 ui.warn(_('warning: uncommitted changes in the working directory\n'))
3142 ui.warn(_('warning: uncommitted changes in the working directory\n'))
3138 # queue.finish may changes phases but leave the responsibility to lock the
3143 # queue.finish may changes phases but leave the responsibility to lock the
3139 # repo to the caller to avoid deadlock with wlock. This command code is
3144 # repo to the caller to avoid deadlock with wlock. This command code is
3140 # responsibility for this locking.
3145 # responsibility for this locking.
3141 lock = repo.lock()
3146 lock = repo.lock()
3142 try:
3147 try:
3143 q.finish(repo, revs)
3148 q.finish(repo, revs)
3144 q.savedirty()
3149 q.savedirty()
3145 finally:
3150 finally:
3146 lock.release()
3151 lock.release()
3147 return 0
3152 return 0
3148
3153
3149 @command("qqueue",
3154 @command("qqueue",
3150 [('l', 'list', False, _('list all available queues')),
3155 [('l', 'list', False, _('list all available queues')),
3151 ('', 'active', False, _('print name of active queue')),
3156 ('', 'active', False, _('print name of active queue')),
3152 ('c', 'create', False, _('create new queue')),
3157 ('c', 'create', False, _('create new queue')),
3153 ('', 'rename', False, _('rename active queue')),
3158 ('', 'rename', False, _('rename active queue')),
3154 ('', 'delete', False, _('delete reference to queue')),
3159 ('', 'delete', False, _('delete reference to queue')),
3155 ('', 'purge', False, _('delete queue, and remove patch dir')),
3160 ('', 'purge', False, _('delete queue, and remove patch dir')),
3156 ],
3161 ],
3157 _('[OPTION] [QUEUE]'))
3162 _('[OPTION] [QUEUE]'))
3158 def qqueue(ui, repo, name=None, **opts):
3163 def qqueue(ui, repo, name=None, **opts):
3159 '''manage multiple patch queues
3164 '''manage multiple patch queues
3160
3165
3161 Supports switching between different patch queues, as well as creating
3166 Supports switching between different patch queues, as well as creating
3162 new patch queues and deleting existing ones.
3167 new patch queues and deleting existing ones.
3163
3168
3164 Omitting a queue name or specifying -l/--list will show you the registered
3169 Omitting a queue name or specifying -l/--list will show you the registered
3165 queues - by default the "normal" patches queue is registered. The currently
3170 queues - by default the "normal" patches queue is registered. The currently
3166 active queue will be marked with "(active)". Specifying --active will print
3171 active queue will be marked with "(active)". Specifying --active will print
3167 only the name of the active queue.
3172 only the name of the active queue.
3168
3173
3169 To create a new queue, use -c/--create. The queue is automatically made
3174 To create a new queue, use -c/--create. The queue is automatically made
3170 active, except in the case where there are applied patches from the
3175 active, except in the case where there are applied patches from the
3171 currently active queue in the repository. Then the queue will only be
3176 currently active queue in the repository. Then the queue will only be
3172 created and switching will fail.
3177 created and switching will fail.
3173
3178
3174 To delete an existing queue, use --delete. You cannot delete the currently
3179 To delete an existing queue, use --delete. You cannot delete the currently
3175 active queue.
3180 active queue.
3176
3181
3177 Returns 0 on success.
3182 Returns 0 on success.
3178 '''
3183 '''
3179 q = repo.mq
3184 q = repo.mq
3180 _defaultqueue = 'patches'
3185 _defaultqueue = 'patches'
3181 _allqueues = 'patches.queues'
3186 _allqueues = 'patches.queues'
3182 _activequeue = 'patches.queue'
3187 _activequeue = 'patches.queue'
3183
3188
3184 def _getcurrent():
3189 def _getcurrent():
3185 cur = os.path.basename(q.path)
3190 cur = os.path.basename(q.path)
3186 if cur.startswith('patches-'):
3191 if cur.startswith('patches-'):
3187 cur = cur[8:]
3192 cur = cur[8:]
3188 return cur
3193 return cur
3189
3194
3190 def _noqueues():
3195 def _noqueues():
3191 try:
3196 try:
3192 fh = repo.opener(_allqueues, 'r')
3197 fh = repo.opener(_allqueues, 'r')
3193 fh.close()
3198 fh.close()
3194 except IOError:
3199 except IOError:
3195 return True
3200 return True
3196
3201
3197 return False
3202 return False
3198
3203
3199 def _getqueues():
3204 def _getqueues():
3200 current = _getcurrent()
3205 current = _getcurrent()
3201
3206
3202 try:
3207 try:
3203 fh = repo.opener(_allqueues, 'r')
3208 fh = repo.opener(_allqueues, 'r')
3204 queues = [queue.strip() for queue in fh if queue.strip()]
3209 queues = [queue.strip() for queue in fh if queue.strip()]
3205 fh.close()
3210 fh.close()
3206 if current not in queues:
3211 if current not in queues:
3207 queues.append(current)
3212 queues.append(current)
3208 except IOError:
3213 except IOError:
3209 queues = [_defaultqueue]
3214 queues = [_defaultqueue]
3210
3215
3211 return sorted(queues)
3216 return sorted(queues)
3212
3217
3213 def _setactive(name):
3218 def _setactive(name):
3214 if q.applied:
3219 if q.applied:
3215 raise util.Abort(_('new queue created, but cannot make active '
3220 raise util.Abort(_('new queue created, but cannot make active '
3216 'as patches are applied'))
3221 'as patches are applied'))
3217 _setactivenocheck(name)
3222 _setactivenocheck(name)
3218
3223
3219 def _setactivenocheck(name):
3224 def _setactivenocheck(name):
3220 fh = repo.opener(_activequeue, 'w')
3225 fh = repo.opener(_activequeue, 'w')
3221 if name != 'patches':
3226 if name != 'patches':
3222 fh.write(name)
3227 fh.write(name)
3223 fh.close()
3228 fh.close()
3224
3229
3225 def _addqueue(name):
3230 def _addqueue(name):
3226 fh = repo.opener(_allqueues, 'a')
3231 fh = repo.opener(_allqueues, 'a')
3227 fh.write('%s\n' % (name,))
3232 fh.write('%s\n' % (name,))
3228 fh.close()
3233 fh.close()
3229
3234
3230 def _queuedir(name):
3235 def _queuedir(name):
3231 if name == 'patches':
3236 if name == 'patches':
3232 return repo.join('patches')
3237 return repo.join('patches')
3233 else:
3238 else:
3234 return repo.join('patches-' + name)
3239 return repo.join('patches-' + name)
3235
3240
3236 def _validname(name):
3241 def _validname(name):
3237 for n in name:
3242 for n in name:
3238 if n in ':\\/.':
3243 if n in ':\\/.':
3239 return False
3244 return False
3240 return True
3245 return True
3241
3246
3242 def _delete(name):
3247 def _delete(name):
3243 if name not in existing:
3248 if name not in existing:
3244 raise util.Abort(_('cannot delete queue that does not exist'))
3249 raise util.Abort(_('cannot delete queue that does not exist'))
3245
3250
3246 current = _getcurrent()
3251 current = _getcurrent()
3247
3252
3248 if name == current:
3253 if name == current:
3249 raise util.Abort(_('cannot delete currently active queue'))
3254 raise util.Abort(_('cannot delete currently active queue'))
3250
3255
3251 fh = repo.opener('patches.queues.new', 'w')
3256 fh = repo.opener('patches.queues.new', 'w')
3252 for queue in existing:
3257 for queue in existing:
3253 if queue == name:
3258 if queue == name:
3254 continue
3259 continue
3255 fh.write('%s\n' % (queue,))
3260 fh.write('%s\n' % (queue,))
3256 fh.close()
3261 fh.close()
3257 util.rename(repo.join('patches.queues.new'), repo.join(_allqueues))
3262 util.rename(repo.join('patches.queues.new'), repo.join(_allqueues))
3258
3263
3259 if not name or opts.get('list') or opts.get('active'):
3264 if not name or opts.get('list') or opts.get('active'):
3260 current = _getcurrent()
3265 current = _getcurrent()
3261 if opts.get('active'):
3266 if opts.get('active'):
3262 ui.write('%s\n' % (current,))
3267 ui.write('%s\n' % (current,))
3263 return
3268 return
3264 for queue in _getqueues():
3269 for queue in _getqueues():
3265 ui.write('%s' % (queue,))
3270 ui.write('%s' % (queue,))
3266 if queue == current and not ui.quiet:
3271 if queue == current and not ui.quiet:
3267 ui.write(_(' (active)\n'))
3272 ui.write(_(' (active)\n'))
3268 else:
3273 else:
3269 ui.write('\n')
3274 ui.write('\n')
3270 return
3275 return
3271
3276
3272 if not _validname(name):
3277 if not _validname(name):
3273 raise util.Abort(
3278 raise util.Abort(
3274 _('invalid queue name, may not contain the characters ":\\/."'))
3279 _('invalid queue name, may not contain the characters ":\\/."'))
3275
3280
3276 existing = _getqueues()
3281 existing = _getqueues()
3277
3282
3278 if opts.get('create'):
3283 if opts.get('create'):
3279 if name in existing:
3284 if name in existing:
3280 raise util.Abort(_('queue "%s" already exists') % name)
3285 raise util.Abort(_('queue "%s" already exists') % name)
3281 if _noqueues():
3286 if _noqueues():
3282 _addqueue(_defaultqueue)
3287 _addqueue(_defaultqueue)
3283 _addqueue(name)
3288 _addqueue(name)
3284 _setactive(name)
3289 _setactive(name)
3285 elif opts.get('rename'):
3290 elif opts.get('rename'):
3286 current = _getcurrent()
3291 current = _getcurrent()
3287 if name == current:
3292 if name == current:
3288 raise util.Abort(_('can\'t rename "%s" to its current name') % name)
3293 raise util.Abort(_('can\'t rename "%s" to its current name') % name)
3289 if name in existing:
3294 if name in existing:
3290 raise util.Abort(_('queue "%s" already exists') % name)
3295 raise util.Abort(_('queue "%s" already exists') % name)
3291
3296
3292 olddir = _queuedir(current)
3297 olddir = _queuedir(current)
3293 newdir = _queuedir(name)
3298 newdir = _queuedir(name)
3294
3299
3295 if os.path.exists(newdir):
3300 if os.path.exists(newdir):
3296 raise util.Abort(_('non-queue directory "%s" already exists') %
3301 raise util.Abort(_('non-queue directory "%s" already exists') %
3297 newdir)
3302 newdir)
3298
3303
3299 fh = repo.opener('patches.queues.new', 'w')
3304 fh = repo.opener('patches.queues.new', 'w')
3300 for queue in existing:
3305 for queue in existing:
3301 if queue == current:
3306 if queue == current:
3302 fh.write('%s\n' % (name,))
3307 fh.write('%s\n' % (name,))
3303 if os.path.exists(olddir):
3308 if os.path.exists(olddir):
3304 util.rename(olddir, newdir)
3309 util.rename(olddir, newdir)
3305 else:
3310 else:
3306 fh.write('%s\n' % (queue,))
3311 fh.write('%s\n' % (queue,))
3307 fh.close()
3312 fh.close()
3308 util.rename(repo.join('patches.queues.new'), repo.join(_allqueues))
3313 util.rename(repo.join('patches.queues.new'), repo.join(_allqueues))
3309 _setactivenocheck(name)
3314 _setactivenocheck(name)
3310 elif opts.get('delete'):
3315 elif opts.get('delete'):
3311 _delete(name)
3316 _delete(name)
3312 elif opts.get('purge'):
3317 elif opts.get('purge'):
3313 if name in existing:
3318 if name in existing:
3314 _delete(name)
3319 _delete(name)
3315 qdir = _queuedir(name)
3320 qdir = _queuedir(name)
3316 if os.path.exists(qdir):
3321 if os.path.exists(qdir):
3317 shutil.rmtree(qdir)
3322 shutil.rmtree(qdir)
3318 else:
3323 else:
3319 if name not in existing:
3324 if name not in existing:
3320 raise util.Abort(_('use --create to create a new queue'))
3325 raise util.Abort(_('use --create to create a new queue'))
3321 _setactive(name)
3326 _setactive(name)
3322
3327
3323 def mqphasedefaults(repo, roots):
3328 def mqphasedefaults(repo, roots):
3324 """callback used to set mq changeset as secret when no phase data exists"""
3329 """callback used to set mq changeset as secret when no phase data exists"""
3325 if repo.mq.applied:
3330 if repo.mq.applied:
3326 if repo.ui.configbool('mq', 'secret', False):
3331 if repo.ui.configbool('mq', 'secret', False):
3327 mqphase = phases.secret
3332 mqphase = phases.secret
3328 else:
3333 else:
3329 mqphase = phases.draft
3334 mqphase = phases.draft
3330 qbase = repo[repo.mq.applied[0].node]
3335 qbase = repo[repo.mq.applied[0].node]
3331 roots[mqphase].add(qbase.node())
3336 roots[mqphase].add(qbase.node())
3332 return roots
3337 return roots
3333
3338
3334 def reposetup(ui, repo):
3339 def reposetup(ui, repo):
3335 class mqrepo(repo.__class__):
3340 class mqrepo(repo.__class__):
3336 @localrepo.unfilteredpropertycache
3341 @localrepo.unfilteredpropertycache
3337 def mq(self):
3342 def mq(self):
3338 return queue(self.ui, self.baseui, self.path)
3343 return queue(self.ui, self.baseui, self.path)
3339
3344
3340 def invalidateall(self):
3345 def invalidateall(self):
3341 super(mqrepo, self).invalidateall()
3346 super(mqrepo, self).invalidateall()
3342 if localrepo.hasunfilteredcache(self, 'mq'):
3347 if localrepo.hasunfilteredcache(self, 'mq'):
3343 # recreate mq in case queue path was changed
3348 # recreate mq in case queue path was changed
3344 delattr(self.unfiltered(), 'mq')
3349 delattr(self.unfiltered(), 'mq')
3345
3350
3346 def abortifwdirpatched(self, errmsg, force=False):
3351 def abortifwdirpatched(self, errmsg, force=False):
3347 if self.mq.applied and self.mq.checkapplied and not force:
3352 if self.mq.applied and self.mq.checkapplied and not force:
3348 parents = self.dirstate.parents()
3353 parents = self.dirstate.parents()
3349 patches = [s.node for s in self.mq.applied]
3354 patches = [s.node for s in self.mq.applied]
3350 if parents[0] in patches or parents[1] in patches:
3355 if parents[0] in patches or parents[1] in patches:
3351 raise util.Abort(errmsg)
3356 raise util.Abort(errmsg)
3352
3357
3353 def commit(self, text="", user=None, date=None, match=None,
3358 def commit(self, text="", user=None, date=None, match=None,
3354 force=False, editor=False, extra={}):
3359 force=False, editor=False, extra={}):
3355 self.abortifwdirpatched(
3360 self.abortifwdirpatched(
3356 _('cannot commit over an applied mq patch'),
3361 _('cannot commit over an applied mq patch'),
3357 force)
3362 force)
3358
3363
3359 return super(mqrepo, self).commit(text, user, date, match, force,
3364 return super(mqrepo, self).commit(text, user, date, match, force,
3360 editor, extra)
3365 editor, extra)
3361
3366
3362 def checkpush(self, pushop):
3367 def checkpush(self, pushop):
3363 if self.mq.applied and self.mq.checkapplied and not pushop.force:
3368 if self.mq.applied and self.mq.checkapplied and not pushop.force:
3364 outapplied = [e.node for e in self.mq.applied]
3369 outapplied = [e.node for e in self.mq.applied]
3365 if pushop.revs:
3370 if pushop.revs:
3366 # Assume applied patches have no non-patch descendants and
3371 # Assume applied patches have no non-patch descendants and
3367 # are not on remote already. Filtering any changeset not
3372 # are not on remote already. Filtering any changeset not
3368 # pushed.
3373 # pushed.
3369 heads = set(pushop.revs)
3374 heads = set(pushop.revs)
3370 for node in reversed(outapplied):
3375 for node in reversed(outapplied):
3371 if node in heads:
3376 if node in heads:
3372 break
3377 break
3373 else:
3378 else:
3374 outapplied.pop()
3379 outapplied.pop()
3375 # looking for pushed and shared changeset
3380 # looking for pushed and shared changeset
3376 for node in outapplied:
3381 for node in outapplied:
3377 if self[node].phase() < phases.secret:
3382 if self[node].phase() < phases.secret:
3378 raise util.Abort(_('source has mq patches applied'))
3383 raise util.Abort(_('source has mq patches applied'))
3379 # no non-secret patches pushed
3384 # no non-secret patches pushed
3380 super(mqrepo, self).checkpush(pushop)
3385 super(mqrepo, self).checkpush(pushop)
3381
3386
3382 def _findtags(self):
3387 def _findtags(self):
3383 '''augment tags from base class with patch tags'''
3388 '''augment tags from base class with patch tags'''
3384 result = super(mqrepo, self)._findtags()
3389 result = super(mqrepo, self)._findtags()
3385
3390
3386 q = self.mq
3391 q = self.mq
3387 if not q.applied:
3392 if not q.applied:
3388 return result
3393 return result
3389
3394
3390 mqtags = [(patch.node, patch.name) for patch in q.applied]
3395 mqtags = [(patch.node, patch.name) for patch in q.applied]
3391
3396
3392 try:
3397 try:
3393 # for now ignore filtering business
3398 # for now ignore filtering business
3394 self.unfiltered().changelog.rev(mqtags[-1][0])
3399 self.unfiltered().changelog.rev(mqtags[-1][0])
3395 except error.LookupError:
3400 except error.LookupError:
3396 self.ui.warn(_('mq status file refers to unknown node %s\n')
3401 self.ui.warn(_('mq status file refers to unknown node %s\n')
3397 % short(mqtags[-1][0]))
3402 % short(mqtags[-1][0]))
3398 return result
3403 return result
3399
3404
3400 # do not add fake tags for filtered revisions
3405 # do not add fake tags for filtered revisions
3401 included = self.changelog.hasnode
3406 included = self.changelog.hasnode
3402 mqtags = [mqt for mqt in mqtags if included(mqt[0])]
3407 mqtags = [mqt for mqt in mqtags if included(mqt[0])]
3403 if not mqtags:
3408 if not mqtags:
3404 return result
3409 return result
3405
3410
3406 mqtags.append((mqtags[-1][0], 'qtip'))
3411 mqtags.append((mqtags[-1][0], 'qtip'))
3407 mqtags.append((mqtags[0][0], 'qbase'))
3412 mqtags.append((mqtags[0][0], 'qbase'))
3408 mqtags.append((self.changelog.parents(mqtags[0][0])[0], 'qparent'))
3413 mqtags.append((self.changelog.parents(mqtags[0][0])[0], 'qparent'))
3409 tags = result[0]
3414 tags = result[0]
3410 for patch in mqtags:
3415 for patch in mqtags:
3411 if patch[1] in tags:
3416 if patch[1] in tags:
3412 self.ui.warn(_('tag %s overrides mq patch of the same '
3417 self.ui.warn(_('tag %s overrides mq patch of the same '
3413 'name\n') % patch[1])
3418 'name\n') % patch[1])
3414 else:
3419 else:
3415 tags[patch[1]] = patch[0]
3420 tags[patch[1]] = patch[0]
3416
3421
3417 return result
3422 return result
3418
3423
3419 if repo.local():
3424 if repo.local():
3420 repo.__class__ = mqrepo
3425 repo.__class__ = mqrepo
3421
3426
3422 repo._phasedefaults.append(mqphasedefaults)
3427 repo._phasedefaults.append(mqphasedefaults)
3423
3428
3424 def mqimport(orig, ui, repo, *args, **kwargs):
3429 def mqimport(orig, ui, repo, *args, **kwargs):
3425 if (util.safehasattr(repo, 'abortifwdirpatched')
3430 if (util.safehasattr(repo, 'abortifwdirpatched')
3426 and not kwargs.get('no_commit', False)):
3431 and not kwargs.get('no_commit', False)):
3427 repo.abortifwdirpatched(_('cannot import over an applied patch'),
3432 repo.abortifwdirpatched(_('cannot import over an applied patch'),
3428 kwargs.get('force'))
3433 kwargs.get('force'))
3429 return orig(ui, repo, *args, **kwargs)
3434 return orig(ui, repo, *args, **kwargs)
3430
3435
3431 def mqinit(orig, ui, *args, **kwargs):
3436 def mqinit(orig, ui, *args, **kwargs):
3432 mq = kwargs.pop('mq', None)
3437 mq = kwargs.pop('mq', None)
3433
3438
3434 if not mq:
3439 if not mq:
3435 return orig(ui, *args, **kwargs)
3440 return orig(ui, *args, **kwargs)
3436
3441
3437 if args:
3442 if args:
3438 repopath = args[0]
3443 repopath = args[0]
3439 if not hg.islocal(repopath):
3444 if not hg.islocal(repopath):
3440 raise util.Abort(_('only a local queue repository '
3445 raise util.Abort(_('only a local queue repository '
3441 'may be initialized'))
3446 'may be initialized'))
3442 else:
3447 else:
3443 repopath = cmdutil.findrepo(os.getcwd())
3448 repopath = cmdutil.findrepo(os.getcwd())
3444 if not repopath:
3449 if not repopath:
3445 raise util.Abort(_('there is no Mercurial repository here '
3450 raise util.Abort(_('there is no Mercurial repository here '
3446 '(.hg not found)'))
3451 '(.hg not found)'))
3447 repo = hg.repository(ui, repopath)
3452 repo = hg.repository(ui, repopath)
3448 return qinit(ui, repo, True)
3453 return qinit(ui, repo, True)
3449
3454
3450 def mqcommand(orig, ui, repo, *args, **kwargs):
3455 def mqcommand(orig, ui, repo, *args, **kwargs):
3451 """Add --mq option to operate on patch repository instead of main"""
3456 """Add --mq option to operate on patch repository instead of main"""
3452
3457
3453 # some commands do not like getting unknown options
3458 # some commands do not like getting unknown options
3454 mq = kwargs.pop('mq', None)
3459 mq = kwargs.pop('mq', None)
3455
3460
3456 if not mq:
3461 if not mq:
3457 return orig(ui, repo, *args, **kwargs)
3462 return orig(ui, repo, *args, **kwargs)
3458
3463
3459 q = repo.mq
3464 q = repo.mq
3460 r = q.qrepo()
3465 r = q.qrepo()
3461 if not r:
3466 if not r:
3462 raise util.Abort(_('no queue repository'))
3467 raise util.Abort(_('no queue repository'))
3463 return orig(r.ui, r, *args, **kwargs)
3468 return orig(r.ui, r, *args, **kwargs)
3464
3469
3465 def summaryhook(ui, repo):
3470 def summaryhook(ui, repo):
3466 q = repo.mq
3471 q = repo.mq
3467 m = []
3472 m = []
3468 a, u = len(q.applied), len(q.unapplied(repo))
3473 a, u = len(q.applied), len(q.unapplied(repo))
3469 if a:
3474 if a:
3470 m.append(ui.label(_("%d applied"), 'qseries.applied') % a)
3475 m.append(ui.label(_("%d applied"), 'qseries.applied') % a)
3471 if u:
3476 if u:
3472 m.append(ui.label(_("%d unapplied"), 'qseries.unapplied') % u)
3477 m.append(ui.label(_("%d unapplied"), 'qseries.unapplied') % u)
3473 if m:
3478 if m:
3474 # i18n: column positioning for "hg summary"
3479 # i18n: column positioning for "hg summary"
3475 ui.write(_("mq: %s\n") % ', '.join(m))
3480 ui.write(_("mq: %s\n") % ', '.join(m))
3476 else:
3481 else:
3477 # i18n: column positioning for "hg summary"
3482 # i18n: column positioning for "hg summary"
3478 ui.note(_("mq: (empty queue)\n"))
3483 ui.note(_("mq: (empty queue)\n"))
3479
3484
3480 def revsetmq(repo, subset, x):
3485 def revsetmq(repo, subset, x):
3481 """``mq()``
3486 """``mq()``
3482 Changesets managed by MQ.
3487 Changesets managed by MQ.
3483 """
3488 """
3484 revset.getargs(x, 0, 0, _("mq takes no arguments"))
3489 revset.getargs(x, 0, 0, _("mq takes no arguments"))
3485 applied = set([repo[r.node].rev() for r in repo.mq.applied])
3490 applied = set([repo[r.node].rev() for r in repo.mq.applied])
3486 return revset.baseset([r for r in subset if r in applied])
3491 return revset.baseset([r for r in subset if r in applied])
3487
3492
3488 # tell hggettext to extract docstrings from these functions:
3493 # tell hggettext to extract docstrings from these functions:
3489 i18nfunctions = [revsetmq]
3494 i18nfunctions = [revsetmq]
3490
3495
3491 def extsetup(ui):
3496 def extsetup(ui):
3492 # Ensure mq wrappers are called first, regardless of extension load order by
3497 # Ensure mq wrappers are called first, regardless of extension load order by
3493 # NOT wrapping in uisetup() and instead deferring to init stage two here.
3498 # NOT wrapping in uisetup() and instead deferring to init stage two here.
3494 mqopt = [('', 'mq', None, _("operate on patch repository"))]
3499 mqopt = [('', 'mq', None, _("operate on patch repository"))]
3495
3500
3496 extensions.wrapcommand(commands.table, 'import', mqimport)
3501 extensions.wrapcommand(commands.table, 'import', mqimport)
3497 cmdutil.summaryhooks.add('mq', summaryhook)
3502 cmdutil.summaryhooks.add('mq', summaryhook)
3498
3503
3499 entry = extensions.wrapcommand(commands.table, 'init', mqinit)
3504 entry = extensions.wrapcommand(commands.table, 'init', mqinit)
3500 entry[1].extend(mqopt)
3505 entry[1].extend(mqopt)
3501
3506
3502 nowrap = set(commands.norepo.split(" "))
3507 nowrap = set(commands.norepo.split(" "))
3503
3508
3504 def dotable(cmdtable):
3509 def dotable(cmdtable):
3505 for cmd in cmdtable.keys():
3510 for cmd in cmdtable.keys():
3506 cmd = cmdutil.parsealiases(cmd)[0]
3511 cmd = cmdutil.parsealiases(cmd)[0]
3507 if cmd in nowrap:
3512 if cmd in nowrap:
3508 continue
3513 continue
3509 entry = extensions.wrapcommand(cmdtable, cmd, mqcommand)
3514 entry = extensions.wrapcommand(cmdtable, cmd, mqcommand)
3510 entry[1].extend(mqopt)
3515 entry[1].extend(mqopt)
3511
3516
3512 dotable(commands.table)
3517 dotable(commands.table)
3513
3518
3514 for extname, extmodule in extensions.extensions():
3519 for extname, extmodule in extensions.extensions():
3515 if extmodule.__file__ != __file__:
3520 if extmodule.__file__ != __file__:
3516 dotable(getattr(extmodule, 'cmdtable', {}))
3521 dotable(getattr(extmodule, 'cmdtable', {}))
3517
3522
3518 revset.symbols['mq'] = revsetmq
3523 revset.symbols['mq'] = revsetmq
3519
3524
3520 colortable = {'qguard.negative': 'red',
3525 colortable = {'qguard.negative': 'red',
3521 'qguard.positive': 'yellow',
3526 'qguard.positive': 'yellow',
3522 'qguard.unguarded': 'green',
3527 'qguard.unguarded': 'green',
3523 'qseries.applied': 'blue bold underline',
3528 'qseries.applied': 'blue bold underline',
3524 'qseries.guarded': 'black bold',
3529 'qseries.guarded': 'black bold',
3525 'qseries.missing': 'red bold',
3530 'qseries.missing': 'red bold',
3526 'qseries.unapplied': 'black bold'}
3531 'qseries.unapplied': 'black bold'}
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