##// END OF EJS Templates
merge with stable
Matt Mackall -
r16576:eab32ab5 merge default
parent child Browse files
Show More
@@ -1,55 +1,56 b''
1 1 35fb62a3a673d5322f6274a44ba6456e5e4b3b37 0 iD8DBQBEYmO2ywK+sNU5EO8RAnaYAKCO7x15xUn5mnhqWNXqk/ehlhRt2QCfRDfY0LrUq2q4oK/KypuJYPHgq1A=
2 2 2be3001847cb18a23c403439d9e7d0ace30804e9 0 iD8DBQBExUbjywK+sNU5EO8RAhzxAKCtyHAQUzcTSZTqlfJ0by6vhREwWQCghaQFHfkfN0l9/40EowNhuMOKnJk=
3 3 36a957364b1b89c150f2d0e60a99befe0ee08bd3 0 iD8DBQBFfL2QywK+sNU5EO8RAjYFAKCoGlaWRTeMsjdmxAjUYx6diZxOBwCfY6IpBYsKvPTwB3oktnPt5Rmrlys=
4 4 27230c29bfec36d5540fbe1c976810aefecfd1d2 0 iD8DBQBFheweywK+sNU5EO8RAt7VAKCrqJQWT2/uo2RWf0ZI4bLp6v82jACgjrMdsaTbxRsypcmEsdPhlG6/8F4=
5 5 fb4b6d5fe100b0886f8bc3d6731ec0e5ed5c4694 0 iD8DBQBGgHicywK+sNU5EO8RAgNxAJ0VG8ixAaeudx4sZbhngI1syu49HQCeNUJQfWBgA8bkJ2pvsFpNxwYaX3I=
6 6 23889160905a1b09fffe1c07378e9fc1827606eb 0 iD8DBQBHGTzoywK+sNU5EO8RAr/UAJ0Y8s4jQtzgS+G9vM8z6CWBThZ8fwCcCT5XDj2XwxKkz/0s6UELwjsO3LU=
7 7 bae2e9c838e90a393bae3973a7850280413e091a 0 iD8DBQBH6DO5ywK+sNU5EO8RAsfrAJ0e4r9c9GF/MJsM7Xjd3NesLRC3+ACffj6+6HXdZf8cswAoFPO+DY00oD0=
8 8 d5cbbe2c49cee22a9fbeb9ea41daa0ac4e26b846 0 iD8DBQBINdwsywK+sNU5EO8RAjIUAKCPmlFJSpsPAAUKF+iNHAwVnwmzeQCdEXrL27CWclXuUKdbQC8De7LICtE=
9 9 d2375bbee6d47e62ba8e415c86e83a465dc4dce9 0 iD8DBQBIo1wpywK+sNU5EO8RAmRNAJ94x3OFt6blbqu/yBoypm/AJ44fuACfUaldXcV5z9tht97hSp22DVTEPGc=
10 10 2a67430f92f15ea5159c26b09ec4839a0c549a26 0 iEYEABECAAYFAkk1hykACgkQywK+sNU5EO85QACeNJNUanjc2tl4wUoPHNuv+lSj0ZMAoIm93wSTc/feyYnO2YCaQ1iyd9Nu
11 11 3773e510d433969e277b1863c317b674cbee2065 0 iEYEABECAAYFAklNbbAACgkQywK+sNU5EO8o+gCfeb2/lfIJZMvyDA1m+G1CsBAxfFsAoIa6iAMG8SBY7hW1Q85Yf/LXEvaE
12 12 11a4eb81fb4f4742451591489e2797dc47903277 0 iEYEABECAAYFAklcAnsACgkQywK+sNU5EO+uXwCbBVHNNsLy1g7BlAyQJwadYVyHOXoAoKvtAVO71+bv7EbVoukwTzT+P4Sx
13 13 11efa41037e280d08cfb07c09ad485df30fb0ea8 0 iEYEABECAAYFAkmvJRQACgkQywK+sNU5EO9XZwCeLMgDgPSMWMm6vgjL4lDs2pEc5+0AnRxfiFbpbBfuEFTqKz9nbzeyoBlx
14 14 02981000012e3adf40c4849bd7b3d5618f9ce82d 0 iEYEABECAAYFAknEH3wACgkQywK+sNU5EO+uXwCeI+LbLMmhjU1lKSfU3UWJHjjUC7oAoIZLvYDGOL/tNZFUuatc3RnZ2eje
15 15 196d40e7c885fa6e95f89134809b3ec7bdbca34b 0 iEYEABECAAYFAkpL2X4ACgkQywK+sNU5EO9FOwCfXJycjyKJXsvQqKkHrglwOQhEKS4An36GfKzptfN8b1qNc3+ya/5c2WOM
16 16 3ef6c14a1e8e83a31226f5881b7fe6095bbfa6f6 0 iEYEABECAAYFAkpopLIACgkQywK+sNU5EO8QSgCfZ0ztsd071rOa2lhmp9Fyue/WoI0AoLTei80/xrhRlB8L/rZEf2KBl8dA
17 17 31ec469f9b556f11819937cf68ee53f2be927ebf 0 iEYEABECAAYFAksBuxAACgkQywK+sNU5EO+mBwCfagB+A0txzWZ6dRpug3LEoK7Z1QsAoKpbk8vsLjv6/oRDicSk/qBu33+m
18 18 439d7ea6fe3aa4ab9ec274a68846779153789de9 0 iEYEABECAAYFAksVw0kACgkQywK+sNU5EO/oZwCfdfBEkgp38xq6wN2F4nj+SzofrJIAnjmxt04vaJSeOOeHylHvk6lzuQsw
19 19 296a0b14a68621f6990c54fdba0083f6f20935bf 0 iEYEABECAAYFAks+jCoACgkQywK+sNU5EO9J8wCeMUGF9E/gS2UBsqIz56WS4HMPRPUAoI5J95mwEIK8Clrl7qFRidNI6APq
20 20 4aa619c4c2c09907034d9824ebb1dd0e878206eb 0 iEYEABECAAYFAktm9IsACgkQywK+sNU5EO9XGgCgk4HclRQhexEtooPE5GcUCdB6M8EAn2ptOhMVbIoO+JncA+tNACPFXh0O
21 21 ff2704a8ded37fbebd8b6eb5ec733731d725da8a 0 iEYEABECAAYFAkuRoSQACgkQywK+sNU5EO//3QCeJDc5r2uFyFCtAlpSA27DEE5rrxAAn2FSwTy9fhrB3QAdDQlwkEZcQzDh
22 22 2b01dab594167bc0dd33331dbaa6dca3dca1b3aa 0 iEYEABECAAYFAku1IwIACgkQywK+sNU5EO9MjgCdHLVwkTZlNHxhcznZKBL1rjN+J7cAoLLWi9LTL6f/TgBaPSKOy1ublbaW
23 23 39f725929f0c48c5fb3b90c071fc3066012456ca 0 iEYEABECAAYFAkvclvsACgkQywK+sNU5EO9FSwCeL9i5x8ALW/LE5+lCX6MFEAe4MhwAn1ev5o6SX6GrNdDfKweiemfO2VBk
24 24 fdcf80f26604f233dc4d8f0a5ef9d7470e317e8a 0 iEYEABECAAYFAkvsKTkACgkQywK+sNU5EO9qEACgiSiRGvTG2vXGJ65tUSOIYihTuFAAnRzRIqEVSw8M8/RGeUXRps0IzaCO
25 25 24fe2629c6fd0c74c90bd066e77387c2b02e8437 0 iEYEABECAAYFAkwFLRsACgkQywK+sNU5EO+pJACgp13tPI+pbwKZV+LeMjcQ4H6tCZYAoJebzhd6a8yYx6qiwpJxA9BXZNXy
26 26 f786fc4b8764cd2a5526d259cf2f94d8a66924d9 0 iEYEABECAAYFAkwsyxcACgkQywK+sNU5EO+crACfUpNAF57PmClkSri9nJcBjb2goN4AniPCNaKvnki7TnUsi1u2oxltpKKL
27 27 bf1774d95bde614af3956d92b20e2a0c68c5fec7 0 iEYEABECAAYFAkxVwccACgkQywK+sNU5EO+oFQCeJzwZ+we1fIIyBGCddHceOUAN++cAnjvT6A8ZWW0zV21NXIFF1qQmjxJd
28 28 c00f03a4982e467fb6b6bd45908767db6df4771d 0 iEYEABECAAYFAkxXDqsACgkQywK+sNU5EO/GJACfT9Rz4hZOxPQEs91JwtmfjevO84gAmwSmtfo5mmWSm8gtTUebCcdTv0Kf
29 29 ff5cec76b1c5b6be9c3bb923aae8c3c6d079d6b9 0 iD8DBQBMdo+qywK+sNU5EO8RAqQpAJ975BL2CCAiWMz9SXthNQ9xG181IwCgp4O+KViHPkufZVFn2aTKMNvcr1A=
30 30 93d8bff78c96fe7e33237b257558ee97290048a4 0 iD8DBQBMpfvdywK+sNU5EO8RAsxVAJ0UaL1XB51C76JUBhafc9GBefuMxwCdEWkTOzwvE0SarJBe9i008jhbqW4=
31 31 333421b9e0f96c7bc788e5667c146a58a9440a55 0 iD8DBQBMz0HOywK+sNU5EO8RAlsEAJ0USh6yOG7OrWkADGunVt9QimBQnwCbBqeMnKgSbwEw8jZwE3Iz1mdrYlo=
32 32 4438875ec01bd0fc32be92b0872eb6daeed4d44f 0 iD8DBQBM4WYUywK+sNU5EO8RAhCVAJ0dJswachwFAHALmk1x0RJehxzqPQCbBNskP9n/X689jB+btNTZTyKU/fw=
33 33 6aff4f144ad356311318b0011df0bb21f2c97429 0 iD8DBQBM9uxXywK+sNU5EO8RAv+4AKCDj4qKP16GdPaq1tP6BUwpM/M1OACfRyzLPp/qiiN8xJTWoWYSe/XjJug=
34 34 e3bf16703e2601de99e563cdb3a5d50b64e6d320 0 iD8DBQBNH8WqywK+sNU5EO8RAiQTAJ9sBO+TeiGro4si77VVaQaA6jcRUgCfSA28dBbjj0oFoQwvPoZjANiZBH8=
35 35 a6c855c32ea081da3c3b8ff628f1847ff271482f 0 iD8DBQBNSJJ+ywK+sNU5EO8RAoJaAKCweDEF70fu+r1Zn7pYDXdlk5RuSgCeO9gK/eit8Lin/1n3pO7aYguFLok=
36 36 2b2155623ee2559caf288fd333f30475966c4525 0 iD8DBQBNSJeBywK+sNU5EO8RAm1KAJ4hW9Cm9nHaaGJguchBaPLlAr+O3wCgqgmMok8bdAS06N6PL60PSTM//Gg=
37 37 2616325766e3504c8ae7c84bd15ee610901fe91d 0 iD8DBQBNbWy9ywK+sNU5EO8RAlWCAJ4mW8HbzjJj9GpK98muX7k+7EvEHwCfaTLbC/DH3QEsZBhEP+M8tzL6RU4=
38 38 aa1f3be38ab127280761889d2dca906ca465b5f4 0 iD8DBQBNeQq7ywK+sNU5EO8RAlEOAJ4tlEDdetE9lKfjGgjbkcR8PrC3egCfXCfF3qNVvU/2YYjpgvRwevjvDy0=
39 39 b032bec2c0a651ca0ddecb65714bfe6770f67d70 0 iD8DBQBNlg5kywK+sNU5EO8RAnGEAJ9gmEx6MfaR4XcG2m/93vwtfyzs3gCgltzx8/YdHPwqDwRX/WbpYgi33is=
40 40 3cb1e95676ad089596bd81d0937cad37d6e3b7fb 0 iD8DBQBNvTy4ywK+sNU5EO8RAmp8AJ9QnxK4jTJ7G722MyeBxf0UXEdGwACgtlM7BKtNQfbEH/fOW5y+45W88VI=
41 41 733af5d9f6b22387913e1d11350fb8cb7c1487dd 0 iD8DBQBN5q/8ywK+sNU5EO8RArRGAKCNGT94GKIYtSuwZ57z1sQbcw6uLACfffpbMV4NAPMl8womAwg+7ZPKnIU=
42 42 de9eb6b1da4fc522b1cab16d86ca166204c24f25 0 iD8DBQBODhfhywK+sNU5EO8RAr2+AJ4ugbAj8ae8/K0bYZzx3sascIAg1QCeK3b+zbbVVqd3b7CDpwFnaX8kTd4=
43 43 4a43e23b8c55b4566b8200bf69fe2158485a2634 0 iD8DBQBONzIMywK+sNU5EO8RAj5SAJ0aPS3+JHnyI6bHB2Fl0LImbDmagwCdGbDLp1S7TFobxXudOH49bX45Iik=
44 44 d629f1e89021103f1753addcef6b310e4435b184 0 iD8DBQBOWAsBywK+sNU5EO8RAht4AJwJl9oNFopuGkj5m8aKuf7bqPkoAQCeNrEm7UhFsZKYT5iUOjnMV7s2LaM=
45 45 351a9292e430e35766c552066ed3e87c557b803b 0 iD8DBQBOh3zUywK+sNU5EO8RApFMAKCD3Y/u3avDFndznwqfG5UeTHMlvACfUivPIVQZyDZnhZMq0UhC6zhCEQg=
46 46 384082750f2c51dc917d85a7145748330fa6ef4d 0 iD8DBQBOmd+OywK+sNU5EO8RAgDgAJ9V/X+G7VLwhTpHrZNiOHabzSyzYQCdE2kKfIevJUYB9QLAWCWP6DPwrwI=
47 47 41453d55b481ddfcc1dacb445179649e24ca861d 0 iD8DBQBOsFhpywK+sNU5EO8RAqM6AKCyfxUae3/zLuiLdQz+JR78690eMACfQ6JTBQib4AbE+rUDdkeFYg9K/+4=
48 48 195dbd1cef0c2f9f8bcf4ea303238105f716bda3 0 iD8DBQBO1/fWywK+sNU5EO8RAmoPAKCR5lpv1D6JLURHD8KVLSV4GRVEBgCgnd0Sy78ligNfqAMafmACRDvj7vo=
49 49 6344043924497cd06d781d9014c66802285072e4 0 iD8DBQBPALgmywK+sNU5EO8RAlfhAJ9nYOdWnhfVDHYtDTJAyJtXBAQS9wCgnefoSQt7QABkbGxM+Q85UYEBuD0=
50 50 db33555eafeaf9df1e18950e29439eaa706d399b 0 iD8DBQBPGdzxywK+sNU5EO8RAppkAJ9jOXhUVE/97CPgiMA0pMGiIYnesQCfengAszcBiSiKGugiI8Okc9ghU+Y=
51 51 2aa5b51f310fb3befd26bed99c02267f5c12c734 0 iD8DBQBPKZ9bywK+sNU5EO8RAt1TAJ45r1eJ0YqSkInzrrayg4TVCh0SnQCgm0GA/Ua74jnnDwVQ60lAwROuz1Q=
52 52 53e2cd303ecf8ca7c7eeebd785c34e5ed6b0f4a4 0 iD8DBQBPT/fvywK+sNU5EO8RAnfYAKCn7d0vwqIb100YfWm1F7nFD5B+FACeM02YHpQLSNsztrBCObtqcnfod7Q=
53 53 b9bd95e61b49c221c4cca24e6da7c946fc02f992 0 iD8DBQBPeLsIywK+sNU5EO8RAvpNAKCtKe2gitz8dYn52IRF0hFOPCR7AQCfRJL/RWCFweu2T1vH/mUOCf8SXXc=
54 54 d9e2f09d5488c395ae9ddbb320ceacd24757e055 0 iD8DBQBPju/dywK+sNU5EO8RArBYAJ9xtifdbk+hCOJO8OZa4JfHX8OYZQCeKPMBaBWiT8N/WHoOm1XU0q+iono=
55 55 00182b3d087909e3c3ae44761efecdde8f319ef3 0 iD8DBQBPoFhIywK+sNU5EO8RAhzhAKCBj1n2jxPTkZNJJ5pSp3soa+XHIgCgsZZpAQxOpXwCp0eCdNGe0+pmxmg=
56 5983de86462c5a9f42a3ad0f5e90ce5b1d221d25 0 iD8DBQBPovNWywK+sNU5EO8RAhgiAJ980T91FdPTRMmVONDhpkMsZwVIMACgg3bKvoWSeuCW28llUhAJtUjrMv0=
@@ -1,67 +1,68 b''
1 1 d40cc5aacc31ed673d9b5b24f98bee78c283062c 0.4f
2 2 1c590d34bf61e2ea12c71738e5a746cd74586157 0.4e
3 3 7eca4cfa8aad5fce9a04f7d8acadcd0452e2f34e 0.4d
4 4 b4d0c3786ad3e47beacf8412157326a32b6d25a4 0.4c
5 5 f40273b0ad7b3a6d3012fd37736d0611f41ecf54 0.5
6 6 0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 0.5b
7 7 12e0fdbc57a0be78f0e817fd1d170a3615cd35da 0.6
8 8 4ccf3de52989b14c3d84e1097f59e39a992e00bd 0.6b
9 9 eac9c8efcd9bd8244e72fb6821f769f450457a32 0.6c
10 10 979c049974485125e1f9357f6bbe9c1b548a64c3 0.7
11 11 3a56574f329a368d645853e0f9e09472aee62349 0.8
12 12 6a03cff2b0f5d30281e6addefe96b993582f2eac 0.8.1
13 13 35fb62a3a673d5322f6274a44ba6456e5e4b3b37 0.9
14 14 2be3001847cb18a23c403439d9e7d0ace30804e9 0.9.1
15 15 36a957364b1b89c150f2d0e60a99befe0ee08bd3 0.9.2
16 16 27230c29bfec36d5540fbe1c976810aefecfd1d2 0.9.3
17 17 fb4b6d5fe100b0886f8bc3d6731ec0e5ed5c4694 0.9.4
18 18 23889160905a1b09fffe1c07378e9fc1827606eb 0.9.5
19 19 bae2e9c838e90a393bae3973a7850280413e091a 1.0
20 20 d5cbbe2c49cee22a9fbeb9ea41daa0ac4e26b846 1.0.1
21 21 d2375bbee6d47e62ba8e415c86e83a465dc4dce9 1.0.2
22 22 2a67430f92f15ea5159c26b09ec4839a0c549a26 1.1
23 23 3773e510d433969e277b1863c317b674cbee2065 1.1.1
24 24 11a4eb81fb4f4742451591489e2797dc47903277 1.1.2
25 25 11efa41037e280d08cfb07c09ad485df30fb0ea8 1.2
26 26 02981000012e3adf40c4849bd7b3d5618f9ce82d 1.2.1
27 27 196d40e7c885fa6e95f89134809b3ec7bdbca34b 1.3
28 28 3ef6c14a1e8e83a31226f5881b7fe6095bbfa6f6 1.3.1
29 29 31ec469f9b556f11819937cf68ee53f2be927ebf 1.4
30 30 439d7ea6fe3aa4ab9ec274a68846779153789de9 1.4.1
31 31 296a0b14a68621f6990c54fdba0083f6f20935bf 1.4.2
32 32 4aa619c4c2c09907034d9824ebb1dd0e878206eb 1.4.3
33 33 ff2704a8ded37fbebd8b6eb5ec733731d725da8a 1.5
34 34 2b01dab594167bc0dd33331dbaa6dca3dca1b3aa 1.5.1
35 35 39f725929f0c48c5fb3b90c071fc3066012456ca 1.5.2
36 36 fdcf80f26604f233dc4d8f0a5ef9d7470e317e8a 1.5.3
37 37 24fe2629c6fd0c74c90bd066e77387c2b02e8437 1.5.4
38 38 f786fc4b8764cd2a5526d259cf2f94d8a66924d9 1.6
39 39 bf1774d95bde614af3956d92b20e2a0c68c5fec7 1.6.1
40 40 c00f03a4982e467fb6b6bd45908767db6df4771d 1.6.2
41 41 ff5cec76b1c5b6be9c3bb923aae8c3c6d079d6b9 1.6.3
42 42 93d8bff78c96fe7e33237b257558ee97290048a4 1.6.4
43 43 333421b9e0f96c7bc788e5667c146a58a9440a55 1.7
44 44 4438875ec01bd0fc32be92b0872eb6daeed4d44f 1.7.1
45 45 6aff4f144ad356311318b0011df0bb21f2c97429 1.7.2
46 46 e3bf16703e2601de99e563cdb3a5d50b64e6d320 1.7.3
47 47 a6c855c32ea081da3c3b8ff628f1847ff271482f 1.7.4
48 48 2b2155623ee2559caf288fd333f30475966c4525 1.7.5
49 49 2616325766e3504c8ae7c84bd15ee610901fe91d 1.8
50 50 aa1f3be38ab127280761889d2dca906ca465b5f4 1.8.1
51 51 b032bec2c0a651ca0ddecb65714bfe6770f67d70 1.8.2
52 52 3cb1e95676ad089596bd81d0937cad37d6e3b7fb 1.8.3
53 53 733af5d9f6b22387913e1d11350fb8cb7c1487dd 1.8.4
54 54 de9eb6b1da4fc522b1cab16d86ca166204c24f25 1.9
55 55 4a43e23b8c55b4566b8200bf69fe2158485a2634 1.9.1
56 56 d629f1e89021103f1753addcef6b310e4435b184 1.9.2
57 57 351a9292e430e35766c552066ed3e87c557b803b 1.9.3
58 58 384082750f2c51dc917d85a7145748330fa6ef4d 2.0-rc
59 59 41453d55b481ddfcc1dacb445179649e24ca861d 2.0
60 60 195dbd1cef0c2f9f8bcf4ea303238105f716bda3 2.0.1
61 61 6344043924497cd06d781d9014c66802285072e4 2.0.2
62 62 db33555eafeaf9df1e18950e29439eaa706d399b 2.1-rc
63 63 2aa5b51f310fb3befd26bed99c02267f5c12c734 2.1
64 64 53e2cd303ecf8ca7c7eeebd785c34e5ed6b0f4a4 2.1.1
65 65 b9bd95e61b49c221c4cca24e6da7c946fc02f992 2.1.2
66 66 d9e2f09d5488c395ae9ddbb320ceacd24757e055 2.2-rc
67 67 00182b3d087909e3c3ae44761efecdde8f319ef3 2.2
68 5983de86462c5a9f42a3ad0f5e90ce5b1d221d25 2.2.1
@@ -1,466 +1,462 b''
1 1 # Copyright 2009-2010 Gregory P. Ward
2 2 # Copyright 2009-2010 Intelerad Medical Systems Incorporated
3 3 # Copyright 2010-2011 Fog Creek Software
4 4 # Copyright 2010-2011 Unity Technologies
5 5 #
6 6 # This software may be used and distributed according to the terms of the
7 7 # GNU General Public License version 2 or any later version.
8 8
9 9 '''setup for largefiles repositories: reposetup'''
10 10 import copy
11 11 import types
12 12 import os
13 13
14 14 from mercurial import context, error, manifest, match as match_, util
15 15 from mercurial import node as node_
16 16 from mercurial.i18n import _
17 17
18 18 import lfcommands
19 19 import proto
20 20 import lfutil
21 21
22 22 def reposetup(ui, repo):
23 23 # wire repositories should be given new wireproto functions but not the
24 24 # other largefiles modifications
25 25 if not repo.local():
26 26 return proto.wirereposetup(ui, repo)
27 27
28 28 for name in ('status', 'commitctx', 'commit', 'push'):
29 29 method = getattr(repo, name)
30 30 if (isinstance(method, types.FunctionType) and
31 31 method.func_name == 'wrap'):
32 32 ui.warn(_('largefiles: repo method %r appears to have already been'
33 33 ' wrapped by another extension: '
34 34 'largefiles may behave incorrectly\n')
35 35 % name)
36 36
37 37 class lfilesrepo(repo.__class__):
38 38 lfstatus = False
39 39 def status_nolfiles(self, *args, **kwargs):
40 40 return super(lfilesrepo, self).status(*args, **kwargs)
41 41
42 42 # When lfstatus is set, return a context that gives the names
43 43 # of largefiles instead of their corresponding standins and
44 44 # identifies the largefiles as always binary, regardless of
45 45 # their actual contents.
46 46 def __getitem__(self, changeid):
47 47 ctx = super(lfilesrepo, self).__getitem__(changeid)
48 48 if self.lfstatus:
49 49 class lfilesmanifestdict(manifest.manifestdict):
50 50 def __contains__(self, filename):
51 51 if super(lfilesmanifestdict,
52 52 self).__contains__(filename):
53 53 return True
54 54 return super(lfilesmanifestdict,
55 55 self).__contains__(lfutil.standin(filename))
56 56 class lfilesctx(ctx.__class__):
57 57 def files(self):
58 58 filenames = super(lfilesctx, self).files()
59 59 return [lfutil.splitstandin(f) or f for f in filenames]
60 60 def manifest(self):
61 61 man1 = super(lfilesctx, self).manifest()
62 62 man1.__class__ = lfilesmanifestdict
63 63 return man1
64 64 def filectx(self, path, fileid=None, filelog=None):
65 65 try:
66 66 if filelog is not None:
67 67 result = super(lfilesctx, self).filectx(
68 68 path, fileid, filelog)
69 69 else:
70 70 result = super(lfilesctx, self).filectx(
71 71 path, fileid)
72 72 except error.LookupError:
73 73 # Adding a null character will cause Mercurial to
74 74 # identify this as a binary file.
75 75 if filelog is not None:
76 76 result = super(lfilesctx, self).filectx(
77 77 lfutil.standin(path), fileid, filelog)
78 78 else:
79 79 result = super(lfilesctx, self).filectx(
80 80 lfutil.standin(path), fileid)
81 81 olddata = result.data
82 82 result.data = lambda: olddata() + '\0'
83 83 return result
84 84 ctx.__class__ = lfilesctx
85 85 return ctx
86 86
87 87 # Figure out the status of big files and insert them into the
88 88 # appropriate list in the result. Also removes standin files
89 89 # from the listing. Revert to the original status if
90 90 # self.lfstatus is False.
91 91 def status(self, node1='.', node2=None, match=None, ignored=False,
92 92 clean=False, unknown=False, listsubrepos=False):
93 93 listignored, listclean, listunknown = ignored, clean, unknown
94 94 if not self.lfstatus:
95 95 return super(lfilesrepo, self).status(node1, node2, match,
96 96 listignored, listclean, listunknown, listsubrepos)
97 97 else:
98 98 # some calls in this function rely on the old version of status
99 99 self.lfstatus = False
100 100 if isinstance(node1, context.changectx):
101 101 ctx1 = node1
102 102 else:
103 103 ctx1 = repo[node1]
104 104 if isinstance(node2, context.changectx):
105 105 ctx2 = node2
106 106 else:
107 107 ctx2 = repo[node2]
108 108 working = ctx2.rev() is None
109 109 parentworking = working and ctx1 == self['.']
110 110
111 111 def inctx(file, ctx):
112 112 try:
113 113 if ctx.rev() is None:
114 114 return file in ctx.manifest()
115 115 ctx[file]
116 116 return True
117 117 except KeyError:
118 118 return False
119 119
120 120 if match is None:
121 121 match = match_.always(self.root, self.getcwd())
122 122
123 123 # First check if there were files specified on the
124 124 # command line. If there were, and none of them were
125 125 # largefiles, we should just bail here and let super
126 126 # handle it -- thus gaining a big performance boost.
127 127 lfdirstate = lfutil.openlfdirstate(ui, self)
128 128 if match.files() and not match.anypats():
129 129 for f in lfdirstate:
130 130 if match(f):
131 131 break
132 132 else:
133 133 return super(lfilesrepo, self).status(node1, node2,
134 134 match, listignored, listclean,
135 135 listunknown, listsubrepos)
136 136
137 137 # Create a copy of match that matches standins instead
138 138 # of largefiles.
139 139 def tostandin(file):
140 140 if working:
141 141 sf = lfutil.standin(file)
142 142 dirstate = repo.dirstate
143 143 if sf in dirstate or sf in dirstate.dirs():
144 144 return sf
145 145 return file
146 146
147 147 # Create a function that we can use to override what is
148 148 # normally the ignore matcher. We've already checked
149 149 # for ignored files on the first dirstate walk, and
150 150 # unecessarily re-checking here causes a huge performance
151 151 # hit because lfdirstate only knows about largefiles
152 152 def _ignoreoverride(self):
153 153 return False
154 154
155 155 m = copy.copy(match)
156 156 m._files = [tostandin(f) for f in m._files]
157 157
158 158 # Get ignored files here even if we weren't asked for them; we
159 159 # must use the result here for filtering later
160 160 result = super(lfilesrepo, self).status(node1, node2, m,
161 161 True, clean, unknown, listsubrepos)
162 162 if working:
163 163 try:
164 164 # Any non-largefiles that were explicitly listed must be
165 165 # taken out or lfdirstate.status will report an error.
166 166 # The status of these files was already computed using
167 167 # super's status.
168 168 # Override lfdirstate's ignore matcher to not do
169 169 # anything
170 170 origignore = lfdirstate._ignore
171 171 lfdirstate._ignore = _ignoreoverride
172 172
173 173 def sfindirstate(f):
174 174 sf = lfutil.standin(f)
175 175 dirstate = repo.dirstate
176 176 return sf in dirstate or sf in dirstate.dirs()
177 177 match._files = [f for f in match._files
178 178 if sfindirstate(f)]
179 179 # Don't waste time getting the ignored and unknown
180 180 # files again; we already have them
181 181 s = lfdirstate.status(match, [], False,
182 182 listclean, False)
183 183 (unsure, modified, added, removed, missing, unknown,
184 184 ignored, clean) = s
185 185 # Replace the list of ignored and unknown files with
186 186 # the previously caclulated lists, and strip out the
187 187 # largefiles
188 188 lfiles = set(lfdirstate._map)
189 189 ignored = set(result[5]).difference(lfiles)
190 190 unknown = set(result[4]).difference(lfiles)
191 191 if parentworking:
192 192 for lfile in unsure:
193 193 standin = lfutil.standin(lfile)
194 194 if standin not in ctx1:
195 195 # from second parent
196 196 modified.append(lfile)
197 197 elif ctx1[standin].data().strip() \
198 198 != lfutil.hashfile(self.wjoin(lfile)):
199 199 modified.append(lfile)
200 200 else:
201 201 clean.append(lfile)
202 202 lfdirstate.normal(lfile)
203 203 else:
204 204 tocheck = unsure + modified + added + clean
205 205 modified, added, clean = [], [], []
206 206
207 207 for lfile in tocheck:
208 208 standin = lfutil.standin(lfile)
209 209 if inctx(standin, ctx1):
210 210 if ctx1[standin].data().strip() != \
211 211 lfutil.hashfile(self.wjoin(lfile)):
212 212 modified.append(lfile)
213 213 else:
214 214 clean.append(lfile)
215 215 else:
216 216 added.append(lfile)
217 217 finally:
218 218 # Replace the original ignore function
219 219 lfdirstate._ignore = origignore
220 220
221 221 for standin in ctx1.manifest():
222 222 if not lfutil.isstandin(standin):
223 223 continue
224 224 lfile = lfutil.splitstandin(standin)
225 225 if not match(lfile):
226 226 continue
227 227 if lfile not in lfdirstate:
228 228 removed.append(lfile)
229 229
230 230 # Filter result lists
231 231 result = list(result)
232 232
233 233 # Largefiles are not really removed when they're
234 234 # still in the normal dirstate. Likewise, normal
235 235 # files are not really removed if it's still in
236 236 # lfdirstate. This happens in merges where files
237 237 # change type.
238 238 removed = [f for f in removed if f not in repo.dirstate]
239 239 result[2] = [f for f in result[2] if f not in lfdirstate]
240 240
241 241 # Unknown files
242 242 unknown = set(unknown).difference(ignored)
243 243 result[4] = [f for f in unknown
244 244 if (repo.dirstate[f] == '?' and
245 245 not lfutil.isstandin(f))]
246 246 # Ignored files were calculated earlier by the dirstate,
247 247 # and we already stripped out the largefiles from the list
248 248 result[5] = ignored
249 249 # combine normal files and largefiles
250 250 normals = [[fn for fn in filelist
251 251 if not lfutil.isstandin(fn)]
252 252 for filelist in result]
253 253 lfiles = (modified, added, removed, missing, [], [], clean)
254 254 result = [sorted(list1 + list2)
255 255 for (list1, list2) in zip(normals, lfiles)]
256 256 else:
257 257 def toname(f):
258 258 if lfutil.isstandin(f):
259 259 return lfutil.splitstandin(f)
260 260 return f
261 261 result = [[toname(f) for f in items] for items in result]
262 262
263 263 if not listunknown:
264 264 result[4] = []
265 265 if not listignored:
266 266 result[5] = []
267 267 if not listclean:
268 268 result[6] = []
269 269 self.lfstatus = True
270 270 return result
271 271
272 272 # As part of committing, copy all of the largefiles into the
273 273 # cache.
274 274 def commitctx(self, *args, **kwargs):
275 275 node = super(lfilesrepo, self).commitctx(*args, **kwargs)
276 276 lfutil.copyalltostore(self, node)
277 277 return node
278 278
279 279 # Before commit, largefile standins have not had their
280 280 # contents updated to reflect the hash of their largefile.
281 281 # Do that here.
282 282 def commit(self, text="", user=None, date=None, match=None,
283 283 force=False, editor=False, extra={}):
284 284 orig = super(lfilesrepo, self).commit
285 285
286 286 wlock = repo.wlock()
287 287 try:
288 288 # Case 0: Rebase or Transplant
289 289 # We have to take the time to pull down the new largefiles now.
290 290 # Otherwise, any largefiles that were modified in the
291 291 # destination changesets get overwritten, either by the rebase
292 292 # or in the first commit after the rebase or transplant.
293 293 # updatelfiles will update the dirstate to mark any pulled
294 294 # largefiles as modified
295 295 if getattr(repo, "_isrebasing", False) or \
296 296 getattr(repo, "_istransplanting", False):
297 297 lfcommands.updatelfiles(repo.ui, repo, filelist=None,
298 298 printmessage=False)
299 299 result = orig(text=text, user=user, date=date, match=match,
300 300 force=force, editor=editor, extra=extra)
301 301 return result
302 302 # Case 1: user calls commit with no specific files or
303 303 # include/exclude patterns: refresh and commit all files that
304 304 # are "dirty".
305 305 if ((match is None) or
306 306 (not match.anypats() and not match.files())):
307 307 # Spend a bit of time here to get a list of files we know
308 308 # are modified so we can compare only against those.
309 309 # It can cost a lot of time (several seconds)
310 310 # otherwise to update all standins if the largefiles are
311 311 # large.
312 312 lfdirstate = lfutil.openlfdirstate(ui, self)
313 313 dirtymatch = match_.always(repo.root, repo.getcwd())
314 314 s = lfdirstate.status(dirtymatch, [], False, False, False)
315 315 modifiedfiles = []
316 316 for i in s:
317 317 modifiedfiles.extend(i)
318 318 lfiles = lfutil.listlfiles(self)
319 319 # this only loops through largefiles that exist (not
320 320 # removed/renamed)
321 321 for lfile in lfiles:
322 322 if lfile in modifiedfiles:
323 323 if os.path.exists(
324 324 self.wjoin(lfutil.standin(lfile))):
325 325 # this handles the case where a rebase is being
326 326 # performed and the working copy is not updated
327 327 # yet.
328 328 if os.path.exists(self.wjoin(lfile)):
329 329 lfutil.updatestandin(self,
330 330 lfutil.standin(lfile))
331 331 lfdirstate.normal(lfile)
332 332 for lfile in lfdirstate:
333 333 if lfile in modifiedfiles:
334 334 if not os.path.exists(
335 335 repo.wjoin(lfutil.standin(lfile))):
336 336 lfdirstate.drop(lfile)
337 337
338 338 result = orig(text=text, user=user, date=date, match=match,
339 339 force=force, editor=editor, extra=extra)
340 340 # This needs to be after commit; otherwise precommit hooks
341 341 # get the wrong status
342 342 lfdirstate.write()
343 343 return result
344 344
345 345 for f in match.files():
346 346 if lfutil.isstandin(f):
347 347 raise util.Abort(
348 348 _('file "%s" is a largefile standin') % f,
349 349 hint=('commit the largefile itself instead'))
350 350
351 351 # Case 2: user calls commit with specified patterns: refresh
352 352 # any matching big files.
353 353 smatcher = lfutil.composestandinmatcher(self, match)
354 354 standins = lfutil.dirstatewalk(self.dirstate, smatcher)
355 355
356 356 # No matching big files: get out of the way and pass control to
357 357 # the usual commit() method.
358 358 if not standins:
359 359 return orig(text=text, user=user, date=date, match=match,
360 360 force=force, editor=editor, extra=extra)
361 361
362 362 # Refresh all matching big files. It's possible that the
363 363 # commit will end up failing, in which case the big files will
364 364 # stay refreshed. No harm done: the user modified them and
365 365 # asked to commit them, so sooner or later we're going to
366 366 # refresh the standins. Might as well leave them refreshed.
367 367 lfdirstate = lfutil.openlfdirstate(ui, self)
368 368 for standin in standins:
369 369 lfile = lfutil.splitstandin(standin)
370 370 if lfdirstate[lfile] <> 'r':
371 371 lfutil.updatestandin(self, standin)
372 372 lfdirstate.normal(lfile)
373 373 else:
374 374 lfdirstate.drop(lfile)
375 375
376 376 # Cook up a new matcher that only matches regular files or
377 377 # standins corresponding to the big files requested by the
378 378 # user. Have to modify _files to prevent commit() from
379 379 # complaining "not tracked" for big files.
380 380 lfiles = lfutil.listlfiles(repo)
381 381 match = copy.copy(match)
382 382 origmatchfn = match.matchfn
383 383
384 384 # Check both the list of largefiles and the list of
385 385 # standins because if a largefile was removed, it
386 386 # won't be in the list of largefiles at this point
387 387 match._files += sorted(standins)
388 388
389 389 actualfiles = []
390 390 for f in match._files:
391 391 fstandin = lfutil.standin(f)
392 392
393 393 # ignore known largefiles and standins
394 394 if f in lfiles or fstandin in standins:
395 395 continue
396 396
397 397 # append directory separator to avoid collisions
398 398 if not fstandin.endswith(os.sep):
399 399 fstandin += os.sep
400 400
401 # prevalidate matching standin directories
402 if util.any(st for st in match._files
403 if st.startswith(fstandin)):
404 continue
405 401 actualfiles.append(f)
406 402 match._files = actualfiles
407 403
408 404 def matchfn(f):
409 405 if origmatchfn(f):
410 406 return f not in lfiles
411 407 else:
412 408 return f in standins
413 409
414 410 match.matchfn = matchfn
415 411 result = orig(text=text, user=user, date=date, match=match,
416 412 force=force, editor=editor, extra=extra)
417 413 # This needs to be after commit; otherwise precommit hooks
418 414 # get the wrong status
419 415 lfdirstate.write()
420 416 return result
421 417 finally:
422 418 wlock.release()
423 419
424 420 def push(self, remote, force=False, revs=None, newbranch=False):
425 421 o = lfutil.findoutgoing(repo, remote, force)
426 422 if o:
427 423 toupload = set()
428 424 o = repo.changelog.nodesbetween(o, revs)[0]
429 425 for n in o:
430 426 parents = [p for p in repo.changelog.parents(n)
431 427 if p != node_.nullid]
432 428 ctx = repo[n]
433 429 files = set(ctx.files())
434 430 if len(parents) == 2:
435 431 mc = ctx.manifest()
436 432 mp1 = ctx.parents()[0].manifest()
437 433 mp2 = ctx.parents()[1].manifest()
438 434 for f in mp1:
439 435 if f not in mc:
440 436 files.add(f)
441 437 for f in mp2:
442 438 if f not in mc:
443 439 files.add(f)
444 440 for f in mc:
445 441 if mc[f] != mp1.get(f, None) or mc[f] != mp2.get(f,
446 442 None):
447 443 files.add(f)
448 444
449 445 toupload = toupload.union(
450 446 set([ctx[f].data().strip()
451 447 for f in files
452 448 if lfutil.isstandin(f) and f in ctx]))
453 449 lfcommands.uploadlfiles(ui, self, remote, toupload)
454 450 return super(lfilesrepo, self).push(remote, force, revs,
455 451 newbranch)
456 452
457 453 repo.__class__ = lfilesrepo
458 454
459 455 def checkrequireslfiles(ui, repo, **kwargs):
460 456 if 'largefiles' not in repo.requirements and util.any(
461 457 lfutil.shortname+'/' in f[0] for f in repo.store.datafiles()):
462 458 repo.requirements.add('largefiles')
463 459 repo._writerequirements()
464 460
465 461 ui.setconfig('hooks', 'changegroup.lfiles', checkrequireslfiles)
466 462 ui.setconfig('hooks', 'commit.lfiles', checkrequireslfiles)
@@ -1,242 +1,242 b''
1 1 # Mercurial bookmark support code
2 2 #
3 3 # Copyright 2008 David Soria Parra <dsp@php.net>
4 4 #
5 5 # This software may be used and distributed according to the terms of the
6 6 # GNU General Public License version 2 or any later version.
7 7
8 8 from mercurial.i18n import _
9 9 from mercurial.node import hex
10 from mercurial import encoding, error, util
10 from mercurial import encoding, util
11 11 import errno, os
12 12
13 13 def valid(mark):
14 14 for c in (':', '\0', '\n', '\r'):
15 15 if c in mark:
16 16 return False
17 17 return True
18 18
19 19 def read(repo):
20 20 '''Parse .hg/bookmarks file and return a dictionary
21 21
22 22 Bookmarks are stored as {HASH}\\s{NAME}\\n (localtags format) values
23 23 in the .hg/bookmarks file.
24 24 Read the file and return a (name=>nodeid) dictionary
25 25 '''
26 26 bookmarks = {}
27 27 try:
28 28 for line in repo.opener('bookmarks'):
29 29 line = line.strip()
30 30 if not line:
31 31 continue
32 32 if ' ' not in line:
33 33 repo.ui.warn(_('malformed line in .hg/bookmarks: %r\n') % line)
34 34 continue
35 35 sha, refspec = line.split(' ', 1)
36 36 refspec = encoding.tolocal(refspec)
37 37 try:
38 38 bookmarks[refspec] = repo.changelog.lookup(sha)
39 except error.RepoLookupError:
39 except LookupError:
40 40 pass
41 41 except IOError, inst:
42 42 if inst.errno != errno.ENOENT:
43 43 raise
44 44 return bookmarks
45 45
46 46 def readcurrent(repo):
47 47 '''Get the current bookmark
48 48
49 49 If we use gittishsh branches we have a current bookmark that
50 50 we are on. This function returns the name of the bookmark. It
51 51 is stored in .hg/bookmarks.current
52 52 '''
53 53 mark = None
54 54 try:
55 55 file = repo.opener('bookmarks.current')
56 56 except IOError, inst:
57 57 if inst.errno != errno.ENOENT:
58 58 raise
59 59 return None
60 60 try:
61 61 # No readline() in posixfile_nt, reading everything is cheap
62 62 mark = encoding.tolocal((file.readlines() or [''])[0])
63 63 if mark == '' or mark not in repo._bookmarks:
64 64 mark = None
65 65 finally:
66 66 file.close()
67 67 return mark
68 68
69 69 def write(repo):
70 70 '''Write bookmarks
71 71
72 72 Write the given bookmark => hash dictionary to the .hg/bookmarks file
73 73 in a format equal to those of localtags.
74 74
75 75 We also store a backup of the previous state in undo.bookmarks that
76 76 can be copied back on rollback.
77 77 '''
78 78 refs = repo._bookmarks
79 79
80 80 if repo._bookmarkcurrent not in refs:
81 81 setcurrent(repo, None)
82 82 for mark in refs.keys():
83 83 if not valid(mark):
84 84 raise util.Abort(_("bookmark '%s' contains illegal "
85 85 "character" % mark))
86 86
87 87 wlock = repo.wlock()
88 88 try:
89 89
90 90 file = repo.opener('bookmarks', 'w', atomictemp=True)
91 91 for refspec, node in refs.iteritems():
92 92 file.write("%s %s\n" % (hex(node), encoding.fromlocal(refspec)))
93 93 file.close()
94 94
95 95 # touch 00changelog.i so hgweb reloads bookmarks (no lock needed)
96 96 try:
97 97 os.utime(repo.sjoin('00changelog.i'), None)
98 98 except OSError:
99 99 pass
100 100
101 101 finally:
102 102 wlock.release()
103 103
104 104 def setcurrent(repo, mark):
105 105 '''Set the name of the bookmark that we are currently on
106 106
107 107 Set the name of the bookmark that we are on (hg update <bookmark>).
108 108 The name is recorded in .hg/bookmarks.current
109 109 '''
110 110 current = repo._bookmarkcurrent
111 111 if current == mark:
112 112 return
113 113
114 114 if mark not in repo._bookmarks:
115 115 mark = ''
116 116 if not valid(mark):
117 117 raise util.Abort(_("bookmark '%s' contains illegal "
118 118 "character" % mark))
119 119
120 120 wlock = repo.wlock()
121 121 try:
122 122 file = repo.opener('bookmarks.current', 'w', atomictemp=True)
123 123 file.write(encoding.fromlocal(mark))
124 124 file.close()
125 125 finally:
126 126 wlock.release()
127 127 repo._bookmarkcurrent = mark
128 128
129 129 def unsetcurrent(repo):
130 130 wlock = repo.wlock()
131 131 try:
132 132 try:
133 133 util.unlink(repo.join('bookmarks.current'))
134 134 repo._bookmarkcurrent = None
135 135 except OSError, inst:
136 136 if inst.errno != errno.ENOENT:
137 137 raise
138 138 finally:
139 139 wlock.release()
140 140
141 141 def updatecurrentbookmark(repo, oldnode, curbranch):
142 142 try:
143 143 return update(repo, oldnode, repo.branchtags()[curbranch])
144 144 except KeyError:
145 145 if curbranch == "default": # no default branch!
146 146 return update(repo, oldnode, repo.lookup("tip"))
147 147 else:
148 148 raise util.Abort(_("branch %s not found") % curbranch)
149 149
150 150 def update(repo, parents, node):
151 151 marks = repo._bookmarks
152 152 update = False
153 153 mark = repo._bookmarkcurrent
154 154 if mark and marks[mark] in parents:
155 155 old = repo[marks[mark]]
156 156 new = repo[node]
157 157 if new in old.descendants():
158 158 marks[mark] = new.node()
159 159 update = True
160 160 if update:
161 161 repo._writebookmarks(marks)
162 162 return update
163 163
164 164 def listbookmarks(repo):
165 165 # We may try to list bookmarks on a repo type that does not
166 166 # support it (e.g., statichttprepository).
167 167 marks = getattr(repo, '_bookmarks', {})
168 168
169 169 d = {}
170 170 for k, v in marks.iteritems():
171 171 # don't expose local divergent bookmarks
172 172 if '@' not in k or k.endswith('@'):
173 173 d[k] = hex(v)
174 174 return d
175 175
176 176 def pushbookmark(repo, key, old, new):
177 177 w = repo.wlock()
178 178 try:
179 179 marks = repo._bookmarks
180 180 if hex(marks.get(key, '')) != old:
181 181 return False
182 182 if new == '':
183 183 del marks[key]
184 184 else:
185 185 if new not in repo:
186 186 return False
187 187 marks[key] = repo[new].node()
188 188 write(repo)
189 189 return True
190 190 finally:
191 191 w.release()
192 192
193 193 def updatefromremote(ui, repo, remote, path):
194 194 ui.debug("checking for updated bookmarks\n")
195 195 rb = remote.listkeys('bookmarks')
196 196 changed = False
197 197 for k in rb.keys():
198 198 if k in repo._bookmarks:
199 199 nr, nl = rb[k], repo._bookmarks[k]
200 200 if nr in repo:
201 201 cr = repo[nr]
202 202 cl = repo[nl]
203 203 if cl.rev() >= cr.rev():
204 204 continue
205 205 if cr in cl.descendants():
206 206 repo._bookmarks[k] = cr.node()
207 207 changed = True
208 208 ui.status(_("updating bookmark %s\n") % k)
209 209 else:
210 210 # find a unique @ suffix
211 211 for x in range(1, 100):
212 212 n = '%s@%d' % (k, x)
213 213 if n not in repo._bookmarks:
214 214 break
215 215 # try to use an @pathalias suffix
216 216 # if an @pathalias already exists, we overwrite (update) it
217 217 for p, u in ui.configitems("paths"):
218 218 if path == u:
219 219 n = '%s@%s' % (k, p)
220 220
221 221 repo._bookmarks[n] = cr.node()
222 222 changed = True
223 223 ui.warn(_("divergent bookmark %s stored as %s\n") % (k, n))
224 224
225 225 if changed:
226 226 write(repo)
227 227
228 228 def diff(ui, repo, remote):
229 229 ui.status(_("searching for changed bookmarks\n"))
230 230
231 231 lmarks = repo.listkeys('bookmarks')
232 232 rmarks = remote.listkeys('bookmarks')
233 233
234 234 diff = sorted(set(rmarks) - set(lmarks))
235 235 for k in diff:
236 236 mark = ui.debugflag and rmarks[k] or rmarks[k][:12]
237 237 ui.write(" %-25s %s\n" % (k, mark))
238 238
239 239 if len(diff) <= 0:
240 240 ui.status(_("no changed bookmarks found\n"))
241 241 return 1
242 242 return 0
@@ -1,1424 +1,1433 b''
1 1 The Mercurial system uses a set of configuration files to control
2 2 aspects of its behavior.
3 3
4 4 The configuration files use a simple ini-file format. A configuration
5 5 file consists of sections, led by a ``[section]`` header and followed
6 6 by ``name = value`` entries::
7 7
8 8 [ui]
9 9 username = Firstname Lastname <firstname.lastname@example.net>
10 10 verbose = True
11 11
12 12 The above entries will be referred to as ``ui.username`` and
13 13 ``ui.verbose``, respectively. See the Syntax section below.
14 14
15 15 Files
16 16 -----
17 17
18 18 Mercurial reads configuration data from several files, if they exist.
19 19 These files do not exist by default and you will have to create the
20 20 appropriate configuration files yourself: global configuration like
21 21 the username setting is typically put into
22 22 ``%USERPROFILE%\mercurial.ini`` or ``$HOME/.hgrc`` and local
23 23 configuration is put into the per-repository ``<repo>/.hg/hgrc`` file.
24 24
25 25 The names of these files depend on the system on which Mercurial is
26 26 installed. ``*.rc`` files from a single directory are read in
27 27 alphabetical order, later ones overriding earlier ones. Where multiple
28 28 paths are given below, settings from earlier paths override later
29 29 ones.
30 30
31 31 | (All) ``<repo>/.hg/hgrc``
32 32
33 33 Per-repository configuration options that only apply in a
34 34 particular repository. This file is not version-controlled, and
35 35 will not get transferred during a "clone" operation. Options in
36 36 this file override options in all other configuration files. On
37 37 Plan 9 and Unix, most of this file will be ignored if it doesn't
38 38 belong to a trusted user or to a trusted group. See the documentation
39 39 for the ``[trusted]`` section below for more details.
40 40
41 41 | (Plan 9) ``$home/lib/hgrc``
42 42 | (Unix) ``$HOME/.hgrc``
43 43 | (Windows) ``%USERPROFILE%\.hgrc``
44 44 | (Windows) ``%USERPROFILE%\Mercurial.ini``
45 45 | (Windows) ``%HOME%\.hgrc``
46 46 | (Windows) ``%HOME%\Mercurial.ini``
47 47
48 48 Per-user configuration file(s), for the user running Mercurial. On
49 49 Windows 9x, ``%HOME%`` is replaced by ``%APPDATA%``. Options in these
50 50 files apply to all Mercurial commands executed by this user in any
51 51 directory. Options in these files override per-system and per-installation
52 52 options.
53 53
54 54 | (Plan 9) ``/lib/mercurial/hgrc``
55 55 | (Plan 9) ``/lib/mercurial/hgrc.d/*.rc``
56 56 | (Unix) ``/etc/mercurial/hgrc``
57 57 | (Unix) ``/etc/mercurial/hgrc.d/*.rc``
58 58
59 59 Per-system configuration files, for the system on which Mercurial
60 60 is running. Options in these files apply to all Mercurial commands
61 61 executed by any user in any directory. Options in these files
62 62 override per-installation options.
63 63
64 64 | (Plan 9) ``<install-root>/lib/mercurial/hgrc``
65 65 | (Plan 9) ``<install-root>/lib/mercurial/hgrc.d/*.rc``
66 66 | (Unix) ``<install-root>/etc/mercurial/hgrc``
67 67 | (Unix) ``<install-root>/etc/mercurial/hgrc.d/*.rc``
68 68
69 69 Per-installation configuration files, searched for in the
70 70 directory where Mercurial is installed. ``<install-root>`` is the
71 71 parent directory of the **hg** executable (or symlink) being run. For
72 72 example, if installed in ``/shared/tools/bin/hg``, Mercurial will look
73 73 in ``/shared/tools/etc/mercurial/hgrc``. Options in these files apply
74 74 to all Mercurial commands executed by any user in any directory.
75 75
76 76 | (Windows) ``<install-dir>\Mercurial.ini`` **or**
77 77 | (Windows) ``<install-dir>\hgrc.d\*.rc`` **or**
78 78 | (Windows) ``HKEY_LOCAL_MACHINE\SOFTWARE\Mercurial``
79 79
80 80 Per-installation/system configuration files, for the system on
81 81 which Mercurial is running. Options in these files apply to all
82 82 Mercurial commands executed by any user in any directory. Registry
83 83 keys contain PATH-like strings, every part of which must reference
84 84 a ``Mercurial.ini`` file or be a directory where ``*.rc`` files will
85 85 be read. Mercurial checks each of these locations in the specified
86 86 order until one or more configuration files are detected. If the
87 87 pywin32 extensions are not installed, Mercurial will only look for
88 88 site-wide configuration in ``C:\Mercurial\Mercurial.ini``.
89 89
90 90 Syntax
91 91 ------
92 92
93 93 A configuration file consists of sections, led by a ``[section]`` header
94 94 and followed by ``name = value`` entries (sometimes called
95 95 ``configuration keys``)::
96 96
97 97 [spam]
98 98 eggs=ham
99 99 green=
100 100 eggs
101 101
102 102 Each line contains one entry. If the lines that follow are indented,
103 103 they are treated as continuations of that entry. Leading whitespace is
104 104 removed from values. Empty lines are skipped. Lines beginning with
105 105 ``#`` or ``;`` are ignored and may be used to provide comments.
106 106
107 107 Configuration keys can be set multiple times, in which case Mercurial
108 108 will use the value that was configured last. As an example::
109 109
110 110 [spam]
111 111 eggs=large
112 112 ham=serrano
113 113 eggs=small
114 114
115 115 This would set the configuration key named ``eggs`` to ``small``.
116 116
117 117 It is also possible to define a section multiple times. A section can
118 118 be redefined on the same and/or on different configuration files. For
119 119 example::
120 120
121 121 [foo]
122 122 eggs=large
123 123 ham=serrano
124 124 eggs=small
125 125
126 126 [bar]
127 127 eggs=ham
128 128 green=
129 129 eggs
130 130
131 131 [foo]
132 132 ham=prosciutto
133 133 eggs=medium
134 134 bread=toasted
135 135
136 136 This would set the ``eggs``, ``ham``, and ``bread`` configuration keys
137 137 of the ``foo`` section to ``medium``, ``prosciutto``, and ``toasted``,
138 138 respectively. As you can see there only thing that matters is the last
139 139 value that was set for each of the configuration keys.
140 140
141 141 If a configuration key is set multiple times in different
142 142 configuration files the final value will depend on the order in which
143 143 the different configuration files are read, with settings from earlier
144 144 paths overriding later ones as described on the ``Files`` section
145 145 above.
146 146
147 147 A line of the form ``%include file`` will include ``file`` into the
148 148 current configuration file. The inclusion is recursive, which means
149 149 that included files can include other files. Filenames are relative to
150 150 the configuration file in which the ``%include`` directive is found.
151 151 Environment variables and ``~user`` constructs are expanded in
152 152 ``file``. This lets you do something like::
153 153
154 154 %include ~/.hgrc.d/$HOST.rc
155 155
156 156 to include a different configuration file on each computer you use.
157 157
158 158 A line with ``%unset name`` will remove ``name`` from the current
159 159 section, if it has been set previously.
160 160
161 161 The values are either free-form text strings, lists of text strings,
162 162 or Boolean values. Boolean values can be set to true using any of "1",
163 163 "yes", "true", or "on" and to false using "0", "no", "false", or "off"
164 164 (all case insensitive).
165 165
166 166 List values are separated by whitespace or comma, except when values are
167 167 placed in double quotation marks::
168 168
169 169 allow_read = "John Doe, PhD", brian, betty
170 170
171 171 Quotation marks can be escaped by prefixing them with a backslash. Only
172 172 quotation marks at the beginning of a word is counted as a quotation
173 173 (e.g., ``foo"bar baz`` is the list of ``foo"bar`` and ``baz``).
174 174
175 175 Sections
176 176 --------
177 177
178 178 This section describes the different sections that may appear in a
179 179 Mercurial configuration file, the purpose of each section, its possible
180 180 keys, and their possible values.
181 181
182 182 ``alias``
183 183 """""""""
184 184
185 185 Defines command aliases.
186 186 Aliases allow you to define your own commands in terms of other
187 187 commands (or aliases), optionally including arguments. Positional
188 188 arguments in the form of ``$1``, ``$2``, etc in the alias definition
189 189 are expanded by Mercurial before execution. Positional arguments not
190 190 already used by ``$N`` in the definition are put at the end of the
191 191 command to be executed.
192 192
193 193 Alias definitions consist of lines of the form::
194 194
195 195 <alias> = <command> [<argument>]...
196 196
197 197 For example, this definition::
198 198
199 199 latest = log --limit 5
200 200
201 201 creates a new command ``latest`` that shows only the five most recent
202 202 changesets. You can define subsequent aliases using earlier ones::
203 203
204 204 stable5 = latest -b stable
205 205
206 206 .. note:: It is possible to create aliases with the same names as
207 207 existing commands, which will then override the original
208 208 definitions. This is almost always a bad idea!
209 209
210 210 An alias can start with an exclamation point (``!``) to make it a
211 211 shell alias. A shell alias is executed with the shell and will let you
212 212 run arbitrary commands. As an example, ::
213 213
214 214 echo = !echo $@
215 215
216 216 will let you do ``hg echo foo`` to have ``foo`` printed in your
217 217 terminal. A better example might be::
218 218
219 219 purge = !$HG status --no-status --unknown -0 | xargs -0 rm
220 220
221 221 which will make ``hg purge`` delete all unknown files in the
222 222 repository in the same manner as the purge extension.
223 223
224 224 Positional arguments like ``$1``, ``$2``, etc. in the alias definition
225 225 expand to the command arguments. Unmatched arguments are
226 226 removed. ``$0`` expands to the alias name and ``$@`` expands to all
227 227 arguments separated by a space. These expansions happen before the
228 228 command is passed to the shell.
229 229
230 230 Shell aliases are executed in an environment where ``$HG`` expands to
231 231 the path of the Mercurial that was used to execute the alias. This is
232 232 useful when you want to call further Mercurial commands in a shell
233 233 alias, as was done above for the purge alias. In addition,
234 234 ``$HG_ARGS`` expands to the arguments given to Mercurial. In the ``hg
235 235 echo foo`` call above, ``$HG_ARGS`` would expand to ``echo foo``.
236 236
237 237 .. note:: Some global configuration options such as ``-R`` are
238 238 processed before shell aliases and will thus not be passed to
239 239 aliases.
240 240
241 241
242 242 ``annotate``
243 243 """"""""""""
244 244
245 245 Settings used when displaying file annotations. All values are
246 246 Booleans and default to False. See ``diff`` section for related
247 247 options for the diff command.
248 248
249 249 ``ignorews``
250 250 Ignore white space when comparing lines.
251 251
252 252 ``ignorewsamount``
253 253 Ignore changes in the amount of white space.
254 254
255 255 ``ignoreblanklines``
256 256 Ignore changes whose lines are all blank.
257 257
258 258
259 259 ``auth``
260 260 """"""""
261 261
262 262 Authentication credentials for HTTP authentication. This section
263 263 allows you to store usernames and passwords for use when logging
264 264 *into* HTTP servers. See the ``[web]`` configuration section if
265 265 you want to configure *who* can login to your HTTP server.
266 266
267 267 Each line has the following format::
268 268
269 269 <name>.<argument> = <value>
270 270
271 271 where ``<name>`` is used to group arguments into authentication
272 272 entries. Example::
273 273
274 274 foo.prefix = hg.intevation.org/mercurial
275 275 foo.username = foo
276 276 foo.password = bar
277 277 foo.schemes = http https
278 278
279 279 bar.prefix = secure.example.org
280 280 bar.key = path/to/file.key
281 281 bar.cert = path/to/file.cert
282 282 bar.schemes = https
283 283
284 284 Supported arguments:
285 285
286 286 ``prefix``
287 287 Either ``*`` or a URI prefix with or without the scheme part.
288 288 The authentication entry with the longest matching prefix is used
289 289 (where ``*`` matches everything and counts as a match of length
290 290 1). If the prefix doesn't include a scheme, the match is performed
291 291 against the URI with its scheme stripped as well, and the schemes
292 292 argument, q.v., is then subsequently consulted.
293 293
294 294 ``username``
295 295 Optional. Username to authenticate with. If not given, and the
296 296 remote site requires basic or digest authentication, the user will
297 297 be prompted for it. Environment variables are expanded in the
298 298 username letting you do ``foo.username = $USER``. If the URI
299 299 includes a username, only ``[auth]`` entries with a matching
300 300 username or without a username will be considered.
301 301
302 302 ``password``
303 303 Optional. Password to authenticate with. If not given, and the
304 304 remote site requires basic or digest authentication, the user
305 305 will be prompted for it.
306 306
307 307 ``key``
308 308 Optional. PEM encoded client certificate key file. Environment
309 309 variables are expanded in the filename.
310 310
311 311 ``cert``
312 312 Optional. PEM encoded client certificate chain file. Environment
313 313 variables are expanded in the filename.
314 314
315 315 ``schemes``
316 316 Optional. Space separated list of URI schemes to use this
317 317 authentication entry with. Only used if the prefix doesn't include
318 318 a scheme. Supported schemes are http and https. They will match
319 319 static-http and static-https respectively, as well.
320 320 Default: https.
321 321
322 322 If no suitable authentication entry is found, the user is prompted
323 323 for credentials as usual if required by the remote.
324 324
325 325
326 326 ``decode/encode``
327 327 """""""""""""""""
328 328
329 329 Filters for transforming files on checkout/checkin. This would
330 330 typically be used for newline processing or other
331 331 localization/canonicalization of files.
332 332
333 333 Filters consist of a filter pattern followed by a filter command.
334 334 Filter patterns are globs by default, rooted at the repository root.
335 335 For example, to match any file ending in ``.txt`` in the root
336 336 directory only, use the pattern ``*.txt``. To match any file ending
337 337 in ``.c`` anywhere in the repository, use the pattern ``**.c``.
338 338 For each file only the first matching filter applies.
339 339
340 340 The filter command can start with a specifier, either ``pipe:`` or
341 341 ``tempfile:``. If no specifier is given, ``pipe:`` is used by default.
342 342
343 343 A ``pipe:`` command must accept data on stdin and return the transformed
344 344 data on stdout.
345 345
346 346 Pipe example::
347 347
348 348 [encode]
349 349 # uncompress gzip files on checkin to improve delta compression
350 350 # note: not necessarily a good idea, just an example
351 351 *.gz = pipe: gunzip
352 352
353 353 [decode]
354 354 # recompress gzip files when writing them to the working dir (we
355 355 # can safely omit "pipe:", because it's the default)
356 356 *.gz = gzip
357 357
358 358 A ``tempfile:`` command is a template. The string ``INFILE`` is replaced
359 359 with the name of a temporary file that contains the data to be
360 360 filtered by the command. The string ``OUTFILE`` is replaced with the name
361 361 of an empty temporary file, where the filtered data must be written by
362 362 the command.
363 363
364 364 .. note:: The tempfile mechanism is recommended for Windows systems,
365 365 where the standard shell I/O redirection operators often have
366 366 strange effects and may corrupt the contents of your files.
367 367
368 368 This filter mechanism is used internally by the ``eol`` extension to
369 369 translate line ending characters between Windows (CRLF) and Unix (LF)
370 370 format. We suggest you use the ``eol`` extension for convenience.
371 371
372 372
373 373 ``defaults``
374 374 """"""""""""
375 375
376 376 (defaults are deprecated. Don't use them. Use aliases instead)
377 377
378 378 Use the ``[defaults]`` section to define command defaults, i.e. the
379 379 default options/arguments to pass to the specified commands.
380 380
381 381 The following example makes :hg:`log` run in verbose mode, and
382 382 :hg:`status` show only the modified files, by default::
383 383
384 384 [defaults]
385 385 log = -v
386 386 status = -m
387 387
388 388 The actual commands, instead of their aliases, must be used when
389 389 defining command defaults. The command defaults will also be applied
390 390 to the aliases of the commands defined.
391 391
392 392
393 393 ``diff``
394 394 """"""""
395 395
396 396 Settings used when displaying diffs. Everything except for ``unified``
397 397 is a Boolean and defaults to False. See ``annotate`` section for
398 398 related options for the annotate command.
399 399
400 400 ``git``
401 401 Use git extended diff format.
402 402
403 403 ``nodates``
404 404 Don't include dates in diff headers.
405 405
406 406 ``showfunc``
407 407 Show which function each change is in.
408 408
409 409 ``ignorews``
410 410 Ignore white space when comparing lines.
411 411
412 412 ``ignorewsamount``
413 413 Ignore changes in the amount of white space.
414 414
415 415 ``ignoreblanklines``
416 416 Ignore changes whose lines are all blank.
417 417
418 418 ``unified``
419 419 Number of lines of context to show.
420 420
421 421 ``email``
422 422 """""""""
423 423
424 424 Settings for extensions that send email messages.
425 425
426 426 ``from``
427 427 Optional. Email address to use in "From" header and SMTP envelope
428 428 of outgoing messages.
429 429
430 430 ``to``
431 431 Optional. Comma-separated list of recipients' email addresses.
432 432
433 433 ``cc``
434 434 Optional. Comma-separated list of carbon copy recipients'
435 435 email addresses.
436 436
437 437 ``bcc``
438 438 Optional. Comma-separated list of blind carbon copy recipients'
439 439 email addresses.
440 440
441 441 ``method``
442 442 Optional. Method to use to send email messages. If value is ``smtp``
443 443 (default), use SMTP (see the ``[smtp]`` section for configuration).
444 444 Otherwise, use as name of program to run that acts like sendmail
445 445 (takes ``-f`` option for sender, list of recipients on command line,
446 446 message on stdin). Normally, setting this to ``sendmail`` or
447 447 ``/usr/sbin/sendmail`` is enough to use sendmail to send messages.
448 448
449 449 ``charsets``
450 450 Optional. Comma-separated list of character sets considered
451 451 convenient for recipients. Addresses, headers, and parts not
452 452 containing patches of outgoing messages will be encoded in the
453 453 first character set to which conversion from local encoding
454 454 (``$HGENCODING``, ``ui.fallbackencoding``) succeeds. If correct
455 455 conversion fails, the text in question is sent as is. Defaults to
456 456 empty (explicit) list.
457 457
458 458 Order of outgoing email character sets:
459 459
460 460 1. ``us-ascii``: always first, regardless of settings
461 461 2. ``email.charsets``: in order given by user
462 462 3. ``ui.fallbackencoding``: if not in email.charsets
463 463 4. ``$HGENCODING``: if not in email.charsets
464 464 5. ``utf-8``: always last, regardless of settings
465 465
466 466 Email example::
467 467
468 468 [email]
469 469 from = Joseph User <joe.user@example.com>
470 470 method = /usr/sbin/sendmail
471 471 # charsets for western Europeans
472 472 # us-ascii, utf-8 omitted, as they are tried first and last
473 473 charsets = iso-8859-1, iso-8859-15, windows-1252
474 474
475 475
476 476 ``extensions``
477 477 """"""""""""""
478 478
479 479 Mercurial has an extension mechanism for adding new features. To
480 480 enable an extension, create an entry for it in this section.
481 481
482 482 If you know that the extension is already in Python's search path,
483 483 you can give the name of the module, followed by ``=``, with nothing
484 484 after the ``=``.
485 485
486 486 Otherwise, give a name that you choose, followed by ``=``, followed by
487 487 the path to the ``.py`` file (including the file name extension) that
488 488 defines the extension.
489 489
490 490 To explicitly disable an extension that is enabled in an hgrc of
491 491 broader scope, prepend its path with ``!``, as in ``foo = !/ext/path``
492 492 or ``foo = !`` when path is not supplied.
493 493
494 494 Example for ``~/.hgrc``::
495 495
496 496 [extensions]
497 497 # (the mq extension will get loaded from Mercurial's path)
498 498 mq =
499 499 # (this extension will get loaded from the file specified)
500 500 myfeature = ~/.hgext/myfeature.py
501 501
502 502
503 503 ``format``
504 504 """"""""""
505 505
506 506 ``usestore``
507 507 Enable or disable the "store" repository format which improves
508 508 compatibility with systems that fold case or otherwise mangle
509 509 filenames. Enabled by default. Disabling this option will allow
510 510 you to store longer filenames in some situations at the expense of
511 511 compatibility and ensures that the on-disk format of newly created
512 512 repositories will be compatible with Mercurial before version 0.9.4.
513 513
514 514 ``usefncache``
515 515 Enable or disable the "fncache" repository format which enhances
516 516 the "store" repository format (which has to be enabled to use
517 517 fncache) to allow longer filenames and avoids using Windows
518 518 reserved names, e.g. "nul". Enabled by default. Disabling this
519 519 option ensures that the on-disk format of newly created
520 520 repositories will be compatible with Mercurial before version 1.1.
521 521
522 522 ``dotencode``
523 523 Enable or disable the "dotencode" repository format which enhances
524 524 the "fncache" repository format (which has to be enabled to use
525 525 dotencode) to avoid issues with filenames starting with ._ on
526 526 Mac OS X and spaces on Windows. Enabled by default. Disabling this
527 527 option ensures that the on-disk format of newly created
528 528 repositories will be compatible with Mercurial before version 1.7.
529 529
530 530 ``graph``
531 531 """""""""
532 532
533 533 Web graph view configuration. This section let you change graph
534 534 elements display properties by branches, for instance to make the
535 535 ``default`` branch stand out.
536 536
537 537 Each line has the following format::
538 538
539 539 <branch>.<argument> = <value>
540 540
541 541 where ``<branch>`` is the name of the branch being
542 542 customized. Example::
543 543
544 544 [graph]
545 545 # 2px width
546 546 default.width = 2
547 547 # red color
548 548 default.color = FF0000
549 549
550 550 Supported arguments:
551 551
552 552 ``width``
553 553 Set branch edges width in pixels.
554 554
555 555 ``color``
556 556 Set branch edges color in hexadecimal RGB notation.
557 557
558 558 ``hooks``
559 559 """""""""
560 560
561 561 Commands or Python functions that get automatically executed by
562 562 various actions such as starting or finishing a commit. Multiple
563 563 hooks can be run for the same action by appending a suffix to the
564 564 action. Overriding a site-wide hook can be done by changing its
565 565 value or setting it to an empty string. Hooks can be prioritized
566 566 by adding a prefix of ``priority`` to the hook name on a new line
567 567 and setting the priority. The default priority is 0 if
568 568 not specified.
569 569
570 570 Example ``.hg/hgrc``::
571 571
572 572 [hooks]
573 573 # update working directory after adding changesets
574 574 changegroup.update = hg update
575 575 # do not use the site-wide hook
576 576 incoming =
577 577 incoming.email = /my/email/hook
578 578 incoming.autobuild = /my/build/hook
579 579 # force autobuild hook to run before other incoming hooks
580 580 priority.incoming.autobuild = 1
581 581
582 582 Most hooks are run with environment variables set that give useful
583 583 additional information. For each hook below, the environment
584 584 variables it is passed are listed with names of the form ``$HG_foo``.
585 585
586 586 ``changegroup``
587 587 Run after a changegroup has been added via push, pull or unbundle.
588 588 ID of the first new changeset is in ``$HG_NODE``. URL from which
589 589 changes came is in ``$HG_URL``.
590 590
591 591 ``commit``
592 592 Run after a changeset has been created in the local repository. ID
593 593 of the newly created changeset is in ``$HG_NODE``. Parent changeset
594 594 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
595 595
596 596 ``incoming``
597 597 Run after a changeset has been pulled, pushed, or unbundled into
598 598 the local repository. The ID of the newly arrived changeset is in
599 599 ``$HG_NODE``. URL that was source of changes came is in ``$HG_URL``.
600 600
601 601 ``outgoing``
602 602 Run after sending changes from local repository to another. ID of
603 603 first changeset sent is in ``$HG_NODE``. Source of operation is in
604 604 ``$HG_SOURCE``; see "preoutgoing" hook for description.
605 605
606 606 ``post-<command>``
607 607 Run after successful invocations of the associated command. The
608 608 contents of the command line are passed as ``$HG_ARGS`` and the result
609 609 code in ``$HG_RESULT``. Parsed command line arguments are passed as
610 610 ``$HG_PATS`` and ``$HG_OPTS``. These contain string representations of
611 611 the python data internally passed to <command>. ``$HG_OPTS`` is a
612 612 dictionary of options (with unspecified options set to their defaults).
613 613 ``$HG_PATS`` is a list of arguments. Hook failure is ignored.
614 614
615 615 ``pre-<command>``
616 616 Run before executing the associated command. The contents of the
617 617 command line are passed as ``$HG_ARGS``. Parsed command line arguments
618 618 are passed as ``$HG_PATS`` and ``$HG_OPTS``. These contain string
619 619 representations of the data internally passed to <command>. ``$HG_OPTS``
620 620 is a dictionary of options (with unspecified options set to their
621 621 defaults). ``$HG_PATS`` is a list of arguments. If the hook returns
622 622 failure, the command doesn't execute and Mercurial returns the failure
623 623 code.
624 624
625 625 ``prechangegroup``
626 626 Run before a changegroup is added via push, pull or unbundle. Exit
627 627 status 0 allows the changegroup to proceed. Non-zero status will
628 628 cause the push, pull or unbundle to fail. URL from which changes
629 629 will come is in ``$HG_URL``.
630 630
631 631 ``precommit``
632 632 Run before starting a local commit. Exit status 0 allows the
633 633 commit to proceed. Non-zero status will cause the commit to fail.
634 634 Parent changeset IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
635 635
636 636 ``prelistkeys``
637 637 Run before listing pushkeys (like bookmarks) in the
638 638 repository. Non-zero status will cause failure. The key namespace is
639 639 in ``$HG_NAMESPACE``.
640 640
641 641 ``preoutgoing``
642 642 Run before collecting changes to send from the local repository to
643 643 another. Non-zero status will cause failure. This lets you prevent
644 644 pull over HTTP or SSH. Also prevents against local pull, push
645 645 (outbound) or bundle commands, but not effective, since you can
646 646 just copy files instead then. Source of operation is in
647 647 ``$HG_SOURCE``. If "serve", operation is happening on behalf of remote
648 648 SSH or HTTP repository. If "push", "pull" or "bundle", operation
649 649 is happening on behalf of repository on same system.
650 650
651 651 ``prepushkey``
652 652 Run before a pushkey (like a bookmark) is added to the
653 653 repository. Non-zero status will cause the key to be rejected. The
654 654 key namespace is in ``$HG_NAMESPACE``, the key is in ``$HG_KEY``,
655 655 the old value (if any) is in ``$HG_OLD``, and the new value is in
656 656 ``$HG_NEW``.
657 657
658 658 ``pretag``
659 659 Run before creating a tag. Exit status 0 allows the tag to be
660 660 created. Non-zero status will cause the tag to fail. ID of
661 661 changeset to tag is in ``$HG_NODE``. Name of tag is in ``$HG_TAG``. Tag is
662 662 local if ``$HG_LOCAL=1``, in repository if ``$HG_LOCAL=0``.
663 663
664 664 ``pretxnchangegroup``
665 665 Run after a changegroup has been added via push, pull or unbundle,
666 666 but before the transaction has been committed. Changegroup is
667 667 visible to hook program. This lets you validate incoming changes
668 668 before accepting them. Passed the ID of the first new changeset in
669 669 ``$HG_NODE``. Exit status 0 allows the transaction to commit. Non-zero
670 670 status will cause the transaction to be rolled back and the push,
671 671 pull or unbundle will fail. URL that was source of changes is in
672 672 ``$HG_URL``.
673 673
674 674 ``pretxncommit``
675 675 Run after a changeset has been created but the transaction not yet
676 676 committed. Changeset is visible to hook program. This lets you
677 677 validate commit message and changes. Exit status 0 allows the
678 678 commit to proceed. Non-zero status will cause the transaction to
679 679 be rolled back. ID of changeset is in ``$HG_NODE``. Parent changeset
680 680 IDs are in ``$HG_PARENT1`` and ``$HG_PARENT2``.
681 681
682 682 ``preupdate``
683 683 Run before updating the working directory. Exit status 0 allows
684 684 the update to proceed. Non-zero status will prevent the update.
685 685 Changeset ID of first new parent is in ``$HG_PARENT1``. If merge, ID
686 686 of second new parent is in ``$HG_PARENT2``.
687 687
688 688 ``listkeys``
689 689 Run after listing pushkeys (like bookmarks) in the repository. The
690 690 key namespace is in ``$HG_NAMESPACE``. ``$HG_VALUES`` is a
691 691 dictionary containing the keys and values.
692 692
693 693 ``pushkey``
694 694 Run after a pushkey (like a bookmark) is added to the
695 695 repository. The key namespace is in ``$HG_NAMESPACE``, the key is in
696 696 ``$HG_KEY``, the old value (if any) is in ``$HG_OLD``, and the new
697 697 value is in ``$HG_NEW``.
698 698
699 699 ``tag``
700 700 Run after a tag is created. ID of tagged changeset is in ``$HG_NODE``.
701 701 Name of tag is in ``$HG_TAG``. Tag is local if ``$HG_LOCAL=1``, in
702 702 repository if ``$HG_LOCAL=0``.
703 703
704 704 ``update``
705 705 Run after updating the working directory. Changeset ID of first
706 706 new parent is in ``$HG_PARENT1``. If merge, ID of second new parent is
707 707 in ``$HG_PARENT2``. If the update succeeded, ``$HG_ERROR=0``. If the
708 708 update failed (e.g. because conflicts not resolved), ``$HG_ERROR=1``.
709 709
710 710 .. note:: It is generally better to use standard hooks rather than the
711 711 generic pre- and post- command hooks as they are guaranteed to be
712 712 called in the appropriate contexts for influencing transactions.
713 713 Also, hooks like "commit" will be called in all contexts that
714 714 generate a commit (e.g. tag) and not just the commit command.
715 715
716 716 .. note:: Environment variables with empty values may not be passed to
717 717 hooks on platforms such as Windows. As an example, ``$HG_PARENT2``
718 718 will have an empty value under Unix-like platforms for non-merge
719 719 changesets, while it will not be available at all under Windows.
720 720
721 721 The syntax for Python hooks is as follows::
722 722
723 723 hookname = python:modulename.submodule.callable
724 724 hookname = python:/path/to/python/module.py:callable
725 725
726 726 Python hooks are run within the Mercurial process. Each hook is
727 727 called with at least three keyword arguments: a ui object (keyword
728 728 ``ui``), a repository object (keyword ``repo``), and a ``hooktype``
729 729 keyword that tells what kind of hook is used. Arguments listed as
730 730 environment variables above are passed as keyword arguments, with no
731 731 ``HG_`` prefix, and names in lower case.
732 732
733 733 If a Python hook returns a "true" value or raises an exception, this
734 734 is treated as a failure.
735 735
736 736
737 737 ``hostfingerprints``
738 738 """"""""""""""""""""
739 739
740 740 Fingerprints of the certificates of known HTTPS servers.
741 741 A HTTPS connection to a server with a fingerprint configured here will
742 742 only succeed if the servers certificate matches the fingerprint.
743 743 This is very similar to how ssh known hosts works.
744 744 The fingerprint is the SHA-1 hash value of the DER encoded certificate.
745 745 The CA chain and web.cacerts is not used for servers with a fingerprint.
746 746
747 747 For example::
748 748
749 749 [hostfingerprints]
750 750 hg.intevation.org = 38:76:52:7c:87:26:9a:8f:4a:f8:d3:de:08:45:3b:ea:d6:4b:ee:cc
751 751
752 752 This feature is only supported when using Python 2.6 or later.
753 753
754 754
755 755 ``http_proxy``
756 756 """"""""""""""
757 757
758 758 Used to access web-based Mercurial repositories through a HTTP
759 759 proxy.
760 760
761 761 ``host``
762 762 Host name and (optional) port of the proxy server, for example
763 763 "myproxy:8000".
764 764
765 765 ``no``
766 766 Optional. Comma-separated list of host names that should bypass
767 767 the proxy.
768 768
769 769 ``passwd``
770 770 Optional. Password to authenticate with at the proxy server.
771 771
772 772 ``user``
773 773 Optional. User name to authenticate with at the proxy server.
774 774
775 775 ``always``
776 776 Optional. Always use the proxy, even for localhost and any entries
777 777 in ``http_proxy.no``. True or False. Default: False.
778 778
779 779 ``merge-patterns``
780 780 """"""""""""""""""
781 781
782 782 This section specifies merge tools to associate with particular file
783 783 patterns. Tools matched here will take precedence over the default
784 784 merge tool. Patterns are globs by default, rooted at the repository
785 785 root.
786 786
787 787 Example::
788 788
789 789 [merge-patterns]
790 790 **.c = kdiff3
791 791 **.jpg = myimgmerge
792 792
793 793 ``merge-tools``
794 794 """""""""""""""
795 795
796 796 This section configures external merge tools to use for file-level
797 797 merges.
798 798
799 799 Example ``~/.hgrc``::
800 800
801 801 [merge-tools]
802 802 # Override stock tool location
803 803 kdiff3.executable = ~/bin/kdiff3
804 804 # Specify command line
805 805 kdiff3.args = $base $local $other -o $output
806 806 # Give higher priority
807 807 kdiff3.priority = 1
808 808
809 809 # Define new tool
810 810 myHtmlTool.args = -m $local $other $base $output
811 811 myHtmlTool.regkey = Software\FooSoftware\HtmlMerge
812 812 myHtmlTool.priority = 1
813 813
814 814 Supported arguments:
815 815
816 816 ``priority``
817 817 The priority in which to evaluate this tool.
818 818 Default: 0.
819 819
820 820 ``executable``
821 821 Either just the name of the executable or its pathname. On Windows,
822 822 the path can use environment variables with ${ProgramFiles} syntax.
823 823 Default: the tool name.
824 824
825 825 ``args``
826 826 The arguments to pass to the tool executable. You can refer to the
827 827 files being merged as well as the output file through these
828 828 variables: ``$base``, ``$local``, ``$other``, ``$output``.
829 829 Default: ``$local $base $other``
830 830
831 831 ``premerge``
832 832 Attempt to run internal non-interactive 3-way merge tool before
833 833 launching external tool. Options are ``true``, ``false``, or ``keep``
834 834 to leave markers in the file if the premerge fails.
835 835 Default: True
836 836
837 837 ``binary``
838 838 This tool can merge binary files. Defaults to False, unless tool
839 839 was selected by file pattern match.
840 840
841 841 ``symlink``
842 842 This tool can merge symlinks. Defaults to False, even if tool was
843 843 selected by file pattern match.
844 844
845 845 ``check``
846 846 A list of merge success-checking options:
847 847
848 848 ``changed``
849 849 Ask whether merge was successful when the merged file shows no changes.
850 850 ``conflicts``
851 851 Check whether there are conflicts even though the tool reported success.
852 852 ``prompt``
853 853 Always prompt for merge success, regardless of success reported by tool.
854 854
855 855 ``checkchanged``
856 856 True is equivalent to ``check = changed``.
857 857 Default: False
858 858
859 859 ``checkconflicts``
860 860 True is equivalent to ``check = conflicts``.
861 861 Default: False
862 862
863 863 ``fixeol``
864 864 Attempt to fix up EOL changes caused by the merge tool.
865 865 Default: False
866 866
867 867 ``gui``
868 868 This tool requires a graphical interface to run. Default: False
869 869
870 870 ``regkey``
871 871 Windows registry key which describes install location of this
872 872 tool. Mercurial will search for this key first under
873 873 ``HKEY_CURRENT_USER`` and then under ``HKEY_LOCAL_MACHINE``.
874 874 Default: None
875 875
876 876 ``regkeyalt``
877 877 An alternate Windows registry key to try if the first key is not
878 878 found. The alternate key uses the same ``regname`` and ``regappend``
879 879 semantics of the primary key. The most common use for this key
880 880 is to search for 32bit applications on 64bit operating systems.
881 881 Default: None
882 882
883 883 ``regname``
884 884 Name of value to read from specified registry key. Defaults to the
885 885 unnamed (default) value.
886 886
887 887 ``regappend``
888 888 String to append to the value read from the registry, typically
889 889 the executable name of the tool.
890 890 Default: None
891 891
892 892
893 893 ``patch``
894 894 """""""""
895 895
896 896 Settings used when applying patches, for instance through the 'import'
897 897 command or with Mercurial Queues extension.
898 898
899 899 ``eol``
900 900 When set to 'strict' patch content and patched files end of lines
901 901 are preserved. When set to ``lf`` or ``crlf``, both files end of
902 902 lines are ignored when patching and the result line endings are
903 903 normalized to either LF (Unix) or CRLF (Windows). When set to
904 904 ``auto``, end of lines are again ignored while patching but line
905 905 endings in patched files are normalized to their original setting
906 906 on a per-file basis. If target file does not exist or has no end
907 907 of line, patch line endings are preserved.
908 908 Default: strict.
909 909
910 910
911 911 ``paths``
912 912 """""""""
913 913
914 914 Assigns symbolic names to repositories. The left side is the
915 915 symbolic name, and the right gives the directory or URL that is the
916 916 location of the repository. Default paths can be declared by setting
917 917 the following entries.
918 918
919 919 ``default``
920 920 Directory or URL to use when pulling if no source is specified.
921 921 Default is set to repository from which the current repository was
922 922 cloned.
923 923
924 924 ``default-push``
925 925 Optional. Directory or URL to use when pushing if no destination
926 926 is specified.
927 927
928 928 ``phases``
929 929 """"""""""
930 930
931 931 Specifies default handling of phases. See :hg:`help phases` for more
932 932 information about working with phases.
933 933
934 934 ``publish``
935 935 Controls draft phase behavior when working as a server. When true,
936 936 pushed changesets are set to public in both client and server and
937 937 pulled or cloned changesets are set to public in the client.
938 938 Default: True
939 939
940 940 ``new-commit``
941 941 Phase of newly-created commits.
942 942 Default: draft
943 943
944 944 ``profiling``
945 945 """""""""""""
946 946
947 947 Specifies profiling type, format, and file output. Two profilers are
948 948 supported: an instrumenting profiler (named ``ls``), and a sampling
949 949 profiler (named ``stat``).
950 950
951 951 In this section description, 'profiling data' stands for the raw data
952 952 collected during profiling, while 'profiling report' stands for a
953 953 statistical text report generated from the profiling data. The
954 954 profiling is done using lsprof.
955 955
956 956 ``type``
957 957 The type of profiler to use.
958 958 Default: ls.
959 959
960 960 ``ls``
961 961 Use Python's built-in instrumenting profiler. This profiler
962 962 works on all platforms, but each line number it reports is the
963 963 first line of a function. This restriction makes it difficult to
964 964 identify the expensive parts of a non-trivial function.
965 965 ``stat``
966 966 Use a third-party statistical profiler, statprof. This profiler
967 967 currently runs only on Unix systems, and is most useful for
968 968 profiling commands that run for longer than about 0.1 seconds.
969 969
970 970 ``format``
971 971 Profiling format. Specific to the ``ls`` instrumenting profiler.
972 972 Default: text.
973 973
974 974 ``text``
975 975 Generate a profiling report. When saving to a file, it should be
976 976 noted that only the report is saved, and the profiling data is
977 977 not kept.
978 978 ``kcachegrind``
979 979 Format profiling data for kcachegrind use: when saving to a
980 980 file, the generated file can directly be loaded into
981 981 kcachegrind.
982 982
983 983 ``frequency``
984 984 Sampling frequency. Specific to the ``stat`` sampling profiler.
985 985 Default: 1000.
986 986
987 987 ``output``
988 988 File path where profiling data or report should be saved. If the
989 989 file exists, it is replaced. Default: None, data is printed on
990 990 stderr
991 991
992 992 ``revsetalias``
993 993 """""""""""""""
994 994
995 995 Alias definitions for revsets. See :hg:`help revsets` for details.
996 996
997 997 ``server``
998 998 """"""""""
999 999
1000 1000 Controls generic server settings.
1001 1001
1002 1002 ``uncompressed``
1003 1003 Whether to allow clients to clone a repository using the
1004 1004 uncompressed streaming protocol. This transfers about 40% more
1005 1005 data than a regular clone, but uses less memory and CPU on both
1006 1006 server and client. Over a LAN (100 Mbps or better) or a very fast
1007 1007 WAN, an uncompressed streaming clone is a lot faster (~10x) than a
1008 1008 regular clone. Over most WAN connections (anything slower than
1009 1009 about 6 Mbps), uncompressed streaming is slower, because of the
1010 1010 extra data transfer overhead. This mode will also temporarily hold
1011 1011 the write lock while determining what data to transfer.
1012 1012 Default is True.
1013 1013
1014 1014 ``preferuncompressed``
1015 1015 When set, clients will try to use the uncompressed streaming
1016 1016 protocol. Default is False.
1017 1017
1018 1018 ``validate``
1019 1019 Whether to validate the completeness of pushed changesets by
1020 1020 checking that all new file revisions specified in manifests are
1021 1021 present. Default is False.
1022 1022
1023 1023 ``smtp``
1024 1024 """"""""
1025 1025
1026 1026 Configuration for extensions that need to send email messages.
1027 1027
1028 1028 ``host``
1029 1029 Host name of mail server, e.g. "mail.example.com".
1030 1030
1031 1031 ``port``
1032 1032 Optional. Port to connect to on mail server. Default: 25.
1033 1033
1034 1034 ``tls``
1035 1035 Optional. Method to enable TLS when connecting to mail server: starttls,
1036 1036 smtps or none. Default: none.
1037 1037
1038 1038 ``username``
1039 1039 Optional. User name for authenticating with the SMTP server.
1040 1040 Default: none.
1041 1041
1042 1042 ``password``
1043 1043 Optional. Password for authenticating with the SMTP server. If not
1044 1044 specified, interactive sessions will prompt the user for a
1045 1045 password; non-interactive sessions will fail. Default: none.
1046 1046
1047 1047 ``local_hostname``
1048 1048 Optional. It's the hostname that the sender can use to identify
1049 1049 itself to the MTA.
1050 1050
1051 1051
1052 1052 ``subpaths``
1053 1053 """"""""""""
1054 1054
1055 1055 Subrepository source URLs can go stale if a remote server changes name
1056 1056 or becomes temporarily unavailable. This section lets you define
1057 1057 rewrite rules of the form::
1058 1058
1059 1059 <pattern> = <replacement>
1060 1060
1061 1061 where ``pattern`` is a regular expression matching a subrepository
1062 1062 source URL and ``replacement`` is the replacement string used to
1063 1063 rewrite it. Groups can be matched in ``pattern`` and referenced in
1064 1064 ``replacements``. For instance::
1065 1065
1066 1066 http://server/(.*)-hg/ = http://hg.server/\1/
1067 1067
1068 1068 rewrites ``http://server/foo-hg/`` into ``http://hg.server/foo/``.
1069 1069
1070 1070 Relative subrepository paths are first made absolute, and the the
1071 1071 rewrite rules are then applied on the full (absolute) path. The rules
1072 1072 are applied in definition order.
1073 1073
1074 1074 ``trusted``
1075 1075 """""""""""
1076 1076
1077 1077 Mercurial will not use the settings in the
1078 1078 ``.hg/hgrc`` file from a repository if it doesn't belong to a trusted
1079 1079 user or to a trusted group, as various hgrc features allow arbitrary
1080 1080 commands to be run. This issue is often encountered when configuring
1081 1081 hooks or extensions for shared repositories or servers. However,
1082 1082 the web interface will use some safe settings from the ``[web]``
1083 1083 section.
1084 1084
1085 1085 This section specifies what users and groups are trusted. The
1086 1086 current user is always trusted. To trust everybody, list a user or a
1087 1087 group with name ``*``. These settings must be placed in an
1088 1088 *already-trusted file* to take effect, such as ``$HOME/.hgrc`` of the
1089 1089 user or service running Mercurial.
1090 1090
1091 1091 ``users``
1092 1092 Comma-separated list of trusted users.
1093 1093
1094 1094 ``groups``
1095 1095 Comma-separated list of trusted groups.
1096 1096
1097 1097
1098 1098 ``ui``
1099 1099 """"""
1100 1100
1101 1101 User interface controls.
1102 1102
1103 1103 ``archivemeta``
1104 1104 Whether to include the .hg_archival.txt file containing meta data
1105 1105 (hashes for the repository base and for tip) in archives created
1106 1106 by the :hg:`archive` command or downloaded via hgweb.
1107 1107 Default is True.
1108 1108
1109 1109 ``askusername``
1110 1110 Whether to prompt for a username when committing. If True, and
1111 1111 neither ``$HGUSER`` nor ``$EMAIL`` has been specified, then the user will
1112 1112 be prompted to enter a username. If no username is entered, the
1113 1113 default ``USER@HOST`` is used instead.
1114 1114 Default is False.
1115 1115
1116 1116 ``commitsubrepos``
1117 1117 Whether to commit modified subrepositories when committing the
1118 1118 parent repository. If False and one subrepository has uncommitted
1119 1119 changes, abort the commit.
1120 1120 Default is False.
1121 1121
1122 1122 ``debug``
1123 1123 Print debugging information. True or False. Default is False.
1124 1124
1125 1125 ``editor``
1126 1126 The editor to use during a commit. Default is ``$EDITOR`` or ``vi``.
1127 1127
1128 1128 ``fallbackencoding``
1129 1129 Encoding to try if it's not possible to decode the changelog using
1130 1130 UTF-8. Default is ISO-8859-1.
1131 1131
1132 1132 ``ignore``
1133 1133 A file to read per-user ignore patterns from. This file should be
1134 1134 in the same format as a repository-wide .hgignore file. This
1135 1135 option supports hook syntax, so if you want to specify multiple
1136 1136 ignore files, you can do so by setting something like
1137 1137 ``ignore.other = ~/.hgignore2``. For details of the ignore file
1138 1138 format, see the ``hgignore(5)`` man page.
1139 1139
1140 1140 ``interactive``
1141 1141 Allow to prompt the user. True or False. Default is True.
1142 1142
1143 1143 ``logtemplate``
1144 1144 Template string for commands that print changesets.
1145 1145
1146 1146 ``merge``
1147 1147 The conflict resolution program to use during a manual merge.
1148 1148 For more information on merge tools see :hg:`help merge-tools`.
1149 1149 For configuring merge tools see the ``[merge-tools]`` section.
1150 1150
1151 1151 ``portablefilenames``
1152 1152 Check for portable filenames. Can be ``warn``, ``ignore`` or ``abort``.
1153 1153 Default is ``warn``.
1154 1154 If set to ``warn`` (or ``true``), a warning message is printed on POSIX
1155 1155 platforms, if a file with a non-portable filename is added (e.g. a file
1156 1156 with a name that can't be created on Windows because it contains reserved
1157 1157 parts like ``AUX``, reserved characters like ``:``, or would cause a case
1158 1158 collision with an existing file).
1159 1159 If set to ``ignore`` (or ``false``), no warning is printed.
1160 1160 If set to ``abort``, the command is aborted.
1161 1161 On Windows, this configuration option is ignored and the command aborted.
1162 1162
1163 1163 ``quiet``
1164 1164 Reduce the amount of output printed. True or False. Default is False.
1165 1165
1166 1166 ``remotecmd``
1167 1167 remote command to use for clone/push/pull operations. Default is ``hg``.
1168 1168
1169 1169 ``reportoldssl``
1170 1170 Warn if an SSL certificate is unable to be due to using Python
1171 1171 2.5 or earlier. True or False. Default is True.
1172 1172
1173 1173 ``report_untrusted``
1174 1174 Warn if a ``.hg/hgrc`` file is ignored due to not being owned by a
1175 1175 trusted user or group. True or False. Default is True.
1176 1176
1177 1177 ``slash``
1178 1178 Display paths using a slash (``/``) as the path separator. This
1179 1179 only makes a difference on systems where the default path
1180 1180 separator is not the slash character (e.g. Windows uses the
1181 1181 backslash character (``\``)).
1182 1182 Default is False.
1183 1183
1184 1184 ``ssh``
1185 1185 command to use for SSH connections. Default is ``ssh``.
1186 1186
1187 1187 ``strict``
1188 1188 Require exact command names, instead of allowing unambiguous
1189 1189 abbreviations. True or False. Default is False.
1190 1190
1191 1191 ``style``
1192 1192 Name of style to use for command output.
1193 1193
1194 1194 ``timeout``
1195 1195 The timeout used when a lock is held (in seconds), a negative value
1196 1196 means no timeout. Default is 600.
1197 1197
1198 1198 ``traceback``
1199 1199 Mercurial always prints a traceback when an unknown exception
1200 1200 occurs. Setting this to True will make Mercurial print a traceback
1201 1201 on all exceptions, even those recognized by Mercurial (such as
1202 1202 IOError or MemoryError). Default is False.
1203 1203
1204 1204 ``username``
1205 1205 The committer of a changeset created when running "commit".
1206 1206 Typically a person's name and email address, e.g. ``Fred Widget
1207 1207 <fred@example.com>``. Default is ``$EMAIL`` or ``username@hostname``. If
1208 1208 the username in hgrc is empty, it has to be specified manually or
1209 1209 in a different hgrc file (e.g. ``$HOME/.hgrc``, if the admin set
1210 1210 ``username =`` in the system hgrc). Environment variables in the
1211 1211 username are expanded.
1212 1212
1213 1213 ``verbose``
1214 1214 Increase the amount of output printed. True or False. Default is False.
1215 1215
1216 1216
1217 1217 ``web``
1218 1218 """""""
1219 1219
1220 1220 Web interface configuration. The settings in this section apply to
1221 1221 both the builtin webserver (started by :hg:`serve`) and the script you
1222 1222 run through a webserver (``hgweb.cgi`` and the derivatives for FastCGI
1223 1223 and WSGI).
1224 1224
1225 1225 The Mercurial webserver does no authentication (it does not prompt for
1226 1226 usernames and passwords to validate *who* users are), but it does do
1227 1227 authorization (it grants or denies access for *authenticated users*
1228 1228 based on settings in this section). You must either configure your
1229 1229 webserver to do authentication for you, or disable the authorization
1230 1230 checks.
1231 1231
1232 1232 For a quick setup in a trusted environment, e.g., a private LAN, where
1233 1233 you want it to accept pushes from anybody, you can use the following
1234 1234 command line::
1235 1235
1236 1236 $ hg --config web.allow_push=* --config web.push_ssl=False serve
1237 1237
1238 1238 Note that this will allow anybody to push anything to the server and
1239 1239 that this should not be used for public servers.
1240 1240
1241 1241 The full set of options is:
1242 1242
1243 1243 ``accesslog``
1244 1244 Where to output the access log. Default is stdout.
1245 1245
1246 1246 ``address``
1247 1247 Interface address to bind to. Default is all.
1248 1248
1249 1249 ``allow_archive``
1250 1250 List of archive format (bz2, gz, zip) allowed for downloading.
1251 1251 Default is empty.
1252 1252
1253 1253 ``allowbz2``
1254 1254 (DEPRECATED) Whether to allow .tar.bz2 downloading of repository
1255 1255 revisions.
1256 1256 Default is False.
1257 1257
1258 1258 ``allowgz``
1259 1259 (DEPRECATED) Whether to allow .tar.gz downloading of repository
1260 1260 revisions.
1261 1261 Default is False.
1262 1262
1263 1263 ``allowpull``
1264 1264 Whether to allow pulling from the repository. Default is True.
1265 1265
1266 1266 ``allow_push``
1267 1267 Whether to allow pushing to the repository. If empty or not set,
1268 1268 push is not allowed. If the special value ``*``, any remote user can
1269 1269 push, including unauthenticated users. Otherwise, the remote user
1270 1270 must have been authenticated, and the authenticated user name must
1271 1271 be present in this list. The contents of the allow_push list are
1272 1272 examined after the deny_push list.
1273 1273
1274 1274 ``guessmime``
1275 1275 Control MIME types for raw download of file content.
1276 1276 Set to True to let hgweb guess the content type from the file
1277 1277 extension. This will serve HTML files as ``text/html`` and might
1278 1278 allow cross-site scripting attacks when serving untrusted
1279 1279 repositories. Default is False.
1280 1280
1281 1281 ``allow_read``
1282 1282 If the user has not already been denied repository access due to
1283 1283 the contents of deny_read, this list determines whether to grant
1284 1284 repository access to the user. If this list is not empty, and the
1285 1285 user is unauthenticated or not present in the list, then access is
1286 1286 denied for the user. If the list is empty or not set, then access
1287 1287 is permitted to all users by default. Setting allow_read to the
1288 1288 special value ``*`` is equivalent to it not being set (i.e. access
1289 1289 is permitted to all users). The contents of the allow_read list are
1290 1290 examined after the deny_read list.
1291 1291
1292 1292 ``allowzip``
1293 1293 (DEPRECATED) Whether to allow .zip downloading of repository
1294 1294 revisions. Default is False. This feature creates temporary files.
1295 1295
1296 1296 ``baseurl``
1297 1297 Base URL to use when publishing URLs in other locations, so
1298 1298 third-party tools like email notification hooks can construct
1299 1299 URLs. Example: ``http://hgserver/repos/``.
1300 1300
1301 1301 ``cacerts``
1302 1302 Path to file containing a list of PEM encoded certificate
1303 1303 authority certificates. Environment variables and ``~user``
1304 1304 constructs are expanded in the filename. If specified on the
1305 1305 client, then it will verify the identity of remote HTTPS servers
1306 1306 with these certificates.
1307 1307
1308 1308 This feature is only supported when using Python 2.6 or later. If you wish
1309 1309 to use it with earlier versions of Python, install the backported
1310 1310 version of the ssl library that is available from
1311 1311 ``http://pypi.python.org``.
1312 1312
1313 1313 To disable SSL verification temporarily, specify ``--insecure`` from
1314 1314 command line.
1315 1315
1316 1316 You can use OpenSSL's CA certificate file if your platform has
1317 1317 one. On most Linux systems this will be
1318 1318 ``/etc/ssl/certs/ca-certificates.crt``. Otherwise you will have to
1319 1319 generate this file manually. The form must be as follows::
1320 1320
1321 1321 -----BEGIN CERTIFICATE-----
1322 1322 ... (certificate in base64 PEM encoding) ...
1323 1323 -----END CERTIFICATE-----
1324 1324 -----BEGIN CERTIFICATE-----
1325 1325 ... (certificate in base64 PEM encoding) ...
1326 1326 -----END CERTIFICATE-----
1327 1327
1328 1328 ``cache``
1329 1329 Whether to support caching in hgweb. Defaults to True.
1330 1330
1331 ``collapse``
1332 With ``descend`` enabled, repositories in subdirectories are shown at
1333 a single level alongside repositories in the current path. With
1334 ``collapse`` also enabled, repositories residing at a deeper level than
1335 the current path are grouped behind navigable directory entries that
1336 lead to the locations of these repositories. In effect, this setting
1337 collapses each collection of repositories found within a subdirectory
1338 into a single entry for that subdirectory. Default is False.
1339
1331 1340 ``contact``
1332 1341 Name or email address of the person in charge of the repository.
1333 1342 Defaults to ui.username or ``$EMAIL`` or "unknown" if unset or empty.
1334 1343
1335 1344 ``deny_push``
1336 1345 Whether to deny pushing to the repository. If empty or not set,
1337 1346 push is not denied. If the special value ``*``, all remote users are
1338 1347 denied push. Otherwise, unauthenticated users are all denied, and
1339 1348 any authenticated user name present in this list is also denied. The
1340 1349 contents of the deny_push list are examined before the allow_push list.
1341 1350
1342 1351 ``deny_read``
1343 1352 Whether to deny reading/viewing of the repository. If this list is
1344 1353 not empty, unauthenticated users are all denied, and any
1345 1354 authenticated user name present in this list is also denied access to
1346 1355 the repository. If set to the special value ``*``, all remote users
1347 1356 are denied access (rarely needed ;). If deny_read is empty or not set,
1348 1357 the determination of repository access depends on the presence and
1349 1358 content of the allow_read list (see description). If both
1350 1359 deny_read and allow_read are empty or not set, then access is
1351 1360 permitted to all users by default. If the repository is being
1352 1361 served via hgwebdir, denied users will not be able to see it in
1353 1362 the list of repositories. The contents of the deny_read list have
1354 1363 priority over (are examined before) the contents of the allow_read
1355 1364 list.
1356 1365
1357 1366 ``descend``
1358 1367 hgwebdir indexes will not descend into subdirectories. Only repositories
1359 1368 directly in the current path will be shown (other repositories are still
1360 1369 available from the index corresponding to their containing path).
1361 1370
1362 1371 ``description``
1363 1372 Textual description of the repository's purpose or contents.
1364 1373 Default is "unknown".
1365 1374
1366 1375 ``encoding``
1367 1376 Character encoding name. Default is the current locale charset.
1368 1377 Example: "UTF-8"
1369 1378
1370 1379 ``errorlog``
1371 1380 Where to output the error log. Default is stderr.
1372 1381
1373 1382 ``hidden``
1374 1383 Whether to hide the repository in the hgwebdir index.
1375 1384 Default is False.
1376 1385
1377 1386 ``ipv6``
1378 1387 Whether to use IPv6. Default is False.
1379 1388
1380 1389 ``logoimg``
1381 1390 File name of the logo image that some templates display on each page.
1382 1391 The file name is relative to ``staticurl``. That is, the full path to
1383 1392 the logo image is "staticurl/logoimg".
1384 1393 If unset, ``hglogo.png`` will be used.
1385 1394
1386 1395 ``logourl``
1387 1396 Base URL to use for logos. If unset, ``http://mercurial.selenic.com/``
1388 1397 will be used.
1389 1398
1390 1399 ``name``
1391 1400 Repository name to use in the web interface. Default is current
1392 1401 working directory.
1393 1402
1394 1403 ``maxchanges``
1395 1404 Maximum number of changes to list on the changelog. Default is 10.
1396 1405
1397 1406 ``maxfiles``
1398 1407 Maximum number of files to list per changeset. Default is 10.
1399 1408
1400 1409 ``port``
1401 1410 Port to listen on. Default is 8000.
1402 1411
1403 1412 ``prefix``
1404 1413 Prefix path to serve from. Default is '' (server root).
1405 1414
1406 1415 ``push_ssl``
1407 1416 Whether to require that inbound pushes be transported over SSL to
1408 1417 prevent password sniffing. Default is True.
1409 1418
1410 1419 ``staticurl``
1411 1420 Base URL to use for static files. If unset, static files (e.g. the
1412 1421 hgicon.png favicon) will be served by the CGI script itself. Use
1413 1422 this setting to serve them directly with the HTTP server.
1414 1423 Example: ``http://hgserver/static/``.
1415 1424
1416 1425 ``stripes``
1417 1426 How many lines a "zebra stripe" should span in multiline output.
1418 1427 Default is 1; set to 0 to disable.
1419 1428
1420 1429 ``style``
1421 1430 Which template map style to use.
1422 1431
1423 1432 ``templates``
1424 1433 Where to find the HTML templates. Default is install path.
@@ -1,1195 +1,1186 b''
1 1 /*
2 2 parsers.c - efficient content parsing
3 3
4 4 Copyright 2008 Matt Mackall <mpm@selenic.com> and others
5 5
6 6 This software may be used and distributed according to the terms of
7 7 the GNU General Public License, incorporated herein by reference.
8 8 */
9 9
10 10 #include <Python.h>
11 11 #include <ctype.h>
12 12 #include <string.h>
13 13
14 14 #include "util.h"
15 15
16 16 static int hexdigit(char c)
17 17 {
18 18 if (c >= '0' && c <= '9')
19 19 return c - '0';
20 20 if (c >= 'a' && c <= 'f')
21 21 return c - 'a' + 10;
22 22 if (c >= 'A' && c <= 'F')
23 23 return c - 'A' + 10;
24 24
25 25 PyErr_SetString(PyExc_ValueError, "input contains non-hex character");
26 26 return 0;
27 27 }
28 28
29 29 /*
30 30 * Turn a hex-encoded string into binary.
31 31 */
32 32 static PyObject *unhexlify(const char *str, int len)
33 33 {
34 34 PyObject *ret;
35 35 const char *c;
36 36 char *d;
37 37
38 38 ret = PyBytes_FromStringAndSize(NULL, len / 2);
39 39
40 40 if (!ret)
41 41 return NULL;
42 42
43 43 d = PyBytes_AsString(ret);
44 44
45 45 for (c = str; c < str + len;) {
46 46 int hi = hexdigit(*c++);
47 47 int lo = hexdigit(*c++);
48 48 *d++ = (hi << 4) | lo;
49 49 }
50 50
51 51 return ret;
52 52 }
53 53
54 54 /*
55 55 * This code assumes that a manifest is stitched together with newline
56 56 * ('\n') characters.
57 57 */
58 58 static PyObject *parse_manifest(PyObject *self, PyObject *args)
59 59 {
60 60 PyObject *mfdict, *fdict;
61 61 char *str, *cur, *start, *zero;
62 62 int len;
63 63
64 64 if (!PyArg_ParseTuple(args, "O!O!s#:parse_manifest",
65 65 &PyDict_Type, &mfdict,
66 66 &PyDict_Type, &fdict,
67 67 &str, &len))
68 68 goto quit;
69 69
70 70 for (start = cur = str, zero = NULL; cur < str + len; cur++) {
71 71 PyObject *file = NULL, *node = NULL;
72 72 PyObject *flags = NULL;
73 73 int nlen;
74 74
75 75 if (!*cur) {
76 76 zero = cur;
77 77 continue;
78 78 }
79 79 else if (*cur != '\n')
80 80 continue;
81 81
82 82 if (!zero) {
83 83 PyErr_SetString(PyExc_ValueError,
84 84 "manifest entry has no separator");
85 85 goto quit;
86 86 }
87 87
88 88 file = PyBytes_FromStringAndSize(start, zero - start);
89 89
90 90 if (!file)
91 91 goto bail;
92 92
93 93 nlen = cur - zero - 1;
94 94
95 95 node = unhexlify(zero + 1, nlen > 40 ? 40 : nlen);
96 96 if (!node)
97 97 goto bail;
98 98
99 99 if (nlen > 40) {
100 100 flags = PyBytes_FromStringAndSize(zero + 41,
101 101 nlen - 40);
102 102 if (!flags)
103 103 goto bail;
104 104
105 105 if (PyDict_SetItem(fdict, file, flags) == -1)
106 106 goto bail;
107 107 }
108 108
109 109 if (PyDict_SetItem(mfdict, file, node) == -1)
110 110 goto bail;
111 111
112 112 start = cur + 1;
113 113 zero = NULL;
114 114
115 115 Py_XDECREF(flags);
116 116 Py_XDECREF(node);
117 117 Py_XDECREF(file);
118 118 continue;
119 119 bail:
120 120 Py_XDECREF(flags);
121 121 Py_XDECREF(node);
122 122 Py_XDECREF(file);
123 123 goto quit;
124 124 }
125 125
126 126 if (len > 0 && *(cur - 1) != '\n') {
127 127 PyErr_SetString(PyExc_ValueError,
128 128 "manifest contains trailing garbage");
129 129 goto quit;
130 130 }
131 131
132 132 Py_INCREF(Py_None);
133 133 return Py_None;
134 134 quit:
135 135 return NULL;
136 136 }
137 137
138 138 static PyObject *parse_dirstate(PyObject *self, PyObject *args)
139 139 {
140 140 PyObject *dmap, *cmap, *parents = NULL, *ret = NULL;
141 141 PyObject *fname = NULL, *cname = NULL, *entry = NULL;
142 142 char *str, *cur, *end, *cpos;
143 143 int state, mode, size, mtime;
144 144 unsigned int flen;
145 145 int len;
146 146
147 147 if (!PyArg_ParseTuple(args, "O!O!s#:parse_dirstate",
148 148 &PyDict_Type, &dmap,
149 149 &PyDict_Type, &cmap,
150 150 &str, &len))
151 151 goto quit;
152 152
153 153 /* read parents */
154 154 if (len < 40)
155 155 goto quit;
156 156
157 157 parents = Py_BuildValue("s#s#", str, 20, str + 20, 20);
158 158 if (!parents)
159 159 goto quit;
160 160
161 161 /* read filenames */
162 162 cur = str + 40;
163 163 end = str + len;
164 164
165 165 while (cur < end - 17) {
166 166 /* unpack header */
167 167 state = *cur;
168 168 mode = getbe32(cur + 1);
169 169 size = getbe32(cur + 5);
170 170 mtime = getbe32(cur + 9);
171 171 flen = getbe32(cur + 13);
172 172 cur += 17;
173 173 if (cur + flen > end || cur + flen < cur) {
174 174 PyErr_SetString(PyExc_ValueError, "overflow in dirstate");
175 175 goto quit;
176 176 }
177 177
178 178 entry = Py_BuildValue("ciii", state, mode, size, mtime);
179 179 if (!entry)
180 180 goto quit;
181 181 PyObject_GC_UnTrack(entry); /* don't waste time with this */
182 182
183 183 cpos = memchr(cur, 0, flen);
184 184 if (cpos) {
185 185 fname = PyBytes_FromStringAndSize(cur, cpos - cur);
186 186 cname = PyBytes_FromStringAndSize(cpos + 1,
187 187 flen - (cpos - cur) - 1);
188 188 if (!fname || !cname ||
189 189 PyDict_SetItem(cmap, fname, cname) == -1 ||
190 190 PyDict_SetItem(dmap, fname, entry) == -1)
191 191 goto quit;
192 192 Py_DECREF(cname);
193 193 } else {
194 194 fname = PyBytes_FromStringAndSize(cur, flen);
195 195 if (!fname ||
196 196 PyDict_SetItem(dmap, fname, entry) == -1)
197 197 goto quit;
198 198 }
199 199 cur += flen;
200 200 Py_DECREF(fname);
201 201 Py_DECREF(entry);
202 202 fname = cname = entry = NULL;
203 203 }
204 204
205 205 ret = parents;
206 206 Py_INCREF(ret);
207 207 quit:
208 208 Py_XDECREF(fname);
209 209 Py_XDECREF(cname);
210 210 Py_XDECREF(entry);
211 211 Py_XDECREF(parents);
212 212 return ret;
213 213 }
214 214
215 215 /*
216 216 * A base-16 trie for fast node->rev mapping.
217 217 *
218 218 * Positive value is index of the next node in the trie
219 219 * Negative value is a leaf: -(rev + 1)
220 220 * Zero is empty
221 221 */
222 222 typedef struct {
223 223 int children[16];
224 224 } nodetree;
225 225
226 226 /*
227 227 * This class has two behaviours.
228 228 *
229 229 * When used in a list-like way (with integer keys), we decode an
230 230 * entry in a RevlogNG index file on demand. Our last entry is a
231 231 * sentinel, always a nullid. We have limited support for
232 232 * integer-keyed insert and delete, only at elements right before the
233 233 * sentinel.
234 234 *
235 235 * With string keys, we lazily perform a reverse mapping from node to
236 236 * rev, using a base-16 trie.
237 237 */
238 238 typedef struct {
239 239 PyObject_HEAD
240 240 /* Type-specific fields go here. */
241 241 PyObject *data; /* raw bytes of index */
242 242 PyObject **cache; /* cached tuples */
243 243 const char **offsets; /* populated on demand */
244 244 Py_ssize_t raw_length; /* original number of elements */
245 245 Py_ssize_t length; /* current number of elements */
246 246 PyObject *added; /* populated on demand */
247 247 nodetree *nt; /* base-16 trie */
248 248 int ntlength; /* # nodes in use */
249 249 int ntcapacity; /* # nodes allocated */
250 250 int ntdepth; /* maximum depth of tree */
251 251 int ntsplits; /* # splits performed */
252 252 int ntrev; /* last rev scanned */
253 253 int ntlookups; /* # lookups */
254 254 int ntmisses; /* # lookups that miss the cache */
255 255 int inlined;
256 256 } indexObject;
257 257
258 258 static Py_ssize_t index_length(const indexObject *self)
259 259 {
260 260 if (self->added == NULL)
261 261 return self->length;
262 262 return self->length + PyList_GET_SIZE(self->added);
263 263 }
264 264
265 265 static PyObject *nullentry;
266 266 static const char nullid[20];
267 267
268 268 static long inline_scan(indexObject *self, const char **offsets);
269 269
270 270 #if LONG_MAX == 0x7fffffffL
271 271 static char *tuple_format = "Kiiiiiis#";
272 272 #else
273 273 static char *tuple_format = "kiiiiiis#";
274 274 #endif
275 275
276 276 /*
277 277 * Return a pointer to the beginning of a RevlogNG record.
278 278 */
279 279 static const char *index_deref(indexObject *self, Py_ssize_t pos)
280 280 {
281 281 if (self->inlined && pos > 0) {
282 282 if (self->offsets == NULL) {
283 283 self->offsets = malloc(self->raw_length *
284 284 sizeof(*self->offsets));
285 285 if (self->offsets == NULL)
286 286 return (const char *)PyErr_NoMemory();
287 287 inline_scan(self, self->offsets);
288 288 }
289 289 return self->offsets[pos];
290 290 }
291 291
292 292 return PyString_AS_STRING(self->data) + pos * 64;
293 293 }
294 294
295 295 /*
296 296 * RevlogNG format (all in big endian, data may be inlined):
297 297 * 6 bytes: offset
298 298 * 2 bytes: flags
299 299 * 4 bytes: compressed length
300 300 * 4 bytes: uncompressed length
301 301 * 4 bytes: base revision
302 302 * 4 bytes: link revision
303 303 * 4 bytes: parent 1 revision
304 304 * 4 bytes: parent 2 revision
305 305 * 32 bytes: nodeid (only 20 bytes used)
306 306 */
307 307 static PyObject *index_get(indexObject *self, Py_ssize_t pos)
308 308 {
309 309 uint64_t offset_flags;
310 310 int comp_len, uncomp_len, base_rev, link_rev, parent_1, parent_2;
311 311 const char *c_node_id;
312 312 const char *data;
313 313 Py_ssize_t length = index_length(self);
314 314 PyObject *entry;
315 315
316 316 if (pos < 0)
317 317 pos += length;
318 318
319 319 if (pos < 0 || pos >= length) {
320 320 PyErr_SetString(PyExc_IndexError, "revlog index out of range");
321 321 return NULL;
322 322 }
323 323
324 324 if (pos == length - 1) {
325 325 Py_INCREF(nullentry);
326 326 return nullentry;
327 327 }
328 328
329 329 if (pos >= self->length - 1) {
330 330 PyObject *obj;
331 331 obj = PyList_GET_ITEM(self->added, pos - self->length + 1);
332 332 Py_INCREF(obj);
333 333 return obj;
334 334 }
335 335
336 336 if (self->cache) {
337 337 if (self->cache[pos]) {
338 338 Py_INCREF(self->cache[pos]);
339 339 return self->cache[pos];
340 340 }
341 341 } else {
342 342 self->cache = calloc(self->raw_length, sizeof(PyObject *));
343 343 if (self->cache == NULL)
344 344 return PyErr_NoMemory();
345 345 }
346 346
347 347 data = index_deref(self, pos);
348 348 if (data == NULL)
349 349 return NULL;
350 350
351 351 offset_flags = getbe32(data + 4);
352 352 if (pos == 0) /* mask out version number for the first entry */
353 353 offset_flags &= 0xFFFF;
354 354 else {
355 355 uint32_t offset_high = getbe32(data);
356 356 offset_flags |= ((uint64_t)offset_high) << 32;
357 357 }
358 358
359 359 comp_len = getbe32(data + 8);
360 360 uncomp_len = getbe32(data + 12);
361 361 base_rev = getbe32(data + 16);
362 362 link_rev = getbe32(data + 20);
363 363 parent_1 = getbe32(data + 24);
364 364 parent_2 = getbe32(data + 28);
365 365 c_node_id = data + 32;
366 366
367 367 entry = Py_BuildValue(tuple_format, offset_flags, comp_len,
368 368 uncomp_len, base_rev, link_rev,
369 369 parent_1, parent_2, c_node_id, 20);
370 370
371 371 if (entry)
372 372 PyObject_GC_UnTrack(entry);
373 373
374 374 self->cache[pos] = entry;
375 375 Py_INCREF(entry);
376 376
377 377 return entry;
378 378 }
379 379
380 380 /*
381 381 * Return the 20-byte SHA of the node corresponding to the given rev.
382 382 */
383 383 static const char *index_node(indexObject *self, Py_ssize_t pos)
384 384 {
385 385 Py_ssize_t length = index_length(self);
386 386 const char *data;
387 387
388 388 if (pos == length - 1)
389 389 return nullid;
390 390
391 391 if (pos >= length)
392 392 return NULL;
393 393
394 394 if (pos >= self->length - 1) {
395 395 PyObject *tuple, *str;
396 396 tuple = PyList_GET_ITEM(self->added, pos - self->length + 1);
397 397 str = PyTuple_GetItem(tuple, 7);
398 398 return str ? PyString_AS_STRING(str) : NULL;
399 399 }
400 400
401 401 data = index_deref(self, pos);
402 402 return data ? data + 32 : NULL;
403 403 }
404 404
405 405 static int nt_insert(indexObject *self, const char *node, int rev);
406 406
407 407 static int node_check(PyObject *obj, char **node, Py_ssize_t *nodelen)
408 408 {
409 409 if (PyString_AsStringAndSize(obj, node, nodelen) == -1)
410 410 return -1;
411 411 if (*nodelen == 20)
412 412 return 0;
413 413 PyErr_SetString(PyExc_ValueError, "20-byte hash required");
414 414 return -1;
415 415 }
416 416
417 417 static PyObject *index_insert(indexObject *self, PyObject *args)
418 418 {
419 419 PyObject *obj;
420 420 char *node;
421 421 long offset;
422 422 Py_ssize_t len, nodelen;
423 423
424 424 if (!PyArg_ParseTuple(args, "lO", &offset, &obj))
425 425 return NULL;
426 426
427 427 if (!PyTuple_Check(obj) || PyTuple_GET_SIZE(obj) != 8) {
428 428 PyErr_SetString(PyExc_TypeError, "8-tuple required");
429 429 return NULL;
430 430 }
431 431
432 432 if (node_check(PyTuple_GET_ITEM(obj, 7), &node, &nodelen) == -1)
433 433 return NULL;
434 434
435 435 len = index_length(self);
436 436
437 437 if (offset < 0)
438 438 offset += len;
439 439
440 440 if (offset != len - 1) {
441 441 PyErr_SetString(PyExc_IndexError,
442 442 "insert only supported at index -1");
443 443 return NULL;
444 444 }
445 445
446 446 if (offset > INT_MAX) {
447 447 PyErr_SetString(PyExc_ValueError,
448 448 "currently only 2**31 revs supported");
449 449 return NULL;
450 450 }
451 451
452 452 if (self->added == NULL) {
453 453 self->added = PyList_New(0);
454 454 if (self->added == NULL)
455 455 return NULL;
456 456 }
457 457
458 458 if (PyList_Append(self->added, obj) == -1)
459 459 return NULL;
460 460
461 461 if (self->nt)
462 462 nt_insert(self, node, (int)offset);
463 463
464 464 Py_RETURN_NONE;
465 465 }
466 466
467 467 static void _index_clearcaches(indexObject *self)
468 468 {
469 469 if (self->cache) {
470 470 Py_ssize_t i;
471 471
472 472 for (i = 0; i < self->raw_length; i++) {
473 Py_XDECREF(self->cache[i]);
473 if (self->cache[i]) {
474 Py_DECREF(self->cache[i]);
474 475 self->cache[i] = NULL;
475 476 }
477 }
476 478 free(self->cache);
477 479 self->cache = NULL;
478 480 }
479 481 if (self->offsets) {
480 482 free(self->offsets);
481 483 self->offsets = NULL;
482 484 }
483 485 if (self->nt) {
484 486 free(self->nt);
485 487 self->nt = NULL;
486 488 }
487 489 }
488 490
489 491 static PyObject *index_clearcaches(indexObject *self)
490 492 {
491 493 _index_clearcaches(self);
492 494 self->ntlength = self->ntcapacity = 0;
493 495 self->ntdepth = self->ntsplits = 0;
494 496 self->ntrev = -1;
495 497 self->ntlookups = self->ntmisses = 0;
496 498 Py_RETURN_NONE;
497 499 }
498 500
499 501 static PyObject *index_stats(indexObject *self)
500 502 {
501 503 PyObject *obj = PyDict_New();
502 504
503 505 if (obj == NULL)
504 506 return NULL;
505 507
506 508 #define istat(__n, __d) \
507 509 if (PyDict_SetItemString(obj, __d, PyInt_FromLong(self->__n)) == -1) \
508 510 goto bail;
509 511
510 512 if (self->added) {
511 513 Py_ssize_t len = PyList_GET_SIZE(self->added);
512 514 if (PyDict_SetItemString(obj, "index entries added",
513 515 PyInt_FromLong(len)) == -1)
514 516 goto bail;
515 517 }
516 518
517 519 if (self->raw_length != self->length - 1)
518 520 istat(raw_length, "revs on disk");
519 521 istat(length, "revs in memory");
520 522 istat(ntcapacity, "node trie capacity");
521 523 istat(ntdepth, "node trie depth");
522 524 istat(ntlength, "node trie count");
523 525 istat(ntlookups, "node trie lookups");
524 526 istat(ntmisses, "node trie misses");
525 527 istat(ntrev, "node trie last rev scanned");
526 528 istat(ntsplits, "node trie splits");
527 529
528 530 #undef istat
529 531
530 532 return obj;
531 533
532 534 bail:
533 535 Py_XDECREF(obj);
534 536 return NULL;
535 537 }
536 538
537 539 static inline int nt_level(const char *node, int level)
538 540 {
539 541 int v = node[level>>1];
540 542 if (!(level & 1))
541 543 v >>= 4;
542 544 return v & 0xf;
543 545 }
544 546
545 547 static int nt_find(indexObject *self, const char *node, Py_ssize_t nodelen)
546 548 {
547 549 int level, off;
548 550
549 551 if (nodelen == 20 && node[0] == '\0' && memcmp(node, nullid, 20) == 0)
550 552 return -1;
551 553
552 554 if (self->nt == NULL)
553 555 return -2;
554 556
555 557 for (level = off = 0; level < nodelen; level++) {
556 558 int k = nt_level(node, level);
557 559 nodetree *n = &self->nt[off];
558 560 int v = n->children[k];
559 561
560 562 if (v < 0) {
561 563 const char *n;
562 564 v = -v - 1;
563 565 n = index_node(self, v);
564 566 if (n == NULL)
565 567 return -2;
566 568 return memcmp(node, n, nodelen > 20 ? 20 : nodelen)
567 569 ? -2 : v;
568 570 }
569 571 if (v == 0)
570 572 return -2;
571 573 off = v;
572 574 }
573 575 return -2;
574 576 }
575 577
576 578 static int nt_new(indexObject *self)
577 579 {
578 580 if (self->ntlength == self->ntcapacity) {
579 581 self->ntcapacity *= 2;
580 582 self->nt = realloc(self->nt,
581 583 self->ntcapacity * sizeof(nodetree));
582 584 if (self->nt == NULL) {
583 585 PyErr_SetString(PyExc_MemoryError, "out of memory");
584 586 return -1;
585 587 }
586 588 memset(&self->nt[self->ntlength], 0,
587 589 sizeof(nodetree) * (self->ntcapacity - self->ntlength));
588 590 }
589 591 return self->ntlength++;
590 592 }
591 593
592 594 static int nt_insert(indexObject *self, const char *node, int rev)
593 595 {
594 596 int level = 0;
595 597 int off = 0;
596 598
597 599 while (level < 20) {
598 600 int k = nt_level(node, level);
599 601 nodetree *n;
600 602 int v;
601 603
602 604 n = &self->nt[off];
603 605 v = n->children[k];
604 606
605 607 if (v == 0) {
606 608 n->children[k] = -rev - 1;
607 609 return 0;
608 610 }
609 611 if (v < 0) {
610 612 const char *oldnode = index_node(self, -v - 1);
611 613 int noff;
612 614
613 615 if (!oldnode || !memcmp(oldnode, node, 20)) {
614 616 n->children[k] = -rev - 1;
615 617 return 0;
616 618 }
617 619 noff = nt_new(self);
618 620 if (noff == -1)
619 621 return -1;
620 622 /* self->nt may have been changed by realloc */
621 623 self->nt[off].children[k] = noff;
622 624 off = noff;
623 625 n = &self->nt[off];
624 626 n->children[nt_level(oldnode, ++level)] = v;
625 627 if (level > self->ntdepth)
626 628 self->ntdepth = level;
627 629 self->ntsplits += 1;
628 630 } else {
629 631 level += 1;
630 632 off = v;
631 633 }
632 634 }
633 635
634 636 return -1;
635 637 }
636 638
637 639 /*
638 640 * Return values:
639 641 *
640 642 * -3: error (exception set)
641 643 * -2: not found (no exception set)
642 644 * rest: valid rev
643 645 */
644 646 static int index_find_node(indexObject *self,
645 647 const char *node, Py_ssize_t nodelen)
646 648 {
647 649 int rev;
648 650
649 651 self->ntlookups++;
650 652 rev = nt_find(self, node, nodelen);
651 653 if (rev >= -1)
652 654 return rev;
653 655
654 656 if (self->nt == NULL) {
655 657 self->ntcapacity = self->raw_length < 4
656 658 ? 4 : self->raw_length / 2;
657 659 self->nt = calloc(self->ntcapacity, sizeof(nodetree));
658 660 if (self->nt == NULL) {
659 661 PyErr_SetString(PyExc_MemoryError, "out of memory");
660 662 return -3;
661 663 }
662 664 self->ntlength = 1;
663 665 self->ntrev = (int)index_length(self) - 1;
664 666 self->ntlookups = 1;
665 667 self->ntmisses = 0;
666 668 }
667 669
668 670 /*
669 671 * For the first handful of lookups, we scan the entire index,
670 672 * and cache only the matching nodes. This optimizes for cases
671 673 * like "hg tip", where only a few nodes are accessed.
672 674 *
673 675 * After that, we cache every node we visit, using a single
674 676 * scan amortized over multiple lookups. This gives the best
675 677 * bulk performance, e.g. for "hg log".
676 678 */
677 679 if (self->ntmisses++ < 4) {
678 680 for (rev = self->ntrev - 1; rev >= 0; rev--) {
679 681 const char *n = index_node(self, rev);
680 682 if (n == NULL)
681 683 return -2;
682 684 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
683 685 if (nt_insert(self, n, rev) == -1)
684 686 return -3;
685 687 break;
686 688 }
687 689 }
688 690 } else {
689 691 for (rev = self->ntrev - 1; rev >= 0; rev--) {
690 692 const char *n = index_node(self, rev);
691 693 if (n == NULL)
692 694 return -2;
693 695 if (nt_insert(self, n, rev) == -1)
694 696 return -3;
695 697 if (memcmp(node, n, nodelen > 20 ? 20 : nodelen) == 0) {
696 698 break;
697 699 }
698 700 }
699 701 self->ntrev = rev;
700 702 }
701 703
702 704 if (rev >= 0)
703 705 return rev;
704 706 return -2;
705 707 }
706 708
707 709 static PyObject *raise_revlog_error(void)
708 710 {
709 711 static PyObject *errclass;
710 712 PyObject *mod = NULL, *errobj;
711 713
712 714 if (errclass == NULL) {
713 715 PyObject *dict;
714 716
715 717 mod = PyImport_ImportModule("mercurial.error");
716 718 if (mod == NULL)
717 719 goto classfail;
718 720
719 721 dict = PyModule_GetDict(mod);
720 722 if (dict == NULL)
721 723 goto classfail;
722 724
723 725 errclass = PyDict_GetItemString(dict, "RevlogError");
724 726 if (errclass == NULL) {
725 727 PyErr_SetString(PyExc_SystemError,
726 728 "could not find RevlogError");
727 729 goto classfail;
728 730 }
729 731 Py_INCREF(errclass);
730 732 }
731 733
732 734 errobj = PyObject_CallFunction(errclass, NULL);
733 735 if (errobj == NULL)
734 736 return NULL;
735 737 PyErr_SetObject(errclass, errobj);
736 738 return errobj;
737 739
738 740 classfail:
739 741 Py_XDECREF(mod);
740 742 return NULL;
741 743 }
742 744
743 745 static PyObject *index_getitem(indexObject *self, PyObject *value)
744 746 {
745 747 char *node;
746 748 Py_ssize_t nodelen;
747 749 int rev;
748 750
749 751 if (PyInt_Check(value))
750 752 return index_get(self, PyInt_AS_LONG(value));
751 753
752 754 if (PyString_AsStringAndSize(value, &node, &nodelen) == -1)
753 755 return NULL;
754 756 rev = index_find_node(self, node, nodelen);
755 757 if (rev >= -1)
756 758 return PyInt_FromLong(rev);
757 759 if (rev == -2)
758 760 raise_revlog_error();
759 761 return NULL;
760 762 }
761 763
762 764 static PyObject *index_m_get(indexObject *self, PyObject *args)
763 765 {
764 766 char *node;
765 767 int nodelen, rev;
766 768
767 769 if (!PyArg_ParseTuple(args, "s#", &node, &nodelen))
768 770 return NULL;
769 771
770 772 rev = index_find_node(self, node, nodelen);
771 773 if (rev == -3)
772 774 return NULL;
773 775 if (rev == -2)
774 776 Py_RETURN_NONE;
775 777 return PyInt_FromLong(rev);
776 778 }
777 779
778 780 static int index_contains(indexObject *self, PyObject *value)
779 781 {
780 782 char *node;
781 783 Py_ssize_t nodelen;
782 784
783 785 if (PyInt_Check(value)) {
784 786 long rev = PyInt_AS_LONG(value);
785 787 return rev >= -1 && rev < index_length(self);
786 788 }
787 789
788 790 if (!PyString_Check(value))
789 791 return 0;
790 792
791 793 node = PyString_AS_STRING(value);
792 794 nodelen = PyString_GET_SIZE(value);
793 795
794 796 switch (index_find_node(self, node, nodelen)) {
795 797 case -3:
796 798 return -1;
797 799 case -2:
798 800 return 0;
799 801 default:
800 802 return 1;
801 803 }
802 804 }
803 805
804 806 /*
805 807 * Invalidate any trie entries introduced by added revs.
806 808 */
807 809 static void nt_invalidate_added(indexObject *self, Py_ssize_t start)
808 810 {
809 811 Py_ssize_t i, len = PyList_GET_SIZE(self->added);
810 812
811 813 for (i = start; i < len; i++) {
812 814 PyObject *tuple = PyList_GET_ITEM(self->added, i);
813 815 PyObject *node = PyTuple_GET_ITEM(tuple, 7);
814 816
815 817 nt_insert(self, PyString_AS_STRING(node), -1);
816 818 }
817 819
818 820 if (start == 0) {
819 821 Py_DECREF(self->added);
820 822 self->added = NULL;
821 823 }
822 824 }
823 825
824 826 /*
825 827 * Delete a numeric range of revs, which must be at the end of the
826 828 * range, but exclude the sentinel nullid entry.
827 829 */
828 830 static int index_slice_del(indexObject *self, PyObject *item)
829 831 {
830 832 Py_ssize_t start, stop, step, slicelength;
831 833 Py_ssize_t length = index_length(self);
832 834
833 835 if (PySlice_GetIndicesEx((PySliceObject*)item, length,
834 836 &start, &stop, &step, &slicelength) < 0)
835 837 return -1;
836 838
837 839 if (slicelength <= 0)
838 840 return 0;
839 841
840 842 if ((step < 0 && start < stop) || (step > 0 && start > stop))
841 843 stop = start;
842 844
843 845 if (step < 0) {
844 846 stop = start + 1;
845 847 start = stop + step*(slicelength - 1) - 1;
846 848 step = -step;
847 849 }
848 850
849 851 if (step != 1) {
850 852 PyErr_SetString(PyExc_ValueError,
851 853 "revlog index delete requires step size of 1");
852 854 return -1;
853 855 }
854 856
855 857 if (stop != length - 1) {
856 858 PyErr_SetString(PyExc_IndexError,
857 859 "revlog index deletion indices are invalid");
858 860 return -1;
859 861 }
860 862
861 863 if (start < self->length - 1) {
862 864 if (self->nt) {
863 865 Py_ssize_t i;
864 866
865 867 for (i = start + 1; i < self->length - 1; i++) {
866 868 const char *node = index_node(self, i);
867 869
868 870 if (node)
869 871 nt_insert(self, node, -1);
870 872 }
871 873 if (self->added)
872 874 nt_invalidate_added(self, 0);
873 875 if (self->ntrev > start)
874 876 self->ntrev = (int)start;
875 877 }
876 878 self->length = start + 1;
877 879 return 0;
878 880 }
879 881
880 882 if (self->nt) {
881 883 nt_invalidate_added(self, start - self->length + 1);
882 884 if (self->ntrev > start)
883 885 self->ntrev = (int)start;
884 886 }
885 887 return self->added
886 888 ? PyList_SetSlice(self->added, start - self->length + 1,
887 889 PyList_GET_SIZE(self->added), NULL)
888 890 : 0;
889 891 }
890 892
891 893 /*
892 894 * Supported ops:
893 895 *
894 896 * slice deletion
895 897 * string assignment (extend node->rev mapping)
896 898 * string deletion (shrink node->rev mapping)
897 899 */
898 900 static int index_assign_subscript(indexObject *self, PyObject *item,
899 901 PyObject *value)
900 902 {
901 903 char *node;
902 904 Py_ssize_t nodelen;
903 905 long rev;
904 906
905 907 if (PySlice_Check(item) && value == NULL)
906 908 return index_slice_del(self, item);
907 909
908 910 if (node_check(item, &node, &nodelen) == -1)
909 911 return -1;
910 912
911 913 if (value == NULL)
912 914 return self->nt ? nt_insert(self, node, -1) : 0;
913 915 rev = PyInt_AsLong(value);
914 916 if (rev > INT_MAX || rev < 0) {
915 917 if (!PyErr_Occurred())
916 918 PyErr_SetString(PyExc_ValueError, "rev out of range");
917 919 return -1;
918 920 }
919 921 return nt_insert(self, node, (int)rev);
920 922 }
921 923
922 924 /*
923 925 * Find all RevlogNG entries in an index that has inline data. Update
924 926 * the optional "offsets" table with those entries.
925 927 */
926 928 static long inline_scan(indexObject *self, const char **offsets)
927 929 {
928 930 const char *data = PyString_AS_STRING(self->data);
929 931 const char *end = data + PyString_GET_SIZE(self->data);
930 932 const long hdrsize = 64;
931 933 long incr = hdrsize;
932 934 Py_ssize_t len = 0;
933 935
934 936 while (data + hdrsize <= end) {
935 937 uint32_t comp_len;
936 938 const char *old_data;
937 939 /* 3rd element of header is length of compressed inline data */
938 940 comp_len = getbe32(data + 8);
939 941 incr = hdrsize + comp_len;
940 942 if (incr < hdrsize)
941 943 break;
942 944 if (offsets)
943 945 offsets[len] = data;
944 946 len++;
945 947 old_data = data;
946 948 data += incr;
947 949 if (data <= old_data)
948 950 break;
949 951 }
950 952
951 953 if (data != end && data + hdrsize != end) {
952 954 if (!PyErr_Occurred())
953 955 PyErr_SetString(PyExc_ValueError, "corrupt index file");
954 956 return -1;
955 957 }
956 958
957 959 return len;
958 960 }
959 961
960 static int index_real_init(indexObject *self, const char *data, int size,
961 PyObject *inlined_obj, PyObject *data_obj)
962 static int index_init(indexObject *self, PyObject *args)
962 963 {
964 PyObject *data_obj, *inlined_obj;
965 Py_ssize_t size;
966
967 if (!PyArg_ParseTuple(args, "OO", &data_obj, &inlined_obj))
968 return -1;
969 if (!PyString_Check(data_obj)) {
970 PyErr_SetString(PyExc_TypeError, "data is not a string");
971 return -1;
972 }
973 size = PyString_GET_SIZE(data_obj);
974
963 975 self->inlined = inlined_obj && PyObject_IsTrue(inlined_obj);
964 976 self->data = data_obj;
965 977 self->cache = NULL;
966 978
967 979 self->added = NULL;
968 980 self->offsets = NULL;
969 981 self->nt = NULL;
970 982 self->ntlength = self->ntcapacity = 0;
971 983 self->ntdepth = self->ntsplits = 0;
972 984 self->ntlookups = self->ntmisses = 0;
973 985 self->ntrev = -1;
974 Py_INCREF(self->data);
975 986
976 987 if (self->inlined) {
977 988 long len = inline_scan(self, NULL);
978 989 if (len == -1)
979 990 goto bail;
980 991 self->raw_length = len;
981 992 self->length = len + 1;
982 993 } else {
983 994 if (size % 64) {
984 995 PyErr_SetString(PyExc_ValueError, "corrupt index file");
985 996 goto bail;
986 997 }
987 998 self->raw_length = size / 64;
988 999 self->length = self->raw_length + 1;
989 1000 }
1001 Py_INCREF(self->data);
990 1002
991 1003 return 0;
992 1004 bail:
993 1005 return -1;
994 1006 }
995 1007
996 static int index_init(indexObject *self, PyObject *args, PyObject *kwds)
997 {
998 const char *data;
999 int size;
1000 PyObject *inlined_obj;
1001
1002 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
1003 return -1;
1004
1005 return index_real_init(self, data, size, inlined_obj,
1006 PyTuple_GET_ITEM(args, 0));
1007 }
1008
1009 1008 static PyObject *index_nodemap(indexObject *self)
1010 1009 {
1010 Py_INCREF(self);
1011 1011 return (PyObject *)self;
1012 1012 }
1013 1013
1014 1014 static void index_dealloc(indexObject *self)
1015 1015 {
1016 1016 _index_clearcaches(self);
1017 1017 Py_DECREF(self->data);
1018 1018 Py_XDECREF(self->added);
1019 1019 PyObject_Del(self);
1020 1020 }
1021 1021
1022 1022 static PySequenceMethods index_sequence_methods = {
1023 1023 (lenfunc)index_length, /* sq_length */
1024 1024 0, /* sq_concat */
1025 1025 0, /* sq_repeat */
1026 1026 (ssizeargfunc)index_get, /* sq_item */
1027 1027 0, /* sq_slice */
1028 1028 0, /* sq_ass_item */
1029 1029 0, /* sq_ass_slice */
1030 1030 (objobjproc)index_contains, /* sq_contains */
1031 1031 };
1032 1032
1033 1033 static PyMappingMethods index_mapping_methods = {
1034 1034 (lenfunc)index_length, /* mp_length */
1035 1035 (binaryfunc)index_getitem, /* mp_subscript */
1036 1036 (objobjargproc)index_assign_subscript, /* mp_ass_subscript */
1037 1037 };
1038 1038
1039 1039 static PyMethodDef index_methods[] = {
1040 1040 {"clearcaches", (PyCFunction)index_clearcaches, METH_NOARGS,
1041 1041 "clear the index caches"},
1042 1042 {"get", (PyCFunction)index_m_get, METH_VARARGS,
1043 1043 "get an index entry"},
1044 1044 {"insert", (PyCFunction)index_insert, METH_VARARGS,
1045 1045 "insert an index entry"},
1046 1046 {"stats", (PyCFunction)index_stats, METH_NOARGS,
1047 1047 "stats for the index"},
1048 1048 {NULL} /* Sentinel */
1049 1049 };
1050 1050
1051 1051 static PyGetSetDef index_getset[] = {
1052 1052 {"nodemap", (getter)index_nodemap, NULL, "nodemap", NULL},
1053 1053 {NULL} /* Sentinel */
1054 1054 };
1055 1055
1056 1056 static PyTypeObject indexType = {
1057 1057 PyObject_HEAD_INIT(NULL)
1058 1058 0, /* ob_size */
1059 1059 "parsers.index", /* tp_name */
1060 1060 sizeof(indexObject), /* tp_basicsize */
1061 1061 0, /* tp_itemsize */
1062 1062 (destructor)index_dealloc, /* tp_dealloc */
1063 1063 0, /* tp_print */
1064 1064 0, /* tp_getattr */
1065 1065 0, /* tp_setattr */
1066 1066 0, /* tp_compare */
1067 1067 0, /* tp_repr */
1068 1068 0, /* tp_as_number */
1069 1069 &index_sequence_methods, /* tp_as_sequence */
1070 1070 &index_mapping_methods, /* tp_as_mapping */
1071 1071 0, /* tp_hash */
1072 1072 0, /* tp_call */
1073 1073 0, /* tp_str */
1074 1074 0, /* tp_getattro */
1075 1075 0, /* tp_setattro */
1076 1076 0, /* tp_as_buffer */
1077 1077 Py_TPFLAGS_DEFAULT, /* tp_flags */
1078 1078 "revlog index", /* tp_doc */
1079 1079 0, /* tp_traverse */
1080 1080 0, /* tp_clear */
1081 1081 0, /* tp_richcompare */
1082 1082 0, /* tp_weaklistoffset */
1083 1083 0, /* tp_iter */
1084 1084 0, /* tp_iternext */
1085 1085 index_methods, /* tp_methods */
1086 1086 0, /* tp_members */
1087 1087 index_getset, /* tp_getset */
1088 1088 0, /* tp_base */
1089 1089 0, /* tp_dict */
1090 1090 0, /* tp_descr_get */
1091 1091 0, /* tp_descr_set */
1092 1092 0, /* tp_dictoffset */
1093 1093 (initproc)index_init, /* tp_init */
1094 1094 0, /* tp_alloc */
1095 1095 PyType_GenericNew, /* tp_new */
1096 1096 };
1097 1097
1098 1098 /*
1099 1099 * returns a tuple of the form (index, index, cache) with elements as
1100 1100 * follows:
1101 1101 *
1102 1102 * index: an index object that lazily parses RevlogNG records
1103 1103 * cache: if data is inlined, a tuple (index_file_content, 0), else None
1104 1104 *
1105 1105 * added complications are for backwards compatibility
1106 1106 */
1107 1107 static PyObject *parse_index2(PyObject *self, PyObject *args)
1108 1108 {
1109 const char *data;
1110 int size, ret;
1111 PyObject *inlined_obj, *tuple = NULL, *cache = NULL;
1109 PyObject *tuple = NULL, *cache = NULL;
1112 1110 indexObject *idx;
1113
1114 if (!PyArg_ParseTuple(args, "s#O", &data, &size, &inlined_obj))
1115 return NULL;
1111 int ret;
1116 1112
1117 1113 idx = PyObject_New(indexObject, &indexType);
1118
1119 1114 if (idx == NULL)
1120 1115 goto bail;
1121 1116
1122 ret = index_real_init(idx, data, size, inlined_obj,
1123 PyTuple_GET_ITEM(args, 0));
1124 if (ret)
1117 ret = index_init(idx, args);
1118 if (ret == -1)
1125 1119 goto bail;
1126 1120
1127 1121 if (idx->inlined) {
1128 Py_INCREF(idx->data);
1129 1122 cache = Py_BuildValue("iO", 0, idx->data);
1130 1123 if (cache == NULL)
1131 1124 goto bail;
1132 1125 } else {
1133 1126 cache = Py_None;
1134 1127 Py_INCREF(cache);
1135 1128 }
1136 1129
1137 Py_INCREF(idx);
1138
1139 1130 tuple = Py_BuildValue("NN", idx, cache);
1140 1131 if (!tuple)
1141 1132 goto bail;
1142 1133 return tuple;
1143 1134
1144 1135 bail:
1145 1136 Py_XDECREF(idx);
1146 1137 Py_XDECREF(cache);
1147 1138 Py_XDECREF(tuple);
1148 1139 return NULL;
1149 1140 }
1150 1141
1151 1142 static char parsers_doc[] = "Efficient content parsing.";
1152 1143
1153 1144 static PyMethodDef methods[] = {
1154 1145 {"parse_manifest", parse_manifest, METH_VARARGS, "parse a manifest\n"},
1155 1146 {"parse_dirstate", parse_dirstate, METH_VARARGS, "parse a dirstate\n"},
1156 1147 {"parse_index2", parse_index2, METH_VARARGS, "parse a revlog index\n"},
1157 1148 {NULL, NULL}
1158 1149 };
1159 1150
1160 1151 static void module_init(PyObject *mod)
1161 1152 {
1162 1153 if (PyType_Ready(&indexType) < 0)
1163 1154 return;
1164 1155 Py_INCREF(&indexType);
1165 1156
1166 1157 PyModule_AddObject(mod, "index", (PyObject *)&indexType);
1167 1158
1168 1159 nullentry = Py_BuildValue("iiiiiiis#", 0, 0, 0,
1169 1160 -1, -1, -1, -1, nullid, 20);
1170 1161 if (nullentry)
1171 1162 PyObject_GC_UnTrack(nullentry);
1172 1163 }
1173 1164
1174 1165 #ifdef IS_PY3K
1175 1166 static struct PyModuleDef parsers_module = {
1176 1167 PyModuleDef_HEAD_INIT,
1177 1168 "parsers",
1178 1169 parsers_doc,
1179 1170 -1,
1180 1171 methods
1181 1172 };
1182 1173
1183 1174 PyMODINIT_FUNC PyInit_parsers(void)
1184 1175 {
1185 1176 PyObject *mod = PyModule_Create(&parsers_module);
1186 1177 module_init(mod);
1187 1178 return mod;
1188 1179 }
1189 1180 #else
1190 1181 PyMODINIT_FUNC initparsers(void)
1191 1182 {
1192 1183 PyObject *mod = Py_InitModule3("parsers", methods, parsers_doc);
1193 1184 module_init(mod);
1194 1185 }
1195 1186 #endif
@@ -1,373 +1,378 b''
1 1 $ hg init
2 2
3 3 no bookmarks
4 4
5 5 $ hg bookmarks
6 6 no bookmarks set
7 7
8 8 bookmark rev -1
9 9
10 10 $ hg bookmark X
11 11
12 12 list bookmarks
13 13
14 14 $ hg bookmarks
15 15 * X -1:000000000000
16 16
17 17 list bookmarks with color
18 18
19 19 $ hg --config extensions.color= --config color.mode=ansi \
20 20 > bookmarks --color=always
21 21 \x1b[0;32m * X -1:000000000000\x1b[0m (esc)
22 22
23 23 $ echo a > a
24 24 $ hg add a
25 25 $ hg commit -m 0
26 26
27 27 bookmark X moved to rev 0
28 28
29 29 $ hg bookmarks
30 30 * X 0:f7b1eb17ad24
31 31
32 32 look up bookmark
33 33
34 34 $ hg log -r X
35 35 changeset: 0:f7b1eb17ad24
36 36 bookmark: X
37 37 tag: tip
38 38 user: test
39 39 date: Thu Jan 01 00:00:00 1970 +0000
40 40 summary: 0
41 41
42 42
43 43 second bookmark for rev 0
44 44
45 45 $ hg bookmark X2
46 46
47 47 bookmark rev -1 again
48 48
49 49 $ hg bookmark -r null Y
50 50
51 51 list bookmarks
52 52
53 53 $ hg bookmarks
54 54 X 0:f7b1eb17ad24
55 55 * X2 0:f7b1eb17ad24
56 56 Y -1:000000000000
57 57
58 58 $ echo b > b
59 59 $ hg add b
60 60 $ hg commit -m 1
61 61
62 62 bookmarks revset
63 63
64 64 $ hg log -r 'bookmark()'
65 65 changeset: 0:f7b1eb17ad24
66 66 bookmark: X
67 67 user: test
68 68 date: Thu Jan 01 00:00:00 1970 +0000
69 69 summary: 0
70 70
71 71 changeset: 1:925d80f479bb
72 72 bookmark: X2
73 73 tag: tip
74 74 user: test
75 75 date: Thu Jan 01 00:00:00 1970 +0000
76 76 summary: 1
77 77
78 78 $ hg log -r 'bookmark(Y)'
79 79 $ hg log -r 'bookmark(X2)'
80 80 changeset: 1:925d80f479bb
81 81 bookmark: X2
82 82 tag: tip
83 83 user: test
84 84 date: Thu Jan 01 00:00:00 1970 +0000
85 85 summary: 1
86 86
87 87 $ hg log -r 'bookmark(unknown)'
88 88 abort: bookmark 'unknown' does not exist
89 89 [255]
90 90
91 91 $ hg help revsets | grep 'bookmark('
92 92 "bookmark([name])"
93 93
94 94 bookmarks X and X2 moved to rev 1, Y at rev -1
95 95
96 96 $ hg bookmarks
97 97 X 0:f7b1eb17ad24
98 98 * X2 1:925d80f479bb
99 99 Y -1:000000000000
100 100
101 101 bookmark rev 0 again
102 102
103 103 $ hg bookmark -r 0 Z
104 104
105 105 $ hg update X
106 106 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
107 107 $ echo c > c
108 108 $ hg add c
109 109 $ hg commit -m 2
110 110 created new head
111 111
112 112 bookmarks X moved to rev 2, Y at rev -1, Z at rev 0
113 113
114 114 $ hg bookmarks
115 115 * X 2:db815d6d32e6
116 116 X2 1:925d80f479bb
117 117 Y -1:000000000000
118 118 Z 0:f7b1eb17ad24
119 119
120 120 rename nonexistent bookmark
121 121
122 122 $ hg bookmark -m A B
123 123 abort: bookmark 'A' does not exist
124 124 [255]
125 125
126 126 rename to existent bookmark
127 127
128 128 $ hg bookmark -m X Y
129 129 abort: bookmark 'Y' already exists (use -f to force)
130 130 [255]
131 131
132 132 force rename to existent bookmark
133 133
134 134 $ hg bookmark -f -m X Y
135 135
136 136 list bookmarks
137 137
138 138 $ hg bookmark
139 139 X2 1:925d80f479bb
140 140 * Y 2:db815d6d32e6
141 141 Z 0:f7b1eb17ad24
142 142
143 143 rename without new name
144 144
145 145 $ hg bookmark -m Y
146 146 abort: new bookmark name required
147 147 [255]
148 148
149 149 delete without name
150 150
151 151 $ hg bookmark -d
152 152 abort: bookmark name required
153 153 [255]
154 154
155 155 delete nonexistent bookmark
156 156
157 157 $ hg bookmark -d A
158 158 abort: bookmark 'A' does not exist
159 159 [255]
160 160
161 161 bookmark name with spaces should be stripped
162 162
163 163 $ hg bookmark ' x y '
164 164
165 165 list bookmarks
166 166
167 167 $ hg bookmarks
168 168 X2 1:925d80f479bb
169 169 Y 2:db815d6d32e6
170 170 Z 0:f7b1eb17ad24
171 171 * x y 2:db815d6d32e6
172 172
173 173 look up stripped bookmark name
174 174
175 175 $ hg log -r '"x y"'
176 176 changeset: 2:db815d6d32e6
177 177 bookmark: Y
178 178 bookmark: x y
179 179 tag: tip
180 180 parent: 0:f7b1eb17ad24
181 181 user: test
182 182 date: Thu Jan 01 00:00:00 1970 +0000
183 183 summary: 2
184 184
185 185
186 186 reject bookmark name with newline
187 187
188 188 $ hg bookmark '
189 189 > '
190 190 abort: bookmark name cannot contain newlines
191 191 [255]
192 192
193 193 bookmark with existing name
194 194
195 195 $ hg bookmark Z
196 196 abort: bookmark 'Z' already exists (use -f to force)
197 197 [255]
198 198
199 199 force bookmark with existing name
200 200
201 201 $ hg bookmark -f Z
202 202
203 203 list bookmarks
204 204
205 205 $ hg bookmark
206 206 X2 1:925d80f479bb
207 207 Y 2:db815d6d32e6
208 208 * Z 2:db815d6d32e6
209 209 x y 2:db815d6d32e6
210 210
211 211 revision but no bookmark name
212 212
213 213 $ hg bookmark -r .
214 214 abort: bookmark name required
215 215 [255]
216 216
217 217 bookmark name with whitespace only
218 218
219 219 $ hg bookmark ' '
220 220 abort: bookmark names cannot consist entirely of whitespace
221 221 [255]
222 222
223 223 invalid bookmark
224 224
225 225 $ hg bookmark 'foo:bar'
226 226 abort: bookmark 'foo:bar' contains illegal character
227 227 [255]
228 228
229 229 the bookmark extension should be ignored now that it is part of core
230 230
231 231 $ echo "[extensions]" >> $HGRCPATH
232 232 $ echo "bookmarks=" >> $HGRCPATH
233 233 $ hg bookmarks
234 234 X2 1:925d80f479bb
235 235 Y 2:db815d6d32e6
236 236 * Z 2:db815d6d32e6
237 237 x y 2:db815d6d32e6
238 238
239 239 test summary
240 240
241 241 $ hg summary
242 242 parent: 2:db815d6d32e6 tip
243 243 2
244 244 branch: default
245 245 bookmarks: *Z Y x y
246 246 commit: (clean)
247 247 update: 1 new changesets, 2 branch heads (merge)
248 248
249 249 test id
250 250
251 251 $ hg id
252 252 db815d6d32e6 tip Y/Z/x y
253 253
254 254 test rollback
255 255
256 256 $ echo foo > f1
257 257 $ hg ci -Amr
258 258 adding f1
259 259 $ hg bookmark -f Y -r 1
260 260 $ hg bookmark -f Z -r 1
261 261 $ hg rollback
262 262 repository tip rolled back to revision 2 (undo commit)
263 263 working directory now based on revision 2
264 264 $ hg bookmarks
265 265 X2 1:925d80f479bb
266 266 Y 2:db815d6d32e6
267 267 * Z 2:db815d6d32e6
268 268 x y 2:db815d6d32e6
269 269
270 270 test clone
271 271
272 272 $ hg bookmark -r 2 -i @
273 273 $ hg bookmark -r 2 -i a@
274 274 $ hg bookmarks
275 275 @ 2:db815d6d32e6
276 276 X2 1:925d80f479bb
277 277 Y 2:db815d6d32e6
278 278 * Z 2:db815d6d32e6
279 279 a@ 2:db815d6d32e6
280 280 x y 2:db815d6d32e6
281 281 $ hg clone . cloned-bookmarks
282 282 updating to branch default
283 283 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
284 284 $ hg -R cloned-bookmarks bookmarks
285 285 @ 2:db815d6d32e6
286 286 X2 1:925d80f479bb
287 287 Y 2:db815d6d32e6
288 288 Z 2:db815d6d32e6
289 289 a@ 2:db815d6d32e6
290 290 x y 2:db815d6d32e6
291 291
292 292 test clone with pull protocol
293 293
294 294 $ hg clone --pull . cloned-bookmarks-pull
295 295 requesting all changes
296 296 adding changesets
297 297 adding manifests
298 298 adding file changes
299 299 added 3 changesets with 3 changes to 3 files (+1 heads)
300 300 updating to branch default
301 301 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
302 302 $ hg -R cloned-bookmarks-pull bookmarks
303 303 @ 2:db815d6d32e6
304 304 X2 1:925d80f479bb
305 305 Y 2:db815d6d32e6
306 306 Z 2:db815d6d32e6
307 307 a@ 2:db815d6d32e6
308 308 x y 2:db815d6d32e6
309 309
310 310 $ hg bookmark -d @
311 311 $ hg bookmark -d a@
312 312
313 313 test clone with a specific revision
314 314
315 315 $ hg clone -r 925d80 . cloned-bookmarks-rev
316 316 adding changesets
317 317 adding manifests
318 318 adding file changes
319 319 added 2 changesets with 2 changes to 2 files
320 320 updating to branch default
321 321 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
322 322 $ hg -R cloned-bookmarks-rev bookmarks
323 323 X2 1:925d80f479bb
324 324
325 325 create bundle with two heads
326 326
327 327 $ hg clone . tobundle
328 328 updating to branch default
329 329 2 files updated, 0 files merged, 0 files removed, 0 files unresolved
330 330 $ echo x > tobundle/x
331 331 $ hg -R tobundle add tobundle/x
332 332 $ hg -R tobundle commit -m'x'
333 333 $ hg -R tobundle update -r -2
334 334 0 files updated, 0 files merged, 1 files removed, 0 files unresolved
335 335 $ echo y > tobundle/y
336 336 $ hg -R tobundle branch test
337 337 marked working directory as branch test
338 338 (branches are permanent and global, did you want a bookmark?)
339 339 $ hg -R tobundle add tobundle/y
340 340 $ hg -R tobundle commit -m'y'
341 341 $ hg -R tobundle bundle tobundle.hg
342 342 searching for changes
343 343 2 changesets found
344 344 $ hg unbundle tobundle.hg
345 345 adding changesets
346 346 adding manifests
347 347 adding file changes
348 348 added 2 changesets with 2 changes to 2 files (+1 heads)
349 349 (run 'hg heads' to see heads, 'hg merge' to merge)
350 350 $ hg update
351 351 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
352 352 $ hg bookmarks
353 353 X2 1:925d80f479bb
354 354 Y 2:db815d6d32e6
355 355 * Z 3:125c9a1d6df6
356 356 x y 2:db815d6d32e6
357 357
358 358 test wrongly formated bookmark
359 359
360 360 $ echo '' >> .hg/bookmarks
361 361 $ hg bookmarks
362 362 X2 1:925d80f479bb
363 363 Y 2:db815d6d32e6
364 364 * Z 3:125c9a1d6df6
365 365 x y 2:db815d6d32e6
366 366 $ echo "Ican'thasformatedlines" >> .hg/bookmarks
367 367 $ hg bookmarks
368 368 malformed line in .hg/bookmarks: "Ican'thasformatedlines"
369 369 X2 1:925d80f479bb
370 370 Y 2:db815d6d32e6
371 371 * Z 3:125c9a1d6df6
372 372 x y 2:db815d6d32e6
373 373
374 test missing revisions
375
376 $ echo "925d80f479bc z" > .hg/bookmarks
377 $ hg book
378 no bookmarks set
General Comments 0
You need to be logged in to leave comments. Login now