Show More
The requested changes are too big and content was truncated. Show full diff
@@ -0,0 +1,6 b'' | |||||
|
1 | { | |||
|
2 | "conduit_uri": "https://phab.mercurial-scm.org/api", | |||
|
3 | "repository.callsign": "HG", | |||
|
4 | "arc.land.onto.default": "@", | |||
|
5 | "base": "hg:.^" | |||
|
6 | } |
@@ -0,0 +1,13 b'' | |||||
|
1 | BasedOnStyle: LLVM | |||
|
2 | IndentWidth: 8 | |||
|
3 | UseTab: ForIndentation | |||
|
4 | BreakBeforeBraces: Linux | |||
|
5 | AllowShortIfStatementsOnASingleLine: false | |||
|
6 | IndentCaseLabels: false | |||
|
7 | AllowShortBlocksOnASingleLine: false | |||
|
8 | AllowShortFunctionsOnASingleLine: false | |||
|
9 | IncludeCategories: | |||
|
10 | - Regex: '^<' | |||
|
11 | Priority: 1 | |||
|
12 | - Regex: '^"' | |||
|
13 | Priority: 2 |
@@ -0,0 +1,18 b'' | |||||
|
1 | # See http://EditorConfig.org for the specification | |||
|
2 | ||||
|
3 | root = true | |||
|
4 | ||||
|
5 | [*.py] | |||
|
6 | indent_size = 4 | |||
|
7 | indent_style = space | |||
|
8 | trim_trailing_whitespace = true | |||
|
9 | ||||
|
10 | [*.{c,h}] | |||
|
11 | indent_size = 8 | |||
|
12 | indent_style = tab | |||
|
13 | trim_trailing_whitespace = true | |||
|
14 | ||||
|
15 | [*.t] | |||
|
16 | indent_size = 2 | |||
|
17 | indent_style = space | |||
|
18 | trim_trailing_whitespace = false |
@@ -0,0 +1,68 b'' | |||||
|
1 | syntax: glob | |||
|
2 | ||||
|
3 | *.elc | |||
|
4 | *.tmp | |||
|
5 | *.orig | |||
|
6 | *.rej | |||
|
7 | *~ | |||
|
8 | *.mergebackup | |||
|
9 | *.o | |||
|
10 | *.so | |||
|
11 | *.dll | |||
|
12 | *.exe | |||
|
13 | *.pyd | |||
|
14 | *.pyc | |||
|
15 | *.pyo | |||
|
16 | *$py.class | |||
|
17 | *.swp | |||
|
18 | *.prof | |||
|
19 | *.zip | |||
|
20 | \#*\# | |||
|
21 | .\#* | |||
|
22 | tests/.coverage* | |||
|
23 | tests/.testtimes* | |||
|
24 | tests/.hypothesis | |||
|
25 | tests/hypothesis-generated | |||
|
26 | tests/annotated | |||
|
27 | tests/exceptions | |||
|
28 | tests/*.err | |||
|
29 | tests/htmlcov | |||
|
30 | build | |||
|
31 | contrib/chg/chg | |||
|
32 | contrib/hgsh/hgsh | |||
|
33 | contrib/vagrant/.vagrant | |||
|
34 | dist | |||
|
35 | packages | |||
|
36 | doc/common.txt | |||
|
37 | doc/*.[0-9] | |||
|
38 | doc/*.[0-9].txt | |||
|
39 | doc/*.[0-9].gendoc.txt | |||
|
40 | doc/*.[0-9].{x,ht}ml | |||
|
41 | MANIFEST | |||
|
42 | MANIFEST.in | |||
|
43 | patches | |||
|
44 | mercurial/__modulepolicy__.py | |||
|
45 | mercurial/__version__.py | |||
|
46 | mercurial/hgpythonlib.h | |||
|
47 | mercurial.egg-info | |||
|
48 | .DS_Store | |||
|
49 | tags | |||
|
50 | cscope.* | |||
|
51 | .idea/* | |||
|
52 | .asv/* | |||
|
53 | i18n/hg.pot | |||
|
54 | locale/*/LC_MESSAGES/hg.mo | |||
|
55 | hgext/__index__.py | |||
|
56 | ||||
|
57 | rust/target/ | |||
|
58 | ||||
|
59 | # Generated wheels | |||
|
60 | wheelhouse/ | |||
|
61 | ||||
|
62 | syntax: regexp | |||
|
63 | ^\.pc/ | |||
|
64 | ^\.(pydev)?project | |||
|
65 | ||||
|
66 | # hackable windows distribution additions | |||
|
67 | ^hg-python | |||
|
68 | ^hg.py$ |
@@ -0,0 +1,170 b'' | |||||
|
1 | 35fb62a3a673d5322f6274a44ba6456e5e4b3b37 0 iD8DBQBEYmO2ywK+sNU5EO8RAnaYAKCO7x15xUn5mnhqWNXqk/ehlhRt2QCfRDfY0LrUq2q4oK/KypuJYPHgq1A= | |||
|
2 | 2be3001847cb18a23c403439d9e7d0ace30804e9 0 iD8DBQBExUbjywK+sNU5EO8RAhzxAKCtyHAQUzcTSZTqlfJ0by6vhREwWQCghaQFHfkfN0l9/40EowNhuMOKnJk= | |||
|
3 | 36a957364b1b89c150f2d0e60a99befe0ee08bd3 0 iD8DBQBFfL2QywK+sNU5EO8RAjYFAKCoGlaWRTeMsjdmxAjUYx6diZxOBwCfY6IpBYsKvPTwB3oktnPt5Rmrlys= | |||
|
4 | 27230c29bfec36d5540fbe1c976810aefecfd1d2 0 iD8DBQBFheweywK+sNU5EO8RAt7VAKCrqJQWT2/uo2RWf0ZI4bLp6v82jACgjrMdsaTbxRsypcmEsdPhlG6/8F4= | |||
|
5 | fb4b6d5fe100b0886f8bc3d6731ec0e5ed5c4694 0 iD8DBQBGgHicywK+sNU5EO8RAgNxAJ0VG8ixAaeudx4sZbhngI1syu49HQCeNUJQfWBgA8bkJ2pvsFpNxwYaX3I= | |||
|
6 | 23889160905a1b09fffe1c07378e9fc1827606eb 0 iD8DBQBHGTzoywK+sNU5EO8RAr/UAJ0Y8s4jQtzgS+G9vM8z6CWBThZ8fwCcCT5XDj2XwxKkz/0s6UELwjsO3LU= | |||
|
7 | bae2e9c838e90a393bae3973a7850280413e091a 0 iD8DBQBH6DO5ywK+sNU5EO8RAsfrAJ0e4r9c9GF/MJsM7Xjd3NesLRC3+ACffj6+6HXdZf8cswAoFPO+DY00oD0= | |||
|
8 | d5cbbe2c49cee22a9fbeb9ea41daa0ac4e26b846 0 iD8DBQBINdwsywK+sNU5EO8RAjIUAKCPmlFJSpsPAAUKF+iNHAwVnwmzeQCdEXrL27CWclXuUKdbQC8De7LICtE= | |||
|
9 | d2375bbee6d47e62ba8e415c86e83a465dc4dce9 0 iD8DBQBIo1wpywK+sNU5EO8RAmRNAJ94x3OFt6blbqu/yBoypm/AJ44fuACfUaldXcV5z9tht97hSp22DVTEPGc= | |||
|
10 | 2a67430f92f15ea5159c26b09ec4839a0c549a26 0 iEYEABECAAYFAkk1hykACgkQywK+sNU5EO85QACeNJNUanjc2tl4wUoPHNuv+lSj0ZMAoIm93wSTc/feyYnO2YCaQ1iyd9Nu | |||
|
11 | 3773e510d433969e277b1863c317b674cbee2065 0 iEYEABECAAYFAklNbbAACgkQywK+sNU5EO8o+gCfeb2/lfIJZMvyDA1m+G1CsBAxfFsAoIa6iAMG8SBY7hW1Q85Yf/LXEvaE | |||
|
12 | 11a4eb81fb4f4742451591489e2797dc47903277 0 iEYEABECAAYFAklcAnsACgkQywK+sNU5EO+uXwCbBVHNNsLy1g7BlAyQJwadYVyHOXoAoKvtAVO71+bv7EbVoukwTzT+P4Sx | |||
|
13 | 11efa41037e280d08cfb07c09ad485df30fb0ea8 0 iEYEABECAAYFAkmvJRQACgkQywK+sNU5EO9XZwCeLMgDgPSMWMm6vgjL4lDs2pEc5+0AnRxfiFbpbBfuEFTqKz9nbzeyoBlx | |||
|
14 | 02981000012e3adf40c4849bd7b3d5618f9ce82d 0 iEYEABECAAYFAknEH3wACgkQywK+sNU5EO+uXwCeI+LbLMmhjU1lKSfU3UWJHjjUC7oAoIZLvYDGOL/tNZFUuatc3RnZ2eje | |||
|
15 | 196d40e7c885fa6e95f89134809b3ec7bdbca34b 0 iEYEABECAAYFAkpL2X4ACgkQywK+sNU5EO9FOwCfXJycjyKJXsvQqKkHrglwOQhEKS4An36GfKzptfN8b1qNc3+ya/5c2WOM | |||
|
16 | 3ef6c14a1e8e83a31226f5881b7fe6095bbfa6f6 0 iEYEABECAAYFAkpopLIACgkQywK+sNU5EO8QSgCfZ0ztsd071rOa2lhmp9Fyue/WoI0AoLTei80/xrhRlB8L/rZEf2KBl8dA | |||
|
17 | 31ec469f9b556f11819937cf68ee53f2be927ebf 0 iEYEABECAAYFAksBuxAACgkQywK+sNU5EO+mBwCfagB+A0txzWZ6dRpug3LEoK7Z1QsAoKpbk8vsLjv6/oRDicSk/qBu33+m | |||
|
18 | 439d7ea6fe3aa4ab9ec274a68846779153789de9 0 iEYEABECAAYFAksVw0kACgkQywK+sNU5EO/oZwCfdfBEkgp38xq6wN2F4nj+SzofrJIAnjmxt04vaJSeOOeHylHvk6lzuQsw | |||
|
19 | 296a0b14a68621f6990c54fdba0083f6f20935bf 0 iEYEABECAAYFAks+jCoACgkQywK+sNU5EO9J8wCeMUGF9E/gS2UBsqIz56WS4HMPRPUAoI5J95mwEIK8Clrl7qFRidNI6APq | |||
|
20 | 4aa619c4c2c09907034d9824ebb1dd0e878206eb 0 iEYEABECAAYFAktm9IsACgkQywK+sNU5EO9XGgCgk4HclRQhexEtooPE5GcUCdB6M8EAn2ptOhMVbIoO+JncA+tNACPFXh0O | |||
|
21 | ff2704a8ded37fbebd8b6eb5ec733731d725da8a 0 iEYEABECAAYFAkuRoSQACgkQywK+sNU5EO//3QCeJDc5r2uFyFCtAlpSA27DEE5rrxAAn2FSwTy9fhrB3QAdDQlwkEZcQzDh | |||
|
22 | 2b01dab594167bc0dd33331dbaa6dca3dca1b3aa 0 iEYEABECAAYFAku1IwIACgkQywK+sNU5EO9MjgCdHLVwkTZlNHxhcznZKBL1rjN+J7cAoLLWi9LTL6f/TgBaPSKOy1ublbaW | |||
|
23 | 39f725929f0c48c5fb3b90c071fc3066012456ca 0 iEYEABECAAYFAkvclvsACgkQywK+sNU5EO9FSwCeL9i5x8ALW/LE5+lCX6MFEAe4MhwAn1ev5o6SX6GrNdDfKweiemfO2VBk | |||
|
24 | fdcf80f26604f233dc4d8f0a5ef9d7470e317e8a 0 iEYEABECAAYFAkvsKTkACgkQywK+sNU5EO9qEACgiSiRGvTG2vXGJ65tUSOIYihTuFAAnRzRIqEVSw8M8/RGeUXRps0IzaCO | |||
|
25 | 24fe2629c6fd0c74c90bd066e77387c2b02e8437 0 iEYEABECAAYFAkwFLRsACgkQywK+sNU5EO+pJACgp13tPI+pbwKZV+LeMjcQ4H6tCZYAoJebzhd6a8yYx6qiwpJxA9BXZNXy | |||
|
26 | f786fc4b8764cd2a5526d259cf2f94d8a66924d9 0 iEYEABECAAYFAkwsyxcACgkQywK+sNU5EO+crACfUpNAF57PmClkSri9nJcBjb2goN4AniPCNaKvnki7TnUsi1u2oxltpKKL | |||
|
27 | bf1774d95bde614af3956d92b20e2a0c68c5fec7 0 iEYEABECAAYFAkxVwccACgkQywK+sNU5EO+oFQCeJzwZ+we1fIIyBGCddHceOUAN++cAnjvT6A8ZWW0zV21NXIFF1qQmjxJd | |||
|
28 | c00f03a4982e467fb6b6bd45908767db6df4771d 0 iEYEABECAAYFAkxXDqsACgkQywK+sNU5EO/GJACfT9Rz4hZOxPQEs91JwtmfjevO84gAmwSmtfo5mmWSm8gtTUebCcdTv0Kf | |||
|
29 | ff5cec76b1c5b6be9c3bb923aae8c3c6d079d6b9 0 iD8DBQBMdo+qywK+sNU5EO8RAqQpAJ975BL2CCAiWMz9SXthNQ9xG181IwCgp4O+KViHPkufZVFn2aTKMNvcr1A= | |||
|
30 | 93d8bff78c96fe7e33237b257558ee97290048a4 0 iD8DBQBMpfvdywK+sNU5EO8RAsxVAJ0UaL1XB51C76JUBhafc9GBefuMxwCdEWkTOzwvE0SarJBe9i008jhbqW4= | |||
|
31 | 333421b9e0f96c7bc788e5667c146a58a9440a55 0 iD8DBQBMz0HOywK+sNU5EO8RAlsEAJ0USh6yOG7OrWkADGunVt9QimBQnwCbBqeMnKgSbwEw8jZwE3Iz1mdrYlo= | |||
|
32 | 4438875ec01bd0fc32be92b0872eb6daeed4d44f 0 iD8DBQBM4WYUywK+sNU5EO8RAhCVAJ0dJswachwFAHALmk1x0RJehxzqPQCbBNskP9n/X689jB+btNTZTyKU/fw= | |||
|
33 | 6aff4f144ad356311318b0011df0bb21f2c97429 0 iD8DBQBM9uxXywK+sNU5EO8RAv+4AKCDj4qKP16GdPaq1tP6BUwpM/M1OACfRyzLPp/qiiN8xJTWoWYSe/XjJug= | |||
|
34 | e3bf16703e2601de99e563cdb3a5d50b64e6d320 0 iD8DBQBNH8WqywK+sNU5EO8RAiQTAJ9sBO+TeiGro4si77VVaQaA6jcRUgCfSA28dBbjj0oFoQwvPoZjANiZBH8= | |||
|
35 | a6c855c32ea081da3c3b8ff628f1847ff271482f 0 iD8DBQBNSJJ+ywK+sNU5EO8RAoJaAKCweDEF70fu+r1Zn7pYDXdlk5RuSgCeO9gK/eit8Lin/1n3pO7aYguFLok= | |||
|
36 | 2b2155623ee2559caf288fd333f30475966c4525 0 iD8DBQBNSJeBywK+sNU5EO8RAm1KAJ4hW9Cm9nHaaGJguchBaPLlAr+O3wCgqgmMok8bdAS06N6PL60PSTM//Gg= | |||
|
37 | 2616325766e3504c8ae7c84bd15ee610901fe91d 0 iD8DBQBNbWy9ywK+sNU5EO8RAlWCAJ4mW8HbzjJj9GpK98muX7k+7EvEHwCfaTLbC/DH3QEsZBhEP+M8tzL6RU4= | |||
|
38 | aa1f3be38ab127280761889d2dca906ca465b5f4 0 iD8DBQBNeQq7ywK+sNU5EO8RAlEOAJ4tlEDdetE9lKfjGgjbkcR8PrC3egCfXCfF3qNVvU/2YYjpgvRwevjvDy0= | |||
|
39 | b032bec2c0a651ca0ddecb65714bfe6770f67d70 0 iD8DBQBNlg5kywK+sNU5EO8RAnGEAJ9gmEx6MfaR4XcG2m/93vwtfyzs3gCgltzx8/YdHPwqDwRX/WbpYgi33is= | |||
|
40 | 3cb1e95676ad089596bd81d0937cad37d6e3b7fb 0 iD8DBQBNvTy4ywK+sNU5EO8RAmp8AJ9QnxK4jTJ7G722MyeBxf0UXEdGwACgtlM7BKtNQfbEH/fOW5y+45W88VI= | |||
|
41 | 733af5d9f6b22387913e1d11350fb8cb7c1487dd 0 iD8DBQBN5q/8ywK+sNU5EO8RArRGAKCNGT94GKIYtSuwZ57z1sQbcw6uLACfffpbMV4NAPMl8womAwg+7ZPKnIU= | |||
|
42 | de9eb6b1da4fc522b1cab16d86ca166204c24f25 0 iD8DBQBODhfhywK+sNU5EO8RAr2+AJ4ugbAj8ae8/K0bYZzx3sascIAg1QCeK3b+zbbVVqd3b7CDpwFnaX8kTd4= | |||
|
43 | 4a43e23b8c55b4566b8200bf69fe2158485a2634 0 iD8DBQBONzIMywK+sNU5EO8RAj5SAJ0aPS3+JHnyI6bHB2Fl0LImbDmagwCdGbDLp1S7TFobxXudOH49bX45Iik= | |||
|
44 | d629f1e89021103f1753addcef6b310e4435b184 0 iD8DBQBOWAsBywK+sNU5EO8RAht4AJwJl9oNFopuGkj5m8aKuf7bqPkoAQCeNrEm7UhFsZKYT5iUOjnMV7s2LaM= | |||
|
45 | 351a9292e430e35766c552066ed3e87c557b803b 0 iD8DBQBOh3zUywK+sNU5EO8RApFMAKCD3Y/u3avDFndznwqfG5UeTHMlvACfUivPIVQZyDZnhZMq0UhC6zhCEQg= | |||
|
46 | 384082750f2c51dc917d85a7145748330fa6ef4d 0 iD8DBQBOmd+OywK+sNU5EO8RAgDgAJ9V/X+G7VLwhTpHrZNiOHabzSyzYQCdE2kKfIevJUYB9QLAWCWP6DPwrwI= | |||
|
47 | 41453d55b481ddfcc1dacb445179649e24ca861d 0 iD8DBQBOsFhpywK+sNU5EO8RAqM6AKCyfxUae3/zLuiLdQz+JR78690eMACfQ6JTBQib4AbE+rUDdkeFYg9K/+4= | |||
|
48 | 195dbd1cef0c2f9f8bcf4ea303238105f716bda3 0 iD8DBQBO1/fWywK+sNU5EO8RAmoPAKCR5lpv1D6JLURHD8KVLSV4GRVEBgCgnd0Sy78ligNfqAMafmACRDvj7vo= | |||
|
49 | 6344043924497cd06d781d9014c66802285072e4 0 iD8DBQBPALgmywK+sNU5EO8RAlfhAJ9nYOdWnhfVDHYtDTJAyJtXBAQS9wCgnefoSQt7QABkbGxM+Q85UYEBuD0= | |||
|
50 | db33555eafeaf9df1e18950e29439eaa706d399b 0 iD8DBQBPGdzxywK+sNU5EO8RAppkAJ9jOXhUVE/97CPgiMA0pMGiIYnesQCfengAszcBiSiKGugiI8Okc9ghU+Y= | |||
|
51 | 2aa5b51f310fb3befd26bed99c02267f5c12c734 0 iD8DBQBPKZ9bywK+sNU5EO8RAt1TAJ45r1eJ0YqSkInzrrayg4TVCh0SnQCgm0GA/Ua74jnnDwVQ60lAwROuz1Q= | |||
|
52 | 53e2cd303ecf8ca7c7eeebd785c34e5ed6b0f4a4 0 iD8DBQBPT/fvywK+sNU5EO8RAnfYAKCn7d0vwqIb100YfWm1F7nFD5B+FACeM02YHpQLSNsztrBCObtqcnfod7Q= | |||
|
53 | b9bd95e61b49c221c4cca24e6da7c946fc02f992 0 iD8DBQBPeLsIywK+sNU5EO8RAvpNAKCtKe2gitz8dYn52IRF0hFOPCR7AQCfRJL/RWCFweu2T1vH/mUOCf8SXXc= | |||
|
54 | d9e2f09d5488c395ae9ddbb320ceacd24757e055 0 iD8DBQBPju/dywK+sNU5EO8RArBYAJ9xtifdbk+hCOJO8OZa4JfHX8OYZQCeKPMBaBWiT8N/WHoOm1XU0q+iono= | |||
|
55 | 00182b3d087909e3c3ae44761efecdde8f319ef3 0 iD8DBQBPoFhIywK+sNU5EO8RAhzhAKCBj1n2jxPTkZNJJ5pSp3soa+XHIgCgsZZpAQxOpXwCp0eCdNGe0+pmxmg= | |||
|
56 | 5983de86462c5a9f42a3ad0f5e90ce5b1d221d25 0 iD8DBQBPovNWywK+sNU5EO8RAhgiAJ980T91FdPTRMmVONDhpkMsZwVIMACgg3bKvoWSeuCW28llUhAJtUjrMv0= | |||
|
57 | 85a358df5bbbe404ca25730c9c459b34263441dc 0 iD8DBQBPyZsWywK+sNU5EO8RAnpLAJ48qrGDJRT+pteS0mSQ11haqHstPwCdG4ccGbk+0JHb7aNy8/NRGAOqn9w= | |||
|
58 | b013baa3898e117959984fc64c29d8c784d2f28b 0 iD8DBQBP8QOPywK+sNU5EO8RAqimAKCFRSx0lvG6y8vne2IhNG062Hn0dACeMLI5/zhpWpHBIVeAAquYfx2XFeA= | |||
|
59 | 7f5094bb3f423fc799e471aac2aee81a7ce57a0b 0 iD8DBQBQGiL8ywK+sNU5EO8RAq5oAJ4rMMCPx6O+OuzNXVOexogedWz/QgCeIiIxLd76I4pXO48tdXhr0hQcBuM= | |||
|
60 | 072209ae4ddb654eb2d5fd35bff358c738414432 0 iD8DBQBQQkq0ywK+sNU5EO8RArDTAJ9nk5CySnNAjAXYvqvx4uWCw9ThZwCgqmFRehH/l+oTwj3f8nw8u8qTCdc= | |||
|
61 | b3f0f9a39c4e1d0250048cd803ab03542d6f140a 0 iD8DBQBQamltywK+sNU5EO8RAlsqAJ4qF/m6aFu4mJCOKTiAP5RvZFK02ACfawYShUZO6OXEFfveU0aAxDR0M1k= | |||
|
62 | d118a4f4fd16d9b558ec3f3e87bfee772861d2b7 0 iD8DBQBQgPV5ywK+sNU5EO8RArylAJ0abcx5NlDjyv3ZDWpAfRIHyRsJtQCgn4TMuEayqgxzrvadQZHdTEU2g38= | |||
|
63 | 195ad823b5d58c68903a6153a25e3fb4ed25239d 0 iD8DBQBQkuT9ywK+sNU5EO8RAhB4AKCeerItoK2Jipm2cVf4euGofAa/WACeJj3TVd4pFILpb+ogj7ebweFLJi0= | |||
|
64 | 0c10cf8191469e7c3c8844922e17e71a176cb7cb 0 iD8DBQBQvQWoywK+sNU5EO8RAnq3AJoCn98u4geFx5YaQaeh99gFhCd7bQCgjoBwBSUyOvGd0yBy60E3Vv3VZhM= | |||
|
65 | a4765077b65e6ae29ba42bab7834717b5072d5ba 0 iD8DBQBQ486sywK+sNU5EO8RAhmJAJ90aLfLKZhmcZN7kqphigQJxiFOQACeJ5IUZxjGKH4xzi3MrgIcx9n+dB0= | |||
|
66 | f5fbe15ca7449f2c9a3cf817c86d0ae68b307214 0 iD8DBQBQ+yuYywK+sNU5EO8RAm9JAJoD/UciWvpGeKBcpGtZJBFJVcL/HACghDXSgQ+xQDjB+6uGrdgAQsRR1Lg= | |||
|
67 | a6088c05e43a8aee0472ca3a4f6f8d7dd914ebbf 0 iD8DBQBRDDROywK+sNU5EO8RAh75AJ9uJCGoCWnP0Lv/+XuYs4hvUl+sAgCcD36QgAnuw8IQXrvv684BAXAnHcA= | |||
|
68 | 7511d4df752e61fe7ae4f3682e0a0008573b0402 0 iD8DBQBRFYaoywK+sNU5EO8RAuErAJoDyhXn+lptU3+AevVdwAIeNFyR2gCdHzPHyWd+JDeWCUR+pSOBi8O2ppM= | |||
|
69 | 5b7175377babacce80a6c1e12366d8032a6d4340 0 iD8DBQBRMCYgywK+sNU5EO8RAq1/AKCWKlt9ysibyQgYwoxxIOZv5J8rpwCcDSHQaaf1fFZUTnQsOePwcM2Y/Sg= | |||
|
70 | 50c922c1b5145dab8baefefb0437d363b6a6c21c 0 iD8DBQBRWnUnywK+sNU5EO8RAuQRAJwM42cJqJPeqJ0jVNdMqKMDqr4dSACeP0cRVGz1gitMuV0x8f3mrZrqc7I= | |||
|
71 | 8a7bd2dccd44ed571afe7424cd7f95594f27c092 0 iD8DBQBRXfBvywK+sNU5EO8RAn+LAKCsMmflbuXjYRxlzFwId5ptm8TZcwCdGkyLbZcASBOkzQUm/WW1qfknJHU= | |||
|
72 | 292cd385856d98bacb2c3086f8897bc660c2beea 0 iD8DBQBRcM0BywK+sNU5EO8RAjp4AKCJBykQbvXhKuvLSMxKx3a2TBiXcACfbr/kLg5GlZTF/XDPmY+PyHgI/GM= | |||
|
73 | 23f785b38af38d2fca6b8f3db56b8007a84cd73a 0 iD8DBQBRgZwNywK+sNU5EO8RAmO4AJ4u2ILGuimRP6MJgE2t65LZ5dAdkACgiENEstIdrlFC80p+sWKD81kKIYI= | |||
|
74 | ddc7a6be20212d18f3e27d9d7e6f079a66d96f21 0 iD8DBQBRkswvywK+sNU5EO8RAiYYAJsHTHyHbJeAgmGvBTmDrfcKu4doUgCeLm7eGBjx7yAPUvEtxef8rAkQmXI= | |||
|
75 | cceaf7af4c9e9e6fa2dbfdcfe9856c5da69c4ffd 0 iD8DBQBRqnFLywK+sNU5EO8RAsWNAJ9RR6t+y1DLFc2HeH0eN9VfZAKF9gCeJ8ezvhtKq/LMs0/nvcgKQc/d5jk= | |||
|
76 | 009794acc6e37a650f0fae37872e733382ac1c0c 0 iD8DBQBR0guxywK+sNU5EO8RArNkAKCq9pMihVzP8Os5kCmgbWpe5C37wgCgqzuPZTHvAsXF5wTyaSTMVa9Ccq4= | |||
|
77 | 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 |
@@ -0,0 +1,183 b'' | |||||
|
1 | d40cc5aacc31ed673d9b5b24f98bee78c283062c 0.4f | |||
|
2 | 1c590d34bf61e2ea12c71738e5a746cd74586157 0.4e | |||
|
3 | 7eca4cfa8aad5fce9a04f7d8acadcd0452e2f34e 0.4d | |||
|
4 | b4d0c3786ad3e47beacf8412157326a32b6d25a4 0.4c | |||
|
5 | f40273b0ad7b3a6d3012fd37736d0611f41ecf54 0.5 | |||
|
6 | 0a28dfe59f8fab54a5118c5be4f40da34a53cdb7 0.5b | |||
|
7 | 12e0fdbc57a0be78f0e817fd1d170a3615cd35da 0.6 | |||
|
8 | 4ccf3de52989b14c3d84e1097f59e39a992e00bd 0.6b | |||
|
9 | eac9c8efcd9bd8244e72fb6821f769f450457a32 0.6c | |||
|
10 | 979c049974485125e1f9357f6bbe9c1b548a64c3 0.7 | |||
|
11 | 3a56574f329a368d645853e0f9e09472aee62349 0.8 | |||
|
12 | 6a03cff2b0f5d30281e6addefe96b993582f2eac 0.8.1 | |||
|
13 | 35fb62a3a673d5322f6274a44ba6456e5e4b3b37 0.9 | |||
|
14 | 2be3001847cb18a23c403439d9e7d0ace30804e9 0.9.1 | |||
|
15 | 36a957364b1b89c150f2d0e60a99befe0ee08bd3 0.9.2 | |||
|
16 | 27230c29bfec36d5540fbe1c976810aefecfd1d2 0.9.3 | |||
|
17 | fb4b6d5fe100b0886f8bc3d6731ec0e5ed5c4694 0.9.4 | |||
|
18 | 23889160905a1b09fffe1c07378e9fc1827606eb 0.9.5 | |||
|
19 | bae2e9c838e90a393bae3973a7850280413e091a 1.0 | |||
|
20 | d5cbbe2c49cee22a9fbeb9ea41daa0ac4e26b846 1.0.1 | |||
|
21 | d2375bbee6d47e62ba8e415c86e83a465dc4dce9 1.0.2 | |||
|
22 | 2a67430f92f15ea5159c26b09ec4839a0c549a26 1.1 | |||
|
23 | 3773e510d433969e277b1863c317b674cbee2065 1.1.1 | |||
|
24 | 11a4eb81fb4f4742451591489e2797dc47903277 1.1.2 | |||
|
25 | 11efa41037e280d08cfb07c09ad485df30fb0ea8 1.2 | |||
|
26 | 02981000012e3adf40c4849bd7b3d5618f9ce82d 1.2.1 | |||
|
27 | 196d40e7c885fa6e95f89134809b3ec7bdbca34b 1.3 | |||
|
28 | 3ef6c14a1e8e83a31226f5881b7fe6095bbfa6f6 1.3.1 | |||
|
29 | 31ec469f9b556f11819937cf68ee53f2be927ebf 1.4 | |||
|
30 | 439d7ea6fe3aa4ab9ec274a68846779153789de9 1.4.1 | |||
|
31 | 296a0b14a68621f6990c54fdba0083f6f20935bf 1.4.2 | |||
|
32 | 4aa619c4c2c09907034d9824ebb1dd0e878206eb 1.4.3 | |||
|
33 | ff2704a8ded37fbebd8b6eb5ec733731d725da8a 1.5 | |||
|
34 | 2b01dab594167bc0dd33331dbaa6dca3dca1b3aa 1.5.1 | |||
|
35 | 39f725929f0c48c5fb3b90c071fc3066012456ca 1.5.2 | |||
|
36 | fdcf80f26604f233dc4d8f0a5ef9d7470e317e8a 1.5.3 | |||
|
37 | 24fe2629c6fd0c74c90bd066e77387c2b02e8437 1.5.4 | |||
|
38 | f786fc4b8764cd2a5526d259cf2f94d8a66924d9 1.6 | |||
|
39 | bf1774d95bde614af3956d92b20e2a0c68c5fec7 1.6.1 | |||
|
40 | c00f03a4982e467fb6b6bd45908767db6df4771d 1.6.2 | |||
|
41 | ff5cec76b1c5b6be9c3bb923aae8c3c6d079d6b9 1.6.3 | |||
|
42 | 93d8bff78c96fe7e33237b257558ee97290048a4 1.6.4 | |||
|
43 | 333421b9e0f96c7bc788e5667c146a58a9440a55 1.7 | |||
|
44 | 4438875ec01bd0fc32be92b0872eb6daeed4d44f 1.7.1 | |||
|
45 | 6aff4f144ad356311318b0011df0bb21f2c97429 1.7.2 | |||
|
46 | e3bf16703e2601de99e563cdb3a5d50b64e6d320 1.7.3 | |||
|
47 | a6c855c32ea081da3c3b8ff628f1847ff271482f 1.7.4 | |||
|
48 | 2b2155623ee2559caf288fd333f30475966c4525 1.7.5 | |||
|
49 | 2616325766e3504c8ae7c84bd15ee610901fe91d 1.8 | |||
|
50 | aa1f3be38ab127280761889d2dca906ca465b5f4 1.8.1 | |||
|
51 | b032bec2c0a651ca0ddecb65714bfe6770f67d70 1.8.2 | |||
|
52 | 3cb1e95676ad089596bd81d0937cad37d6e3b7fb 1.8.3 | |||
|
53 | 733af5d9f6b22387913e1d11350fb8cb7c1487dd 1.8.4 | |||
|
54 | de9eb6b1da4fc522b1cab16d86ca166204c24f25 1.9 | |||
|
55 | 4a43e23b8c55b4566b8200bf69fe2158485a2634 1.9.1 | |||
|
56 | d629f1e89021103f1753addcef6b310e4435b184 1.9.2 | |||
|
57 | 351a9292e430e35766c552066ed3e87c557b803b 1.9.3 | |||
|
58 | 384082750f2c51dc917d85a7145748330fa6ef4d 2.0-rc | |||
|
59 | 41453d55b481ddfcc1dacb445179649e24ca861d 2.0 | |||
|
60 | 195dbd1cef0c2f9f8bcf4ea303238105f716bda3 2.0.1 | |||
|
61 | 6344043924497cd06d781d9014c66802285072e4 2.0.2 | |||
|
62 | db33555eafeaf9df1e18950e29439eaa706d399b 2.1-rc | |||
|
63 | 2aa5b51f310fb3befd26bed99c02267f5c12c734 2.1 | |||
|
64 | 53e2cd303ecf8ca7c7eeebd785c34e5ed6b0f4a4 2.1.1 | |||
|
65 | b9bd95e61b49c221c4cca24e6da7c946fc02f992 2.1.2 | |||
|
66 | d9e2f09d5488c395ae9ddbb320ceacd24757e055 2.2-rc | |||
|
67 | 00182b3d087909e3c3ae44761efecdde8f319ef3 2.2 | |||
|
68 | 5983de86462c5a9f42a3ad0f5e90ce5b1d221d25 2.2.1 | |||
|
69 | 85a358df5bbbe404ca25730c9c459b34263441dc 2.2.2 | |||
|
70 | b013baa3898e117959984fc64c29d8c784d2f28b 2.2.3 | |||
|
71 | a06e2681dd1786e2354d84a5fa9c1c88dd4fa3e0 2.3-rc | |||
|
72 | 7f5094bb3f423fc799e471aac2aee81a7ce57a0b 2.3 | |||
|
73 | 072209ae4ddb654eb2d5fd35bff358c738414432 2.3.1 | |||
|
74 | b3f0f9a39c4e1d0250048cd803ab03542d6f140a 2.3.2 | |||
|
75 | d118a4f4fd16d9b558ec3f3e87bfee772861d2b7 2.4-rc | |||
|
76 | 195ad823b5d58c68903a6153a25e3fb4ed25239d 2.4 | |||
|
77 | 0c10cf8191469e7c3c8844922e17e71a176cb7cb 2.4.1 | |||
|
78 | a4765077b65e6ae29ba42bab7834717b5072d5ba 2.4.2 | |||
|
79 | f5fbe15ca7449f2c9a3cf817c86d0ae68b307214 2.5-rc | |||
|
80 | a6088c05e43a8aee0472ca3a4f6f8d7dd914ebbf 2.5 | |||
|
81 | 7511d4df752e61fe7ae4f3682e0a0008573b0402 2.5.1 | |||
|
82 | 5b7175377babacce80a6c1e12366d8032a6d4340 2.5.2 | |||
|
83 | 50c922c1b5145dab8baefefb0437d363b6a6c21c 2.5.3 | |||
|
84 | 8a7bd2dccd44ed571afe7424cd7f95594f27c092 2.5.4 | |||
|
85 | 292cd385856d98bacb2c3086f8897bc660c2beea 2.6-rc | |||
|
86 | 23f785b38af38d2fca6b8f3db56b8007a84cd73a 2.6 | |||
|
87 | ddc7a6be20212d18f3e27d9d7e6f079a66d96f21 2.6.1 | |||
|
88 | cceaf7af4c9e9e6fa2dbfdcfe9856c5da69c4ffd 2.6.2 | |||
|
89 | 009794acc6e37a650f0fae37872e733382ac1c0c 2.6.3 | |||
|
90 | f0d7721d7322dcfb5af33599c2543f27335334bb 2.7-rc | |||
|
91 | f37b5a17e6a0ee17afde2cdde5393dd74715fb58 2.7 | |||
|
92 | 335a558f81dc73afeab4d7be63617392b130117f 2.7.1 | |||
|
93 | e7fa36d2ad3a7944a52dca126458d6f482db3524 2.7.2 | |||
|
94 | 1596f2d8f2421314b1ddead8f7d0c91009358994 2.8-rc | |||
|
95 | d825e4025e39d1c39db943cdc89818abd0a87c27 2.8 | |||
|
96 | 209e04a06467e2969c0cc6501335be0406d46ef0 2.8.1 | |||
|
97 | ca387377df7a3a67dbb90b6336b781cdadc3ef41 2.8.2 | |||
|
98 | 8862469e16f9236208581b20de5f96bd13cc039d 2.9-rc | |||
|
99 | 3cec5134e9c4bceab6a00c60f52a4f80677a78f2 2.9 | |||
|
100 | b96cb15ec9e04d8ac5ee08b34fcbbe4200588965 2.9.1 | |||
|
101 | 3f83fc5cfe715d292069ee8417c83804f6c6c1e4 2.9.2 | |||
|
102 | 564f55b251224f16508dd1311452db7780dafe2b 3.0-rc | |||
|
103 | 2195ac506c6ababe86985b932f4948837c0891b5 3.0 | |||
|
104 | 269c80ee5b3cb3684fa8edc61501b3506d02eb10 3.0.1 | |||
|
105 | 2d8cd3d0e83c7336c0cb45a9f88638363f993848 3.0.2 | |||
|
106 | 6c36dc6cd61a0e1b563f1d51e55bdf4dacf12162 3.1-rc | |||
|
107 | 3178e49892020336491cdc6945885c4de26ffa8b 3.1 | |||
|
108 | 5dc91146f35369949ea56b40172308158b59063a 3.1.1 | |||
|
109 | f768c888aaa68d12dd7f509dcc7f01c9584357d0 3.1.2 | |||
|
110 | 7f8d16af8cae246fa5a48e723d48d58b015aed94 3.2-rc | |||
|
111 | ced632394371a36953ce4d394f86278ae51a2aae 3.2 | |||
|
112 | 643c58303fb0ec020907af28b9e486be299ba043 3.2.1 | |||
|
113 | 902554884335e5ca3661d63be9978eb4aec3f68a 3.2.2 | |||
|
114 | 6dad422ecc5adb63d9fa649eeb8e05a5f9bc4900 3.2.3 | |||
|
115 | 1265a3a71d75396f5d4cf6935ae7d9ba5407a547 3.2.4 | |||
|
116 | db8e3f7948b1fdeb9ad12d448fc3525759908b9f 3.3-rc | |||
|
117 | fbdd5195528fae4f41feebc1838215c110b25d6a 3.3 | |||
|
118 | 5b4ed033390bf6e2879c8f5c28c84e1ee3b87231 3.3.1 | |||
|
119 | 07a92bbd02e5e3a625e0820389b47786b02b2cea 3.3.2 | |||
|
120 | 2e2e9a0750f91a6fe0ad88e4de34f8efefdcab08 3.3.3 | |||
|
121 | e89f909edffad558b56f4affa8239e4832f88de0 3.4-rc | |||
|
122 | 8cc6036bca532e06681c5a8fa37efaa812de67b5 3.4 | |||
|
123 | ed18f4acf435a2824c6f49fba40f42b9df5da7ad 3.4.1 | |||
|
124 | 540cd0ddac49c1125b2e013aa2ff18ecbd4dd954 3.4.2 | |||
|
125 | 96a38d44ba093bd1d1ecfd34119e94056030278b 3.5-rc | |||
|
126 | 21aa1c313b05b1a85f8ffa1120d51579ddf6bf24 3.5 | |||
|
127 | 1a45e49a6bed023deb229102a8903234d18054d3 3.5.1 | |||
|
128 | 9a466b9f9792e3ad7ae3fc6c43c3ff2e136b718d 3.5.2 | |||
|
129 | b66e3ca0b90c3095ea28dfd39aa24247bebf5c20 3.6-rc | |||
|
130 | 47dd34f2e7272be9e3b2a5a83cd0d20be44293f4 3.6 | |||
|
131 | 1aa5083cbebbe7575c88f3402ab377539b484897 3.6.1 | |||
|
132 | 2d437a0f3355834a9485bbbeb30a52a052c98f19 3.6.2 | |||
|
133 | ea389970c08449440587712117f178d33bab3f1e 3.6.3 | |||
|
134 | 158bdc8965720ca4061f8f8d806563cfc7cdb62e 3.7-rc | |||
|
135 | 2408645de650d8a29a6ce9e7dce601d8dd0d1474 3.7 | |||
|
136 | b698abf971e7377d9b7ec7fc8c52df45255b0329 3.7.1 | |||
|
137 | d493d64757eb45ada99fcb3693e479a51b7782da 3.7.2 | |||
|
138 | ae279d4a19e9683214cbd1fe8298cf0b50571432 3.7.3 | |||
|
139 | 740156eedf2c450aee58b1a90b0e826f47c5da64 3.8-rc | |||
|
140 | f85de28eae32e7d3064b1a1321309071bbaaa069 3.8 | |||
|
141 | a56296f55a5e1038ea5016dace2076b693c28a56 3.8.1 | |||
|
142 | aaabed77791a75968a12b8c43ad263631a23ee81 3.8.2 | |||
|
143 | a9764ab80e11bcf6a37255db7dd079011f767c6c 3.8.3 | |||
|
144 | 26a5d605b8683a292bb89aea11f37a81b06ac016 3.8.4 | |||
|
145 | 519bb4f9d3a47a6e83c2b414d58811ed38f503c2 3.9-rc | |||
|
146 | 299546f84e68dbb9bd026f0f3a974ce4bdb93686 3.9 | |||
|
147 | ccd436f7db6d5d7b9af89715179b911d031d44f1 3.9.1 | |||
|
148 | 149433e68974eb5c63ccb03f794d8b57339a80c4 3.9.2 | |||
|
149 | 438173c415874f6ac653efc1099dec9c9150e90f 4.0-rc | |||
|
150 | eab27446995210c334c3d06f1a659e3b9b5da769 4.0 | |||
|
151 | b3b1ae98f6a0e14c1e1ba806a6c18e193b6dae5c 4.0.1 | |||
|
152 | e69874dc1f4e142746ff3df91e678a09c6fc208c 4.0.2 | |||
|
153 | a1dd2c0c479e0550040542e392e87bc91262517e 4.1-rc | |||
|
154 | e1526da1e6d84e03146151c9b6e6950fe9a83d7d 4.1 | |||
|
155 | 25703b624d27e3917d978af56d6ad59331e0464a 4.1.1 | |||
|
156 | ed5b25874d998ababb181a939dd37a16ea644435 4.1.2 | |||
|
157 | 77eaf9539499a1b8be259ffe7ada787d07857f80 4.1.3 | |||
|
158 | 616e788321cc4ae9975b7f0c54c849f36d82182b 4.2-rc | |||
|
159 | bb96d4a497432722623ae60d9bc734a1e360179e 4.2 | |||
|
160 | c850f0ed54c1d42f9aa079ad528f8127e5775217 4.2.1 | |||
|
161 | 26c49ed51a698ec016d2b4c6b44ca3c3f73cc788 4.2.2 | |||
|
162 | 857876ebaed4e315f63157bd157d6ce553c7ab73 4.3-rc | |||
|
163 | 5544af8622863796a0027566f6b646e10d522c4c 4.3 | |||
|
164 | 943c91326b23954e6e1c6960d0239511f9530258 4.2.3 | |||
|
165 | 3fee7f7d2da04226914c2258cc2884dc27384fd7 4.3.1 | |||
|
166 | 920977f72c7b70acfdaf56ab35360584d7845827 4.3.2 | |||
|
167 | 2f427b57bf9019c6dc3750baa539dc22c1be50f6 4.3.3 | |||
|
168 | 1e2454b60e5936f5e77498cab2648db469504487 4.4-rc | |||
|
169 | 0ccb43d4cf01d013ae05917ec4f305509f851b2d 4.4 | |||
|
170 | cabc840ffdee8a72f3689fb77dd74d04fdc2bc04 4.4.1 | |||
|
171 | a92b9f8e11ba330614cdfd6af0e03b15c1ff3797 4.4.2 | |||
|
172 | 27b6df1b5adbdf647cf5c6675b40575e1b197c60 4.5-rc | |||
|
173 | d334afc585e29577f271c5eda03378736a16ca6b 4.5 | |||
|
174 | 369aadf7a3264b03c8b09efce715bc41e6ab4a9b 4.5.1 | |||
|
175 | 8bba684efde7f45add05f737952093bb2aa07155 4.5.2 | |||
|
176 | 7de7bd407251af2bc98e5b809c8598ee95830daf 4.5.3 | |||
|
177 | ed5448edcbfa747b9154099e18630e49024fd47b 4.6rc0 | |||
|
178 | 1ec874717d8a93b19e0d50628443e0ee5efab3a9 4.6rc1 | |||
|
179 | 6614cac550aea66d19c601e45efd1b7bd08d7c40 4.6 | |||
|
180 | 9c5ced5276d6e7d54f7c3dadf5247b7ee98ec79c 4.6.1 | |||
|
181 | 0b63a6743010dfdbf8a8154186e119949bdaa1cc 4.6.2 | |||
|
182 | e90130af47ce8dd53a3109aed9d15876b3e7dee8 4.7rc0 | |||
|
183 | 33ac6a72308a215e6086fbced347ec10aa963b0a 4.7 |
@@ -0,0 +1,11 b'' | |||||
|
1 | { | |||
|
2 | // Enforcing | |||
|
3 | "eqeqeq" : true, // true: Require triple equals (===) for comparison | |||
|
4 | "forin" : true, // true: Require filtering for..in loops with obj.hasOwnProperty() | |||
|
5 | "freeze" : true, // true: prohibits overwriting prototypes of native objects such as Array, Date etc. | |||
|
6 | "nonbsp" : true, // true: Prohibit "non-breaking whitespace" characters. | |||
|
7 | "undef" : true, // true: Require all non-global variables to be declared (prevents global leaks) | |||
|
8 | ||||
|
9 | // Environments | |||
|
10 | "browser" : true // Web Browser (window, document, etc) | |||
|
11 | } |
@@ -0,0 +1,13 b'' | |||||
|
1 | Our full contribution guidelines are in our wiki, please see: | |||
|
2 | ||||
|
3 | https://www.mercurial-scm.org/wiki/ContributingChanges | |||
|
4 | ||||
|
5 | If you just want a checklist to follow, you can go straight to | |||
|
6 | ||||
|
7 | https://www.mercurial-scm.org/wiki/ContributingChanges#Submission_checklist | |||
|
8 | ||||
|
9 | If you can't run the entire testsuite for some reason (it can be | |||
|
10 | difficult on Windows), please at least run `contrib/check-code.py` on | |||
|
11 | any files you've modified and run `python contrib/check-commit` on any | |||
|
12 | commits you've made (for example, `python contrib/check-commit | |||
|
13 | 273ce12ad8f1` will report some style violations on a very old commit). |
@@ -0,0 +1,41 b'' | |||||
|
1 | [This file is here for historical purposes, all recent contributors | |||
|
2 | should appear in the changelog directly] | |||
|
3 | ||||
|
4 | Andrea Arcangeli <andrea at suse.de> | |||
|
5 | Thomas Arendsen Hein <thomas at intevation.de> | |||
|
6 | Goffredo Baroncelli <kreijack at libero.it> | |||
|
7 | Muli Ben-Yehuda <mulix at mulix.org> | |||
|
8 | Mikael Berthe <mikael at lilotux.net> | |||
|
9 | Benoit Boissinot <bboissin at gmail.com> | |||
|
10 | Brendan Cully <brendan at kublai.com> | |||
|
11 | Vincent Danjean <vdanjean.ml at free.fr> | |||
|
12 | Jake Edge <jake at edge2.net> | |||
|
13 | Michael Fetterman <michael.fetterman at intel.com> | |||
|
14 | Edouard Gomez <ed.gomez at free.fr> | |||
|
15 | Eric Hopper <hopper at omnifarious.org> | |||
|
16 | Alecs King <alecsk at gmail.com> | |||
|
17 | Volker Kleinfeld <Volker.Kleinfeld at gmx.de> | |||
|
18 | Vadim Lebedev <vadim at mbdsys.com> | |||
|
19 | Christopher Li <hg at chrisli.org> | |||
|
20 | Chris Mason <mason at suse.com> | |||
|
21 | Colin McMillen <mcmillen at cs.cmu.edu> | |||
|
22 | Wojciech Milkowski <wmilkowski at interia.pl> | |||
|
23 | Chad Netzer <chad.netzer at gmail.com> | |||
|
24 | Bryan O'Sullivan <bos at serpentine.com> | |||
|
25 | Vicent Seguí Pascual <vseguip at gmail.com> | |||
|
26 | Sean Perry <shaleh at speakeasy.net> | |||
|
27 | Nguyen Anh Quynh <aquynh at gmail.com> | |||
|
28 | Ollivier Robert <roberto at keltia.freenix.fr> | |||
|
29 | Alexander Schremmer <alex at alexanderweb.de> | |||
|
30 | Arun Sharma <arun at sharma-home.net> | |||
|
31 | Josef "Jeff" Sipek <jeffpc at optonline.net> | |||
|
32 | Kevin Smith <yarcs at qualitycode.com> | |||
|
33 | TK Soh <teekaysoh at yahoo.com> | |||
|
34 | Radoslaw Szkodzinski <astralstorm at gorzow.mm.pl> | |||
|
35 | Samuel Tardieu <sam at rfc1149.net> | |||
|
36 | K Thananchayan <thananck at yahoo.com> | |||
|
37 | Andrew Thompson <andrewkt at aktzero.com> | |||
|
38 | Michael S. Tsirkin <mst at mellanox.co.il> | |||
|
39 | Rafael Villar Burke <pachi at mmn-arquitectos.com> | |||
|
40 | Tristan Wibberley <tristan at wibberley.org> | |||
|
41 | Mark Williamson <mark.williamson at cl.cam.ac.uk> |
@@ -0,0 +1,339 b'' | |||||
|
1 | GNU GENERAL PUBLIC LICENSE | |||
|
2 | Version 2, June 1991 | |||
|
3 | ||||
|
4 | Copyright (C) 1989, 1991 Free Software Foundation, Inc., | |||
|
5 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |||
|
6 | Everyone is permitted to copy and distribute verbatim copies | |||
|
7 | of this license document, but changing it is not allowed. | |||
|
8 | ||||
|
9 | Preamble | |||
|
10 | ||||
|
11 | The licenses for most software are designed to take away your | |||
|
12 | freedom to share and change it. By contrast, the GNU General Public | |||
|
13 | License is intended to guarantee your freedom to share and change free | |||
|
14 | software--to make sure the software is free for all its users. This | |||
|
15 | General Public License applies to most of the Free Software | |||
|
16 | Foundation's software and to any other program whose authors commit to | |||
|
17 | using it. (Some other Free Software Foundation software is covered by | |||
|
18 | the GNU Lesser General Public License instead.) You can apply it to | |||
|
19 | your programs, too. | |||
|
20 | ||||
|
21 | When we speak of free software, we are referring to freedom, not | |||
|
22 | price. Our General Public Licenses are designed to make sure that you | |||
|
23 | have the freedom to distribute copies of free software (and charge for | |||
|
24 | this service if you wish), that you receive source code or can get it | |||
|
25 | if you want it, that you can change the software or use pieces of it | |||
|
26 | in new free programs; and that you know you can do these things. | |||
|
27 | ||||
|
28 | To protect your rights, we need to make restrictions that forbid | |||
|
29 | anyone to deny you these rights or to ask you to surrender the rights. | |||
|
30 | These restrictions translate to certain responsibilities for you if you | |||
|
31 | distribute copies of the software, or if you modify it. | |||
|
32 | ||||
|
33 | For example, if you distribute copies of such a program, whether | |||
|
34 | gratis or for a fee, you must give the recipients all the rights that | |||
|
35 | you have. You must make sure that they, too, receive or can get the | |||
|
36 | source code. And you must show them these terms so they know their | |||
|
37 | rights. | |||
|
38 | ||||
|
39 | We protect your rights with two steps: (1) copyright the software, and | |||
|
40 | (2) offer you this license which gives you legal permission to copy, | |||
|
41 | distribute and/or modify the software. | |||
|
42 | ||||
|
43 | Also, for each author's protection and ours, we want to make certain | |||
|
44 | that everyone understands that there is no warranty for this free | |||
|
45 | software. If the software is modified by someone else and passed on, we | |||
|
46 | want its recipients to know that what they have is not the original, so | |||
|
47 | that any problems introduced by others will not reflect on the original | |||
|
48 | authors' reputations. | |||
|
49 | ||||
|
50 | Finally, any free program is threatened constantly by software | |||
|
51 | patents. We wish to avoid the danger that redistributors of a free | |||
|
52 | program will individually obtain patent licenses, in effect making the | |||
|
53 | program proprietary. To prevent this, we have made it clear that any | |||
|
54 | patent must be licensed for everyone's free use or not licensed at all. | |||
|
55 | ||||
|
56 | The precise terms and conditions for copying, distribution and | |||
|
57 | modification follow. | |||
|
58 | ||||
|
59 | GNU GENERAL PUBLIC LICENSE | |||
|
60 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION | |||
|
61 | ||||
|
62 | 0. This License applies to any program or other work which contains | |||
|
63 | a notice placed by the copyright holder saying it may be distributed | |||
|
64 | under the terms of this General Public License. The "Program", below, | |||
|
65 | refers to any such program or work, and a "work based on the Program" | |||
|
66 | means either the Program or any derivative work under copyright law: | |||
|
67 | that is to say, a work containing the Program or a portion of it, | |||
|
68 | either verbatim or with modifications and/or translated into another | |||
|
69 | language. (Hereinafter, translation is included without limitation in | |||
|
70 | the term "modification".) Each licensee is addressed as "you". | |||
|
71 | ||||
|
72 | Activities other than copying, distribution and modification are not | |||
|
73 | covered by this License; they are outside its scope. The act of | |||
|
74 | running the Program is not restricted, and the output from the Program | |||
|
75 | is covered only if its contents constitute a work based on the | |||
|
76 | Program (independent of having been made by running the Program). | |||
|
77 | Whether that is true depends on what the Program does. | |||
|
78 | ||||
|
79 | 1. You may copy and distribute verbatim copies of the Program's | |||
|
80 | source code as you receive it, in any medium, provided that you | |||
|
81 | conspicuously and appropriately publish on each copy an appropriate | |||
|
82 | copyright notice and disclaimer of warranty; keep intact all the | |||
|
83 | notices that refer to this License and to the absence of any warranty; | |||
|
84 | and give any other recipients of the Program a copy of this License | |||
|
85 | along with the Program. | |||
|
86 | ||||
|
87 | You may charge a fee for the physical act of transferring a copy, and | |||
|
88 | you may at your option offer warranty protection in exchange for a fee. | |||
|
89 | ||||
|
90 | 2. You may modify your copy or copies of the Program or any portion | |||
|
91 | of it, thus forming a work based on the Program, and copy and | |||
|
92 | distribute such modifications or work under the terms of Section 1 | |||
|
93 | above, provided that you also meet all of these conditions: | |||
|
94 | ||||
|
95 | a) You must cause the modified files to carry prominent notices | |||
|
96 | stating that you changed the files and the date of any change. | |||
|
97 | ||||
|
98 | b) You must cause any work that you distribute or publish, that in | |||
|
99 | whole or in part contains or is derived from the Program or any | |||
|
100 | part thereof, to be licensed as a whole at no charge to all third | |||
|
101 | parties under the terms of this License. | |||
|
102 | ||||
|
103 | c) If the modified program normally reads commands interactively | |||
|
104 | when run, you must cause it, when started running for such | |||
|
105 | interactive use in the most ordinary way, to print or display an | |||
|
106 | announcement including an appropriate copyright notice and a | |||
|
107 | notice that there is no warranty (or else, saying that you provide | |||
|
108 | a warranty) and that users may redistribute the program under | |||
|
109 | these conditions, and telling the user how to view a copy of this | |||
|
110 | License. (Exception: if the Program itself is interactive but | |||
|
111 | does not normally print such an announcement, your work based on | |||
|
112 | the Program is not required to print an announcement.) | |||
|
113 | ||||
|
114 | These requirements apply to the modified work as a whole. If | |||
|
115 | identifiable sections of that work are not derived from the Program, | |||
|
116 | and can be reasonably considered independent and separate works in | |||
|
117 | themselves, then this License, and its terms, do not apply to those | |||
|
118 | sections when you distribute them as separate works. But when you | |||
|
119 | distribute the same sections as part of a whole which is a work based | |||
|
120 | on the Program, the distribution of the whole must be on the terms of | |||
|
121 | this License, whose permissions for other licensees extend to the | |||
|
122 | entire whole, and thus to each and every part regardless of who wrote it. | |||
|
123 | ||||
|
124 | Thus, it is not the intent of this section to claim rights or contest | |||
|
125 | your rights to work written entirely by you; rather, the intent is to | |||
|
126 | exercise the right to control the distribution of derivative or | |||
|
127 | collective works based on the Program. | |||
|
128 | ||||
|
129 | In addition, mere aggregation of another work not based on the Program | |||
|
130 | with the Program (or with a work based on the Program) on a volume of | |||
|
131 | a storage or distribution medium does not bring the other work under | |||
|
132 | the scope of this License. | |||
|
133 | ||||
|
134 | 3. You may copy and distribute the Program (or a work based on it, | |||
|
135 | under Section 2) in object code or executable form under the terms of | |||
|
136 | Sections 1 and 2 above provided that you also do one of the following: | |||
|
137 | ||||
|
138 | a) Accompany it with the complete corresponding machine-readable | |||
|
139 | source code, which must be distributed under the terms of Sections | |||
|
140 | 1 and 2 above on a medium customarily used for software interchange; or, | |||
|
141 | ||||
|
142 | b) Accompany it with a written offer, valid for at least three | |||
|
143 | years, to give any third party, for a charge no more than your | |||
|
144 | cost of physically performing source distribution, a complete | |||
|
145 | machine-readable copy of the corresponding source code, to be | |||
|
146 | distributed under the terms of Sections 1 and 2 above on a medium | |||
|
147 | customarily used for software interchange; or, | |||
|
148 | ||||
|
149 | c) Accompany it with the information you received as to the offer | |||
|
150 | to distribute corresponding source code. (This alternative is | |||
|
151 | allowed only for noncommercial distribution and only if you | |||
|
152 | received the program in object code or executable form with such | |||
|
153 | an offer, in accord with Subsection b above.) | |||
|
154 | ||||
|
155 | The source code for a work means the preferred form of the work for | |||
|
156 | making modifications to it. For an executable work, complete source | |||
|
157 | code means all the source code for all modules it contains, plus any | |||
|
158 | associated interface definition files, plus the scripts used to | |||
|
159 | control compilation and installation of the executable. However, as a | |||
|
160 | special exception, the source code distributed need not include | |||
|
161 | anything that is normally distributed (in either source or binary | |||
|
162 | form) with the major components (compiler, kernel, and so on) of the | |||
|
163 | operating system on which the executable runs, unless that component | |||
|
164 | itself accompanies the executable. | |||
|
165 | ||||
|
166 | If distribution of executable or object code is made by offering | |||
|
167 | access to copy from a designated place, then offering equivalent | |||
|
168 | access to copy the source code from the same place counts as | |||
|
169 | distribution of the source code, even though third parties are not | |||
|
170 | compelled to copy the source along with the object code. | |||
|
171 | ||||
|
172 | 4. You may not copy, modify, sublicense, or distribute the Program | |||
|
173 | except as expressly provided under this License. Any attempt | |||
|
174 | otherwise to copy, modify, sublicense or distribute the Program is | |||
|
175 | void, and will automatically terminate your rights under this License. | |||
|
176 | However, parties who have received copies, or rights, from you under | |||
|
177 | this License will not have their licenses terminated so long as such | |||
|
178 | parties remain in full compliance. | |||
|
179 | ||||
|
180 | 5. You are not required to accept this License, since you have not | |||
|
181 | signed it. However, nothing else grants you permission to modify or | |||
|
182 | distribute the Program or its derivative works. These actions are | |||
|
183 | prohibited by law if you do not accept this License. Therefore, by | |||
|
184 | modifying or distributing the Program (or any work based on the | |||
|
185 | Program), you indicate your acceptance of this License to do so, and | |||
|
186 | all its terms and conditions for copying, distributing or modifying | |||
|
187 | the Program or works based on it. | |||
|
188 | ||||
|
189 | 6. Each time you redistribute the Program (or any work based on the | |||
|
190 | Program), the recipient automatically receives a license from the | |||
|
191 | original licensor to copy, distribute or modify the Program subject to | |||
|
192 | these terms and conditions. You may not impose any further | |||
|
193 | restrictions on the recipients' exercise of the rights granted herein. | |||
|
194 | You are not responsible for enforcing compliance by third parties to | |||
|
195 | this License. | |||
|
196 | ||||
|
197 | 7. If, as a consequence of a court judgment or allegation of patent | |||
|
198 | infringement or for any other reason (not limited to patent issues), | |||
|
199 | conditions are imposed on you (whether by court order, agreement or | |||
|
200 | otherwise) that contradict the conditions of this License, they do not | |||
|
201 | excuse you from the conditions of this License. If you cannot | |||
|
202 | distribute so as to satisfy simultaneously your obligations under this | |||
|
203 | License and any other pertinent obligations, then as a consequence you | |||
|
204 | may not distribute the Program at all. For example, if a patent | |||
|
205 | license would not permit royalty-free redistribution of the Program by | |||
|
206 | all those who receive copies directly or indirectly through you, then | |||
|
207 | the only way you could satisfy both it and this License would be to | |||
|
208 | refrain entirely from distribution of the Program. | |||
|
209 | ||||
|
210 | If any portion of this section is held invalid or unenforceable under | |||
|
211 | any particular circumstance, the balance of the section is intended to | |||
|
212 | apply and the section as a whole is intended to apply in other | |||
|
213 | circumstances. | |||
|
214 | ||||
|
215 | It is not the purpose of this section to induce you to infringe any | |||
|
216 | patents or other property right claims or to contest validity of any | |||
|
217 | such claims; this section has the sole purpose of protecting the | |||
|
218 | integrity of the free software distribution system, which is | |||
|
219 | implemented by public license practices. Many people have made | |||
|
220 | generous contributions to the wide range of software distributed | |||
|
221 | through that system in reliance on consistent application of that | |||
|
222 | system; it is up to the author/donor to decide if he or she is willing | |||
|
223 | to distribute software through any other system and a licensee cannot | |||
|
224 | impose that choice. | |||
|
225 | ||||
|
226 | This section is intended to make thoroughly clear what is believed to | |||
|
227 | be a consequence of the rest of this License. | |||
|
228 | ||||
|
229 | 8. If the distribution and/or use of the Program is restricted in | |||
|
230 | certain countries either by patents or by copyrighted interfaces, the | |||
|
231 | original copyright holder who places the Program under this License | |||
|
232 | may add an explicit geographical distribution limitation excluding | |||
|
233 | those countries, so that distribution is permitted only in or among | |||
|
234 | countries not thus excluded. In such case, this License incorporates | |||
|
235 | the limitation as if written in the body of this License. | |||
|
236 | ||||
|
237 | 9. The Free Software Foundation may publish revised and/or new versions | |||
|
238 | of the General Public License from time to time. Such new versions will | |||
|
239 | be similar in spirit to the present version, but may differ in detail to | |||
|
240 | address new problems or concerns. | |||
|
241 | ||||
|
242 | Each version is given a distinguishing version number. If the Program | |||
|
243 | specifies a version number of this License which applies to it and "any | |||
|
244 | later version", you have the option of following the terms and conditions | |||
|
245 | either of that version or of any later version published by the Free | |||
|
246 | Software Foundation. If the Program does not specify a version number of | |||
|
247 | this License, you may choose any version ever published by the Free Software | |||
|
248 | Foundation. | |||
|
249 | ||||
|
250 | 10. If you wish to incorporate parts of the Program into other free | |||
|
251 | programs whose distribution conditions are different, write to the author | |||
|
252 | to ask for permission. For software which is copyrighted by the Free | |||
|
253 | Software Foundation, write to the Free Software Foundation; we sometimes | |||
|
254 | make exceptions for this. Our decision will be guided by the two goals | |||
|
255 | of preserving the free status of all derivatives of our free software and | |||
|
256 | of promoting the sharing and reuse of software generally. | |||
|
257 | ||||
|
258 | NO WARRANTY | |||
|
259 | ||||
|
260 | 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY | |||
|
261 | FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN | |||
|
262 | OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES | |||
|
263 | PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED | |||
|
264 | OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF | |||
|
265 | MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS | |||
|
266 | TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE | |||
|
267 | PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, | |||
|
268 | REPAIR OR CORRECTION. | |||
|
269 | ||||
|
270 | 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING | |||
|
271 | WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR | |||
|
272 | REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, | |||
|
273 | INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING | |||
|
274 | OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED | |||
|
275 | TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY | |||
|
276 | YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER | |||
|
277 | PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE | |||
|
278 | POSSIBILITY OF SUCH DAMAGES. | |||
|
279 | ||||
|
280 | END OF TERMS AND CONDITIONS | |||
|
281 | ||||
|
282 | How to Apply These Terms to Your New Programs | |||
|
283 | ||||
|
284 | If you develop a new program, and you want it to be of the greatest | |||
|
285 | possible use to the public, the best way to achieve this is to make it | |||
|
286 | free software which everyone can redistribute and change under these terms. | |||
|
287 | ||||
|
288 | To do so, attach the following notices to the program. It is safest | |||
|
289 | to attach them to the start of each source file to most effectively | |||
|
290 | convey the exclusion of warranty; and each file should have at least | |||
|
291 | the "copyright" line and a pointer to where the full notice is found. | |||
|
292 | ||||
|
293 | <one line to give the program's name and a brief idea of what it does.> | |||
|
294 | Copyright (C) <year> <name of author> | |||
|
295 | ||||
|
296 | This program is free software; you can redistribute it and/or modify | |||
|
297 | it under the terms of the GNU General Public License as published by | |||
|
298 | the Free Software Foundation; either version 2 of the License, or | |||
|
299 | (at your option) any later version. | |||
|
300 | ||||
|
301 | This program is distributed in the hope that it will be useful, | |||
|
302 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |||
|
303 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |||
|
304 | GNU General Public License for more details. | |||
|
305 | ||||
|
306 | You should have received a copy of the GNU General Public License along | |||
|
307 | with this program; if not, write to the Free Software Foundation, Inc., | |||
|
308 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | |||
|
309 | ||||
|
310 | Also add information on how to contact you by electronic and paper mail. | |||
|
311 | ||||
|
312 | If the program is interactive, make it output a short notice like this | |||
|
313 | when it starts in an interactive mode: | |||
|
314 | ||||
|
315 | Gnomovision version 69, Copyright (C) year name of author | |||
|
316 | Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. | |||
|
317 | This is free software, and you are welcome to redistribute it | |||
|
318 | under certain conditions; type `show c' for details. | |||
|
319 | ||||
|
320 | The hypothetical commands `show w' and `show c' should show the appropriate | |||
|
321 | parts of the General Public License. Of course, the commands you use may | |||
|
322 | be called something other than `show w' and `show c'; they could even be | |||
|
323 | mouse-clicks or menu items--whatever suits your program. | |||
|
324 | ||||
|
325 | You should also get your employer (if you work as a programmer) or your | |||
|
326 | school, if any, to sign a "copyright disclaimer" for the program, if | |||
|
327 | necessary. Here is a sample; alter the names: | |||
|
328 | ||||
|
329 | Yoyodyne, Inc., hereby disclaims all copyright interest in the program | |||
|
330 | `Gnomovision' (which makes passes at compilers) written by James Hacker. | |||
|
331 | ||||
|
332 | <signature of Ty Coon>, 1 April 1989 | |||
|
333 | Ty Coon, President of Vice | |||
|
334 | ||||
|
335 | This General Public License does not permit incorporating your program into | |||
|
336 | proprietary programs. If your program is a subroutine library, you may | |||
|
337 | consider it more useful to permit linking proprietary applications with the | |||
|
338 | library. If this is what you want to do, use the GNU Lesser General | |||
|
339 | Public License instead of this License. |
@@ -0,0 +1,243 b'' | |||||
|
1 | # If you want to change PREFIX, do not just edit it below. The changed | |||
|
2 | # value wont get passed on to recursive make calls. You should instead | |||
|
3 | # override the variable on the command like: | |||
|
4 | # | |||
|
5 | # % make PREFIX=/opt/ install | |||
|
6 | ||||
|
7 | export PREFIX=/usr/local | |||
|
8 | PYTHON=python | |||
|
9 | $(eval HGROOT := $(shell pwd)) | |||
|
10 | HGPYTHONS ?= $(HGROOT)/build/pythons | |||
|
11 | PURE= | |||
|
12 | PYFILES:=$(shell find mercurial hgext doc -name '*.py') | |||
|
13 | DOCFILES=mercurial/help/*.txt | |||
|
14 | export LANGUAGE=C | |||
|
15 | export LC_ALL=C | |||
|
16 | TESTFLAGS ?= $(shell echo $$HGTESTFLAGS) | |||
|
17 | OSXVERSIONFLAGS ?= $(shell echo $$OSXVERSIONFLAGS) | |||
|
18 | ||||
|
19 | # Set this to e.g. "mingw32" to use a non-default compiler. | |||
|
20 | COMPILER= | |||
|
21 | ||||
|
22 | COMPILERFLAG_tmp_ = | |||
|
23 | COMPILERFLAG_tmp_${COMPILER} ?= -c $(COMPILER) | |||
|
24 | COMPILERFLAG=${COMPILERFLAG_tmp_${COMPILER}} | |||
|
25 | ||||
|
26 | help: | |||
|
27 | @echo 'Commonly used make targets:' | |||
|
28 | @echo ' all - build program and documentation' | |||
|
29 | @echo ' install - install program and man pages to $$PREFIX ($(PREFIX))' | |||
|
30 | @echo ' install-home - install with setup.py install --home=$$HOME ($(HOME))' | |||
|
31 | @echo ' local - build for inplace usage' | |||
|
32 | @echo ' tests - run all tests in the automatic test suite' | |||
|
33 | @echo ' test-foo - run only specified tests (e.g. test-merge1.t)' | |||
|
34 | @echo ' dist - run all tests and create a source tarball in dist/' | |||
|
35 | @echo ' clean - remove files created by other targets' | |||
|
36 | @echo ' (except installed files or dist source tarball)' | |||
|
37 | @echo ' update-pot - update i18n/hg.pot' | |||
|
38 | @echo | |||
|
39 | @echo 'Example for a system-wide installation under /usr/local:' | |||
|
40 | @echo ' make all && su -c "make install" && hg version' | |||
|
41 | @echo | |||
|
42 | @echo 'Example for a local installation (usable in this directory):' | |||
|
43 | @echo ' make local && ./hg version' | |||
|
44 | ||||
|
45 | all: build doc | |||
|
46 | ||||
|
47 | local: | |||
|
48 | $(PYTHON) setup.py $(PURE) \ | |||
|
49 | build_py -c -d . \ | |||
|
50 | build_ext $(COMPILERFLAG) -i \ | |||
|
51 | build_hgexe $(COMPILERFLAG) -i \ | |||
|
52 | build_mo | |||
|
53 | env HGRCPATH= $(PYTHON) hg version | |||
|
54 | ||||
|
55 | build: | |||
|
56 | $(PYTHON) setup.py $(PURE) build $(COMPILERFLAG) | |||
|
57 | ||||
|
58 | wheel: | |||
|
59 | FORCE_SETUPTOOLS=1 $(PYTHON) setup.py $(PURE) bdist_wheel $(COMPILERFLAG) | |||
|
60 | ||||
|
61 | doc: | |||
|
62 | $(MAKE) -C doc | |||
|
63 | ||||
|
64 | cleanbutpackages: | |||
|
65 | -$(PYTHON) setup.py clean --all # ignore errors from this command | |||
|
66 | find contrib doc hgext hgext3rd i18n mercurial tests hgdemandimport \ | |||
|
67 | \( -name '*.py[cdo]' -o -name '*.so' \) -exec rm -f '{}' ';' | |||
|
68 | rm -f MANIFEST MANIFEST.in hgext/__index__.py tests/*.err | |||
|
69 | rm -f mercurial/__modulepolicy__.py | |||
|
70 | if test -d .hg; then rm -f mercurial/__version__.py; fi | |||
|
71 | rm -rf build mercurial/locale | |||
|
72 | $(MAKE) -C doc clean | |||
|
73 | $(MAKE) -C contrib/chg distclean | |||
|
74 | ||||
|
75 | clean: cleanbutpackages | |||
|
76 | rm -rf packages | |||
|
77 | ||||
|
78 | install: install-bin install-doc | |||
|
79 | ||||
|
80 | install-bin: build | |||
|
81 | $(PYTHON) setup.py $(PURE) install --root="$(DESTDIR)/" --prefix="$(PREFIX)" --force | |||
|
82 | ||||
|
83 | install-doc: doc | |||
|
84 | cd doc && $(MAKE) $(MFLAGS) install | |||
|
85 | ||||
|
86 | install-home: install-home-bin install-home-doc | |||
|
87 | ||||
|
88 | install-home-bin: build | |||
|
89 | $(PYTHON) setup.py $(PURE) install --home="$(HOME)" --prefix="" --force | |||
|
90 | ||||
|
91 | install-home-doc: doc | |||
|
92 | cd doc && $(MAKE) $(MFLAGS) PREFIX="$(HOME)" install | |||
|
93 | ||||
|
94 | MANIFEST-doc: | |||
|
95 | $(MAKE) -C doc MANIFEST | |||
|
96 | ||||
|
97 | MANIFEST.in: MANIFEST-doc | |||
|
98 | hg manifest | sed -e 's/^/include /' > MANIFEST.in | |||
|
99 | echo include mercurial/__version__.py >> MANIFEST.in | |||
|
100 | sed -e 's/^/include /' < doc/MANIFEST >> MANIFEST.in | |||
|
101 | ||||
|
102 | dist: tests dist-notests | |||
|
103 | ||||
|
104 | dist-notests: doc MANIFEST.in | |||
|
105 | TAR_OPTIONS="--owner=root --group=root --mode=u+w,go-w,a+rX-s" $(PYTHON) setup.py -q sdist | |||
|
106 | ||||
|
107 | check: tests | |||
|
108 | ||||
|
109 | tests: | |||
|
110 | cd tests && $(PYTHON) run-tests.py $(TESTFLAGS) | |||
|
111 | ||||
|
112 | test-%: | |||
|
113 | cd tests && $(PYTHON) run-tests.py $(TESTFLAGS) $@ | |||
|
114 | ||||
|
115 | testpy-%: | |||
|
116 | @echo Looking for Python $* in $(HGPYTHONS) | |||
|
117 | [ -e $(HGPYTHONS)/$*/bin/python ] || ( \ | |||
|
118 | cd $$(mktemp --directory --tmpdir) && \ | |||
|
119 | $(MAKE) -f $(HGROOT)/contrib/Makefile.python PYTHONVER=$* PREFIX=$(HGPYTHONS)/$* python ) | |||
|
120 | cd tests && $(HGPYTHONS)/$*/bin/python run-tests.py $(TESTFLAGS) | |||
|
121 | ||||
|
122 | check-code: | |||
|
123 | hg manifest | xargs python contrib/check-code.py | |||
|
124 | ||||
|
125 | format-c: | |||
|
126 | clang-format --style file -i \ | |||
|
127 | `hg files 'set:(**.c or **.cc or **.h) and not "listfile:contrib/clang-format-ignorelist"'` | |||
|
128 | ||||
|
129 | update-pot: i18n/hg.pot | |||
|
130 | ||||
|
131 | i18n/hg.pot: $(PYFILES) $(DOCFILES) i18n/posplit i18n/hggettext | |||
|
132 | $(PYTHON) i18n/hggettext mercurial/commands.py \ | |||
|
133 | hgext/*.py hgext/*/__init__.py \ | |||
|
134 | mercurial/fileset.py mercurial/revset.py \ | |||
|
135 | mercurial/templatefilters.py \ | |||
|
136 | mercurial/templatefuncs.py \ | |||
|
137 | mercurial/templatekw.py \ | |||
|
138 | mercurial/filemerge.py \ | |||
|
139 | mercurial/hgweb/webcommands.py \ | |||
|
140 | mercurial/util.py \ | |||
|
141 | $(DOCFILES) > i18n/hg.pot.tmp | |||
|
142 | # All strings marked for translation in Mercurial contain | |||
|
143 | # ASCII characters only. But some files contain string | |||
|
144 | # literals like this '\037\213'. xgettext thinks it has to | |||
|
145 | # parse them even though they are not marked for translation. | |||
|
146 | # Extracting with an explicit encoding of ISO-8859-1 will make | |||
|
147 | # xgettext "parse" and ignore them. | |||
|
148 | echo $(PYFILES) | xargs \ | |||
|
149 | xgettext --package-name "Mercurial" \ | |||
|
150 | --msgid-bugs-address "<mercurial-devel@mercurial-scm.org>" \ | |||
|
151 | --copyright-holder "Matt Mackall <mpm@selenic.com> and others" \ | |||
|
152 | --from-code ISO-8859-1 --join --sort-by-file --add-comments=i18n: \ | |||
|
153 | -d hg -p i18n -o hg.pot.tmp | |||
|
154 | $(PYTHON) i18n/posplit i18n/hg.pot.tmp | |||
|
155 | # The target file is not created before the last step. So it never is in | |||
|
156 | # an intermediate state. | |||
|
157 | mv -f i18n/hg.pot.tmp i18n/hg.pot | |||
|
158 | ||||
|
159 | %.po: i18n/hg.pot | |||
|
160 | # work on a temporary copy for never having a half completed target | |||
|
161 | cp $@ $@.tmp | |||
|
162 | msgmerge --no-location --update $@.tmp $^ | |||
|
163 | mv -f $@.tmp $@ | |||
|
164 | ||||
|
165 | # Packaging targets | |||
|
166 | ||||
|
167 | packaging_targets := \ | |||
|
168 | centos5 \ | |||
|
169 | centos6 \ | |||
|
170 | centos7 \ | |||
|
171 | deb \ | |||
|
172 | docker-centos5 \ | |||
|
173 | docker-centos6 \ | |||
|
174 | docker-centos7 \ | |||
|
175 | docker-debian-jessie \ | |||
|
176 | docker-debian-stretch \ | |||
|
177 | docker-fedora20 \ | |||
|
178 | docker-fedora21 \ | |||
|
179 | docker-fedora28 \ | |||
|
180 | docker-ubuntu-trusty \ | |||
|
181 | docker-ubuntu-trusty-ppa \ | |||
|
182 | docker-ubuntu-xenial \ | |||
|
183 | docker-ubuntu-xenial-ppa \ | |||
|
184 | docker-ubuntu-artful \ | |||
|
185 | docker-ubuntu-artful-ppa \ | |||
|
186 | docker-ubuntu-bionic \ | |||
|
187 | docker-ubuntu-bionic-ppa \ | |||
|
188 | fedora20 \ | |||
|
189 | fedora21 \ | |||
|
190 | fedora28 \ | |||
|
191 | linux-wheels \ | |||
|
192 | linux-wheels-x86_64 \ | |||
|
193 | linux-wheels-i686 \ | |||
|
194 | ppa | |||
|
195 | ||||
|
196 | # Forward packaging targets for convenience. | |||
|
197 | $(packaging_targets): | |||
|
198 | $(MAKE) -C contrib/packaging $@ | |||
|
199 | ||||
|
200 | osx: | |||
|
201 | rm -rf build/mercurial | |||
|
202 | /usr/bin/python2.7 setup.py install --optimize=1 \ | |||
|
203 | --root=build/mercurial/ --prefix=/usr/local/ \ | |||
|
204 | --install-lib=/Library/Python/2.7/site-packages/ | |||
|
205 | make -C doc all install DESTDIR="$(PWD)/build/mercurial/" | |||
|
206 | # Place a bogon .DS_Store file in the target dir so we can be | |||
|
207 | # sure it doesn't get included in the final package. | |||
|
208 | touch build/mercurial/.DS_Store | |||
|
209 | # install zsh completions - this location appears to be | |||
|
210 | # searched by default as of macOS Sierra. | |||
|
211 | install -d build/mercurial/usr/local/share/zsh/site-functions/ | |||
|
212 | install -m 0644 contrib/zsh_completion build/mercurial/usr/local/share/zsh/site-functions/_hg | |||
|
213 | # install bash completions - there doesn't appear to be a | |||
|
214 | # place that's searched by default for bash, so we'll follow | |||
|
215 | # the lead of Apple's git install and just put it in a | |||
|
216 | # location of our own. | |||
|
217 | install -d build/mercurial/usr/local/hg/contrib/ | |||
|
218 | install -m 0644 contrib/bash_completion build/mercurial/usr/local/hg/contrib/hg-completion.bash | |||
|
219 | make -C contrib/chg \ | |||
|
220 | HGPATH=/usr/local/bin/hg \ | |||
|
221 | PYTHON=/usr/bin/python2.7 \ | |||
|
222 | HGEXTDIR=/Library/Python/2.7/site-packages/hgext \ | |||
|
223 | DESTDIR=../../build/mercurial \ | |||
|
224 | PREFIX=/usr/local \ | |||
|
225 | clean install | |||
|
226 | mkdir -p $${OUTPUTDIR:-dist} | |||
|
227 | HGVER=$$(python contrib/genosxversion.py $(OSXVERSIONFLAGS) build/mercurial/Library/Python/2.7/site-packages/mercurial/__version__.py) && \ | |||
|
228 | OSXVER=$$(sw_vers -productVersion | cut -d. -f1,2) && \ | |||
|
229 | pkgbuild --filter \\.DS_Store --root build/mercurial/ \ | |||
|
230 | --identifier org.mercurial-scm.mercurial \ | |||
|
231 | --version "$${HGVER}" \ | |||
|
232 | build/mercurial.pkg && \ | |||
|
233 | productbuild --distribution contrib/packaging/macosx/distribution.xml \ | |||
|
234 | --package-path build/ \ | |||
|
235 | --version "$${HGVER}" \ | |||
|
236 | --resources contrib/packaging/macosx/ \ | |||
|
237 | "$${OUTPUTDIR:-dist/}"/Mercurial-"$${HGVER}"-macosx"$${OSXVER}".pkg | |||
|
238 | ||||
|
239 | .PHONY: help all local build doc cleanbutpackages clean install install-bin \ | |||
|
240 | install-doc install-home install-home-bin install-home-doc \ | |||
|
241 | dist dist-notests check tests check-code format-c update-pot \ | |||
|
242 | $(packaging_targets) \ | |||
|
243 | osx |
@@ -0,0 +1,20 b'' | |||||
|
1 | Mercurial | |||
|
2 | ========= | |||
|
3 | ||||
|
4 | Mercurial is a fast, easy to use, distributed revision control tool | |||
|
5 | for software developers. | |||
|
6 | ||||
|
7 | Basic install:: | |||
|
8 | ||||
|
9 | $ make # see install targets | |||
|
10 | $ make install # do a system-wide install | |||
|
11 | $ hg debuginstall # sanity-check setup | |||
|
12 | $ hg # see help | |||
|
13 | ||||
|
14 | Running without installing:: | |||
|
15 | ||||
|
16 | $ make local # build for inplace usage | |||
|
17 | $ ./hg --version # should show the latest version | |||
|
18 | ||||
|
19 | See https://mercurial-scm.org/ for detailed installation | |||
|
20 | instructions, platform-specific notes, and Mercurial user information. |
@@ -0,0 +1,76 b'' | |||||
|
1 | PYTHONVER=2.7.14 | |||
|
2 | PYTHONNAME=python- | |||
|
3 | PREFIX=$(HOME)/bin/prefix-$(PYTHONNAME)$(PYTHONVER) | |||
|
4 | SYMLINKDIR=$(HOME)/bin | |||
|
5 | ||||
|
6 | help: | |||
|
7 | @echo | |||
|
8 | @echo 'Make a custom installation of a Python version' | |||
|
9 | @echo | |||
|
10 | @echo 'Common make parameters:' | |||
|
11 | @echo ' PYTHONVER=... [$(PYTHONVER)]' | |||
|
12 | @echo ' PREFIX=... [$(PREFIX)]' | |||
|
13 | @echo ' SYMLINKDIR=... [$(SYMLINKDIR) creating $(PYTHONNAME)$(PYTHONVER)]' | |||
|
14 | @echo | |||
|
15 | @echo 'Common make targets:' | |||
|
16 | @echo ' python - install Python $$PYTHONVER in $$PREFIX' | |||
|
17 | @echo ' symlink - create a $$SYMLINKDIR/$(PYTHONNAME)$$PYTHONVER symlink' | |||
|
18 | @echo | |||
|
19 | @echo 'Example: create a temporary Python installation:' | |||
|
20 | @echo ' $$ make -f Makefile.python python PYTHONVER=${PYTHONVER} PREFIX=/tmp/p27' | |||
|
21 | @echo ' $$ /tmp/p27/bin/python -V' | |||
|
22 | @echo ' Python 2.7' | |||
|
23 | @echo | |||
|
24 | @echo 'Some external libraries are required for building Python: zlib bzip2 openssl.' | |||
|
25 | @echo 'Make sure their development packages are installed systemwide.' | |||
|
26 | # fedora: yum install zlib-devel bzip2-devel openssl-devel | |||
|
27 | # debian: apt-get install zlib1g-dev libbz2-dev libssl-dev | |||
|
28 | @echo | |||
|
29 | @echo 'To build a nice collection of interesting Python versions:' | |||
|
30 | @echo ' $$ for v in 2.{6{,.1,.2,.9},7{,.8,.10}}; do' | |||
|
31 | @echo ' make -f Makefile.python symlink PYTHONVER=$$v || break; done' | |||
|
32 | @echo 'To run a Mercurial test on all these Python versions:' | |||
|
33 | @echo ' $$ for py in `cd ~/bin && ls $(PYTHONNAME)2.*`; do' | |||
|
34 | @echo ' echo $$py; $$py run-tests.py test-http.t; echo; done' | |||
|
35 | @echo | |||
|
36 | ||||
|
37 | export LANGUAGE=C | |||
|
38 | export LC_ALL=C | |||
|
39 | ||||
|
40 | python: $(PREFIX)/bin/python docutils | |||
|
41 | printf 'import sys, zlib, bz2, docutils, ssl' | $(PREFIX)/bin/python | |||
|
42 | ||||
|
43 | PYTHON_SRCDIR=Python-$(PYTHONVER) | |||
|
44 | PYTHON_SRCFILE=$(PYTHON_SRCDIR).tgz | |||
|
45 | ||||
|
46 | $(PREFIX)/bin/python: | |||
|
47 | [ -f $(PYTHON_SRCFILE) ] || wget http://www.python.org/ftp/python/$(PYTHONVER)/$(PYTHON_SRCFILE) || curl -OL http://www.python.org/ftp/python/$(PYTHONVER)/$(PYTHON_SRCFILE) || [ -f $(PYTHON_SRCFILE) ] | |||
|
48 | rm -rf $(PYTHON_SRCDIR) | |||
|
49 | tar xf $(PYTHON_SRCFILE) | |||
|
50 | # Debian/Ubuntu disables SSLv2,3 the hard way, disable it on old Pythons too | |||
|
51 | -sed -i 's,self.*SSLv[23]_method(),0;//\0,g' $(PYTHON_SRCDIR)/Modules/_ssl.c | |||
|
52 | # Find multiarch system libraries on Ubuntu and disable fortify error when setting argv | |||
|
53 | LDFLAGS="-L/usr/lib/`dpkg-architecture -qDEB_HOST_MULTIARCH`"; \ | |||
|
54 | BASECFLAGS=-U_FORTIFY_SOURCE; \ | |||
|
55 | export LDFLAGS BASECFLAGS; \ | |||
|
56 | cd $(PYTHON_SRCDIR) && ./configure --prefix=$(PREFIX) && make all SVNVERSION=pwd && make install | |||
|
57 | printf 'import sys, zlib, bz2, ssl' | $(PREFIX)/bin/python | |||
|
58 | rm -rf $(PYTHON_SRCDIR) | |||
|
59 | ||||
|
60 | DOCUTILSVER=0.12 | |||
|
61 | DOCUTILS_SRCDIR=docutils-$(DOCUTILSVER) | |||
|
62 | DOCUTILS_SRCFILE=$(DOCUTILS_SRCDIR).tar.gz | |||
|
63 | ||||
|
64 | docutils: $(PREFIX)/bin/python | |||
|
65 | @$(PREFIX)/bin/python -c 'import docutils' || ( set -ex; \ | |||
|
66 | [ -f $(DOCUTILS_SRCFILE) ] || wget http://downloads.sourceforge.net/project/docutils/docutils/$(DOCUTILSVER)/$(DOCUTILS_SRCFILE) || [ -f $(DOCUTILS_SRCFILE) ]; \ | |||
|
67 | rm -rf $(DOCUTILS_SRCDIR); \ | |||
|
68 | tar xf $(DOCUTILS_SRCFILE); \ | |||
|
69 | cd $(DOCUTILS_SRCDIR) && $(PREFIX)/bin/python setup.py install --prefix=$(PREFIX); \ | |||
|
70 | $(PREFIX)/bin/python -c 'import docutils'; \ | |||
|
71 | rm -rf $(DOCUTILS_SRCDIR); ) | |||
|
72 | ||||
|
73 | symlink: python $(SYMLINKDIR) | |||
|
74 | ln -sf $(PREFIX)/bin/python $(SYMLINKDIR)/$(PYTHONNAME)$(PYTHONVER) | |||
|
75 | ||||
|
76 | .PHONY: help python docutils symlink |
@@ -0,0 +1,141 b'' | |||||
|
1 | # All revsets ever used with revsetbenchmarks.py script | |||
|
2 | # | |||
|
3 | # The goal of this file is to gather all revsets ever used for benchmarking | |||
|
4 | # revset's performance. It should be used to gather revsets that test a | |||
|
5 | # specific usecase or a specific implementation of revset predicates. | |||
|
6 | # If you are working on the smartset implementation itself, check | |||
|
7 | # 'base-revsets.txt'. | |||
|
8 | # | |||
|
9 | # Please update this file with any revsets you use for benchmarking a change so | |||
|
10 | # that future contributors can easily find and retest it when doing further | |||
|
11 | # modification. Feel free to highlight interesting variants if needed. | |||
|
12 | ||||
|
13 | ||||
|
14 | ## Revset from this section are all extracted from changelog when this file was | |||
|
15 | # created. Feel free to dig and improve documentation. | |||
|
16 | ||||
|
17 | # Used in revision da05fe01170b | |||
|
18 | (20000::) - (20000) | |||
|
19 | # Used in revision 95af98616aa7 | |||
|
20 | parents(20000) | |||
|
21 | # Used in revision 186fd06283b4 | |||
|
22 | (_intlist('20000\x0020001')) and merge() | |||
|
23 | # Used in revision 911f5a6579d1 | |||
|
24 | p1(20000) | |||
|
25 | p2(10000) | |||
|
26 | # Used in revision b6dc3b79bb25 | |||
|
27 | 0:: | |||
|
28 | # Used in revision faf4f63533ff | |||
|
29 | bookmark() | |||
|
30 | # Used in revision 22ba2c0825da | |||
|
31 | tip~25 | |||
|
32 | # Used in revision 0cf46b8298fe | |||
|
33 | bisect(range) | |||
|
34 | # Used in revision 5b65429721d5 | |||
|
35 | divergent() | |||
|
36 | # Used in revision 6261b9c549a2 | |||
|
37 | file(COPYING) | |||
|
38 | # Used in revision 44f471102f3a | |||
|
39 | follow(COPYING) | |||
|
40 | # Used in revision 8040a44aab1c | |||
|
41 | origin(tip) | |||
|
42 | # Used in revision bbf4f3dfd700 | |||
|
43 | rev(25) | |||
|
44 | # Used in revision a428db9ab61d | |||
|
45 | p1() | |||
|
46 | # Used in revision c1546d7400ef | |||
|
47 | min(0::) | |||
|
48 | # Used in revision 546fa6576815 | |||
|
49 | author(lmoscovicz) or author(mpm) | |||
|
50 | author(mpm) or author(lmoscovicz) | |||
|
51 | # Used in revision 9bfe68357c01 | |||
|
52 | public() and id("d82e2223f132") | |||
|
53 | # Used in revision ba89f7b542c9 | |||
|
54 | rev(25) | |||
|
55 | # Used in revision eb763217152a | |||
|
56 | rev(210000) | |||
|
57 | # Used in revision 69524a05a7fa | |||
|
58 | 10:100 | |||
|
59 | parents(10):parents(100) | |||
|
60 | # Used in revision 6f1b8b3f12fd | |||
|
61 | 100~5 | |||
|
62 | parents(100)~5 | |||
|
63 | (100~5)~5 | |||
|
64 | # Used in revision 7a42e5d4c418 | |||
|
65 | children(tip~100) | |||
|
66 | # Used in revision 7e8737e6ab08 | |||
|
67 | 100^1 | |||
|
68 | parents(100)^1 | |||
|
69 | (100^1)^1 | |||
|
70 | # Used in revision 30e0dcd7c5ff | |||
|
71 | matching(100) | |||
|
72 | matching(parents(100)) | |||
|
73 | # Used in revision aafeaba22826 | |||
|
74 | 0|1|2|3|4|5|6|7|8|9 | |||
|
75 | # Used in revision 33c7a94d4dd0 | |||
|
76 | tip:0 | |||
|
77 | # Used in revision 7d369fae098e | |||
|
78 | (0:100000) | |||
|
79 | # Used in revision b333ca94403d | |||
|
80 | 0 + 1 + 2 + ... + 200 | |||
|
81 | 0 + 1 + 2 + ... + 1000 | |||
|
82 | sort(0 + 1 + 2 + ... + 200) | |||
|
83 | sort(0 + 1 + 2 + ... + 1000) | |||
|
84 | # Used in revision 7fbef7932af9 | |||
|
85 | first(0 + 1 + 2 + ... + 1000) | |||
|
86 | # Used in revision ceaf04bb14ff | |||
|
87 | 0:1000 | |||
|
88 | # Used in revision 262e6ad93885 | |||
|
89 | not public() | |||
|
90 | (tip~1000::) - public() | |||
|
91 | not public() and branch("default") | |||
|
92 | # Used in revision 15412bba5a68 | |||
|
93 | 0::tip | |||
|
94 | ||||
|
95 | ## all the revsets from this section have been taken from the former central file | |||
|
96 | # for revset's benchmarking, they are undocumented for this reason. | |||
|
97 | all() | |||
|
98 | draft() | |||
|
99 | ::tip | |||
|
100 | draft() and ::tip | |||
|
101 | ::tip and draft() | |||
|
102 | author(lmoscovicz) | |||
|
103 | author(mpm) | |||
|
104 | ::p1(p1(tip)):: | |||
|
105 | public() | |||
|
106 | :10000 and public() | |||
|
107 | :10000 and draft() | |||
|
108 | (not public() - obsolete()) | |||
|
109 | ||||
|
110 | # The one below is used by rebase | |||
|
111 | (children(ancestor(tip~5, tip)) and ::(tip~5)):: | |||
|
112 | ||||
|
113 | # those two `roots(...)` inputs are close to what phase movement use. | |||
|
114 | roots((tip~100::) - (tip~100::tip)) | |||
|
115 | roots((0::) - (0::tip)) | |||
|
116 | ||||
|
117 | # more roots testing | |||
|
118 | roots(tip~100:) | |||
|
119 | roots(:42) | |||
|
120 | roots(not public()) | |||
|
121 | roots((0:tip)::) | |||
|
122 | roots(0::tip) | |||
|
123 | 42:68 and roots(42:tip) | |||
|
124 | # Used in revision f140d6207cca | |||
|
125 | roots(0:tip) | |||
|
126 | # test disjoint set with multiple roots | |||
|
127 | roots((:42) + (tip~42:)) | |||
|
128 | ||||
|
129 | # Testing the behavior of "head()" in various situations | |||
|
130 | head() | |||
|
131 | head() - public() | |||
|
132 | draft() and head() | |||
|
133 | head() and author("mpm") | |||
|
134 | ||||
|
135 | # testing the mutable phases set | |||
|
136 | draft() | |||
|
137 | secret() | |||
|
138 | ||||
|
139 | # test finding common ancestors | |||
|
140 | heads(commonancestors(last(head(), 2))) | |||
|
141 | heads(commonancestors(head())) |
@@ -0,0 +1,13 b'' | |||||
|
1 | { | |||
|
2 | "version": 1, | |||
|
3 | "project": "mercurial", | |||
|
4 | "project_url": "https://mercurial-scm.org/", | |||
|
5 | "repo": "..", | |||
|
6 | "branches": ["default", "stable"], | |||
|
7 | "environment_type": "virtualenv", | |||
|
8 | "show_commit_url": "https://www.mercurial-scm.org/repo/hg/rev/", | |||
|
9 | "benchmark_dir": "benchmarks", | |||
|
10 | "env_dir": "../.asv/env", | |||
|
11 | "results_dir": "../.asv/results", | |||
|
12 | "html_dir": "../.asv/html" | |||
|
13 | } |
@@ -0,0 +1,49 b'' | |||||
|
1 | # Base Revsets to be used with revsetbenchmarks.py script | |||
|
2 | # | |||
|
3 | # The goal of this file is to gather a limited amount of revsets that allow a | |||
|
4 | # good coverage of the internal revsets mechanisms. Revsets included should not | |||
|
5 | # be selected for their individual implementation, but for what they reveal of | |||
|
6 | # the internal implementation of smartsets classes (and their interactions). | |||
|
7 | # | |||
|
8 | # Use and update this file when you change internal implementation of these | |||
|
9 | # smartsets classes. Please include a comment explaining what each of your | |||
|
10 | # addition is testing. Also check if your changes to the smartset class makes | |||
|
11 | # some of the tests inadequate and replace them with a new one testing the same | |||
|
12 | # behavior. | |||
|
13 | # | |||
|
14 | # If you want to benchmark revsets predicate itself, check 'all-revsets.txt'. | |||
|
15 | # | |||
|
16 | # The current content of this file is currently likely not reaching this goal | |||
|
17 | # entirely, feel free, to audit its content and comment on each revset to | |||
|
18 | # highlight what internal mechanisms they test. | |||
|
19 | ||||
|
20 | all() | |||
|
21 | draft() | |||
|
22 | ::tip | |||
|
23 | draft() and ::tip | |||
|
24 | ::tip and draft() | |||
|
25 | 0::tip | |||
|
26 | roots(0::tip) | |||
|
27 | author(lmoscovicz) | |||
|
28 | author(mpm) | |||
|
29 | author(lmoscovicz) or author(mpm) | |||
|
30 | author(mpm) or author(lmoscovicz) | |||
|
31 | tip:0 | |||
|
32 | 0:: | |||
|
33 | # those two `roots(...)` inputs are close to what phase movement use. | |||
|
34 | roots((tip~100::) - (tip~100::tip)) | |||
|
35 | roots((0::) - (0::tip)) | |||
|
36 | 42:68 and roots(42:tip) | |||
|
37 | ::p1(p1(tip)):: | |||
|
38 | public() | |||
|
39 | :10000 and public() | |||
|
40 | draft() | |||
|
41 | :10000 and draft() | |||
|
42 | roots((0:tip)::) | |||
|
43 | (not public() - obsolete()) | |||
|
44 | (_intlist('20000\x0020001')) and merge() | |||
|
45 | parents(20000) | |||
|
46 | (20000::) - (20000) | |||
|
47 | # The one below is used by rebase | |||
|
48 | (children(ancestor(tip~5, tip)) and ::(tip~5)):: | |||
|
49 | heads(commonancestors(last(head(), 2))) |
This diff has been collapsed as it changes many lines, (644 lines changed) Show them Hide them | |||||
@@ -0,0 +1,644 b'' | |||||
|
1 | # bash completion for the Mercurial distributed SCM -*- sh -*- | |||
|
2 | ||||
|
3 | # Docs: | |||
|
4 | # | |||
|
5 | # If you source this file from your .bashrc, bash should be able to | |||
|
6 | # complete a command line that uses hg with all the available commands | |||
|
7 | # and options and sometimes even arguments. | |||
|
8 | # | |||
|
9 | # Mercurial allows you to define additional commands through extensions. | |||
|
10 | # Bash should be able to automatically figure out the name of these new | |||
|
11 | # commands and their options. See below for how to define _hg_opt_foo | |||
|
12 | # and _hg_cmd_foo functions to fine-tune the completion for option and | |||
|
13 | # non-option arguments, respectively. | |||
|
14 | # | |||
|
15 | # | |||
|
16 | # Notes about completion for specific commands: | |||
|
17 | # | |||
|
18 | # - the completion function for the email command from the patchbomb | |||
|
19 | # extension will try to call _hg_emails to get a list of e-mail | |||
|
20 | # addresses. It's up to the user to define this function. For | |||
|
21 | # example, put the addresses of the lists that you usually patchbomb | |||
|
22 | # in ~/.patchbomb-to and the addresses that you usually use to send | |||
|
23 | # the patchbombs in ~/.patchbomb-from and use something like this: | |||
|
24 | # | |||
|
25 | # _hg_emails() | |||
|
26 | # { | |||
|
27 | # if [ -r ~/.patchbomb-$1 ]; then | |||
|
28 | # cat ~/.patchbomb-$1 | |||
|
29 | # fi | |||
|
30 | # } | |||
|
31 | # | |||
|
32 | # | |||
|
33 | # Writing completion functions for additional commands: | |||
|
34 | # | |||
|
35 | # If it exists, the function _hg_cmd_foo will be called without | |||
|
36 | # arguments to generate the completion candidates for the hg command | |||
|
37 | # "foo". If the command receives some arguments that aren't options | |||
|
38 | # even though they start with a "-", you can define a function called | |||
|
39 | # _hg_opt_foo to generate the completion candidates. If _hg_opt_foo | |||
|
40 | # doesn't return 0, regular completion for options is attempted. | |||
|
41 | # | |||
|
42 | # In addition to the regular completion variables provided by bash, | |||
|
43 | # the following variables are also set: | |||
|
44 | # - $hg - the hg program being used (e.g. /usr/bin/hg) | |||
|
45 | # - $cmd - the name of the hg command being completed | |||
|
46 | # - $cmd_index - the index of $cmd in $COMP_WORDS | |||
|
47 | # - $cur - the current argument being completed | |||
|
48 | # - $prev - the argument before $cur | |||
|
49 | # - $global_args - "|"-separated list of global options that accept | |||
|
50 | # an argument (e.g. '--cwd|-R|--repository') | |||
|
51 | # - $canonical - 1 if we canonicalized $cmd before calling the function | |||
|
52 | # 0 otherwise | |||
|
53 | # | |||
|
54 | ||||
|
55 | shopt -s extglob | |||
|
56 | ||||
|
57 | _hg_cmd() | |||
|
58 | { | |||
|
59 | HGPLAIN=1 "$hg" "$@" 2>/dev/null | |||
|
60 | } | |||
|
61 | ||||
|
62 | _hg_commands() | |||
|
63 | { | |||
|
64 | local commands | |||
|
65 | commands="$(HGPLAINEXCEPT=alias _hg_cmd debugcomplete "$cur")" || commands="" | |||
|
66 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$commands' -- "$cur")) | |||
|
67 | } | |||
|
68 | ||||
|
69 | _hg_paths() | |||
|
70 | { | |||
|
71 | local paths="$(_hg_cmd paths -q)" | |||
|
72 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$paths' -- "$cur")) | |||
|
73 | } | |||
|
74 | ||||
|
75 | _hg_repos() | |||
|
76 | { | |||
|
77 | local i | |||
|
78 | for i in $(compgen -d -- "$cur"); do | |||
|
79 | test ! -d "$i"/.hg || COMPREPLY=(${COMPREPLY[@]:-} "$i") | |||
|
80 | done | |||
|
81 | } | |||
|
82 | ||||
|
83 | _hg_debugpathcomplete() | |||
|
84 | { | |||
|
85 | local files="$(_hg_cmd debugpathcomplete $1 "$cur")" | |||
|
86 | local IFS=$'\n' | |||
|
87 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur")) | |||
|
88 | } | |||
|
89 | ||||
|
90 | _hg_status() | |||
|
91 | { | |||
|
92 | if [ -z "$HGCOMPLETE_NOSTATUS" ]; then | |||
|
93 | local files="$(_hg_cmd status -n$1 "glob:$cur**")" | |||
|
94 | local IFS=$'\n' | |||
|
95 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur")) | |||
|
96 | fi | |||
|
97 | } | |||
|
98 | ||||
|
99 | _hg_branches() | |||
|
100 | { | |||
|
101 | local branches="$(_hg_cmd branches -q)" | |||
|
102 | local IFS=$'\n' | |||
|
103 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$branches' -- "$cur")) | |||
|
104 | } | |||
|
105 | ||||
|
106 | _hg_bookmarks() | |||
|
107 | { | |||
|
108 | local bookmarks="$(_hg_cmd bookmarks -q)" | |||
|
109 | local IFS=$'\n' | |||
|
110 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$bookmarks' -- "$cur")) | |||
|
111 | } | |||
|
112 | ||||
|
113 | _hg_labels() | |||
|
114 | { | |||
|
115 | local labels="$(_hg_cmd debugnamecomplete "$cur")" | |||
|
116 | local IFS=$'\n' | |||
|
117 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$labels' -- "$cur")) | |||
|
118 | } | |||
|
119 | ||||
|
120 | # this is "kind of" ugly... | |||
|
121 | _hg_count_non_option() | |||
|
122 | { | |||
|
123 | local i count=0 | |||
|
124 | local filters="$1" | |||
|
125 | ||||
|
126 | for ((i=1; $i<=$COMP_CWORD; i++)); do | |||
|
127 | if [[ "${COMP_WORDS[i]}" != -* ]]; then | |||
|
128 | if [[ ${COMP_WORDS[i-1]} == @($filters|$global_args) ]]; then | |||
|
129 | continue | |||
|
130 | fi | |||
|
131 | count=$(($count + 1)) | |||
|
132 | fi | |||
|
133 | done | |||
|
134 | ||||
|
135 | echo $(($count - 1)) | |||
|
136 | } | |||
|
137 | ||||
|
138 | _hg_fix_wordlist() | |||
|
139 | { | |||
|
140 | local LASTCHAR=' ' | |||
|
141 | if [ ${#COMPREPLY[@]} = 1 ]; then | |||
|
142 | [ -d "$COMPREPLY" ] && LASTCHAR=/ | |||
|
143 | COMPREPLY=$(printf %q%s "$COMPREPLY" "$LASTCHAR") | |||
|
144 | else | |||
|
145 | for ((i=0; i < ${#COMPREPLY[@]}; i++)); do | |||
|
146 | [ -d "${COMPREPLY[$i]}" ] && COMPREPLY[$i]=${COMPREPLY[$i]}/ | |||
|
147 | done | |||
|
148 | fi | |||
|
149 | } | |||
|
150 | ||||
|
151 | _hg() | |||
|
152 | { | |||
|
153 | local cur prev cmd cmd_index opts i aliashg | |||
|
154 | # global options that receive an argument | |||
|
155 | local global_args='--cwd|-R|--repository' | |||
|
156 | local hg="$1" | |||
|
157 | local canonical=0 | |||
|
158 | ||||
|
159 | aliashg=$(alias $hg 2>/dev/null) | |||
|
160 | if [[ -n "$aliashg" ]]; then | |||
|
161 | aliashg=${aliashg#"alias $hg='"} | |||
|
162 | aliashg=${aliashg%"'"} | |||
|
163 | hg=$aliashg | |||
|
164 | fi | |||
|
165 | ||||
|
166 | COMPREPLY=() | |||
|
167 | cur="$2" | |||
|
168 | prev="$3" | |||
|
169 | ||||
|
170 | # searching for the command | |||
|
171 | # (first non-option argument that doesn't follow a global option that | |||
|
172 | # receives an argument) | |||
|
173 | for ((i=1; $i<=$COMP_CWORD; i++)); do | |||
|
174 | if [[ ${COMP_WORDS[i]} != -* ]]; then | |||
|
175 | if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then | |||
|
176 | cmd="${COMP_WORDS[i]}" | |||
|
177 | cmd_index=$i | |||
|
178 | break | |||
|
179 | fi | |||
|
180 | fi | |||
|
181 | done | |||
|
182 | ||||
|
183 | if [[ "$cur" == -* ]]; then | |||
|
184 | if [ "$(type -t "_hg_opt_$cmd")" = function ] && "_hg_opt_$cmd"; then | |||
|
185 | _hg_fix_wordlist | |||
|
186 | return | |||
|
187 | fi | |||
|
188 | ||||
|
189 | opts=$(HGPLAINEXCEPT=alias _hg_cmd debugcomplete --options "$cmd") | |||
|
190 | ||||
|
191 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$opts' -- "$cur")) | |||
|
192 | _hg_fix_wordlist | |||
|
193 | return | |||
|
194 | fi | |||
|
195 | ||||
|
196 | # global options | |||
|
197 | case "$prev" in | |||
|
198 | -R|--repository) | |||
|
199 | _hg_paths | |||
|
200 | _hg_repos | |||
|
201 | _hg_fix_wordlist | |||
|
202 | return | |||
|
203 | ;; | |||
|
204 | --cwd) | |||
|
205 | # Stick with default bash completion | |||
|
206 | _hg_fix_wordlist | |||
|
207 | return | |||
|
208 | ;; | |||
|
209 | esac | |||
|
210 | ||||
|
211 | if [ -z "$cmd" ] || [ $COMP_CWORD -eq $i ]; then | |||
|
212 | _hg_commands | |||
|
213 | _hg_fix_wordlist | |||
|
214 | return | |||
|
215 | fi | |||
|
216 | ||||
|
217 | # try to generate completion candidates for whatever command the user typed | |||
|
218 | local help | |||
|
219 | if _hg_command_specific; then | |||
|
220 | _hg_fix_wordlist | |||
|
221 | return | |||
|
222 | fi | |||
|
223 | ||||
|
224 | # canonicalize the command name and try again | |||
|
225 | help=$(_hg_cmd help "$cmd") | |||
|
226 | if [ $? -ne 0 ]; then | |||
|
227 | # Probably either the command doesn't exist or it's ambiguous | |||
|
228 | return | |||
|
229 | fi | |||
|
230 | cmd=${help#hg } | |||
|
231 | cmd=${cmd%%[$' \n']*} | |||
|
232 | canonical=1 | |||
|
233 | _hg_command_specific | |||
|
234 | _hg_fix_wordlist | |||
|
235 | } | |||
|
236 | ||||
|
237 | _hg_command_specific() | |||
|
238 | { | |||
|
239 | if [ "$(type -t "_hg_cmd_$cmd")" = function ]; then | |||
|
240 | "_hg_cmd_$cmd" | |||
|
241 | return 0 | |||
|
242 | fi | |||
|
243 | ||||
|
244 | if [ "$cmd" != status ]; then | |||
|
245 | case "$prev" in | |||
|
246 | -r|--rev) | |||
|
247 | if [[ $canonical = 1 || status != "$cmd"* ]]; then | |||
|
248 | _hg_labels | |||
|
249 | return 0 | |||
|
250 | fi | |||
|
251 | return 1 | |||
|
252 | ;; | |||
|
253 | -B|--bookmark) | |||
|
254 | if [[ $canonical = 1 || status != "$cmd"* ]]; then | |||
|
255 | _hg_bookmarks | |||
|
256 | return 0 | |||
|
257 | fi | |||
|
258 | return 1 | |||
|
259 | ;; | |||
|
260 | -b|--branch) | |||
|
261 | if [[ $canonical = 1 || status != "$cmd"* ]]; then | |||
|
262 | _hg_branches | |||
|
263 | return 0 | |||
|
264 | fi | |||
|
265 | return 1 | |||
|
266 | ;; | |||
|
267 | esac | |||
|
268 | fi | |||
|
269 | ||||
|
270 | local aliascmd=$(_hg_cmd showconfig alias.$cmd | awk '{print $1}') | |||
|
271 | [ -n "$aliascmd" ] && cmd=$aliascmd | |||
|
272 | ||||
|
273 | case "$cmd" in | |||
|
274 | help) | |||
|
275 | _hg_commands | |||
|
276 | ;; | |||
|
277 | export) | |||
|
278 | if _hg_ext_mq_patchlist qapplied && [ "${COMPREPLY[*]}" ]; then | |||
|
279 | return 0 | |||
|
280 | fi | |||
|
281 | _hg_labels | |||
|
282 | ;; | |||
|
283 | manifest|update|up|checkout|co) | |||
|
284 | _hg_labels | |||
|
285 | ;; | |||
|
286 | pull|push|outgoing|incoming) | |||
|
287 | _hg_paths | |||
|
288 | _hg_repos | |||
|
289 | ;; | |||
|
290 | paths) | |||
|
291 | _hg_paths | |||
|
292 | ;; | |||
|
293 | add) | |||
|
294 | _hg_status "u" | |||
|
295 | ;; | |||
|
296 | merge) | |||
|
297 | _hg_labels | |||
|
298 | ;; | |||
|
299 | commit|ci|record|amend) | |||
|
300 | _hg_status "mar" | |||
|
301 | ;; | |||
|
302 | remove|rm) | |||
|
303 | _hg_debugpathcomplete -n | |||
|
304 | ;; | |||
|
305 | forget) | |||
|
306 | _hg_debugpathcomplete -fa | |||
|
307 | ;; | |||
|
308 | diff) | |||
|
309 | _hg_status "mar" | |||
|
310 | ;; | |||
|
311 | revert) | |||
|
312 | _hg_status "mard" | |||
|
313 | ;; | |||
|
314 | clone) | |||
|
315 | local count=$(_hg_count_non_option) | |||
|
316 | if [ $count = 1 ]; then | |||
|
317 | _hg_paths | |||
|
318 | fi | |||
|
319 | _hg_repos | |||
|
320 | ;; | |||
|
321 | debugindex|debugindexdot) | |||
|
322 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.i" -- "$cur")) | |||
|
323 | ;; | |||
|
324 | debugdata) | |||
|
325 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -f -X "!*.d" -- "$cur")) | |||
|
326 | ;; | |||
|
327 | *) | |||
|
328 | return 1 | |||
|
329 | ;; | |||
|
330 | esac | |||
|
331 | ||||
|
332 | return 0 | |||
|
333 | } | |||
|
334 | ||||
|
335 | complete -o bashdefault -o default -o nospace -F _hg hg \ | |||
|
336 | || complete -o default -o nospace -F _hg hg | |||
|
337 | ||||
|
338 | ||||
|
339 | # Completion for commands provided by extensions | |||
|
340 | ||||
|
341 | # bookmarks | |||
|
342 | _hg_cmd_bookmarks() | |||
|
343 | { | |||
|
344 | _hg_bookmarks | |||
|
345 | return | |||
|
346 | } | |||
|
347 | ||||
|
348 | # mq | |||
|
349 | _hg_ext_mq_patchlist() | |||
|
350 | { | |||
|
351 | local patches | |||
|
352 | patches=$(_hg_cmd $1) | |||
|
353 | if [ $? -eq 0 ] && [ "$patches" ]; then | |||
|
354 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$patches' -- "$cur")) | |||
|
355 | return 0 | |||
|
356 | fi | |||
|
357 | return 1 | |||
|
358 | } | |||
|
359 | ||||
|
360 | _hg_ext_mq_queues() | |||
|
361 | { | |||
|
362 | local root=$(_hg_cmd root) | |||
|
363 | local n | |||
|
364 | for n in $(cd "$root"/.hg && compgen -d -- "$cur"); do | |||
|
365 | # I think we're usually not interested in the regular "patches" queue | |||
|
366 | # so just filter it. | |||
|
367 | if [ "$n" != patches ] && [ -e "$root/.hg/$n/series" ]; then | |||
|
368 | COMPREPLY=(${COMPREPLY[@]:-} "$n") | |||
|
369 | fi | |||
|
370 | done | |||
|
371 | } | |||
|
372 | ||||
|
373 | _hg_cmd_qpop() | |||
|
374 | { | |||
|
375 | if [[ "$prev" = @(-n|--name) ]]; then | |||
|
376 | _hg_ext_mq_queues | |||
|
377 | return | |||
|
378 | fi | |||
|
379 | _hg_ext_mq_patchlist qapplied | |||
|
380 | } | |||
|
381 | ||||
|
382 | _hg_cmd_qpush() | |||
|
383 | { | |||
|
384 | if [[ "$prev" = @(-n|--name) ]]; then | |||
|
385 | _hg_ext_mq_queues | |||
|
386 | return | |||
|
387 | fi | |||
|
388 | _hg_ext_mq_patchlist qunapplied | |||
|
389 | } | |||
|
390 | ||||
|
391 | _hg_cmd_qgoto() | |||
|
392 | { | |||
|
393 | if [[ "$prev" = @(-n|--name) ]]; then | |||
|
394 | _hg_ext_mq_queues | |||
|
395 | return | |||
|
396 | fi | |||
|
397 | _hg_ext_mq_patchlist qseries | |||
|
398 | } | |||
|
399 | ||||
|
400 | _hg_cmd_qdelete() | |||
|
401 | { | |||
|
402 | local qcmd=qunapplied | |||
|
403 | if [[ "$prev" = @(-r|--rev) ]]; then | |||
|
404 | qcmd=qapplied | |||
|
405 | fi | |||
|
406 | _hg_ext_mq_patchlist $qcmd | |||
|
407 | } | |||
|
408 | ||||
|
409 | _hg_cmd_qfinish() | |||
|
410 | { | |||
|
411 | if [[ "$prev" = @(-a|--applied) ]]; then | |||
|
412 | return | |||
|
413 | fi | |||
|
414 | _hg_ext_mq_patchlist qapplied | |||
|
415 | } | |||
|
416 | ||||
|
417 | _hg_cmd_qsave() | |||
|
418 | { | |||
|
419 | if [[ "$prev" = @(-n|--name) ]]; then | |||
|
420 | _hg_ext_mq_queues | |||
|
421 | return | |||
|
422 | fi | |||
|
423 | } | |||
|
424 | ||||
|
425 | _hg_cmd_rebase() { | |||
|
426 | if [[ "$prev" = @(-s|--source|-d|--dest|-b|--base|-r|--rev) ]]; then | |||
|
427 | _hg_labels | |||
|
428 | return | |||
|
429 | fi | |||
|
430 | } | |||
|
431 | ||||
|
432 | _hg_cmd_strip() | |||
|
433 | { | |||
|
434 | if [[ "$prev" = @(-B|--bookmark) ]]; then | |||
|
435 | _hg_bookmarks | |||
|
436 | return | |||
|
437 | fi | |||
|
438 | _hg_labels | |||
|
439 | } | |||
|
440 | ||||
|
441 | _hg_cmd_qcommit() | |||
|
442 | { | |||
|
443 | local root=$(_hg_cmd root) | |||
|
444 | # this is run in a sub-shell, so we can't use _hg_status | |||
|
445 | local files=$(cd "$root/.hg/patches" && _hg_cmd status -nmar) | |||
|
446 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$files' -- "$cur")) | |||
|
447 | } | |||
|
448 | ||||
|
449 | _hg_cmd_qfold() | |||
|
450 | { | |||
|
451 | _hg_ext_mq_patchlist qunapplied | |||
|
452 | } | |||
|
453 | ||||
|
454 | _hg_cmd_qrename() | |||
|
455 | { | |||
|
456 | _hg_ext_mq_patchlist qseries | |||
|
457 | } | |||
|
458 | ||||
|
459 | _hg_cmd_qheader() | |||
|
460 | { | |||
|
461 | _hg_ext_mq_patchlist qseries | |||
|
462 | } | |||
|
463 | ||||
|
464 | _hg_cmd_qclone() | |||
|
465 | { | |||
|
466 | local count=$(_hg_count_non_option) | |||
|
467 | if [ $count = 1 ]; then | |||
|
468 | _hg_paths | |||
|
469 | fi | |||
|
470 | _hg_repos | |||
|
471 | } | |||
|
472 | ||||
|
473 | _hg_ext_mq_guards() | |||
|
474 | { | |||
|
475 | _hg_cmd qselect --series | sed -e 's/^.//' | |||
|
476 | } | |||
|
477 | ||||
|
478 | _hg_cmd_qselect() | |||
|
479 | { | |||
|
480 | local guards=$(_hg_ext_mq_guards) | |||
|
481 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$guards' -- "$cur")) | |||
|
482 | } | |||
|
483 | ||||
|
484 | _hg_cmd_qguard() | |||
|
485 | { | |||
|
486 | local prefix='' | |||
|
487 | ||||
|
488 | if [[ "$cur" == +* ]]; then | |||
|
489 | prefix=+ | |||
|
490 | elif [[ "$cur" == -* ]]; then | |||
|
491 | prefix=- | |||
|
492 | fi | |||
|
493 | local ncur=${cur#[-+]} | |||
|
494 | ||||
|
495 | if ! [ "$prefix" ]; then | |||
|
496 | _hg_ext_mq_patchlist qseries | |||
|
497 | return | |||
|
498 | fi | |||
|
499 | ||||
|
500 | local guards=$(_hg_ext_mq_guards) | |||
|
501 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -P $prefix -W '$guards' -- "$ncur")) | |||
|
502 | } | |||
|
503 | ||||
|
504 | _hg_opt_qguard() | |||
|
505 | { | |||
|
506 | local i | |||
|
507 | for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do | |||
|
508 | if [[ ${COMP_WORDS[i]} != -* ]]; then | |||
|
509 | if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then | |||
|
510 | _hg_cmd_qguard | |||
|
511 | return 0 | |||
|
512 | fi | |||
|
513 | elif [ "${COMP_WORDS[i]}" = -- ]; then | |||
|
514 | _hg_cmd_qguard | |||
|
515 | return 0 | |||
|
516 | fi | |||
|
517 | done | |||
|
518 | return 1 | |||
|
519 | } | |||
|
520 | ||||
|
521 | _hg_cmd_qqueue() | |||
|
522 | { | |||
|
523 | local q | |||
|
524 | local queues | |||
|
525 | local opts="--list --create --rename --delete --purge" | |||
|
526 | ||||
|
527 | queues=$( _hg_cmd qqueue --quiet ) | |||
|
528 | ||||
|
529 | COMPREPLY=( $( compgen -W "${opts} ${queues}" "${cur}" ) ) | |||
|
530 | } | |||
|
531 | ||||
|
532 | ||||
|
533 | # hbisect | |||
|
534 | _hg_cmd_bisect() | |||
|
535 | { | |||
|
536 | local i subcmd | |||
|
537 | ||||
|
538 | # find the sub-command | |||
|
539 | for ((i=cmd_index+1; i<=COMP_CWORD; i++)); do | |||
|
540 | if [[ ${COMP_WORDS[i]} != -* ]]; then | |||
|
541 | if [[ ${COMP_WORDS[i-1]} != @($global_args) ]]; then | |||
|
542 | subcmd="${COMP_WORDS[i]}" | |||
|
543 | break | |||
|
544 | fi | |||
|
545 | fi | |||
|
546 | done | |||
|
547 | ||||
|
548 | if [ -z "$subcmd" ] || [ $COMP_CWORD -eq $i ] || [ "$subcmd" = help ]; then | |||
|
549 | COMPREPLY=(${COMPREPLY[@]:-} | |||
|
550 | $(compgen -W 'bad good help init next reset' -- "$cur")) | |||
|
551 | return | |||
|
552 | fi | |||
|
553 | ||||
|
554 | case "$subcmd" in | |||
|
555 | good|bad) | |||
|
556 | _hg_labels | |||
|
557 | ;; | |||
|
558 | esac | |||
|
559 | ||||
|
560 | return | |||
|
561 | } | |||
|
562 | ||||
|
563 | ||||
|
564 | # patchbomb | |||
|
565 | _hg_cmd_email() | |||
|
566 | { | |||
|
567 | case "$prev" in | |||
|
568 | -c|--cc|-t|--to|-f|--from|--bcc) | |||
|
569 | # we need an e-mail address. let the user provide a function | |||
|
570 | # to get them | |||
|
571 | if [ "$(type -t _hg_emails)" = function ]; then | |||
|
572 | local arg=to | |||
|
573 | if [[ "$prev" == @(-f|--from) ]]; then | |||
|
574 | arg=from | |||
|
575 | fi | |||
|
576 | local addresses=$(_hg_emails $arg) | |||
|
577 | COMPREPLY=(${COMPREPLY[@]:-} | |||
|
578 | $(compgen -W '$addresses' -- "$cur")) | |||
|
579 | fi | |||
|
580 | return | |||
|
581 | ;; | |||
|
582 | -m|--mbox) | |||
|
583 | # fallback to standard filename completion | |||
|
584 | return | |||
|
585 | ;; | |||
|
586 | -s|--subject) | |||
|
587 | # free form string | |||
|
588 | return | |||
|
589 | ;; | |||
|
590 | esac | |||
|
591 | ||||
|
592 | _hg_labels | |||
|
593 | return | |||
|
594 | } | |||
|
595 | ||||
|
596 | ||||
|
597 | # gpg | |||
|
598 | _hg_cmd_sign() | |||
|
599 | { | |||
|
600 | _hg_labels | |||
|
601 | } | |||
|
602 | ||||
|
603 | ||||
|
604 | # transplant | |||
|
605 | _hg_cmd_transplant() | |||
|
606 | { | |||
|
607 | case "$prev" in | |||
|
608 | -s|--source) | |||
|
609 | _hg_paths | |||
|
610 | _hg_repos | |||
|
611 | return | |||
|
612 | ;; | |||
|
613 | --filter) | |||
|
614 | # standard filename completion | |||
|
615 | return | |||
|
616 | ;; | |||
|
617 | esac | |||
|
618 | ||||
|
619 | # all other transplant options values and command parameters are revisions | |||
|
620 | _hg_labels | |||
|
621 | return | |||
|
622 | } | |||
|
623 | ||||
|
624 | # shelve | |||
|
625 | _hg_shelves() | |||
|
626 | { | |||
|
627 | local shelves="$(_hg_cmd shelve -ql)" | |||
|
628 | local IFS=$'\n' | |||
|
629 | COMPREPLY=(${COMPREPLY[@]:-} $(compgen -W '$shelves' -- "$cur")) | |||
|
630 | } | |||
|
631 | ||||
|
632 | _hg_cmd_shelve() | |||
|
633 | { | |||
|
634 | if [[ "$prev" = @(-d|--delete|-l|--list|-p|--patch|--stat) ]]; then | |||
|
635 | _hg_shelves | |||
|
636 | else | |||
|
637 | _hg_status "mard" | |||
|
638 | fi | |||
|
639 | } | |||
|
640 | ||||
|
641 | _hg_cmd_unshelve() | |||
|
642 | { | |||
|
643 | _hg_shelves | |||
|
644 | } |
@@ -0,0 +1,99 b'' | |||||
|
1 | # Randomized torture test generation for bdiff | |||
|
2 | ||||
|
3 | from __future__ import absolute_import, print_function | |||
|
4 | import random | |||
|
5 | import sys | |||
|
6 | ||||
|
7 | from mercurial import ( | |||
|
8 | mdiff, | |||
|
9 | ) | |||
|
10 | ||||
|
11 | def reducetest(a, b): | |||
|
12 | tries = 0 | |||
|
13 | reductions = 0 | |||
|
14 | print("reducing...") | |||
|
15 | while tries < 1000: | |||
|
16 | a2 = "\n".join(l for l in a.splitlines() | |||
|
17 | if random.randint(0, 100) > 0) + "\n" | |||
|
18 | b2 = "\n".join(l for l in b.splitlines() | |||
|
19 | if random.randint(0, 100) > 0) + "\n" | |||
|
20 | if a2 == a and b2 == b: | |||
|
21 | continue | |||
|
22 | if a2 == b2: | |||
|
23 | continue | |||
|
24 | tries += 1 | |||
|
25 | ||||
|
26 | try: | |||
|
27 | test1(a, b) | |||
|
28 | except Exception as inst: | |||
|
29 | reductions += 1 | |||
|
30 | tries = 0 | |||
|
31 | a = a2 | |||
|
32 | b = b2 | |||
|
33 | ||||
|
34 | print("reduced:", reductions, len(a) + len(b), | |||
|
35 | repr(a), repr(b)) | |||
|
36 | try: | |||
|
37 | test1(a, b) | |||
|
38 | except Exception as inst: | |||
|
39 | print("failed:", inst) | |||
|
40 | ||||
|
41 | sys.exit(0) | |||
|
42 | ||||
|
43 | def test1(a, b): | |||
|
44 | d = mdiff.textdiff(a, b) | |||
|
45 | if not d: | |||
|
46 | raise ValueError("empty") | |||
|
47 | c = mdiff.patches(a, [d]) | |||
|
48 | if c != b: | |||
|
49 | raise ValueError("bad") | |||
|
50 | ||||
|
51 | def testwrap(a, b): | |||
|
52 | try: | |||
|
53 | test1(a, b) | |||
|
54 | return | |||
|
55 | except Exception as inst: | |||
|
56 | pass | |||
|
57 | print("exception:", inst) | |||
|
58 | reducetest(a, b) | |||
|
59 | ||||
|
60 | def test(a, b): | |||
|
61 | testwrap(a, b) | |||
|
62 | testwrap(b, a) | |||
|
63 | ||||
|
64 | def rndtest(size, noise): | |||
|
65 | a = [] | |||
|
66 | src = " aaaaaaaabbbbccd" | |||
|
67 | for x in xrange(size): | |||
|
68 | a.append(src[random.randint(0, len(src) - 1)]) | |||
|
69 | ||||
|
70 | while True: | |||
|
71 | b = [c for c in a if random.randint(0, 99) > noise] | |||
|
72 | b2 = [] | |||
|
73 | for c in b: | |||
|
74 | b2.append(c) | |||
|
75 | while random.randint(0, 99) < noise: | |||
|
76 | b2.append(src[random.randint(0, len(src) - 1)]) | |||
|
77 | if b2 != a: | |||
|
78 | break | |||
|
79 | ||||
|
80 | a = "\n".join(a) + "\n" | |||
|
81 | b = "\n".join(b2) + "\n" | |||
|
82 | ||||
|
83 | test(a, b) | |||
|
84 | ||||
|
85 | maxvol = 10000 | |||
|
86 | startsize = 2 | |||
|
87 | while True: | |||
|
88 | size = startsize | |||
|
89 | count = 0 | |||
|
90 | while size < maxvol: | |||
|
91 | print(size) | |||
|
92 | volume = 0 | |||
|
93 | while volume < maxvol: | |||
|
94 | rndtest(size, 2) | |||
|
95 | volume += size | |||
|
96 | count += 2 | |||
|
97 | size *= 2 | |||
|
98 | maxvol *= 4 | |||
|
99 | startsize *= 4 |
@@ -0,0 +1,113 b'' | |||||
|
1 | # __init__.py - asv benchmark suite | |||
|
2 | # | |||
|
3 | # Copyright 2016 Logilab SA <contact@logilab.fr> | |||
|
4 | # | |||
|
5 | # This software may be used and distributed according to the terms of the | |||
|
6 | # GNU General Public License version 2 or any later version. | |||
|
7 | ||||
|
8 | # "historical portability" policy of contrib/benchmarks: | |||
|
9 | # | |||
|
10 | # We have to make this code work correctly with current mercurial stable branch | |||
|
11 | # and if possible with reasonable cost with early Mercurial versions. | |||
|
12 | ||||
|
13 | '''ASV (https://asv.readthedocs.io) benchmark suite | |||
|
14 | ||||
|
15 | Benchmark are parameterized against reference repositories found in the | |||
|
16 | directory pointed by the REPOS_DIR environment variable. | |||
|
17 | ||||
|
18 | Invocation example: | |||
|
19 | ||||
|
20 | $ export REPOS_DIR=~/hgperf/repos | |||
|
21 | # run suite on given revision | |||
|
22 | $ asv --config contrib/asv.conf.json run REV | |||
|
23 | # run suite on new changesets found in stable and default branch | |||
|
24 | $ asv --config contrib/asv.conf.json run NEW | |||
|
25 | # display a comparative result table of benchmark results between two given | |||
|
26 | # revisions | |||
|
27 | $ asv --config contrib/asv.conf.json compare REV1 REV2 | |||
|
28 | # compute regression detection and generate ASV static website | |||
|
29 | $ asv --config contrib/asv.conf.json publish | |||
|
30 | # serve the static website | |||
|
31 | $ asv --config contrib/asv.conf.json preview | |||
|
32 | ''' | |||
|
33 | ||||
|
34 | from __future__ import absolute_import | |||
|
35 | ||||
|
36 | import functools | |||
|
37 | import os | |||
|
38 | import re | |||
|
39 | ||||
|
40 | from mercurial import ( | |||
|
41 | extensions, | |||
|
42 | hg, | |||
|
43 | ui as uimod, | |||
|
44 | util, | |||
|
45 | ) | |||
|
46 | ||||
|
47 | basedir = os.path.abspath(os.path.join(os.path.dirname(__file__), | |||
|
48 | os.path.pardir, os.path.pardir)) | |||
|
49 | reposdir = os.environ['REPOS_DIR'] | |||
|
50 | reposnames = [name for name in os.listdir(reposdir) | |||
|
51 | if os.path.isdir(os.path.join(reposdir, name, ".hg"))] | |||
|
52 | if not reposnames: | |||
|
53 | raise ValueError("No repositories found in $REPO_DIR") | |||
|
54 | outputre = re.compile((r'! wall (\d+.\d+) comb \d+.\d+ user \d+.\d+ sys ' | |||
|
55 | r'\d+.\d+ \(best of \d+\)')) | |||
|
56 | ||||
|
57 | def runperfcommand(reponame, command, *args, **kwargs): | |||
|
58 | os.environ["HGRCPATH"] = os.environ.get("ASVHGRCPATH", "") | |||
|
59 | # for "historical portability" | |||
|
60 | # ui.load() has been available since d83ca85 | |||
|
61 | if util.safehasattr(uimod.ui, "load"): | |||
|
62 | ui = uimod.ui.load() | |||
|
63 | else: | |||
|
64 | ui = uimod.ui() | |||
|
65 | repo = hg.repository(ui, os.path.join(reposdir, reponame)) | |||
|
66 | perfext = extensions.load(ui, 'perfext', | |||
|
67 | os.path.join(basedir, 'contrib', 'perf.py')) | |||
|
68 | cmd = getattr(perfext, command) | |||
|
69 | ui.pushbuffer() | |||
|
70 | cmd(ui, repo, *args, **kwargs) | |||
|
71 | output = ui.popbuffer() | |||
|
72 | match = outputre.search(output) | |||
|
73 | if not match: | |||
|
74 | raise ValueError("Invalid output {0}".format(output)) | |||
|
75 | return float(match.group(1)) | |||
|
76 | ||||
|
77 | def perfbench(repos=reposnames, name=None, params=None): | |||
|
78 | """decorator to declare ASV benchmark based on contrib/perf.py extension | |||
|
79 | ||||
|
80 | An ASV benchmark is a python function with the given attributes: | |||
|
81 | ||||
|
82 | __name__: should start with track_, time_ or mem_ to be collected by ASV | |||
|
83 | params and param_name: parameter matrix to display multiple graphs on the | |||
|
84 | same page. | |||
|
85 | pretty_name: If defined it's displayed in web-ui instead of __name__ | |||
|
86 | (useful for revsets) | |||
|
87 | the module name is prepended to the benchmark name and displayed as | |||
|
88 | "category" in webui. | |||
|
89 | ||||
|
90 | Benchmarks are automatically parameterized with repositories found in the | |||
|
91 | REPOS_DIR environment variable. | |||
|
92 | ||||
|
93 | `params` is the param matrix in the form of a list of tuple | |||
|
94 | (param_name, [value0, value1]) | |||
|
95 | ||||
|
96 | For example [(x, [a, b]), (y, [c, d])] declare benchmarks for | |||
|
97 | (a, c), (a, d), (b, c) and (b, d). | |||
|
98 | """ | |||
|
99 | params = list(params or []) | |||
|
100 | params.insert(0, ("repo", repos)) | |||
|
101 | ||||
|
102 | def decorator(func): | |||
|
103 | @functools.wraps(func) | |||
|
104 | def wrapped(repo, *args): | |||
|
105 | def perf(command, *a, **kw): | |||
|
106 | return runperfcommand(repo, command, *a, **kw) | |||
|
107 | return func(perf, *args) | |||
|
108 | ||||
|
109 | wrapped.params = [p[1] for p in params] | |||
|
110 | wrapped.param_names = [p[0] for p in params] | |||
|
111 | wrapped.pretty_name = name | |||
|
112 | return wrapped | |||
|
113 | return decorator |
@@ -0,0 +1,26 b'' | |||||
|
1 | # perf.py - asv benchmarks using contrib/perf.py extension | |||
|
2 | # | |||
|
3 | # Copyright 2016 Logilab SA <contact@logilab.fr> | |||
|
4 | # | |||
|
5 | # This software may be used and distributed according to the terms of the | |||
|
6 | # GNU General Public License version 2 or any later version. | |||
|
7 | ||||
|
8 | from __future__ import absolute_import | |||
|
9 | ||||
|
10 | from . import perfbench | |||
|
11 | ||||
|
12 | @perfbench() | |||
|
13 | def track_tags(perf): | |||
|
14 | return perf("perftags") | |||
|
15 | ||||
|
16 | @perfbench() | |||
|
17 | def track_status(perf): | |||
|
18 | return perf("perfstatus", unknown=False) | |||
|
19 | ||||
|
20 | @perfbench(params=[('rev', ['1000', '10000', 'tip'])]) | |||
|
21 | def track_manifest(perf, rev): | |||
|
22 | return perf("perfmanifest", rev) | |||
|
23 | ||||
|
24 | @perfbench() | |||
|
25 | def track_heads(perf): | |||
|
26 | return perf("perfheads") |
@@ -0,0 +1,53 b'' | |||||
|
1 | # revset.py - asv revset benchmarks | |||
|
2 | # | |||
|
3 | # Copyright 2016 Logilab SA <contact@logilab.fr> | |||
|
4 | # | |||
|
5 | # This software may be used and distributed according to the terms of the | |||
|
6 | # GNU General Public License version 2 or any later version. | |||
|
7 | ||||
|
8 | '''ASV revset benchmarks generated from contrib/base-revsets.txt | |||
|
9 | ||||
|
10 | Each revset benchmark is parameterized with variants (first, last, sort, ...) | |||
|
11 | ''' | |||
|
12 | ||||
|
13 | from __future__ import absolute_import | |||
|
14 | ||||
|
15 | import os | |||
|
16 | import string | |||
|
17 | import sys | |||
|
18 | ||||
|
19 | from . import basedir, perfbench | |||
|
20 | ||||
|
21 | def createrevsetbenchmark(baseset, variants=None): | |||
|
22 | if variants is None: | |||
|
23 | # Default variants | |||
|
24 | variants = ["plain", "first", "last", "sort", "sort+first", | |||
|
25 | "sort+last"] | |||
|
26 | fname = "track_" + "_".join("".join([ | |||
|
27 | c if c in string.digits + string.letters else " " | |||
|
28 | for c in baseset | |||
|
29 | ]).split()) | |||
|
30 | ||||
|
31 | def wrap(fname, baseset): | |||
|
32 | @perfbench(name=baseset, params=[("variant", variants)]) | |||
|
33 | def f(perf, variant): | |||
|
34 | revset = baseset | |||
|
35 | if variant != "plain": | |||
|
36 | for var in variant.split("+"): | |||
|
37 | revset = "%s(%s)" % (var, revset) | |||
|
38 | return perf("perfrevset", revset) | |||
|
39 | f.__name__ = fname | |||
|
40 | return f | |||
|
41 | return wrap(fname, baseset) | |||
|
42 | ||||
|
43 | def initializerevsetbenchmarks(): | |||
|
44 | mod = sys.modules[__name__] | |||
|
45 | with open(os.path.join(basedir, 'contrib', 'base-revsets.txt'), | |||
|
46 | 'rb') as fh: | |||
|
47 | for line in fh: | |||
|
48 | baseset = line.strip() | |||
|
49 | if baseset and not baseset.startswith('#'): | |||
|
50 | func = createrevsetbenchmark(baseset) | |||
|
51 | setattr(mod, func.__name__, func) | |||
|
52 | ||||
|
53 | initializerevsetbenchmarks() |
@@ -0,0 +1,225 b'' | |||||
|
1 | #!/usr/bin/env python3 | |||
|
2 | # | |||
|
3 | # byteify-strings.py - transform string literals to be Python 3 safe | |||
|
4 | # | |||
|
5 | # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com> | |||
|
6 | # | |||
|
7 | # This software may be used and distributed according to the terms of the | |||
|
8 | # GNU General Public License version 2 or any later version. | |||
|
9 | ||||
|
10 | from __future__ import absolute_import | |||
|
11 | ||||
|
12 | import argparse | |||
|
13 | import contextlib | |||
|
14 | import errno | |||
|
15 | import os | |||
|
16 | import sys | |||
|
17 | import tempfile | |||
|
18 | import token | |||
|
19 | import tokenize | |||
|
20 | ||||
|
21 | def adjusttokenpos(t, ofs): | |||
|
22 | """Adjust start/end column of the given token""" | |||
|
23 | return t._replace(start=(t.start[0], t.start[1] + ofs), | |||
|
24 | end=(t.end[0], t.end[1] + ofs)) | |||
|
25 | ||||
|
26 | def replacetokens(tokens, opts): | |||
|
27 | """Transform a stream of tokens from raw to Python 3. | |||
|
28 | ||||
|
29 | Returns a generator of possibly rewritten tokens. | |||
|
30 | ||||
|
31 | The input token list may be mutated as part of processing. However, | |||
|
32 | its changes do not necessarily match the output token stream. | |||
|
33 | """ | |||
|
34 | sysstrtokens = set() | |||
|
35 | ||||
|
36 | # The following utility functions access the tokens list and i index of | |||
|
37 | # the for i, t enumerate(tokens) loop below | |||
|
38 | def _isop(j, *o): | |||
|
39 | """Assert that tokens[j] is an OP with one of the given values""" | |||
|
40 | try: | |||
|
41 | return tokens[j].type == token.OP and tokens[j].string in o | |||
|
42 | except IndexError: | |||
|
43 | return False | |||
|
44 | ||||
|
45 | def _findargnofcall(n): | |||
|
46 | """Find arg n of a call expression (start at 0) | |||
|
47 | ||||
|
48 | Returns index of the first token of that argument, or None if | |||
|
49 | there is not that many arguments. | |||
|
50 | ||||
|
51 | Assumes that token[i + 1] is '('. | |||
|
52 | ||||
|
53 | """ | |||
|
54 | nested = 0 | |||
|
55 | for j in range(i + 2, len(tokens)): | |||
|
56 | if _isop(j, ')', ']', '}'): | |||
|
57 | # end of call, tuple, subscription or dict / set | |||
|
58 | nested -= 1 | |||
|
59 | if nested < 0: | |||
|
60 | return None | |||
|
61 | elif n == 0: | |||
|
62 | # this is the starting position of arg | |||
|
63 | return j | |||
|
64 | elif _isop(j, '(', '[', '{'): | |||
|
65 | nested += 1 | |||
|
66 | elif _isop(j, ',') and nested == 0: | |||
|
67 | n -= 1 | |||
|
68 | ||||
|
69 | return None | |||
|
70 | ||||
|
71 | def _ensuresysstr(j): | |||
|
72 | """Make sure the token at j is a system string | |||
|
73 | ||||
|
74 | Remember the given token so the string transformer won't add | |||
|
75 | the byte prefix. | |||
|
76 | ||||
|
77 | Ignores tokens that are not strings. Assumes bounds checking has | |||
|
78 | already been done. | |||
|
79 | ||||
|
80 | """ | |||
|
81 | st = tokens[j] | |||
|
82 | if st.type == token.STRING and st.string.startswith(("'", '"')): | |||
|
83 | sysstrtokens.add(st) | |||
|
84 | ||||
|
85 | coldelta = 0 # column increment for new opening parens | |||
|
86 | coloffset = -1 # column offset for the current line (-1: TBD) | |||
|
87 | parens = [(0, 0, 0)] # stack of (line, end-column, column-offset) | |||
|
88 | for i, t in enumerate(tokens): | |||
|
89 | # Compute the column offset for the current line, such that | |||
|
90 | # the current line will be aligned to the last opening paren | |||
|
91 | # as before. | |||
|
92 | if coloffset < 0: | |||
|
93 | if t.start[1] == parens[-1][1]: | |||
|
94 | coloffset = parens[-1][2] | |||
|
95 | elif t.start[1] + 1 == parens[-1][1]: | |||
|
96 | # fix misaligned indent of s/util.Abort/error.Abort/ | |||
|
97 | coloffset = parens[-1][2] + (parens[-1][1] - t.start[1]) | |||
|
98 | else: | |||
|
99 | coloffset = 0 | |||
|
100 | ||||
|
101 | # Reset per-line attributes at EOL. | |||
|
102 | if t.type in (token.NEWLINE, tokenize.NL): | |||
|
103 | yield adjusttokenpos(t, coloffset) | |||
|
104 | coldelta = 0 | |||
|
105 | coloffset = -1 | |||
|
106 | continue | |||
|
107 | ||||
|
108 | # Remember the last paren position. | |||
|
109 | if _isop(i, '(', '[', '{'): | |||
|
110 | parens.append(t.end + (coloffset + coldelta,)) | |||
|
111 | elif _isop(i, ')', ']', '}'): | |||
|
112 | parens.pop() | |||
|
113 | ||||
|
114 | # Convert most string literals to byte literals. String literals | |||
|
115 | # in Python 2 are bytes. String literals in Python 3 are unicode. | |||
|
116 | # Most strings in Mercurial are bytes and unicode strings are rare. | |||
|
117 | # Rather than rewrite all string literals to use ``b''`` to indicate | |||
|
118 | # byte strings, we apply this token transformer to insert the ``b`` | |||
|
119 | # prefix nearly everywhere. | |||
|
120 | if t.type == token.STRING and t not in sysstrtokens: | |||
|
121 | s = t.string | |||
|
122 | ||||
|
123 | # Preserve docstrings as string literals. This is inconsistent | |||
|
124 | # with regular unprefixed strings. However, the | |||
|
125 | # "from __future__" parsing (which allows a module docstring to | |||
|
126 | # exist before it) doesn't properly handle the docstring if it | |||
|
127 | # is b''' prefixed, leading to a SyntaxError. We leave all | |||
|
128 | # docstrings as unprefixed to avoid this. This means Mercurial | |||
|
129 | # components touching docstrings need to handle unicode, | |||
|
130 | # unfortunately. | |||
|
131 | if s[0:3] in ("'''", '"""'): | |||
|
132 | yield adjusttokenpos(t, coloffset) | |||
|
133 | continue | |||
|
134 | ||||
|
135 | # If the first character isn't a quote, it is likely a string | |||
|
136 | # prefixing character (such as 'b', 'u', or 'r'. Ignore. | |||
|
137 | if s[0] not in ("'", '"'): | |||
|
138 | yield adjusttokenpos(t, coloffset) | |||
|
139 | continue | |||
|
140 | ||||
|
141 | # String literal. Prefix to make a b'' string. | |||
|
142 | yield adjusttokenpos(t._replace(string='b%s' % t.string), | |||
|
143 | coloffset) | |||
|
144 | coldelta += 1 | |||
|
145 | continue | |||
|
146 | ||||
|
147 | # This looks like a function call. | |||
|
148 | if t.type == token.NAME and _isop(i + 1, '('): | |||
|
149 | fn = t.string | |||
|
150 | ||||
|
151 | # *attr() builtins don't accept byte strings to 2nd argument. | |||
|
152 | if (fn in ('getattr', 'setattr', 'hasattr', 'safehasattr') and | |||
|
153 | not _isop(i - 1, '.')): | |||
|
154 | arg1idx = _findargnofcall(1) | |||
|
155 | if arg1idx is not None: | |||
|
156 | _ensuresysstr(arg1idx) | |||
|
157 | ||||
|
158 | # .encode() and .decode() on str/bytes/unicode don't accept | |||
|
159 | # byte strings on Python 3. | |||
|
160 | elif fn in ('encode', 'decode') and _isop(i - 1, '.'): | |||
|
161 | for argn in range(2): | |||
|
162 | argidx = _findargnofcall(argn) | |||
|
163 | if argidx is not None: | |||
|
164 | _ensuresysstr(argidx) | |||
|
165 | ||||
|
166 | # It changes iteritems/values to items/values as they are not | |||
|
167 | # present in Python 3 world. | |||
|
168 | elif opts['dictiter'] and fn in ('iteritems', 'itervalues'): | |||
|
169 | yield adjusttokenpos(t._replace(string=fn[4:]), coloffset) | |||
|
170 | continue | |||
|
171 | ||||
|
172 | # Emit unmodified token. | |||
|
173 | yield adjusttokenpos(t, coloffset) | |||
|
174 | ||||
|
175 | def process(fin, fout, opts): | |||
|
176 | tokens = tokenize.tokenize(fin.readline) | |||
|
177 | tokens = replacetokens(list(tokens), opts) | |||
|
178 | fout.write(tokenize.untokenize(tokens)) | |||
|
179 | ||||
|
180 | def tryunlink(fname): | |||
|
181 | try: | |||
|
182 | os.unlink(fname) | |||
|
183 | except OSError as err: | |||
|
184 | if err.errno != errno.ENOENT: | |||
|
185 | raise | |||
|
186 | ||||
|
187 | @contextlib.contextmanager | |||
|
188 | def editinplace(fname): | |||
|
189 | n = os.path.basename(fname) | |||
|
190 | d = os.path.dirname(fname) | |||
|
191 | fp = tempfile.NamedTemporaryFile(prefix='.%s-' % n, suffix='~', dir=d, | |||
|
192 | delete=False) | |||
|
193 | try: | |||
|
194 | yield fp | |||
|
195 | fp.close() | |||
|
196 | if os.name == 'nt': | |||
|
197 | tryunlink(fname) | |||
|
198 | os.rename(fp.name, fname) | |||
|
199 | finally: | |||
|
200 | fp.close() | |||
|
201 | tryunlink(fp.name) | |||
|
202 | ||||
|
203 | def main(): | |||
|
204 | ap = argparse.ArgumentParser() | |||
|
205 | ap.add_argument('-i', '--inplace', action='store_true', default=False, | |||
|
206 | help='edit files in place') | |||
|
207 | ap.add_argument('--dictiter', action='store_true', default=False, | |||
|
208 | help='rewrite iteritems() and itervalues()'), | |||
|
209 | ap.add_argument('files', metavar='FILE', nargs='+', help='source file') | |||
|
210 | args = ap.parse_args() | |||
|
211 | opts = { | |||
|
212 | 'dictiter': args.dictiter, | |||
|
213 | } | |||
|
214 | for fname in args.files: | |||
|
215 | if args.inplace: | |||
|
216 | with editinplace(fname) as fout: | |||
|
217 | with open(fname, 'rb') as fin: | |||
|
218 | process(fin, fout, opts) | |||
|
219 | else: | |||
|
220 | with open(fname, 'rb') as fin: | |||
|
221 | fout = sys.stdout.buffer | |||
|
222 | process(fin, fout, opts) | |||
|
223 | ||||
|
224 | if __name__ == '__main__': | |||
|
225 | main() |
@@ -0,0 +1,38 b'' | |||||
|
1 | from __future__ import absolute_import | |||
|
2 | import __builtin__ | |||
|
3 | import os | |||
|
4 | from mercurial import ( | |||
|
5 | util, | |||
|
6 | ) | |||
|
7 | ||||
|
8 | def lowerwrap(scope, funcname): | |||
|
9 | f = getattr(scope, funcname) | |||
|
10 | def wrap(fname, *args, **kwargs): | |||
|
11 | d, base = os.path.split(fname) | |||
|
12 | try: | |||
|
13 | files = os.listdir(d or '.') | |||
|
14 | except OSError: | |||
|
15 | files = [] | |||
|
16 | if base in files: | |||
|
17 | return f(fname, *args, **kwargs) | |||
|
18 | for fn in files: | |||
|
19 | if fn.lower() == base.lower(): | |||
|
20 | return f(os.path.join(d, fn), *args, **kwargs) | |||
|
21 | return f(fname, *args, **kwargs) | |||
|
22 | scope.__dict__[funcname] = wrap | |||
|
23 | ||||
|
24 | def normcase(path): | |||
|
25 | return path.lower() | |||
|
26 | ||||
|
27 | os.path.normcase = normcase | |||
|
28 | ||||
|
29 | for f in 'file open'.split(): | |||
|
30 | lowerwrap(__builtin__, f) | |||
|
31 | ||||
|
32 | for f in "chmod chown open lstat stat remove unlink".split(): | |||
|
33 | lowerwrap(os, f) | |||
|
34 | ||||
|
35 | for f in "exists lexists".split(): | |||
|
36 | lowerwrap(os.path, f) | |||
|
37 | ||||
|
38 | lowerwrap(util, 'posixfile') |
This diff has been collapsed as it changes many lines, (743 lines changed) Show them Hide them | |||||
@@ -0,0 +1,743 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | # | |||
|
3 | # check-code - a style and portability checker for Mercurial | |||
|
4 | # | |||
|
5 | # Copyright 2010 Matt Mackall <mpm@selenic.com> | |||
|
6 | # | |||
|
7 | # This software may be used and distributed according to the terms of the | |||
|
8 | # GNU General Public License version 2 or any later version. | |||
|
9 | ||||
|
10 | """style and portability checker for Mercurial | |||
|
11 | ||||
|
12 | when a rule triggers wrong, do one of the following (prefer one from top): | |||
|
13 | * do the work-around the rule suggests | |||
|
14 | * doublecheck that it is a false match | |||
|
15 | * improve the rule pattern | |||
|
16 | * add an ignore pattern to the rule (3rd arg) which matches your good line | |||
|
17 | (you can append a short comment and match this, like: #re-raises) | |||
|
18 | * change the pattern to a warning and list the exception in test-check-code-hg | |||
|
19 | * ONLY use no--check-code for skipping entire files from external sources | |||
|
20 | """ | |||
|
21 | ||||
|
22 | from __future__ import absolute_import, print_function | |||
|
23 | import glob | |||
|
24 | import keyword | |||
|
25 | import optparse | |||
|
26 | import os | |||
|
27 | import re | |||
|
28 | import sys | |||
|
29 | if sys.version_info[0] < 3: | |||
|
30 | opentext = open | |||
|
31 | else: | |||
|
32 | def opentext(f): | |||
|
33 | return open(f, encoding='ascii') | |||
|
34 | try: | |||
|
35 | xrange | |||
|
36 | except NameError: | |||
|
37 | xrange = range | |||
|
38 | try: | |||
|
39 | import re2 | |||
|
40 | except ImportError: | |||
|
41 | re2 = None | |||
|
42 | ||||
|
43 | def compilere(pat, multiline=False): | |||
|
44 | if multiline: | |||
|
45 | pat = '(?m)' + pat | |||
|
46 | if re2: | |||
|
47 | try: | |||
|
48 | return re2.compile(pat) | |||
|
49 | except re2.error: | |||
|
50 | pass | |||
|
51 | return re.compile(pat) | |||
|
52 | ||||
|
53 | # check "rules depending on implementation of repquote()" in each | |||
|
54 | # patterns (especially pypats), before changing around repquote() | |||
|
55 | _repquotefixedmap = {' ': ' ', '\n': '\n', '.': 'p', ':': 'q', | |||
|
56 | '%': '%', '\\': 'b', '*': 'A', '+': 'P', '-': 'M'} | |||
|
57 | def _repquoteencodechr(i): | |||
|
58 | if i > 255: | |||
|
59 | return 'u' | |||
|
60 | c = chr(i) | |||
|
61 | if c in _repquotefixedmap: | |||
|
62 | return _repquotefixedmap[c] | |||
|
63 | if c.isalpha(): | |||
|
64 | return 'x' | |||
|
65 | if c.isdigit(): | |||
|
66 | return 'n' | |||
|
67 | return 'o' | |||
|
68 | _repquotett = ''.join(_repquoteencodechr(i) for i in xrange(256)) | |||
|
69 | ||||
|
70 | def repquote(m): | |||
|
71 | t = m.group('text') | |||
|
72 | t = t.translate(_repquotett) | |||
|
73 | return m.group('quote') + t + m.group('quote') | |||
|
74 | ||||
|
75 | def reppython(m): | |||
|
76 | comment = m.group('comment') | |||
|
77 | if comment: | |||
|
78 | l = len(comment.rstrip()) | |||
|
79 | return "#" * l + comment[l:] | |||
|
80 | return repquote(m) | |||
|
81 | ||||
|
82 | def repcomment(m): | |||
|
83 | return m.group(1) + "#" * len(m.group(2)) | |||
|
84 | ||||
|
85 | def repccomment(m): | |||
|
86 | t = re.sub(r"((?<=\n) )|\S", "x", m.group(2)) | |||
|
87 | return m.group(1) + t + "*/" | |||
|
88 | ||||
|
89 | def repcallspaces(m): | |||
|
90 | t = re.sub(r"\n\s+", "\n", m.group(2)) | |||
|
91 | return m.group(1) + t | |||
|
92 | ||||
|
93 | def repinclude(m): | |||
|
94 | return m.group(1) + "<foo>" | |||
|
95 | ||||
|
96 | def rephere(m): | |||
|
97 | t = re.sub(r"\S", "x", m.group(2)) | |||
|
98 | return m.group(1) + t | |||
|
99 | ||||
|
100 | ||||
|
101 | testpats = [ | |||
|
102 | [ | |||
|
103 | (r'\b(push|pop)d\b', "don't use 'pushd' or 'popd', use 'cd'"), | |||
|
104 | (r'\W\$?\(\([^\)\n]*\)\)', "don't use (()) or $(()), use 'expr'"), | |||
|
105 | (r'grep.*-q', "don't use 'grep -q', redirect to /dev/null"), | |||
|
106 | (r'(?<!hg )grep.* -a', "don't use 'grep -a', use in-line python"), | |||
|
107 | (r'sed.*-i', "don't use 'sed -i', use a temporary file"), | |||
|
108 | (r'\becho\b.*\\n', "don't use 'echo \\n', use printf"), | |||
|
109 | (r'echo -n', "don't use 'echo -n', use printf"), | |||
|
110 | (r'(^|\|\s*)\bwc\b[^|]*$\n(?!.*\(re\))', "filter wc output"), | |||
|
111 | (r'head -c', "don't use 'head -c', use 'dd'"), | |||
|
112 | (r'tail -n', "don't use the '-n' option to tail, just use '-<num>'"), | |||
|
113 | (r'sha1sum', "don't use sha1sum, use $TESTDIR/md5sum.py"), | |||
|
114 | (r'\bls\b.*-\w*R', "don't use 'ls -R', use 'find'"), | |||
|
115 | (r'printf.*[^\\]\\([1-9]|0\d)', r"don't use 'printf \NNN', use Python"), | |||
|
116 | (r'printf.*[^\\]\\x', "don't use printf \\x, use Python"), | |||
|
117 | (r'\$\(.*\)', "don't use $(expr), use `expr`"), | |||
|
118 | (r'rm -rf \*', "don't use naked rm -rf, target a directory"), | |||
|
119 | (r'\[[^\]]+==', '[ foo == bar ] is a bashism, use [ foo = bar ] instead'), | |||
|
120 | (r'(^|\|\s*)grep (-\w\s+)*[^|]*[(|]\w', | |||
|
121 | "use egrep for extended grep syntax"), | |||
|
122 | (r'(^|\|\s*)e?grep .*\\S', "don't use \\S in regular expression"), | |||
|
123 | (r'(?<!!)/bin/', "don't use explicit paths for tools"), | |||
|
124 | (r'#!.*/bash', "don't use bash in shebang, use sh"), | |||
|
125 | (r'[^\n]\Z', "no trailing newline"), | |||
|
126 | (r'export .*=', "don't export and assign at once"), | |||
|
127 | (r'^source\b', "don't use 'source', use '.'"), | |||
|
128 | (r'touch -d', "don't use 'touch -d', use 'touch -t' instead"), | |||
|
129 | (r'\bls +[^|\n-]+ +-', "options to 'ls' must come before filenames"), | |||
|
130 | (r'[^>\n]>\s*\$HGRCPATH', "don't overwrite $HGRCPATH, append to it"), | |||
|
131 | (r'^stop\(\)', "don't use 'stop' as a shell function name"), | |||
|
132 | (r'(\[|\btest\b).*-e ', "don't use 'test -e', use 'test -f'"), | |||
|
133 | (r'\[\[\s+[^\]]*\]\]', "don't use '[[ ]]', use '[ ]'"), | |||
|
134 | (r'^alias\b.*=', "don't use alias, use a function"), | |||
|
135 | (r'if\s*!', "don't use '!' to negate exit status"), | |||
|
136 | (r'/dev/u?random', "don't use entropy, use /dev/zero"), | |||
|
137 | (r'do\s*true;\s*done', "don't use true as loop body, use sleep 0"), | |||
|
138 | (r'sed (-e )?\'(\d+|/[^/]*/)i(?!\\\n)', | |||
|
139 | "put a backslash-escaped newline after sed 'i' command"), | |||
|
140 | (r'^diff *-\w*[uU].*$\n(^ \$ |^$)', "prefix diff -u/-U with cmp"), | |||
|
141 | (r'^\s+(if)? diff *-\w*[uU]', "prefix diff -u/-U with cmp"), | |||
|
142 | (r'[\s="`\']python\s(?!bindings)', "don't use 'python', use '$PYTHON'"), | |||
|
143 | (r'seq ', "don't use 'seq', use $TESTDIR/seq.py"), | |||
|
144 | (r'\butil\.Abort\b', "directly use error.Abort"), | |||
|
145 | (r'\|&', "don't use |&, use 2>&1"), | |||
|
146 | (r'\w = +\w', "only one space after = allowed"), | |||
|
147 | (r'\bsed\b.*[^\\]\\n', "don't use 'sed ... \\n', use a \\ and a newline"), | |||
|
148 | (r'env.*-u', "don't use 'env -u VAR', use 'unset VAR'"), | |||
|
149 | (r'cp.* -r ', "don't use 'cp -r', use 'cp -R'"), | |||
|
150 | (r'grep.* -[ABC]', "don't use grep's context flags"), | |||
|
151 | (r'find.*-printf', | |||
|
152 | "don't use 'find -printf', it doesn't exist on BSD find(1)"), | |||
|
153 | (r'\$RANDOM ', "don't use bash-only $RANDOM to generate random values"), | |||
|
154 | ], | |||
|
155 | # warnings | |||
|
156 | [ | |||
|
157 | (r'^function', "don't use 'function', use old style"), | |||
|
158 | (r'^diff.*-\w*N', "don't use 'diff -N'"), | |||
|
159 | (r'\$PWD|\${PWD}', "don't use $PWD, use `pwd`"), | |||
|
160 | (r'^([^"\'\n]|("[^"\n]*")|(\'[^\'\n]*\'))*\^', "^ must be quoted"), | |||
|
161 | (r'kill (`|\$\()', "don't use kill, use killdaemons.py") | |||
|
162 | ] | |||
|
163 | ] | |||
|
164 | ||||
|
165 | testfilters = [ | |||
|
166 | (r"( *)(#([^!][^\n]*\S)?)", repcomment), | |||
|
167 | (r"<<(\S+)((.|\n)*?\n\1)", rephere), | |||
|
168 | ] | |||
|
169 | ||||
|
170 | uprefix = r"^ \$ " | |||
|
171 | utestpats = [ | |||
|
172 | [ | |||
|
173 | (r'^(\S.*|| [$>] \S.*)[ \t]\n', "trailing whitespace on non-output"), | |||
|
174 | (uprefix + r'.*\|\s*sed[^|>\n]*\n', | |||
|
175 | "use regex test output patterns instead of sed"), | |||
|
176 | (uprefix + r'(true|exit 0)', "explicit zero exit unnecessary"), | |||
|
177 | (uprefix + r'.*(?<!\[)\$\?', "explicit exit code checks unnecessary"), | |||
|
178 | (uprefix + r'.*\|\| echo.*(fail|error)', | |||
|
179 | "explicit exit code checks unnecessary"), | |||
|
180 | (uprefix + r'set -e', "don't use set -e"), | |||
|
181 | (uprefix + r'(\s|fi\b|done\b)', "use > for continued lines"), | |||
|
182 | (uprefix + r'.*:\.\S*/', "x:.y in a path does not work on msys, rewrite " | |||
|
183 | "as x://.y, or see `hg log -k msys` for alternatives", r'-\S+:\.|' #-Rxxx | |||
|
184 | '# no-msys'), # in test-pull.t which is skipped on windows | |||
|
185 | (r'^ [^$>].*27\.0\.0\.1', | |||
|
186 | 'use $LOCALIP not an explicit loopback address'), | |||
|
187 | (r'^ (?![>$] ).*\$LOCALIP.*[^)]$', | |||
|
188 | 'mark $LOCALIP output lines with (glob) to help tests in BSD jails'), | |||
|
189 | (r'^ (cat|find): .*: \$ENOENT\$', | |||
|
190 | 'use test -f to test for file existence'), | |||
|
191 | (r'^ diff -[^ -]*p', | |||
|
192 | "don't use (external) diff with -p for portability"), | |||
|
193 | (r' readlink ', 'use readlink.py instead of readlink'), | |||
|
194 | (r'^ [-+][-+][-+] .* [-+]0000 \(glob\)', | |||
|
195 | "glob timezone field in diff output for portability"), | |||
|
196 | (r'^ @@ -[0-9]+ [+][0-9]+,[0-9]+ @@', | |||
|
197 | "use '@@ -N* +N,n @@ (glob)' style chunk header for portability"), | |||
|
198 | (r'^ @@ -[0-9]+,[0-9]+ [+][0-9]+ @@', | |||
|
199 | "use '@@ -N,n +N* @@ (glob)' style chunk header for portability"), | |||
|
200 | (r'^ @@ -[0-9]+ [+][0-9]+ @@', | |||
|
201 | "use '@@ -N* +N* @@ (glob)' style chunk header for portability"), | |||
|
202 | (uprefix + r'hg( +-[^ ]+( +[^ ]+)?)* +extdiff' | |||
|
203 | r'( +(-[^ po-]+|--(?!program|option)[^ ]+|[^-][^ ]*))*$', | |||
|
204 | "use $RUNTESTDIR/pdiff via extdiff (or -o/-p for false-positives)"), | |||
|
205 | ], | |||
|
206 | # warnings | |||
|
207 | [ | |||
|
208 | (r'^ (?!.*\$LOCALIP)[^*?/\n]* \(glob\)$', | |||
|
209 | "glob match with no glob string (?, *, /, and $LOCALIP)"), | |||
|
210 | ] | |||
|
211 | ] | |||
|
212 | ||||
|
213 | # transform plain test rules to unified test's | |||
|
214 | for i in [0, 1]: | |||
|
215 | for tp in testpats[i]: | |||
|
216 | p = tp[0] | |||
|
217 | m = tp[1] | |||
|
218 | if p.startswith(r'^'): | |||
|
219 | p = r"^ [$>] (%s)" % p[1:] | |||
|
220 | else: | |||
|
221 | p = r"^ [$>] .*(%s)" % p | |||
|
222 | utestpats[i].append((p, m) + tp[2:]) | |||
|
223 | ||||
|
224 | # don't transform the following rules: | |||
|
225 | # " > \t" and " \t" should be allowed in unified tests | |||
|
226 | testpats[0].append((r'^( *)\t', "don't use tabs to indent")) | |||
|
227 | utestpats[0].append((r'^( ?)\t', "don't use tabs to indent")) | |||
|
228 | ||||
|
229 | utestfilters = [ | |||
|
230 | (r"<<(\S+)((.|\n)*?\n > \1)", rephere), | |||
|
231 | (r"( +)(#([^!][^\n]*\S)?)", repcomment), | |||
|
232 | ] | |||
|
233 | ||||
|
234 | pypats = [ | |||
|
235 | [ | |||
|
236 | (r'^\s*def\s*\w+\s*\(.*,\s*\(', | |||
|
237 | "tuple parameter unpacking not available in Python 3+"), | |||
|
238 | (r'lambda\s*\(.*,.*\)', | |||
|
239 | "tuple parameter unpacking not available in Python 3+"), | |||
|
240 | (r'(?<!def)\s+(cmp)\(', "cmp is not available in Python 3+"), | |||
|
241 | (r'(?<!\.)\breduce\s*\(.*', "reduce is not available in Python 3+"), | |||
|
242 | (r'\bdict\(.*=', 'dict() is different in Py2 and 3 and is slower than {}', | |||
|
243 | 'dict-from-generator'), | |||
|
244 | (r'\.has_key\b', "dict.has_key is not available in Python 3+"), | |||
|
245 | (r'\s<>\s', '<> operator is not available in Python 3+, use !='), | |||
|
246 | (r'^\s*\t', "don't use tabs"), | |||
|
247 | (r'\S;\s*\n', "semicolon"), | |||
|
248 | (r'[^_]_\([ \t\n]*(?:"[^"]+"[ \t\n+]*)+%', "don't use % inside _()"), | |||
|
249 | (r"[^_]_\([ \t\n]*(?:'[^']+'[ \t\n+]*)+%", "don't use % inside _()"), | |||
|
250 | (r'(\w|\)),\w', "missing whitespace after ,"), | |||
|
251 | (r'(\w|\))[+/*\-<>]\w', "missing whitespace in expression"), | |||
|
252 | (r'^\s+(\w|\.)+=\w[^,()\n]*$', "missing whitespace in assignment"), | |||
|
253 | (r'\w\s=\s\s+\w', "gratuitous whitespace after ="), | |||
|
254 | (( | |||
|
255 | # a line ending with a colon, potentially with trailing comments | |||
|
256 | r':([ \t]*#[^\n]*)?\n' | |||
|
257 | # one that is not a pass and not only a comment | |||
|
258 | r'(?P<indent>[ \t]+)[^#][^\n]+\n' | |||
|
259 | # more lines at the same indent level | |||
|
260 | r'((?P=indent)[^\n]+\n)*' | |||
|
261 | # a pass at the same indent level, which is bogus | |||
|
262 | r'(?P=indent)pass[ \t\n#]' | |||
|
263 | ), 'omit superfluous pass'), | |||
|
264 | (r'.{81}', "line too long"), | |||
|
265 | (r'[^\n]\Z', "no trailing newline"), | |||
|
266 | (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"), | |||
|
267 | # (r'^\s+[^_ \n][^_. \n]+_[^_\n]+\s*=', | |||
|
268 | # "don't use underbars in identifiers"), | |||
|
269 | (r'^\s+(self\.)?[A-Za-z][a-z0-9]+[A-Z]\w* = ', | |||
|
270 | "don't use camelcase in identifiers", r'#.*camelcase-required'), | |||
|
271 | (r'^\s*(if|while|def|class|except|try)\s[^[\n]*:\s*[^\\n]#\s]+', | |||
|
272 | "linebreak after :"), | |||
|
273 | (r'class\s[^( \n]+:', "old-style class, use class foo(object)", | |||
|
274 | r'#.*old-style'), | |||
|
275 | (r'class\s[^( \n]+\(\):', | |||
|
276 | "class foo() creates old style object, use class foo(object)", | |||
|
277 | r'#.*old-style'), | |||
|
278 | (r'\b(%s)\(' % '|'.join(k for k in keyword.kwlist | |||
|
279 | if k not in ('print', 'exec')), | |||
|
280 | "Python keyword is not a function"), | |||
|
281 | (r',]', "unneeded trailing ',' in list"), | |||
|
282 | # (r'class\s[A-Z][^\(]*\((?!Exception)', | |||
|
283 | # "don't capitalize non-exception classes"), | |||
|
284 | # (r'in range\(', "use xrange"), | |||
|
285 | # (r'^\s*print\s+', "avoid using print in core and extensions"), | |||
|
286 | (r'[\x80-\xff]', "non-ASCII character literal"), | |||
|
287 | (r'("\')\.format\(', "str.format() has no bytes counterpart, use %"), | |||
|
288 | (r'^\s*(%s)\s\s' % '|'.join(keyword.kwlist), | |||
|
289 | "gratuitous whitespace after Python keyword"), | |||
|
290 | (r'([\(\[][ \t]\S)|(\S[ \t][\)\]])', "gratuitous whitespace in () or []"), | |||
|
291 | # (r'\s\s=', "gratuitous whitespace before ="), | |||
|
292 | (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S', | |||
|
293 | "missing whitespace around operator"), | |||
|
294 | (r'[^>< ](\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\s', | |||
|
295 | "missing whitespace around operator"), | |||
|
296 | (r'\s(\+=|-=|!=|<>|<=|>=|<<=|>>=|%=)\S', | |||
|
297 | "missing whitespace around operator"), | |||
|
298 | (r'[^^+=*/!<>&| %-](\s=|=\s)[^= ]', | |||
|
299 | "wrong whitespace around ="), | |||
|
300 | (r'\([^()]*( =[^=]|[^<>!=]= )', | |||
|
301 | "no whitespace around = for named parameters"), | |||
|
302 | (r'raise Exception', "don't raise generic exceptions"), | |||
|
303 | (r'raise [^,(]+, (\([^\)]+\)|[^,\(\)]+)$', | |||
|
304 | "don't use old-style two-argument raise, use Exception(message)"), | |||
|
305 | (r' is\s+(not\s+)?["\'0-9-]', "object comparison with literal"), | |||
|
306 | (r' [=!]=\s+(True|False|None)', | |||
|
307 | "comparison with singleton, use 'is' or 'is not' instead"), | |||
|
308 | (r'^\s*(while|if) [01]:', | |||
|
309 | "use True/False for constant Boolean expression"), | |||
|
310 | (r'^\s*if False(:| +and)', 'Remove code instead of using `if False`'), | |||
|
311 | (r'(?:(?<!def)\s+|\()hasattr\(', | |||
|
312 | 'hasattr(foo, bar) is broken on py2, use util.safehasattr(foo, bar) ' | |||
|
313 | 'instead', r'#.*hasattr-py3-only'), | |||
|
314 | (r'opener\([^)]*\).read\(', | |||
|
315 | "use opener.read() instead"), | |||
|
316 | (r'opener\([^)]*\).write\(', | |||
|
317 | "use opener.write() instead"), | |||
|
318 | (r'[\s\(](open|file)\([^)]*\)\.read\(', | |||
|
319 | "use util.readfile() instead"), | |||
|
320 | (r'[\s\(](open|file)\([^)]*\)\.write\(', | |||
|
321 | "use util.writefile() instead"), | |||
|
322 | (r'^[\s\(]*(open(er)?|file)\([^)]*\)(?!\.close\(\))', | |||
|
323 | "always assign an opened file to a variable, and close it afterwards"), | |||
|
324 | (r'[\s\(](open|file)\([^)]*\)\.(?!close\(\))', | |||
|
325 | "always assign an opened file to a variable, and close it afterwards"), | |||
|
326 | (r'(?i)descend[e]nt', "the proper spelling is descendAnt"), | |||
|
327 | (r'\.debug\(\_', "don't mark debug messages for translation"), | |||
|
328 | (r'\.strip\(\)\.split\(\)', "no need to strip before splitting"), | |||
|
329 | (r'^\s*except\s*:', "naked except clause", r'#.*re-raises'), | |||
|
330 | (r'^\s*except\s([^\(,]+|\([^\)]+\))\s*,', | |||
|
331 | 'legacy exception syntax; use "as" instead of ","'), | |||
|
332 | (r':\n( )*( ){1,3}[^ ]', "must indent 4 spaces"), | |||
|
333 | (r'release\(.*wlock, .*lock\)', "wrong lock release order"), | |||
|
334 | (r'\bdef\s+__bool__\b', "__bool__ should be __nonzero__ in Python 2"), | |||
|
335 | (r'os\.path\.join\(.*, *(""|\'\')\)', | |||
|
336 | "use pathutil.normasprefix(path) instead of os.path.join(path, '')"), | |||
|
337 | (r'\s0[0-7]+\b', 'legacy octal syntax; use "0o" prefix instead of "0"'), | |||
|
338 | # XXX only catch mutable arguments on the first line of the definition | |||
|
339 | (r'def.*[( ]\w+=\{\}', "don't use mutable default arguments"), | |||
|
340 | (r'\butil\.Abort\b', "directly use error.Abort"), | |||
|
341 | (r'^@(\w*\.)?cachefunc', "module-level @cachefunc is risky, please avoid"), | |||
|
342 | (r'^import atexit', "don't use atexit, use ui.atexit"), | |||
|
343 | (r'^import Queue', "don't use Queue, use pycompat.queue.Queue + " | |||
|
344 | "pycompat.queue.Empty"), | |||
|
345 | (r'^import cStringIO', "don't use cStringIO.StringIO, use util.stringio"), | |||
|
346 | (r'^import urllib', "don't use urllib, use util.urlreq/util.urlerr"), | |||
|
347 | (r'^import SocketServer', "don't use SockerServer, use util.socketserver"), | |||
|
348 | (r'^import urlparse', "don't use urlparse, use util.urlreq"), | |||
|
349 | (r'^import xmlrpclib', "don't use xmlrpclib, use util.xmlrpclib"), | |||
|
350 | (r'^import cPickle', "don't use cPickle, use util.pickle"), | |||
|
351 | (r'^import pickle', "don't use pickle, use util.pickle"), | |||
|
352 | (r'^import httplib', "don't use httplib, use util.httplib"), | |||
|
353 | (r'^import BaseHTTPServer', "use util.httpserver instead"), | |||
|
354 | (r'^(from|import) mercurial\.(cext|pure|cffi)', | |||
|
355 | "use mercurial.policy.importmod instead"), | |||
|
356 | (r'\.next\(\)', "don't use .next(), use next(...)"), | |||
|
357 | (r'([a-z]*).revision\(\1\.node\(', | |||
|
358 | "don't convert rev to node before passing to revision(nodeorrev)"), | |||
|
359 | (r'platform\.system\(\)', "don't use platform.system(), use pycompat"), | |||
|
360 | ||||
|
361 | # rules depending on implementation of repquote() | |||
|
362 | (r' x+[xpqo%APM][\'"]\n\s+[\'"]x', | |||
|
363 | 'string join across lines with no space'), | |||
|
364 | (r'''(?x)ui\.(status|progress|write|note|warn)\( | |||
|
365 | [ \t\n#]* | |||
|
366 | (?# any strings/comments might precede a string, which | |||
|
367 | # contains translatable message) | |||
|
368 | ((['"]|\'\'\'|""")[ \npq%bAPMxno]*(['"]|\'\'\'|""")[ \t\n#]+)* | |||
|
369 | (?# sequence consisting of below might precede translatable message | |||
|
370 | # - formatting string: "% 10s", "%05d", "% -3.2f", "%*s", "%%" ... | |||
|
371 | # - escaped character: "\\", "\n", "\0" ... | |||
|
372 | # - character other than '%', 'b' as '\', and 'x' as alphabet) | |||
|
373 | (['"]|\'\'\'|""") | |||
|
374 | ((%([ n]?[PM]?([np]+|A))?x)|%%|b[bnx]|[ \nnpqAPMo])*x | |||
|
375 | (?# this regexp can't use [^...] style, | |||
|
376 | # because _preparepats forcibly adds "\n" into [^...], | |||
|
377 | # even though this regexp wants match it against "\n")''', | |||
|
378 | "missing _() in ui message (use () to hide false-positives)"), | |||
|
379 | ], | |||
|
380 | # warnings | |||
|
381 | [ | |||
|
382 | # rules depending on implementation of repquote() | |||
|
383 | (r'(^| )pp +xxxxqq[ \n][^\n]', "add two newlines after '.. note::'"), | |||
|
384 | ] | |||
|
385 | ] | |||
|
386 | ||||
|
387 | pyfilters = [ | |||
|
388 | (r"""(?msx)(?P<comment>\#.*?$)| | |||
|
389 | ((?P<quote>('''|\"\"\"|(?<!')'(?!')|(?<!")"(?!"))) | |||
|
390 | (?P<text>(([^\\]|\\.)*?)) | |||
|
391 | (?P=quote))""", reppython), | |||
|
392 | ] | |||
|
393 | ||||
|
394 | # non-filter patterns | |||
|
395 | pynfpats = [ | |||
|
396 | [ | |||
|
397 | (r'pycompat\.osname\s*[=!]=\s*[\'"]nt[\'"]', "use pycompat.iswindows"), | |||
|
398 | (r'pycompat\.osname\s*[=!]=\s*[\'"]posix[\'"]', "use pycompat.isposix"), | |||
|
399 | (r'pycompat\.sysplatform\s*[!=]=\s*[\'"]darwin[\'"]', | |||
|
400 | "use pycompat.isdarwin"), | |||
|
401 | ], | |||
|
402 | # warnings | |||
|
403 | [], | |||
|
404 | ] | |||
|
405 | ||||
|
406 | # extension non-filter patterns | |||
|
407 | pyextnfpats = [ | |||
|
408 | [(r'^"""\n?[A-Z]', "don't capitalize docstring title")], | |||
|
409 | # warnings | |||
|
410 | [], | |||
|
411 | ] | |||
|
412 | ||||
|
413 | txtfilters = [] | |||
|
414 | ||||
|
415 | txtpats = [ | |||
|
416 | [ | |||
|
417 | ('\s$', 'trailing whitespace'), | |||
|
418 | ('.. note::[ \n][^\n]', 'add two newlines after note::') | |||
|
419 | ], | |||
|
420 | [] | |||
|
421 | ] | |||
|
422 | ||||
|
423 | cpats = [ | |||
|
424 | [ | |||
|
425 | (r'//', "don't use //-style comments"), | |||
|
426 | (r'\S\t', "don't use tabs except for indent"), | |||
|
427 | (r'(\S[ \t]+|^[ \t]+)\n', "trailing whitespace"), | |||
|
428 | (r'.{81}', "line too long"), | |||
|
429 | (r'(while|if|do|for)\(', "use space after while/if/do/for"), | |||
|
430 | (r'return\(', "return is not a function"), | |||
|
431 | (r' ;', "no space before ;"), | |||
|
432 | (r'[^;] \)', "no space before )"), | |||
|
433 | (r'[)][{]', "space between ) and {"), | |||
|
434 | (r'\w+\* \w+', "use int *foo, not int* foo"), | |||
|
435 | (r'\W\([^\)]+\) \w+', "use (int)foo, not (int) foo"), | |||
|
436 | (r'\w+ (\+\+|--)', "use foo++, not foo ++"), | |||
|
437 | (r'\w,\w', "missing whitespace after ,"), | |||
|
438 | (r'^[^#]\w[+/*]\w', "missing whitespace in expression"), | |||
|
439 | (r'\w\s=\s\s+\w', "gratuitous whitespace after ="), | |||
|
440 | (r'^#\s+\w', "use #foo, not # foo"), | |||
|
441 | (r'[^\n]\Z', "no trailing newline"), | |||
|
442 | (r'^\s*#import\b', "use only #include in standard C code"), | |||
|
443 | (r'strcpy\(', "don't use strcpy, use strlcpy or memcpy"), | |||
|
444 | (r'strcat\(', "don't use strcat"), | |||
|
445 | ||||
|
446 | # rules depending on implementation of repquote() | |||
|
447 | ], | |||
|
448 | # warnings | |||
|
449 | [ | |||
|
450 | # rules depending on implementation of repquote() | |||
|
451 | ] | |||
|
452 | ] | |||
|
453 | ||||
|
454 | cfilters = [ | |||
|
455 | (r'(/\*)(((\*(?!/))|[^*])*)\*/', repccomment), | |||
|
456 | (r'''(?P<quote>(?<!")")(?P<text>([^"]|\\")+)"(?!")''', repquote), | |||
|
457 | (r'''(#\s*include\s+<)([^>]+)>''', repinclude), | |||
|
458 | (r'(\()([^)]+\))', repcallspaces), | |||
|
459 | ] | |||
|
460 | ||||
|
461 | inutilpats = [ | |||
|
462 | [ | |||
|
463 | (r'\bui\.', "don't use ui in util"), | |||
|
464 | ], | |||
|
465 | # warnings | |||
|
466 | [] | |||
|
467 | ] | |||
|
468 | ||||
|
469 | inrevlogpats = [ | |||
|
470 | [ | |||
|
471 | (r'\brepo\.', "don't use repo in revlog"), | |||
|
472 | ], | |||
|
473 | # warnings | |||
|
474 | [] | |||
|
475 | ] | |||
|
476 | ||||
|
477 | webtemplatefilters = [] | |||
|
478 | ||||
|
479 | webtemplatepats = [ | |||
|
480 | [], | |||
|
481 | [ | |||
|
482 | (r'{desc(\|(?!websub|firstline)[^\|]*)+}', | |||
|
483 | 'follow desc keyword with either firstline or websub'), | |||
|
484 | ] | |||
|
485 | ] | |||
|
486 | ||||
|
487 | allfilesfilters = [] | |||
|
488 | ||||
|
489 | allfilespats = [ | |||
|
490 | [ | |||
|
491 | (r'(http|https)://[a-zA-Z0-9./]*selenic.com/', | |||
|
492 | 'use mercurial-scm.org domain URL'), | |||
|
493 | (r'mercurial@selenic\.com', | |||
|
494 | 'use mercurial-scm.org domain for mercurial ML address'), | |||
|
495 | (r'mercurial-devel@selenic\.com', | |||
|
496 | 'use mercurial-scm.org domain for mercurial-devel ML address'), | |||
|
497 | ], | |||
|
498 | # warnings | |||
|
499 | [], | |||
|
500 | ] | |||
|
501 | ||||
|
502 | py3pats = [ | |||
|
503 | [ | |||
|
504 | (r'os\.environ', "use encoding.environ instead (py3)", r'#.*re-exports'), | |||
|
505 | (r'os\.name', "use pycompat.osname instead (py3)"), | |||
|
506 | (r'os\.getcwd', "use pycompat.getcwd instead (py3)"), | |||
|
507 | (r'os\.sep', "use pycompat.ossep instead (py3)"), | |||
|
508 | (r'os\.pathsep', "use pycompat.ospathsep instead (py3)"), | |||
|
509 | (r'os\.altsep', "use pycompat.osaltsep instead (py3)"), | |||
|
510 | (r'sys\.platform', "use pycompat.sysplatform instead (py3)"), | |||
|
511 | (r'getopt\.getopt', "use pycompat.getoptb instead (py3)"), | |||
|
512 | (r'os\.getenv', "use encoding.environ.get instead"), | |||
|
513 | (r'os\.setenv', "modifying the environ dict is not preferred"), | |||
|
514 | (r'(?<!pycompat\.)xrange', "use pycompat.xrange instead (py3)"), | |||
|
515 | ], | |||
|
516 | # warnings | |||
|
517 | [], | |||
|
518 | ] | |||
|
519 | ||||
|
520 | checks = [ | |||
|
521 | ('python', r'.*\.(py|cgi)$', r'^#!.*python', pyfilters, pypats), | |||
|
522 | ('python', r'.*\.(py|cgi)$', r'^#!.*python', [], pynfpats), | |||
|
523 | ('python', r'.*hgext.*\.py$', '', [], pyextnfpats), | |||
|
524 | ('python 3', r'.*(hgext|mercurial)/(?!demandimport|policy|pycompat).*\.py', | |||
|
525 | '', pyfilters, py3pats), | |||
|
526 | ('test script', r'(.*/)?test-[^.~]*$', '', testfilters, testpats), | |||
|
527 | ('c', r'.*\.[ch]$', '', cfilters, cpats), | |||
|
528 | ('unified test', r'.*\.t$', '', utestfilters, utestpats), | |||
|
529 | ('layering violation repo in revlog', r'mercurial/revlog\.py', '', | |||
|
530 | pyfilters, inrevlogpats), | |||
|
531 | ('layering violation ui in util', r'mercurial/util\.py', '', pyfilters, | |||
|
532 | inutilpats), | |||
|
533 | ('txt', r'.*\.txt$', '', txtfilters, txtpats), | |||
|
534 | ('web template', r'mercurial/templates/.*\.tmpl', '', | |||
|
535 | webtemplatefilters, webtemplatepats), | |||
|
536 | ('all except for .po', r'.*(?<!\.po)$', '', | |||
|
537 | allfilesfilters, allfilespats), | |||
|
538 | ] | |||
|
539 | ||||
|
540 | def _preparepats(): | |||
|
541 | for c in checks: | |||
|
542 | failandwarn = c[-1] | |||
|
543 | for pats in failandwarn: | |||
|
544 | for i, pseq in enumerate(pats): | |||
|
545 | # fix-up regexes for multi-line searches | |||
|
546 | p = pseq[0] | |||
|
547 | # \s doesn't match \n (done in two steps) | |||
|
548 | # first, we replace \s that appears in a set already | |||
|
549 | p = re.sub(r'\[\\s', r'[ \\t', p) | |||
|
550 | # now we replace other \s instances. | |||
|
551 | p = re.sub(r'(?<!(\\|\[))\\s', r'[ \\t]', p) | |||
|
552 | # [^...] doesn't match newline | |||
|
553 | p = re.sub(r'(?<!\\)\[\^', r'[^\\n', p) | |||
|
554 | ||||
|
555 | pats[i] = (re.compile(p, re.MULTILINE),) + pseq[1:] | |||
|
556 | filters = c[3] | |||
|
557 | for i, flt in enumerate(filters): | |||
|
558 | filters[i] = re.compile(flt[0]), flt[1] | |||
|
559 | ||||
|
560 | class norepeatlogger(object): | |||
|
561 | def __init__(self): | |||
|
562 | self._lastseen = None | |||
|
563 | ||||
|
564 | def log(self, fname, lineno, line, msg, blame): | |||
|
565 | """print error related a to given line of a given file. | |||
|
566 | ||||
|
567 | The faulty line will also be printed but only once in the case | |||
|
568 | of multiple errors. | |||
|
569 | ||||
|
570 | :fname: filename | |||
|
571 | :lineno: line number | |||
|
572 | :line: actual content of the line | |||
|
573 | :msg: error message | |||
|
574 | """ | |||
|
575 | msgid = fname, lineno, line | |||
|
576 | if msgid != self._lastseen: | |||
|
577 | if blame: | |||
|
578 | print("%s:%d (%s):" % (fname, lineno, blame)) | |||
|
579 | else: | |||
|
580 | print("%s:%d:" % (fname, lineno)) | |||
|
581 | print(" > %s" % line) | |||
|
582 | self._lastseen = msgid | |||
|
583 | print(" " + msg) | |||
|
584 | ||||
|
585 | _defaultlogger = norepeatlogger() | |||
|
586 | ||||
|
587 | def getblame(f): | |||
|
588 | lines = [] | |||
|
589 | for l in os.popen('hg annotate -un %s' % f): | |||
|
590 | start, line = l.split(':', 1) | |||
|
591 | user, rev = start.split() | |||
|
592 | lines.append((line[1:-1], user, rev)) | |||
|
593 | return lines | |||
|
594 | ||||
|
595 | def checkfile(f, logfunc=_defaultlogger.log, maxerr=None, warnings=False, | |||
|
596 | blame=False, debug=False, lineno=True): | |||
|
597 | """checks style and portability of a given file | |||
|
598 | ||||
|
599 | :f: filepath | |||
|
600 | :logfunc: function used to report error | |||
|
601 | logfunc(filename, linenumber, linecontent, errormessage) | |||
|
602 | :maxerr: number of error to display before aborting. | |||
|
603 | Set to false (default) to report all errors | |||
|
604 | ||||
|
605 | return True if no error is found, False otherwise. | |||
|
606 | """ | |||
|
607 | blamecache = None | |||
|
608 | result = True | |||
|
609 | ||||
|
610 | try: | |||
|
611 | with opentext(f) as fp: | |||
|
612 | try: | |||
|
613 | pre = post = fp.read() | |||
|
614 | except UnicodeDecodeError as e: | |||
|
615 | print("%s while reading %s" % (e, f)) | |||
|
616 | return result | |||
|
617 | except IOError as e: | |||
|
618 | print("Skipping %s, %s" % (f, str(e).split(':', 1)[0])) | |||
|
619 | return result | |||
|
620 | ||||
|
621 | for name, match, magic, filters, pats in checks: | |||
|
622 | post = pre # discard filtering result of previous check | |||
|
623 | if debug: | |||
|
624 | print(name, f) | |||
|
625 | fc = 0 | |||
|
626 | if not (re.match(match, f) or (magic and re.search(magic, pre))): | |||
|
627 | if debug: | |||
|
628 | print("Skipping %s for %s it doesn't match %s" % ( | |||
|
629 | name, match, f)) | |||
|
630 | continue | |||
|
631 | if "no-" "check-code" in pre: | |||
|
632 | # If you're looking at this line, it's because a file has: | |||
|
633 | # no- check- code | |||
|
634 | # but the reason to output skipping is to make life for | |||
|
635 | # tests easier. So, instead of writing it with a normal | |||
|
636 | # spelling, we write it with the expected spelling from | |||
|
637 | # tests/test-check-code.t | |||
|
638 | print("Skipping %s it has no-che?k-code (glob)" % f) | |||
|
639 | return "Skip" # skip checking this file | |||
|
640 | for p, r in filters: | |||
|
641 | post = re.sub(p, r, post) | |||
|
642 | nerrs = len(pats[0]) # nerr elements are errors | |||
|
643 | if warnings: | |||
|
644 | pats = pats[0] + pats[1] | |||
|
645 | else: | |||
|
646 | pats = pats[0] | |||
|
647 | # print post # uncomment to show filtered version | |||
|
648 | ||||
|
649 | if debug: | |||
|
650 | print("Checking %s for %s" % (name, f)) | |||
|
651 | ||||
|
652 | prelines = None | |||
|
653 | errors = [] | |||
|
654 | for i, pat in enumerate(pats): | |||
|
655 | if len(pat) == 3: | |||
|
656 | p, msg, ignore = pat | |||
|
657 | else: | |||
|
658 | p, msg = pat | |||
|
659 | ignore = None | |||
|
660 | if i >= nerrs: | |||
|
661 | msg = "warning: " + msg | |||
|
662 | ||||
|
663 | pos = 0 | |||
|
664 | n = 0 | |||
|
665 | for m in p.finditer(post): | |||
|
666 | if prelines is None: | |||
|
667 | prelines = pre.splitlines() | |||
|
668 | postlines = post.splitlines(True) | |||
|
669 | ||||
|
670 | start = m.start() | |||
|
671 | while n < len(postlines): | |||
|
672 | step = len(postlines[n]) | |||
|
673 | if pos + step > start: | |||
|
674 | break | |||
|
675 | pos += step | |||
|
676 | n += 1 | |||
|
677 | l = prelines[n] | |||
|
678 | ||||
|
679 | if ignore and re.search(ignore, l, re.MULTILINE): | |||
|
680 | if debug: | |||
|
681 | print("Skipping %s for %s:%s (ignore pattern)" % ( | |||
|
682 | name, f, n)) | |||
|
683 | continue | |||
|
684 | bd = "" | |||
|
685 | if blame: | |||
|
686 | bd = 'working directory' | |||
|
687 | if not blamecache: | |||
|
688 | blamecache = getblame(f) | |||
|
689 | if n < len(blamecache): | |||
|
690 | bl, bu, br = blamecache[n] | |||
|
691 | if bl == l: | |||
|
692 | bd = '%s@%s' % (bu, br) | |||
|
693 | ||||
|
694 | errors.append((f, lineno and n + 1, l, msg, bd)) | |||
|
695 | result = False | |||
|
696 | ||||
|
697 | errors.sort() | |||
|
698 | for e in errors: | |||
|
699 | logfunc(*e) | |||
|
700 | fc += 1 | |||
|
701 | if maxerr and fc >= maxerr: | |||
|
702 | print(" (too many errors, giving up)") | |||
|
703 | break | |||
|
704 | ||||
|
705 | return result | |||
|
706 | ||||
|
707 | def main(): | |||
|
708 | parser = optparse.OptionParser("%prog [options] [files | -]") | |||
|
709 | parser.add_option("-w", "--warnings", action="store_true", | |||
|
710 | help="include warning-level checks") | |||
|
711 | parser.add_option("-p", "--per-file", type="int", | |||
|
712 | help="max warnings per file") | |||
|
713 | parser.add_option("-b", "--blame", action="store_true", | |||
|
714 | help="use annotate to generate blame info") | |||
|
715 | parser.add_option("", "--debug", action="store_true", | |||
|
716 | help="show debug information") | |||
|
717 | parser.add_option("", "--nolineno", action="store_false", | |||
|
718 | dest='lineno', help="don't show line numbers") | |||
|
719 | ||||
|
720 | parser.set_defaults(per_file=15, warnings=False, blame=False, debug=False, | |||
|
721 | lineno=True) | |||
|
722 | (options, args) = parser.parse_args() | |||
|
723 | ||||
|
724 | if len(args) == 0: | |||
|
725 | check = glob.glob("*") | |||
|
726 | elif args == ['-']: | |||
|
727 | # read file list from stdin | |||
|
728 | check = sys.stdin.read().splitlines() | |||
|
729 | else: | |||
|
730 | check = args | |||
|
731 | ||||
|
732 | _preparepats() | |||
|
733 | ||||
|
734 | ret = 0 | |||
|
735 | for f in check: | |||
|
736 | if not checkfile(f, maxerr=options.per_file, warnings=options.warnings, | |||
|
737 | blame=options.blame, debug=options.debug, | |||
|
738 | lineno=options.lineno): | |||
|
739 | ret = 1 | |||
|
740 | return ret | |||
|
741 | ||||
|
742 | if __name__ == "__main__": | |||
|
743 | sys.exit(main()) |
@@ -0,0 +1,111 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | # | |||
|
3 | # Copyright 2014 Matt Mackall <mpm@selenic.com> | |||
|
4 | # | |||
|
5 | # A tool/hook to run basic sanity checks on commits/patches for | |||
|
6 | # submission to Mercurial. Install by adding the following to your | |||
|
7 | # .hg/hgrc: | |||
|
8 | # | |||
|
9 | # [hooks] | |||
|
10 | # pretxncommit = contrib/check-commit | |||
|
11 | # | |||
|
12 | # The hook can be temporarily bypassed with: | |||
|
13 | # | |||
|
14 | # $ BYPASS= hg commit | |||
|
15 | # | |||
|
16 | # See also: https://mercurial-scm.org/wiki/ContributingChanges | |||
|
17 | ||||
|
18 | from __future__ import absolute_import, print_function | |||
|
19 | ||||
|
20 | import os | |||
|
21 | import re | |||
|
22 | import sys | |||
|
23 | ||||
|
24 | commitheader = r"^(?:# [^\n]*\n)*" | |||
|
25 | afterheader = commitheader + r"(?!#)" | |||
|
26 | beforepatch = afterheader + r"(?!\n(?!@@))" | |||
|
27 | ||||
|
28 | errors = [ | |||
|
29 | (beforepatch + r".*[(]bc[)]", "(BC) needs to be uppercase"), | |||
|
30 | (beforepatch + r".*[(]issue \d\d\d", | |||
|
31 | "no space allowed between issue and number"), | |||
|
32 | (beforepatch + r".*[(]bug(\d|\s)", "use (issueDDDD) instead of bug"), | |||
|
33 | (commitheader + r"# User [^@\n]+\n", "username is not an email address"), | |||
|
34 | (commitheader + r"(?!merge with )[^#]\S+[^:] ", | |||
|
35 | "summary line doesn't start with 'topic: '"), | |||
|
36 | (afterheader + r"[A-Z][a-z]\S+", "don't capitalize summary lines"), | |||
|
37 | (afterheader + r"[^\n]*: *[A-Z][a-z]\S+", "don't capitalize summary lines"), | |||
|
38 | (afterheader + r"\S*[^A-Za-z0-9-_]\S*: ", | |||
|
39 | "summary keyword should be most user-relevant one-word command or topic"), | |||
|
40 | (afterheader + r".*\.\s*\n", "don't add trailing period on summary line"), | |||
|
41 | (afterheader + r".{79,}", "summary line too long (limit is 78)"), | |||
|
42 | (r"\n\+\n( |\+)\n", "adds double empty line"), | |||
|
43 | (r"\n \n\+\n", "adds double empty line"), | |||
|
44 | # Forbid "_" in function name. | |||
|
45 | # | |||
|
46 | # We skip the check for cffi related functions. They use names mapping the | |||
|
47 | # name of the C function. C function names may contain "_". | |||
|
48 | (r"\n\+[ \t]+def (?!cffi)[a-z]+_[a-z]", | |||
|
49 | "adds a function with foo_bar naming"), | |||
|
50 | ] | |||
|
51 | ||||
|
52 | word = re.compile('\S') | |||
|
53 | def nonempty(first, second): | |||
|
54 | if word.search(first): | |||
|
55 | return first | |||
|
56 | return second | |||
|
57 | ||||
|
58 | def checkcommit(commit, node=None): | |||
|
59 | exitcode = 0 | |||
|
60 | printed = node is None | |||
|
61 | hits = [] | |||
|
62 | signtag = (afterheader + | |||
|
63 | r'Added (tag [^ ]+|signature) for changeset [a-f0-9]{12}') | |||
|
64 | if re.search(signtag, commit): | |||
|
65 | return 0 | |||
|
66 | for exp, msg in errors: | |||
|
67 | for m in re.finditer(exp, commit): | |||
|
68 | end = m.end() | |||
|
69 | trailing = re.search(r'(\\n)+$', exp) | |||
|
70 | if trailing: | |||
|
71 | end -= len(trailing.group()) / 2 | |||
|
72 | hits.append((end, exp, msg)) | |||
|
73 | if hits: | |||
|
74 | hits.sort() | |||
|
75 | pos = 0 | |||
|
76 | last = '' | |||
|
77 | for n, l in enumerate(commit.splitlines(True)): | |||
|
78 | pos += len(l) | |||
|
79 | while len(hits): | |||
|
80 | end, exp, msg = hits[0] | |||
|
81 | if pos < end: | |||
|
82 | break | |||
|
83 | if not printed: | |||
|
84 | printed = True | |||
|
85 | print("node: %s" % node) | |||
|
86 | print("%d: %s" % (n, msg)) | |||
|
87 | print(" %s" % nonempty(l, last)[:-1]) | |||
|
88 | if "BYPASS" not in os.environ: | |||
|
89 | exitcode = 1 | |||
|
90 | del hits[0] | |||
|
91 | last = nonempty(l, last) | |||
|
92 | ||||
|
93 | return exitcode | |||
|
94 | ||||
|
95 | def readcommit(node): | |||
|
96 | return os.popen("hg export %s" % node).read() | |||
|
97 | ||||
|
98 | if __name__ == "__main__": | |||
|
99 | exitcode = 0 | |||
|
100 | node = os.environ.get("HG_NODE") | |||
|
101 | ||||
|
102 | if node: | |||
|
103 | commit = readcommit(node) | |||
|
104 | exitcode = checkcommit(commit) | |||
|
105 | elif sys.argv[1:]: | |||
|
106 | for node in sys.argv[1:]: | |||
|
107 | exitcode |= checkcommit(readcommit(node), node) | |||
|
108 | else: | |||
|
109 | commit = sys.stdin.read() | |||
|
110 | exitcode = checkcommit(commit) | |||
|
111 | sys.exit(exitcode) |
@@ -0,0 +1,142 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | # | |||
|
3 | # check-config - a config flag documentation checker for Mercurial | |||
|
4 | # | |||
|
5 | # Copyright 2015 Matt Mackall <mpm@selenic.com> | |||
|
6 | # | |||
|
7 | # This software may be used and distributed according to the terms of the | |||
|
8 | # GNU General Public License version 2 or any later version. | |||
|
9 | ||||
|
10 | from __future__ import absolute_import, print_function | |||
|
11 | import re | |||
|
12 | import sys | |||
|
13 | ||||
|
14 | foundopts = {} | |||
|
15 | documented = {} | |||
|
16 | allowinconsistent = set() | |||
|
17 | ||||
|
18 | configre = re.compile(br''' | |||
|
19 | # Function call | |||
|
20 | ui\.config(?P<ctype>|int|bool|list)\( | |||
|
21 | # First argument. | |||
|
22 | ['"](?P<section>\S+)['"],\s* | |||
|
23 | # Second argument | |||
|
24 | ['"](?P<option>\S+)['"](,\s+ | |||
|
25 | (?:default=)?(?P<default>\S+?))? | |||
|
26 | \)''', re.VERBOSE | re.MULTILINE) | |||
|
27 | ||||
|
28 | configwithre = re.compile(b''' | |||
|
29 | ui\.config(?P<ctype>with)\( | |||
|
30 | # First argument is callback function. This doesn't parse robustly | |||
|
31 | # if it is e.g. a function call. | |||
|
32 | [^,]+,\s* | |||
|
33 | ['"](?P<section>\S+)['"],\s* | |||
|
34 | ['"](?P<option>\S+)['"](,\s+ | |||
|
35 | (?:default=)?(?P<default>\S+?))? | |||
|
36 | \)''', re.VERBOSE | re.MULTILINE) | |||
|
37 | ||||
|
38 | configpartialre = (br"""ui\.config""") | |||
|
39 | ||||
|
40 | ignorere = re.compile(br''' | |||
|
41 | \#\s(?P<reason>internal|experimental|deprecated|developer|inconsistent)\s | |||
|
42 | config:\s(?P<config>\S+\.\S+)$ | |||
|
43 | ''', re.VERBOSE | re.MULTILINE) | |||
|
44 | ||||
|
45 | def main(args): | |||
|
46 | for f in args: | |||
|
47 | sect = b'' | |||
|
48 | prevname = b'' | |||
|
49 | confsect = b'' | |||
|
50 | carryover = b'' | |||
|
51 | linenum = 0 | |||
|
52 | for l in open(f, 'rb'): | |||
|
53 | linenum += 1 | |||
|
54 | ||||
|
55 | # check topic-like bits | |||
|
56 | m = re.match(b'\s*``(\S+)``', l) | |||
|
57 | if m: | |||
|
58 | prevname = m.group(1) | |||
|
59 | if re.match(b'^\s*-+$', l): | |||
|
60 | sect = prevname | |||
|
61 | prevname = b'' | |||
|
62 | ||||
|
63 | if sect and prevname: | |||
|
64 | name = sect + b'.' + prevname | |||
|
65 | documented[name] = 1 | |||
|
66 | ||||
|
67 | # check docstring bits | |||
|
68 | m = re.match(br'^\s+\[(\S+)\]', l) | |||
|
69 | if m: | |||
|
70 | confsect = m.group(1) | |||
|
71 | continue | |||
|
72 | m = re.match(br'^\s+(?:#\s*)?(\S+) = ', l) | |||
|
73 | if m: | |||
|
74 | name = confsect + b'.' + m.group(1) | |||
|
75 | documented[name] = 1 | |||
|
76 | ||||
|
77 | # like the bugzilla extension | |||
|
78 | m = re.match(br'^\s*(\S+\.\S+)$', l) | |||
|
79 | if m: | |||
|
80 | documented[m.group(1)] = 1 | |||
|
81 | ||||
|
82 | # like convert | |||
|
83 | m = re.match(br'^\s*:(\S+\.\S+):\s+', l) | |||
|
84 | if m: | |||
|
85 | documented[m.group(1)] = 1 | |||
|
86 | ||||
|
87 | # quoted in help or docstrings | |||
|
88 | m = re.match(br'.*?``(\S+\.\S+)``', l) | |||
|
89 | if m: | |||
|
90 | documented[m.group(1)] = 1 | |||
|
91 | ||||
|
92 | # look for ignore markers | |||
|
93 | m = ignorere.search(l) | |||
|
94 | if m: | |||
|
95 | if m.group('reason') == 'inconsistent': | |||
|
96 | allowinconsistent.add(m.group('config')) | |||
|
97 | else: | |||
|
98 | documented[m.group('config')] = 1 | |||
|
99 | ||||
|
100 | # look for code-like bits | |||
|
101 | line = carryover + l | |||
|
102 | m = configre.search(line) or configwithre.search(line) | |||
|
103 | if m: | |||
|
104 | ctype = m.group('ctype') | |||
|
105 | if not ctype: | |||
|
106 | ctype = 'str' | |||
|
107 | name = m.group('section') + "." + m.group('option') | |||
|
108 | default = m.group('default') | |||
|
109 | if default in (None, 'False', 'None', '0', '[]', '""', "''"): | |||
|
110 | default = '' | |||
|
111 | if re.match(b'[a-z.]+$', default): | |||
|
112 | default = '<variable>' | |||
|
113 | if (name in foundopts and (ctype, default) != foundopts[name] | |||
|
114 | and name not in allowinconsistent): | |||
|
115 | print(l.rstrip()) | |||
|
116 | print("conflict on %s: %r != %r" % (name, (ctype, default), | |||
|
117 | foundopts[name])) | |||
|
118 | print("at %s:%d:" % (f, linenum)) | |||
|
119 | foundopts[name] = (ctype, default) | |||
|
120 | carryover = '' | |||
|
121 | else: | |||
|
122 | m = re.search(configpartialre, line) | |||
|
123 | if m: | |||
|
124 | carryover = line | |||
|
125 | else: | |||
|
126 | carryover = '' | |||
|
127 | ||||
|
128 | for name in sorted(foundopts): | |||
|
129 | if name not in documented: | |||
|
130 | if not (name.startswith("devel.") or | |||
|
131 | name.startswith("experimental.") or | |||
|
132 | name.startswith("debug.")): | |||
|
133 | ctype, default = foundopts[name] | |||
|
134 | if default: | |||
|
135 | default = ' [%s]' % default | |||
|
136 | print("undocumented: %s (%s)%s" % (name, ctype, default)) | |||
|
137 | ||||
|
138 | if __name__ == "__main__": | |||
|
139 | if len(sys.argv) > 1: | |||
|
140 | sys.exit(main(sys.argv[1:])) | |||
|
141 | else: | |||
|
142 | sys.exit(main([l.rstrip() for l in sys.stdin])) |
@@ -0,0 +1,96 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | # | |||
|
3 | # check-py3-compat - check Python 3 compatibility of Mercurial files | |||
|
4 | # | |||
|
5 | # Copyright 2015 Gregory Szorc <gregory.szorc@gmail.com> | |||
|
6 | # | |||
|
7 | # This software may be used and distributed according to the terms of the | |||
|
8 | # GNU General Public License version 2 or any later version. | |||
|
9 | ||||
|
10 | from __future__ import absolute_import, print_function | |||
|
11 | ||||
|
12 | import ast | |||
|
13 | import importlib | |||
|
14 | import os | |||
|
15 | import sys | |||
|
16 | import traceback | |||
|
17 | ||||
|
18 | def check_compat_py2(f): | |||
|
19 | """Check Python 3 compatibility for a file with Python 2""" | |||
|
20 | with open(f, 'rb') as fh: | |||
|
21 | content = fh.read() | |||
|
22 | root = ast.parse(content) | |||
|
23 | ||||
|
24 | # Ignore empty files. | |||
|
25 | if not root.body: | |||
|
26 | return | |||
|
27 | ||||
|
28 | futures = set() | |||
|
29 | haveprint = False | |||
|
30 | for node in ast.walk(root): | |||
|
31 | if isinstance(node, ast.ImportFrom): | |||
|
32 | if node.module == '__future__': | |||
|
33 | futures |= set(n.name for n in node.names) | |||
|
34 | elif isinstance(node, ast.Print): | |||
|
35 | haveprint = True | |||
|
36 | ||||
|
37 | if 'absolute_import' not in futures: | |||
|
38 | print('%s not using absolute_import' % f) | |||
|
39 | if haveprint and 'print_function' not in futures: | |||
|
40 | print('%s requires print_function' % f) | |||
|
41 | ||||
|
42 | def check_compat_py3(f): | |||
|
43 | """Check Python 3 compatibility of a file with Python 3.""" | |||
|
44 | with open(f, 'rb') as fh: | |||
|
45 | content = fh.read() | |||
|
46 | ||||
|
47 | try: | |||
|
48 | ast.parse(content) | |||
|
49 | except SyntaxError as e: | |||
|
50 | print('%s: invalid syntax: %s' % (f, e)) | |||
|
51 | return | |||
|
52 | ||||
|
53 | # Try to import the module. | |||
|
54 | # For now we only support modules in packages because figuring out module | |||
|
55 | # paths for things not in a package can be confusing. | |||
|
56 | if (f.startswith(('hgdemandimport/', 'hgext/', 'mercurial/')) | |||
|
57 | and not f.endswith('__init__.py')): | |||
|
58 | assert f.endswith('.py') | |||
|
59 | name = f.replace('/', '.')[:-3] | |||
|
60 | try: | |||
|
61 | importlib.import_module(name) | |||
|
62 | except Exception as e: | |||
|
63 | exc_type, exc_value, tb = sys.exc_info() | |||
|
64 | # We walk the stack and ignore frames from our custom importer, | |||
|
65 | # import mechanisms, and stdlib modules. This kinda/sorta | |||
|
66 | # emulates CPython behavior in import.c while also attempting | |||
|
67 | # to pin blame on a Mercurial file. | |||
|
68 | for frame in reversed(traceback.extract_tb(tb)): | |||
|
69 | if frame.name == '_call_with_frames_removed': | |||
|
70 | continue | |||
|
71 | if 'importlib' in frame.filename: | |||
|
72 | continue | |||
|
73 | if 'mercurial/__init__.py' in frame.filename: | |||
|
74 | continue | |||
|
75 | if frame.filename.startswith(sys.prefix): | |||
|
76 | continue | |||
|
77 | break | |||
|
78 | ||||
|
79 | if frame.filename: | |||
|
80 | filename = os.path.basename(frame.filename) | |||
|
81 | print('%s: error importing: <%s> %s (error at %s:%d)' % ( | |||
|
82 | f, type(e).__name__, e, filename, frame.lineno)) | |||
|
83 | else: | |||
|
84 | print('%s: error importing module: <%s> %s (line %d)' % ( | |||
|
85 | f, type(e).__name__, e, frame.lineno)) | |||
|
86 | ||||
|
87 | if __name__ == '__main__': | |||
|
88 | if sys.version_info[0] == 2: | |||
|
89 | fn = check_compat_py2 | |||
|
90 | else: | |||
|
91 | fn = check_compat_py3 | |||
|
92 | ||||
|
93 | for f in sys.argv[1:]: | |||
|
94 | fn(f) | |||
|
95 | ||||
|
96 | sys.exit(0) |
@@ -0,0 +1,40 b'' | |||||
|
1 | TARGET = chg | |||
|
2 | SRCS = chg.c hgclient.c procutil.c util.c | |||
|
3 | OBJS = $(SRCS:.c=.o) | |||
|
4 | ||||
|
5 | CFLAGS ?= -O2 -Wall -Wextra -pedantic -g | |||
|
6 | CPPFLAGS ?= -D_FORTIFY_SOURCE=2 -D_GNU_SOURCE | |||
|
7 | override CFLAGS += -std=gnu99 | |||
|
8 | ifdef HGPATH | |||
|
9 | override CPPFLAGS += -DHGPATH=\"$(HGPATH)\" | |||
|
10 | endif | |||
|
11 | ||||
|
12 | DESTDIR = | |||
|
13 | PREFIX = /usr/local | |||
|
14 | MANDIR = $(PREFIX)/share/man/man1 | |||
|
15 | ||||
|
16 | .PHONY: all | |||
|
17 | all: $(TARGET) | |||
|
18 | ||||
|
19 | $(TARGET): $(OBJS) | |||
|
20 | $(CC) $(LDFLAGS) -o $@ $(OBJS) | |||
|
21 | ||||
|
22 | chg.o: hgclient.h procutil.h util.h | |||
|
23 | hgclient.o: hgclient.h procutil.h util.h | |||
|
24 | procutil.o: procutil.h util.h | |||
|
25 | util.o: util.h | |||
|
26 | ||||
|
27 | .PHONY: install | |||
|
28 | install: $(TARGET) | |||
|
29 | install -d "$(DESTDIR)$(PREFIX)"/bin | |||
|
30 | install -m 755 "$(TARGET)" "$(DESTDIR)$(PREFIX)"/bin | |||
|
31 | install -d "$(DESTDIR)$(MANDIR)" | |||
|
32 | install -m 644 chg.1 "$(DESTDIR)$(MANDIR)" | |||
|
33 | ||||
|
34 | .PHONY: clean | |||
|
35 | clean: | |||
|
36 | $(RM) $(OBJS) | |||
|
37 | ||||
|
38 | .PHONY: distclean | |||
|
39 | distclean: | |||
|
40 | $(RM) $(OBJS) $(TARGET) |
@@ -0,0 +1,32 b'' | |||||
|
1 | cHg | |||
|
2 | === | |||
|
3 | ||||
|
4 | A fast client for Mercurial command server running on Unix. | |||
|
5 | ||||
|
6 | Install: | |||
|
7 | ||||
|
8 | $ make | |||
|
9 | $ make install | |||
|
10 | ||||
|
11 | Usage: | |||
|
12 | ||||
|
13 | $ chg help # show help of Mercurial | |||
|
14 | $ alias hg=chg # replace hg command | |||
|
15 | $ chg --kill-chg-daemon # terminate background server | |||
|
16 | ||||
|
17 | Environment variables: | |||
|
18 | ||||
|
19 | Although cHg tries to update environment variables, some of them cannot be | |||
|
20 | changed after spawning the server. The following variables are specially | |||
|
21 | handled: | |||
|
22 | ||||
|
23 | * configuration files are reloaded automatically by default. | |||
|
24 | * CHGHG or HG specifies the path to the hg executable spawned as the | |||
|
25 | background command server. | |||
|
26 | ||||
|
27 | The following variables are available for testing: | |||
|
28 | ||||
|
29 | * CHGDEBUG enables debug messages. | |||
|
30 | * CHGSOCKNAME specifies the socket path of the background cmdserver. | |||
|
31 | * CHGTIMEOUT specifies how many seconds chg will wait before giving up | |||
|
32 | connecting to a cmdserver. If it is 0, chg will wait forever. Default: 60 |
@@ -0,0 +1,41 b'' | |||||
|
1 | .\" Hey, EMACS: -*- nroff -*- | |||
|
2 | .\" First parameter, NAME, should be all caps | |||
|
3 | .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection | |||
|
4 | .\" other parameters are allowed: see man(7), man(1) | |||
|
5 | .TH CHG 1 "March 3, 2013" | |||
|
6 | .\" Please adjust this date whenever revising the manpage. | |||
|
7 | .\" | |||
|
8 | .\" Some roff macros, for reference: | |||
|
9 | .\" .nh disable hyphenation | |||
|
10 | .\" .hy enable hyphenation | |||
|
11 | .\" .ad l left justify | |||
|
12 | .\" .ad b justify to both left and right margins | |||
|
13 | .\" .nf disable filling | |||
|
14 | .\" .fi enable filling | |||
|
15 | .\" .br insert line break | |||
|
16 | .\" .sp <n> insert n+1 empty lines | |||
|
17 | .\" for manpage-specific macros, see man(7) | |||
|
18 | .SH NAME | |||
|
19 | chg \- a fast client for Mercurial command server | |||
|
20 | .SH SYNOPSIS | |||
|
21 | .B chg | |||
|
22 | .IR command " [" options "] [" arguments "]..." | |||
|
23 | .br | |||
|
24 | .SH DESCRIPTION | |||
|
25 | The | |||
|
26 | .B chg | |||
|
27 | command is the wrapper for | |||
|
28 | .B hg | |||
|
29 | command. | |||
|
30 | It uses the Mercurial command server to reduce start-up overhead. | |||
|
31 | .SH OPTIONS | |||
|
32 | This program accepts the same command line syntax as the | |||
|
33 | .B hg | |||
|
34 | command. Additionally it accepts the following options. | |||
|
35 | .TP | |||
|
36 | .B \-\-kill\-chg\-daemon | |||
|
37 | Terminate the background command servers. | |||
|
38 | .SH SEE ALSO | |||
|
39 | .BR hg (1), | |||
|
40 | .SH AUTHOR | |||
|
41 | Written by Yuya Nishihara <yuya@tcha.org>. |
@@ -0,0 +1,456 b'' | |||||
|
1 | /* | |||
|
2 | * A fast client for Mercurial command server | |||
|
3 | * | |||
|
4 | * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org> | |||
|
5 | * | |||
|
6 | * This software may be used and distributed according to the terms of the | |||
|
7 | * GNU General Public License version 2 or any later version. | |||
|
8 | */ | |||
|
9 | ||||
|
10 | #include <assert.h> | |||
|
11 | #include <errno.h> | |||
|
12 | #include <fcntl.h> | |||
|
13 | #include <signal.h> | |||
|
14 | #include <stdio.h> | |||
|
15 | #include <stdlib.h> | |||
|
16 | #include <string.h> | |||
|
17 | #include <sys/file.h> | |||
|
18 | #include <sys/stat.h> | |||
|
19 | #include <sys/types.h> | |||
|
20 | #include <sys/un.h> | |||
|
21 | #include <sys/wait.h> | |||
|
22 | #include <time.h> | |||
|
23 | #include <unistd.h> | |||
|
24 | ||||
|
25 | #include "hgclient.h" | |||
|
26 | #include "procutil.h" | |||
|
27 | #include "util.h" | |||
|
28 | ||||
|
29 | #ifndef PATH_MAX | |||
|
30 | #define PATH_MAX 4096 | |||
|
31 | #endif | |||
|
32 | ||||
|
33 | struct cmdserveropts { | |||
|
34 | char sockname[PATH_MAX]; | |||
|
35 | char initsockname[PATH_MAX]; | |||
|
36 | char redirectsockname[PATH_MAX]; | |||
|
37 | size_t argsize; | |||
|
38 | const char **args; | |||
|
39 | }; | |||
|
40 | ||||
|
41 | static void initcmdserveropts(struct cmdserveropts *opts) | |||
|
42 | { | |||
|
43 | memset(opts, 0, sizeof(struct cmdserveropts)); | |||
|
44 | } | |||
|
45 | ||||
|
46 | static void freecmdserveropts(struct cmdserveropts *opts) | |||
|
47 | { | |||
|
48 | free(opts->args); | |||
|
49 | opts->args = NULL; | |||
|
50 | opts->argsize = 0; | |||
|
51 | } | |||
|
52 | ||||
|
53 | /* | |||
|
54 | * Test if an argument is a sensitive flag that should be passed to the server. | |||
|
55 | * Return 0 if not, otherwise the number of arguments starting from the current | |||
|
56 | * one that should be passed to the server. | |||
|
57 | */ | |||
|
58 | static size_t testsensitiveflag(const char *arg) | |||
|
59 | { | |||
|
60 | static const struct { | |||
|
61 | const char *name; | |||
|
62 | size_t narg; | |||
|
63 | } flags[] = { | |||
|
64 | {"--config", 1}, {"--cwd", 1}, {"--repo", 1}, | |||
|
65 | {"--repository", 1}, {"--traceback", 0}, {"-R", 1}, | |||
|
66 | }; | |||
|
67 | size_t i; | |||
|
68 | for (i = 0; i < sizeof(flags) / sizeof(flags[0]); ++i) { | |||
|
69 | size_t len = strlen(flags[i].name); | |||
|
70 | size_t narg = flags[i].narg; | |||
|
71 | if (memcmp(arg, flags[i].name, len) == 0) { | |||
|
72 | if (arg[len] == '\0') { | |||
|
73 | /* --flag (value) */ | |||
|
74 | return narg + 1; | |||
|
75 | } else if (arg[len] == '=' && narg > 0) { | |||
|
76 | /* --flag=value */ | |||
|
77 | return 1; | |||
|
78 | } else if (flags[i].name[1] != '-') { | |||
|
79 | /* short flag */ | |||
|
80 | return 1; | |||
|
81 | } | |||
|
82 | } | |||
|
83 | } | |||
|
84 | return 0; | |||
|
85 | } | |||
|
86 | ||||
|
87 | /* | |||
|
88 | * Parse argv[] and put sensitive flags to opts->args | |||
|
89 | */ | |||
|
90 | static void setcmdserverargs(struct cmdserveropts *opts, int argc, | |||
|
91 | const char *argv[]) | |||
|
92 | { | |||
|
93 | size_t i, step; | |||
|
94 | opts->argsize = 0; | |||
|
95 | for (i = 0, step = 1; i < (size_t)argc; i += step, step = 1) { | |||
|
96 | if (!argv[i]) | |||
|
97 | continue; /* pass clang-analyse */ | |||
|
98 | if (strcmp(argv[i], "--") == 0) | |||
|
99 | break; | |||
|
100 | size_t n = testsensitiveflag(argv[i]); | |||
|
101 | if (n == 0 || i + n > (size_t)argc) | |||
|
102 | continue; | |||
|
103 | opts->args = | |||
|
104 | reallocx(opts->args, (n + opts->argsize) * sizeof(char *)); | |||
|
105 | memcpy(opts->args + opts->argsize, argv + i, | |||
|
106 | sizeof(char *) * n); | |||
|
107 | opts->argsize += n; | |||
|
108 | step = n; | |||
|
109 | } | |||
|
110 | } | |||
|
111 | ||||
|
112 | static void preparesockdir(const char *sockdir) | |||
|
113 | { | |||
|
114 | int r; | |||
|
115 | r = mkdir(sockdir, 0700); | |||
|
116 | if (r < 0 && errno != EEXIST) | |||
|
117 | abortmsgerrno("cannot create sockdir %s", sockdir); | |||
|
118 | ||||
|
119 | struct stat st; | |||
|
120 | r = lstat(sockdir, &st); | |||
|
121 | if (r < 0) | |||
|
122 | abortmsgerrno("cannot stat %s", sockdir); | |||
|
123 | if (!S_ISDIR(st.st_mode)) | |||
|
124 | abortmsg("cannot create sockdir %s (file exists)", sockdir); | |||
|
125 | if (st.st_uid != geteuid() || st.st_mode & 0077) | |||
|
126 | abortmsg("insecure sockdir %s", sockdir); | |||
|
127 | } | |||
|
128 | ||||
|
129 | /* | |||
|
130 | * Check if a socket directory exists and is only owned by the current user. | |||
|
131 | * Return 1 if so, 0 if not. This is used to check if XDG_RUNTIME_DIR can be | |||
|
132 | * used or not. According to the specification [1], XDG_RUNTIME_DIR should be | |||
|
133 | * ignored if the directory is not owned by the user with mode 0700. | |||
|
134 | * [1]: https://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html | |||
|
135 | */ | |||
|
136 | static int checkruntimedir(const char *sockdir) | |||
|
137 | { | |||
|
138 | struct stat st; | |||
|
139 | int r = lstat(sockdir, &st); | |||
|
140 | if (r < 0) /* ex. does not exist */ | |||
|
141 | return 0; | |||
|
142 | if (!S_ISDIR(st.st_mode)) /* ex. is a file, not a directory */ | |||
|
143 | return 0; | |||
|
144 | return st.st_uid == geteuid() && (st.st_mode & 0777) == 0700; | |||
|
145 | } | |||
|
146 | ||||
|
147 | static void getdefaultsockdir(char sockdir[], size_t size) | |||
|
148 | { | |||
|
149 | /* by default, put socket file in secure directory | |||
|
150 | * (${XDG_RUNTIME_DIR}/chg, or /${TMPDIR:-tmp}/chg$UID) | |||
|
151 | * (permission of socket file may be ignored on some Unices) */ | |||
|
152 | const char *runtimedir = getenv("XDG_RUNTIME_DIR"); | |||
|
153 | int r; | |||
|
154 | if (runtimedir && checkruntimedir(runtimedir)) { | |||
|
155 | r = snprintf(sockdir, size, "%s/chg", runtimedir); | |||
|
156 | } else { | |||
|
157 | const char *tmpdir = getenv("TMPDIR"); | |||
|
158 | if (!tmpdir) | |||
|
159 | tmpdir = "/tmp"; | |||
|
160 | r = snprintf(sockdir, size, "%s/chg%d", tmpdir, geteuid()); | |||
|
161 | } | |||
|
162 | if (r < 0 || (size_t)r >= size) | |||
|
163 | abortmsg("too long TMPDIR (r = %d)", r); | |||
|
164 | } | |||
|
165 | ||||
|
166 | static void setcmdserveropts(struct cmdserveropts *opts) | |||
|
167 | { | |||
|
168 | int r; | |||
|
169 | char sockdir[PATH_MAX]; | |||
|
170 | const char *envsockname = getenv("CHGSOCKNAME"); | |||
|
171 | if (!envsockname) { | |||
|
172 | getdefaultsockdir(sockdir, sizeof(sockdir)); | |||
|
173 | preparesockdir(sockdir); | |||
|
174 | } | |||
|
175 | ||||
|
176 | const char *basename = (envsockname) ? envsockname : sockdir; | |||
|
177 | const char *sockfmt = (envsockname) ? "%s" : "%s/server"; | |||
|
178 | r = snprintf(opts->sockname, sizeof(opts->sockname), sockfmt, basename); | |||
|
179 | if (r < 0 || (size_t)r >= sizeof(opts->sockname)) | |||
|
180 | abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r); | |||
|
181 | r = snprintf(opts->initsockname, sizeof(opts->initsockname), "%s.%u", | |||
|
182 | opts->sockname, (unsigned)getpid()); | |||
|
183 | if (r < 0 || (size_t)r >= sizeof(opts->initsockname)) | |||
|
184 | abortmsg("too long TMPDIR or CHGSOCKNAME (r = %d)", r); | |||
|
185 | } | |||
|
186 | ||||
|
187 | static const char *gethgcmd(void) | |||
|
188 | { | |||
|
189 | static const char *hgcmd = NULL; | |||
|
190 | if (!hgcmd) { | |||
|
191 | hgcmd = getenv("CHGHG"); | |||
|
192 | if (!hgcmd || hgcmd[0] == '\0') | |||
|
193 | hgcmd = getenv("HG"); | |||
|
194 | if (!hgcmd || hgcmd[0] == '\0') | |||
|
195 | #ifdef HGPATH | |||
|
196 | hgcmd = (HGPATH); | |||
|
197 | #else | |||
|
198 | hgcmd = "hg"; | |||
|
199 | #endif | |||
|
200 | } | |||
|
201 | return hgcmd; | |||
|
202 | } | |||
|
203 | ||||
|
204 | static void execcmdserver(const struct cmdserveropts *opts) | |||
|
205 | { | |||
|
206 | const char *hgcmd = gethgcmd(); | |||
|
207 | ||||
|
208 | const char *baseargv[] = { | |||
|
209 | hgcmd, | |||
|
210 | "serve", | |||
|
211 | "--cmdserver", | |||
|
212 | "chgunix", | |||
|
213 | "--address", | |||
|
214 | opts->initsockname, | |||
|
215 | "--daemon-postexec", | |||
|
216 | "chdir:/", | |||
|
217 | }; | |||
|
218 | size_t baseargvsize = sizeof(baseargv) / sizeof(baseargv[0]); | |||
|
219 | size_t argsize = baseargvsize + opts->argsize + 1; | |||
|
220 | ||||
|
221 | const char **argv = mallocx(sizeof(char *) * argsize); | |||
|
222 | memcpy(argv, baseargv, sizeof(baseargv)); | |||
|
223 | if (opts->args) { | |||
|
224 | size_t size = sizeof(char *) * opts->argsize; | |||
|
225 | memcpy(argv + baseargvsize, opts->args, size); | |||
|
226 | } | |||
|
227 | argv[argsize - 1] = NULL; | |||
|
228 | ||||
|
229 | if (putenv("CHGINTERNALMARK=") != 0) | |||
|
230 | abortmsgerrno("failed to putenv"); | |||
|
231 | if (execvp(hgcmd, (char **)argv) < 0) | |||
|
232 | abortmsgerrno("failed to exec cmdserver"); | |||
|
233 | free(argv); | |||
|
234 | } | |||
|
235 | ||||
|
236 | /* Retry until we can connect to the server. Give up after some time. */ | |||
|
237 | static hgclient_t *retryconnectcmdserver(struct cmdserveropts *opts, pid_t pid) | |||
|
238 | { | |||
|
239 | static const struct timespec sleepreq = {0, 10 * 1000000}; | |||
|
240 | int pst = 0; | |||
|
241 | ||||
|
242 | debugmsg("try connect to %s repeatedly", opts->initsockname); | |||
|
243 | ||||
|
244 | unsigned int timeoutsec = 60; /* default: 60 seconds */ | |||
|
245 | const char *timeoutenv = getenv("CHGTIMEOUT"); | |||
|
246 | if (timeoutenv) | |||
|
247 | sscanf(timeoutenv, "%u", &timeoutsec); | |||
|
248 | ||||
|
249 | for (unsigned int i = 0; !timeoutsec || i < timeoutsec * 100; i++) { | |||
|
250 | hgclient_t *hgc = hgc_open(opts->initsockname); | |||
|
251 | if (hgc) { | |||
|
252 | debugmsg("rename %s to %s", opts->initsockname, | |||
|
253 | opts->sockname); | |||
|
254 | int r = rename(opts->initsockname, opts->sockname); | |||
|
255 | if (r != 0) | |||
|
256 | abortmsgerrno("cannot rename"); | |||
|
257 | return hgc; | |||
|
258 | } | |||
|
259 | ||||
|
260 | if (pid > 0) { | |||
|
261 | /* collect zombie if child process fails to start */ | |||
|
262 | int r = waitpid(pid, &pst, WNOHANG); | |||
|
263 | if (r != 0) | |||
|
264 | goto cleanup; | |||
|
265 | } | |||
|
266 | ||||
|
267 | nanosleep(&sleepreq, NULL); | |||
|
268 | } | |||
|
269 | ||||
|
270 | abortmsg("timed out waiting for cmdserver %s", opts->initsockname); | |||
|
271 | return NULL; | |||
|
272 | ||||
|
273 | cleanup: | |||
|
274 | if (WIFEXITED(pst)) { | |||
|
275 | if (WEXITSTATUS(pst) == 0) | |||
|
276 | abortmsg("could not connect to cmdserver " | |||
|
277 | "(exited with status 0)"); | |||
|
278 | debugmsg("cmdserver exited with status %d", WEXITSTATUS(pst)); | |||
|
279 | exit(WEXITSTATUS(pst)); | |||
|
280 | } else if (WIFSIGNALED(pst)) { | |||
|
281 | abortmsg("cmdserver killed by signal %d", WTERMSIG(pst)); | |||
|
282 | } else { | |||
|
283 | abortmsg("error while waiting for cmdserver"); | |||
|
284 | } | |||
|
285 | return NULL; | |||
|
286 | } | |||
|
287 | ||||
|
288 | /* Connect to a cmdserver. Will start a new server on demand. */ | |||
|
289 | static hgclient_t *connectcmdserver(struct cmdserveropts *opts) | |||
|
290 | { | |||
|
291 | const char *sockname = | |||
|
292 | opts->redirectsockname[0] ? opts->redirectsockname : opts->sockname; | |||
|
293 | debugmsg("try connect to %s", sockname); | |||
|
294 | hgclient_t *hgc = hgc_open(sockname); | |||
|
295 | if (hgc) | |||
|
296 | return hgc; | |||
|
297 | ||||
|
298 | /* prevent us from being connected to an outdated server: we were | |||
|
299 | * told by a server to redirect to opts->redirectsockname and that | |||
|
300 | * address does not work. we do not want to connect to the server | |||
|
301 | * again because it will probably tell us the same thing. */ | |||
|
302 | if (sockname == opts->redirectsockname) | |||
|
303 | unlink(opts->sockname); | |||
|
304 | ||||
|
305 | debugmsg("start cmdserver at %s", opts->initsockname); | |||
|
306 | ||||
|
307 | pid_t pid = fork(); | |||
|
308 | if (pid < 0) | |||
|
309 | abortmsg("failed to fork cmdserver process"); | |||
|
310 | if (pid == 0) { | |||
|
311 | execcmdserver(opts); | |||
|
312 | } else { | |||
|
313 | hgc = retryconnectcmdserver(opts, pid); | |||
|
314 | } | |||
|
315 | ||||
|
316 | return hgc; | |||
|
317 | } | |||
|
318 | ||||
|
319 | static void killcmdserver(const struct cmdserveropts *opts) | |||
|
320 | { | |||
|
321 | /* resolve config hash */ | |||
|
322 | char *resolvedpath = realpath(opts->sockname, NULL); | |||
|
323 | if (resolvedpath) { | |||
|
324 | unlink(resolvedpath); | |||
|
325 | free(resolvedpath); | |||
|
326 | } | |||
|
327 | } | |||
|
328 | ||||
|
329 | /* Run instructions sent from the server like unlink and set redirect path | |||
|
330 | * Return 1 if reconnect is needed, otherwise 0 */ | |||
|
331 | static int runinstructions(struct cmdserveropts *opts, const char **insts) | |||
|
332 | { | |||
|
333 | int needreconnect = 0; | |||
|
334 | if (!insts) | |||
|
335 | return needreconnect; | |||
|
336 | ||||
|
337 | assert(insts); | |||
|
338 | opts->redirectsockname[0] = '\0'; | |||
|
339 | const char **pinst; | |||
|
340 | for (pinst = insts; *pinst; pinst++) { | |||
|
341 | debugmsg("instruction: %s", *pinst); | |||
|
342 | if (strncmp(*pinst, "unlink ", 7) == 0) { | |||
|
343 | unlink(*pinst + 7); | |||
|
344 | } else if (strncmp(*pinst, "redirect ", 9) == 0) { | |||
|
345 | int r = snprintf(opts->redirectsockname, | |||
|
346 | sizeof(opts->redirectsockname), "%s", | |||
|
347 | *pinst + 9); | |||
|
348 | if (r < 0 || r >= (int)sizeof(opts->redirectsockname)) | |||
|
349 | abortmsg("redirect path is too long (%d)", r); | |||
|
350 | needreconnect = 1; | |||
|
351 | } else if (strncmp(*pinst, "exit ", 5) == 0) { | |||
|
352 | int n = 0; | |||
|
353 | if (sscanf(*pinst + 5, "%d", &n) != 1) | |||
|
354 | abortmsg("cannot read the exit code"); | |||
|
355 | exit(n); | |||
|
356 | } else if (strcmp(*pinst, "reconnect") == 0) { | |||
|
357 | needreconnect = 1; | |||
|
358 | } else { | |||
|
359 | abortmsg("unknown instruction: %s", *pinst); | |||
|
360 | } | |||
|
361 | } | |||
|
362 | return needreconnect; | |||
|
363 | } | |||
|
364 | ||||
|
365 | /* | |||
|
366 | * Test whether the command is unsupported or not. This is not designed to | |||
|
367 | * cover all cases. But it's fast, does not depend on the server and does | |||
|
368 | * not return false positives. | |||
|
369 | */ | |||
|
370 | static int isunsupported(int argc, const char *argv[]) | |||
|
371 | { | |||
|
372 | enum { SERVE = 1, | |||
|
373 | DAEMON = 2, | |||
|
374 | SERVEDAEMON = SERVE | DAEMON, | |||
|
375 | }; | |||
|
376 | unsigned int state = 0; | |||
|
377 | int i; | |||
|
378 | for (i = 0; i < argc; ++i) { | |||
|
379 | if (strcmp(argv[i], "--") == 0) | |||
|
380 | break; | |||
|
381 | if (i == 0 && strcmp("serve", argv[i]) == 0) | |||
|
382 | state |= SERVE; | |||
|
383 | else if (strcmp("-d", argv[i]) == 0 || | |||
|
384 | strcmp("--daemon", argv[i]) == 0) | |||
|
385 | state |= DAEMON; | |||
|
386 | } | |||
|
387 | return (state & SERVEDAEMON) == SERVEDAEMON; | |||
|
388 | } | |||
|
389 | ||||
|
390 | static void execoriginalhg(const char *argv[]) | |||
|
391 | { | |||
|
392 | debugmsg("execute original hg"); | |||
|
393 | if (execvp(gethgcmd(), (char **)argv) < 0) | |||
|
394 | abortmsgerrno("failed to exec original hg"); | |||
|
395 | } | |||
|
396 | ||||
|
397 | int main(int argc, const char *argv[], const char *envp[]) | |||
|
398 | { | |||
|
399 | if (getenv("CHGDEBUG")) | |||
|
400 | enabledebugmsg(); | |||
|
401 | ||||
|
402 | if (!getenv("HGPLAIN") && isatty(fileno(stderr))) | |||
|
403 | enablecolor(); | |||
|
404 | ||||
|
405 | if (getenv("CHGINTERNALMARK")) | |||
|
406 | abortmsg("chg started by chg detected.\n" | |||
|
407 | "Please make sure ${HG:-hg} is not a symlink or " | |||
|
408 | "wrapper to chg. Alternatively, set $CHGHG to the " | |||
|
409 | "path of real hg."); | |||
|
410 | ||||
|
411 | if (isunsupported(argc - 1, argv + 1)) | |||
|
412 | execoriginalhg(argv); | |||
|
413 | ||||
|
414 | struct cmdserveropts opts; | |||
|
415 | initcmdserveropts(&opts); | |||
|
416 | setcmdserveropts(&opts); | |||
|
417 | setcmdserverargs(&opts, argc, argv); | |||
|
418 | ||||
|
419 | if (argc == 2) { | |||
|
420 | if (strcmp(argv[1], "--kill-chg-daemon") == 0) { | |||
|
421 | killcmdserver(&opts); | |||
|
422 | return 0; | |||
|
423 | } | |||
|
424 | } | |||
|
425 | ||||
|
426 | hgclient_t *hgc; | |||
|
427 | size_t retry = 0; | |||
|
428 | while (1) { | |||
|
429 | hgc = connectcmdserver(&opts); | |||
|
430 | if (!hgc) | |||
|
431 | abortmsg("cannot open hg client"); | |||
|
432 | hgc_setenv(hgc, envp); | |||
|
433 | const char **insts = hgc_validate(hgc, argv + 1, argc - 1); | |||
|
434 | int needreconnect = runinstructions(&opts, insts); | |||
|
435 | free(insts); | |||
|
436 | if (!needreconnect) | |||
|
437 | break; | |||
|
438 | hgc_close(hgc); | |||
|
439 | if (++retry > 10) | |||
|
440 | abortmsg("too many redirections.\n" | |||
|
441 | "Please make sure %s is not a wrapper which " | |||
|
442 | "changes sensitive environment variables " | |||
|
443 | "before executing hg. If you have to use a " | |||
|
444 | "wrapper, wrap chg instead of hg.", | |||
|
445 | gethgcmd()); | |||
|
446 | } | |||
|
447 | ||||
|
448 | setupsignalhandler(hgc_peerpid(hgc), hgc_peerpgid(hgc)); | |||
|
449 | atexit(waitpager); | |||
|
450 | int exitcode = hgc_runcommand(hgc, argv + 1, argc - 1); | |||
|
451 | restoresignalhandler(); | |||
|
452 | hgc_close(hgc); | |||
|
453 | freecmdserveropts(&opts); | |||
|
454 | ||||
|
455 | return exitcode; | |||
|
456 | } |
This diff has been collapsed as it changes many lines, (619 lines changed) Show them Hide them | |||||
@@ -0,0 +1,619 b'' | |||||
|
1 | /* | |||
|
2 | * A command server client that uses Unix domain socket | |||
|
3 | * | |||
|
4 | * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org> | |||
|
5 | * | |||
|
6 | * This software may be used and distributed according to the terms of the | |||
|
7 | * GNU General Public License version 2 or any later version. | |||
|
8 | */ | |||
|
9 | ||||
|
10 | #include <arpa/inet.h> /* for ntohl(), htonl() */ | |||
|
11 | #include <assert.h> | |||
|
12 | #include <ctype.h> | |||
|
13 | #include <errno.h> | |||
|
14 | #include <fcntl.h> | |||
|
15 | #include <signal.h> | |||
|
16 | #include <stdint.h> | |||
|
17 | #include <stdio.h> | |||
|
18 | #include <stdlib.h> | |||
|
19 | #include <string.h> | |||
|
20 | #include <sys/socket.h> | |||
|
21 | #include <sys/stat.h> | |||
|
22 | #include <sys/un.h> | |||
|
23 | #include <unistd.h> | |||
|
24 | ||||
|
25 | #include "hgclient.h" | |||
|
26 | #include "procutil.h" | |||
|
27 | #include "util.h" | |||
|
28 | ||||
|
29 | enum { CAP_GETENCODING = 0x0001, | |||
|
30 | CAP_RUNCOMMAND = 0x0002, | |||
|
31 | /* cHg extension: */ | |||
|
32 | CAP_ATTACHIO = 0x0100, | |||
|
33 | CAP_CHDIR = 0x0200, | |||
|
34 | CAP_SETENV = 0x0800, | |||
|
35 | CAP_SETUMASK = 0x1000, | |||
|
36 | CAP_VALIDATE = 0x2000, | |||
|
37 | CAP_SETPROCNAME = 0x4000, | |||
|
38 | }; | |||
|
39 | ||||
|
40 | typedef struct { | |||
|
41 | const char *name; | |||
|
42 | unsigned int flag; | |||
|
43 | } cappair_t; | |||
|
44 | ||||
|
45 | static const cappair_t captable[] = { | |||
|
46 | {"getencoding", CAP_GETENCODING}, | |||
|
47 | {"runcommand", CAP_RUNCOMMAND}, | |||
|
48 | {"attachio", CAP_ATTACHIO}, | |||
|
49 | {"chdir", CAP_CHDIR}, | |||
|
50 | {"setenv", CAP_SETENV}, | |||
|
51 | {"setumask", CAP_SETUMASK}, | |||
|
52 | {"validate", CAP_VALIDATE}, | |||
|
53 | {"setprocname", CAP_SETPROCNAME}, | |||
|
54 | {NULL, 0}, /* terminator */ | |||
|
55 | }; | |||
|
56 | ||||
|
57 | typedef struct { | |||
|
58 | char ch; | |||
|
59 | char *data; | |||
|
60 | size_t maxdatasize; | |||
|
61 | size_t datasize; | |||
|
62 | } context_t; | |||
|
63 | ||||
|
64 | struct hgclient_tag_ { | |||
|
65 | int sockfd; | |||
|
66 | pid_t pgid; | |||
|
67 | pid_t pid; | |||
|
68 | context_t ctx; | |||
|
69 | unsigned int capflags; | |||
|
70 | }; | |||
|
71 | ||||
|
72 | static const size_t defaultdatasize = 4096; | |||
|
73 | ||||
|
74 | static void attachio(hgclient_t *hgc); | |||
|
75 | ||||
|
76 | static void initcontext(context_t *ctx) | |||
|
77 | { | |||
|
78 | ctx->ch = '\0'; | |||
|
79 | ctx->data = malloc(defaultdatasize); | |||
|
80 | ctx->maxdatasize = (ctx->data) ? defaultdatasize : 0; | |||
|
81 | ctx->datasize = 0; | |||
|
82 | debugmsg("initialize context buffer with size %zu", ctx->maxdatasize); | |||
|
83 | } | |||
|
84 | ||||
|
85 | static void enlargecontext(context_t *ctx, size_t newsize) | |||
|
86 | { | |||
|
87 | if (newsize <= ctx->maxdatasize) | |||
|
88 | return; | |||
|
89 | ||||
|
90 | newsize = defaultdatasize * | |||
|
91 | ((newsize + defaultdatasize - 1) / defaultdatasize); | |||
|
92 | ctx->data = reallocx(ctx->data, newsize); | |||
|
93 | ctx->maxdatasize = newsize; | |||
|
94 | debugmsg("enlarge context buffer to %zu", ctx->maxdatasize); | |||
|
95 | } | |||
|
96 | ||||
|
97 | static void freecontext(context_t *ctx) | |||
|
98 | { | |||
|
99 | debugmsg("free context buffer"); | |||
|
100 | free(ctx->data); | |||
|
101 | ctx->data = NULL; | |||
|
102 | ctx->maxdatasize = 0; | |||
|
103 | ctx->datasize = 0; | |||
|
104 | } | |||
|
105 | ||||
|
106 | /* Read channeled response from cmdserver */ | |||
|
107 | static void readchannel(hgclient_t *hgc) | |||
|
108 | { | |||
|
109 | assert(hgc); | |||
|
110 | ||||
|
111 | ssize_t rsize = recv(hgc->sockfd, &hgc->ctx.ch, sizeof(hgc->ctx.ch), 0); | |||
|
112 | if (rsize != sizeof(hgc->ctx.ch)) { | |||
|
113 | /* server would have exception and traceback would be printed */ | |||
|
114 | debugmsg("failed to read channel"); | |||
|
115 | exit(255); | |||
|
116 | } | |||
|
117 | ||||
|
118 | uint32_t datasize_n; | |||
|
119 | rsize = recv(hgc->sockfd, &datasize_n, sizeof(datasize_n), 0); | |||
|
120 | if (rsize != sizeof(datasize_n)) | |||
|
121 | abortmsg("failed to read data size"); | |||
|
122 | ||||
|
123 | /* datasize denotes the maximum size to write if input request */ | |||
|
124 | hgc->ctx.datasize = ntohl(datasize_n); | |||
|
125 | enlargecontext(&hgc->ctx, hgc->ctx.datasize); | |||
|
126 | ||||
|
127 | if (isupper(hgc->ctx.ch) && hgc->ctx.ch != 'S') | |||
|
128 | return; /* assumes input request */ | |||
|
129 | ||||
|
130 | size_t cursize = 0; | |||
|
131 | while (cursize < hgc->ctx.datasize) { | |||
|
132 | rsize = recv(hgc->sockfd, hgc->ctx.data + cursize, | |||
|
133 | hgc->ctx.datasize - cursize, 0); | |||
|
134 | if (rsize < 1) | |||
|
135 | abortmsg("failed to read data block"); | |||
|
136 | cursize += rsize; | |||
|
137 | } | |||
|
138 | } | |||
|
139 | ||||
|
140 | static void sendall(int sockfd, const void *data, size_t datasize) | |||
|
141 | { | |||
|
142 | const char *p = data; | |||
|
143 | const char *const endp = p + datasize; | |||
|
144 | while (p < endp) { | |||
|
145 | ssize_t r = send(sockfd, p, endp - p, 0); | |||
|
146 | if (r < 0) | |||
|
147 | abortmsgerrno("cannot communicate"); | |||
|
148 | p += r; | |||
|
149 | } | |||
|
150 | } | |||
|
151 | ||||
|
152 | /* Write lengh-data block to cmdserver */ | |||
|
153 | static void writeblock(const hgclient_t *hgc) | |||
|
154 | { | |||
|
155 | assert(hgc); | |||
|
156 | ||||
|
157 | const uint32_t datasize_n = htonl(hgc->ctx.datasize); | |||
|
158 | sendall(hgc->sockfd, &datasize_n, sizeof(datasize_n)); | |||
|
159 | ||||
|
160 | sendall(hgc->sockfd, hgc->ctx.data, hgc->ctx.datasize); | |||
|
161 | } | |||
|
162 | ||||
|
163 | static void writeblockrequest(const hgclient_t *hgc, const char *chcmd) | |||
|
164 | { | |||
|
165 | debugmsg("request %s, block size %zu", chcmd, hgc->ctx.datasize); | |||
|
166 | ||||
|
167 | char buf[strlen(chcmd) + 1]; | |||
|
168 | memcpy(buf, chcmd, sizeof(buf) - 1); | |||
|
169 | buf[sizeof(buf) - 1] = '\n'; | |||
|
170 | sendall(hgc->sockfd, buf, sizeof(buf)); | |||
|
171 | ||||
|
172 | writeblock(hgc); | |||
|
173 | } | |||
|
174 | ||||
|
175 | /* Build '\0'-separated list of args. argsize < 0 denotes that args are | |||
|
176 | * terminated by NULL. */ | |||
|
177 | static void packcmdargs(context_t *ctx, const char *const args[], | |||
|
178 | ssize_t argsize) | |||
|
179 | { | |||
|
180 | ctx->datasize = 0; | |||
|
181 | const char *const *const end = (argsize >= 0) ? args + argsize : NULL; | |||
|
182 | for (const char *const *it = args; it != end && *it; ++it) { | |||
|
183 | const size_t n = strlen(*it) + 1; /* include '\0' */ | |||
|
184 | enlargecontext(ctx, ctx->datasize + n); | |||
|
185 | memcpy(ctx->data + ctx->datasize, *it, n); | |||
|
186 | ctx->datasize += n; | |||
|
187 | } | |||
|
188 | ||||
|
189 | if (ctx->datasize > 0) | |||
|
190 | --ctx->datasize; /* strip last '\0' */ | |||
|
191 | } | |||
|
192 | ||||
|
193 | /* Extract '\0'-separated list of args to new buffer, terminated by NULL */ | |||
|
194 | static const char **unpackcmdargsnul(const context_t *ctx) | |||
|
195 | { | |||
|
196 | const char **args = NULL; | |||
|
197 | size_t nargs = 0, maxnargs = 0; | |||
|
198 | const char *s = ctx->data; | |||
|
199 | const char *e = ctx->data + ctx->datasize; | |||
|
200 | for (;;) { | |||
|
201 | if (nargs + 1 >= maxnargs) { /* including last NULL */ | |||
|
202 | maxnargs += 256; | |||
|
203 | args = reallocx(args, maxnargs * sizeof(args[0])); | |||
|
204 | } | |||
|
205 | args[nargs] = s; | |||
|
206 | nargs++; | |||
|
207 | s = memchr(s, '\0', e - s); | |||
|
208 | if (!s) | |||
|
209 | break; | |||
|
210 | s++; | |||
|
211 | } | |||
|
212 | args[nargs] = NULL; | |||
|
213 | return args; | |||
|
214 | } | |||
|
215 | ||||
|
216 | static void handlereadrequest(hgclient_t *hgc) | |||
|
217 | { | |||
|
218 | context_t *ctx = &hgc->ctx; | |||
|
219 | size_t r = fread(ctx->data, sizeof(ctx->data[0]), ctx->datasize, stdin); | |||
|
220 | ctx->datasize = r; | |||
|
221 | writeblock(hgc); | |||
|
222 | } | |||
|
223 | ||||
|
224 | /* Read single-line */ | |||
|
225 | static void handlereadlinerequest(hgclient_t *hgc) | |||
|
226 | { | |||
|
227 | context_t *ctx = &hgc->ctx; | |||
|
228 | if (!fgets(ctx->data, ctx->datasize, stdin)) | |||
|
229 | ctx->data[0] = '\0'; | |||
|
230 | ctx->datasize = strlen(ctx->data); | |||
|
231 | writeblock(hgc); | |||
|
232 | } | |||
|
233 | ||||
|
234 | /* Execute the requested command and write exit code */ | |||
|
235 | static void handlesystemrequest(hgclient_t *hgc) | |||
|
236 | { | |||
|
237 | context_t *ctx = &hgc->ctx; | |||
|
238 | enlargecontext(ctx, ctx->datasize + 1); | |||
|
239 | ctx->data[ctx->datasize] = '\0'; /* terminate last string */ | |||
|
240 | ||||
|
241 | const char **args = unpackcmdargsnul(ctx); | |||
|
242 | if (!args[0] || !args[1] || !args[2]) | |||
|
243 | abortmsg("missing type or command or cwd in system request"); | |||
|
244 | if (strcmp(args[0], "system") == 0) { | |||
|
245 | debugmsg("run '%s' at '%s'", args[1], args[2]); | |||
|
246 | int32_t r = runshellcmd(args[1], args + 3, args[2]); | |||
|
247 | free(args); | |||
|
248 | ||||
|
249 | uint32_t r_n = htonl(r); | |||
|
250 | memcpy(ctx->data, &r_n, sizeof(r_n)); | |||
|
251 | ctx->datasize = sizeof(r_n); | |||
|
252 | writeblock(hgc); | |||
|
253 | } else if (strcmp(args[0], "pager") == 0) { | |||
|
254 | setuppager(args[1], args + 3); | |||
|
255 | if (hgc->capflags & CAP_ATTACHIO) | |||
|
256 | attachio(hgc); | |||
|
257 | /* unblock the server */ | |||
|
258 | static const char emptycmd[] = "\n"; | |||
|
259 | sendall(hgc->sockfd, emptycmd, sizeof(emptycmd) - 1); | |||
|
260 | } else { | |||
|
261 | abortmsg("unknown type in system request: %s", args[0]); | |||
|
262 | } | |||
|
263 | } | |||
|
264 | ||||
|
265 | /* Read response of command execution until receiving 'r'-esult */ | |||
|
266 | static void handleresponse(hgclient_t *hgc) | |||
|
267 | { | |||
|
268 | for (;;) { | |||
|
269 | readchannel(hgc); | |||
|
270 | context_t *ctx = &hgc->ctx; | |||
|
271 | debugmsg("response read from channel %c, size %zu", ctx->ch, | |||
|
272 | ctx->datasize); | |||
|
273 | switch (ctx->ch) { | |||
|
274 | case 'o': | |||
|
275 | fwrite(ctx->data, sizeof(ctx->data[0]), ctx->datasize, | |||
|
276 | stdout); | |||
|
277 | break; | |||
|
278 | case 'e': | |||
|
279 | fwrite(ctx->data, sizeof(ctx->data[0]), ctx->datasize, | |||
|
280 | stderr); | |||
|
281 | break; | |||
|
282 | case 'd': | |||
|
283 | /* assumes last char is '\n' */ | |||
|
284 | ctx->data[ctx->datasize - 1] = '\0'; | |||
|
285 | debugmsg("server: %s", ctx->data); | |||
|
286 | break; | |||
|
287 | case 'r': | |||
|
288 | return; | |||
|
289 | case 'I': | |||
|
290 | handlereadrequest(hgc); | |||
|
291 | break; | |||
|
292 | case 'L': | |||
|
293 | handlereadlinerequest(hgc); | |||
|
294 | break; | |||
|
295 | case 'S': | |||
|
296 | handlesystemrequest(hgc); | |||
|
297 | break; | |||
|
298 | default: | |||
|
299 | if (isupper(ctx->ch)) | |||
|
300 | abortmsg("cannot handle response (ch = %c)", | |||
|
301 | ctx->ch); | |||
|
302 | } | |||
|
303 | } | |||
|
304 | } | |||
|
305 | ||||
|
306 | static unsigned int parsecapabilities(const char *s, const char *e) | |||
|
307 | { | |||
|
308 | unsigned int flags = 0; | |||
|
309 | while (s < e) { | |||
|
310 | const char *t = strchr(s, ' '); | |||
|
311 | if (!t || t > e) | |||
|
312 | t = e; | |||
|
313 | const cappair_t *cap; | |||
|
314 | for (cap = captable; cap->flag; ++cap) { | |||
|
315 | size_t n = t - s; | |||
|
316 | if (strncmp(s, cap->name, n) == 0 && | |||
|
317 | strlen(cap->name) == n) { | |||
|
318 | flags |= cap->flag; | |||
|
319 | break; | |||
|
320 | } | |||
|
321 | } | |||
|
322 | s = t + 1; | |||
|
323 | } | |||
|
324 | return flags; | |||
|
325 | } | |||
|
326 | ||||
|
327 | static void readhello(hgclient_t *hgc) | |||
|
328 | { | |||
|
329 | readchannel(hgc); | |||
|
330 | context_t *ctx = &hgc->ctx; | |||
|
331 | if (ctx->ch != 'o') { | |||
|
332 | char ch = ctx->ch; | |||
|
333 | if (ch == 'e') { | |||
|
334 | /* write early error and will exit */ | |||
|
335 | fwrite(ctx->data, sizeof(ctx->data[0]), ctx->datasize, | |||
|
336 | stderr); | |||
|
337 | handleresponse(hgc); | |||
|
338 | } | |||
|
339 | abortmsg("unexpected channel of hello message (ch = %c)", ch); | |||
|
340 | } | |||
|
341 | enlargecontext(ctx, ctx->datasize + 1); | |||
|
342 | ctx->data[ctx->datasize] = '\0'; | |||
|
343 | debugmsg("hello received: %s (size = %zu)", ctx->data, ctx->datasize); | |||
|
344 | ||||
|
345 | const char *s = ctx->data; | |||
|
346 | const char *const dataend = ctx->data + ctx->datasize; | |||
|
347 | while (s < dataend) { | |||
|
348 | const char *t = strchr(s, ':'); | |||
|
349 | if (!t || t[1] != ' ') | |||
|
350 | break; | |||
|
351 | const char *u = strchr(t + 2, '\n'); | |||
|
352 | if (!u) | |||
|
353 | u = dataend; | |||
|
354 | if (strncmp(s, "capabilities:", t - s + 1) == 0) { | |||
|
355 | hgc->capflags = parsecapabilities(t + 2, u); | |||
|
356 | } else if (strncmp(s, "pgid:", t - s + 1) == 0) { | |||
|
357 | hgc->pgid = strtol(t + 2, NULL, 10); | |||
|
358 | } else if (strncmp(s, "pid:", t - s + 1) == 0) { | |||
|
359 | hgc->pid = strtol(t + 2, NULL, 10); | |||
|
360 | } | |||
|
361 | s = u + 1; | |||
|
362 | } | |||
|
363 | debugmsg("capflags=0x%04x, pid=%d", hgc->capflags, hgc->pid); | |||
|
364 | } | |||
|
365 | ||||
|
366 | static void updateprocname(hgclient_t *hgc) | |||
|
367 | { | |||
|
368 | int r = snprintf(hgc->ctx.data, hgc->ctx.maxdatasize, "chg[worker/%d]", | |||
|
369 | (int)getpid()); | |||
|
370 | if (r < 0 || (size_t)r >= hgc->ctx.maxdatasize) | |||
|
371 | abortmsg("insufficient buffer to write procname (r = %d)", r); | |||
|
372 | hgc->ctx.datasize = (size_t)r; | |||
|
373 | writeblockrequest(hgc, "setprocname"); | |||
|
374 | } | |||
|
375 | ||||
|
376 | static void attachio(hgclient_t *hgc) | |||
|
377 | { | |||
|
378 | debugmsg("request attachio"); | |||
|
379 | static const char chcmd[] = "attachio\n"; | |||
|
380 | sendall(hgc->sockfd, chcmd, sizeof(chcmd) - 1); | |||
|
381 | readchannel(hgc); | |||
|
382 | context_t *ctx = &hgc->ctx; | |||
|
383 | if (ctx->ch != 'I') | |||
|
384 | abortmsg("unexpected response for attachio (ch = %c)", ctx->ch); | |||
|
385 | ||||
|
386 | static const int fds[3] = {STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO}; | |||
|
387 | struct msghdr msgh; | |||
|
388 | memset(&msgh, 0, sizeof(msgh)); | |||
|
389 | struct iovec iov = {ctx->data, ctx->datasize}; /* dummy payload */ | |||
|
390 | msgh.msg_iov = &iov; | |||
|
391 | msgh.msg_iovlen = 1; | |||
|
392 | char fdbuf[CMSG_SPACE(sizeof(fds))]; | |||
|
393 | msgh.msg_control = fdbuf; | |||
|
394 | msgh.msg_controllen = sizeof(fdbuf); | |||
|
395 | struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msgh); | |||
|
396 | cmsg->cmsg_level = SOL_SOCKET; | |||
|
397 | cmsg->cmsg_type = SCM_RIGHTS; | |||
|
398 | cmsg->cmsg_len = CMSG_LEN(sizeof(fds)); | |||
|
399 | memcpy(CMSG_DATA(cmsg), fds, sizeof(fds)); | |||
|
400 | msgh.msg_controllen = cmsg->cmsg_len; | |||
|
401 | ssize_t r = sendmsg(hgc->sockfd, &msgh, 0); | |||
|
402 | if (r < 0) | |||
|
403 | abortmsgerrno("sendmsg failed"); | |||
|
404 | ||||
|
405 | handleresponse(hgc); | |||
|
406 | int32_t n; | |||
|
407 | if (ctx->datasize != sizeof(n)) | |||
|
408 | abortmsg("unexpected size of attachio result"); | |||
|
409 | memcpy(&n, ctx->data, sizeof(n)); | |||
|
410 | n = ntohl(n); | |||
|
411 | if (n != sizeof(fds) / sizeof(fds[0])) | |||
|
412 | abortmsg("failed to send fds (n = %d)", n); | |||
|
413 | } | |||
|
414 | ||||
|
415 | static void chdirtocwd(hgclient_t *hgc) | |||
|
416 | { | |||
|
417 | if (!getcwd(hgc->ctx.data, hgc->ctx.maxdatasize)) | |||
|
418 | abortmsgerrno("failed to getcwd"); | |||
|
419 | hgc->ctx.datasize = strlen(hgc->ctx.data); | |||
|
420 | writeblockrequest(hgc, "chdir"); | |||
|
421 | } | |||
|
422 | ||||
|
423 | static void forwardumask(hgclient_t *hgc) | |||
|
424 | { | |||
|
425 | mode_t mask = umask(0); | |||
|
426 | umask(mask); | |||
|
427 | ||||
|
428 | static const char command[] = "setumask\n"; | |||
|
429 | sendall(hgc->sockfd, command, sizeof(command) - 1); | |||
|
430 | uint32_t data = htonl(mask); | |||
|
431 | sendall(hgc->sockfd, &data, sizeof(data)); | |||
|
432 | } | |||
|
433 | ||||
|
434 | /*! | |||
|
435 | * Open connection to per-user cmdserver | |||
|
436 | * | |||
|
437 | * If no background server running, returns NULL. | |||
|
438 | */ | |||
|
439 | hgclient_t *hgc_open(const char *sockname) | |||
|
440 | { | |||
|
441 | int fd = socket(AF_UNIX, SOCK_STREAM, 0); | |||
|
442 | if (fd < 0) | |||
|
443 | abortmsgerrno("cannot create socket"); | |||
|
444 | ||||
|
445 | /* don't keep fd on fork(), so that it can be closed when the parent | |||
|
446 | * process get terminated. */ | |||
|
447 | fsetcloexec(fd); | |||
|
448 | ||||
|
449 | struct sockaddr_un addr; | |||
|
450 | addr.sun_family = AF_UNIX; | |||
|
451 | ||||
|
452 | /* use chdir to workaround small sizeof(sun_path) */ | |||
|
453 | int bakfd = -1; | |||
|
454 | const char *basename = sockname; | |||
|
455 | { | |||
|
456 | const char *split = strrchr(sockname, '/'); | |||
|
457 | if (split && split != sockname) { | |||
|
458 | if (split[1] == '\0') | |||
|
459 | abortmsg("sockname cannot end with a slash"); | |||
|
460 | size_t len = split - sockname; | |||
|
461 | char sockdir[len + 1]; | |||
|
462 | memcpy(sockdir, sockname, len); | |||
|
463 | sockdir[len] = '\0'; | |||
|
464 | ||||
|
465 | bakfd = open(".", O_DIRECTORY); | |||
|
466 | if (bakfd == -1) | |||
|
467 | abortmsgerrno("cannot open cwd"); | |||
|
468 | ||||
|
469 | int r = chdir(sockdir); | |||
|
470 | if (r != 0) | |||
|
471 | abortmsgerrno("cannot chdir %s", sockdir); | |||
|
472 | ||||
|
473 | basename = split + 1; | |||
|
474 | } | |||
|
475 | } | |||
|
476 | if (strlen(basename) >= sizeof(addr.sun_path)) | |||
|
477 | abortmsg("sockname is too long: %s", basename); | |||
|
478 | strncpy(addr.sun_path, basename, sizeof(addr.sun_path)); | |||
|
479 | addr.sun_path[sizeof(addr.sun_path) - 1] = '\0'; | |||
|
480 | ||||
|
481 | /* real connect */ | |||
|
482 | int r = connect(fd, (struct sockaddr *)&addr, sizeof(addr)); | |||
|
483 | if (r < 0) { | |||
|
484 | if (errno != ENOENT && errno != ECONNREFUSED) | |||
|
485 | abortmsgerrno("cannot connect to %s", sockname); | |||
|
486 | } | |||
|
487 | if (bakfd != -1) { | |||
|
488 | fchdirx(bakfd); | |||
|
489 | close(bakfd); | |||
|
490 | } | |||
|
491 | if (r < 0) { | |||
|
492 | close(fd); | |||
|
493 | return NULL; | |||
|
494 | } | |||
|
495 | debugmsg("connected to %s", addr.sun_path); | |||
|
496 | ||||
|
497 | hgclient_t *hgc = mallocx(sizeof(hgclient_t)); | |||
|
498 | memset(hgc, 0, sizeof(*hgc)); | |||
|
499 | hgc->sockfd = fd; | |||
|
500 | initcontext(&hgc->ctx); | |||
|
501 | ||||
|
502 | readhello(hgc); | |||
|
503 | if (!(hgc->capflags & CAP_RUNCOMMAND)) | |||
|
504 | abortmsg("insufficient capability: runcommand"); | |||
|
505 | if (hgc->capflags & CAP_SETPROCNAME) | |||
|
506 | updateprocname(hgc); | |||
|
507 | if (hgc->capflags & CAP_ATTACHIO) | |||
|
508 | attachio(hgc); | |||
|
509 | if (hgc->capflags & CAP_CHDIR) | |||
|
510 | chdirtocwd(hgc); | |||
|
511 | if (hgc->capflags & CAP_SETUMASK) | |||
|
512 | forwardumask(hgc); | |||
|
513 | ||||
|
514 | return hgc; | |||
|
515 | } | |||
|
516 | ||||
|
517 | /*! | |||
|
518 | * Close connection and free allocated memory | |||
|
519 | */ | |||
|
520 | void hgc_close(hgclient_t *hgc) | |||
|
521 | { | |||
|
522 | assert(hgc); | |||
|
523 | freecontext(&hgc->ctx); | |||
|
524 | close(hgc->sockfd); | |||
|
525 | free(hgc); | |||
|
526 | } | |||
|
527 | ||||
|
528 | pid_t hgc_peerpgid(const hgclient_t *hgc) | |||
|
529 | { | |||
|
530 | assert(hgc); | |||
|
531 | return hgc->pgid; | |||
|
532 | } | |||
|
533 | ||||
|
534 | pid_t hgc_peerpid(const hgclient_t *hgc) | |||
|
535 | { | |||
|
536 | assert(hgc); | |||
|
537 | return hgc->pid; | |||
|
538 | } | |||
|
539 | ||||
|
540 | /*! | |||
|
541 | * Send command line arguments to let the server load the repo config and check | |||
|
542 | * whether it can process our request directly or not. | |||
|
543 | * Make sure hgc_setenv is called before calling this. | |||
|
544 | * | |||
|
545 | * @return - NULL, the server believes it can handle our request, or does not | |||
|
546 | * support "validate" command. | |||
|
547 | * - a list of strings, the server probably cannot handle our request | |||
|
548 | * and it sent instructions telling us what to do next. See | |||
|
549 | * chgserver.py for possible instruction formats. | |||
|
550 | * the list should be freed by the caller. | |||
|
551 | * the last string is guaranteed to be NULL. | |||
|
552 | */ | |||
|
553 | const char **hgc_validate(hgclient_t *hgc, const char *const args[], | |||
|
554 | size_t argsize) | |||
|
555 | { | |||
|
556 | assert(hgc); | |||
|
557 | if (!(hgc->capflags & CAP_VALIDATE)) | |||
|
558 | return NULL; | |||
|
559 | ||||
|
560 | packcmdargs(&hgc->ctx, args, argsize); | |||
|
561 | writeblockrequest(hgc, "validate"); | |||
|
562 | handleresponse(hgc); | |||
|
563 | ||||
|
564 | /* the server returns '\0' if it can handle our request */ | |||
|
565 | if (hgc->ctx.datasize <= 1) | |||
|
566 | return NULL; | |||
|
567 | ||||
|
568 | /* make sure the buffer is '\0' terminated */ | |||
|
569 | enlargecontext(&hgc->ctx, hgc->ctx.datasize + 1); | |||
|
570 | hgc->ctx.data[hgc->ctx.datasize] = '\0'; | |||
|
571 | return unpackcmdargsnul(&hgc->ctx); | |||
|
572 | } | |||
|
573 | ||||
|
574 | /*! | |||
|
575 | * Execute the specified Mercurial command | |||
|
576 | * | |||
|
577 | * @return result code | |||
|
578 | */ | |||
|
579 | int hgc_runcommand(hgclient_t *hgc, const char *const args[], size_t argsize) | |||
|
580 | { | |||
|
581 | assert(hgc); | |||
|
582 | ||||
|
583 | packcmdargs(&hgc->ctx, args, argsize); | |||
|
584 | writeblockrequest(hgc, "runcommand"); | |||
|
585 | handleresponse(hgc); | |||
|
586 | ||||
|
587 | int32_t exitcode_n; | |||
|
588 | if (hgc->ctx.datasize != sizeof(exitcode_n)) { | |||
|
589 | abortmsg("unexpected size of exitcode"); | |||
|
590 | } | |||
|
591 | memcpy(&exitcode_n, hgc->ctx.data, sizeof(exitcode_n)); | |||
|
592 | return ntohl(exitcode_n); | |||
|
593 | } | |||
|
594 | ||||
|
595 | /*! | |||
|
596 | * (Re-)send client's stdio channels so that the server can access to tty | |||
|
597 | */ | |||
|
598 | void hgc_attachio(hgclient_t *hgc) | |||
|
599 | { | |||
|
600 | assert(hgc); | |||
|
601 | if (!(hgc->capflags & CAP_ATTACHIO)) | |||
|
602 | return; | |||
|
603 | attachio(hgc); | |||
|
604 | } | |||
|
605 | ||||
|
606 | /*! | |||
|
607 | * Update server's environment variables | |||
|
608 | * | |||
|
609 | * @param envp list of environment variables in "NAME=VALUE" format, | |||
|
610 | * terminated by NULL. | |||
|
611 | */ | |||
|
612 | void hgc_setenv(hgclient_t *hgc, const char *const envp[]) | |||
|
613 | { | |||
|
614 | assert(hgc && envp); | |||
|
615 | if (!(hgc->capflags & CAP_SETENV)) | |||
|
616 | return; | |||
|
617 | packcmdargs(&hgc->ctx, envp, /*argsize*/ -1); | |||
|
618 | writeblockrequest(hgc, "setenv"); | |||
|
619 | } |
@@ -0,0 +1,30 b'' | |||||
|
1 | /* | |||
|
2 | * A command server client that uses Unix domain socket | |||
|
3 | * | |||
|
4 | * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org> | |||
|
5 | * | |||
|
6 | * This software may be used and distributed according to the terms of the | |||
|
7 | * GNU General Public License version 2 or any later version. | |||
|
8 | */ | |||
|
9 | ||||
|
10 | #ifndef HGCLIENT_H_ | |||
|
11 | #define HGCLIENT_H_ | |||
|
12 | ||||
|
13 | #include <sys/types.h> | |||
|
14 | ||||
|
15 | struct hgclient_tag_; | |||
|
16 | typedef struct hgclient_tag_ hgclient_t; | |||
|
17 | ||||
|
18 | hgclient_t *hgc_open(const char *sockname); | |||
|
19 | void hgc_close(hgclient_t *hgc); | |||
|
20 | ||||
|
21 | pid_t hgc_peerpgid(const hgclient_t *hgc); | |||
|
22 | pid_t hgc_peerpid(const hgclient_t *hgc); | |||
|
23 | ||||
|
24 | const char **hgc_validate(hgclient_t *hgc, const char *const args[], | |||
|
25 | size_t argsize); | |||
|
26 | int hgc_runcommand(hgclient_t *hgc, const char *const args[], size_t argsize); | |||
|
27 | void hgc_attachio(hgclient_t *hgc); | |||
|
28 | void hgc_setenv(hgclient_t *hgc, const char *const envp[]); | |||
|
29 | ||||
|
30 | #endif /* HGCLIENT_H_ */ |
@@ -0,0 +1,237 b'' | |||||
|
1 | /* | |||
|
2 | * Utilities about process handling - signal and subprocess (ex. pager) | |||
|
3 | * | |||
|
4 | * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org> | |||
|
5 | * | |||
|
6 | * This software may be used and distributed according to the terms of the | |||
|
7 | * GNU General Public License version 2 or any later version. | |||
|
8 | */ | |||
|
9 | ||||
|
10 | #include <assert.h> | |||
|
11 | #include <errno.h> | |||
|
12 | #include <signal.h> | |||
|
13 | #include <stdio.h> | |||
|
14 | #include <string.h> | |||
|
15 | #include <sys/wait.h> | |||
|
16 | #include <unistd.h> | |||
|
17 | ||||
|
18 | #include "procutil.h" | |||
|
19 | #include "util.h" | |||
|
20 | ||||
|
21 | static pid_t pagerpid = 0; | |||
|
22 | static pid_t peerpgid = 0; | |||
|
23 | static pid_t peerpid = 0; | |||
|
24 | ||||
|
25 | static void forwardsignal(int sig) | |||
|
26 | { | |||
|
27 | assert(peerpid > 0); | |||
|
28 | if (kill(peerpid, sig) < 0) | |||
|
29 | abortmsgerrno("cannot kill %d", peerpid); | |||
|
30 | debugmsg("forward signal %d", sig); | |||
|
31 | } | |||
|
32 | ||||
|
33 | static void forwardsignaltogroup(int sig) | |||
|
34 | { | |||
|
35 | /* prefer kill(-pgid, sig), fallback to pid if pgid is invalid */ | |||
|
36 | pid_t killpid = peerpgid > 1 ? -peerpgid : peerpid; | |||
|
37 | if (kill(killpid, sig) < 0) | |||
|
38 | abortmsgerrno("cannot kill %d", killpid); | |||
|
39 | debugmsg("forward signal %d to %d", sig, killpid); | |||
|
40 | } | |||
|
41 | ||||
|
42 | static void handlestopsignal(int sig) | |||
|
43 | { | |||
|
44 | sigset_t unblockset, oldset; | |||
|
45 | struct sigaction sa, oldsa; | |||
|
46 | if (sigemptyset(&unblockset) < 0) | |||
|
47 | goto error; | |||
|
48 | if (sigaddset(&unblockset, sig) < 0) | |||
|
49 | goto error; | |||
|
50 | memset(&sa, 0, sizeof(sa)); | |||
|
51 | sa.sa_handler = SIG_DFL; | |||
|
52 | sa.sa_flags = SA_RESTART; | |||
|
53 | if (sigemptyset(&sa.sa_mask) < 0) | |||
|
54 | goto error; | |||
|
55 | ||||
|
56 | forwardsignal(sig); | |||
|
57 | if (raise(sig) < 0) /* resend to self */ | |||
|
58 | goto error; | |||
|
59 | if (sigaction(sig, &sa, &oldsa) < 0) | |||
|
60 | goto error; | |||
|
61 | if (sigprocmask(SIG_UNBLOCK, &unblockset, &oldset) < 0) | |||
|
62 | goto error; | |||
|
63 | /* resent signal will be handled before sigprocmask() returns */ | |||
|
64 | if (sigprocmask(SIG_SETMASK, &oldset, NULL) < 0) | |||
|
65 | goto error; | |||
|
66 | if (sigaction(sig, &oldsa, NULL) < 0) | |||
|
67 | goto error; | |||
|
68 | return; | |||
|
69 | ||||
|
70 | error: | |||
|
71 | abortmsgerrno("failed to handle stop signal"); | |||
|
72 | } | |||
|
73 | ||||
|
74 | static void handlechildsignal(int sig UNUSED_) | |||
|
75 | { | |||
|
76 | if (peerpid == 0 || pagerpid == 0) | |||
|
77 | return; | |||
|
78 | /* if pager exits, notify the server with SIGPIPE immediately. | |||
|
79 | * otherwise the server won't get SIGPIPE if it does not write | |||
|
80 | * anything. (issue5278) */ | |||
|
81 | if (waitpid(pagerpid, NULL, WNOHANG) == pagerpid) | |||
|
82 | kill(peerpid, SIGPIPE); | |||
|
83 | } | |||
|
84 | ||||
|
85 | void setupsignalhandler(pid_t pid, pid_t pgid) | |||
|
86 | { | |||
|
87 | if (pid <= 0) | |||
|
88 | return; | |||
|
89 | peerpid = pid; | |||
|
90 | peerpgid = (pgid <= 1 ? 0 : pgid); | |||
|
91 | ||||
|
92 | struct sigaction sa; | |||
|
93 | memset(&sa, 0, sizeof(sa)); | |||
|
94 | ||||
|
95 | /* deadly signals meant to be sent to a process group: | |||
|
96 | * - SIGHUP: usually generated by the kernel, when termination of a | |||
|
97 | * process causes that process group to become orphaned | |||
|
98 | * - SIGINT: usually generated by the terminal */ | |||
|
99 | sa.sa_handler = forwardsignaltogroup; | |||
|
100 | sa.sa_flags = SA_RESTART; | |||
|
101 | if (sigemptyset(&sa.sa_mask) < 0) | |||
|
102 | goto error; | |||
|
103 | if (sigaction(SIGHUP, &sa, NULL) < 0) | |||
|
104 | goto error; | |||
|
105 | if (sigaction(SIGINT, &sa, NULL) < 0) | |||
|
106 | goto error; | |||
|
107 | ||||
|
108 | /* terminate frontend by double SIGTERM in case of server freeze */ | |||
|
109 | sa.sa_handler = forwardsignal; | |||
|
110 | sa.sa_flags |= SA_RESETHAND; | |||
|
111 | if (sigaction(SIGTERM, &sa, NULL) < 0) | |||
|
112 | goto error; | |||
|
113 | ||||
|
114 | /* notify the worker about window resize events */ | |||
|
115 | sa.sa_flags = SA_RESTART; | |||
|
116 | if (sigaction(SIGWINCH, &sa, NULL) < 0) | |||
|
117 | goto error; | |||
|
118 | /* forward user-defined signals */ | |||
|
119 | if (sigaction(SIGUSR1, &sa, NULL) < 0) | |||
|
120 | goto error; | |||
|
121 | if (sigaction(SIGUSR2, &sa, NULL) < 0) | |||
|
122 | goto error; | |||
|
123 | /* propagate job control requests to worker */ | |||
|
124 | sa.sa_handler = forwardsignal; | |||
|
125 | sa.sa_flags = SA_RESTART; | |||
|
126 | if (sigaction(SIGCONT, &sa, NULL) < 0) | |||
|
127 | goto error; | |||
|
128 | sa.sa_handler = handlestopsignal; | |||
|
129 | sa.sa_flags = SA_RESTART; | |||
|
130 | if (sigaction(SIGTSTP, &sa, NULL) < 0) | |||
|
131 | goto error; | |||
|
132 | /* get notified when pager exits */ | |||
|
133 | sa.sa_handler = handlechildsignal; | |||
|
134 | sa.sa_flags = SA_RESTART; | |||
|
135 | if (sigaction(SIGCHLD, &sa, NULL) < 0) | |||
|
136 | goto error; | |||
|
137 | ||||
|
138 | return; | |||
|
139 | ||||
|
140 | error: | |||
|
141 | abortmsgerrno("failed to set up signal handlers"); | |||
|
142 | } | |||
|
143 | ||||
|
144 | void restoresignalhandler(void) | |||
|
145 | { | |||
|
146 | struct sigaction sa; | |||
|
147 | memset(&sa, 0, sizeof(sa)); | |||
|
148 | sa.sa_handler = SIG_DFL; | |||
|
149 | sa.sa_flags = SA_RESTART; | |||
|
150 | if (sigemptyset(&sa.sa_mask) < 0) | |||
|
151 | goto error; | |||
|
152 | ||||
|
153 | if (sigaction(SIGHUP, &sa, NULL) < 0) | |||
|
154 | goto error; | |||
|
155 | if (sigaction(SIGTERM, &sa, NULL) < 0) | |||
|
156 | goto error; | |||
|
157 | if (sigaction(SIGWINCH, &sa, NULL) < 0) | |||
|
158 | goto error; | |||
|
159 | if (sigaction(SIGCONT, &sa, NULL) < 0) | |||
|
160 | goto error; | |||
|
161 | if (sigaction(SIGTSTP, &sa, NULL) < 0) | |||
|
162 | goto error; | |||
|
163 | if (sigaction(SIGCHLD, &sa, NULL) < 0) | |||
|
164 | goto error; | |||
|
165 | ||||
|
166 | /* ignore Ctrl+C while shutting down to make pager exits cleanly */ | |||
|
167 | sa.sa_handler = SIG_IGN; | |||
|
168 | if (sigaction(SIGINT, &sa, NULL) < 0) | |||
|
169 | goto error; | |||
|
170 | ||||
|
171 | peerpid = 0; | |||
|
172 | return; | |||
|
173 | ||||
|
174 | error: | |||
|
175 | abortmsgerrno("failed to restore signal handlers"); | |||
|
176 | } | |||
|
177 | ||||
|
178 | /* This implementation is based on hgext/pager.py (post 369741ef7253) | |||
|
179 | * Return 0 if pager is not started, or pid of the pager */ | |||
|
180 | pid_t setuppager(const char *pagercmd, const char *envp[]) | |||
|
181 | { | |||
|
182 | assert(pagerpid == 0); | |||
|
183 | if (!pagercmd) | |||
|
184 | return 0; | |||
|
185 | ||||
|
186 | int pipefds[2]; | |||
|
187 | if (pipe(pipefds) < 0) | |||
|
188 | return 0; | |||
|
189 | pid_t pid = fork(); | |||
|
190 | if (pid < 0) | |||
|
191 | goto error; | |||
|
192 | if (pid > 0) { | |||
|
193 | close(pipefds[0]); | |||
|
194 | if (dup2(pipefds[1], fileno(stdout)) < 0) | |||
|
195 | goto error; | |||
|
196 | if (isatty(fileno(stderr))) { | |||
|
197 | if (dup2(pipefds[1], fileno(stderr)) < 0) | |||
|
198 | goto error; | |||
|
199 | } | |||
|
200 | close(pipefds[1]); | |||
|
201 | pagerpid = pid; | |||
|
202 | return pid; | |||
|
203 | } else { | |||
|
204 | dup2(pipefds[0], fileno(stdin)); | |||
|
205 | close(pipefds[0]); | |||
|
206 | close(pipefds[1]); | |||
|
207 | ||||
|
208 | int r = | |||
|
209 | execle("/bin/sh", "/bin/sh", "-c", pagercmd, NULL, envp); | |||
|
210 | if (r < 0) { | |||
|
211 | abortmsgerrno("cannot start pager '%s'", pagercmd); | |||
|
212 | } | |||
|
213 | return 0; | |||
|
214 | } | |||
|
215 | ||||
|
216 | error: | |||
|
217 | close(pipefds[0]); | |||
|
218 | close(pipefds[1]); | |||
|
219 | abortmsgerrno("failed to prepare pager"); | |||
|
220 | return 0; | |||
|
221 | } | |||
|
222 | ||||
|
223 | void waitpager(void) | |||
|
224 | { | |||
|
225 | if (pagerpid == 0) | |||
|
226 | return; | |||
|
227 | ||||
|
228 | /* close output streams to notify the pager its input ends */ | |||
|
229 | fclose(stdout); | |||
|
230 | fclose(stderr); | |||
|
231 | while (1) { | |||
|
232 | pid_t ret = waitpid(pagerpid, NULL, 0); | |||
|
233 | if (ret == -1 && errno == EINTR) | |||
|
234 | continue; | |||
|
235 | break; | |||
|
236 | } | |||
|
237 | } |
@@ -0,0 +1,21 b'' | |||||
|
1 | /* | |||
|
2 | * Utilities about process handling - signal and subprocess (ex. pager) | |||
|
3 | * | |||
|
4 | * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org> | |||
|
5 | * | |||
|
6 | * This software may be used and distributed according to the terms of the | |||
|
7 | * GNU General Public License version 2 or any later version. | |||
|
8 | */ | |||
|
9 | ||||
|
10 | #ifndef PROCUTIL_H_ | |||
|
11 | #define PROCUTIL_H_ | |||
|
12 | ||||
|
13 | #include <unistd.h> | |||
|
14 | ||||
|
15 | void restoresignalhandler(void); | |||
|
16 | void setupsignalhandler(pid_t pid, pid_t pgid); | |||
|
17 | ||||
|
18 | pid_t setuppager(const char *pagercmd, const char *envp[]); | |||
|
19 | void waitpager(void); | |||
|
20 | ||||
|
21 | #endif /* PROCUTIL_H_ */ |
@@ -0,0 +1,200 b'' | |||||
|
1 | /* | |||
|
2 | * Utility functions | |||
|
3 | * | |||
|
4 | * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org> | |||
|
5 | * | |||
|
6 | * This software may be used and distributed according to the terms of the | |||
|
7 | * GNU General Public License version 2 or any later version. | |||
|
8 | */ | |||
|
9 | ||||
|
10 | #include <errno.h> | |||
|
11 | #include <fcntl.h> | |||
|
12 | #include <signal.h> | |||
|
13 | #include <stdarg.h> | |||
|
14 | #include <stdio.h> | |||
|
15 | #include <stdlib.h> | |||
|
16 | #include <string.h> | |||
|
17 | #include <sys/time.h> | |||
|
18 | #include <sys/types.h> | |||
|
19 | #include <sys/wait.h> | |||
|
20 | #include <unistd.h> | |||
|
21 | ||||
|
22 | #include "util.h" | |||
|
23 | ||||
|
24 | static int colorenabled = 0; | |||
|
25 | ||||
|
26 | static inline void fsetcolor(FILE *fp, const char *code) | |||
|
27 | { | |||
|
28 | if (!colorenabled) | |||
|
29 | return; | |||
|
30 | fprintf(fp, "\033[%sm", code); | |||
|
31 | } | |||
|
32 | ||||
|
33 | static void vabortmsgerrno(int no, const char *fmt, va_list args) | |||
|
34 | { | |||
|
35 | fsetcolor(stderr, "1;31"); | |||
|
36 | fputs("chg: abort: ", stderr); | |||
|
37 | vfprintf(stderr, fmt, args); | |||
|
38 | if (no != 0) | |||
|
39 | fprintf(stderr, " (errno = %d, %s)", no, strerror(no)); | |||
|
40 | fsetcolor(stderr, ""); | |||
|
41 | fputc('\n', stderr); | |||
|
42 | exit(255); | |||
|
43 | } | |||
|
44 | ||||
|
45 | void abortmsg(const char *fmt, ...) | |||
|
46 | { | |||
|
47 | va_list args; | |||
|
48 | va_start(args, fmt); | |||
|
49 | vabortmsgerrno(0, fmt, args); | |||
|
50 | va_end(args); | |||
|
51 | } | |||
|
52 | ||||
|
53 | void abortmsgerrno(const char *fmt, ...) | |||
|
54 | { | |||
|
55 | int no = errno; | |||
|
56 | va_list args; | |||
|
57 | va_start(args, fmt); | |||
|
58 | vabortmsgerrno(no, fmt, args); | |||
|
59 | va_end(args); | |||
|
60 | } | |||
|
61 | ||||
|
62 | static int debugmsgenabled = 0; | |||
|
63 | static double debugstart = 0; | |||
|
64 | ||||
|
65 | static double now() | |||
|
66 | { | |||
|
67 | struct timeval t; | |||
|
68 | gettimeofday(&t, NULL); | |||
|
69 | return t.tv_usec / 1e6 + t.tv_sec; | |||
|
70 | } | |||
|
71 | ||||
|
72 | void enablecolor(void) | |||
|
73 | { | |||
|
74 | colorenabled = 1; | |||
|
75 | } | |||
|
76 | ||||
|
77 | void enabledebugmsg(void) | |||
|
78 | { | |||
|
79 | debugmsgenabled = 1; | |||
|
80 | debugstart = now(); | |||
|
81 | } | |||
|
82 | ||||
|
83 | void debugmsg(const char *fmt, ...) | |||
|
84 | { | |||
|
85 | if (!debugmsgenabled) | |||
|
86 | return; | |||
|
87 | ||||
|
88 | va_list args; | |||
|
89 | va_start(args, fmt); | |||
|
90 | fsetcolor(stderr, "1;30"); | |||
|
91 | fprintf(stderr, "chg: debug: %4.6f ", now() - debugstart); | |||
|
92 | vfprintf(stderr, fmt, args); | |||
|
93 | fsetcolor(stderr, ""); | |||
|
94 | fputc('\n', stderr); | |||
|
95 | va_end(args); | |||
|
96 | } | |||
|
97 | ||||
|
98 | void fchdirx(int dirfd) | |||
|
99 | { | |||
|
100 | int r = fchdir(dirfd); | |||
|
101 | if (r == -1) | |||
|
102 | abortmsgerrno("failed to fchdir"); | |||
|
103 | } | |||
|
104 | ||||
|
105 | void fsetcloexec(int fd) | |||
|
106 | { | |||
|
107 | int flags = fcntl(fd, F_GETFD); | |||
|
108 | if (flags < 0) | |||
|
109 | abortmsgerrno("cannot get flags of fd %d", fd); | |||
|
110 | if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) < 0) | |||
|
111 | abortmsgerrno("cannot set flags of fd %d", fd); | |||
|
112 | } | |||
|
113 | ||||
|
114 | void *mallocx(size_t size) | |||
|
115 | { | |||
|
116 | void *result = malloc(size); | |||
|
117 | if (!result) | |||
|
118 | abortmsg("failed to malloc"); | |||
|
119 | return result; | |||
|
120 | } | |||
|
121 | ||||
|
122 | void *reallocx(void *ptr, size_t size) | |||
|
123 | { | |||
|
124 | void *result = realloc(ptr, size); | |||
|
125 | if (!result) | |||
|
126 | abortmsg("failed to realloc"); | |||
|
127 | return result; | |||
|
128 | } | |||
|
129 | ||||
|
130 | /* | |||
|
131 | * Execute a shell command in mostly the same manner as system(), with the | |||
|
132 | * give environment variables, after chdir to the given cwd. Returns a status | |||
|
133 | * code compatible with the Python subprocess module. | |||
|
134 | */ | |||
|
135 | int runshellcmd(const char *cmd, const char *envp[], const char *cwd) | |||
|
136 | { | |||
|
137 | enum { F_SIGINT = 1, F_SIGQUIT = 2, F_SIGMASK = 4, F_WAITPID = 8 }; | |||
|
138 | unsigned int doneflags = 0; | |||
|
139 | int status = 0; | |||
|
140 | struct sigaction newsa, oldsaint, oldsaquit; | |||
|
141 | sigset_t oldmask; | |||
|
142 | ||||
|
143 | /* block or mask signals just as system() does */ | |||
|
144 | memset(&newsa, 0, sizeof(newsa)); | |||
|
145 | newsa.sa_handler = SIG_IGN; | |||
|
146 | newsa.sa_flags = 0; | |||
|
147 | if (sigemptyset(&newsa.sa_mask) < 0) | |||
|
148 | goto done; | |||
|
149 | if (sigaction(SIGINT, &newsa, &oldsaint) < 0) | |||
|
150 | goto done; | |||
|
151 | doneflags |= F_SIGINT; | |||
|
152 | if (sigaction(SIGQUIT, &newsa, &oldsaquit) < 0) | |||
|
153 | goto done; | |||
|
154 | doneflags |= F_SIGQUIT; | |||
|
155 | ||||
|
156 | if (sigaddset(&newsa.sa_mask, SIGCHLD) < 0) | |||
|
157 | goto done; | |||
|
158 | if (sigprocmask(SIG_BLOCK, &newsa.sa_mask, &oldmask) < 0) | |||
|
159 | goto done; | |||
|
160 | doneflags |= F_SIGMASK; | |||
|
161 | ||||
|
162 | pid_t pid = fork(); | |||
|
163 | if (pid < 0) | |||
|
164 | goto done; | |||
|
165 | if (pid == 0) { | |||
|
166 | sigaction(SIGINT, &oldsaint, NULL); | |||
|
167 | sigaction(SIGQUIT, &oldsaquit, NULL); | |||
|
168 | sigprocmask(SIG_SETMASK, &oldmask, NULL); | |||
|
169 | if (cwd && chdir(cwd) < 0) | |||
|
170 | _exit(127); | |||
|
171 | const char *argv[] = {"sh", "-c", cmd, NULL}; | |||
|
172 | if (envp) { | |||
|
173 | execve("/bin/sh", (char **)argv, (char **)envp); | |||
|
174 | } else { | |||
|
175 | execv("/bin/sh", (char **)argv); | |||
|
176 | } | |||
|
177 | _exit(127); | |||
|
178 | } else { | |||
|
179 | if (waitpid(pid, &status, 0) < 0) | |||
|
180 | goto done; | |||
|
181 | doneflags |= F_WAITPID; | |||
|
182 | } | |||
|
183 | ||||
|
184 | done: | |||
|
185 | if (doneflags & F_SIGINT) | |||
|
186 | sigaction(SIGINT, &oldsaint, NULL); | |||
|
187 | if (doneflags & F_SIGQUIT) | |||
|
188 | sigaction(SIGQUIT, &oldsaquit, NULL); | |||
|
189 | if (doneflags & F_SIGMASK) | |||
|
190 | sigprocmask(SIG_SETMASK, &oldmask, NULL); | |||
|
191 | ||||
|
192 | /* no way to report other errors, use 127 (= shell termination) */ | |||
|
193 | if (!(doneflags & F_WAITPID)) | |||
|
194 | return 127; | |||
|
195 | if (WIFEXITED(status)) | |||
|
196 | return WEXITSTATUS(status); | |||
|
197 | if (WIFSIGNALED(status)) | |||
|
198 | return -WTERMSIG(status); | |||
|
199 | return 127; | |||
|
200 | } |
@@ -0,0 +1,35 b'' | |||||
|
1 | /* | |||
|
2 | * Utility functions | |||
|
3 | * | |||
|
4 | * Copyright (c) 2011 Yuya Nishihara <yuya@tcha.org> | |||
|
5 | * | |||
|
6 | * This software may be used and distributed according to the terms of the | |||
|
7 | * GNU General Public License version 2 or any later version. | |||
|
8 | */ | |||
|
9 | ||||
|
10 | #ifndef UTIL_H_ | |||
|
11 | #define UTIL_H_ | |||
|
12 | ||||
|
13 | #ifdef __GNUC__ | |||
|
14 | #define PRINTF_FORMAT_ __attribute__((format(printf, 1, 2))) | |||
|
15 | #define UNUSED_ __attribute__((unused)) | |||
|
16 | #else | |||
|
17 | #define PRINTF_FORMAT_ | |||
|
18 | #define UNUSED_ | |||
|
19 | #endif | |||
|
20 | ||||
|
21 | void abortmsg(const char *fmt, ...) PRINTF_FORMAT_; | |||
|
22 | void abortmsgerrno(const char *fmt, ...) PRINTF_FORMAT_; | |||
|
23 | ||||
|
24 | void enablecolor(void); | |||
|
25 | void enabledebugmsg(void); | |||
|
26 | void debugmsg(const char *fmt, ...) PRINTF_FORMAT_; | |||
|
27 | ||||
|
28 | void fchdirx(int dirfd); | |||
|
29 | void fsetcloexec(int fd); | |||
|
30 | void *mallocx(size_t size); | |||
|
31 | void *reallocx(void *ptr, size_t size); | |||
|
32 | ||||
|
33 | int runshellcmd(const char *cmd, const char *envp[], const char *cwd); | |||
|
34 | ||||
|
35 | #endif /* UTIL_H_ */ |
@@ -0,0 +1,88 b'' | |||||
|
1 | # Files that just need to be migrated to the formatter. | |||
|
2 | # Do not add new files here! | |||
|
3 | mercurial/cext/dirs.c | |||
|
4 | mercurial/cext/manifest.c | |||
|
5 | mercurial/cext/osutil.c | |||
|
6 | mercurial/cext/revlog.c | |||
|
7 | # Vendored code that we should never format: | |||
|
8 | contrib/python-zstandard/c-ext/bufferutil.c | |||
|
9 | contrib/python-zstandard/c-ext/compressiondict.c | |||
|
10 | contrib/python-zstandard/c-ext/compressionparams.c | |||
|
11 | contrib/python-zstandard/c-ext/compressionreader.c | |||
|
12 | contrib/python-zstandard/c-ext/compressionwriter.c | |||
|
13 | contrib/python-zstandard/c-ext/compressobj.c | |||
|
14 | contrib/python-zstandard/c-ext/compressor.c | |||
|
15 | contrib/python-zstandard/c-ext/compressoriterator.c | |||
|
16 | contrib/python-zstandard/c-ext/constants.c | |||
|
17 | contrib/python-zstandard/c-ext/decompressionreader.c | |||
|
18 | contrib/python-zstandard/c-ext/decompressionwriter.c | |||
|
19 | contrib/python-zstandard/c-ext/decompressobj.c | |||
|
20 | contrib/python-zstandard/c-ext/decompressor.c | |||
|
21 | contrib/python-zstandard/c-ext/decompressoriterator.c | |||
|
22 | contrib/python-zstandard/c-ext/frameparams.c | |||
|
23 | contrib/python-zstandard/c-ext/python-zstandard.h | |||
|
24 | contrib/python-zstandard/zstd.c | |||
|
25 | contrib/python-zstandard/zstd/common/bitstream.h | |||
|
26 | contrib/python-zstandard/zstd/common/compiler.h | |||
|
27 | contrib/python-zstandard/zstd/common/cpu.h | |||
|
28 | contrib/python-zstandard/zstd/common/entropy_common.c | |||
|
29 | contrib/python-zstandard/zstd/common/error_private.c | |||
|
30 | contrib/python-zstandard/zstd/common/error_private.h | |||
|
31 | contrib/python-zstandard/zstd/common/fse_decompress.c | |||
|
32 | contrib/python-zstandard/zstd/common/fse.h | |||
|
33 | contrib/python-zstandard/zstd/common/huf.h | |||
|
34 | contrib/python-zstandard/zstd/common/mem.h | |||
|
35 | contrib/python-zstandard/zstd/common/pool.c | |||
|
36 | contrib/python-zstandard/zstd/common/pool.h | |||
|
37 | contrib/python-zstandard/zstd/common/threading.c | |||
|
38 | contrib/python-zstandard/zstd/common/threading.h | |||
|
39 | contrib/python-zstandard/zstd/common/xxhash.c | |||
|
40 | contrib/python-zstandard/zstd/common/xxhash.h | |||
|
41 | contrib/python-zstandard/zstd/common/zstd_common.c | |||
|
42 | contrib/python-zstandard/zstd/common/zstd_errors.h | |||
|
43 | contrib/python-zstandard/zstd/common/zstd_internal.h | |||
|
44 | contrib/python-zstandard/zstd/compress/fse_compress.c | |||
|
45 | contrib/python-zstandard/zstd/compress/huf_compress.c | |||
|
46 | contrib/python-zstandard/zstd/compress/zstd_compress.c | |||
|
47 | contrib/python-zstandard/zstd/compress/zstd_compress_internal.h | |||
|
48 | contrib/python-zstandard/zstd/compress/zstd_double_fast.c | |||
|
49 | contrib/python-zstandard/zstd/compress/zstd_double_fast.h | |||
|
50 | contrib/python-zstandard/zstd/compress/zstd_fast.c | |||
|
51 | contrib/python-zstandard/zstd/compress/zstd_fast.h | |||
|
52 | contrib/python-zstandard/zstd/compress/zstd_lazy.c | |||
|
53 | contrib/python-zstandard/zstd/compress/zstd_lazy.h | |||
|
54 | contrib/python-zstandard/zstd/compress/zstd_ldm.c | |||
|
55 | contrib/python-zstandard/zstd/compress/zstd_ldm.h | |||
|
56 | contrib/python-zstandard/zstd/compress/zstdmt_compress.c | |||
|
57 | contrib/python-zstandard/zstd/compress/zstdmt_compress.h | |||
|
58 | contrib/python-zstandard/zstd/compress/zstd_opt.c | |||
|
59 | contrib/python-zstandard/zstd/compress/zstd_opt.h | |||
|
60 | contrib/python-zstandard/zstd/decompress/huf_decompress.c | |||
|
61 | contrib/python-zstandard/zstd/decompress/zstd_decompress.c | |||
|
62 | contrib/python-zstandard/zstd/deprecated/zbuff_common.c | |||
|
63 | contrib/python-zstandard/zstd/deprecated/zbuff_compress.c | |||
|
64 | contrib/python-zstandard/zstd/deprecated/zbuff_decompress.c | |||
|
65 | contrib/python-zstandard/zstd/deprecated/zbuff.h | |||
|
66 | contrib/python-zstandard/zstd/dictBuilder/cover.c | |||
|
67 | contrib/python-zstandard/zstd/dictBuilder/divsufsort.c | |||
|
68 | contrib/python-zstandard/zstd/dictBuilder/divsufsort.h | |||
|
69 | contrib/python-zstandard/zstd/dictBuilder/zdict.c | |||
|
70 | contrib/python-zstandard/zstd/dictBuilder/zdict.h | |||
|
71 | contrib/python-zstandard/zstd/zstd.h | |||
|
72 | hgext/fsmonitor/pywatchman/bser.c | |||
|
73 | mercurial/thirdparty/xdiff/xdiff.h | |||
|
74 | mercurial/thirdparty/xdiff/xdiffi.c | |||
|
75 | mercurial/thirdparty/xdiff/xdiffi.h | |||
|
76 | mercurial/thirdparty/xdiff/xemit.c | |||
|
77 | mercurial/thirdparty/xdiff/xemit.h | |||
|
78 | mercurial/thirdparty/xdiff/xhistogram.c | |||
|
79 | mercurial/thirdparty/xdiff/xinclude.h | |||
|
80 | mercurial/thirdparty/xdiff/xmacros.h | |||
|
81 | mercurial/thirdparty/xdiff/xmerge.c | |||
|
82 | mercurial/thirdparty/xdiff/xpatience.c | |||
|
83 | mercurial/thirdparty/xdiff/xprepare.c | |||
|
84 | mercurial/thirdparty/xdiff/xprepare.h | |||
|
85 | mercurial/thirdparty/xdiff/xtypes.h | |||
|
86 | mercurial/thirdparty/xdiff/xutils.c | |||
|
87 | mercurial/thirdparty/xdiff/xutils.h | |||
|
88 | mercurial/thirdparty/zope/interface/_zope_interface_coptimizations.c |
@@ -0,0 +1,49 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | # | |||
|
3 | # Dumps output generated by Mercurial's command server in a formatted style to a | |||
|
4 | # given file or stderr if '-' is specified. Output is also written in its raw | |||
|
5 | # format to stdout. | |||
|
6 | # | |||
|
7 | # $ ./hg serve --cmds pipe | ./contrib/debugcmdserver.py - | |||
|
8 | # o, 52 -> 'capabilities: getencoding runcommand\nencoding: UTF-8' | |||
|
9 | ||||
|
10 | from __future__ import absolute_import, print_function | |||
|
11 | import struct | |||
|
12 | import sys | |||
|
13 | ||||
|
14 | if len(sys.argv) != 2: | |||
|
15 | print('usage: debugcmdserver.py FILE') | |||
|
16 | sys.exit(1) | |||
|
17 | ||||
|
18 | outputfmt = '>cI' | |||
|
19 | outputfmtsize = struct.calcsize(outputfmt) | |||
|
20 | ||||
|
21 | if sys.argv[1] == '-': | |||
|
22 | log = sys.stderr | |||
|
23 | else: | |||
|
24 | log = open(sys.argv[1], 'a') | |||
|
25 | ||||
|
26 | def read(size): | |||
|
27 | data = sys.stdin.read(size) | |||
|
28 | if not data: | |||
|
29 | raise EOFError | |||
|
30 | sys.stdout.write(data) | |||
|
31 | sys.stdout.flush() | |||
|
32 | return data | |||
|
33 | ||||
|
34 | try: | |||
|
35 | while True: | |||
|
36 | header = read(outputfmtsize) | |||
|
37 | channel, length = struct.unpack(outputfmt, header) | |||
|
38 | log.write('%s, %-4d' % (channel, length)) | |||
|
39 | if channel in 'IL': | |||
|
40 | log.write(' -> waiting for input\n') | |||
|
41 | else: | |||
|
42 | data = read(length) | |||
|
43 | log.write(' -> %r\n' % data) | |||
|
44 | log.flush() | |||
|
45 | except EOFError: | |||
|
46 | pass | |||
|
47 | finally: | |||
|
48 | if log != sys.stderr: | |||
|
49 | log.close() |
@@ -0,0 +1,59 b'' | |||||
|
1 | # debugshell extension | |||
|
2 | """a python shell with repo, changelog & manifest objects""" | |||
|
3 | ||||
|
4 | from __future__ import absolute_import | |||
|
5 | import code | |||
|
6 | import mercurial | |||
|
7 | import sys | |||
|
8 | from mercurial import ( | |||
|
9 | demandimport, | |||
|
10 | registrar, | |||
|
11 | ) | |||
|
12 | ||||
|
13 | cmdtable = {} | |||
|
14 | command = registrar.command(cmdtable) | |||
|
15 | ||||
|
16 | def pdb(ui, repo, msg, **opts): | |||
|
17 | objects = { | |||
|
18 | 'mercurial': mercurial, | |||
|
19 | 'repo': repo, | |||
|
20 | 'cl': repo.changelog, | |||
|
21 | 'mf': repo.manifestlog, | |||
|
22 | } | |||
|
23 | ||||
|
24 | code.interact(msg, local=objects) | |||
|
25 | ||||
|
26 | def ipdb(ui, repo, msg, **opts): | |||
|
27 | import IPython | |||
|
28 | ||||
|
29 | cl = repo.changelog | |||
|
30 | mf = repo.manifestlog | |||
|
31 | cl, mf # use variables to appease pyflakes | |||
|
32 | ||||
|
33 | IPython.embed() | |||
|
34 | ||||
|
35 | @command('debugshell|dbsh', []) | |||
|
36 | def debugshell(ui, repo, **opts): | |||
|
37 | bannermsg = "loaded repo : %s\n" \ | |||
|
38 | "using source: %s" % (repo.root, | |||
|
39 | mercurial.__path__[0]) | |||
|
40 | ||||
|
41 | pdbmap = { | |||
|
42 | 'pdb' : 'code', | |||
|
43 | 'ipdb' : 'IPython' | |||
|
44 | } | |||
|
45 | ||||
|
46 | debugger = ui.config("ui", "debugger") | |||
|
47 | if not debugger: | |||
|
48 | debugger = 'pdb' | |||
|
49 | ||||
|
50 | # if IPython doesn't exist, fallback to code.interact | |||
|
51 | try: | |||
|
52 | with demandimport.deactivated(): | |||
|
53 | __import__(pdbmap[debugger]) | |||
|
54 | except ImportError: | |||
|
55 | ui.warn(("%s debugger specified but %s module was not found\n") | |||
|
56 | % (debugger, pdbmap[debugger])) | |||
|
57 | debugger = 'pdb' | |||
|
58 | ||||
|
59 | getattr(sys.modules[__name__], debugger)(ui, repo, bannermsg, **opts) |
@@ -0,0 +1,59 b'' | |||||
|
1 | # dirstatenonnormalcheck.py - extension to check the consistency of the | |||
|
2 | # dirstate's non-normal map | |||
|
3 | # | |||
|
4 | # For most operations on dirstate, this extensions checks that the nonnormalset | |||
|
5 | # contains the right entries. | |||
|
6 | # It compares the nonnormal file to a nonnormalset built from the map of all | |||
|
7 | # the files in the dirstate to check that they contain the same files. | |||
|
8 | ||||
|
9 | from __future__ import absolute_import | |||
|
10 | ||||
|
11 | from mercurial import ( | |||
|
12 | dirstate, | |||
|
13 | extensions, | |||
|
14 | ) | |||
|
15 | ||||
|
16 | def nonnormalentries(dmap): | |||
|
17 | """Compute nonnormal entries from dirstate's dmap""" | |||
|
18 | res = set() | |||
|
19 | for f, e in dmap.iteritems(): | |||
|
20 | if e[0] != b'n' or e[3] == -1: | |||
|
21 | res.add(f) | |||
|
22 | return res | |||
|
23 | ||||
|
24 | def checkconsistency(ui, orig, dmap, _nonnormalset, label): | |||
|
25 | """Compute nonnormalset from dmap, check that it matches _nonnormalset""" | |||
|
26 | nonnormalcomputedmap = nonnormalentries(dmap) | |||
|
27 | if _nonnormalset != nonnormalcomputedmap: | |||
|
28 | ui.develwarn(b"%s call to %s\n" % (label, orig), config=b'dirstate') | |||
|
29 | ui.develwarn(b"inconsistency in nonnormalset\n", config=b'dirstate') | |||
|
30 | ui.develwarn(b"[nonnormalset] %s\n" % _nonnormalset, config=b'dirstate') | |||
|
31 | ui.develwarn(b"[map] %s\n" % nonnormalcomputedmap, config=b'dirstate') | |||
|
32 | ||||
|
33 | def _checkdirstate(orig, self, arg): | |||
|
34 | """Check nonnormal set consistency before and after the call to orig""" | |||
|
35 | checkconsistency(self._ui, orig, self._map, self._map.nonnormalset, | |||
|
36 | b"before") | |||
|
37 | r = orig(self, arg) | |||
|
38 | checkconsistency(self._ui, orig, self._map, self._map.nonnormalset, | |||
|
39 | b"after") | |||
|
40 | return r | |||
|
41 | ||||
|
42 | def extsetup(ui): | |||
|
43 | """Wrap functions modifying dirstate to check nonnormalset consistency""" | |||
|
44 | dirstatecl = dirstate.dirstate | |||
|
45 | devel = ui.configbool(b'devel', b'all-warnings') | |||
|
46 | paranoid = ui.configbool(b'experimental', b'nonnormalparanoidcheck') | |||
|
47 | if devel: | |||
|
48 | extensions.wrapfunction(dirstatecl, '_writedirstate', _checkdirstate) | |||
|
49 | if paranoid: | |||
|
50 | # We don't do all these checks when paranoid is disable as it would | |||
|
51 | # make the extension run very slowly on large repos | |||
|
52 | extensions.wrapfunction(dirstatecl, 'normallookup', _checkdirstate) | |||
|
53 | extensions.wrapfunction(dirstatecl, 'otherparent', _checkdirstate) | |||
|
54 | extensions.wrapfunction(dirstatecl, 'normal', _checkdirstate) | |||
|
55 | extensions.wrapfunction(dirstatecl, 'write', _checkdirstate) | |||
|
56 | extensions.wrapfunction(dirstatecl, 'add', _checkdirstate) | |||
|
57 | extensions.wrapfunction(dirstatecl, 'remove', _checkdirstate) | |||
|
58 | extensions.wrapfunction(dirstatecl, 'merge', _checkdirstate) | |||
|
59 | extensions.wrapfunction(dirstatecl, 'drop', _checkdirstate) |
@@ -0,0 +1,23 b'' | |||||
|
1 | FROM debian:wheezy | |||
|
2 | ||||
|
3 | ENV DEBIAN_FRONTEND noninteractive | |||
|
4 | ENV WSGI_PROCESSES 4 | |||
|
5 | ENV WSGI_THREADS 1 | |||
|
6 | ENV WSGI_MAX_REQUESTS 100000 | |||
|
7 | ||||
|
8 | EXPOSE 80 | |||
|
9 | VOLUME ["/var/hg/htdocs", "/var/hg/repos"] | |||
|
10 | ||||
|
11 | RUN apt-get update && apt-get -y install libapache2-mod-wsgi python-dev vim | |||
|
12 | ||||
|
13 | # Install our own Apache site. | |||
|
14 | RUN a2dissite 000-default | |||
|
15 | ADD vhost.conf /etc/apache2/sites-available/hg | |||
|
16 | RUN a2ensite hg | |||
|
17 | ||||
|
18 | ADD hgwebconfig /defaulthgwebconfig | |||
|
19 | ||||
|
20 | ADD entrypoint.sh /entrypoint.sh | |||
|
21 | ENTRYPOINT ["/entrypoint.sh"] | |||
|
22 | ||||
|
23 | CMD ["/usr/sbin/apache2", "-DFOREGROUND"] |
@@ -0,0 +1,144 b'' | |||||
|
1 | ==================== | |||
|
2 | Apache Docker Server | |||
|
3 | ==================== | |||
|
4 | ||||
|
5 | This directory contains code for running a Mercurial hgweb server via | |||
|
6 | mod_wsgi with the Apache HTTP Server inside a Docker container. | |||
|
7 | ||||
|
8 | .. important:: | |||
|
9 | ||||
|
10 | This container is intended for testing purposes only: it is | |||
|
11 | **not** meant to be suitable for production use. | |||
|
12 | ||||
|
13 | Building Image | |||
|
14 | ============== | |||
|
15 | ||||
|
16 | The first step is to build a Docker image containing Apache and mod_wsgi:: | |||
|
17 | ||||
|
18 | $ docker build -t hg-apache . | |||
|
19 | ||||
|
20 | .. important:: | |||
|
21 | ||||
|
22 | You should rebuild the image whenever the content of this directory | |||
|
23 | changes. Rebuilding after pulling or when you haven't run the container | |||
|
24 | in a while is typically a good idea. | |||
|
25 | ||||
|
26 | Running the Server | |||
|
27 | ================== | |||
|
28 | ||||
|
29 | To run the container, you'll execute something like:: | |||
|
30 | ||||
|
31 | $ docker run --rm -it -v `pwd`/../../..:/var/hg/source -p 8000:80 hg-apache | |||
|
32 | ||||
|
33 | If you aren't a Docker expert: | |||
|
34 | ||||
|
35 | * ``--rm`` will remove the container when it stops (so it doesn't clutter | |||
|
36 | your system) | |||
|
37 | * ``-i`` will launch the container in interactive mode so stdin is attached | |||
|
38 | * ``-t`` will allocate a pseudo TTY | |||
|
39 | * ``-v src:dst`` will mount the host filesystem at ``src`` into ``dst`` | |||
|
40 | in the container. In our example, we assume you are running from this | |||
|
41 | directory and use the source code a few directories up. | |||
|
42 | * ``-p 8000:80`` will publish port ``80`` on the container to port ``8000`` | |||
|
43 | on the host, allowing you to access the HTTP server on the host interface. | |||
|
44 | * ``hg-apache`` is the container image to run. This should correspond to what | |||
|
45 | we build with ``docker build``. | |||
|
46 | ||||
|
47 | .. important:: | |||
|
48 | ||||
|
49 | The container **requires** that ``/var/hg/source`` contain the Mercurial | |||
|
50 | source code. | |||
|
51 | ||||
|
52 | Upon start, the container will attempt an install of the source in that | |||
|
53 | directory. If the architecture of the host machine doesn't match that of | |||
|
54 | the Docker host (e.g. when running Boot2Docker under OS X), Mercurial's | |||
|
55 | Python C extensions will fail to run. Be sure to ``make clean`` your | |||
|
56 | host's source tree before mounting it in the container to avoid this. | |||
|
57 | ||||
|
58 | When starting the container, you should see some start-up actions (including | |||
|
59 | a Mercurial install) and some output saying Apache has started:: | |||
|
60 | ||||
|
61 | Now if you load ``http://localhost:8000/`` (or whatever interface Docker | |||
|
62 | is using), you should see hgweb running! | |||
|
63 | ||||
|
64 | For your convenience, we've created an empty repository available at | |||
|
65 | ``/repo``. Feel free to populate it with ``hg push``. | |||
|
66 | ||||
|
67 | Customizing the Server | |||
|
68 | ====================== | |||
|
69 | ||||
|
70 | By default, the Docker container installs a basic hgweb config and an | |||
|
71 | empty dummy repository. It also uses some reasonable defaults for | |||
|
72 | mod_wsgi. | |||
|
73 | ||||
|
74 | Customizing the WSGI Dispatcher And Mercurial Config | |||
|
75 | ---------------------------------------------------- | |||
|
76 | ||||
|
77 | By default, the Docker environment installs a custom ``hgweb.wsgi`` | |||
|
78 | file (based on the example in ``contrib/hgweb.wsgi``). The file | |||
|
79 | is installed into ``/var/hg/htdocs/hgweb.wsgi``. | |||
|
80 | ||||
|
81 | A default hgweb configuration file is also installed. The ``hgwebconfig`` | |||
|
82 | file from this directory is installed into ``/var/hg/htdocs/config``. | |||
|
83 | ||||
|
84 | You have a few options for customizing these files. | |||
|
85 | ||||
|
86 | The simplest is to hack up ``hgwebconfig`` and ``entrypoint.sh`` in | |||
|
87 | this directory and to rebuild the Docker image. This has the downside | |||
|
88 | that the Mercurial working copy is modified and you may accidentally | |||
|
89 | commit unwanted changes. | |||
|
90 | ||||
|
91 | The next simplest is to copy this directory somewhere, make your changes, | |||
|
92 | then rebuild the image. No working copy changes involved. | |||
|
93 | ||||
|
94 | The preferred solution is to mount a host file into the container and | |||
|
95 | overwrite the built-in defaults. | |||
|
96 | ||||
|
97 | For example, say we create a custom hgweb config file in ``~/hgweb``. We | |||
|
98 | can start the container like so to install our custom config file:: | |||
|
99 | ||||
|
100 | $ docker run -v ~/hgweb:/var/hg/htdocs/config ... | |||
|
101 | ||||
|
102 | You can do something similar to install a custom WSGI dispatcher:: | |||
|
103 | ||||
|
104 | $ docker run -v ~/hgweb.wsgi:/var/hg/htdocs/hgweb.wsgi ... | |||
|
105 | ||||
|
106 | Managing Repositories | |||
|
107 | --------------------- | |||
|
108 | ||||
|
109 | Repositories are served from ``/var/hg/repos`` by default. This directory | |||
|
110 | is configured as a Docker volume. This means you can mount an existing | |||
|
111 | data volume container in the container so repository data is persisted | |||
|
112 | across container invocations. See | |||
|
113 | https://docs.docker.com/userguide/dockervolumes/ for more. | |||
|
114 | ||||
|
115 | Alternatively, if you just want to perform lightweight repository | |||
|
116 | manipulation, open a shell in the container:: | |||
|
117 | ||||
|
118 | $ docker exec -it <container> /bin/bash | |||
|
119 | ||||
|
120 | Then run ``hg init``, etc to manipulate the repositories in ``/var/hg/repos``. | |||
|
121 | ||||
|
122 | mod_wsgi Configuration Settings | |||
|
123 | ------------------------------- | |||
|
124 | ||||
|
125 | mod_wsgi settings can be controlled with the following environment | |||
|
126 | variables. | |||
|
127 | ||||
|
128 | WSGI_PROCESSES | |||
|
129 | Number of WSGI processes to run. | |||
|
130 | WSGI_THREADS | |||
|
131 | Number of threads to run in each WSGI process | |||
|
132 | WSGI_MAX_REQUESTS | |||
|
133 | Maximum number of requests each WSGI process may serve before it is | |||
|
134 | reaped. | |||
|
135 | ||||
|
136 | See https://code.google.com/p/modwsgi/wiki/ConfigurationDirectives#WSGIDaemonProcess | |||
|
137 | for more on these settings. | |||
|
138 | ||||
|
139 | .. note:: | |||
|
140 | ||||
|
141 | The default is to use 1 thread per process. The reason is that Mercurial | |||
|
142 | doesn't perform well in multi-threaded mode due to the GIL. Most people | |||
|
143 | run a single thread per process in production for this reason, so that's | |||
|
144 | what we default to. |
@@ -0,0 +1,80 b'' | |||||
|
1 | #!/bin/bash | |||
|
2 | ||||
|
3 | # This script gets executed on container start. Its job is to set up | |||
|
4 | # the Mercurial environment and invoke the server. | |||
|
5 | ||||
|
6 | # Mercurial can be started in two modes. | |||
|
7 | # If the MERCURIAL_SOURCE environment variable is set and it points to a | |||
|
8 | # Mercurial source directory, we will install Mercurial from that directory. | |||
|
9 | # Otherwise, we download the Mercurial source and install it manually. | |||
|
10 | ||||
|
11 | set -e | |||
|
12 | ||||
|
13 | SOURCE_DIR=/var/hg/source | |||
|
14 | INSTALL_DIR=/var/hg/install | |||
|
15 | REPOS_DIR=/var/hg/repos | |||
|
16 | HTDOCS_DIR=/var/hg/htdocs | |||
|
17 | ||||
|
18 | if [ ! -d ${SOURCE_DIR} ]; then | |||
|
19 | echo "Mercurial source not available at ${SOURCE_DIR}" | |||
|
20 | echo "You need to mount a volume containing the Mercurial source code" | |||
|
21 | echo "when running the container. For example:" | |||
|
22 | echo "" | |||
|
23 | echo " $ docker run -v ~/src/hg:/${SOURCE_DIR} hg-apache" | |||
|
24 | echo "" | |||
|
25 | echo "This container will now stop running." | |||
|
26 | exit 1 | |||
|
27 | fi | |||
|
28 | ||||
|
29 | echo "Installing Mercurial from ${SOURCE_DIR} into ${INSTALL_DIR}" | |||
|
30 | pushd ${SOURCE_DIR} | |||
|
31 | /usr/bin/python2.7 setup.py install --root=/ --prefix=${INSTALL_DIR} --force | |||
|
32 | popd | |||
|
33 | ||||
|
34 | mkdir -p ${HTDOCS_DIR} | |||
|
35 | ||||
|
36 | # Provide a default config if the user hasn't supplied one. | |||
|
37 | if [ ! -f ${HTDOCS_DIR}/config ]; then | |||
|
38 | cp /defaulthgwebconfig ${HTDOCS_DIR}/config | |||
|
39 | fi | |||
|
40 | ||||
|
41 | if [ ! -f ${HTDOCS_DIR}/hgweb.wsgi ]; then | |||
|
42 | cat >> ${HTDOCS_DIR}/hgweb.wsgi << EOF | |||
|
43 | config = '${HTDOCS_DIR}/config' | |||
|
44 | ||||
|
45 | import sys | |||
|
46 | sys.path.insert(0, '${INSTALL_DIR}/lib/python2.7/site-packages') | |||
|
47 | ||||
|
48 | from mercurial import demandimport | |||
|
49 | demandimport.enable() | |||
|
50 | ||||
|
51 | from mercurial.hgweb import hgweb | |||
|
52 | application = hgweb(config) | |||
|
53 | EOF | |||
|
54 | fi | |||
|
55 | ||||
|
56 | mkdir -p ${REPOS_DIR} | |||
|
57 | ||||
|
58 | if [ ! -d ${REPOS_DIR}/repo ]; then | |||
|
59 | ${INSTALL_DIR}/bin/hg init ${REPOS_DIR}/repo | |||
|
60 | chown -R www-data:www-data ${REPOS_DIR}/repo | |||
|
61 | fi | |||
|
62 | ||||
|
63 | # This is necessary to make debuginstall happy. | |||
|
64 | if [ ! -f ~/.hgrc ]; then | |||
|
65 | cat >> ~/.hgrc << EOF | |||
|
66 | [ui] | |||
|
67 | username = Dummy User <nobody@example.com> | |||
|
68 | EOF | |||
|
69 | fi | |||
|
70 | ||||
|
71 | echo "Verifying Mercurial installation looks happy" | |||
|
72 | ${INSTALL_DIR}/bin/hg debuginstall | |||
|
73 | ||||
|
74 | . /etc/apache2/envvars | |||
|
75 | ||||
|
76 | echo "Starting Apache HTTP Server on port 80" | |||
|
77 | echo "We hope you remembered to publish this port when running the container!" | |||
|
78 | echo "If this is an interactive container, simply CTRL^C to stop." | |||
|
79 | ||||
|
80 | exec "$@" |
@@ -0,0 +1,24 b'' | |||||
|
1 | # Apache won't be able to resolve its own hostname, so we sneak this | |||
|
2 | # into the global context to silence a confusing-to-user warning on | |||
|
3 | # server start. | |||
|
4 | ServerName hg | |||
|
5 | ||||
|
6 | <VirtualHost *:80> | |||
|
7 | DocumentRoot /var/hg/htdocs | |||
|
8 | <Directory /> | |||
|
9 | Options FollowSymLinks | |||
|
10 | AllowOverride None | |||
|
11 | </Directory> | |||
|
12 | ||||
|
13 | SetEnv HGENCODING UTF-8 | |||
|
14 | SetEnv LC_TYPE UTF-8 | |||
|
15 | ||||
|
16 | WSGIDaemonProcess hg processes=${WSGI_PROCESSES} threads=${WSGI_THREADS} maximum-requests=${WSGI_MAX_REQUESTS} user=www-data group=www-data display-name=hg-wsgi | |||
|
17 | WSGIProcessGroup hg | |||
|
18 | ||||
|
19 | WSGIScriptAliasMatch ^(.*) /var/hg/htdocs/hgweb.wsgi$1 | |||
|
20 | ||||
|
21 | ErrorLog ${APACHE_LOG_DIR}/error.log | |||
|
22 | LogLevel warn | |||
|
23 | CustomLog ${APACHE_LOG_DIR}/access.log combined | |||
|
24 | </VirtualHost> |
@@ -0,0 +1,37 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | # Dump revlogs as raw data stream | |||
|
3 | # $ find .hg/store/ -name "*.i" | xargs dumprevlog > repo.dump | |||
|
4 | ||||
|
5 | from __future__ import absolute_import, print_function | |||
|
6 | ||||
|
7 | import sys | |||
|
8 | from mercurial import ( | |||
|
9 | node, | |||
|
10 | revlog, | |||
|
11 | ) | |||
|
12 | from mercurial.utils import ( | |||
|
13 | procutil, | |||
|
14 | ) | |||
|
15 | ||||
|
16 | for fp in (sys.stdin, sys.stdout, sys.stderr): | |||
|
17 | procutil.setbinary(fp) | |||
|
18 | ||||
|
19 | def binopen(path, mode='rb'): | |||
|
20 | if 'b' not in mode: | |||
|
21 | mode = mode + 'b' | |||
|
22 | return open(path, mode) | |||
|
23 | ||||
|
24 | for f in sys.argv[1:]: | |||
|
25 | r = revlog.revlog(binopen, f) | |||
|
26 | print("file:", f) | |||
|
27 | for i in r: | |||
|
28 | n = r.node(i) | |||
|
29 | p = r.parents(n) | |||
|
30 | d = r.revision(n) | |||
|
31 | print("node:", node.hex(n)) | |||
|
32 | print("linkrev:", r.linkrev(i)) | |||
|
33 | print("parents:", node.hex(p[0]), node.hex(p[1])) | |||
|
34 | print("length:", len(d)) | |||
|
35 | print("-start-") | |||
|
36 | print(d) | |||
|
37 | print("-end-") |
@@ -0,0 +1,58 b'' | |||||
|
1 | #!/usr/bin/env bash | |||
|
2 | # A simple script for opening merge conflicts in the editor. | |||
|
3 | # Use the following Mercurial settings to enable it. | |||
|
4 | # | |||
|
5 | # [ui] | |||
|
6 | # merge = editmerge | |||
|
7 | # | |||
|
8 | # [merge-tools] | |||
|
9 | # editmerge.args=$output | |||
|
10 | # editmerge.check=changed | |||
|
11 | # editmerge.premerge=keep | |||
|
12 | ||||
|
13 | FILE="$1" | |||
|
14 | ||||
|
15 | getlines() { | |||
|
16 | grep -n "^<<<<<<" "$FILE" | cut -f1 -d: | |||
|
17 | } | |||
|
18 | ||||
|
19 | # editor preference loosely based on https://mercurial-scm.org/wiki/editor | |||
|
20 | # hg showconfig is at the bottom though, since it's slow to run (0.15 seconds) | |||
|
21 | ED="$HGEDITOR" | |||
|
22 | if [ "$ED" = "" ] ; then | |||
|
23 | ED="$VISUAL" | |||
|
24 | fi | |||
|
25 | if [ "$ED" = "" ] ; then | |||
|
26 | ED="$EDITOR" | |||
|
27 | fi | |||
|
28 | if [ "$ED" = "" ] ; then | |||
|
29 | ED="$(hg showconfig ui.editor)" | |||
|
30 | fi | |||
|
31 | if [ "$ED" = "" ] ; then | |||
|
32 | echo "merge failed - unable to find editor" | |||
|
33 | exit 1 | |||
|
34 | fi | |||
|
35 | ||||
|
36 | if [ "$ED" = "emacs" ] || [ "$ED" = "nano" ] || [ "$ED" = "vim" ] ; then | |||
|
37 | FIRSTLINE="$(getlines | head -n 1)" | |||
|
38 | PREVIOUSLINE="" | |||
|
39 | ||||
|
40 | # open the editor to the first conflict until there are no more | |||
|
41 | # or the user stops editing the file | |||
|
42 | while [ ! "$FIRSTLINE" = "" ] && [ ! "$FIRSTLINE" = "$PREVIOUSLINE" ] ; do | |||
|
43 | $ED "+$FIRSTLINE" "$FILE" | |||
|
44 | PREVIOUSLINE="$FIRSTLINE" | |||
|
45 | FIRSTLINE="$(getlines | head -n 1)" | |||
|
46 | done | |||
|
47 | else | |||
|
48 | $ED "$FILE" | |||
|
49 | fi | |||
|
50 | ||||
|
51 | # get the line numbers of the remaining conflicts | |||
|
52 | CONFLICTS="$(getlines | sed ':a;N;$!ba;s/\n/, /g')" | |||
|
53 | if [ ! "$CONFLICTS" = "" ] ; then | |||
|
54 | echo "merge failed - resolve the conflicts (line $CONFLICTS) then use 'hg resolve --mark'" | |||
|
55 | exit 1 | |||
|
56 | fi | |||
|
57 | ||||
|
58 | exit 0 |
@@ -0,0 +1,2 b'' | |||||
|
1 | @echo off | |||
|
2 | powershell -NoProfile -ExecutionPolicy unrestricted -Command "& '%~dp0\editmergeps.ps1' %*" |
@@ -0,0 +1,78 b'' | |||||
|
1 | # A simple script for opening merge conflicts in editor | |||
|
2 | # A loose translation of contrib/editmerge to powershell | |||
|
3 | # Please make sure that both editmergeps.bat and editmerge.ps1 are available | |||
|
4 | # via %PATH% and use the following Mercurial settings to enable it | |||
|
5 | # | |||
|
6 | # [ui] | |||
|
7 | # editmergeps | |||
|
8 | # editmergeps.args=$output | |||
|
9 | # editmergeps.check=changed | |||
|
10 | # editmergeps.premerge=keep | |||
|
11 | ||||
|
12 | $file=$args[0] | |||
|
13 | ||||
|
14 | function Get-Lines | |||
|
15 | { | |||
|
16 | Select-String "^<<<<<<" $file | % {"$($_.LineNumber)"} | |||
|
17 | } | |||
|
18 | ||||
|
19 | $ed = $Env:HGEDITOR; | |||
|
20 | if ($ed -eq $nil) | |||
|
21 | { | |||
|
22 | $ed = $Env:VISUAL; | |||
|
23 | } | |||
|
24 | if ($ed -eq $nil) | |||
|
25 | { | |||
|
26 | $ed = $Env:EDITOR; | |||
|
27 | } | |||
|
28 | if ($ed -eq $nil) | |||
|
29 | { | |||
|
30 | $ed = $(hg showconfig ui.editor); | |||
|
31 | } | |||
|
32 | if ($ed -eq $nil) | |||
|
33 | { | |||
|
34 | Write-Error "merge failed - unable to find editor" | |||
|
35 | exit 1 | |||
|
36 | } | |||
|
37 | ||||
|
38 | if (($ed -eq "vim") -or ($ed -eq "emacs") -or ` | |||
|
39 | ($ed -eq "nano") -or ($ed -eq "notepad++")) | |||
|
40 | { | |||
|
41 | $lines = Get-Lines | |||
|
42 | $firstline = if ($lines.Length -gt 0) { $lines[0] } else { $nil } | |||
|
43 | $previousline = $nil; | |||
|
44 | ||||
|
45 | ||||
|
46 | # open the editor to the first conflict until there are no more | |||
|
47 | # or the user stops editing the file | |||
|
48 | while (($firstline -ne $nil) -and ($firstline -ne $previousline)) | |||
|
49 | { | |||
|
50 | if ($ed -eq "notepad++") | |||
|
51 | { | |||
|
52 | $linearg = "-n$firstline" | |||
|
53 | } | |||
|
54 | else | |||
|
55 | { | |||
|
56 | $linearg = "+$firstline" | |||
|
57 | } | |||
|
58 | ||||
|
59 | Start-Process -Wait -NoNewWindow $ed $linearg,$file | |||
|
60 | $previousline = $firstline | |||
|
61 | $lines = Get-Lines | |||
|
62 | $firstline = if ($lines.Length -gt 0) { $lines[0] } else { $nil } | |||
|
63 | } | |||
|
64 | } | |||
|
65 | else | |||
|
66 | { | |||
|
67 | & "$ed" $file | |||
|
68 | } | |||
|
69 | ||||
|
70 | $conflicts=Get-Lines | |||
|
71 | if ($conflicts.Length -ne 0) | |||
|
72 | { | |||
|
73 | Write-Output "merge failed - resolve the conflicts (line $conflicts) then use 'hg resolve --mark'" | |||
|
74 | exit 1 | |||
|
75 | } | |||
|
76 | ||||
|
77 | exit 0 | |||
|
78 |
@@ -0,0 +1,81 b'' | |||||
|
1 | CC = clang | |||
|
2 | CXX = clang++ | |||
|
3 | ||||
|
4 | all: bdiff mpatch xdiff | |||
|
5 | ||||
|
6 | fuzzutil.o: fuzzutil.cc fuzzutil.h | |||
|
7 | $(CXX) $(CXXFLAGS) -g -O1 -fsanitize=fuzzer-no-link,address \ | |||
|
8 | -std=c++17 \ | |||
|
9 | -I../../mercurial -c -o fuzzutil.o fuzzutil.cc | |||
|
10 | ||||
|
11 | fuzzutil-oss-fuzz.o: fuzzutil.cc fuzzutil.h | |||
|
12 | $(CXX) $(CXXFLAGS) -std=c++17 \ | |||
|
13 | -I../../mercurial -c -o fuzzutil-oss-fuzz.o fuzzutil.cc | |||
|
14 | ||||
|
15 | bdiff.o: ../../mercurial/bdiff.c | |||
|
16 | $(CC) $(CFLAGS) -fsanitize=fuzzer-no-link,address -c -o bdiff.o \ | |||
|
17 | ../../mercurial/bdiff.c | |||
|
18 | ||||
|
19 | bdiff: bdiff.cc bdiff.o fuzzutil.o | |||
|
20 | $(CXX) $(CXXFLAGS) -DHG_FUZZER_INCLUDE_MAIN=1 -g -O1 -fsanitize=fuzzer-no-link,address \ | |||
|
21 | -std=c++17 \ | |||
|
22 | -I../../mercurial bdiff.cc bdiff.o fuzzutil.o -o bdiff | |||
|
23 | ||||
|
24 | bdiff-oss-fuzz.o: ../../mercurial/bdiff.c | |||
|
25 | $(CC) $(CFLAGS) -c -o bdiff-oss-fuzz.o ../../mercurial/bdiff.c | |||
|
26 | ||||
|
27 | bdiff_fuzzer: bdiff.cc bdiff-oss-fuzz.o fuzzutil-oss-fuzz.o | |||
|
28 | $(CXX) $(CXXFLAGS) -std=c++17 -I../../mercurial bdiff.cc \ | |||
|
29 | bdiff-oss-fuzz.o fuzzutil-oss-fuzz.o -lFuzzingEngine -o \ | |||
|
30 | $$OUT/bdiff_fuzzer | |||
|
31 | ||||
|
32 | mpatch.o: ../../mercurial/mpatch.c | |||
|
33 | $(CC) -g -O1 -fsanitize=fuzzer-no-link,address -c -o mpatch.o \ | |||
|
34 | ../../mercurial/mpatch.c | |||
|
35 | ||||
|
36 | mpatch: CXXFLAGS += -std=c++17 | |||
|
37 | mpatch: mpatch.cc mpatch.o fuzzutil.o | |||
|
38 | $(CXX) $(CXXFLAGS) -DHG_FUZZER_INCLUDE_MAIN=1 -g -O1 -fsanitize=fuzzer-no-link,address \ | |||
|
39 | -I../../mercurial mpatch.cc mpatch.o fuzzutil.o -o mpatch | |||
|
40 | ||||
|
41 | mpatch-oss-fuzz.o: ../../mercurial/mpatch.c | |||
|
42 | $(CC) $(CFLAGS) -c -o mpatch-oss-fuzz.o ../../mercurial/mpatch.c | |||
|
43 | ||||
|
44 | mpatch_fuzzer: mpatch.cc mpatch-oss-fuzz.o fuzzutil-oss-fuzz.o | |||
|
45 | $(CXX) $(CXXFLAGS) -std=c++17 -I../../mercurial mpatch.cc \ | |||
|
46 | mpatch-oss-fuzz.o fuzzutil-oss-fuzz.o -lFuzzingEngine -o \ | |||
|
47 | $$OUT/mpatch_fuzzer | |||
|
48 | ||||
|
49 | mpatch_corpus.zip: | |||
|
50 | python mpatch_corpus.py $$OUT/mpatch_fuzzer_seed_corpus.zip | |||
|
51 | ||||
|
52 | x%.o: ../../mercurial/thirdparty/xdiff/x%.c ../../mercurial/thirdparty/xdiff/*.h | |||
|
53 | $(CC) -g -O1 -fsanitize=fuzzer-no-link,address -c \ | |||
|
54 | -o $@ \ | |||
|
55 | $< | |||
|
56 | ||||
|
57 | xdiff: CXXFLAGS += -std=c++17 | |||
|
58 | xdiff: xdiff.cc xdiffi.o xprepare.o xutils.o fuzzutil.o | |||
|
59 | $(CXX) $(CXXFLAGS) -DHG_FUZZER_INCLUDE_MAIN=1 -g -O1 -fsanitize=fuzzer-no-link,address \ | |||
|
60 | -I../../mercurial xdiff.cc \ | |||
|
61 | xdiffi.o xprepare.o xutils.o fuzzutil.o -o xdiff | |||
|
62 | ||||
|
63 | fuzz-x%.o: ../../mercurial/thirdparty/xdiff/x%.c ../../mercurial/thirdparty/xdiff/*.h | |||
|
64 | $(CC) $(CFLAGS) -c \ | |||
|
65 | -o $@ \ | |||
|
66 | $< | |||
|
67 | ||||
|
68 | xdiff_fuzzer: xdiff.cc fuzz-xdiffi.o fuzz-xprepare.o fuzz-xutils.o fuzzutil-oss-fuzz.o | |||
|
69 | $(CXX) $(CXXFLAGS) -std=c++17 -I../../mercurial xdiff.cc \ | |||
|
70 | fuzz-xdiffi.o fuzz-xprepare.o fuzz-xutils.o fuzzutil-oss-fuzz.o \ | |||
|
71 | -lFuzzingEngine -o $$OUT/xdiff_fuzzer | |||
|
72 | ||||
|
73 | clean: | |||
|
74 | $(RM) *.o *_fuzzer \ | |||
|
75 | bdiff \ | |||
|
76 | mpatch \ | |||
|
77 | xdiff | |||
|
78 | ||||
|
79 | oss-fuzz: bdiff_fuzzer mpatch_fuzzer mpatch_corpus.zip xdiff_fuzzer | |||
|
80 | ||||
|
81 | .PHONY: all clean oss-fuzz |
@@ -0,0 +1,26 b'' | |||||
|
1 | How to add fuzzers (partially cribbed from oss-fuzz[0]): | |||
|
2 | ||||
|
3 | 1) git clone https://github.com/google/oss-fuzz | |||
|
4 | 2) cd oss-fuzz | |||
|
5 | 3) python infra/helper.py build_image mercurial | |||
|
6 | 4) docker run --cap-add=SYS_PTRACE -it -v $HG_REPO_PATH:/hg-new \ | |||
|
7 | gcr.io/oss-fuzz/mercurial bash | |||
|
8 | 5) cd /src | |||
|
9 | 6) rm -r mercurial | |||
|
10 | 7) ln -s /hg-new mercurial | |||
|
11 | 8) cd mercurial | |||
|
12 | 9) compile | |||
|
13 | 10) ls $OUT | |||
|
14 | ||||
|
15 | Step 9 is literally running the command "compile", which is part of | |||
|
16 | the docker container. Once you have that working, you can build the | |||
|
17 | fuzzers like this (in the oss-fuzz repo): | |||
|
18 | ||||
|
19 | python infra/helper.py build_fuzzers --sanitizer address mercurial $HG_REPO_PATH | |||
|
20 | ||||
|
21 | (you can also say "memory", "undefined" or "coverage" for | |||
|
22 | sanitizer). Then run the built fuzzers like this: | |||
|
23 | ||||
|
24 | python infra/helper.py run_fuzzer mercurial -- $FUZZER | |||
|
25 | ||||
|
26 | 0: https://github.com/google/oss-fuzz/blob/master/docs/new_project_guide.md |
@@ -0,0 +1,44 b'' | |||||
|
1 | /* | |||
|
2 | * bdiff.cc - fuzzer harness for bdiff.c | |||
|
3 | * | |||
|
4 | * Copyright 2018, Google Inc. | |||
|
5 | * | |||
|
6 | * This software may be used and distributed according to the terms of | |||
|
7 | * the GNU General Public License, incorporated herein by reference. | |||
|
8 | */ | |||
|
9 | #include <memory> | |||
|
10 | #include <stdlib.h> | |||
|
11 | ||||
|
12 | #include "fuzzutil.h" | |||
|
13 | ||||
|
14 | extern "C" { | |||
|
15 | #include "bdiff.h" | |||
|
16 | ||||
|
17 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) | |||
|
18 | { | |||
|
19 | auto maybe_inputs = SplitInputs(Data, Size); | |||
|
20 | if (!maybe_inputs) { | |||
|
21 | return 0; | |||
|
22 | } | |||
|
23 | auto inputs = std::move(maybe_inputs.value()); | |||
|
24 | ||||
|
25 | struct bdiff_line *a, *b; | |||
|
26 | int an = bdiff_splitlines(inputs.left.get(), inputs.left_size, &a); | |||
|
27 | int bn = bdiff_splitlines(inputs.right.get(), inputs.right_size, &b); | |||
|
28 | struct bdiff_hunk l; | |||
|
29 | bdiff_diff(a, an, b, bn, &l); | |||
|
30 | free(a); | |||
|
31 | free(b); | |||
|
32 | bdiff_freehunks(l.next); | |||
|
33 | return 0; // Non-zero return values are reserved for future use. | |||
|
34 | } | |||
|
35 | ||||
|
36 | #ifdef HG_FUZZER_INCLUDE_MAIN | |||
|
37 | int main(int argc, char **argv) | |||
|
38 | { | |||
|
39 | const char data[] = "asdf"; | |||
|
40 | return LLVMFuzzerTestOneInput((const uint8_t *)data, 4); | |||
|
41 | } | |||
|
42 | #endif | |||
|
43 | ||||
|
44 | } // extern "C" |
@@ -0,0 +1,27 b'' | |||||
|
1 | #include "fuzzutil.h" | |||
|
2 | ||||
|
3 | #include <cstring> | |||
|
4 | #include <utility> | |||
|
5 | ||||
|
6 | contrib::optional<two_inputs> SplitInputs(const uint8_t *Data, size_t Size) | |||
|
7 | { | |||
|
8 | if (!Size) { | |||
|
9 | return contrib::nullopt; | |||
|
10 | } | |||
|
11 | // figure out a random point in [0, Size] to split our input. | |||
|
12 | size_t left_size = (Data[0] / 255.0) * (Size - 1); | |||
|
13 | ||||
|
14 | // Copy inputs to new allocations so if bdiff over-reads | |||
|
15 | // AddressSanitizer can detect it. | |||
|
16 | std::unique_ptr<char[]> left(new char[left_size]); | |||
|
17 | std::memcpy(left.get(), Data + 1, left_size); | |||
|
18 | // right starts at the next byte after left ends | |||
|
19 | size_t right_size = Size - (left_size + 1); | |||
|
20 | std::unique_ptr<char[]> right(new char[right_size]); | |||
|
21 | std::memcpy(right.get(), Data + 1 + left_size, right_size); | |||
|
22 | LOG(2) << "inputs are " << left_size << " and " << right_size | |||
|
23 | << " bytes" << std::endl; | |||
|
24 | two_inputs result = {std::move(right), right_size, std::move(left), | |||
|
25 | left_size}; | |||
|
26 | return result; | |||
|
27 | } |
@@ -0,0 +1,47 b'' | |||||
|
1 | #ifndef CONTRIB_FUZZ_FUZZUTIL_H | |||
|
2 | #define CONTRIB_FUZZ_FUZZUTIL_H | |||
|
3 | #include <iostream> | |||
|
4 | #include <memory> | |||
|
5 | #include <stdint.h> | |||
|
6 | ||||
|
7 | /* Try and use std::optional, but failing that assume we'll have a | |||
|
8 | * workable https://abseil.io/ install on the include path to get | |||
|
9 | * their backport of std::optional. */ | |||
|
10 | #ifdef __has_include | |||
|
11 | #if __has_include(<optional>) && __cplusplus >= 201703L | |||
|
12 | #include <optional> | |||
|
13 | #define CONTRIB_FUZZ_HAVE_STD_OPTIONAL | |||
|
14 | #endif | |||
|
15 | #endif | |||
|
16 | #ifdef CONTRIB_FUZZ_HAVE_STD_OPTIONAL | |||
|
17 | namespace contrib | |||
|
18 | { | |||
|
19 | using std::nullopt; | |||
|
20 | using std::optional; | |||
|
21 | } /* namespace contrib */ | |||
|
22 | #else | |||
|
23 | #include "third_party/absl/types/optional.h" | |||
|
24 | namespace contrib | |||
|
25 | { | |||
|
26 | using absl::nullopt; | |||
|
27 | using absl::optional; | |||
|
28 | } /* namespace contrib */ | |||
|
29 | #endif | |||
|
30 | ||||
|
31 | /* set DEBUG to 1 for a few debugging prints, or 2 for a lot */ | |||
|
32 | #define DEBUG 0 | |||
|
33 | #define LOG(level) \ | |||
|
34 | if (level <= DEBUG) \ | |||
|
35 | std::cout | |||
|
36 | ||||
|
37 | struct two_inputs { | |||
|
38 | std::unique_ptr<char[]> right; | |||
|
39 | size_t right_size; | |||
|
40 | std::unique_ptr<char[]> left; | |||
|
41 | size_t left_size; | |||
|
42 | }; | |||
|
43 | ||||
|
44 | /* Split a non-zero-length input into two inputs. */ | |||
|
45 | contrib::optional<two_inputs> SplitInputs(const uint8_t *Data, size_t Size); | |||
|
46 | ||||
|
47 | #endif /* CONTRIB_FUZZ_FUZZUTIL_H */ |
@@ -0,0 +1,122 b'' | |||||
|
1 | /* | |||
|
2 | * mpatch.cc - fuzzer harness for mpatch.c | |||
|
3 | * | |||
|
4 | * Copyright 2018, Google Inc. | |||
|
5 | * | |||
|
6 | * This software may be used and distributed according to the terms of | |||
|
7 | * the GNU General Public License, incorporated herein by reference. | |||
|
8 | */ | |||
|
9 | #include <iostream> | |||
|
10 | #include <memory> | |||
|
11 | #include <stdint.h> | |||
|
12 | #include <stdlib.h> | |||
|
13 | #include <vector> | |||
|
14 | ||||
|
15 | #include "fuzzutil.h" | |||
|
16 | ||||
|
17 | // To avoid having too many OOMs from the fuzzer infrastructure, we'll | |||
|
18 | // skip patch application if the resulting fulltext would be bigger | |||
|
19 | // than 10MiB. | |||
|
20 | #define MAX_OUTPUT_SIZE 10485760 | |||
|
21 | ||||
|
22 | extern "C" { | |||
|
23 | #include "bitmanipulation.h" | |||
|
24 | #include "mpatch.h" | |||
|
25 | ||||
|
26 | struct mpatchbin { | |||
|
27 | std::unique_ptr<char[]> data; | |||
|
28 | size_t len; | |||
|
29 | }; | |||
|
30 | ||||
|
31 | static mpatch_flist *getitem(void *vbins, ssize_t pos) | |||
|
32 | { | |||
|
33 | std::vector<mpatchbin> *bins = (std::vector<mpatchbin> *)vbins; | |||
|
34 | const mpatchbin &bin = bins->at(pos + 1); | |||
|
35 | struct mpatch_flist *res; | |||
|
36 | LOG(2) << "mpatch_decode " << bin.len << std::endl; | |||
|
37 | if (mpatch_decode(bin.data.get(), bin.len, &res) < 0) | |||
|
38 | return NULL; | |||
|
39 | return res; | |||
|
40 | } | |||
|
41 | ||||
|
42 | // input format: | |||
|
43 | // u8 number of inputs | |||
|
44 | // one u16 for each input, its length | |||
|
45 | // the inputs | |||
|
46 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) | |||
|
47 | { | |||
|
48 | if (!Size) { | |||
|
49 | return 0; | |||
|
50 | } | |||
|
51 | // First byte of data is how many texts we expect, first text | |||
|
52 | // being the base the rest being the deltas. | |||
|
53 | ssize_t numtexts = Data[0]; | |||
|
54 | if (numtexts < 2) { | |||
|
55 | // No point if we don't have at least a base text and a delta... | |||
|
56 | return 0; | |||
|
57 | } | |||
|
58 | // Each text will be described by a byte for how long it | |||
|
59 | // should be, so give up if we don't have enough. | |||
|
60 | if ((Size - 1) < (numtexts * 2)) { | |||
|
61 | return 0; | |||
|
62 | } | |||
|
63 | size_t consumed = 1 + (numtexts * 2); | |||
|
64 | LOG(2) << "input contains " << Size << std::endl; | |||
|
65 | LOG(2) << numtexts << " texts, consuming " << consumed << std::endl; | |||
|
66 | std::vector<mpatchbin> bins; | |||
|
67 | bins.reserve(numtexts); | |||
|
68 | for (int i = 0; i < numtexts; ++i) { | |||
|
69 | mpatchbin bin; | |||
|
70 | size_t nthsize = getbeuint16((char *)Data + 1 + (2 * i)); | |||
|
71 | LOG(2) << "text " << i << " is " << nthsize << std::endl; | |||
|
72 | char *start = (char *)Data + consumed; | |||
|
73 | consumed += nthsize; | |||
|
74 | if (consumed > Size) { | |||
|
75 | LOG(2) << "ran out of data, consumed " << consumed | |||
|
76 | << " of " << Size << std::endl; | |||
|
77 | return 0; | |||
|
78 | } | |||
|
79 | bin.len = nthsize; | |||
|
80 | bin.data.reset(new char[nthsize]); | |||
|
81 | memcpy(bin.data.get(), start, nthsize); | |||
|
82 | bins.push_back(std::move(bin)); | |||
|
83 | } | |||
|
84 | LOG(2) << "mpatch_flist" << std::endl; | |||
|
85 | struct mpatch_flist *patch = | |||
|
86 | mpatch_fold(&bins, getitem, 0, numtexts - 1); | |||
|
87 | if (!patch) { | |||
|
88 | return 0; | |||
|
89 | } | |||
|
90 | LOG(2) << "mpatch_calcsize" << std::endl; | |||
|
91 | ssize_t outlen = mpatch_calcsize(bins[0].len, patch); | |||
|
92 | LOG(2) << "outlen " << outlen << std::endl; | |||
|
93 | if (outlen < 0 || outlen > MAX_OUTPUT_SIZE) { | |||
|
94 | goto cleanup; | |||
|
95 | } | |||
|
96 | { | |||
|
97 | char *dest = (char *)malloc(outlen); | |||
|
98 | LOG(2) << "expecting " << outlen << " total bytes at " | |||
|
99 | << (void *)dest << std::endl; | |||
|
100 | mpatch_apply(dest, bins[0].data.get(), bins[0].len, patch); | |||
|
101 | free(dest); | |||
|
102 | LOG(1) << "applied a complete patch" << std::endl; | |||
|
103 | } | |||
|
104 | cleanup: | |||
|
105 | mpatch_lfree(patch); | |||
|
106 | return 0; | |||
|
107 | } | |||
|
108 | ||||
|
109 | #ifdef HG_FUZZER_INCLUDE_MAIN | |||
|
110 | int main(int argc, char **argv) | |||
|
111 | { | |||
|
112 | // One text, one patch. | |||
|
113 | const char data[] = "\x02\x00\0x1\x00\x0d" | |||
|
114 | // base text | |||
|
115 | "a" | |||
|
116 | // binary delta that will append a single b | |||
|
117 | "\x00\x00\x00\x01\x00\x00\x00\x01\x00\x00\x00\x01b"; | |||
|
118 | return LLVMFuzzerTestOneInput((const uint8_t *)data, 19); | |||
|
119 | } | |||
|
120 | #endif | |||
|
121 | ||||
|
122 | } // extern "C" |
@@ -0,0 +1,345 b'' | |||||
|
1 | from __future__ import absolute_import, print_function | |||
|
2 | ||||
|
3 | import argparse | |||
|
4 | import struct | |||
|
5 | import zipfile | |||
|
6 | ||||
|
7 | from mercurial import ( | |||
|
8 | hg, | |||
|
9 | ui as uimod, | |||
|
10 | ) | |||
|
11 | ||||
|
12 | ap = argparse.ArgumentParser() | |||
|
13 | ap.add_argument("out", metavar="some.zip", type=str, nargs=1) | |||
|
14 | args = ap.parse_args() | |||
|
15 | ||||
|
16 | class deltafrag(object): | |||
|
17 | def __init__(self, start, end, data): | |||
|
18 | self.start = start | |||
|
19 | self.end = end | |||
|
20 | self.data = data | |||
|
21 | ||||
|
22 | def __str__(self): | |||
|
23 | return struct.pack( | |||
|
24 | ">lll", self.start, self.end, len(self.data)) + self.data | |||
|
25 | ||||
|
26 | class delta(object): | |||
|
27 | def __init__(self, frags): | |||
|
28 | self.frags = frags | |||
|
29 | ||||
|
30 | def __str__(self): | |||
|
31 | return ''.join(str(f) for f in self.frags) | |||
|
32 | ||||
|
33 | class corpus(object): | |||
|
34 | ||||
|
35 | def __init__(self, base, deltas): | |||
|
36 | self.base = base | |||
|
37 | self.deltas = deltas | |||
|
38 | ||||
|
39 | def __str__(self): | |||
|
40 | deltas = [str(d) for d in self.deltas] | |||
|
41 | parts = ( | |||
|
42 | [ | |||
|
43 | struct.pack(">B", len(deltas) + 1), | |||
|
44 | struct.pack(">H", len(self.base)), | |||
|
45 | ] | |||
|
46 | + [struct.pack(">H", len(d)) for d in deltas] | |||
|
47 | + [self.base] | |||
|
48 | + deltas | |||
|
49 | ) | |||
|
50 | return "".join(parts) | |||
|
51 | ||||
|
52 | with zipfile.ZipFile(args.out[0], "w", zipfile.ZIP_STORED) as zf: | |||
|
53 | # Manually constructed entries | |||
|
54 | zf.writestr( | |||
|
55 | "one_delta_applies", | |||
|
56 | str(corpus('a', [delta([deltafrag(0, 1, 'b')])])) | |||
|
57 | ) | |||
|
58 | zf.writestr( | |||
|
59 | "one_delta_starts_late", | |||
|
60 | str(corpus('a', [delta([deltafrag(3, 1, 'b')])])) | |||
|
61 | ) | |||
|
62 | zf.writestr( | |||
|
63 | "one_delta_ends_late", | |||
|
64 | str(corpus('a', [delta([deltafrag(0, 20, 'b')])])) | |||
|
65 | ) | |||
|
66 | ||||
|
67 | try: | |||
|
68 | # Generated from repo data | |||
|
69 | r = hg.repository(uimod.ui(), '../..') | |||
|
70 | fl = r.file('mercurial/manifest.py') | |||
|
71 | rl = getattr(fl, '_revlog', fl) | |||
|
72 | bins = rl._chunks(rl._deltachain(10)[0]) | |||
|
73 | zf.writestr('manifest_py_rev_10', | |||
|
74 | str(corpus(bins[0], bins[1:]))) | |||
|
75 | except: # skip this, so no re-raises | |||
|
76 | print('skipping seed file from repo data') | |||
|
77 | # Automatically discovered by running the fuzzer | |||
|
78 | zf.writestr( | |||
|
79 | "mpatch_decode_old_overread", "\x02\x00\x00\x00\x02\x00\x00\x00" | |||
|
80 | ) | |||
|
81 | # https://bugs.chromium.org/p/oss-fuzz/issues/detail?id=8876 | |||
|
82 | zf.writestr( | |||
|
83 | "mpatch_ossfuzz_getbe32_ubsan", | |||
|
84 | "\x02\x00\x00\x00\x0c \xff\xff\xff\xff ") | |||
|
85 | zf.writestr( | |||
|
86 | "mpatch_apply_over_memcpy", | |||
|
87 | '\x13\x01\x00\x05\xd0\x00\x00\x00\x00\x00\x00\x00\x00\n \x00\x00\x00' | |||
|
88 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
89 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xff\x00\x00\x00\x00\x00' | |||
|
90 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
91 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
92 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
93 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
94 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
95 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
96 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
97 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
98 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
99 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
100 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
101 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
102 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
103 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
104 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
105 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
106 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
107 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
108 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
109 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
110 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
111 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
112 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
113 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
114 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
115 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
116 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
117 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x8c\x00\x00\x00\x00' | |||
|
118 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
119 | '\x00\x00\x00\x00\x00\x00\x00\x00)\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
120 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
121 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
122 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
123 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
124 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
125 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
126 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
127 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
128 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
129 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
130 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
131 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
132 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
133 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
134 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
135 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
136 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
137 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
138 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
139 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
140 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
141 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
142 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
143 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
144 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
145 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
146 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
147 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
148 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
149 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
150 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
151 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
152 | '\x00\x00\x00\x00\x00\x00\x00\x00\x05\x00\x00\x00A\x00\x00\x00\x00' | |||
|
153 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
154 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
155 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
156 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
157 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
158 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
159 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
160 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
161 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
162 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
163 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
164 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
165 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
166 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
167 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
168 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
169 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
170 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
171 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
172 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
173 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
174 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
175 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
176 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
177 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x94\x18' | |||
|
178 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
179 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
180 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
181 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
182 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
183 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
184 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
185 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
186 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
187 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
188 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
189 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
190 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
191 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
192 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
193 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
194 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
195 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
196 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
197 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
198 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
199 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
200 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
201 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
202 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
203 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
204 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
205 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
206 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
207 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
208 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
209 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
210 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
211 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
212 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
213 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
214 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
215 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
216 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
217 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
218 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
219 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
220 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
221 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
222 | '\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
223 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
224 | '\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfa\x00\x00\x00\x00\x00\x00\x00' | |||
|
225 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
226 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
227 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
228 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
229 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
230 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
231 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
232 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
233 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
234 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
235 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
236 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
237 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
238 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
239 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
240 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
241 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
242 | '\x00\x00\x94\x18\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
243 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
244 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
245 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
246 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
247 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
248 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
249 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
250 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
251 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
252 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
253 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
254 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
255 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
256 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
257 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
258 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
259 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
260 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
261 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
262 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
263 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
264 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
265 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
266 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
267 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
268 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
269 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
270 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
271 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
272 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
273 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
274 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
275 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
276 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
277 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
278 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
279 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
280 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
281 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
282 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
283 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
284 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
285 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
286 | '\x00\x00\x00\x00\x00\x03\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
287 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
288 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xff\xfa\x00\x00\x00' | |||
|
289 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
290 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
291 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
292 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
293 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
294 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
295 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
296 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
297 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
298 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
299 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
300 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
301 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
302 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
303 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
304 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
305 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
306 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
307 | '\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
308 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
309 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
310 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
311 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
312 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
313 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
314 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
315 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
316 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
317 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
318 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
319 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
320 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
321 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
322 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x13\x00\x00\x00\x00\x00\x00' | |||
|
323 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
324 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
325 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
326 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
327 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00]\x00\x00' | |||
|
328 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
329 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
330 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
331 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
332 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
333 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
334 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
335 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
336 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
337 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
338 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
339 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
340 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
341 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
342 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
343 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00se\x00\x00' | |||
|
344 | '\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00' | |||
|
345 | '\x00\x00\x00\x00') |
@@ -0,0 +1,58 b'' | |||||
|
1 | /* | |||
|
2 | * xdiff.cc - fuzzer harness for thirdparty/xdiff | |||
|
3 | * | |||
|
4 | * Copyright 2018, Google Inc. | |||
|
5 | * | |||
|
6 | * This software may be used and distributed according to the terms of | |||
|
7 | * the GNU General Public License, incorporated herein by reference. | |||
|
8 | */ | |||
|
9 | #include "thirdparty/xdiff/xdiff.h" | |||
|
10 | #include <inttypes.h> | |||
|
11 | #include <stdlib.h> | |||
|
12 | ||||
|
13 | #include "fuzzutil.h" | |||
|
14 | ||||
|
15 | extern "C" { | |||
|
16 | ||||
|
17 | int hunk_consumer(long a1, long a2, long b1, long b2, void *priv) | |||
|
18 | { | |||
|
19 | // TODO: probably also test returning -1 from this when things break? | |||
|
20 | return 0; | |||
|
21 | } | |||
|
22 | ||||
|
23 | int LLVMFuzzerTestOneInput(const uint8_t *Data, size_t Size) | |||
|
24 | { | |||
|
25 | auto maybe_inputs = SplitInputs(Data, Size); | |||
|
26 | if (!maybe_inputs) { | |||
|
27 | return 0; | |||
|
28 | } | |||
|
29 | auto inputs = std::move(maybe_inputs.value()); | |||
|
30 | mmfile_t a, b; | |||
|
31 | ||||
|
32 | a.ptr = inputs.left.get(); | |||
|
33 | a.size = inputs.left_size; | |||
|
34 | b.ptr = inputs.right.get(); | |||
|
35 | b.size = inputs.right_size; | |||
|
36 | xpparam_t xpp = { | |||
|
37 | XDF_INDENT_HEURISTIC, /* flags */ | |||
|
38 | }; | |||
|
39 | xdemitconf_t xecfg = { | |||
|
40 | XDL_EMIT_BDIFFHUNK, /* flags */ | |||
|
41 | hunk_consumer, /* hunk_consume_func */ | |||
|
42 | }; | |||
|
43 | xdemitcb_t ecb = { | |||
|
44 | NULL, /* priv */ | |||
|
45 | }; | |||
|
46 | xdl_diff(&a, &b, &xpp, &xecfg, &ecb); | |||
|
47 | return 0; // Non-zero return values are reserved for future use. | |||
|
48 | } | |||
|
49 | ||||
|
50 | #ifdef HG_FUZZER_INCLUDE_MAIN | |||
|
51 | int main(int argc, char **argv) | |||
|
52 | { | |||
|
53 | const char data[] = "asdf"; | |||
|
54 | return LLVMFuzzerTestOneInput((const uint8_t *)data, 4); | |||
|
55 | } | |||
|
56 | #endif | |||
|
57 | ||||
|
58 | } // extern "C" |
@@ -0,0 +1,130 b'' | |||||
|
1 | #!/usr/bin/env python2 | |||
|
2 | from __future__ import absolute_import, print_function | |||
|
3 | ||||
|
4 | import argparse | |||
|
5 | import json | |||
|
6 | import os | |||
|
7 | import subprocess | |||
|
8 | import sys | |||
|
9 | ||||
|
10 | # Always load hg libraries from the hg we can find on $PATH. | |||
|
11 | hglib = json.loads(subprocess.check_output( | |||
|
12 | ['hg', 'debuginstall', '-Tjson']))[0]['hgmodules'] | |||
|
13 | sys.path.insert(0, os.path.dirname(hglib)) | |||
|
14 | ||||
|
15 | from mercurial import util | |||
|
16 | ||||
|
17 | ap = argparse.ArgumentParser() | |||
|
18 | ap.add_argument('--paranoid', | |||
|
19 | action='store_true', | |||
|
20 | help=("Be paranoid about how version numbers compare and " | |||
|
21 | "produce something that's more likely to sort " | |||
|
22 | "reasonably.")) | |||
|
23 | ap.add_argument('--selftest', action='store_true', help='Run self-tests.') | |||
|
24 | ap.add_argument('versionfile', help='Path to a valid mercurial __version__.py') | |||
|
25 | ||||
|
26 | def paranoidver(ver): | |||
|
27 | """Given an hg version produce something that distutils can sort. | |||
|
28 | ||||
|
29 | Some Mac package management systems use distutils code in order to | |||
|
30 | figure out upgrades, which makes life difficult. The test case is | |||
|
31 | a reduced version of code in the Munki tool used by some large | |||
|
32 | organizations to centrally manage OS X packages, which is what | |||
|
33 | inspired this kludge. | |||
|
34 | ||||
|
35 | >>> paranoidver('3.4') | |||
|
36 | '3.4.0' | |||
|
37 | >>> paranoidver('3.4.2') | |||
|
38 | '3.4.2' | |||
|
39 | >>> paranoidver('3.0-rc+10') | |||
|
40 | '2.9.9999-rc+10' | |||
|
41 | >>> paranoidver('4.2+483-5d44d7d4076e') | |||
|
42 | '4.2.0+483-5d44d7d4076e' | |||
|
43 | >>> paranoidver('4.2.1+598-48d1e1214d8c') | |||
|
44 | '4.2.1+598-48d1e1214d8c' | |||
|
45 | >>> paranoidver('4.3-rc') | |||
|
46 | '4.2.9999-rc' | |||
|
47 | >>> paranoidver('4.3') | |||
|
48 | '4.3.0' | |||
|
49 | >>> from distutils import version | |||
|
50 | >>> class LossyPaddedVersion(version.LooseVersion): | |||
|
51 | ... '''Subclass version.LooseVersion to compare things like | |||
|
52 | ... "10.6" and "10.6.0" as equal''' | |||
|
53 | ... def __init__(self, s): | |||
|
54 | ... self.parse(s) | |||
|
55 | ... | |||
|
56 | ... def _pad(self, version_list, max_length): | |||
|
57 | ... 'Pad a version list by adding extra 0 components to the end' | |||
|
58 | ... # copy the version_list so we don't modify it | |||
|
59 | ... cmp_list = list(version_list) | |||
|
60 | ... while len(cmp_list) < max_length: | |||
|
61 | ... cmp_list.append(0) | |||
|
62 | ... return cmp_list | |||
|
63 | ... | |||
|
64 | ... def __cmp__(self, other): | |||
|
65 | ... if isinstance(other, str): | |||
|
66 | ... other = MunkiLooseVersion(other) | |||
|
67 | ... max_length = max(len(self.version), len(other.version)) | |||
|
68 | ... self_cmp_version = self._pad(self.version, max_length) | |||
|
69 | ... other_cmp_version = self._pad(other.version, max_length) | |||
|
70 | ... return cmp(self_cmp_version, other_cmp_version) | |||
|
71 | >>> def testver(older, newer): | |||
|
72 | ... o = LossyPaddedVersion(paranoidver(older)) | |||
|
73 | ... n = LossyPaddedVersion(paranoidver(newer)) | |||
|
74 | ... return o < n | |||
|
75 | >>> testver('3.4', '3.5') | |||
|
76 | True | |||
|
77 | >>> testver('3.4.0', '3.5-rc') | |||
|
78 | True | |||
|
79 | >>> testver('3.4-rc', '3.5') | |||
|
80 | True | |||
|
81 | >>> testver('3.4-rc+10-deadbeef', '3.5') | |||
|
82 | True | |||
|
83 | >>> testver('3.4.2', '3.5-rc') | |||
|
84 | True | |||
|
85 | >>> testver('3.4.2', '3.5-rc+10-deadbeef') | |||
|
86 | True | |||
|
87 | >>> testver('4.2+483-5d44d7d4076e', '4.2.1+598-48d1e1214d8c') | |||
|
88 | True | |||
|
89 | >>> testver('4.3-rc', '4.3') | |||
|
90 | True | |||
|
91 | >>> testver('4.3', '4.3-rc') | |||
|
92 | False | |||
|
93 | """ | |||
|
94 | major, minor, micro, extra = util.versiontuple(ver, n=4) | |||
|
95 | if micro is None: | |||
|
96 | micro = 0 | |||
|
97 | if extra: | |||
|
98 | if extra.startswith('rc'): | |||
|
99 | if minor == 0: | |||
|
100 | major -= 1 | |||
|
101 | minor = 9 | |||
|
102 | else: | |||
|
103 | minor -= 1 | |||
|
104 | micro = 9999 | |||
|
105 | extra = '-' + extra | |||
|
106 | else: | |||
|
107 | extra = '+' + extra | |||
|
108 | else: | |||
|
109 | extra = '' | |||
|
110 | return '%d.%d.%d%s' % (major, minor, micro, extra) | |||
|
111 | ||||
|
112 | def main(argv): | |||
|
113 | opts = ap.parse_args(argv[1:]) | |||
|
114 | if opts.selftest: | |||
|
115 | import doctest | |||
|
116 | doctest.testmod() | |||
|
117 | return | |||
|
118 | with open(opts.versionfile) as f: | |||
|
119 | for l in f: | |||
|
120 | if l.startswith('version = b'): | |||
|
121 | # version number is entire line minus the quotes | |||
|
122 | ver = l[len('version = b') + 1:-2] | |||
|
123 | break | |||
|
124 | if opts.paranoid: | |||
|
125 | print(paranoidver(ver)) | |||
|
126 | else: | |||
|
127 | print(ver) | |||
|
128 | ||||
|
129 | if __name__ == '__main__': | |||
|
130 | main(sys.argv) |
@@ -0,0 +1,97 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | # | |||
|
3 | # Copyright 2005-2007 by Intevation GmbH <intevation@intevation.de> | |||
|
4 | # | |||
|
5 | # Author(s): | |||
|
6 | # Thomas Arendsen Hein <thomas@intevation.de> | |||
|
7 | # | |||
|
8 | # This software may be used and distributed according to the terms of the | |||
|
9 | # GNU General Public License version 2 or any later version. | |||
|
10 | ||||
|
11 | """ | |||
|
12 | hg-ssh - a wrapper for ssh access to a limited set of mercurial repos | |||
|
13 | ||||
|
14 | To be used in ~/.ssh/authorized_keys with the "command" option, see sshd(8): | |||
|
15 | command="hg-ssh path/to/repo1 /path/to/repo2 ~/repo3 ~user/repo4" ssh-dss ... | |||
|
16 | (probably together with these other useful options: | |||
|
17 | no-port-forwarding,no-X11-forwarding,no-agent-forwarding) | |||
|
18 | ||||
|
19 | This allows pull/push over ssh from/to the repositories given as arguments. | |||
|
20 | ||||
|
21 | If all your repositories are subdirectories of a common directory, you can | |||
|
22 | allow shorter paths with: | |||
|
23 | command="cd path/to/my/repositories && hg-ssh repo1 subdir/repo2" | |||
|
24 | ||||
|
25 | You can use pattern matching of your normal shell, e.g.: | |||
|
26 | command="cd repos && hg-ssh user/thomas/* projects/{mercurial,foo}" | |||
|
27 | ||||
|
28 | You can also add a --read-only flag to allow read-only access to a key, e.g.: | |||
|
29 | command="hg-ssh --read-only repos/*" | |||
|
30 | """ | |||
|
31 | from __future__ import absolute_import | |||
|
32 | ||||
|
33 | import os | |||
|
34 | import shlex | |||
|
35 | import sys | |||
|
36 | ||||
|
37 | # enable importing on demand to reduce startup time | |||
|
38 | import hgdemandimport ; hgdemandimport.enable() | |||
|
39 | ||||
|
40 | from mercurial import ( | |||
|
41 | dispatch, | |||
|
42 | pycompat, | |||
|
43 | ui as uimod, | |||
|
44 | ) | |||
|
45 | ||||
|
46 | def main(): | |||
|
47 | # Prevent insertion/deletion of CRs | |||
|
48 | dispatch.initstdio() | |||
|
49 | ||||
|
50 | cwd = os.getcwd() | |||
|
51 | readonly = False | |||
|
52 | args = sys.argv[1:] | |||
|
53 | while len(args): | |||
|
54 | if args[0] == '--read-only': | |||
|
55 | readonly = True | |||
|
56 | args.pop(0) | |||
|
57 | else: | |||
|
58 | break | |||
|
59 | allowed_paths = [os.path.normpath(os.path.join(cwd, | |||
|
60 | os.path.expanduser(path))) | |||
|
61 | for path in args] | |||
|
62 | orig_cmd = os.getenv('SSH_ORIGINAL_COMMAND', '?') | |||
|
63 | try: | |||
|
64 | cmdargv = shlex.split(orig_cmd) | |||
|
65 | except ValueError as e: | |||
|
66 | sys.stderr.write('Illegal command "%s": %s\n' % (orig_cmd, e)) | |||
|
67 | sys.exit(255) | |||
|
68 | ||||
|
69 | if cmdargv[:2] == ['hg', '-R'] and cmdargv[3:] == ['serve', '--stdio']: | |||
|
70 | path = cmdargv[2] | |||
|
71 | repo = os.path.normpath(os.path.join(cwd, os.path.expanduser(path))) | |||
|
72 | if repo in allowed_paths: | |||
|
73 | cmd = [b'-R', pycompat.fsencode(repo), b'serve', b'--stdio'] | |||
|
74 | req = dispatch.request(cmd) | |||
|
75 | if readonly: | |||
|
76 | if not req.ui: | |||
|
77 | req.ui = uimod.ui.load() | |||
|
78 | req.ui.setconfig(b'hooks', b'pretxnopen.hg-ssh', | |||
|
79 | b'python:__main__.rejectpush', b'hg-ssh') | |||
|
80 | req.ui.setconfig(b'hooks', b'prepushkey.hg-ssh', | |||
|
81 | b'python:__main__.rejectpush', b'hg-ssh') | |||
|
82 | dispatch.dispatch(req) | |||
|
83 | else: | |||
|
84 | sys.stderr.write('Illegal repository "%s"\n' % repo) | |||
|
85 | sys.exit(255) | |||
|
86 | else: | |||
|
87 | sys.stderr.write('Illegal command "%s"\n' % orig_cmd) | |||
|
88 | sys.exit(255) | |||
|
89 | ||||
|
90 | def rejectpush(ui, **kwargs): | |||
|
91 | ui.warn((b"Permission denied\n")) | |||
|
92 | # mercurial hooks use unix process conventions for hook return values | |||
|
93 | # so a truthy return means failure | |||
|
94 | return True | |||
|
95 | ||||
|
96 | if __name__ == '__main__': | |||
|
97 | main() |
@@ -0,0 +1,56 b'' | |||||
|
1 | ;; hg-test-mode.el - Major mode for editing Mercurial tests | |||
|
2 | ;; | |||
|
3 | ;; Copyright 2014 Matt Mackall <mpm@selenic.com> | |||
|
4 | ;; "I have no idea what I'm doing" | |||
|
5 | ;; | |||
|
6 | ;; This software may be used and distributed according to the terms of the | |||
|
7 | ;; GNU General Public License version 2 or any later version. | |||
|
8 | ;; | |||
|
9 | ;; To enable, add something like the following to your .emacs: | |||
|
10 | ;; | |||
|
11 | ;; (if (file-exists-p "~/hg/contrib/hg-test-mode.el") | |||
|
12 | ;; (load "~/hg/contrib/hg-test-mode.el")) | |||
|
13 | ||||
|
14 | (defvar hg-test-mode-hook nil) | |||
|
15 | ||||
|
16 | (defvar hg-test-mode-map | |||
|
17 | (let ((map (make-keymap))) | |||
|
18 | (define-key map "\C-j" 'newline-and-indent) | |||
|
19 | map) | |||
|
20 | "Keymap for hg test major mode") | |||
|
21 | ||||
|
22 | (add-to-list 'auto-mode-alist '("\\.t\\'" . hg-test-mode)) | |||
|
23 | ||||
|
24 | (defconst hg-test-font-lock-keywords-1 | |||
|
25 | (list | |||
|
26 | '("^ \\(\\$\\|>>>\\) " 1 font-lock-builtin-face) | |||
|
27 | '("^ \\(>\\|\\.\\.\\.\\) " 1 font-lock-constant-face) | |||
|
28 | '("^ \\([[][0-9]+[]]\\)$" 1 font-lock-warning-face) | |||
|
29 | '("^ \\(.*?\\)\\(\\( [(][-a-z]+[)]\\)*\\)$" 1 font-lock-string-face) | |||
|
30 | '("\\$?\\(HG\\|TEST\\)\\w+=?" . font-lock-variable-name-face) | |||
|
31 | '("^ \\(.*?\\)\\(\\( [(][-a-z]+[)]\\)+\\)$" 2 font-lock-type-face) | |||
|
32 | '("^#.*" . font-lock-preprocessor-face) | |||
|
33 | '("^\\([^ ].*\\)$" 1 font-lock-comment-face) | |||
|
34 | ) | |||
|
35 | "Minimal highlighting expressions for hg-test mode") | |||
|
36 | ||||
|
37 | (defvar hg-test-font-lock-keywords hg-test-font-lock-keywords-1 | |||
|
38 | "Default highlighting expressions for hg-test mode") | |||
|
39 | ||||
|
40 | (defvar hg-test-mode-syntax-table | |||
|
41 | (let ((st (make-syntax-table))) | |||
|
42 | (modify-syntax-entry ?\" "w" st) ;; disable standard quoting | |||
|
43 | st) | |||
|
44 | "Syntax table for hg-test mode") | |||
|
45 | ||||
|
46 | (defun hg-test-mode () | |||
|
47 | (interactive) | |||
|
48 | (kill-all-local-variables) | |||
|
49 | (use-local-map hg-test-mode-map) | |||
|
50 | (set-syntax-table hg-test-mode-syntax-table) | |||
|
51 | (set (make-local-variable 'font-lock-defaults) '(hg-test-font-lock-keywords)) | |||
|
52 | (setq major-mode 'hg-test-mode) | |||
|
53 | (setq mode-name "hg-test") | |||
|
54 | (run-hooks 'hg-test-mode-hook)) | |||
|
55 | ||||
|
56 | (provide 'hg-test-mode) |
@@ -0,0 +1,123 b'' | |||||
|
1 | # A minimal client for Mercurial's command server | |||
|
2 | ||||
|
3 | from __future__ import absolute_import, print_function | |||
|
4 | import os | |||
|
5 | import signal | |||
|
6 | import socket | |||
|
7 | import struct | |||
|
8 | import subprocess | |||
|
9 | import sys | |||
|
10 | import time | |||
|
11 | ||||
|
12 | try: | |||
|
13 | import cStringIO as io | |||
|
14 | stringio = io.StringIO | |||
|
15 | except ImportError: | |||
|
16 | import io | |||
|
17 | stringio = io.StringIO | |||
|
18 | ||||
|
19 | def connectpipe(path=None): | |||
|
20 | cmdline = ['hg', 'serve', '--cmdserver', 'pipe'] | |||
|
21 | if path: | |||
|
22 | cmdline += ['-R', path] | |||
|
23 | ||||
|
24 | server = subprocess.Popen(cmdline, stdin=subprocess.PIPE, | |||
|
25 | stdout=subprocess.PIPE) | |||
|
26 | ||||
|
27 | return server | |||
|
28 | ||||
|
29 | class unixconnection(object): | |||
|
30 | def __init__(self, sockpath): | |||
|
31 | self.sock = sock = socket.socket(socket.AF_UNIX) | |||
|
32 | sock.connect(sockpath) | |||
|
33 | self.stdin = sock.makefile('wb') | |||
|
34 | self.stdout = sock.makefile('rb') | |||
|
35 | ||||
|
36 | def wait(self): | |||
|
37 | self.stdin.close() | |||
|
38 | self.stdout.close() | |||
|
39 | self.sock.close() | |||
|
40 | ||||
|
41 | class unixserver(object): | |||
|
42 | def __init__(self, sockpath, logpath=None, repopath=None): | |||
|
43 | self.sockpath = sockpath | |||
|
44 | cmdline = ['hg', 'serve', '--cmdserver', 'unix', '-a', sockpath] | |||
|
45 | if repopath: | |||
|
46 | cmdline += ['-R', repopath] | |||
|
47 | if logpath: | |||
|
48 | stdout = open(logpath, 'a') | |||
|
49 | stderr = subprocess.STDOUT | |||
|
50 | else: | |||
|
51 | stdout = stderr = None | |||
|
52 | self.server = subprocess.Popen(cmdline, stdout=stdout, stderr=stderr) | |||
|
53 | # wait for listen() | |||
|
54 | while self.server.poll() is None: | |||
|
55 | if os.path.exists(sockpath): | |||
|
56 | break | |||
|
57 | time.sleep(0.1) | |||
|
58 | ||||
|
59 | def connect(self): | |||
|
60 | return unixconnection(self.sockpath) | |||
|
61 | ||||
|
62 | def shutdown(self): | |||
|
63 | os.kill(self.server.pid, signal.SIGTERM) | |||
|
64 | self.server.wait() | |||
|
65 | ||||
|
66 | def writeblock(server, data): | |||
|
67 | server.stdin.write(struct.pack('>I', len(data))) | |||
|
68 | server.stdin.write(data) | |||
|
69 | server.stdin.flush() | |||
|
70 | ||||
|
71 | def readchannel(server): | |||
|
72 | data = server.stdout.read(5) | |||
|
73 | if not data: | |||
|
74 | raise EOFError | |||
|
75 | channel, length = struct.unpack('>cI', data) | |||
|
76 | if channel in 'IL': | |||
|
77 | return channel, length | |||
|
78 | else: | |||
|
79 | return channel, server.stdout.read(length) | |||
|
80 | ||||
|
81 | def sep(text): | |||
|
82 | return text.replace('\\', '/') | |||
|
83 | ||||
|
84 | def runcommand(server, args, output=sys.stdout, error=sys.stderr, input=None, | |||
|
85 | outfilter=lambda x: x): | |||
|
86 | print('*** runcommand', ' '.join(args)) | |||
|
87 | sys.stdout.flush() | |||
|
88 | server.stdin.write('runcommand\n') | |||
|
89 | writeblock(server, '\0'.join(args)) | |||
|
90 | ||||
|
91 | if not input: | |||
|
92 | input = stringio() | |||
|
93 | ||||
|
94 | while True: | |||
|
95 | ch, data = readchannel(server) | |||
|
96 | if ch == 'o': | |||
|
97 | output.write(outfilter(data)) | |||
|
98 | output.flush() | |||
|
99 | elif ch == 'e': | |||
|
100 | error.write(data) | |||
|
101 | error.flush() | |||
|
102 | elif ch == 'I': | |||
|
103 | writeblock(server, input.read(data)) | |||
|
104 | elif ch == 'L': | |||
|
105 | writeblock(server, input.readline(data)) | |||
|
106 | elif ch == 'r': | |||
|
107 | ret, = struct.unpack('>i', data) | |||
|
108 | if ret != 0: | |||
|
109 | print(' [%d]' % ret) | |||
|
110 | return ret | |||
|
111 | else: | |||
|
112 | print("unexpected channel %c: %r" % (ch, data)) | |||
|
113 | if ch.isupper(): | |||
|
114 | return | |||
|
115 | ||||
|
116 | def check(func, connect=connectpipe): | |||
|
117 | sys.stdout.flush() | |||
|
118 | server = connect() | |||
|
119 | try: | |||
|
120 | return func(server) | |||
|
121 | finally: | |||
|
122 | server.stdin.close() | |||
|
123 | server.wait() |
This diff has been collapsed as it changes many lines, (4155 lines changed) Show them Hide them | |||||
@@ -0,0 +1,4155 b'' | |||||
|
1 | #!/usr/bin/env wish | |||
|
2 | ||||
|
3 | # Copyright (C) 2005 Paul Mackerras. All rights reserved. | |||
|
4 | # This program is free software; it may be used, copied, modified | |||
|
5 | # and distributed under the terms of the GNU General Public Licence, | |||
|
6 | # either version 2, or (at your option) any later version. | |||
|
7 | # | |||
|
8 | # See hgk.py for extension usage and configuration. | |||
|
9 | ||||
|
10 | ||||
|
11 | # Modified version of Tip 171: | |||
|
12 | # http://www.tcl.tk/cgi-bin/tct/tip/171.html | |||
|
13 | # | |||
|
14 | # The in_mousewheel global was added to fix strange reentrancy issues. | |||
|
15 | # The whole snipped is activated only under windows, mouse wheel | |||
|
16 | # bindings working already under MacOSX and Linux. | |||
|
17 | ||||
|
18 | if {[catch {package require Ttk}]} { | |||
|
19 | # use a shim | |||
|
20 | namespace eval ttk { | |||
|
21 | proc style args {} | |||
|
22 | ||||
|
23 | proc entry args { | |||
|
24 | eval [linsert $args 0 ::entry] -relief flat | |||
|
25 | } | |||
|
26 | } | |||
|
27 | ||||
|
28 | interp alias {} ttk::button {} button | |||
|
29 | interp alias {} ttk::frame {} frame | |||
|
30 | interp alias {} ttk::label {} label | |||
|
31 | interp alias {} ttk::scrollbar {} scrollbar | |||
|
32 | interp alias {} ttk::optionMenu {} tk_optionMenu | |||
|
33 | ||||
|
34 | proc updatepalette {} {} | |||
|
35 | } else { | |||
|
36 | proc ::ttk::optionMenu {w varName firstValue args} { | |||
|
37 | upvar #0 $varName var | |||
|
38 | ||||
|
39 | if {![info exists var]} { | |||
|
40 | set var $firstValue | |||
|
41 | } | |||
|
42 | ttk::menubutton $w -textvariable $varName -menu $w.menu \ | |||
|
43 | -direction flush | |||
|
44 | menu $w.menu -tearoff 0 | |||
|
45 | $w.menu add radiobutton -label $firstValue -variable $varName | |||
|
46 | foreach i $args { | |||
|
47 | $w.menu add radiobutton -label $i -variable $varName | |||
|
48 | } | |||
|
49 | return $w.menu | |||
|
50 | } | |||
|
51 | proc updatepalette {} { | |||
|
52 | catch { | |||
|
53 | tk_setPalette background [ttk::style lookup client -background] | |||
|
54 | } | |||
|
55 | } | |||
|
56 | } | |||
|
57 | ||||
|
58 | if {[tk windowingsystem] eq "win32"} { | |||
|
59 | ||||
|
60 | ttk::style theme use xpnative | |||
|
61 | ||||
|
62 | set mw_classes [list Text Listbox Table TreeCtrl] | |||
|
63 | foreach class $mw_classes { bind $class <MouseWheel> {} } | |||
|
64 | ||||
|
65 | set in_mousewheel 0 | |||
|
66 | ||||
|
67 | proc ::tk::MouseWheel {wFired X Y D {shifted 0}} { | |||
|
68 | global in_mousewheel | |||
|
69 | if { $in_mousewheel != 0 } { return } | |||
|
70 | # Set event to check based on call | |||
|
71 | set evt "<[expr {$shifted?{Shift-}:{}}]MouseWheel>" | |||
|
72 | # do not double-fire in case the class already has a binding | |||
|
73 | if {[bind [winfo class $wFired] $evt] ne ""} { return } | |||
|
74 | # obtain the window the mouse is over | |||
|
75 | set w [winfo containing $X $Y] | |||
|
76 | # if we are outside the app, try and scroll the focus widget | |||
|
77 | if {![winfo exists $w]} { catch {set w [focus]} } | |||
|
78 | if {[winfo exists $w]} { | |||
|
79 | ||||
|
80 | if {[bind $w $evt] ne ""} { | |||
|
81 | # Awkward ... this widget has a MouseWheel binding, but to | |||
|
82 | # trigger successfully in it, we must give it focus. | |||
|
83 | catch {focus} old | |||
|
84 | if {$w ne $old} { focus $w } | |||
|
85 | set in_mousewheel 1 | |||
|
86 | event generate $w $evt -rootx $X -rooty $Y -delta $D | |||
|
87 | set in_mousewheel 0 | |||
|
88 | if {$w ne $old} { focus $old } | |||
|
89 | return | |||
|
90 | } | |||
|
91 | ||||
|
92 | # aqua and x11/win32 have different delta handling | |||
|
93 | if {[tk windowingsystem] ne "aqua"} { | |||
|
94 | set delta [expr {- ($D / 30)}] | |||
|
95 | } else { | |||
|
96 | set delta [expr {- ($D)}] | |||
|
97 | } | |||
|
98 | # scrollbars have different call conventions | |||
|
99 | if {[string match "*Scrollbar" [winfo class $w]]} { | |||
|
100 | catch {tk::ScrollByUnits $w \ | |||
|
101 | [string index [$w cget -orient] 0] $delta} | |||
|
102 | } else { | |||
|
103 | set cmd [list $w [expr {$shifted ? "xview" : "yview"}] \ | |||
|
104 | scroll $delta units] | |||
|
105 | # Walking up to find the proper widget (handles cases like | |||
|
106 | # embedded widgets in a canvas) | |||
|
107 | while {[catch $cmd] && [winfo toplevel $w] ne $w} { | |||
|
108 | set w [winfo parent $w] | |||
|
109 | } | |||
|
110 | } | |||
|
111 | } | |||
|
112 | } | |||
|
113 | ||||
|
114 | bind all <MouseWheel> [list ::tk::MouseWheel %W %X %Y %D 0] | |||
|
115 | ||||
|
116 | # end of win32 section | |||
|
117 | } else { | |||
|
118 | ||||
|
119 | if {[catch { | |||
|
120 | set theme [ttk::style theme use] | |||
|
121 | }]} { | |||
|
122 | set theme $::ttk::currentTheme | |||
|
123 | } | |||
|
124 | if {$theme eq "default"} { | |||
|
125 | ttk::style theme use clam | |||
|
126 | } | |||
|
127 | ||||
|
128 | } | |||
|
129 | ||||
|
130 | updatepalette | |||
|
131 | ||||
|
132 | # Unify right mouse button handling. | |||
|
133 | # See "mouse buttons on macintosh" thread on comp.lang.tcl | |||
|
134 | if {[tk windowingsystem] eq "aqua"} { | |||
|
135 | event add <<B3>> <Control-ButtonPress-1> | |||
|
136 | event add <<B3>> <Button-2> | |||
|
137 | } else { | |||
|
138 | event add <<B3>> <Button-3> | |||
|
139 | } | |||
|
140 | ||||
|
141 | proc gitdir {} { | |||
|
142 | global env | |||
|
143 | if {[info exists env(GIT_DIR)]} { | |||
|
144 | return $env(GIT_DIR) | |||
|
145 | } else { | |||
|
146 | return ".hg" | |||
|
147 | } | |||
|
148 | } | |||
|
149 | ||||
|
150 | proc popupify {w} { | |||
|
151 | wm resizable $w 0 0 | |||
|
152 | wm withdraw $w | |||
|
153 | update | |||
|
154 | set x [expr {([winfo screenwidth .]-[winfo reqwidth $w])/2}] | |||
|
155 | set y [expr {([winfo screenheight .]-[winfo reqheight $w])/2}] | |||
|
156 | wm geometry $w +$x+$y | |||
|
157 | wm transient $w . | |||
|
158 | wm deiconify $w | |||
|
159 | wm resizable $w 1 1 | |||
|
160 | } | |||
|
161 | ||||
|
162 | proc getcommits {rargs} { | |||
|
163 | global commits commfd phase canv mainfont env | |||
|
164 | global startmsecs nextupdate ncmupdate | |||
|
165 | global ctext maincursor textcursor leftover | |||
|
166 | ||||
|
167 | # check that we can find a .git directory somewhere... | |||
|
168 | set gitdir [gitdir] | |||
|
169 | if {![file isdirectory $gitdir]} { | |||
|
170 | error_popup "Cannot find the git directory \"$gitdir\"." | |||
|
171 | exit 1 | |||
|
172 | } | |||
|
173 | set commits {} | |||
|
174 | set phase getcommits | |||
|
175 | set startmsecs [clock clicks -milliseconds] | |||
|
176 | set nextupdate [expr $startmsecs + 100] | |||
|
177 | set ncmupdate 1 | |||
|
178 | set limit 0 | |||
|
179 | set revargs {} | |||
|
180 | set showhidden no | |||
|
181 | for {set i 0} {$i < [llength $rargs]} {incr i} { | |||
|
182 | set opt [lindex $rargs $i] | |||
|
183 | switch -- $opt --limit { | |||
|
184 | incr i | |||
|
185 | set limit [lindex $rargs $i] | |||
|
186 | } --hidden { | |||
|
187 | set showhidden yes | |||
|
188 | } default { | |||
|
189 | lappend revargs $opt | |||
|
190 | } | |||
|
191 | } | |||
|
192 | if [catch { | |||
|
193 | set parse_args [concat tip $revargs] | |||
|
194 | set parse_temp [eval exec {$env(HG)} --config ui.report_untrusted=false log --template '{node}\n' $parse_args] | |||
|
195 | regsub -all "\r\n" $parse_temp "\n" parse_temp | |||
|
196 | set parsed_args [split $parse_temp "\n"] | |||
|
197 | } err] { | |||
|
198 | # if git-rev-parse failed for some reason... | |||
|
199 | if {$rargs == {}} { | |||
|
200 | set revargs HEAD | |||
|
201 | } | |||
|
202 | set parsed_args $revargs | |||
|
203 | } | |||
|
204 | if {$limit > 0} { | |||
|
205 | set parsed_args [concat -n $limit $parsed_args] | |||
|
206 | } | |||
|
207 | if {$showhidden} { | |||
|
208 | append parsed_args --hidden | |||
|
209 | } | |||
|
210 | if [catch { | |||
|
211 | set commfd [open "|{$env(HG)} --config ui.report_untrusted=false debug-rev-list --header --topo-order --parents $parsed_args" r] | |||
|
212 | } err] { | |||
|
213 | puts stderr "Error executing hg debug-rev-list: $err" | |||
|
214 | exit 1 | |||
|
215 | } | |||
|
216 | set leftover {} | |||
|
217 | fconfigure $commfd -blocking 0 -translation lf -eofchar {} | |||
|
218 | fileevent $commfd readable [list getcommitlines $commfd] | |||
|
219 | $canv delete all | |||
|
220 | $canv create text 3 3 -anchor nw -text "Reading commits..." \ | |||
|
221 | -font $mainfont -tags textitems | |||
|
222 | . config -cursor watch | |||
|
223 | settextcursor watch | |||
|
224 | } | |||
|
225 | ||||
|
226 | proc getcommitlines {commfd} { | |||
|
227 | global commits parents cdate children | |||
|
228 | global commitlisted phase commitinfo nextupdate | |||
|
229 | global stopped redisplaying leftover | |||
|
230 | ||||
|
231 | set stuff [read $commfd] | |||
|
232 | if {$stuff == {}} { | |||
|
233 | if {![eof $commfd]} return | |||
|
234 | # set it blocking so we wait for the process to terminate | |||
|
235 | fconfigure $commfd -blocking 1 | |||
|
236 | if {![catch {close $commfd} err]} { | |||
|
237 | after idle finishcommits | |||
|
238 | return | |||
|
239 | } | |||
|
240 | if {[string range $err 0 4] == "usage"} { | |||
|
241 | set err \ | |||
|
242 | {Gitk: error reading commits: bad arguments to git-rev-list. | |||
|
243 | (Note: arguments to gitk are passed to git-rev-list | |||
|
244 | to allow selection of commits to be displayed.)} | |||
|
245 | } else { | |||
|
246 | set err "Error reading commits: $err" | |||
|
247 | } | |||
|
248 | error_popup $err | |||
|
249 | exit 1 | |||
|
250 | } | |||
|
251 | set start 0 | |||
|
252 | while 1 { | |||
|
253 | set i [string first "\0" $stuff $start] | |||
|
254 | if {$i < 0} { | |||
|
255 | append leftover [string range $stuff $start end] | |||
|
256 | return | |||
|
257 | } | |||
|
258 | set cmit [string range $stuff $start [expr {$i - 1}]] | |||
|
259 | if {$start == 0} { | |||
|
260 | set cmit "$leftover$cmit" | |||
|
261 | set leftover {} | |||
|
262 | } | |||
|
263 | set start [expr {$i + 1}] | |||
|
264 | regsub -all "\r\n" $cmit "\n" cmit | |||
|
265 | set j [string first "\n" $cmit] | |||
|
266 | set ok 0 | |||
|
267 | if {$j >= 0} { | |||
|
268 | set ids [string range $cmit 0 [expr {$j - 1}]] | |||
|
269 | set ok 1 | |||
|
270 | foreach id $ids { | |||
|
271 | if {![regexp {^[0-9a-f]{12}$} $id]} { | |||
|
272 | set ok 0 | |||
|
273 | break | |||
|
274 | } | |||
|
275 | } | |||
|
276 | } | |||
|
277 | if {!$ok} { | |||
|
278 | set shortcmit $cmit | |||
|
279 | if {[string length $shortcmit] > 80} { | |||
|
280 | set shortcmit "[string range $shortcmit 0 80]..." | |||
|
281 | } | |||
|
282 | error_popup "Can't parse hg debug-rev-list output: {$shortcmit}" | |||
|
283 | exit 1 | |||
|
284 | } | |||
|
285 | set id [lindex $ids 0] | |||
|
286 | set olds [lrange $ids 1 end] | |||
|
287 | set cmit [string range $cmit [expr {$j + 1}] end] | |||
|
288 | lappend commits $id | |||
|
289 | set commitlisted($id) 1 | |||
|
290 | parsecommit $id $cmit 1 [lrange $ids 1 end] | |||
|
291 | drawcommit $id | |||
|
292 | if {[clock clicks -milliseconds] >= $nextupdate} { | |||
|
293 | doupdate 1 | |||
|
294 | } | |||
|
295 | while {$redisplaying} { | |||
|
296 | set redisplaying 0 | |||
|
297 | if {$stopped == 1} { | |||
|
298 | set stopped 0 | |||
|
299 | set phase "getcommits" | |||
|
300 | foreach id $commits { | |||
|
301 | drawcommit $id | |||
|
302 | if {$stopped} break | |||
|
303 | if {[clock clicks -milliseconds] >= $nextupdate} { | |||
|
304 | doupdate 1 | |||
|
305 | } | |||
|
306 | } | |||
|
307 | } | |||
|
308 | } | |||
|
309 | } | |||
|
310 | } | |||
|
311 | ||||
|
312 | proc doupdate {reading} { | |||
|
313 | global commfd nextupdate numcommits ncmupdate | |||
|
314 | ||||
|
315 | if {$reading} { | |||
|
316 | fileevent $commfd readable {} | |||
|
317 | } | |||
|
318 | update | |||
|
319 | set nextupdate [expr {[clock clicks -milliseconds] + 100}] | |||
|
320 | if {$numcommits < 100} { | |||
|
321 | set ncmupdate [expr {$numcommits + 1}] | |||
|
322 | } elseif {$numcommits < 10000} { | |||
|
323 | set ncmupdate [expr {$numcommits + 10}] | |||
|
324 | } else { | |||
|
325 | set ncmupdate [expr {$numcommits + 100}] | |||
|
326 | } | |||
|
327 | if {$reading} { | |||
|
328 | fileevent $commfd readable [list getcommitlines $commfd] | |||
|
329 | } | |||
|
330 | } | |||
|
331 | ||||
|
332 | proc readcommit {id} { | |||
|
333 | global env | |||
|
334 | if [catch {set contents [exec $env(HG) --config ui.report_untrusted=false debug-cat-file commit $id]}] return | |||
|
335 | parsecommit $id $contents 0 {} | |||
|
336 | } | |||
|
337 | ||||
|
338 | proc parsecommit {id contents listed olds} { | |||
|
339 | global commitinfo children nchildren parents nparents cdate ncleft | |||
|
340 | global firstparents obsolete | |||
|
341 | ||||
|
342 | set inhdr 1 | |||
|
343 | set comment {} | |||
|
344 | set headline {} | |||
|
345 | set auname {} | |||
|
346 | set audate {} | |||
|
347 | set comname {} | |||
|
348 | set comdate {} | |||
|
349 | set rev {} | |||
|
350 | set branch {} | |||
|
351 | set bookmark {} | |||
|
352 | if {![info exists nchildren($id)]} { | |||
|
353 | set children($id) {} | |||
|
354 | set nchildren($id) 0 | |||
|
355 | set ncleft($id) 0 | |||
|
356 | } | |||
|
357 | set parents($id) $olds | |||
|
358 | set nparents($id) [llength $olds] | |||
|
359 | foreach p $olds { | |||
|
360 | if {![info exists nchildren($p)]} { | |||
|
361 | set children($p) [list $id] | |||
|
362 | set nchildren($p) 1 | |||
|
363 | set ncleft($p) 1 | |||
|
364 | } elseif {[lsearch -exact $children($p) $id] < 0} { | |||
|
365 | lappend children($p) $id | |||
|
366 | incr nchildren($p) | |||
|
367 | incr ncleft($p) | |||
|
368 | } | |||
|
369 | } | |||
|
370 | regsub -all "\r\n" $contents "\n" contents | |||
|
371 | foreach line [split $contents "\n"] { | |||
|
372 | if {$inhdr} { | |||
|
373 | set line [split $line] | |||
|
374 | if {$line == {}} { | |||
|
375 | set inhdr 0 | |||
|
376 | } else { | |||
|
377 | set tag [lindex $line 0] | |||
|
378 | switch -- $tag "author" { | |||
|
379 | set x [expr {[llength $line] - 2}] | |||
|
380 | set audate [lindex $line $x] | |||
|
381 | set auname [join [lrange $line 1 [expr {$x - 1}]]] | |||
|
382 | } "committer" { | |||
|
383 | set x [expr {[llength $line] - 2}] | |||
|
384 | set comdate [lindex $line $x] | |||
|
385 | set comname [join [lrange $line 1 [expr {$x - 1}]]] | |||
|
386 | } "revision" { | |||
|
387 | set rev [lindex $line 1] | |||
|
388 | } "branch" { | |||
|
389 | set branch [join [lrange $line 1 end]] | |||
|
390 | } "bookmark" { | |||
|
391 | set bookmark [join [lrange $line 1 end]] | |||
|
392 | } "obsolete" { | |||
|
393 | set obsolete($id) "" | |||
|
394 | } "phase" { | |||
|
395 | set phase [lindex $line 1 end] | |||
|
396 | } | |||
|
397 | } | |||
|
398 | } else { | |||
|
399 | if {$comment == {}} { | |||
|
400 | set headline [string trim $line] | |||
|
401 | } else { | |||
|
402 | append comment "\n" | |||
|
403 | } | |||
|
404 | if {!$listed} { | |||
|
405 | # git-rev-list indents the comment by 4 spaces; | |||
|
406 | # if we got this via git-cat-file, add the indentation | |||
|
407 | append comment " " | |||
|
408 | } | |||
|
409 | append comment $line | |||
|
410 | } | |||
|
411 | } | |||
|
412 | if {$audate != {}} { | |||
|
413 | set audate [clock format $audate] | |||
|
414 | } | |||
|
415 | if {$comdate != {}} { | |||
|
416 | set cdate($id) $comdate | |||
|
417 | set comdate [clock format $comdate] | |||
|
418 | } | |||
|
419 | set commitinfo($id) [list $headline $auname $audate \ | |||
|
420 | $comname $comdate $comment $rev $branch $bookmark $phase] | |||
|
421 | ||||
|
422 | if {[info exists firstparents]} { | |||
|
423 | set i [lsearch $firstparents $id] | |||
|
424 | if {$i != -1} { | |||
|
425 | # remove the parent from firstparents, possible building | |||
|
426 | # an empty list | |||
|
427 | set firstparents [concat \ | |||
|
428 | [lrange $firstparents 0 [expr $i - 1]] \ | |||
|
429 | [lrange $firstparents [expr $i + 1] end]] | |||
|
430 | if {$firstparents eq {}} { | |||
|
431 | # we have found all parents of the first changeset | |||
|
432 | # which means that we can safely select the first line | |||
|
433 | after idle { | |||
|
434 | selectline 0 0 | |||
|
435 | } | |||
|
436 | } | |||
|
437 | } | |||
|
438 | } else { | |||
|
439 | # this is the first changeset, save the parents | |||
|
440 | set firstparents $olds | |||
|
441 | if {$firstparents eq {}} { | |||
|
442 | # a repository with a single changeset | |||
|
443 | after idle { | |||
|
444 | selectline 0 0 | |||
|
445 | } | |||
|
446 | } | |||
|
447 | } | |||
|
448 | } | |||
|
449 | ||||
|
450 | proc readrefs {} { | |||
|
451 | global bookmarkcurrent bookmarkids tagids idtags idbookmarks headids idheads tagcontents env curid | |||
|
452 | ||||
|
453 | set status [catch {exec $env(HG) --config ui.report_untrusted=false id} curid] | |||
|
454 | if { $status != 0 } { | |||
|
455 | puts $::errorInfo | |||
|
456 | if { ![string equal $::errorCode NONE] } { | |||
|
457 | exit 2 | |||
|
458 | } | |||
|
459 | } | |||
|
460 | regexp -- {[[:xdigit:]]+} $curid curid | |||
|
461 | ||||
|
462 | set status [catch {exec $env(HG) --config ui.report_untrusted=false tags} tags] | |||
|
463 | if { $status != 0 } { | |||
|
464 | puts $::errorInfo | |||
|
465 | if { ![string equal $::errorCode NONE] } { | |||
|
466 | exit 2 | |||
|
467 | } | |||
|
468 | } | |||
|
469 | ||||
|
470 | foreach {- tag rev id} [regexp -inline -all -line {^(.+\S)\s+(\d+):(\S+)} $tags] { | |||
|
471 | # we use foreach as Tcl8.4 doesn't support lassign | |||
|
472 | lappend tagids($tag) $id | |||
|
473 | lappend idtags($id) $tag | |||
|
474 | } | |||
|
475 | ||||
|
476 | set status [catch {exec $env(HG) --config ui.report_untrusted=false heads} heads] | |||
|
477 | if { $status != 0 } { | |||
|
478 | puts $::errorInfo | |||
|
479 | if { ![string equal $::errorCode NONE] } { | |||
|
480 | exit 2 | |||
|
481 | } | |||
|
482 | } | |||
|
483 | ||||
|
484 | set lines [split $heads \r\n] | |||
|
485 | foreach f $lines { | |||
|
486 | set match "" | |||
|
487 | regexp {changeset:\s+(\S+):(\S+)$} $f match id sha | |||
|
488 | if {$match != ""} { | |||
|
489 | lappend idheads($sha) $id | |||
|
490 | } | |||
|
491 | } | |||
|
492 | ||||
|
493 | set status [catch {exec $env(HG) --config ui.report_untrusted=false bookmarks} bookmarks] | |||
|
494 | if { $status != 0 } { | |||
|
495 | puts $::errorInfo | |||
|
496 | if { ![string equal $::errorCode NONE] } { | |||
|
497 | exit 2 | |||
|
498 | } | |||
|
499 | } | |||
|
500 | set lines [split $bookmarks "\n"] | |||
|
501 | set bookmarkcurrent 0 | |||
|
502 | foreach f $lines { | |||
|
503 | regexp {(\S+)$} $f full | |||
|
504 | regsub {\s+(\S+)$} $f "" direct | |||
|
505 | set sha [split $full ':'] | |||
|
506 | set bookmark [lindex $sha 1] | |||
|
507 | set current [string first " * " $direct)] | |||
|
508 | regsub {^\s(\*|\s)\s} $direct "" direct | |||
|
509 | lappend bookmarkids($direct) $bookmark | |||
|
510 | lappend idbookmarks($bookmark) $direct | |||
|
511 | if {$current >= 0} { | |||
|
512 | set bookmarkcurrent $direct | |||
|
513 | } | |||
|
514 | } | |||
|
515 | } | |||
|
516 | ||||
|
517 | proc readotherrefs {base dname excl} { | |||
|
518 | global otherrefids idotherrefs | |||
|
519 | ||||
|
520 | set git [gitdir] | |||
|
521 | set files [glob -nocomplain -types f [file join $git $base *]] | |||
|
522 | foreach f $files { | |||
|
523 | catch { | |||
|
524 | set fd [open $f r] | |||
|
525 | set line [read $fd 40] | |||
|
526 | if {[regexp {^[0-9a-f]{12}} $line id]} { | |||
|
527 | set name "$dname[file tail $f]" | |||
|
528 | set otherrefids($name) $id | |||
|
529 | lappend idotherrefs($id) $name | |||
|
530 | } | |||
|
531 | close $fd | |||
|
532 | } | |||
|
533 | } | |||
|
534 | set dirs [glob -nocomplain -types d [file join $git $base *]] | |||
|
535 | foreach d $dirs { | |||
|
536 | set dir [file tail $d] | |||
|
537 | if {[lsearch -exact $excl $dir] >= 0} continue | |||
|
538 | readotherrefs [file join $base $dir] "$dname$dir/" {} | |||
|
539 | } | |||
|
540 | } | |||
|
541 | ||||
|
542 | proc allcansmousewheel {delta} { | |||
|
543 | set delta [expr -5*(int($delta)/abs($delta))] | |||
|
544 | allcanvs yview scroll $delta units | |||
|
545 | } | |||
|
546 | ||||
|
547 | proc error_popup msg { | |||
|
548 | set w .error | |||
|
549 | toplevel $w | |||
|
550 | wm transient $w . | |||
|
551 | message $w.m -text $msg -justify center -aspect 400 | |||
|
552 | pack $w.m -side top -fill x -padx 20 -pady 20 | |||
|
553 | ttk::button $w.ok -text OK -command "destroy $w" | |||
|
554 | pack $w.ok -side bottom -fill x | |||
|
555 | bind $w <Visibility> "grab $w; focus $w" | |||
|
556 | popupify $w | |||
|
557 | tkwait window $w | |||
|
558 | } | |||
|
559 | ||||
|
560 | proc makewindow {} { | |||
|
561 | global canv canv2 canv3 linespc charspc ctext cflist textfont | |||
|
562 | global findtype findtypemenu findloc findstring fstring geometry | |||
|
563 | global entries sha1entry sha1string sha1but | |||
|
564 | global maincursor textcursor curtextcursor | |||
|
565 | global rowctxmenu gaudydiff mergemax | |||
|
566 | global hgvdiff bgcolor fgcolor diffremcolor diffaddcolor diffmerge1color | |||
|
567 | global diffmerge2color hunksepcolor | |||
|
568 | global posx posy | |||
|
569 | ||||
|
570 | if {[info exists posx]} { | |||
|
571 | wm geometry . +$posx+$posy | |||
|
572 | } | |||
|
573 | ||||
|
574 | menu .bar | |||
|
575 | .bar add cascade -label "File" -menu .bar.file | |||
|
576 | menu .bar.file | |||
|
577 | .bar.file add command -label "Reread references" -command rereadrefs | |||
|
578 | .bar.file add command -label "Quit" -command doquit | |||
|
579 | menu .bar.help | |||
|
580 | .bar add cascade -label "Help" -menu .bar.help | |||
|
581 | .bar.help add command -label "About hgk" -command about | |||
|
582 | . configure -menu .bar | |||
|
583 | ||||
|
584 | if {![info exists geometry(canv1)]} { | |||
|
585 | set geometry(canv1) [expr 45 * $charspc] | |||
|
586 | set geometry(canv2) [expr 30 * $charspc] | |||
|
587 | set geometry(canv3) [expr 15 * $charspc] | |||
|
588 | set geometry(canvh) [expr 25 * $linespc + 4] | |||
|
589 | set geometry(ctextw) 80 | |||
|
590 | set geometry(ctexth) 30 | |||
|
591 | set geometry(cflistw) 30 | |||
|
592 | } | |||
|
593 | panedwindow .ctop -orient vertical | |||
|
594 | if {[info exists geometry(width)]} { | |||
|
595 | .ctop conf -width $geometry(width) -height $geometry(height) | |||
|
596 | set texth [expr {$geometry(height) - $geometry(canvh) - 56}] | |||
|
597 | set geometry(ctexth) [expr {($texth - 8) / | |||
|
598 | [font metrics $textfont -linespace]}] | |||
|
599 | } | |||
|
600 | ttk::frame .ctop.top | |||
|
601 | ttk::frame .ctop.top.bar | |||
|
602 | pack .ctop.top.bar -side bottom -fill x | |||
|
603 | set cscroll .ctop.top.csb | |||
|
604 | ttk::scrollbar $cscroll -command {allcanvs yview} | |||
|
605 | pack $cscroll -side right -fill y | |||
|
606 | panedwindow .ctop.top.clist -orient horizontal -sashpad 0 -handlesize 4 | |||
|
607 | pack .ctop.top.clist -side top -fill both -expand 1 | |||
|
608 | .ctop add .ctop.top | |||
|
609 | set canv .ctop.top.clist.canv | |||
|
610 | canvas $canv -height $geometry(canvh) -width $geometry(canv1) \ | |||
|
611 | -bg $bgcolor -bd 0 \ | |||
|
612 | -yscrollincr $linespc -yscrollcommand "$cscroll set" -selectbackground "#c0c0c0" | |||
|
613 | .ctop.top.clist add $canv | |||
|
614 | set canv2 .ctop.top.clist.canv2 | |||
|
615 | canvas $canv2 -height $geometry(canvh) -width $geometry(canv2) \ | |||
|
616 | -bg $bgcolor -bd 0 -yscrollincr $linespc -selectbackground "#c0c0c0" | |||
|
617 | .ctop.top.clist add $canv2 | |||
|
618 | set canv3 .ctop.top.clist.canv3 | |||
|
619 | canvas $canv3 -height $geometry(canvh) -width $geometry(canv3) \ | |||
|
620 | -bg $bgcolor -bd 0 -yscrollincr $linespc -selectbackground "#c0c0c0" | |||
|
621 | .ctop.top.clist add $canv3 | |||
|
622 | bind .ctop.top.clist <Configure> {resizeclistpanes %W %w} | |||
|
623 | ||||
|
624 | set sha1entry .ctop.top.bar.sha1 | |||
|
625 | set entries $sha1entry | |||
|
626 | set sha1but .ctop.top.bar.sha1label | |||
|
627 | button $sha1but -text "SHA1 ID: " -state disabled -relief flat \ | |||
|
628 | -command gotocommit -width 8 | |||
|
629 | $sha1but conf -disabledforeground [$sha1but cget -foreground] | |||
|
630 | pack .ctop.top.bar.sha1label -side left | |||
|
631 | ttk::entry $sha1entry -width 40 -font $textfont -textvariable sha1string | |||
|
632 | trace add variable sha1string write sha1change | |||
|
633 | pack $sha1entry -side left -pady 2 | |||
|
634 | ||||
|
635 | image create bitmap bm-left -data { | |||
|
636 | #define left_width 16 | |||
|
637 | #define left_height 16 | |||
|
638 | static unsigned char left_bits[] = { | |||
|
639 | 0x00, 0x00, 0xc0, 0x01, 0xe0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1c, 0x00, | |||
|
640 | 0x0e, 0x00, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x0e, 0x00, 0x1c, 0x00, | |||
|
641 | 0x38, 0x00, 0x70, 0x00, 0xe0, 0x00, 0xc0, 0x01}; | |||
|
642 | } | |||
|
643 | image create bitmap bm-right -data { | |||
|
644 | #define right_width 16 | |||
|
645 | #define right_height 16 | |||
|
646 | static unsigned char right_bits[] = { | |||
|
647 | 0x00, 0x00, 0xc0, 0x01, 0x80, 0x03, 0x00, 0x07, 0x00, 0x0e, 0x00, 0x1c, | |||
|
648 | 0x00, 0x38, 0xff, 0x7f, 0xff, 0x7f, 0xff, 0x7f, 0x00, 0x38, 0x00, 0x1c, | |||
|
649 | 0x00, 0x0e, 0x00, 0x07, 0x80, 0x03, 0xc0, 0x01}; | |||
|
650 | } | |||
|
651 | ttk::button .ctop.top.bar.leftbut -image bm-left -command goback \ | |||
|
652 | -state disabled -width 26 | |||
|
653 | pack .ctop.top.bar.leftbut -side left -fill y | |||
|
654 | ttk::button .ctop.top.bar.rightbut -image bm-right -command goforw \ | |||
|
655 | -state disabled -width 26 | |||
|
656 | pack .ctop.top.bar.rightbut -side left -fill y | |||
|
657 | ||||
|
658 | ttk::button .ctop.top.bar.findbut -text "Find" -command dofind | |||
|
659 | pack .ctop.top.bar.findbut -side left | |||
|
660 | set findstring {} | |||
|
661 | set fstring .ctop.top.bar.findstring | |||
|
662 | lappend entries $fstring | |||
|
663 | ttk::entry $fstring -width 30 -font $textfont -textvariable findstring | |||
|
664 | pack $fstring -side left -expand 1 -fill x | |||
|
665 | set findtype Exact | |||
|
666 | set findtypemenu [ttk::optionMenu .ctop.top.bar.findtype \ | |||
|
667 | findtype Exact IgnCase Regexp] | |||
|
668 | set findloc "All fields" | |||
|
669 | ttk::optionMenu .ctop.top.bar.findloc findloc "All fields" Headline \ | |||
|
670 | Comments Author Files Pickaxe | |||
|
671 | pack .ctop.top.bar.findloc -side right | |||
|
672 | pack .ctop.top.bar.findtype -side right | |||
|
673 | # for making sure type==Exact whenever loc==Pickaxe | |||
|
674 | trace add variable findloc write findlocchange | |||
|
675 | ||||
|
676 | panedwindow .ctop.cdet -orient horizontal | |||
|
677 | .ctop add .ctop.cdet | |||
|
678 | ttk::frame .ctop.cdet.left | |||
|
679 | set ctext .ctop.cdet.left.ctext | |||
|
680 | text $ctext -fg $fgcolor -bg $bgcolor -state disabled -font $textfont \ | |||
|
681 | -width $geometry(ctextw) -height $geometry(ctexth) \ | |||
|
682 | -yscrollcommand ".ctop.cdet.left.sb set" \ | |||
|
683 | -xscrollcommand ".ctop.cdet.left.hb set" -wrap none | |||
|
684 | ttk::scrollbar .ctop.cdet.left.sb -command "$ctext yview" | |||
|
685 | ttk::scrollbar .ctop.cdet.left.hb -orient horizontal -command "$ctext xview" | |||
|
686 | pack .ctop.cdet.left.sb -side right -fill y | |||
|
687 | pack .ctop.cdet.left.hb -side bottom -fill x | |||
|
688 | pack $ctext -side left -fill both -expand 1 | |||
|
689 | .ctop.cdet add .ctop.cdet.left | |||
|
690 | ||||
|
691 | $ctext tag conf filesep -font [concat $textfont bold] -back "#aaaaaa" | |||
|
692 | if {$gaudydiff} { | |||
|
693 | $ctext tag conf hunksep -back blue -fore white | |||
|
694 | $ctext tag conf d0 -back "#ff8080" | |||
|
695 | $ctext tag conf d1 -back green | |||
|
696 | } else { | |||
|
697 | $ctext tag conf hunksep -fore $hunksepcolor | |||
|
698 | $ctext tag conf d0 -fore $diffremcolor | |||
|
699 | $ctext tag conf d1 -fore $diffaddcolor | |||
|
700 | ||||
|
701 | # The mX colours seem to be used in merge changesets, where m0 | |||
|
702 | # is first parent, m1 is second parent and so on. Git can have | |||
|
703 | # several parents, Hg cannot, so I think the m2..mmax would be | |||
|
704 | # unused. | |||
|
705 | $ctext tag conf m0 -fore $diffmerge1color | |||
|
706 | $ctext tag conf m1 -fore $diffmerge2color | |||
|
707 | $ctext tag conf m2 -fore green | |||
|
708 | $ctext tag conf m3 -fore purple | |||
|
709 | $ctext tag conf m4 -fore brown | |||
|
710 | $ctext tag conf mmax -fore darkgrey | |||
|
711 | set mergemax 5 | |||
|
712 | $ctext tag conf mresult -font [concat $textfont bold] | |||
|
713 | $ctext tag conf msep -font [concat $textfont bold] | |||
|
714 | $ctext tag conf found -back yellow | |||
|
715 | } | |||
|
716 | ||||
|
717 | ttk::frame .ctop.cdet.right | |||
|
718 | set cflist .ctop.cdet.right.cfiles | |||
|
719 | listbox $cflist -fg $fgcolor -bg $bgcolor \ | |||
|
720 | -selectmode extended -width $geometry(cflistw) \ | |||
|
721 | -yscrollcommand ".ctop.cdet.right.sb set" | |||
|
722 | ttk::scrollbar .ctop.cdet.right.sb -command "$cflist yview" | |||
|
723 | pack .ctop.cdet.right.sb -side right -fill y | |||
|
724 | pack $cflist -side left -fill both -expand 1 | |||
|
725 | .ctop.cdet add .ctop.cdet.right | |||
|
726 | bind .ctop.cdet <Configure> {resizecdetpanes %W %w} | |||
|
727 | ||||
|
728 | pack .ctop -side top -fill both -expand 1 | |||
|
729 | ||||
|
730 | bindall <1> {selcanvline %W %x %y} | |||
|
731 | #bindall <B1-Motion> {selcanvline %W %x %y} | |||
|
732 | bindall <MouseWheel> "allcansmousewheel %D" | |||
|
733 | bindall <ButtonRelease-4> "allcanvs yview scroll -5 units" | |||
|
734 | bindall <ButtonRelease-5> "allcanvs yview scroll 5 units" | |||
|
735 | bindall <2> "allcanvs scan mark 0 %y" | |||
|
736 | bindall <B2-Motion> "allcanvs scan dragto 0 %y" | |||
|
737 | bind . <Key-Up> "selnextline -1" | |||
|
738 | bind . <Key-Down> "selnextline 1" | |||
|
739 | bind . <Key-Prior> "allcanvs yview scroll -1 pages" | |||
|
740 | bind . <Key-Next> "allcanvs yview scroll 1 pages" | |||
|
741 | bindkey <Key-Delete> "$ctext yview scroll -1 pages" | |||
|
742 | bindkey <Key-BackSpace> "$ctext yview scroll -1 pages" | |||
|
743 | bindkey <Key-space> "$ctext yview scroll 1 pages" | |||
|
744 | bindkey p "selnextline -1" | |||
|
745 | bindkey n "selnextline 1" | |||
|
746 | bindkey b "$ctext yview scroll -1 pages" | |||
|
747 | bindkey d "$ctext yview scroll 18 units" | |||
|
748 | bindkey u "$ctext yview scroll -18 units" | |||
|
749 | bindkey / {findnext 1} | |||
|
750 | bindkey <Key-Return> {findnext 0} | |||
|
751 | bindkey ? findprev | |||
|
752 | bindkey f nextfile | |||
|
753 | bind . <Control-q> doquit | |||
|
754 | bind . <Control-w> doquit | |||
|
755 | bind . <Control-f> dofind | |||
|
756 | bind . <Control-g> {findnext 0} | |||
|
757 | bind . <Control-r> findprev | |||
|
758 | bind . <Control-equal> {incrfont 1} | |||
|
759 | bind . <Control-KP_Add> {incrfont 1} | |||
|
760 | bind . <Control-minus> {incrfont -1} | |||
|
761 | bind . <Control-KP_Subtract> {incrfont -1} | |||
|
762 | bind $cflist <<ListboxSelect>> listboxsel | |||
|
763 | bind . <Destroy> {savestuff %W} | |||
|
764 | bind . <Button-1> "click %W" | |||
|
765 | bind $fstring <Key-Return> dofind | |||
|
766 | bind $sha1entry <Key-Return> gotocommit | |||
|
767 | bind $sha1entry <<PasteSelection>> clearsha1 | |||
|
768 | ||||
|
769 | set maincursor [. cget -cursor] | |||
|
770 | set textcursor [$ctext cget -cursor] | |||
|
771 | set curtextcursor $textcursor | |||
|
772 | ||||
|
773 | set rowctxmenu .rowctxmenu | |||
|
774 | menu $rowctxmenu -tearoff 0 | |||
|
775 | $rowctxmenu add command -label "Diff this -> selected" \ | |||
|
776 | -command {diffvssel 0} | |||
|
777 | $rowctxmenu add command -label "Diff selected -> this" \ | |||
|
778 | -command {diffvssel 1} | |||
|
779 | $rowctxmenu add command -label "Make patch" -command mkpatch | |||
|
780 | $rowctxmenu add command -label "Create tag" -command mktag | |||
|
781 | $rowctxmenu add command -label "Write commit to file" -command writecommit | |||
|
782 | if { $hgvdiff ne "" } { | |||
|
783 | $rowctxmenu add command -label "Visual diff with parent" \ | |||
|
784 | -command {vdiff 1} | |||
|
785 | $rowctxmenu add command -label "Visual diff with selected" \ | |||
|
786 | -command {vdiff 0} | |||
|
787 | } | |||
|
788 | } | |||
|
789 | ||||
|
790 | # when we make a key binding for the toplevel, make sure | |||
|
791 | # it doesn't get triggered when that key is pressed in the | |||
|
792 | # find string entry widget. | |||
|
793 | proc bindkey {ev script} { | |||
|
794 | global entries | |||
|
795 | bind . $ev $script | |||
|
796 | set escript [bind Entry $ev] | |||
|
797 | if {$escript == {}} { | |||
|
798 | set escript [bind Entry <Key>] | |||
|
799 | } | |||
|
800 | foreach e $entries { | |||
|
801 | bind $e $ev "$escript; break" | |||
|
802 | } | |||
|
803 | } | |||
|
804 | ||||
|
805 | # set the focus back to the toplevel for any click outside | |||
|
806 | # the entry widgets | |||
|
807 | proc click {w} { | |||
|
808 | global ctext entries | |||
|
809 | foreach e [concat $entries $ctext] { | |||
|
810 | if {$w == $e} return | |||
|
811 | } | |||
|
812 | focus . | |||
|
813 | } | |||
|
814 | ||||
|
815 | proc savestuff {w} { | |||
|
816 | global canv canv2 canv3 ctext cflist mainfont textfont | |||
|
817 | global stuffsaved findmergefiles gaudydiff maxgraphpct | |||
|
818 | global maxwidth authorcolors curidfont bgcolor fgcolor | |||
|
819 | global diffremcolor diffaddcolor hunksepcolor | |||
|
820 | global diffmerge1color diffmerge2color | |||
|
821 | ||||
|
822 | if {$stuffsaved} return | |||
|
823 | if {![winfo viewable .]} return | |||
|
824 | catch { | |||
|
825 | set f [open "~/.hgk-new" w] | |||
|
826 | puts $f [list set mainfont $mainfont] | |||
|
827 | puts $f [list set curidfont $curidfont] | |||
|
828 | puts $f [list set textfont $textfont] | |||
|
829 | puts $f [list set findmergefiles $findmergefiles] | |||
|
830 | puts $f [list set gaudydiff $gaudydiff] | |||
|
831 | puts $f [list set maxgraphpct $maxgraphpct] | |||
|
832 | puts $f [list set maxwidth $maxwidth] | |||
|
833 | puts $f "set geometry(width) [winfo width .ctop]" | |||
|
834 | puts $f "set geometry(height) [winfo height .ctop]" | |||
|
835 | puts $f "set geometry(canv1) [expr [winfo width $canv]-2]" | |||
|
836 | puts $f "set geometry(canv2) [expr [winfo width $canv2]-2]" | |||
|
837 | puts $f "set geometry(canv3) [expr [winfo width $canv3]-2]" | |||
|
838 | puts $f "set geometry(canvh) [expr [winfo height $canv]-2]" | |||
|
839 | set wid [expr {([winfo width $ctext] - 8) \ | |||
|
840 | / [font measure $textfont "0"]}] | |||
|
841 | puts $f "set geometry(ctextw) $wid" | |||
|
842 | set wid [expr {([winfo width $cflist] - 11) \ | |||
|
843 | / [font measure [$cflist cget -font] "0"]}] | |||
|
844 | puts $f "set geometry(cflistw) $wid" | |||
|
845 | puts $f "#" | |||
|
846 | puts $f "# main window position:" | |||
|
847 | puts $f "set posx [winfo x .]" | |||
|
848 | puts $f "set posy [winfo y .]" | |||
|
849 | puts $f "#" | |||
|
850 | puts $f "# authorcolors format:" | |||
|
851 | puts $f "#" | |||
|
852 | puts $f "# zero or more sublists of" | |||
|
853 | puts $f "#" | |||
|
854 | puts $f "# { regex color }" | |||
|
855 | puts $f "#" | |||
|
856 | puts $f "# followed by a list of colors" | |||
|
857 | puts $f "#" | |||
|
858 | puts $f "# If the commit author matches a regex in a sublist," | |||
|
859 | puts $f "# the commit will be colored by that color" | |||
|
860 | puts $f "# otherwise the next unused entry from the list of colors" | |||
|
861 | puts $f "# will be assigned to this commit and also all other commits" | |||
|
862 | puts $f "# of the same author. When the list of colors is exhausted," | |||
|
863 | puts $f "# the last entry will be reused." | |||
|
864 | puts $f "#" | |||
|
865 | puts $f "set authorcolors {$authorcolors}" | |||
|
866 | puts $f "#" | |||
|
867 | puts $f "# The background color in the text windows" | |||
|
868 | puts $f "set bgcolor $bgcolor" | |||
|
869 | puts $f "#" | |||
|
870 | puts $f "# The text color used in the diff and file list view" | |||
|
871 | puts $f "set fgcolor $fgcolor" | |||
|
872 | puts $f "#" | |||
|
873 | puts $f "# Color to display + lines in diffs" | |||
|
874 | puts $f "set diffaddcolor $diffaddcolor" | |||
|
875 | puts $f "#" | |||
|
876 | puts $f "# Color to display - lines in diffs" | |||
|
877 | puts $f "set diffremcolor $diffremcolor" | |||
|
878 | puts $f "#" | |||
|
879 | puts $f "# Merge diffs: Color to signal lines from first parent" | |||
|
880 | puts $f "set diffmerge1color $diffmerge1color" | |||
|
881 | puts $f "#" | |||
|
882 | puts $f "# Merge diffs: Color to signal lines from second parent" | |||
|
883 | puts $f "set diffmerge2color $diffmerge2color" | |||
|
884 | puts $f "#" | |||
|
885 | puts $f "# Hunkseparator (@@ -lineno,lines +lineno,lines @@) color" | |||
|
886 | puts $f "set hunksepcolor $hunksepcolor" | |||
|
887 | close $f | |||
|
888 | file rename -force "~/.hgk-new" "~/.hgk" | |||
|
889 | } | |||
|
890 | set stuffsaved 1 | |||
|
891 | } | |||
|
892 | ||||
|
893 | proc resizeclistpanes {win w} { | |||
|
894 | global oldwidth | |||
|
895 | if [info exists oldwidth($win)] { | |||
|
896 | set s0 [$win sash coord 0] | |||
|
897 | set s1 [$win sash coord 1] | |||
|
898 | if {$w < 60} { | |||
|
899 | set sash0 [expr {int($w/2 - 2)}] | |||
|
900 | set sash1 [expr {int($w*5/6 - 2)}] | |||
|
901 | } else { | |||
|
902 | set factor [expr {1.0 * $w / $oldwidth($win)}] | |||
|
903 | set sash0 [expr {int($factor * [lindex $s0 0])}] | |||
|
904 | set sash1 [expr {int($factor * [lindex $s1 0])}] | |||
|
905 | if {$sash0 < 30} { | |||
|
906 | set sash0 30 | |||
|
907 | } | |||
|
908 | if {$sash1 < $sash0 + 20} { | |||
|
909 | set sash1 [expr $sash0 + 20] | |||
|
910 | } | |||
|
911 | if {$sash1 > $w - 10} { | |||
|
912 | set sash1 [expr $w - 10] | |||
|
913 | if {$sash0 > $sash1 - 20} { | |||
|
914 | set sash0 [expr $sash1 - 20] | |||
|
915 | } | |||
|
916 | } | |||
|
917 | } | |||
|
918 | $win sash place 0 $sash0 [lindex $s0 1] | |||
|
919 | $win sash place 1 $sash1 [lindex $s1 1] | |||
|
920 | } | |||
|
921 | set oldwidth($win) $w | |||
|
922 | } | |||
|
923 | ||||
|
924 | proc resizecdetpanes {win w} { | |||
|
925 | global oldwidth | |||
|
926 | if [info exists oldwidth($win)] { | |||
|
927 | set s0 [$win sash coord 0] | |||
|
928 | if {$w < 60} { | |||
|
929 | set sash0 [expr {int($w*3/4 - 2)}] | |||
|
930 | } else { | |||
|
931 | set factor [expr {1.0 * $w / $oldwidth($win)}] | |||
|
932 | set sash0 [expr {int($factor * [lindex $s0 0])}] | |||
|
933 | if {$sash0 < 45} { | |||
|
934 | set sash0 45 | |||
|
935 | } | |||
|
936 | if {$sash0 > $w - 15} { | |||
|
937 | set sash0 [expr $w - 15] | |||
|
938 | } | |||
|
939 | } | |||
|
940 | $win sash place 0 $sash0 [lindex $s0 1] | |||
|
941 | } | |||
|
942 | set oldwidth($win) $w | |||
|
943 | } | |||
|
944 | ||||
|
945 | proc allcanvs args { | |||
|
946 | global canv canv2 canv3 | |||
|
947 | eval $canv $args | |||
|
948 | eval $canv2 $args | |||
|
949 | eval $canv3 $args | |||
|
950 | } | |||
|
951 | ||||
|
952 | proc bindall {event action} { | |||
|
953 | global canv canv2 canv3 | |||
|
954 | bind $canv $event $action | |||
|
955 | bind $canv2 $event $action | |||
|
956 | bind $canv3 $event $action | |||
|
957 | } | |||
|
958 | ||||
|
959 | proc about {} { | |||
|
960 | set w .about | |||
|
961 | if {[winfo exists $w]} { | |||
|
962 | raise $w | |||
|
963 | return | |||
|
964 | } | |||
|
965 | toplevel $w | |||
|
966 | wm title $w "About hgk" | |||
|
967 | message $w.m -text { | |||
|
968 | Hgk version 1.2 | |||
|
969 | ||||
|
970 | Copyright � 2005 Paul Mackerras | |||
|
971 | ||||
|
972 | Use and redistribute under the terms of the GNU General Public License} \ | |||
|
973 | -justify center -aspect 400 | |||
|
974 | pack $w.m -side top -fill x -padx 20 -pady 20 | |||
|
975 | ttk::button $w.ok -text Close -command "destroy $w" | |||
|
976 | pack $w.ok -side bottom | |||
|
977 | popupify $w | |||
|
978 | } | |||
|
979 | ||||
|
980 | set aunextcolor 0 | |||
|
981 | proc assignauthorcolor {name} { | |||
|
982 | global authorcolors aucolormap aunextcolor | |||
|
983 | if [info exists aucolormap($name)] return | |||
|
984 | ||||
|
985 | set randomcolors {black} | |||
|
986 | for {set i 0} {$i < [llength $authorcolors]} {incr i} { | |||
|
987 | set col [lindex $authorcolors $i] | |||
|
988 | if {[llength $col] > 1} { | |||
|
989 | set re [lindex $col 0] | |||
|
990 | set c [lindex $col 1] | |||
|
991 | if {[regexp -- $re $name]} { | |||
|
992 | set aucolormap($name) $c | |||
|
993 | return | |||
|
994 | } | |||
|
995 | } else { | |||
|
996 | set randomcolors [lrange $authorcolors $i end] | |||
|
997 | break | |||
|
998 | } | |||
|
999 | } | |||
|
1000 | ||||
|
1001 | set ncolors [llength $randomcolors] | |||
|
1002 | set c [lindex $randomcolors $aunextcolor] | |||
|
1003 | if {[incr aunextcolor] >= $ncolors} { | |||
|
1004 | incr aunextcolor -1 | |||
|
1005 | } | |||
|
1006 | set aucolormap($name) $c | |||
|
1007 | } | |||
|
1008 | ||||
|
1009 | proc assigncolor {id} { | |||
|
1010 | global commitinfo colormap commcolors colors nextcolor | |||
|
1011 | global parents nparents children nchildren | |||
|
1012 | global cornercrossings crossings | |||
|
1013 | ||||
|
1014 | if [info exists colormap($id)] return | |||
|
1015 | set ncolors [llength $colors] | |||
|
1016 | if {$nparents($id) <= 1 && $nchildren($id) == 1} { | |||
|
1017 | set child [lindex $children($id) 0] | |||
|
1018 | if {[info exists colormap($child)] | |||
|
1019 | && $nparents($child) == 1} { | |||
|
1020 | set colormap($id) $colormap($child) | |||
|
1021 | return | |||
|
1022 | } | |||
|
1023 | } | |||
|
1024 | set badcolors {} | |||
|
1025 | if {[info exists cornercrossings($id)]} { | |||
|
1026 | foreach x $cornercrossings($id) { | |||
|
1027 | if {[info exists colormap($x)] | |||
|
1028 | && [lsearch -exact $badcolors $colormap($x)] < 0} { | |||
|
1029 | lappend badcolors $colormap($x) | |||
|
1030 | } | |||
|
1031 | } | |||
|
1032 | if {[llength $badcolors] >= $ncolors} { | |||
|
1033 | set badcolors {} | |||
|
1034 | } | |||
|
1035 | } | |||
|
1036 | set origbad $badcolors | |||
|
1037 | if {[llength $badcolors] < $ncolors - 1} { | |||
|
1038 | if {[info exists crossings($id)]} { | |||
|
1039 | foreach x $crossings($id) { | |||
|
1040 | if {[info exists colormap($x)] | |||
|
1041 | && [lsearch -exact $badcolors $colormap($x)] < 0} { | |||
|
1042 | lappend badcolors $colormap($x) | |||
|
1043 | } | |||
|
1044 | } | |||
|
1045 | if {[llength $badcolors] >= $ncolors} { | |||
|
1046 | set badcolors $origbad | |||
|
1047 | } | |||
|
1048 | } | |||
|
1049 | set origbad $badcolors | |||
|
1050 | } | |||
|
1051 | if {[llength $badcolors] < $ncolors - 1} { | |||
|
1052 | foreach child $children($id) { | |||
|
1053 | if {[info exists colormap($child)] | |||
|
1054 | && [lsearch -exact $badcolors $colormap($child)] < 0} { | |||
|
1055 | lappend badcolors $colormap($child) | |||
|
1056 | } | |||
|
1057 | if {[info exists parents($child)]} { | |||
|
1058 | foreach p $parents($child) { | |||
|
1059 | if {[info exists colormap($p)] | |||
|
1060 | && [lsearch -exact $badcolors $colormap($p)] < 0} { | |||
|
1061 | lappend badcolors $colormap($p) | |||
|
1062 | } | |||
|
1063 | } | |||
|
1064 | } | |||
|
1065 | } | |||
|
1066 | if {[llength $badcolors] >= $ncolors} { | |||
|
1067 | set badcolors $origbad | |||
|
1068 | } | |||
|
1069 | } | |||
|
1070 | for {set i 0} {$i <= $ncolors} {incr i} { | |||
|
1071 | set c [lindex $colors $nextcolor] | |||
|
1072 | if {[incr nextcolor] >= $ncolors} { | |||
|
1073 | set nextcolor 0 | |||
|
1074 | } | |||
|
1075 | if {[lsearch -exact $badcolors $c]} break | |||
|
1076 | } | |||
|
1077 | set colormap($id) $c | |||
|
1078 | } | |||
|
1079 | ||||
|
1080 | proc initgraph {} { | |||
|
1081 | global canvy canvy0 lineno numcommits nextcolor linespc | |||
|
1082 | global mainline mainlinearrow sidelines | |||
|
1083 | global nchildren ncleft | |||
|
1084 | global displist nhyperspace | |||
|
1085 | ||||
|
1086 | allcanvs delete all | |||
|
1087 | set nextcolor 0 | |||
|
1088 | set canvy $canvy0 | |||
|
1089 | set lineno -1 | |||
|
1090 | set numcommits 0 | |||
|
1091 | catch {unset mainline} | |||
|
1092 | catch {unset mainlinearrow} | |||
|
1093 | catch {unset sidelines} | |||
|
1094 | foreach id [array names nchildren] { | |||
|
1095 | set ncleft($id) $nchildren($id) | |||
|
1096 | } | |||
|
1097 | set displist {} | |||
|
1098 | set nhyperspace 0 | |||
|
1099 | } | |||
|
1100 | ||||
|
1101 | proc bindline {t id} { | |||
|
1102 | global canv | |||
|
1103 | ||||
|
1104 | $canv bind $t <Enter> "lineenter %x %y $id" | |||
|
1105 | $canv bind $t <Motion> "linemotion %x %y $id" | |||
|
1106 | $canv bind $t <Leave> "lineleave $id" | |||
|
1107 | $canv bind $t <Button-1> "lineclick %x %y $id 1" | |||
|
1108 | } | |||
|
1109 | ||||
|
1110 | proc drawlines {id xtra} { | |||
|
1111 | global mainline mainlinearrow sidelines lthickness colormap canv | |||
|
1112 | ||||
|
1113 | $canv delete lines.$id | |||
|
1114 | if {[info exists mainline($id)]} { | |||
|
1115 | set t [$canv create line $mainline($id) \ | |||
|
1116 | -width [expr {($xtra + 1) * $lthickness}] \ | |||
|
1117 | -fill $colormap($id) -tags lines.$id \ | |||
|
1118 | -arrow $mainlinearrow($id)] | |||
|
1119 | $canv lower $t | |||
|
1120 | bindline $t $id | |||
|
1121 | } | |||
|
1122 | if {[info exists sidelines($id)]} { | |||
|
1123 | foreach ls $sidelines($id) { | |||
|
1124 | set coords [lindex $ls 0] | |||
|
1125 | set thick [lindex $ls 1] | |||
|
1126 | set arrow [lindex $ls 2] | |||
|
1127 | set t [$canv create line $coords -fill $colormap($id) \ | |||
|
1128 | -width [expr {($thick + $xtra) * $lthickness}] \ | |||
|
1129 | -arrow $arrow -tags lines.$id] | |||
|
1130 | $canv lower $t | |||
|
1131 | bindline $t $id | |||
|
1132 | } | |||
|
1133 | } | |||
|
1134 | } | |||
|
1135 | ||||
|
1136 | # level here is an index in displist | |||
|
1137 | proc drawcommitline {level} { | |||
|
1138 | global parents children nparents displist | |||
|
1139 | global canv canv2 canv3 mainfont namefont canvy linespc | |||
|
1140 | global lineid linehtag linentag linedtag commitinfo | |||
|
1141 | global colormap numcommits currentparents dupparents | |||
|
1142 | global idtags idline idheads idotherrefs idbookmarks | |||
|
1143 | global lineno lthickness mainline mainlinearrow sidelines | |||
|
1144 | global commitlisted rowtextx idpos lastuse displist | |||
|
1145 | global oldnlines olddlevel olddisplist | |||
|
1146 | global aucolormap curid curidfont obsolete | |||
|
1147 | ||||
|
1148 | incr numcommits | |||
|
1149 | incr lineno | |||
|
1150 | set id [lindex $displist $level] | |||
|
1151 | set lastuse($id) $lineno | |||
|
1152 | set lineid($lineno) $id | |||
|
1153 | set idline($id) $lineno | |||
|
1154 | set shape oval | |||
|
1155 | set outline #000080 | |||
|
1156 | set ofill [expr {[info exists commitlisted($id)]? "#7f7fff": "white"}] | |||
|
1157 | if {![info exists commitinfo($id)]} { | |||
|
1158 | readcommit $id | |||
|
1159 | if {![info exists commitinfo($id)]} { | |||
|
1160 | set commitinfo($id) {"No commit information available"} | |||
|
1161 | set nparents($id) 0 | |||
|
1162 | } | |||
|
1163 | } else { | |||
|
1164 | switch [lindex $commitinfo($id) 9] secret { | |||
|
1165 | set shape rect | |||
|
1166 | } public { | |||
|
1167 | set outline black | |||
|
1168 | set ofill blue | |||
|
1169 | } | |||
|
1170 | } | |||
|
1171 | if {[info exists obsolete($id)]} { | |||
|
1172 | set outline darkgrey | |||
|
1173 | set ofill lightgrey | |||
|
1174 | } | |||
|
1175 | assigncolor $id | |||
|
1176 | set currentparents {} | |||
|
1177 | set dupparents {} | |||
|
1178 | if {[info exists commitlisted($id)] && [info exists parents($id)]} { | |||
|
1179 | foreach p $parents($id) { | |||
|
1180 | if {[lsearch -exact $currentparents $p] < 0} { | |||
|
1181 | lappend currentparents $p | |||
|
1182 | } else { | |||
|
1183 | # remember that this parent was listed twice | |||
|
1184 | lappend dupparents $p | |||
|
1185 | } | |||
|
1186 | } | |||
|
1187 | } | |||
|
1188 | set x [xcoord $level $level $lineno] | |||
|
1189 | set y1 $canvy | |||
|
1190 | set canvy [expr $canvy + $linespc] | |||
|
1191 | allcanvs conf -scrollregion \ | |||
|
1192 | [list 0 0 0 [expr $y1 + 0.5 * $linespc + 2]] | |||
|
1193 | if {[info exists mainline($id)]} { | |||
|
1194 | lappend mainline($id) $x $y1 | |||
|
1195 | if {$mainlinearrow($id) ne "none"} { | |||
|
1196 | set mainline($id) [trimdiagstart $mainline($id)] | |||
|
1197 | } | |||
|
1198 | } | |||
|
1199 | drawlines $id 0 | |||
|
1200 | set orad [expr {$linespc / 3}] | |||
|
1201 | set t [$canv create $shape [expr $x - $orad] [expr $y1 - $orad] \ | |||
|
1202 | [expr $x + $orad - 1] [expr $y1 + $orad - 1] \ | |||
|
1203 | -fill $ofill -outline $outline -width 1] | |||
|
1204 | $canv raise $t | |||
|
1205 | $canv bind $t <1> {selcanvline {} %x %y} | |||
|
1206 | set xt [xcoord [llength $displist] $level $lineno] | |||
|
1207 | if {[llength $currentparents] > 2} { | |||
|
1208 | set xt [expr {$xt + ([llength $currentparents] - 2) * $linespc}] | |||
|
1209 | } | |||
|
1210 | set rowtextx($lineno) $xt | |||
|
1211 | set idpos($id) [list $x $xt $y1] | |||
|
1212 | if {[info exists idtags($id)] || [info exists idheads($id)] | |||
|
1213 | || [info exists idotherrefs($id)] || [info exists idbookmarks($id)]} { | |||
|
1214 | set xt [drawtags $id $x $xt $y1] | |||
|
1215 | } | |||
|
1216 | set headline [lindex $commitinfo($id) 0] | |||
|
1217 | set name [lindex $commitinfo($id) 1] | |||
|
1218 | assignauthorcolor $name | |||
|
1219 | set fg $aucolormap($name) | |||
|
1220 | if {$id == $curid} { | |||
|
1221 | set fn $curidfont | |||
|
1222 | } else { | |||
|
1223 | set fn $mainfont | |||
|
1224 | } | |||
|
1225 | ||||
|
1226 | set date [lindex $commitinfo($id) 2] | |||
|
1227 | set linehtag($lineno) [$canv create text $xt $y1 -anchor w \ | |||
|
1228 | -text $headline -font $fn \ | |||
|
1229 | -fill $fg] | |||
|
1230 | $canv bind $linehtag($lineno) <<B3>> "rowmenu %X %Y $id" | |||
|
1231 | set linentag($lineno) [$canv2 create text 3 $y1 -anchor w \ | |||
|
1232 | -text $name -font $namefont \ | |||
|
1233 | -fill $fg] | |||
|
1234 | set linedtag($lineno) [$canv3 create text 3 $y1 -anchor w \ | |||
|
1235 | -text $date -font $mainfont \ | |||
|
1236 | -fill $fg] | |||
|
1237 | ||||
|
1238 | set olddlevel $level | |||
|
1239 | set olddisplist $displist | |||
|
1240 | set oldnlines [llength $displist] | |||
|
1241 | } | |||
|
1242 | ||||
|
1243 | proc drawtags {id x xt y1} { | |||
|
1244 | global bookmarkcurrent idtags idbookmarks idheads idotherrefs commitinfo | |||
|
1245 | global linespc lthickness | |||
|
1246 | global canv mainfont idline rowtextx | |||
|
1247 | ||||
|
1248 | set marks {} | |||
|
1249 | set nbookmarks 0 | |||
|
1250 | set ntags 0 | |||
|
1251 | set nheads 0 | |||
|
1252 | if {[info exists idtags($id)]} { | |||
|
1253 | set marks $idtags($id) | |||
|
1254 | set ntags [llength $marks] | |||
|
1255 | } | |||
|
1256 | if {[info exists idbookmarks($id)]} { | |||
|
1257 | set marks [concat $marks $idbookmarks($id)] | |||
|
1258 | set nbookmarks [llength $idbookmarks($id)] | |||
|
1259 | } | |||
|
1260 | if {[info exists idheads($id)]} { | |||
|
1261 | set headmark [lindex $commitinfo($id) 7] | |||
|
1262 | if {$headmark ne "default"} { | |||
|
1263 | lappend marks $headmark | |||
|
1264 | set nheads 1 | |||
|
1265 | } | |||
|
1266 | } | |||
|
1267 | if {$marks eq {}} { | |||
|
1268 | return $xt | |||
|
1269 | } | |||
|
1270 | ||||
|
1271 | set delta [expr {int(0.5 * ($linespc - $lthickness))}] | |||
|
1272 | set yt [expr $y1 - 0.5 * $linespc] | |||
|
1273 | set yb [expr $yt + $linespc - 1] | |||
|
1274 | set xvals {} | |||
|
1275 | set wvals {} | |||
|
1276 | foreach tag $marks { | |||
|
1277 | set wid [font measure $mainfont $tag] | |||
|
1278 | lappend xvals $xt | |||
|
1279 | lappend wvals $wid | |||
|
1280 | set xt [expr {$xt + $delta + $wid + $lthickness + $linespc}] | |||
|
1281 | } | |||
|
1282 | set t [$canv create line $x $y1 [lindex $xvals end] $y1 \ | |||
|
1283 | -width $lthickness -fill black -tags tag.$id] | |||
|
1284 | $canv lower $t | |||
|
1285 | foreach tag $marks x $xvals wid $wvals { | |||
|
1286 | set xl [expr $x + $delta] | |||
|
1287 | set xr [expr $x + $delta + $wid + $lthickness] | |||
|
1288 | if {[incr ntags -1] >= 0} { | |||
|
1289 | # draw a tag | |||
|
1290 | set t [$canv create polygon $x [expr $yt + $delta] $xl $yt \ | |||
|
1291 | $xr $yt $xr $yb $xl $yb $x [expr $yb - $delta] \ | |||
|
1292 | -width 1 -outline black -fill yellow -tags tag.$id] | |||
|
1293 | $canv bind $t <1> [list showtag $tag 1] | |||
|
1294 | set rowtextx($idline($id)) [expr {$xr + $linespc}] | |||
|
1295 | } elseif {[incr nbookmarks -1] >= 0} { | |||
|
1296 | # draw a tag | |||
|
1297 | set col "#7f7f7f" | |||
|
1298 | if {[string compare $bookmarkcurrent $tag] == 0} { | |||
|
1299 | set col "#bebebe" | |||
|
1300 | } | |||
|
1301 | set xl [expr $xl - $delta/2] | |||
|
1302 | $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \ | |||
|
1303 | -width 1 -outline black -fill $col -tags tag.$id | |||
|
1304 | } else { | |||
|
1305 | # draw a head or other ref | |||
|
1306 | if {[incr nheads -1] >= 0} { | |||
|
1307 | set col "#00ff00" | |||
|
1308 | } else { | |||
|
1309 | set col "#ddddff" | |||
|
1310 | } | |||
|
1311 | set xl [expr $xl - $delta/2] | |||
|
1312 | $canv create polygon $x $yt $xr $yt $xr $yb $x $yb \ | |||
|
1313 | -width 1 -outline black -fill $col -tags tag.$id | |||
|
1314 | } | |||
|
1315 | set t [$canv create text $xl $y1 -anchor w -text $tag \ | |||
|
1316 | -font $mainfont -tags tag.$id] | |||
|
1317 | if {$ntags >= 0} { | |||
|
1318 | $canv bind $t <1> [list showtag $tag 1] | |||
|
1319 | } | |||
|
1320 | } | |||
|
1321 | return $xt | |||
|
1322 | } | |||
|
1323 | ||||
|
1324 | proc notecrossings {id lo hi corner} { | |||
|
1325 | global olddisplist crossings cornercrossings | |||
|
1326 | ||||
|
1327 | for {set i $lo} {[incr i] < $hi} {} { | |||
|
1328 | set p [lindex $olddisplist $i] | |||
|
1329 | if {$p == {}} continue | |||
|
1330 | if {$i == $corner} { | |||
|
1331 | if {![info exists cornercrossings($id)] | |||
|
1332 | || [lsearch -exact $cornercrossings($id) $p] < 0} { | |||
|
1333 | lappend cornercrossings($id) $p | |||
|
1334 | } | |||
|
1335 | if {![info exists cornercrossings($p)] | |||
|
1336 | || [lsearch -exact $cornercrossings($p) $id] < 0} { | |||
|
1337 | lappend cornercrossings($p) $id | |||
|
1338 | } | |||
|
1339 | } else { | |||
|
1340 | if {![info exists crossings($id)] | |||
|
1341 | || [lsearch -exact $crossings($id) $p] < 0} { | |||
|
1342 | lappend crossings($id) $p | |||
|
1343 | } | |||
|
1344 | if {![info exists crossings($p)] | |||
|
1345 | || [lsearch -exact $crossings($p) $id] < 0} { | |||
|
1346 | lappend crossings($p) $id | |||
|
1347 | } | |||
|
1348 | } | |||
|
1349 | } | |||
|
1350 | } | |||
|
1351 | ||||
|
1352 | proc xcoord {i level ln} { | |||
|
1353 | global canvx0 xspc1 xspc2 | |||
|
1354 | ||||
|
1355 | set x [expr {$canvx0 + $i * $xspc1($ln)}] | |||
|
1356 | if {$i > 0 && $i == $level} { | |||
|
1357 | set x [expr {$x + 0.5 * ($xspc2 - $xspc1($ln))}] | |||
|
1358 | } elseif {$i > $level} { | |||
|
1359 | set x [expr {$x + $xspc2 - $xspc1($ln)}] | |||
|
1360 | } | |||
|
1361 | return $x | |||
|
1362 | } | |||
|
1363 | ||||
|
1364 | # it seems Tk can't draw arrows on the end of diagonal line segments... | |||
|
1365 | proc trimdiagend {line} { | |||
|
1366 | while {[llength $line] > 4} { | |||
|
1367 | set x1 [lindex $line end-3] | |||
|
1368 | set y1 [lindex $line end-2] | |||
|
1369 | set x2 [lindex $line end-1] | |||
|
1370 | set y2 [lindex $line end] | |||
|
1371 | if {($x1 == $x2) != ($y1 == $y2)} break | |||
|
1372 | set line [lreplace $line end-1 end] | |||
|
1373 | } | |||
|
1374 | return $line | |||
|
1375 | } | |||
|
1376 | ||||
|
1377 | proc trimdiagstart {line} { | |||
|
1378 | while {[llength $line] > 4} { | |||
|
1379 | set x1 [lindex $line 0] | |||
|
1380 | set y1 [lindex $line 1] | |||
|
1381 | set x2 [lindex $line 2] | |||
|
1382 | set y2 [lindex $line 3] | |||
|
1383 | if {($x1 == $x2) != ($y1 == $y2)} break | |||
|
1384 | set line [lreplace $line 0 1] | |||
|
1385 | } | |||
|
1386 | return $line | |||
|
1387 | } | |||
|
1388 | ||||
|
1389 | proc drawslants {id needonscreen nohs} { | |||
|
1390 | global canv mainline mainlinearrow sidelines | |||
|
1391 | global canvx0 canvy xspc1 xspc2 lthickness | |||
|
1392 | global currentparents dupparents | |||
|
1393 | global lthickness linespc canvy colormap lineno geometry | |||
|
1394 | global maxgraphpct maxwidth | |||
|
1395 | global displist onscreen lastuse | |||
|
1396 | global parents commitlisted | |||
|
1397 | global oldnlines olddlevel olddisplist | |||
|
1398 | global nhyperspace numcommits nnewparents | |||
|
1399 | ||||
|
1400 | if {$lineno < 0} { | |||
|
1401 | lappend displist $id | |||
|
1402 | set onscreen($id) 1 | |||
|
1403 | return 0 | |||
|
1404 | } | |||
|
1405 | ||||
|
1406 | set y1 [expr {$canvy - $linespc}] | |||
|
1407 | set y2 $canvy | |||
|
1408 | ||||
|
1409 | # work out what we need to get back on screen | |||
|
1410 | set reins {} | |||
|
1411 | if {$onscreen($id) < 0} { | |||
|
1412 | # next to do isn't displayed, better get it on screen... | |||
|
1413 | lappend reins [list $id 0] | |||
|
1414 | } | |||
|
1415 | # make sure all the previous commits's parents are on the screen | |||
|
1416 | foreach p $currentparents { | |||
|
1417 | if {$onscreen($p) < 0} { | |||
|
1418 | lappend reins [list $p 0] | |||
|
1419 | } | |||
|
1420 | } | |||
|
1421 | # bring back anything requested by caller | |||
|
1422 | if {$needonscreen ne {}} { | |||
|
1423 | lappend reins $needonscreen | |||
|
1424 | } | |||
|
1425 | ||||
|
1426 | # try the shortcut | |||
|
1427 | if {$currentparents == $id && $onscreen($id) == 0 && $reins eq {}} { | |||
|
1428 | set dlevel $olddlevel | |||
|
1429 | set x [xcoord $dlevel $dlevel $lineno] | |||
|
1430 | set mainline($id) [list $x $y1] | |||
|
1431 | set mainlinearrow($id) none | |||
|
1432 | set lastuse($id) $lineno | |||
|
1433 | set displist [lreplace $displist $dlevel $dlevel $id] | |||
|
1434 | set onscreen($id) 1 | |||
|
1435 | set xspc1([expr {$lineno + 1}]) $xspc1($lineno) | |||
|
1436 | return $dlevel | |||
|
1437 | } | |||
|
1438 | ||||
|
1439 | # update displist | |||
|
1440 | set displist [lreplace $displist $olddlevel $olddlevel] | |||
|
1441 | set j $olddlevel | |||
|
1442 | foreach p $currentparents { | |||
|
1443 | set lastuse($p) $lineno | |||
|
1444 | if {$onscreen($p) == 0} { | |||
|
1445 | set displist [linsert $displist $j $p] | |||
|
1446 | set onscreen($p) 1 | |||
|
1447 | incr j | |||
|
1448 | } | |||
|
1449 | } | |||
|
1450 | if {$onscreen($id) == 0} { | |||
|
1451 | lappend displist $id | |||
|
1452 | set onscreen($id) 1 | |||
|
1453 | } | |||
|
1454 | ||||
|
1455 | # remove the null entry if present | |||
|
1456 | set nullentry [lsearch -exact $displist {}] | |||
|
1457 | if {$nullentry >= 0} { | |||
|
1458 | set displist [lreplace $displist $nullentry $nullentry] | |||
|
1459 | } | |||
|
1460 | ||||
|
1461 | # bring back the ones we need now (if we did it earlier | |||
|
1462 | # it would change displist and invalidate olddlevel) | |||
|
1463 | foreach pi $reins { | |||
|
1464 | # test again in case of duplicates in reins | |||
|
1465 | set p [lindex $pi 0] | |||
|
1466 | if {$onscreen($p) < 0} { | |||
|
1467 | set onscreen($p) 1 | |||
|
1468 | set lastuse($p) $lineno | |||
|
1469 | set displist [linsert $displist [lindex $pi 1] $p] | |||
|
1470 | incr nhyperspace -1 | |||
|
1471 | } | |||
|
1472 | } | |||
|
1473 | ||||
|
1474 | set lastuse($id) $lineno | |||
|
1475 | ||||
|
1476 | # see if we need to make any lines jump off into hyperspace | |||
|
1477 | set displ [llength $displist] | |||
|
1478 | if {$displ > $maxwidth} { | |||
|
1479 | set ages {} | |||
|
1480 | foreach x $displist { | |||
|
1481 | lappend ages [list $lastuse($x) $x] | |||
|
1482 | } | |||
|
1483 | set ages [lsort -integer -index 0 $ages] | |||
|
1484 | set k 0 | |||
|
1485 | while {$displ > $maxwidth} { | |||
|
1486 | set use [lindex $ages $k 0] | |||
|
1487 | set victim [lindex $ages $k 1] | |||
|
1488 | if {$use >= $lineno - 5} break | |||
|
1489 | incr k | |||
|
1490 | if {[lsearch -exact $nohs $victim] >= 0} continue | |||
|
1491 | set i [lsearch -exact $displist $victim] | |||
|
1492 | set displist [lreplace $displist $i $i] | |||
|
1493 | set onscreen($victim) -1 | |||
|
1494 | incr nhyperspace | |||
|
1495 | incr displ -1 | |||
|
1496 | if {$i < $nullentry} { | |||
|
1497 | incr nullentry -1 | |||
|
1498 | } | |||
|
1499 | set x [lindex $mainline($victim) end-1] | |||
|
1500 | lappend mainline($victim) $x $y1 | |||
|
1501 | set line [trimdiagend $mainline($victim)] | |||
|
1502 | set arrow "last" | |||
|
1503 | if {$mainlinearrow($victim) ne "none"} { | |||
|
1504 | set line [trimdiagstart $line] | |||
|
1505 | set arrow "both" | |||
|
1506 | } | |||
|
1507 | lappend sidelines($victim) [list $line 1 $arrow] | |||
|
1508 | unset mainline($victim) | |||
|
1509 | } | |||
|
1510 | } | |||
|
1511 | ||||
|
1512 | set dlevel [lsearch -exact $displist $id] | |||
|
1513 | ||||
|
1514 | # If we are reducing, put in a null entry | |||
|
1515 | if {$displ < $oldnlines} { | |||
|
1516 | # does the next line look like a merge? | |||
|
1517 | # i.e. does it have > 1 new parent? | |||
|
1518 | if {$nnewparents($id) > 1} { | |||
|
1519 | set i [expr {$dlevel + 1}] | |||
|
1520 | } elseif {$nnewparents([lindex $olddisplist $olddlevel]) == 0} { | |||
|
1521 | set i $olddlevel | |||
|
1522 | if {$nullentry >= 0 && $nullentry < $i} { | |||
|
1523 | incr i -1 | |||
|
1524 | } | |||
|
1525 | } elseif {$nullentry >= 0} { | |||
|
1526 | set i $nullentry | |||
|
1527 | while {$i < $displ | |||
|
1528 | && [lindex $olddisplist $i] == [lindex $displist $i]} { | |||
|
1529 | incr i | |||
|
1530 | } | |||
|
1531 | } else { | |||
|
1532 | set i $olddlevel | |||
|
1533 | if {$dlevel >= $i} { | |||
|
1534 | incr i | |||
|
1535 | } | |||
|
1536 | } | |||
|
1537 | if {$i < $displ} { | |||
|
1538 | set displist [linsert $displist $i {}] | |||
|
1539 | incr displ | |||
|
1540 | if {$dlevel >= $i} { | |||
|
1541 | incr dlevel | |||
|
1542 | } | |||
|
1543 | } | |||
|
1544 | } | |||
|
1545 | ||||
|
1546 | # decide on the line spacing for the next line | |||
|
1547 | set lj [expr {$lineno + 1}] | |||
|
1548 | set maxw [expr {$maxgraphpct * $geometry(canv1) / 100}] | |||
|
1549 | if {$displ <= 1 || $canvx0 + $displ * $xspc2 <= $maxw} { | |||
|
1550 | set xspc1($lj) $xspc2 | |||
|
1551 | } else { | |||
|
1552 | set xspc1($lj) [expr {($maxw - $canvx0 - $xspc2) / ($displ - 1)}] | |||
|
1553 | if {$xspc1($lj) < $lthickness} { | |||
|
1554 | set xspc1($lj) $lthickness | |||
|
1555 | } | |||
|
1556 | } | |||
|
1557 | ||||
|
1558 | foreach idi $reins { | |||
|
1559 | set id [lindex $idi 0] | |||
|
1560 | set j [lsearch -exact $displist $id] | |||
|
1561 | set xj [xcoord $j $dlevel $lj] | |||
|
1562 | set mainline($id) [list $xj $y2] | |||
|
1563 | set mainlinearrow($id) first | |||
|
1564 | } | |||
|
1565 | ||||
|
1566 | set i -1 | |||
|
1567 | foreach id $olddisplist { | |||
|
1568 | incr i | |||
|
1569 | if {$id == {}} continue | |||
|
1570 | if {$onscreen($id) <= 0} continue | |||
|
1571 | set xi [xcoord $i $olddlevel $lineno] | |||
|
1572 | if {$i == $olddlevel} { | |||
|
1573 | foreach p $currentparents { | |||
|
1574 | set j [lsearch -exact $displist $p] | |||
|
1575 | set coords [list $xi $y1] | |||
|
1576 | set xj [xcoord $j $dlevel $lj] | |||
|
1577 | if {$xj < $xi - $linespc} { | |||
|
1578 | lappend coords [expr {$xj + $linespc}] $y1 | |||
|
1579 | notecrossings $p $j $i [expr {$j + 1}] | |||
|
1580 | } elseif {$xj > $xi + $linespc} { | |||
|
1581 | lappend coords [expr {$xj - $linespc}] $y1 | |||
|
1582 | notecrossings $p $i $j [expr {$j - 1}] | |||
|
1583 | } | |||
|
1584 | if {[lsearch -exact $dupparents $p] >= 0} { | |||
|
1585 | # draw a double-width line to indicate the doubled parent | |||
|
1586 | lappend coords $xj $y2 | |||
|
1587 | lappend sidelines($p) [list $coords 2 none] | |||
|
1588 | if {![info exists mainline($p)]} { | |||
|
1589 | set mainline($p) [list $xj $y2] | |||
|
1590 | set mainlinearrow($p) none | |||
|
1591 | } | |||
|
1592 | } else { | |||
|
1593 | # normal case, no parent duplicated | |||
|
1594 | set yb $y2 | |||
|
1595 | set dx [expr {abs($xi - $xj)}] | |||
|
1596 | if {0 && $dx < $linespc} { | |||
|
1597 | set yb [expr {$y1 + $dx}] | |||
|
1598 | } | |||
|
1599 | if {![info exists mainline($p)]} { | |||
|
1600 | if {$xi != $xj} { | |||
|
1601 | lappend coords $xj $yb | |||
|
1602 | } | |||
|
1603 | set mainline($p) $coords | |||
|
1604 | set mainlinearrow($p) none | |||
|
1605 | } else { | |||
|
1606 | lappend coords $xj $yb | |||
|
1607 | if {$yb < $y2} { | |||
|
1608 | lappend coords $xj $y2 | |||
|
1609 | } | |||
|
1610 | lappend sidelines($p) [list $coords 1 none] | |||
|
1611 | } | |||
|
1612 | } | |||
|
1613 | } | |||
|
1614 | } else { | |||
|
1615 | set j $i | |||
|
1616 | if {[lindex $displist $i] != $id} { | |||
|
1617 | set j [lsearch -exact $displist $id] | |||
|
1618 | } | |||
|
1619 | if {$j != $i || $xspc1($lineno) != $xspc1($lj) | |||
|
1620 | || ($olddlevel < $i && $i < $dlevel) | |||
|
1621 | || ($dlevel < $i && $i < $olddlevel)} { | |||
|
1622 | set xj [xcoord $j $dlevel $lj] | |||
|
1623 | lappend mainline($id) $xi $y1 $xj $y2 | |||
|
1624 | } | |||
|
1625 | } | |||
|
1626 | } | |||
|
1627 | return $dlevel | |||
|
1628 | } | |||
|
1629 | ||||
|
1630 | # search for x in a list of lists | |||
|
1631 | proc llsearch {llist x} { | |||
|
1632 | set i 0 | |||
|
1633 | foreach l $llist { | |||
|
1634 | if {$l == $x || [lsearch -exact $l $x] >= 0} { | |||
|
1635 | return $i | |||
|
1636 | } | |||
|
1637 | incr i | |||
|
1638 | } | |||
|
1639 | return -1 | |||
|
1640 | } | |||
|
1641 | ||||
|
1642 | proc drawmore {reading} { | |||
|
1643 | global displayorder numcommits ncmupdate nextupdate | |||
|
1644 | global stopped nhyperspace parents commitlisted | |||
|
1645 | global maxwidth onscreen displist currentparents olddlevel | |||
|
1646 | ||||
|
1647 | set n [llength $displayorder] | |||
|
1648 | while {$numcommits < $n} { | |||
|
1649 | set id [lindex $displayorder $numcommits] | |||
|
1650 | set ctxend [expr {$numcommits + 10}] | |||
|
1651 | if {!$reading && $ctxend > $n} { | |||
|
1652 | set ctxend $n | |||
|
1653 | } | |||
|
1654 | set dlist {} | |||
|
1655 | if {$numcommits > 0} { | |||
|
1656 | set dlist [lreplace $displist $olddlevel $olddlevel] | |||
|
1657 | set i $olddlevel | |||
|
1658 | foreach p $currentparents { | |||
|
1659 | if {$onscreen($p) == 0} { | |||
|
1660 | set dlist [linsert $dlist $i $p] | |||
|
1661 | incr i | |||
|
1662 | } | |||
|
1663 | } | |||
|
1664 | } | |||
|
1665 | set nohs {} | |||
|
1666 | set reins {} | |||
|
1667 | set isfat [expr {[llength $dlist] > $maxwidth}] | |||
|
1668 | if {$nhyperspace > 0 || $isfat} { | |||
|
1669 | if {$ctxend > $n} break | |||
|
1670 | # work out what to bring back and | |||
|
1671 | # what we want to don't want to send into hyperspace | |||
|
1672 | set room 1 | |||
|
1673 | for {set k $numcommits} {$k < $ctxend} {incr k} { | |||
|
1674 | set x [lindex $displayorder $k] | |||
|
1675 | set i [llsearch $dlist $x] | |||
|
1676 | if {$i < 0} { | |||
|
1677 | set i [llength $dlist] | |||
|
1678 | lappend dlist $x | |||
|
1679 | } | |||
|
1680 | if {[lsearch -exact $nohs $x] < 0} { | |||
|
1681 | lappend nohs $x | |||
|
1682 | } | |||
|
1683 | if {$reins eq {} && $onscreen($x) < 0 && $room} { | |||
|
1684 | set reins [list $x $i] | |||
|
1685 | } | |||
|
1686 | set newp {} | |||
|
1687 | if {[info exists commitlisted($x)]} { | |||
|
1688 | set right 0 | |||
|
1689 | foreach p $parents($x) { | |||
|
1690 | if {[llsearch $dlist $p] < 0} { | |||
|
1691 | lappend newp $p | |||
|
1692 | if {[lsearch -exact $nohs $p] < 0} { | |||
|
1693 | lappend nohs $p | |||
|
1694 | } | |||
|
1695 | if {$reins eq {} && $onscreen($p) < 0 && $room} { | |||
|
1696 | set reins [list $p [expr {$i + $right}]] | |||
|
1697 | } | |||
|
1698 | } | |||
|
1699 | set right 1 | |||
|
1700 | } | |||
|
1701 | } | |||
|
1702 | set l [lindex $dlist $i] | |||
|
1703 | if {[llength $l] == 1} { | |||
|
1704 | set l $newp | |||
|
1705 | } else { | |||
|
1706 | set j [lsearch -exact $l $x] | |||
|
1707 | set l [concat [lreplace $l $j $j] $newp] | |||
|
1708 | } | |||
|
1709 | set dlist [lreplace $dlist $i $i $l] | |||
|
1710 | if {$room && $isfat && [llength $newp] <= 1} { | |||
|
1711 | set room 0 | |||
|
1712 | } | |||
|
1713 | } | |||
|
1714 | } | |||
|
1715 | ||||
|
1716 | set dlevel [drawslants $id $reins $nohs] | |||
|
1717 | drawcommitline $dlevel | |||
|
1718 | if {[clock clicks -milliseconds] >= $nextupdate | |||
|
1719 | && $numcommits >= $ncmupdate} { | |||
|
1720 | doupdate $reading | |||
|
1721 | if {$stopped} break | |||
|
1722 | } | |||
|
1723 | } | |||
|
1724 | } | |||
|
1725 | ||||
|
1726 | # level here is an index in todo | |||
|
1727 | proc updatetodo {level noshortcut} { | |||
|
1728 | global ncleft todo nnewparents | |||
|
1729 | global commitlisted parents onscreen | |||
|
1730 | ||||
|
1731 | set id [lindex $todo $level] | |||
|
1732 | set olds {} | |||
|
1733 | if {[info exists commitlisted($id)]} { | |||
|
1734 | foreach p $parents($id) { | |||
|
1735 | if {[lsearch -exact $olds $p] < 0} { | |||
|
1736 | lappend olds $p | |||
|
1737 | } | |||
|
1738 | } | |||
|
1739 | } | |||
|
1740 | if {!$noshortcut && [llength $olds] == 1} { | |||
|
1741 | set p [lindex $olds 0] | |||
|
1742 | if {$ncleft($p) == 1 && [lsearch -exact $todo $p] < 0} { | |||
|
1743 | set ncleft($p) 0 | |||
|
1744 | set todo [lreplace $todo $level $level $p] | |||
|
1745 | set onscreen($p) 0 | |||
|
1746 | set nnewparents($id) 1 | |||
|
1747 | return 0 | |||
|
1748 | } | |||
|
1749 | } | |||
|
1750 | ||||
|
1751 | set todo [lreplace $todo $level $level] | |||
|
1752 | set i $level | |||
|
1753 | set n 0 | |||
|
1754 | foreach p $olds { | |||
|
1755 | incr ncleft($p) -1 | |||
|
1756 | set k [lsearch -exact $todo $p] | |||
|
1757 | if {$k < 0} { | |||
|
1758 | set todo [linsert $todo $i $p] | |||
|
1759 | set onscreen($p) 0 | |||
|
1760 | incr i | |||
|
1761 | incr n | |||
|
1762 | } | |||
|
1763 | } | |||
|
1764 | set nnewparents($id) $n | |||
|
1765 | ||||
|
1766 | return 1 | |||
|
1767 | } | |||
|
1768 | ||||
|
1769 | proc decidenext {{noread 0}} { | |||
|
1770 | global ncleft todo | |||
|
1771 | global datemode cdate | |||
|
1772 | global commitinfo | |||
|
1773 | ||||
|
1774 | # choose which one to do next time around | |||
|
1775 | set todol [llength $todo] | |||
|
1776 | set level -1 | |||
|
1777 | set latest {} | |||
|
1778 | for {set k $todol} {[incr k -1] >= 0} {} { | |||
|
1779 | set p [lindex $todo $k] | |||
|
1780 | if {$ncleft($p) == 0} { | |||
|
1781 | if {$datemode} { | |||
|
1782 | if {![info exists commitinfo($p)]} { | |||
|
1783 | if {$noread} { | |||
|
1784 | return {} | |||
|
1785 | } | |||
|
1786 | readcommit $p | |||
|
1787 | } | |||
|
1788 | if {$latest == {} || $cdate($p) > $latest} { | |||
|
1789 | set level $k | |||
|
1790 | set latest $cdate($p) | |||
|
1791 | } | |||
|
1792 | } else { | |||
|
1793 | set level $k | |||
|
1794 | break | |||
|
1795 | } | |||
|
1796 | } | |||
|
1797 | } | |||
|
1798 | if {$level < 0} { | |||
|
1799 | if {$todo != {}} { | |||
|
1800 | puts "ERROR: none of the pending commits can be done yet:" | |||
|
1801 | foreach p $todo { | |||
|
1802 | puts " $p ($ncleft($p))" | |||
|
1803 | } | |||
|
1804 | } | |||
|
1805 | return -1 | |||
|
1806 | } | |||
|
1807 | ||||
|
1808 | return $level | |||
|
1809 | } | |||
|
1810 | ||||
|
1811 | proc drawcommit {id} { | |||
|
1812 | global phase todo nchildren datemode nextupdate | |||
|
1813 | global numcommits ncmupdate displayorder todo onscreen | |||
|
1814 | ||||
|
1815 | if {$phase != "incrdraw"} { | |||
|
1816 | set phase incrdraw | |||
|
1817 | set displayorder {} | |||
|
1818 | set todo {} | |||
|
1819 | initgraph | |||
|
1820 | } | |||
|
1821 | if {$nchildren($id) == 0} { | |||
|
1822 | lappend todo $id | |||
|
1823 | set onscreen($id) 0 | |||
|
1824 | } | |||
|
1825 | set level [decidenext 1] | |||
|
1826 | if {$level == {} || $id != [lindex $todo $level]} { | |||
|
1827 | return | |||
|
1828 | } | |||
|
1829 | while 1 { | |||
|
1830 | lappend displayorder [lindex $todo $level] | |||
|
1831 | if {[updatetodo $level $datemode]} { | |||
|
1832 | set level [decidenext 1] | |||
|
1833 | if {$level == {}} break | |||
|
1834 | } | |||
|
1835 | set id [lindex $todo $level] | |||
|
1836 | if {![info exists commitlisted($id)]} { | |||
|
1837 | break | |||
|
1838 | } | |||
|
1839 | } | |||
|
1840 | drawmore 1 | |||
|
1841 | } | |||
|
1842 | ||||
|
1843 | proc finishcommits {} { | |||
|
1844 | global phase | |||
|
1845 | global canv mainfont ctext maincursor textcursor | |||
|
1846 | ||||
|
1847 | if {$phase != "incrdraw"} { | |||
|
1848 | $canv delete all | |||
|
1849 | $canv create text 3 3 -anchor nw -text "No commits selected" \ | |||
|
1850 | -font $mainfont -tags textitems | |||
|
1851 | set phase {} | |||
|
1852 | } else { | |||
|
1853 | drawrest | |||
|
1854 | } | |||
|
1855 | . config -cursor $maincursor | |||
|
1856 | settextcursor $textcursor | |||
|
1857 | } | |||
|
1858 | ||||
|
1859 | # Don't change the text pane cursor if it is currently the hand cursor, | |||
|
1860 | # showing that we are over a sha1 ID link. | |||
|
1861 | proc settextcursor {c} { | |||
|
1862 | global ctext curtextcursor | |||
|
1863 | ||||
|
1864 | if {[$ctext cget -cursor] == $curtextcursor} { | |||
|
1865 | $ctext config -cursor $c | |||
|
1866 | } | |||
|
1867 | set curtextcursor $c | |||
|
1868 | } | |||
|
1869 | ||||
|
1870 | proc drawgraph {} { | |||
|
1871 | global nextupdate startmsecs ncmupdate | |||
|
1872 | global displayorder onscreen | |||
|
1873 | ||||
|
1874 | if {$displayorder == {}} return | |||
|
1875 | set startmsecs [clock clicks -milliseconds] | |||
|
1876 | set nextupdate [expr $startmsecs + 100] | |||
|
1877 | set ncmupdate 1 | |||
|
1878 | initgraph | |||
|
1879 | foreach id $displayorder { | |||
|
1880 | set onscreen($id) 0 | |||
|
1881 | } | |||
|
1882 | drawmore 0 | |||
|
1883 | } | |||
|
1884 | ||||
|
1885 | proc drawrest {} { | |||
|
1886 | global phase stopped redisplaying selectedline | |||
|
1887 | global datemode todo displayorder | |||
|
1888 | global numcommits ncmupdate | |||
|
1889 | global nextupdate startmsecs | |||
|
1890 | ||||
|
1891 | set level [decidenext] | |||
|
1892 | if {$level >= 0} { | |||
|
1893 | set phase drawgraph | |||
|
1894 | while 1 { | |||
|
1895 | lappend displayorder [lindex $todo $level] | |||
|
1896 | set hard [updatetodo $level $datemode] | |||
|
1897 | if {$hard} { | |||
|
1898 | set level [decidenext] | |||
|
1899 | if {$level < 0} break | |||
|
1900 | } | |||
|
1901 | } | |||
|
1902 | drawmore 0 | |||
|
1903 | } | |||
|
1904 | set phase {} | |||
|
1905 | set drawmsecs [expr [clock clicks -milliseconds] - $startmsecs] | |||
|
1906 | #puts "overall $drawmsecs ms for $numcommits commits" | |||
|
1907 | if {$redisplaying} { | |||
|
1908 | if {$stopped == 0 && [info exists selectedline]} { | |||
|
1909 | selectline $selectedline 0 | |||
|
1910 | } | |||
|
1911 | if {$stopped == 1} { | |||
|
1912 | set stopped 0 | |||
|
1913 | after idle drawgraph | |||
|
1914 | } else { | |||
|
1915 | set redisplaying 0 | |||
|
1916 | } | |||
|
1917 | } | |||
|
1918 | } | |||
|
1919 | ||||
|
1920 | proc findmatches {f} { | |||
|
1921 | global findtype foundstring foundstrlen | |||
|
1922 | if {$findtype == "Regexp"} { | |||
|
1923 | set matches [regexp -indices -all -inline $foundstring $f] | |||
|
1924 | } else { | |||
|
1925 | if {$findtype == "IgnCase"} { | |||
|
1926 | set str [string tolower $f] | |||
|
1927 | } else { | |||
|
1928 | set str $f | |||
|
1929 | } | |||
|
1930 | set matches {} | |||
|
1931 | set i 0 | |||
|
1932 | while {[set j [string first $foundstring $str $i]] >= 0} { | |||
|
1933 | lappend matches [list $j [expr $j+$foundstrlen-1]] | |||
|
1934 | set i [expr $j + $foundstrlen] | |||
|
1935 | } | |||
|
1936 | } | |||
|
1937 | return $matches | |||
|
1938 | } | |||
|
1939 | ||||
|
1940 | proc dofind {} { | |||
|
1941 | global findtype findloc findstring markedmatches commitinfo | |||
|
1942 | global numcommits lineid linehtag linentag linedtag | |||
|
1943 | global mainfont namefont canv canv2 canv3 selectedline | |||
|
1944 | global matchinglines foundstring foundstrlen | |||
|
1945 | ||||
|
1946 | stopfindproc | |||
|
1947 | unmarkmatches | |||
|
1948 | focus . | |||
|
1949 | set matchinglines {} | |||
|
1950 | if {$findloc == "Pickaxe"} { | |||
|
1951 | findpatches | |||
|
1952 | return | |||
|
1953 | } | |||
|
1954 | if {$findtype == "IgnCase"} { | |||
|
1955 | set foundstring [string tolower $findstring] | |||
|
1956 | } else { | |||
|
1957 | set foundstring $findstring | |||
|
1958 | } | |||
|
1959 | set foundstrlen [string length $findstring] | |||
|
1960 | if {$foundstrlen == 0} return | |||
|
1961 | if {$findloc == "Files"} { | |||
|
1962 | findfiles | |||
|
1963 | return | |||
|
1964 | } | |||
|
1965 | if {![info exists selectedline]} { | |||
|
1966 | set oldsel -1 | |||
|
1967 | } else { | |||
|
1968 | set oldsel $selectedline | |||
|
1969 | } | |||
|
1970 | set didsel 0 | |||
|
1971 | set fldtypes {Headline Author Date CDate Comment} | |||
|
1972 | for {set l 0} {$l < $numcommits} {incr l} { | |||
|
1973 | set id $lineid($l) | |||
|
1974 | set info $commitinfo($id) | |||
|
1975 | set doesmatch 0 | |||
|
1976 | foreach f $info ty $fldtypes { | |||
|
1977 | if {$findloc != "All fields" && $findloc != $ty} { | |||
|
1978 | continue | |||
|
1979 | } | |||
|
1980 | set matches [findmatches $f] | |||
|
1981 | if {$matches == {}} continue | |||
|
1982 | set doesmatch 1 | |||
|
1983 | if {$ty == "Headline"} { | |||
|
1984 | markmatches $canv $l $f $linehtag($l) $matches $mainfont | |||
|
1985 | } elseif {$ty == "Author"} { | |||
|
1986 | markmatches $canv2 $l $f $linentag($l) $matches $namefont | |||
|
1987 | } elseif {$ty == "Date"} { | |||
|
1988 | markmatches $canv3 $l $f $linedtag($l) $matches $mainfont | |||
|
1989 | } | |||
|
1990 | } | |||
|
1991 | if {$doesmatch} { | |||
|
1992 | lappend matchinglines $l | |||
|
1993 | if {!$didsel && $l > $oldsel} { | |||
|
1994 | findselectline $l | |||
|
1995 | set didsel 1 | |||
|
1996 | } | |||
|
1997 | } | |||
|
1998 | } | |||
|
1999 | if {$matchinglines == {}} { | |||
|
2000 | bell | |||
|
2001 | } elseif {!$didsel} { | |||
|
2002 | findselectline [lindex $matchinglines 0] | |||
|
2003 | } | |||
|
2004 | } | |||
|
2005 | ||||
|
2006 | proc findselectline {l} { | |||
|
2007 | global findloc commentend ctext | |||
|
2008 | selectline $l 1 | |||
|
2009 | if {$findloc == "All fields" || $findloc == "Comments"} { | |||
|
2010 | # highlight the matches in the comments | |||
|
2011 | set f [$ctext get 1.0 $commentend] | |||
|
2012 | set matches [findmatches $f] | |||
|
2013 | foreach match $matches { | |||
|
2014 | set start [lindex $match 0] | |||
|
2015 | set end [expr [lindex $match 1] + 1] | |||
|
2016 | $ctext tag add found "1.0 + $start c" "1.0 + $end c" | |||
|
2017 | } | |||
|
2018 | } | |||
|
2019 | } | |||
|
2020 | ||||
|
2021 | proc findnext {restart} { | |||
|
2022 | global matchinglines selectedline | |||
|
2023 | if {![info exists matchinglines]} { | |||
|
2024 | if {$restart} { | |||
|
2025 | dofind | |||
|
2026 | } | |||
|
2027 | return | |||
|
2028 | } | |||
|
2029 | if {![info exists selectedline]} return | |||
|
2030 | foreach l $matchinglines { | |||
|
2031 | if {$l > $selectedline} { | |||
|
2032 | findselectline $l | |||
|
2033 | return | |||
|
2034 | } | |||
|
2035 | } | |||
|
2036 | bell | |||
|
2037 | } | |||
|
2038 | ||||
|
2039 | proc findprev {} { | |||
|
2040 | global matchinglines selectedline | |||
|
2041 | if {![info exists matchinglines]} { | |||
|
2042 | dofind | |||
|
2043 | return | |||
|
2044 | } | |||
|
2045 | if {![info exists selectedline]} return | |||
|
2046 | set prev {} | |||
|
2047 | foreach l $matchinglines { | |||
|
2048 | if {$l >= $selectedline} break | |||
|
2049 | set prev $l | |||
|
2050 | } | |||
|
2051 | if {$prev != {}} { | |||
|
2052 | findselectline $prev | |||
|
2053 | } else { | |||
|
2054 | bell | |||
|
2055 | } | |||
|
2056 | } | |||
|
2057 | ||||
|
2058 | proc findlocchange {name ix op} { | |||
|
2059 | global findloc findtype findtypemenu | |||
|
2060 | if {$findloc == "Pickaxe"} { | |||
|
2061 | set findtype Exact | |||
|
2062 | set state disabled | |||
|
2063 | } else { | |||
|
2064 | set state normal | |||
|
2065 | } | |||
|
2066 | $findtypemenu entryconf 1 -state $state | |||
|
2067 | $findtypemenu entryconf 2 -state $state | |||
|
2068 | } | |||
|
2069 | ||||
|
2070 | proc stopfindproc {{done 0}} { | |||
|
2071 | global findprocpid findprocfile findids | |||
|
2072 | global ctext findoldcursor phase maincursor textcursor | |||
|
2073 | global findinprogress | |||
|
2074 | ||||
|
2075 | catch {unset findids} | |||
|
2076 | if {[info exists findprocpid]} { | |||
|
2077 | if {!$done} { | |||
|
2078 | catch {exec kill $findprocpid} | |||
|
2079 | } | |||
|
2080 | catch {close $findprocfile} | |||
|
2081 | unset findprocpid | |||
|
2082 | } | |||
|
2083 | if {[info exists findinprogress]} { | |||
|
2084 | unset findinprogress | |||
|
2085 | if {$phase != "incrdraw"} { | |||
|
2086 | . config -cursor $maincursor | |||
|
2087 | settextcursor $textcursor | |||
|
2088 | } | |||
|
2089 | } | |||
|
2090 | } | |||
|
2091 | ||||
|
2092 | proc findpatches {} { | |||
|
2093 | global findstring selectedline numcommits | |||
|
2094 | global findprocpid findprocfile | |||
|
2095 | global finddidsel ctext lineid findinprogress | |||
|
2096 | global findinsertpos | |||
|
2097 | global env | |||
|
2098 | ||||
|
2099 | if {$numcommits == 0} return | |||
|
2100 | ||||
|
2101 | # make a list of all the ids to search, starting at the one | |||
|
2102 | # after the selected line (if any) | |||
|
2103 | if {[info exists selectedline]} { | |||
|
2104 | set l $selectedline | |||
|
2105 | } else { | |||
|
2106 | set l -1 | |||
|
2107 | } | |||
|
2108 | set inputids {} | |||
|
2109 | for {set i 0} {$i < $numcommits} {incr i} { | |||
|
2110 | if {[incr l] >= $numcommits} { | |||
|
2111 | set l 0 | |||
|
2112 | } | |||
|
2113 | append inputids $lineid($l) "\n" | |||
|
2114 | } | |||
|
2115 | ||||
|
2116 | if {[catch { | |||
|
2117 | set f [open [list | $env(HG) --config ui.report_untrusted=false debug-diff-tree --stdin -s -r -S$findstring << $inputids] r] | |||
|
2118 | } err]} { | |||
|
2119 | error_popup "Error starting search process: $err" | |||
|
2120 | return | |||
|
2121 | } | |||
|
2122 | ||||
|
2123 | set findinsertpos end | |||
|
2124 | set findprocfile $f | |||
|
2125 | set findprocpid [pid $f] | |||
|
2126 | fconfigure $f -blocking 0 | |||
|
2127 | fileevent $f readable readfindproc | |||
|
2128 | set finddidsel 0 | |||
|
2129 | . config -cursor watch | |||
|
2130 | settextcursor watch | |||
|
2131 | set findinprogress 1 | |||
|
2132 | } | |||
|
2133 | ||||
|
2134 | proc readfindproc {} { | |||
|
2135 | global findprocfile finddidsel | |||
|
2136 | global idline matchinglines findinsertpos | |||
|
2137 | ||||
|
2138 | set n [gets $findprocfile line] | |||
|
2139 | if {$n < 0} { | |||
|
2140 | if {[eof $findprocfile]} { | |||
|
2141 | stopfindproc 1 | |||
|
2142 | if {!$finddidsel} { | |||
|
2143 | bell | |||
|
2144 | } | |||
|
2145 | } | |||
|
2146 | return | |||
|
2147 | } | |||
|
2148 | if {![regexp {^[0-9a-f]{12}} $line id]} { | |||
|
2149 | error_popup "Can't parse git-diff-tree output: $line" | |||
|
2150 | stopfindproc | |||
|
2151 | return | |||
|
2152 | } | |||
|
2153 | if {![info exists idline($id)]} { | |||
|
2154 | puts stderr "spurious id: $id" | |||
|
2155 | return | |||
|
2156 | } | |||
|
2157 | set l $idline($id) | |||
|
2158 | insertmatch $l $id | |||
|
2159 | } | |||
|
2160 | ||||
|
2161 | proc insertmatch {l id} { | |||
|
2162 | global matchinglines findinsertpos finddidsel | |||
|
2163 | ||||
|
2164 | if {$findinsertpos == "end"} { | |||
|
2165 | if {$matchinglines != {} && $l < [lindex $matchinglines 0]} { | |||
|
2166 | set matchinglines [linsert $matchinglines 0 $l] | |||
|
2167 | set findinsertpos 1 | |||
|
2168 | } else { | |||
|
2169 | lappend matchinglines $l | |||
|
2170 | } | |||
|
2171 | } else { | |||
|
2172 | set matchinglines [linsert $matchinglines $findinsertpos $l] | |||
|
2173 | incr findinsertpos | |||
|
2174 | } | |||
|
2175 | markheadline $l $id | |||
|
2176 | if {!$finddidsel} { | |||
|
2177 | findselectline $l | |||
|
2178 | set finddidsel 1 | |||
|
2179 | } | |||
|
2180 | } | |||
|
2181 | ||||
|
2182 | proc findfiles {} { | |||
|
2183 | global selectedline numcommits lineid ctext | |||
|
2184 | global ffileline finddidsel parents nparents | |||
|
2185 | global findinprogress findstartline findinsertpos | |||
|
2186 | global treediffs fdiffids fdiffsneeded fdiffpos | |||
|
2187 | global findmergefiles | |||
|
2188 | global env | |||
|
2189 | ||||
|
2190 | if {$numcommits == 0} return | |||
|
2191 | ||||
|
2192 | if {[info exists selectedline]} { | |||
|
2193 | set l [expr {$selectedline + 1}] | |||
|
2194 | } else { | |||
|
2195 | set l 0 | |||
|
2196 | } | |||
|
2197 | set ffileline $l | |||
|
2198 | set findstartline $l | |||
|
2199 | set diffsneeded {} | |||
|
2200 | set fdiffsneeded {} | |||
|
2201 | while 1 { | |||
|
2202 | set id $lineid($l) | |||
|
2203 | if {$findmergefiles || $nparents($id) == 1} { | |||
|
2204 | foreach p $parents($id) { | |||
|
2205 | if {![info exists treediffs([list $id $p])]} { | |||
|
2206 | append diffsneeded "$id $p\n" | |||
|
2207 | lappend fdiffsneeded [list $id $p] | |||
|
2208 | } | |||
|
2209 | } | |||
|
2210 | } | |||
|
2211 | if {[incr l] >= $numcommits} { | |||
|
2212 | set l 0 | |||
|
2213 | } | |||
|
2214 | if {$l == $findstartline} break | |||
|
2215 | } | |||
|
2216 | ||||
|
2217 | # start off a git-diff-tree process if needed | |||
|
2218 | if {$diffsneeded ne {}} { | |||
|
2219 | if {[catch { | |||
|
2220 | set df [open [list | $env(HG) --config ui.report_untrusted=false debug-diff-tree -r --stdin << $diffsneeded] r] | |||
|
2221 | } err ]} { | |||
|
2222 | error_popup "Error starting search process: $err" | |||
|
2223 | return | |||
|
2224 | } | |||
|
2225 | catch {unset fdiffids} | |||
|
2226 | set fdiffpos 0 | |||
|
2227 | fconfigure $df -blocking 0 | |||
|
2228 | fileevent $df readable [list readfilediffs $df] | |||
|
2229 | } | |||
|
2230 | ||||
|
2231 | set finddidsel 0 | |||
|
2232 | set findinsertpos end | |||
|
2233 | set id $lineid($l) | |||
|
2234 | set p [lindex $parents($id) 0] | |||
|
2235 | . config -cursor watch | |||
|
2236 | settextcursor watch | |||
|
2237 | set findinprogress 1 | |||
|
2238 | findcont [list $id $p] | |||
|
2239 | update | |||
|
2240 | } | |||
|
2241 | ||||
|
2242 | proc readfilediffs {df} { | |||
|
2243 | global findids fdiffids fdiffs | |||
|
2244 | ||||
|
2245 | set n [gets $df line] | |||
|
2246 | if {$n < 0} { | |||
|
2247 | if {[eof $df]} { | |||
|
2248 | donefilediff | |||
|
2249 | if {[catch {close $df} err]} { | |||
|
2250 | stopfindproc | |||
|
2251 | bell | |||
|
2252 | error_popup "Error in hg debug-diff-tree: $err" | |||
|
2253 | } elseif {[info exists findids]} { | |||
|
2254 | set ids $findids | |||
|
2255 | stopfindproc | |||
|
2256 | bell | |||
|
2257 | error_popup "Couldn't find diffs for {$ids}" | |||
|
2258 | } | |||
|
2259 | } | |||
|
2260 | return | |||
|
2261 | } | |||
|
2262 | if {[regexp {^([0-9a-f]{12}) \(from ([0-9a-f]{12})\)} $line match id p]} { | |||
|
2263 | # start of a new string of diffs | |||
|
2264 | donefilediff | |||
|
2265 | set fdiffids [list $id $p] | |||
|
2266 | set fdiffs {} | |||
|
2267 | } elseif {[string match ":*" $line]} { | |||
|
2268 | lappend fdiffs [lindex $line 5] | |||
|
2269 | } | |||
|
2270 | } | |||
|
2271 | ||||
|
2272 | proc donefilediff {} { | |||
|
2273 | global fdiffids fdiffs treediffs findids | |||
|
2274 | global fdiffsneeded fdiffpos | |||
|
2275 | ||||
|
2276 | if {[info exists fdiffids]} { | |||
|
2277 | while {[lindex $fdiffsneeded $fdiffpos] ne $fdiffids | |||
|
2278 | && $fdiffpos < [llength $fdiffsneeded]} { | |||
|
2279 | # git-diff-tree doesn't output anything for a commit | |||
|
2280 | # which doesn't change anything | |||
|
2281 | set nullids [lindex $fdiffsneeded $fdiffpos] | |||
|
2282 | set treediffs($nullids) {} | |||
|
2283 | if {[info exists findids] && $nullids eq $findids} { | |||
|
2284 | unset findids | |||
|
2285 | findcont $nullids | |||
|
2286 | } | |||
|
2287 | incr fdiffpos | |||
|
2288 | } | |||
|
2289 | incr fdiffpos | |||
|
2290 | ||||
|
2291 | if {![info exists treediffs($fdiffids)]} { | |||
|
2292 | set treediffs($fdiffids) $fdiffs | |||
|
2293 | } | |||
|
2294 | if {[info exists findids] && $fdiffids eq $findids} { | |||
|
2295 | unset findids | |||
|
2296 | findcont $fdiffids | |||
|
2297 | } | |||
|
2298 | } | |||
|
2299 | } | |||
|
2300 | ||||
|
2301 | proc findcont {ids} { | |||
|
2302 | global findids treediffs parents nparents | |||
|
2303 | global ffileline findstartline finddidsel | |||
|
2304 | global lineid numcommits matchinglines findinprogress | |||
|
2305 | global findmergefiles | |||
|
2306 | ||||
|
2307 | set id [lindex $ids 0] | |||
|
2308 | set p [lindex $ids 1] | |||
|
2309 | set pi [lsearch -exact $parents($id) $p] | |||
|
2310 | set l $ffileline | |||
|
2311 | while 1 { | |||
|
2312 | if {$findmergefiles || $nparents($id) == 1} { | |||
|
2313 | if {![info exists treediffs($ids)]} { | |||
|
2314 | set findids $ids | |||
|
2315 | set ffileline $l | |||
|
2316 | return | |||
|
2317 | } | |||
|
2318 | set doesmatch 0 | |||
|
2319 | foreach f $treediffs($ids) { | |||
|
2320 | set x [findmatches $f] | |||
|
2321 | if {$x != {}} { | |||
|
2322 | set doesmatch 1 | |||
|
2323 | break | |||
|
2324 | } | |||
|
2325 | } | |||
|
2326 | if {$doesmatch} { | |||
|
2327 | insertmatch $l $id | |||
|
2328 | set pi $nparents($id) | |||
|
2329 | } | |||
|
2330 | } else { | |||
|
2331 | set pi $nparents($id) | |||
|
2332 | } | |||
|
2333 | if {[incr pi] >= $nparents($id)} { | |||
|
2334 | set pi 0 | |||
|
2335 | if {[incr l] >= $numcommits} { | |||
|
2336 | set l 0 | |||
|
2337 | } | |||
|
2338 | if {$l == $findstartline} break | |||
|
2339 | set id $lineid($l) | |||
|
2340 | } | |||
|
2341 | set p [lindex $parents($id) $pi] | |||
|
2342 | set ids [list $id $p] | |||
|
2343 | } | |||
|
2344 | stopfindproc | |||
|
2345 | if {!$finddidsel} { | |||
|
2346 | bell | |||
|
2347 | } | |||
|
2348 | } | |||
|
2349 | ||||
|
2350 | # mark a commit as matching by putting a yellow background | |||
|
2351 | # behind the headline | |||
|
2352 | proc markheadline {l id} { | |||
|
2353 | global canv mainfont linehtag commitinfo | |||
|
2354 | ||||
|
2355 | set bbox [$canv bbox $linehtag($l)] | |||
|
2356 | set t [$canv create rect $bbox -outline {} -tags matches -fill yellow] | |||
|
2357 | $canv lower $t | |||
|
2358 | } | |||
|
2359 | ||||
|
2360 | # mark the bits of a headline, author or date that match a find string | |||
|
2361 | proc markmatches {canv l str tag matches font} { | |||
|
2362 | set bbox [$canv bbox $tag] | |||
|
2363 | set x0 [lindex $bbox 0] | |||
|
2364 | set y0 [lindex $bbox 1] | |||
|
2365 | set y1 [lindex $bbox 3] | |||
|
2366 | foreach match $matches { | |||
|
2367 | set start [lindex $match 0] | |||
|
2368 | set end [lindex $match 1] | |||
|
2369 | if {$start > $end} continue | |||
|
2370 | set xoff [font measure $font [string range $str 0 [expr $start-1]]] | |||
|
2371 | set xlen [font measure $font [string range $str 0 [expr $end]]] | |||
|
2372 | set t [$canv create rect [expr $x0+$xoff] $y0 [expr $x0+$xlen+2] $y1 \ | |||
|
2373 | -outline {} -tags matches -fill yellow] | |||
|
2374 | $canv lower $t | |||
|
2375 | } | |||
|
2376 | } | |||
|
2377 | ||||
|
2378 | proc unmarkmatches {} { | |||
|
2379 | global matchinglines findids | |||
|
2380 | allcanvs delete matches | |||
|
2381 | catch {unset matchinglines} | |||
|
2382 | catch {unset findids} | |||
|
2383 | } | |||
|
2384 | ||||
|
2385 | proc selcanvline {w x y} { | |||
|
2386 | global canv canvy0 ctext linespc | |||
|
2387 | global lineid linehtag linentag linedtag rowtextx | |||
|
2388 | set ymax [lindex [$canv cget -scrollregion] 3] | |||
|
2389 | if {$ymax == {}} return | |||
|
2390 | set yfrac [lindex [$canv yview] 0] | |||
|
2391 | set y [expr {$y + $yfrac * $ymax}] | |||
|
2392 | set l [expr {int(($y - $canvy0) / $linespc + 0.5)}] | |||
|
2393 | if {$l < 0} { | |||
|
2394 | set l 0 | |||
|
2395 | } | |||
|
2396 | if {$w eq $canv} { | |||
|
2397 | if {![info exists rowtextx($l)] || $x < $rowtextx($l)} return | |||
|
2398 | } | |||
|
2399 | unmarkmatches | |||
|
2400 | selectline $l 1 | |||
|
2401 | } | |||
|
2402 | ||||
|
2403 | proc commit_descriptor {p} { | |||
|
2404 | global commitinfo | |||
|
2405 | set l "..." | |||
|
2406 | if {[info exists commitinfo($p)]} { | |||
|
2407 | set l [lindex $commitinfo($p) 0] | |||
|
2408 | set r [lindex $commitinfo($p) 6] | |||
|
2409 | } | |||
|
2410 | return "$r:$p ($l)" | |||
|
2411 | } | |||
|
2412 | ||||
|
2413 | # append some text to the ctext widget, and make any SHA1 ID | |||
|
2414 | # that we know about be a clickable link. | |||
|
2415 | proc appendwithlinks {text} { | |||
|
2416 | global ctext idline linknum | |||
|
2417 | ||||
|
2418 | set start [$ctext index "end - 1c"] | |||
|
2419 | $ctext insert end $text | |||
|
2420 | $ctext insert end "\n" | |||
|
2421 | set links [regexp -indices -all -inline {[0-9a-f]{12}} $text] | |||
|
2422 | foreach l $links { | |||
|
2423 | set s [lindex $l 0] | |||
|
2424 | set e [lindex $l 1] | |||
|
2425 | set linkid [string range $text $s $e] | |||
|
2426 | if {![info exists idline($linkid)]} continue | |||
|
2427 | incr e | |||
|
2428 | $ctext tag add link "$start + $s c" "$start + $e c" | |||
|
2429 | $ctext tag add link$linknum "$start + $s c" "$start + $e c" | |||
|
2430 | $ctext tag bind link$linknum <1> [list selectline $idline($linkid) 1] | |||
|
2431 | incr linknum | |||
|
2432 | } | |||
|
2433 | $ctext tag conf link -foreground blue -underline 1 | |||
|
2434 | $ctext tag bind link <Enter> { %W configure -cursor hand2 } | |||
|
2435 | $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor } | |||
|
2436 | } | |||
|
2437 | ||||
|
2438 | proc selectline {l isnew} { | |||
|
2439 | global canv canv2 canv3 ctext commitinfo selectedline | |||
|
2440 | global lineid linehtag linentag linedtag | |||
|
2441 | global canvy0 linespc parents nparents children | |||
|
2442 | global cflist currentid sha1entry | |||
|
2443 | global commentend idtags idbookmarks idline linknum | |||
|
2444 | ||||
|
2445 | $canv delete hover | |||
|
2446 | normalline | |||
|
2447 | if {![info exists lineid($l)] || ![info exists linehtag($l)]} return | |||
|
2448 | $canv delete secsel | |||
|
2449 | set t [eval $canv create rect [$canv bbox $linehtag($l)] -outline {{}} \ | |||
|
2450 | -tags secsel -fill [$canv cget -selectbackground]] | |||
|
2451 | $canv lower $t | |||
|
2452 | $canv2 delete secsel | |||
|
2453 | set t [eval $canv2 create rect [$canv2 bbox $linentag($l)] -outline {{}} \ | |||
|
2454 | -tags secsel -fill [$canv2 cget -selectbackground]] | |||
|
2455 | $canv2 lower $t | |||
|
2456 | $canv3 delete secsel | |||
|
2457 | set t [eval $canv3 create rect [$canv3 bbox $linedtag($l)] -outline {{}} \ | |||
|
2458 | -tags secsel -fill [$canv3 cget -selectbackground]] | |||
|
2459 | $canv3 lower $t | |||
|
2460 | set y [expr {$canvy0 + $l * $linespc}] | |||
|
2461 | set ymax [lindex [$canv cget -scrollregion] 3] | |||
|
2462 | set ytop [expr {$y - $linespc - 1}] | |||
|
2463 | set ybot [expr {$y + $linespc + 1}] | |||
|
2464 | set wnow [$canv yview] | |||
|
2465 | set wtop [expr [lindex $wnow 0] * $ymax] | |||
|
2466 | set wbot [expr [lindex $wnow 1] * $ymax] | |||
|
2467 | set wh [expr {$wbot - $wtop}] | |||
|
2468 | set newtop $wtop | |||
|
2469 | if {$ytop < $wtop} { | |||
|
2470 | if {$ybot < $wtop} { | |||
|
2471 | set newtop [expr {$y - $wh / 2.0}] | |||
|
2472 | } else { | |||
|
2473 | set newtop $ytop | |||
|
2474 | if {$newtop > $wtop - $linespc} { | |||
|
2475 | set newtop [expr {$wtop - $linespc}] | |||
|
2476 | } | |||
|
2477 | } | |||
|
2478 | } elseif {$ybot > $wbot} { | |||
|
2479 | if {$ytop > $wbot} { | |||
|
2480 | set newtop [expr {$y - $wh / 2.0}] | |||
|
2481 | } else { | |||
|
2482 | set newtop [expr {$ybot - $wh}] | |||
|
2483 | if {$newtop < $wtop + $linespc} { | |||
|
2484 | set newtop [expr {$wtop + $linespc}] | |||
|
2485 | } | |||
|
2486 | } | |||
|
2487 | } | |||
|
2488 | if {$newtop != $wtop} { | |||
|
2489 | if {$newtop < 0} { | |||
|
2490 | set newtop 0 | |||
|
2491 | } | |||
|
2492 | allcanvs yview moveto [expr $newtop * 1.0 / $ymax] | |||
|
2493 | } | |||
|
2494 | ||||
|
2495 | if {$isnew} { | |||
|
2496 | addtohistory [list selectline $l 0] | |||
|
2497 | } | |||
|
2498 | ||||
|
2499 | set selectedline $l | |||
|
2500 | ||||
|
2501 | set id $lineid($l) | |||
|
2502 | set currentid $id | |||
|
2503 | $sha1entry delete 0 end | |||
|
2504 | $sha1entry insert 0 $id | |||
|
2505 | $sha1entry selection range 0 end | |||
|
2506 | ||||
|
2507 | $ctext conf -state normal | |||
|
2508 | $ctext delete 0.0 end | |||
|
2509 | set linknum 0 | |||
|
2510 | $ctext mark set fmark.0 0.0 | |||
|
2511 | $ctext mark gravity fmark.0 left | |||
|
2512 | set info $commitinfo($id) | |||
|
2513 | $ctext insert end "Changeset: [lindex $info 6]\n" | |||
|
2514 | if {[llength [lindex $info 7]] > 0} { | |||
|
2515 | $ctext insert end "Branch: [lindex $info 7]\n" | |||
|
2516 | } | |||
|
2517 | $ctext insert end "User: [lindex $info 1]\n" | |||
|
2518 | $ctext insert end "Date: [lindex $info 2]\n" | |||
|
2519 | if {[lindex $info 3] ne ""} { | |||
|
2520 | $ctext insert end "Committer: [lindex $info 3]\n" | |||
|
2521 | } | |||
|
2522 | if {[info exists idbookmarks($id)]} { | |||
|
2523 | $ctext insert end "Bookmarks:" | |||
|
2524 | foreach bookmark $idbookmarks($id) { | |||
|
2525 | $ctext insert end " $bookmark" | |||
|
2526 | } | |||
|
2527 | $ctext insert end "\n" | |||
|
2528 | } | |||
|
2529 | ||||
|
2530 | if {[info exists idtags($id)]} { | |||
|
2531 | $ctext insert end "Tags:" | |||
|
2532 | foreach tag $idtags($id) { | |||
|
2533 | $ctext insert end " $tag" | |||
|
2534 | } | |||
|
2535 | $ctext insert end "\n" | |||
|
2536 | } | |||
|
2537 | ||||
|
2538 | set comment {} | |||
|
2539 | if {[info exists parents($id)]} { | |||
|
2540 | foreach p $parents($id) { | |||
|
2541 | append comment "Parent: [commit_descriptor $p]\n" | |||
|
2542 | } | |||
|
2543 | } | |||
|
2544 | if {[info exists children($id)]} { | |||
|
2545 | foreach c $children($id) { | |||
|
2546 | append comment "Child: [commit_descriptor $c]\n" | |||
|
2547 | } | |||
|
2548 | } | |||
|
2549 | ||||
|
2550 | if {[lindex $info 9] eq "secret"} { | |||
|
2551 | # for now, display phase for secret changesets only | |||
|
2552 | append comment "Phase: [lindex $info 9]\n" | |||
|
2553 | } | |||
|
2554 | ||||
|
2555 | append comment "\n" | |||
|
2556 | append comment [lindex $info 5] | |||
|
2557 | ||||
|
2558 | # make anything that looks like a SHA1 ID be a clickable link | |||
|
2559 | appendwithlinks $comment | |||
|
2560 | ||||
|
2561 | $ctext tag delete Comments | |||
|
2562 | $ctext tag remove found 1.0 end | |||
|
2563 | $ctext conf -state disabled | |||
|
2564 | set commentend [$ctext index "end - 1c"] | |||
|
2565 | ||||
|
2566 | $cflist delete 0 end | |||
|
2567 | $cflist insert end "Comments" | |||
|
2568 | if {$nparents($id) <= 1} { | |||
|
2569 | set parent "null" | |||
|
2570 | if {$nparents($id) == 1} { | |||
|
2571 | set parent $parents($id) | |||
|
2572 | } | |||
|
2573 | startdiff [concat $id $parent] | |||
|
2574 | } elseif {$nparents($id) > 1} { | |||
|
2575 | mergediff $id | |||
|
2576 | } | |||
|
2577 | } | |||
|
2578 | ||||
|
2579 | proc selnextline {dir} { | |||
|
2580 | global selectedline | |||
|
2581 | focus . | |||
|
2582 | if {![info exists selectedline]} return | |||
|
2583 | set l [expr $selectedline + $dir] | |||
|
2584 | unmarkmatches | |||
|
2585 | selectline $l 1 | |||
|
2586 | } | |||
|
2587 | ||||
|
2588 | proc unselectline {} { | |||
|
2589 | global selectedline | |||
|
2590 | ||||
|
2591 | catch {unset selectedline} | |||
|
2592 | allcanvs delete secsel | |||
|
2593 | } | |||
|
2594 | ||||
|
2595 | proc addtohistory {cmd} { | |||
|
2596 | global history historyindex | |||
|
2597 | ||||
|
2598 | if {$historyindex > 0 | |||
|
2599 | && [lindex $history [expr {$historyindex - 1}]] == $cmd} { | |||
|
2600 | return | |||
|
2601 | } | |||
|
2602 | ||||
|
2603 | if {$historyindex < [llength $history]} { | |||
|
2604 | set history [lreplace $history $historyindex end $cmd] | |||
|
2605 | } else { | |||
|
2606 | lappend history $cmd | |||
|
2607 | } | |||
|
2608 | incr historyindex | |||
|
2609 | if {$historyindex > 1} { | |||
|
2610 | .ctop.top.bar.leftbut conf -state normal | |||
|
2611 | } else { | |||
|
2612 | .ctop.top.bar.leftbut conf -state disabled | |||
|
2613 | } | |||
|
2614 | .ctop.top.bar.rightbut conf -state disabled | |||
|
2615 | } | |||
|
2616 | ||||
|
2617 | proc goback {} { | |||
|
2618 | global history historyindex | |||
|
2619 | focus . | |||
|
2620 | ||||
|
2621 | if {$historyindex > 1} { | |||
|
2622 | incr historyindex -1 | |||
|
2623 | set cmd [lindex $history [expr {$historyindex - 1}]] | |||
|
2624 | eval $cmd | |||
|
2625 | .ctop.top.bar.rightbut conf -state normal | |||
|
2626 | } | |||
|
2627 | if {$historyindex <= 1} { | |||
|
2628 | .ctop.top.bar.leftbut conf -state disabled | |||
|
2629 | } | |||
|
2630 | } | |||
|
2631 | ||||
|
2632 | proc goforw {} { | |||
|
2633 | global history historyindex | |||
|
2634 | focus . | |||
|
2635 | ||||
|
2636 | if {$historyindex < [llength $history]} { | |||
|
2637 | set cmd [lindex $history $historyindex] | |||
|
2638 | incr historyindex | |||
|
2639 | eval $cmd | |||
|
2640 | .ctop.top.bar.leftbut conf -state normal | |||
|
2641 | } | |||
|
2642 | if {$historyindex >= [llength $history]} { | |||
|
2643 | .ctop.top.bar.rightbut conf -state disabled | |||
|
2644 | } | |||
|
2645 | } | |||
|
2646 | ||||
|
2647 | proc mergediff {id} { | |||
|
2648 | global parents diffmergeid diffmergegca mergefilelist diffpindex | |||
|
2649 | ||||
|
2650 | set diffmergeid $id | |||
|
2651 | set diffpindex -1 | |||
|
2652 | set diffmergegca [findgca $parents($id)] | |||
|
2653 | if {[info exists mergefilelist($id)]} { | |||
|
2654 | if {$mergefilelist($id) ne {}} { | |||
|
2655 | showmergediff | |||
|
2656 | } | |||
|
2657 | } else { | |||
|
2658 | contmergediff {} | |||
|
2659 | } | |||
|
2660 | } | |||
|
2661 | ||||
|
2662 | proc findgca {ids} { | |||
|
2663 | global env | |||
|
2664 | set gca {} | |||
|
2665 | foreach id $ids { | |||
|
2666 | if {$gca eq {}} { | |||
|
2667 | set gca $id | |||
|
2668 | } else { | |||
|
2669 | if {[catch { | |||
|
2670 | set gca [exec $env(HG) --config ui.report_untrusted=false debug-merge-base $gca $id] | |||
|
2671 | } err]} { | |||
|
2672 | return {} | |||
|
2673 | } | |||
|
2674 | } | |||
|
2675 | } | |||
|
2676 | return $gca | |||
|
2677 | } | |||
|
2678 | ||||
|
2679 | proc contmergediff {ids} { | |||
|
2680 | global diffmergeid diffpindex parents nparents diffmergegca | |||
|
2681 | global treediffs mergefilelist diffids treepending | |||
|
2682 | ||||
|
2683 | # diff the child against each of the parents, and diff | |||
|
2684 | # each of the parents against the GCA. | |||
|
2685 | while 1 { | |||
|
2686 | if {[lindex $ids 0] == $diffmergeid && $diffmergegca ne {}} { | |||
|
2687 | set ids [list [lindex $ids 1] $diffmergegca] | |||
|
2688 | } else { | |||
|
2689 | if {[incr diffpindex] >= $nparents($diffmergeid)} break | |||
|
2690 | set p [lindex $parents($diffmergeid) $diffpindex] | |||
|
2691 | set ids [list $diffmergeid $p] | |||
|
2692 | } | |||
|
2693 | if {![info exists treediffs($ids)]} { | |||
|
2694 | set diffids $ids | |||
|
2695 | if {![info exists treepending]} { | |||
|
2696 | gettreediffs $ids | |||
|
2697 | } | |||
|
2698 | return | |||
|
2699 | } | |||
|
2700 | } | |||
|
2701 | ||||
|
2702 | # If a file in some parent is different from the child and also | |||
|
2703 | # different from the GCA, then it's interesting. | |||
|
2704 | # If we don't have a GCA, then a file is interesting if it is | |||
|
2705 | # different from the child in all the parents. | |||
|
2706 | if {$diffmergegca ne {}} { | |||
|
2707 | set files {} | |||
|
2708 | foreach p $parents($diffmergeid) { | |||
|
2709 | set gcadiffs $treediffs([list $p $diffmergegca]) | |||
|
2710 | foreach f $treediffs([list $diffmergeid $p]) { | |||
|
2711 | if {[lsearch -exact $files $f] < 0 | |||
|
2712 | && [lsearch -exact $gcadiffs $f] >= 0} { | |||
|
2713 | lappend files $f | |||
|
2714 | } | |||
|
2715 | } | |||
|
2716 | } | |||
|
2717 | set files [lsort $files] | |||
|
2718 | } else { | |||
|
2719 | set p [lindex $parents($diffmergeid) 0] | |||
|
2720 | set files $treediffs([list $diffmergeid $p]) | |||
|
2721 | for {set i 1} {$i < $nparents($diffmergeid) && $files ne {}} {incr i} { | |||
|
2722 | set p [lindex $parents($diffmergeid) $i] | |||
|
2723 | set df $treediffs([list $diffmergeid $p]) | |||
|
2724 | set nf {} | |||
|
2725 | foreach f $files { | |||
|
2726 | if {[lsearch -exact $df $f] >= 0} { | |||
|
2727 | lappend nf $f | |||
|
2728 | } | |||
|
2729 | } | |||
|
2730 | set files $nf | |||
|
2731 | } | |||
|
2732 | } | |||
|
2733 | ||||
|
2734 | set mergefilelist($diffmergeid) $files | |||
|
2735 | if {$files ne {}} { | |||
|
2736 | showmergediff | |||
|
2737 | } | |||
|
2738 | } | |||
|
2739 | ||||
|
2740 | proc showmergediff {} { | |||
|
2741 | global cflist diffmergeid mergefilelist parents | |||
|
2742 | global diffopts diffinhunk currentfile currenthunk filelines | |||
|
2743 | global diffblocked groupfilelast mergefds groupfilenum grouphunks | |||
|
2744 | global env | |||
|
2745 | ||||
|
2746 | set files $mergefilelist($diffmergeid) | |||
|
2747 | foreach f $files { | |||
|
2748 | $cflist insert end $f | |||
|
2749 | } | |||
|
2750 | set env(GIT_DIFF_OPTS) $diffopts | |||
|
2751 | set flist {} | |||
|
2752 | catch {unset currentfile} | |||
|
2753 | catch {unset currenthunk} | |||
|
2754 | catch {unset filelines} | |||
|
2755 | catch {unset groupfilenum} | |||
|
2756 | catch {unset grouphunks} | |||
|
2757 | set groupfilelast -1 | |||
|
2758 | foreach p $parents($diffmergeid) { | |||
|
2759 | set cmd [list | $env(HG) --config ui.report_untrusted=false debug-diff-tree -p $p $diffmergeid] | |||
|
2760 | set cmd [concat $cmd $mergefilelist($diffmergeid)] | |||
|
2761 | if {[catch {set f [open $cmd r]} err]} { | |||
|
2762 | error_popup "Error getting diffs: $err" | |||
|
2763 | foreach f $flist { | |||
|
2764 | catch {close $f} | |||
|
2765 | } | |||
|
2766 | return | |||
|
2767 | } | |||
|
2768 | lappend flist $f | |||
|
2769 | set ids [list $diffmergeid $p] | |||
|
2770 | set mergefds($ids) $f | |||
|
2771 | set diffinhunk($ids) 0 | |||
|
2772 | set diffblocked($ids) 0 | |||
|
2773 | fconfigure $f -blocking 0 | |||
|
2774 | fileevent $f readable [list getmergediffline $f $ids $diffmergeid] | |||
|
2775 | } | |||
|
2776 | } | |||
|
2777 | ||||
|
2778 | proc getmergediffline {f ids id} { | |||
|
2779 | global diffmergeid diffinhunk diffoldlines diffnewlines | |||
|
2780 | global currentfile currenthunk | |||
|
2781 | global diffoldstart diffnewstart diffoldlno diffnewlno | |||
|
2782 | global diffblocked mergefilelist | |||
|
2783 | global noldlines nnewlines difflcounts filelines | |||
|
2784 | ||||
|
2785 | set n [gets $f line] | |||
|
2786 | if {$n < 0} { | |||
|
2787 | if {![eof $f]} return | |||
|
2788 | } | |||
|
2789 | ||||
|
2790 | if {!([info exists diffmergeid] && $diffmergeid == $id)} { | |||
|
2791 | if {$n < 0} { | |||
|
2792 | close $f | |||
|
2793 | } | |||
|
2794 | return | |||
|
2795 | } | |||
|
2796 | ||||
|
2797 | if {$diffinhunk($ids) != 0} { | |||
|
2798 | set fi $currentfile($ids) | |||
|
2799 | if {$n > 0 && [regexp {^[-+ \\]} $line match]} { | |||
|
2800 | # continuing an existing hunk | |||
|
2801 | set line [string range $line 1 end] | |||
|
2802 | set p [lindex $ids 1] | |||
|
2803 | if {$match eq "-" || $match eq " "} { | |||
|
2804 | set filelines($p,$fi,$diffoldlno($ids)) $line | |||
|
2805 | incr diffoldlno($ids) | |||
|
2806 | } | |||
|
2807 | if {$match eq "+" || $match eq " "} { | |||
|
2808 | set filelines($id,$fi,$diffnewlno($ids)) $line | |||
|
2809 | incr diffnewlno($ids) | |||
|
2810 | } | |||
|
2811 | if {$match eq " "} { | |||
|
2812 | if {$diffinhunk($ids) == 2} { | |||
|
2813 | lappend difflcounts($ids) \ | |||
|
2814 | [list $noldlines($ids) $nnewlines($ids)] | |||
|
2815 | set noldlines($ids) 0 | |||
|
2816 | set diffinhunk($ids) 1 | |||
|
2817 | } | |||
|
2818 | incr noldlines($ids) | |||
|
2819 | } elseif {$match eq "-" || $match eq "+"} { | |||
|
2820 | if {$diffinhunk($ids) == 1} { | |||
|
2821 | lappend difflcounts($ids) [list $noldlines($ids)] | |||
|
2822 | set noldlines($ids) 0 | |||
|
2823 | set nnewlines($ids) 0 | |||
|
2824 | set diffinhunk($ids) 2 | |||
|
2825 | } | |||
|
2826 | if {$match eq "-"} { | |||
|
2827 | incr noldlines($ids) | |||
|
2828 | } else { | |||
|
2829 | incr nnewlines($ids) | |||
|
2830 | } | |||
|
2831 | } | |||
|
2832 | # and if it's \ No newline at end of line, then what? | |||
|
2833 | return | |||
|
2834 | } | |||
|
2835 | # end of a hunk | |||
|
2836 | if {$diffinhunk($ids) == 1 && $noldlines($ids) != 0} { | |||
|
2837 | lappend difflcounts($ids) [list $noldlines($ids)] | |||
|
2838 | } elseif {$diffinhunk($ids) == 2 | |||
|
2839 | && ($noldlines($ids) != 0 || $nnewlines($ids) != 0)} { | |||
|
2840 | lappend difflcounts($ids) [list $noldlines($ids) $nnewlines($ids)] | |||
|
2841 | } | |||
|
2842 | set currenthunk($ids) [list $currentfile($ids) \ | |||
|
2843 | $diffoldstart($ids) $diffnewstart($ids) \ | |||
|
2844 | $diffoldlno($ids) $diffnewlno($ids) \ | |||
|
2845 | $difflcounts($ids)] | |||
|
2846 | set diffinhunk($ids) 0 | |||
|
2847 | # -1 = need to block, 0 = unblocked, 1 = is blocked | |||
|
2848 | set diffblocked($ids) -1 | |||
|
2849 | processhunks | |||
|
2850 | if {$diffblocked($ids) == -1} { | |||
|
2851 | fileevent $f readable {} | |||
|
2852 | set diffblocked($ids) 1 | |||
|
2853 | } | |||
|
2854 | } | |||
|
2855 | ||||
|
2856 | if {$n < 0} { | |||
|
2857 | # eof | |||
|
2858 | if {!$diffblocked($ids)} { | |||
|
2859 | close $f | |||
|
2860 | set currentfile($ids) [llength $mergefilelist($diffmergeid)] | |||
|
2861 | set currenthunk($ids) [list $currentfile($ids) 0 0 0 0 {}] | |||
|
2862 | processhunks | |||
|
2863 | } | |||
|
2864 | } elseif {[regexp {^diff --git a/(.*) b/} $line match fname]} { | |||
|
2865 | # start of a new file | |||
|
2866 | set currentfile($ids) \ | |||
|
2867 | [lsearch -exact $mergefilelist($diffmergeid) $fname] | |||
|
2868 | } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \ | |||
|
2869 | $line match f1l f1c f2l f2c rest]} { | |||
|
2870 | if {[info exists currentfile($ids)] && $currentfile($ids) >= 0} { | |||
|
2871 | # start of a new hunk | |||
|
2872 | if {$f1l == 0 && $f1c == 0} { | |||
|
2873 | set f1l 1 | |||
|
2874 | } | |||
|
2875 | if {$f2l == 0 && $f2c == 0} { | |||
|
2876 | set f2l 1 | |||
|
2877 | } | |||
|
2878 | set diffinhunk($ids) 1 | |||
|
2879 | set diffoldstart($ids) $f1l | |||
|
2880 | set diffnewstart($ids) $f2l | |||
|
2881 | set diffoldlno($ids) $f1l | |||
|
2882 | set diffnewlno($ids) $f2l | |||
|
2883 | set difflcounts($ids) {} | |||
|
2884 | set noldlines($ids) 0 | |||
|
2885 | set nnewlines($ids) 0 | |||
|
2886 | } | |||
|
2887 | } | |||
|
2888 | } | |||
|
2889 | ||||
|
2890 | proc processhunks {} { | |||
|
2891 | global diffmergeid parents nparents currenthunk | |||
|
2892 | global mergefilelist diffblocked mergefds | |||
|
2893 | global grouphunks grouplinestart grouplineend groupfilenum | |||
|
2894 | ||||
|
2895 | set nfiles [llength $mergefilelist($diffmergeid)] | |||
|
2896 | while 1 { | |||
|
2897 | set fi $nfiles | |||
|
2898 | set lno 0 | |||
|
2899 | # look for the earliest hunk | |||
|
2900 | foreach p $parents($diffmergeid) { | |||
|
2901 | set ids [list $diffmergeid $p] | |||
|
2902 | if {![info exists currenthunk($ids)]} return | |||
|
2903 | set i [lindex $currenthunk($ids) 0] | |||
|
2904 | set l [lindex $currenthunk($ids) 2] | |||
|
2905 | if {$i < $fi || ($i == $fi && $l < $lno)} { | |||
|
2906 | set fi $i | |||
|
2907 | set lno $l | |||
|
2908 | set pi $p | |||
|
2909 | } | |||
|
2910 | } | |||
|
2911 | ||||
|
2912 | if {$fi < $nfiles} { | |||
|
2913 | set ids [list $diffmergeid $pi] | |||
|
2914 | set hunk $currenthunk($ids) | |||
|
2915 | unset currenthunk($ids) | |||
|
2916 | if {$diffblocked($ids) > 0} { | |||
|
2917 | fileevent $mergefds($ids) readable \ | |||
|
2918 | [list getmergediffline $mergefds($ids) $ids $diffmergeid] | |||
|
2919 | } | |||
|
2920 | set diffblocked($ids) 0 | |||
|
2921 | ||||
|
2922 | if {[info exists groupfilenum] && $groupfilenum == $fi | |||
|
2923 | && $lno <= $grouplineend} { | |||
|
2924 | # add this hunk to the pending group | |||
|
2925 | lappend grouphunks($pi) $hunk | |||
|
2926 | set endln [lindex $hunk 4] | |||
|
2927 | if {$endln > $grouplineend} { | |||
|
2928 | set grouplineend $endln | |||
|
2929 | } | |||
|
2930 | continue | |||
|
2931 | } | |||
|
2932 | } | |||
|
2933 | ||||
|
2934 | # succeeding stuff doesn't belong in this group, so | |||
|
2935 | # process the group now | |||
|
2936 | if {[info exists groupfilenum]} { | |||
|
2937 | processgroup | |||
|
2938 | unset groupfilenum | |||
|
2939 | unset grouphunks | |||
|
2940 | } | |||
|
2941 | ||||
|
2942 | if {$fi >= $nfiles} break | |||
|
2943 | ||||
|
2944 | # start a new group | |||
|
2945 | set groupfilenum $fi | |||
|
2946 | set grouphunks($pi) [list $hunk] | |||
|
2947 | set grouplinestart $lno | |||
|
2948 | set grouplineend [lindex $hunk 4] | |||
|
2949 | } | |||
|
2950 | } | |||
|
2951 | ||||
|
2952 | proc processgroup {} { | |||
|
2953 | global groupfilelast groupfilenum difffilestart | |||
|
2954 | global mergefilelist diffmergeid ctext filelines | |||
|
2955 | global parents diffmergeid diffoffset | |||
|
2956 | global grouphunks grouplinestart grouplineend nparents | |||
|
2957 | global mergemax | |||
|
2958 | ||||
|
2959 | $ctext conf -state normal | |||
|
2960 | set id $diffmergeid | |||
|
2961 | set f $groupfilenum | |||
|
2962 | if {$groupfilelast != $f} { | |||
|
2963 | $ctext insert end "\n" | |||
|
2964 | set here [$ctext index "end - 1c"] | |||
|
2965 | set difffilestart($f) $here | |||
|
2966 | set mark fmark.[expr {$f + 1}] | |||
|
2967 | $ctext mark set $mark $here | |||
|
2968 | $ctext mark gravity $mark left | |||
|
2969 | set header [lindex $mergefilelist($id) $f] | |||
|
2970 | set l [expr {(78 - [string length $header]) / 2}] | |||
|
2971 | set pad [string range "----------------------------------------" 1 $l] | |||
|
2972 | $ctext insert end "$pad $header $pad\n" filesep | |||
|
2973 | set groupfilelast $f | |||
|
2974 | foreach p $parents($id) { | |||
|
2975 | set diffoffset($p) 0 | |||
|
2976 | } | |||
|
2977 | } | |||
|
2978 | ||||
|
2979 | $ctext insert end "@@" msep | |||
|
2980 | set nlines [expr {$grouplineend - $grouplinestart}] | |||
|
2981 | set events {} | |||
|
2982 | set pnum 0 | |||
|
2983 | foreach p $parents($id) { | |||
|
2984 | set startline [expr {$grouplinestart + $diffoffset($p)}] | |||
|
2985 | set ol $startline | |||
|
2986 | set nl $grouplinestart | |||
|
2987 | if {[info exists grouphunks($p)]} { | |||
|
2988 | foreach h $grouphunks($p) { | |||
|
2989 | set l [lindex $h 2] | |||
|
2990 | if {$nl < $l} { | |||
|
2991 | for {} {$nl < $l} {incr nl} { | |||
|
2992 | set filelines($p,$f,$ol) $filelines($id,$f,$nl) | |||
|
2993 | incr ol | |||
|
2994 | } | |||
|
2995 | } | |||
|
2996 | foreach chunk [lindex $h 5] { | |||
|
2997 | if {[llength $chunk] == 2} { | |||
|
2998 | set olc [lindex $chunk 0] | |||
|
2999 | set nlc [lindex $chunk 1] | |||
|
3000 | set nnl [expr {$nl + $nlc}] | |||
|
3001 | lappend events [list $nl $nnl $pnum $olc $nlc] | |||
|
3002 | incr ol $olc | |||
|
3003 | set nl $nnl | |||
|
3004 | } else { | |||
|
3005 | incr ol [lindex $chunk 0] | |||
|
3006 | incr nl [lindex $chunk 0] | |||
|
3007 | } | |||
|
3008 | } | |||
|
3009 | } | |||
|
3010 | } | |||
|
3011 | if {$nl < $grouplineend} { | |||
|
3012 | for {} {$nl < $grouplineend} {incr nl} { | |||
|
3013 | set filelines($p,$f,$ol) $filelines($id,$f,$nl) | |||
|
3014 | incr ol | |||
|
3015 | } | |||
|
3016 | } | |||
|
3017 | set nlines [expr {$ol - $startline}] | |||
|
3018 | $ctext insert end " -$startline,$nlines" msep | |||
|
3019 | incr pnum | |||
|
3020 | } | |||
|
3021 | ||||
|
3022 | set nlines [expr {$grouplineend - $grouplinestart}] | |||
|
3023 | $ctext insert end " +$grouplinestart,$nlines @@\n" msep | |||
|
3024 | ||||
|
3025 | set events [lsort -integer -index 0 $events] | |||
|
3026 | set nevents [llength $events] | |||
|
3027 | set nmerge $nparents($diffmergeid) | |||
|
3028 | set l $grouplinestart | |||
|
3029 | for {set i 0} {$i < $nevents} {set i $j} { | |||
|
3030 | set nl [lindex $events $i 0] | |||
|
3031 | while {$l < $nl} { | |||
|
3032 | $ctext insert end " $filelines($id,$f,$l)\n" | |||
|
3033 | incr l | |||
|
3034 | } | |||
|
3035 | set e [lindex $events $i] | |||
|
3036 | set enl [lindex $e 1] | |||
|
3037 | set j $i | |||
|
3038 | set active {} | |||
|
3039 | while 1 { | |||
|
3040 | set pnum [lindex $e 2] | |||
|
3041 | set olc [lindex $e 3] | |||
|
3042 | set nlc [lindex $e 4] | |||
|
3043 | if {![info exists delta($pnum)]} { | |||
|
3044 | set delta($pnum) [expr {$olc - $nlc}] | |||
|
3045 | lappend active $pnum | |||
|
3046 | } else { | |||
|
3047 | incr delta($pnum) [expr {$olc - $nlc}] | |||
|
3048 | } | |||
|
3049 | if {[incr j] >= $nevents} break | |||
|
3050 | set e [lindex $events $j] | |||
|
3051 | if {[lindex $e 0] >= $enl} break | |||
|
3052 | if {[lindex $e 1] > $enl} { | |||
|
3053 | set enl [lindex $e 1] | |||
|
3054 | } | |||
|
3055 | } | |||
|
3056 | set nlc [expr {$enl - $l}] | |||
|
3057 | set ncol mresult | |||
|
3058 | set bestpn -1 | |||
|
3059 | if {[llength $active] == $nmerge - 1} { | |||
|
3060 | # no diff for one of the parents, i.e. it's identical | |||
|
3061 | for {set pnum 0} {$pnum < $nmerge} {incr pnum} { | |||
|
3062 | if {![info exists delta($pnum)]} { | |||
|
3063 | if {$pnum < $mergemax} { | |||
|
3064 | lappend ncol m$pnum | |||
|
3065 | } else { | |||
|
3066 | lappend ncol mmax | |||
|
3067 | } | |||
|
3068 | break | |||
|
3069 | } | |||
|
3070 | } | |||
|
3071 | } elseif {[llength $active] == $nmerge} { | |||
|
3072 | # all parents are different, see if one is very similar | |||
|
3073 | set bestsim 30 | |||
|
3074 | for {set pnum 0} {$pnum < $nmerge} {incr pnum} { | |||
|
3075 | set sim [similarity $pnum $l $nlc $f \ | |||
|
3076 | [lrange $events $i [expr {$j-1}]]] | |||
|
3077 | if {$sim > $bestsim} { | |||
|
3078 | set bestsim $sim | |||
|
3079 | set bestpn $pnum | |||
|
3080 | } | |||
|
3081 | } | |||
|
3082 | if {$bestpn >= 0} { | |||
|
3083 | lappend ncol m$bestpn | |||
|
3084 | } | |||
|
3085 | } | |||
|
3086 | set pnum -1 | |||
|
3087 | foreach p $parents($id) { | |||
|
3088 | incr pnum | |||
|
3089 | if {![info exists delta($pnum)] || $pnum == $bestpn} continue | |||
|
3090 | set olc [expr {$nlc + $delta($pnum)}] | |||
|
3091 | set ol [expr {$l + $diffoffset($p)}] | |||
|
3092 | incr diffoffset($p) $delta($pnum) | |||
|
3093 | unset delta($pnum) | |||
|
3094 | for {} {$olc > 0} {incr olc -1} { | |||
|
3095 | $ctext insert end "-$filelines($p,$f,$ol)\n" m$pnum | |||
|
3096 | incr ol | |||
|
3097 | } | |||
|
3098 | } | |||
|
3099 | set endl [expr {$l + $nlc}] | |||
|
3100 | if {$bestpn >= 0} { | |||
|
3101 | # show this pretty much as a normal diff | |||
|
3102 | set p [lindex $parents($id) $bestpn] | |||
|
3103 | set ol [expr {$l + $diffoffset($p)}] | |||
|
3104 | incr diffoffset($p) $delta($bestpn) | |||
|
3105 | unset delta($bestpn) | |||
|
3106 | for {set k $i} {$k < $j} {incr k} { | |||
|
3107 | set e [lindex $events $k] | |||
|
3108 | if {[lindex $e 2] != $bestpn} continue | |||
|
3109 | set nl [lindex $e 0] | |||
|
3110 | set ol [expr {$ol + $nl - $l}] | |||
|
3111 | for {} {$l < $nl} {incr l} { | |||
|
3112 | $ctext insert end "+$filelines($id,$f,$l)\n" $ncol | |||
|
3113 | } | |||
|
3114 | set c [lindex $e 3] | |||
|
3115 | for {} {$c > 0} {incr c -1} { | |||
|
3116 | $ctext insert end "-$filelines($p,$f,$ol)\n" m$bestpn | |||
|
3117 | incr ol | |||
|
3118 | } | |||
|
3119 | set nl [lindex $e 1] | |||
|
3120 | for {} {$l < $nl} {incr l} { | |||
|
3121 | $ctext insert end "+$filelines($id,$f,$l)\n" mresult | |||
|
3122 | } | |||
|
3123 | } | |||
|
3124 | } | |||
|
3125 | for {} {$l < $endl} {incr l} { | |||
|
3126 | $ctext insert end "+$filelines($id,$f,$l)\n" $ncol | |||
|
3127 | } | |||
|
3128 | } | |||
|
3129 | while {$l < $grouplineend} { | |||
|
3130 | $ctext insert end " $filelines($id,$f,$l)\n" | |||
|
3131 | incr l | |||
|
3132 | } | |||
|
3133 | $ctext conf -state disabled | |||
|
3134 | } | |||
|
3135 | ||||
|
3136 | proc similarity {pnum l nlc f events} { | |||
|
3137 | global diffmergeid parents diffoffset filelines | |||
|
3138 | ||||
|
3139 | set id $diffmergeid | |||
|
3140 | set p [lindex $parents($id) $pnum] | |||
|
3141 | set ol [expr {$l + $diffoffset($p)}] | |||
|
3142 | set endl [expr {$l + $nlc}] | |||
|
3143 | set same 0 | |||
|
3144 | set diff 0 | |||
|
3145 | foreach e $events { | |||
|
3146 | if {[lindex $e 2] != $pnum} continue | |||
|
3147 | set nl [lindex $e 0] | |||
|
3148 | set ol [expr {$ol + $nl - $l}] | |||
|
3149 | for {} {$l < $nl} {incr l} { | |||
|
3150 | incr same [string length $filelines($id,$f,$l)] | |||
|
3151 | incr same | |||
|
3152 | } | |||
|
3153 | set oc [lindex $e 3] | |||
|
3154 | for {} {$oc > 0} {incr oc -1} { | |||
|
3155 | incr diff [string length $filelines($p,$f,$ol)] | |||
|
3156 | incr diff | |||
|
3157 | incr ol | |||
|
3158 | } | |||
|
3159 | set nl [lindex $e 1] | |||
|
3160 | for {} {$l < $nl} {incr l} { | |||
|
3161 | incr diff [string length $filelines($id,$f,$l)] | |||
|
3162 | incr diff | |||
|
3163 | } | |||
|
3164 | } | |||
|
3165 | for {} {$l < $endl} {incr l} { | |||
|
3166 | incr same [string length $filelines($id,$f,$l)] | |||
|
3167 | incr same | |||
|
3168 | } | |||
|
3169 | if {$same == 0} { | |||
|
3170 | return 0 | |||
|
3171 | } | |||
|
3172 | return [expr {200 * $same / (2 * $same + $diff)}] | |||
|
3173 | } | |||
|
3174 | ||||
|
3175 | proc startdiff {ids} { | |||
|
3176 | global treediffs diffids treepending diffmergeid | |||
|
3177 | ||||
|
3178 | set diffids $ids | |||
|
3179 | catch {unset diffmergeid} | |||
|
3180 | if {![info exists treediffs($ids)]} { | |||
|
3181 | if {![info exists treepending]} { | |||
|
3182 | gettreediffs $ids | |||
|
3183 | } | |||
|
3184 | } else { | |||
|
3185 | addtocflist $ids | |||
|
3186 | } | |||
|
3187 | } | |||
|
3188 | ||||
|
3189 | proc addtocflist {ids} { | |||
|
3190 | global treediffs cflist | |||
|
3191 | foreach f $treediffs($ids) { | |||
|
3192 | $cflist insert end $f | |||
|
3193 | } | |||
|
3194 | getblobdiffs $ids | |||
|
3195 | } | |||
|
3196 | ||||
|
3197 | proc gettreediffs {ids} { | |||
|
3198 | global treediff parents treepending env | |||
|
3199 | set treepending $ids | |||
|
3200 | set treediff {} | |||
|
3201 | set id [lindex $ids 0] | |||
|
3202 | set p [lindex $ids 1] | |||
|
3203 | if [catch {set gdtf [open "|{$env(HG)} --config ui.report_untrusted=false debug-diff-tree -r $p $id" r]}] return | |||
|
3204 | fconfigure $gdtf -blocking 0 | |||
|
3205 | fileevent $gdtf readable [list gettreediffline $gdtf $ids] | |||
|
3206 | } | |||
|
3207 | ||||
|
3208 | proc gettreediffline {gdtf ids} { | |||
|
3209 | global treediff treediffs treepending diffids diffmergeid | |||
|
3210 | ||||
|
3211 | set n [gets $gdtf line] | |||
|
3212 | if {$n < 0} { | |||
|
3213 | if {![eof $gdtf]} return | |||
|
3214 | close $gdtf | |||
|
3215 | set treediffs($ids) $treediff | |||
|
3216 | unset treepending | |||
|
3217 | if {$ids != $diffids} { | |||
|
3218 | gettreediffs $diffids | |||
|
3219 | } else { | |||
|
3220 | if {[info exists diffmergeid]} { | |||
|
3221 | contmergediff $ids | |||
|
3222 | } else { | |||
|
3223 | addtocflist $ids | |||
|
3224 | } | |||
|
3225 | } | |||
|
3226 | return | |||
|
3227 | } | |||
|
3228 | set tab1 [expr [string first "\t" $line] + 1] | |||
|
3229 | set tab2 [expr [string first "\t" $line $tab1] - 1] | |||
|
3230 | set file [string range $line $tab1 $tab2] | |||
|
3231 | lappend treediff $file | |||
|
3232 | } | |||
|
3233 | ||||
|
3234 | proc getblobdiffs {ids} { | |||
|
3235 | global diffopts blobdifffd diffids env curdifftag curtagstart | |||
|
3236 | global difffilestart nextupdate diffinhdr treediffs | |||
|
3237 | ||||
|
3238 | set id [lindex $ids 0] | |||
|
3239 | set p [lindex $ids 1] | |||
|
3240 | set env(GIT_DIFF_OPTS) $diffopts | |||
|
3241 | set cmd [list | $env(HG) --config ui.report_untrusted=false debug-diff-tree -r -p -C $p $id] | |||
|
3242 | if {[catch {set bdf [open $cmd r]} err]} { | |||
|
3243 | puts "error getting diffs: $err" | |||
|
3244 | return | |||
|
3245 | } | |||
|
3246 | set diffinhdr 0 | |||
|
3247 | fconfigure $bdf -blocking 0 | |||
|
3248 | set blobdifffd($ids) $bdf | |||
|
3249 | set curdifftag Comments | |||
|
3250 | set curtagstart 0.0 | |||
|
3251 | catch {unset difffilestart} | |||
|
3252 | fileevent $bdf readable [list getblobdiffline $bdf $diffids] | |||
|
3253 | set nextupdate [expr {[clock clicks -milliseconds] + 100}] | |||
|
3254 | } | |||
|
3255 | ||||
|
3256 | proc getblobdiffline {bdf ids} { | |||
|
3257 | global diffids blobdifffd ctext curdifftag curtagstart | |||
|
3258 | global diffnexthead diffnextnote difffilestart | |||
|
3259 | global nextupdate diffinhdr treediffs | |||
|
3260 | global gaudydiff | |||
|
3261 | ||||
|
3262 | set n [gets $bdf line] | |||
|
3263 | if {$n < 0} { | |||
|
3264 | if {[eof $bdf]} { | |||
|
3265 | close $bdf | |||
|
3266 | if {$ids == $diffids && $bdf == $blobdifffd($ids)} { | |||
|
3267 | $ctext tag add $curdifftag $curtagstart end | |||
|
3268 | } | |||
|
3269 | } | |||
|
3270 | return | |||
|
3271 | } | |||
|
3272 | if {$ids != $diffids || $bdf != $blobdifffd($ids)} { | |||
|
3273 | return | |||
|
3274 | } | |||
|
3275 | regsub -all "\r" $line "" line | |||
|
3276 | $ctext conf -state normal | |||
|
3277 | if {[regexp {^diff --git a/(.*) b/(.*)} $line match fname newname]} { | |||
|
3278 | # start of a new file | |||
|
3279 | $ctext insert end "\n" | |||
|
3280 | $ctext tag add $curdifftag $curtagstart end | |||
|
3281 | set curtagstart [$ctext index "end - 1c"] | |||
|
3282 | set header $newname | |||
|
3283 | set here [$ctext index "end - 1c"] | |||
|
3284 | set i [lsearch -exact $treediffs($diffids) $fname] | |||
|
3285 | if {$i >= 0} { | |||
|
3286 | set difffilestart($i) $here | |||
|
3287 | incr i | |||
|
3288 | $ctext mark set fmark.$i $here | |||
|
3289 | $ctext mark gravity fmark.$i left | |||
|
3290 | } | |||
|
3291 | if {$newname != $fname} { | |||
|
3292 | set i [lsearch -exact $treediffs($diffids) $newname] | |||
|
3293 | if {$i >= 0} { | |||
|
3294 | set difffilestart($i) $here | |||
|
3295 | incr i | |||
|
3296 | $ctext mark set fmark.$i $here | |||
|
3297 | $ctext mark gravity fmark.$i left | |||
|
3298 | } | |||
|
3299 | } | |||
|
3300 | set curdifftag "f:$fname" | |||
|
3301 | $ctext tag delete $curdifftag | |||
|
3302 | set l [expr {(78 - [string length $header]) / 2}] | |||
|
3303 | set pad [string range "----------------------------------------" 1 $l] | |||
|
3304 | $ctext insert end "$pad $header $pad\n" filesep | |||
|
3305 | set diffinhdr 1 | |||
|
3306 | } elseif {[regexp {^(---|\+\+\+) } $line] && $diffinhdr} { | |||
|
3307 | set diffinhdr 1 | |||
|
3308 | } elseif {[regexp {^@@ -([0-9]+),([0-9]+) \+([0-9]+),([0-9]+) @@(.*)} \ | |||
|
3309 | $line match f1l f1c f2l f2c rest]} { | |||
|
3310 | if {$gaudydiff} { | |||
|
3311 | $ctext insert end "\t" hunksep | |||
|
3312 | $ctext insert end " $f1l " d0 " $f2l " d1 | |||
|
3313 | $ctext insert end " $rest \n" hunksep | |||
|
3314 | } else { | |||
|
3315 | $ctext insert end "$line\n" hunksep | |||
|
3316 | } | |||
|
3317 | set diffinhdr 0 | |||
|
3318 | } else { | |||
|
3319 | set x [string range $line 0 0] | |||
|
3320 | if {$x == "-" || $x == "+"} { | |||
|
3321 | set tag [expr {$x == "+"}] | |||
|
3322 | if {$gaudydiff} { | |||
|
3323 | set line [string range $line 1 end] | |||
|
3324 | } | |||
|
3325 | $ctext insert end "$line\n" d$tag | |||
|
3326 | } elseif {$x == " "} { | |||
|
3327 | if {$gaudydiff} { | |||
|
3328 | set line [string range $line 1 end] | |||
|
3329 | } | |||
|
3330 | $ctext insert end "$line\n" | |||
|
3331 | } elseif {$diffinhdr || $x == "\\"} { | |||
|
3332 | # e.g. "\ No newline at end of file" | |||
|
3333 | $ctext insert end "$line\n" filesep | |||
|
3334 | } elseif {$line != ""} { | |||
|
3335 | # Something else we don't recognize | |||
|
3336 | if {$curdifftag != "Comments"} { | |||
|
3337 | $ctext insert end "\n" | |||
|
3338 | $ctext tag add $curdifftag $curtagstart end | |||
|
3339 | set curtagstart [$ctext index "end - 1c"] | |||
|
3340 | set curdifftag Comments | |||
|
3341 | } | |||
|
3342 | $ctext insert end "$line\n" filesep | |||
|
3343 | } | |||
|
3344 | } | |||
|
3345 | $ctext conf -state disabled | |||
|
3346 | if {[clock clicks -milliseconds] >= $nextupdate} { | |||
|
3347 | incr nextupdate 100 | |||
|
3348 | fileevent $bdf readable {} | |||
|
3349 | update | |||
|
3350 | fileevent $bdf readable "getblobdiffline $bdf {$ids}" | |||
|
3351 | } | |||
|
3352 | } | |||
|
3353 | ||||
|
3354 | proc nextfile {} { | |||
|
3355 | global difffilestart ctext | |||
|
3356 | set here [$ctext index @0,0] | |||
|
3357 | for {set i 0} {[info exists difffilestart($i)]} {incr i} { | |||
|
3358 | if {[$ctext compare $difffilestart($i) > $here]} { | |||
|
3359 | if {![info exists pos] | |||
|
3360 | || [$ctext compare $difffilestart($i) < $pos]} { | |||
|
3361 | set pos $difffilestart($i) | |||
|
3362 | } | |||
|
3363 | } | |||
|
3364 | } | |||
|
3365 | if {[info exists pos]} { | |||
|
3366 | $ctext yview $pos | |||
|
3367 | } | |||
|
3368 | } | |||
|
3369 | ||||
|
3370 | proc listboxsel {} { | |||
|
3371 | global ctext cflist currentid | |||
|
3372 | if {![info exists currentid]} return | |||
|
3373 | set sel [lsort [$cflist curselection]] | |||
|
3374 | if {$sel eq {}} return | |||
|
3375 | set first [lindex $sel 0] | |||
|
3376 | catch {$ctext yview fmark.$first} | |||
|
3377 | } | |||
|
3378 | ||||
|
3379 | proc setcoords {} { | |||
|
3380 | global linespc charspc canvx0 canvy0 mainfont | |||
|
3381 | global xspc1 xspc2 lthickness | |||
|
3382 | ||||
|
3383 | set linespc [font metrics $mainfont -linespace] | |||
|
3384 | set charspc [font measure $mainfont "m"] | |||
|
3385 | set canvy0 [expr 3 + 0.5 * $linespc] | |||
|
3386 | set canvx0 [expr 3 + 0.5 * $linespc] | |||
|
3387 | set lthickness [expr {int($linespc / 9) + 1}] | |||
|
3388 | set xspc1(0) $linespc | |||
|
3389 | set xspc2 $linespc | |||
|
3390 | } | |||
|
3391 | ||||
|
3392 | proc redisplay {} { | |||
|
3393 | global stopped redisplaying phase | |||
|
3394 | if {$stopped > 1} return | |||
|
3395 | if {$phase == "getcommits"} return | |||
|
3396 | set redisplaying 1 | |||
|
3397 | if {$phase == "drawgraph" || $phase == "incrdraw"} { | |||
|
3398 | set stopped 1 | |||
|
3399 | } else { | |||
|
3400 | drawgraph | |||
|
3401 | } | |||
|
3402 | } | |||
|
3403 | ||||
|
3404 | proc incrfont {inc} { | |||
|
3405 | global mainfont namefont textfont ctext canv phase | |||
|
3406 | global stopped entries curidfont | |||
|
3407 | unmarkmatches | |||
|
3408 | set mainfont [lreplace $mainfont 1 1 [expr {[lindex $mainfont 1] + $inc}]] | |||
|
3409 | set curidfont [lreplace $curidfont 1 1 [expr {[lindex $curidfont 1] + $inc}]] | |||
|
3410 | set namefont [lreplace $namefont 1 1 [expr {[lindex $namefont 1] + $inc}]] | |||
|
3411 | set textfont [lreplace $textfont 1 1 [expr {[lindex $textfont 1] + $inc}]] | |||
|
3412 | setcoords | |||
|
3413 | $ctext conf -font $textfont | |||
|
3414 | $ctext tag conf filesep -font [concat $textfont bold] | |||
|
3415 | foreach e $entries { | |||
|
3416 | $e conf -font $mainfont | |||
|
3417 | } | |||
|
3418 | if {$phase == "getcommits"} { | |||
|
3419 | $canv itemconf textitems -font $mainfont | |||
|
3420 | } | |||
|
3421 | redisplay | |||
|
3422 | } | |||
|
3423 | ||||
|
3424 | proc clearsha1 {} { | |||
|
3425 | global sha1entry sha1string | |||
|
3426 | if {[string length $sha1string] == 40} { | |||
|
3427 | $sha1entry delete 0 end | |||
|
3428 | } | |||
|
3429 | } | |||
|
3430 | ||||
|
3431 | proc sha1change {n1 n2 op} { | |||
|
3432 | global sha1string currentid sha1but | |||
|
3433 | if {$sha1string == {} | |||
|
3434 | || ([info exists currentid] && $sha1string == $currentid)} { | |||
|
3435 | set state disabled | |||
|
3436 | } else { | |||
|
3437 | set state normal | |||
|
3438 | } | |||
|
3439 | if {[$sha1but cget -state] == $state} return | |||
|
3440 | if {$state == "normal"} { | |||
|
3441 | $sha1but conf -state normal -relief raised -text "Goto: " | |||
|
3442 | } else { | |||
|
3443 | $sha1but conf -state disabled -relief flat -text "SHA1 ID: " | |||
|
3444 | } | |||
|
3445 | } | |||
|
3446 | ||||
|
3447 | proc gotocommit {} { | |||
|
3448 | global sha1string currentid idline tagids | |||
|
3449 | global lineid numcommits | |||
|
3450 | ||||
|
3451 | if {$sha1string == {} | |||
|
3452 | || ([info exists currentid] && $sha1string == $currentid)} return | |||
|
3453 | if {[info exists tagids($sha1string)]} { | |||
|
3454 | set id $tagids($sha1string) | |||
|
3455 | } else { | |||
|
3456 | set id [string tolower $sha1string] | |||
|
3457 | if {[regexp {^[0-9a-f]{4,39}$} $id]} { | |||
|
3458 | set matches {} | |||
|
3459 | for {set l 0} {$l < $numcommits} {incr l} { | |||
|
3460 | if {[string match $id* $lineid($l)]} { | |||
|
3461 | lappend matches $lineid($l) | |||
|
3462 | } | |||
|
3463 | } | |||
|
3464 | if {$matches ne {}} { | |||
|
3465 | if {[llength $matches] > 1} { | |||
|
3466 | error_popup "Short SHA1 id $id is ambiguous" | |||
|
3467 | return | |||
|
3468 | } | |||
|
3469 | set id [lindex $matches 0] | |||
|
3470 | } | |||
|
3471 | } | |||
|
3472 | } | |||
|
3473 | if {[info exists idline($id)]} { | |||
|
3474 | selectline $idline($id) 1 | |||
|
3475 | return | |||
|
3476 | } | |||
|
3477 | if {[regexp {^[0-9a-fA-F]{4,}$} $sha1string]} { | |||
|
3478 | set type "SHA1 id" | |||
|
3479 | } else { | |||
|
3480 | set type "Tag" | |||
|
3481 | } | |||
|
3482 | error_popup "$type $sha1string is not known" | |||
|
3483 | } | |||
|
3484 | ||||
|
3485 | proc lineenter {x y id} { | |||
|
3486 | global hoverx hovery hoverid hovertimer | |||
|
3487 | global commitinfo canv | |||
|
3488 | ||||
|
3489 | if {![info exists commitinfo($id)]} return | |||
|
3490 | set hoverx $x | |||
|
3491 | set hovery $y | |||
|
3492 | set hoverid $id | |||
|
3493 | if {[info exists hovertimer]} { | |||
|
3494 | after cancel $hovertimer | |||
|
3495 | } | |||
|
3496 | set hovertimer [after 500 linehover] | |||
|
3497 | $canv delete hover | |||
|
3498 | } | |||
|
3499 | ||||
|
3500 | proc linemotion {x y id} { | |||
|
3501 | global hoverx hovery hoverid hovertimer | |||
|
3502 | ||||
|
3503 | if {[info exists hoverid] && $id == $hoverid} { | |||
|
3504 | set hoverx $x | |||
|
3505 | set hovery $y | |||
|
3506 | if {[info exists hovertimer]} { | |||
|
3507 | after cancel $hovertimer | |||
|
3508 | } | |||
|
3509 | set hovertimer [after 500 linehover] | |||
|
3510 | } | |||
|
3511 | } | |||
|
3512 | ||||
|
3513 | proc lineleave {id} { | |||
|
3514 | global hoverid hovertimer canv | |||
|
3515 | ||||
|
3516 | if {[info exists hoverid] && $id == $hoverid} { | |||
|
3517 | $canv delete hover | |||
|
3518 | if {[info exists hovertimer]} { | |||
|
3519 | after cancel $hovertimer | |||
|
3520 | unset hovertimer | |||
|
3521 | } | |||
|
3522 | unset hoverid | |||
|
3523 | } | |||
|
3524 | } | |||
|
3525 | ||||
|
3526 | proc linehover {} { | |||
|
3527 | global hoverx hovery hoverid hovertimer | |||
|
3528 | global canv linespc lthickness | |||
|
3529 | global commitinfo mainfont | |||
|
3530 | ||||
|
3531 | set text [lindex $commitinfo($hoverid) 0] | |||
|
3532 | set ymax [lindex [$canv cget -scrollregion] 3] | |||
|
3533 | if {$ymax == {}} return | |||
|
3534 | set yfrac [lindex [$canv yview] 0] | |||
|
3535 | set x [expr {$hoverx + 2 * $linespc}] | |||
|
3536 | set y [expr {$hovery + $yfrac * $ymax - $linespc / 2}] | |||
|
3537 | set x0 [expr {$x - 2 * $lthickness}] | |||
|
3538 | set y0 [expr {$y - 2 * $lthickness}] | |||
|
3539 | set x1 [expr {$x + [font measure $mainfont $text] + 2 * $lthickness}] | |||
|
3540 | set y1 [expr {$y + $linespc + 2 * $lthickness}] | |||
|
3541 | set t [$canv create rectangle $x0 $y0 $x1 $y1 \ | |||
|
3542 | -fill \#ffff80 -outline black -width 1 -tags hover] | |||
|
3543 | $canv raise $t | |||
|
3544 | set t [$canv create text $x $y -anchor nw -text $text -tags hover] | |||
|
3545 | $canv raise $t | |||
|
3546 | } | |||
|
3547 | ||||
|
3548 | proc clickisonarrow {id y} { | |||
|
3549 | global mainline mainlinearrow sidelines lthickness | |||
|
3550 | ||||
|
3551 | set thresh [expr {2 * $lthickness + 6}] | |||
|
3552 | if {[info exists mainline($id)]} { | |||
|
3553 | if {$mainlinearrow($id) ne "none"} { | |||
|
3554 | if {abs([lindex $mainline($id) 1] - $y) < $thresh} { | |||
|
3555 | return "up" | |||
|
3556 | } | |||
|
3557 | } | |||
|
3558 | } | |||
|
3559 | if {[info exists sidelines($id)]} { | |||
|
3560 | foreach ls $sidelines($id) { | |||
|
3561 | set coords [lindex $ls 0] | |||
|
3562 | set arrow [lindex $ls 2] | |||
|
3563 | if {$arrow eq "first" || $arrow eq "both"} { | |||
|
3564 | if {abs([lindex $coords 1] - $y) < $thresh} { | |||
|
3565 | return "up" | |||
|
3566 | } | |||
|
3567 | } | |||
|
3568 | if {$arrow eq "last" || $arrow eq "both"} { | |||
|
3569 | if {abs([lindex $coords end] - $y) < $thresh} { | |||
|
3570 | return "down" | |||
|
3571 | } | |||
|
3572 | } | |||
|
3573 | } | |||
|
3574 | } | |||
|
3575 | return {} | |||
|
3576 | } | |||
|
3577 | ||||
|
3578 | proc arrowjump {id dirn y} { | |||
|
3579 | global mainline sidelines canv | |||
|
3580 | ||||
|
3581 | set yt {} | |||
|
3582 | if {$dirn eq "down"} { | |||
|
3583 | if {[info exists mainline($id)]} { | |||
|
3584 | set y1 [lindex $mainline($id) 1] | |||
|
3585 | if {$y1 > $y} { | |||
|
3586 | set yt $y1 | |||
|
3587 | } | |||
|
3588 | } | |||
|
3589 | if {[info exists sidelines($id)]} { | |||
|
3590 | foreach ls $sidelines($id) { | |||
|
3591 | set y1 [lindex $ls 0 1] | |||
|
3592 | if {$y1 > $y && ($yt eq {} || $y1 < $yt)} { | |||
|
3593 | set yt $y1 | |||
|
3594 | } | |||
|
3595 | } | |||
|
3596 | } | |||
|
3597 | } else { | |||
|
3598 | if {[info exists sidelines($id)]} { | |||
|
3599 | foreach ls $sidelines($id) { | |||
|
3600 | set y1 [lindex $ls 0 end] | |||
|
3601 | if {$y1 < $y && ($yt eq {} || $y1 > $yt)} { | |||
|
3602 | set yt $y1 | |||
|
3603 | } | |||
|
3604 | } | |||
|
3605 | } | |||
|
3606 | } | |||
|
3607 | if {$yt eq {}} return | |||
|
3608 | set ymax [lindex [$canv cget -scrollregion] 3] | |||
|
3609 | if {$ymax eq {} || $ymax <= 0} return | |||
|
3610 | set view [$canv yview] | |||
|
3611 | set yspan [expr {[lindex $view 1] - [lindex $view 0]}] | |||
|
3612 | set yfrac [expr {$yt / $ymax - $yspan / 2}] | |||
|
3613 | if {$yfrac < 0} { | |||
|
3614 | set yfrac 0 | |||
|
3615 | } | |||
|
3616 | $canv yview moveto $yfrac | |||
|
3617 | } | |||
|
3618 | ||||
|
3619 | proc lineclick {x y id isnew} { | |||
|
3620 | global ctext commitinfo children cflist canv thickerline | |||
|
3621 | ||||
|
3622 | unmarkmatches | |||
|
3623 | unselectline | |||
|
3624 | normalline | |||
|
3625 | $canv delete hover | |||
|
3626 | # draw this line thicker than normal | |||
|
3627 | drawlines $id 1 | |||
|
3628 | set thickerline $id | |||
|
3629 | if {$isnew} { | |||
|
3630 | set ymax [lindex [$canv cget -scrollregion] 3] | |||
|
3631 | if {$ymax eq {}} return | |||
|
3632 | set yfrac [lindex [$canv yview] 0] | |||
|
3633 | set y [expr {$y + $yfrac * $ymax}] | |||
|
3634 | } | |||
|
3635 | set dirn [clickisonarrow $id $y] | |||
|
3636 | if {$dirn ne {}} { | |||
|
3637 | arrowjump $id $dirn $y | |||
|
3638 | return | |||
|
3639 | } | |||
|
3640 | ||||
|
3641 | if {$isnew} { | |||
|
3642 | addtohistory [list lineclick $x $y $id 0] | |||
|
3643 | } | |||
|
3644 | # fill the details pane with info about this line | |||
|
3645 | $ctext conf -state normal | |||
|
3646 | $ctext delete 0.0 end | |||
|
3647 | $ctext tag conf link -foreground blue -underline 1 | |||
|
3648 | $ctext tag bind link <Enter> { %W configure -cursor hand2 } | |||
|
3649 | $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor } | |||
|
3650 | $ctext insert end "Parent:\t" | |||
|
3651 | $ctext insert end $id [list link link0] | |||
|
3652 | $ctext tag bind link0 <1> [list selbyid $id] | |||
|
3653 | set info $commitinfo($id) | |||
|
3654 | $ctext insert end "\n\t[lindex $info 0]\n" | |||
|
3655 | $ctext insert end "\tUser:\t[lindex $info 1]\n" | |||
|
3656 | $ctext insert end "\tDate:\t[lindex $info 2]\n" | |||
|
3657 | if {[info exists children($id)]} { | |||
|
3658 | $ctext insert end "\nChildren:" | |||
|
3659 | set i 0 | |||
|
3660 | foreach child $children($id) { | |||
|
3661 | incr i | |||
|
3662 | set info $commitinfo($child) | |||
|
3663 | $ctext insert end "\n\t" | |||
|
3664 | $ctext insert end $child [list link link$i] | |||
|
3665 | $ctext tag bind link$i <1> [list selbyid $child] | |||
|
3666 | $ctext insert end "\n\t[lindex $info 0]" | |||
|
3667 | $ctext insert end "\n\tUser:\t[lindex $info 1]" | |||
|
3668 | $ctext insert end "\n\tDate:\t[lindex $info 2]\n" | |||
|
3669 | } | |||
|
3670 | } | |||
|
3671 | $ctext conf -state disabled | |||
|
3672 | ||||
|
3673 | $cflist delete 0 end | |||
|
3674 | } | |||
|
3675 | ||||
|
3676 | proc normalline {} { | |||
|
3677 | global thickerline | |||
|
3678 | if {[info exists thickerline]} { | |||
|
3679 | drawlines $thickerline 0 | |||
|
3680 | unset thickerline | |||
|
3681 | } | |||
|
3682 | } | |||
|
3683 | ||||
|
3684 | proc selbyid {id} { | |||
|
3685 | global idline | |||
|
3686 | if {[info exists idline($id)]} { | |||
|
3687 | selectline $idline($id) 1 | |||
|
3688 | } | |||
|
3689 | } | |||
|
3690 | ||||
|
3691 | proc mstime {} { | |||
|
3692 | global startmstime | |||
|
3693 | if {![info exists startmstime]} { | |||
|
3694 | set startmstime [clock clicks -milliseconds] | |||
|
3695 | } | |||
|
3696 | return [format "%.3f" [expr {([clock click -milliseconds] - $startmstime) / 1000.0}]] | |||
|
3697 | } | |||
|
3698 | ||||
|
3699 | proc rowmenu {x y id} { | |||
|
3700 | global rowctxmenu idline selectedline rowmenuid hgvdiff | |||
|
3701 | ||||
|
3702 | if {![info exists selectedline] || $idline($id) eq $selectedline} { | |||
|
3703 | set state disabled | |||
|
3704 | } else { | |||
|
3705 | set state normal | |||
|
3706 | } | |||
|
3707 | $rowctxmenu entryconfigure 0 -state $state | |||
|
3708 | $rowctxmenu entryconfigure 1 -state $state | |||
|
3709 | $rowctxmenu entryconfigure 2 -state $state | |||
|
3710 | if { $hgvdiff ne "" } { | |||
|
3711 | $rowctxmenu entryconfigure 6 -state $state | |||
|
3712 | } | |||
|
3713 | set rowmenuid $id | |||
|
3714 | tk_popup $rowctxmenu $x $y | |||
|
3715 | } | |||
|
3716 | ||||
|
3717 | proc diffvssel {dirn} { | |||
|
3718 | global rowmenuid selectedline lineid | |||
|
3719 | ||||
|
3720 | if {![info exists selectedline]} return | |||
|
3721 | if {$dirn} { | |||
|
3722 | set oldid $lineid($selectedline) | |||
|
3723 | set newid $rowmenuid | |||
|
3724 | } else { | |||
|
3725 | set oldid $rowmenuid | |||
|
3726 | set newid $lineid($selectedline) | |||
|
3727 | } | |||
|
3728 | addtohistory [list doseldiff $oldid $newid] | |||
|
3729 | doseldiff $oldid $newid | |||
|
3730 | } | |||
|
3731 | ||||
|
3732 | proc doseldiff {oldid newid} { | |||
|
3733 | global ctext cflist | |||
|
3734 | global commitinfo | |||
|
3735 | ||||
|
3736 | $ctext conf -state normal | |||
|
3737 | $ctext delete 0.0 end | |||
|
3738 | $ctext mark set fmark.0 0.0 | |||
|
3739 | $ctext mark gravity fmark.0 left | |||
|
3740 | $cflist delete 0 end | |||
|
3741 | $cflist insert end "Top" | |||
|
3742 | $ctext insert end "From " | |||
|
3743 | $ctext tag conf link -foreground blue -underline 1 | |||
|
3744 | $ctext tag bind link <Enter> { %W configure -cursor hand2 } | |||
|
3745 | $ctext tag bind link <Leave> { %W configure -cursor $curtextcursor } | |||
|
3746 | $ctext tag bind link0 <1> [list selbyid $oldid] | |||
|
3747 | $ctext insert end $oldid [list link link0] | |||
|
3748 | $ctext insert end "\n " | |||
|
3749 | $ctext insert end [lindex $commitinfo($oldid) 0] | |||
|
3750 | $ctext insert end "\n\nTo " | |||
|
3751 | $ctext tag bind link1 <1> [list selbyid $newid] | |||
|
3752 | $ctext insert end $newid [list link link1] | |||
|
3753 | $ctext insert end "\n " | |||
|
3754 | $ctext insert end [lindex $commitinfo($newid) 0] | |||
|
3755 | $ctext insert end "\n" | |||
|
3756 | $ctext conf -state disabled | |||
|
3757 | $ctext tag delete Comments | |||
|
3758 | $ctext tag remove found 1.0 end | |||
|
3759 | startdiff [list $newid $oldid] | |||
|
3760 | } | |||
|
3761 | ||||
|
3762 | proc mkpatch {} { | |||
|
3763 | global rowmenuid currentid commitinfo patchtop patchnum | |||
|
3764 | ||||
|
3765 | if {![info exists currentid]} return | |||
|
3766 | set oldid $currentid | |||
|
3767 | set oldhead [lindex $commitinfo($oldid) 0] | |||
|
3768 | set newid $rowmenuid | |||
|
3769 | set newhead [lindex $commitinfo($newid) 0] | |||
|
3770 | set top .patch | |||
|
3771 | set patchtop $top | |||
|
3772 | catch {destroy $top} | |||
|
3773 | toplevel $top | |||
|
3774 | ttk::label $top.from -text "From:" | |||
|
3775 | ttk::entry $top.fromsha1 -width 40 | |||
|
3776 | $top.fromsha1 insert 0 $oldid | |||
|
3777 | $top.fromsha1 conf -state readonly | |||
|
3778 | grid $top.from $top.fromsha1 -sticky w -pady {10 0} | |||
|
3779 | ttk::entry $top.fromhead -width 60 | |||
|
3780 | $top.fromhead insert 0 $oldhead | |||
|
3781 | $top.fromhead conf -state readonly | |||
|
3782 | grid x $top.fromhead -sticky w | |||
|
3783 | ttk::label $top.to -text "To:" | |||
|
3784 | ttk::entry $top.tosha1 -width 40 | |||
|
3785 | $top.tosha1 insert 0 $newid | |||
|
3786 | $top.tosha1 conf -state readonly | |||
|
3787 | grid $top.to $top.tosha1 -sticky w | |||
|
3788 | ttk::entry $top.tohead -width 60 | |||
|
3789 | $top.tohead insert 0 $newhead | |||
|
3790 | $top.tohead conf -state readonly | |||
|
3791 | grid x $top.tohead -sticky w | |||
|
3792 | ttk::button $top.rev -text "Reverse" -command mkpatchrev | |||
|
3793 | grid $top.rev x -pady 10 | |||
|
3794 | ttk::label $top.flab -text "Output file:" | |||
|
3795 | ttk::entry $top.fname -width 60 | |||
|
3796 | $top.fname insert 0 [file normalize "patch$patchnum.patch"] | |||
|
3797 | incr patchnum | |||
|
3798 | grid $top.flab $top.fname -sticky w | |||
|
3799 | ttk::frame $top.buts | |||
|
3800 | ttk::button $top.buts.gen -text "Generate" -command mkpatchgo | |||
|
3801 | ttk::button $top.buts.can -text "Cancel" -command mkpatchcan | |||
|
3802 | grid $top.buts.gen $top.buts.can | |||
|
3803 | grid columnconfigure $top.buts 0 -weight 1 -uniform a | |||
|
3804 | grid columnconfigure $top.buts 1 -weight 1 -uniform a | |||
|
3805 | grid $top.buts - -pady 10 -sticky ew | |||
|
3806 | focus $top.fname | |||
|
3807 | popupify $top | |||
|
3808 | wm title $top "Generate a patch" | |||
|
3809 | } | |||
|
3810 | ||||
|
3811 | proc mkpatchrev {} { | |||
|
3812 | global patchtop | |||
|
3813 | ||||
|
3814 | set oldid [$patchtop.fromsha1 get] | |||
|
3815 | set oldhead [$patchtop.fromhead get] | |||
|
3816 | set newid [$patchtop.tosha1 get] | |||
|
3817 | set newhead [$patchtop.tohead get] | |||
|
3818 | foreach e [list fromsha1 fromhead tosha1 tohead] \ | |||
|
3819 | v [list $newid $newhead $oldid $oldhead] { | |||
|
3820 | $patchtop.$e conf -state normal | |||
|
3821 | $patchtop.$e delete 0 end | |||
|
3822 | $patchtop.$e insert 0 $v | |||
|
3823 | $patchtop.$e conf -state readonly | |||
|
3824 | } | |||
|
3825 | } | |||
|
3826 | ||||
|
3827 | proc mkpatchgo {} { | |||
|
3828 | global patchtop env | |||
|
3829 | ||||
|
3830 | set oldid [$patchtop.fromsha1 get] | |||
|
3831 | set newid [$patchtop.tosha1 get] | |||
|
3832 | set fname [$patchtop.fname get] | |||
|
3833 | if {[catch {exec $env(HG) --config ui.report_untrusted=false debug-diff-tree -p $oldid $newid >$fname &} err]} { | |||
|
3834 | error_popup "Error creating patch: $err" | |||
|
3835 | } | |||
|
3836 | catch {destroy $patchtop} | |||
|
3837 | unset patchtop | |||
|
3838 | } | |||
|
3839 | ||||
|
3840 | proc mkpatchcan {} { | |||
|
3841 | global patchtop | |||
|
3842 | ||||
|
3843 | catch {destroy $patchtop} | |||
|
3844 | unset patchtop | |||
|
3845 | } | |||
|
3846 | ||||
|
3847 | proc mktag {} { | |||
|
3848 | global rowmenuid mktagtop commitinfo | |||
|
3849 | ||||
|
3850 | set top .maketag | |||
|
3851 | set mktagtop $top | |||
|
3852 | catch {destroy $top} | |||
|
3853 | toplevel $top | |||
|
3854 | ttk::label $top.id -text "ID:" | |||
|
3855 | ttk::entry $top.sha1 -width 40 | |||
|
3856 | $top.sha1 insert 0 $rowmenuid | |||
|
3857 | $top.sha1 conf -state readonly | |||
|
3858 | grid $top.id $top.sha1 -sticky w -pady {10 0} | |||
|
3859 | ttk::entry $top.head -width 60 | |||
|
3860 | $top.head insert 0 [lindex $commitinfo($rowmenuid) 0] | |||
|
3861 | $top.head conf -state readonly | |||
|
3862 | grid x $top.head -sticky w | |||
|
3863 | ttk::label $top.tlab -text "Tag name:" | |||
|
3864 | ttk::entry $top.tag -width 60 | |||
|
3865 | grid $top.tlab $top.tag -sticky w | |||
|
3866 | ttk::frame $top.buts | |||
|
3867 | ttk::button $top.buts.gen -text "Create" -command mktaggo | |||
|
3868 | ttk::button $top.buts.can -text "Cancel" -command mktagcan | |||
|
3869 | grid $top.buts.gen $top.buts.can | |||
|
3870 | grid columnconfigure $top.buts 0 -weight 1 -uniform a | |||
|
3871 | grid columnconfigure $top.buts 1 -weight 1 -uniform a | |||
|
3872 | grid $top.buts - -pady 10 -sticky ew | |||
|
3873 | focus $top.tag | |||
|
3874 | popupify $top | |||
|
3875 | wm title $top "Create a tag" | |||
|
3876 | } | |||
|
3877 | ||||
|
3878 | proc domktag {} { | |||
|
3879 | global mktagtop env tagids idtags | |||
|
3880 | ||||
|
3881 | set id [$mktagtop.sha1 get] | |||
|
3882 | set tag [$mktagtop.tag get] | |||
|
3883 | if {$tag == {}} { | |||
|
3884 | error_popup "No tag name specified" | |||
|
3885 | return | |||
|
3886 | } | |||
|
3887 | if {[info exists tagids($tag)]} { | |||
|
3888 | error_popup "Tag \"$tag\" already exists" | |||
|
3889 | return | |||
|
3890 | } | |||
|
3891 | if {[catch { | |||
|
3892 | set out [exec $env(HG) --config ui.report_untrusted=false tag -r $id $tag] | |||
|
3893 | } err]} { | |||
|
3894 | error_popup "Error creating tag: $err" | |||
|
3895 | return | |||
|
3896 | } | |||
|
3897 | ||||
|
3898 | set tagids($tag) $id | |||
|
3899 | lappend idtags($id) $tag | |||
|
3900 | redrawtags $id | |||
|
3901 | } | |||
|
3902 | ||||
|
3903 | proc redrawtags {id} { | |||
|
3904 | global canv linehtag idline idpos selectedline | |||
|
3905 | ||||
|
3906 | if {![info exists idline($id)]} return | |||
|
3907 | $canv delete tag.$id | |||
|
3908 | set xt [eval drawtags $id $idpos($id)] | |||
|
3909 | $canv coords $linehtag($idline($id)) $xt [lindex $idpos($id) 2] | |||
|
3910 | if {[info exists selectedline] && $selectedline == $idline($id)} { | |||
|
3911 | selectline $selectedline 0 | |||
|
3912 | } | |||
|
3913 | } | |||
|
3914 | ||||
|
3915 | proc mktagcan {} { | |||
|
3916 | global mktagtop | |||
|
3917 | ||||
|
3918 | catch {destroy $mktagtop} | |||
|
3919 | unset mktagtop | |||
|
3920 | } | |||
|
3921 | ||||
|
3922 | proc mktaggo {} { | |||
|
3923 | domktag | |||
|
3924 | mktagcan | |||
|
3925 | } | |||
|
3926 | ||||
|
3927 | proc writecommit {} { | |||
|
3928 | global rowmenuid wrcomtop commitinfo | |||
|
3929 | ||||
|
3930 | set top .writecommit | |||
|
3931 | set wrcomtop $top | |||
|
3932 | catch {destroy $top} | |||
|
3933 | toplevel $top | |||
|
3934 | ttk::label $top.id -text "ID:" | |||
|
3935 | ttk::entry $top.sha1 -width 40 | |||
|
3936 | $top.sha1 insert 0 $rowmenuid | |||
|
3937 | $top.sha1 conf -state readonly | |||
|
3938 | grid $top.id $top.sha1 -sticky w -pady {10 0} | |||
|
3939 | ttk::entry $top.head -width 60 | |||
|
3940 | $top.head insert 0 [lindex $commitinfo($rowmenuid) 0] | |||
|
3941 | $top.head conf -state readonly | |||
|
3942 | grid x $top.head -sticky w | |||
|
3943 | ttk::label $top.flab -text "Output file:" | |||
|
3944 | ttk::entry $top.fname -width 60 | |||
|
3945 | $top.fname insert 0 [file normalize "commit-[string range $rowmenuid 0 6].diff"] | |||
|
3946 | grid $top.flab $top.fname -sticky w | |||
|
3947 | ttk::frame $top.buts | |||
|
3948 | ttk::button $top.buts.gen -text "Write" -command wrcomgo | |||
|
3949 | ttk::button $top.buts.can -text "Cancel" -command wrcomcan | |||
|
3950 | grid $top.buts.gen $top.buts.can | |||
|
3951 | grid columnconfigure $top.buts 0 -weight 1 -uniform a | |||
|
3952 | grid columnconfigure $top.buts 1 -weight 1 -uniform a | |||
|
3953 | grid $top.buts - -pady 10 -sticky ew | |||
|
3954 | focus $top.fname | |||
|
3955 | popupify $top | |||
|
3956 | wm title $top "Write commit to a file" | |||
|
3957 | } | |||
|
3958 | ||||
|
3959 | proc wrcomgo {} { | |||
|
3960 | global wrcomtop | |||
|
3961 | ||||
|
3962 | set id [$wrcomtop.sha1 get] | |||
|
3963 | set fname [$wrcomtop.fname get] | |||
|
3964 | if {[catch {exec $::env(HG) --config ui.report_untrusted=false export --git -o [string map {% %%} $fname] $id} err]} { | |||
|
3965 | error_popup "Error writing commit: $err" | |||
|
3966 | } | |||
|
3967 | catch {destroy $wrcomtop} | |||
|
3968 | unset wrcomtop | |||
|
3969 | } | |||
|
3970 | ||||
|
3971 | proc wrcomcan {} { | |||
|
3972 | global wrcomtop | |||
|
3973 | ||||
|
3974 | catch {destroy $wrcomtop} | |||
|
3975 | unset wrcomtop | |||
|
3976 | } | |||
|
3977 | ||||
|
3978 | proc listrefs {id} { | |||
|
3979 | global idtags idheads idotherrefs idbookmarks | |||
|
3980 | ||||
|
3981 | set w {} | |||
|
3982 | if {[info exists idbookmarks($id)]} { | |||
|
3983 | set w $idbookmarks($id) | |||
|
3984 | } | |||
|
3985 | set x {} | |||
|
3986 | if {[info exists idtags($id)]} { | |||
|
3987 | set x $idtags($id) | |||
|
3988 | } | |||
|
3989 | set y {} | |||
|
3990 | if {[info exists idheads($id)]} { | |||
|
3991 | set y $idheads($id) | |||
|
3992 | } | |||
|
3993 | set z {} | |||
|
3994 | if {[info exists idotherrefs($id)]} { | |||
|
3995 | set z $idotherrefs($id) | |||
|
3996 | } | |||
|
3997 | return [list $w $x $y $z] | |||
|
3998 | } | |||
|
3999 | ||||
|
4000 | proc rereadrefs {} { | |||
|
4001 | global idbookmarks idtags idheads idotherrefs | |||
|
4002 | global bookmarkids tagids headids otherrefids | |||
|
4003 | ||||
|
4004 | set refids [concat [array names idtags] \ | |||
|
4005 | [array names idheads] [array names idotherrefs] \ | |||
|
4006 | [array names idbookmarks]] | |||
|
4007 | foreach id $refids { | |||
|
4008 | if {![info exists ref($id)]} { | |||
|
4009 | set ref($id) [listrefs $id] | |||
|
4010 | } | |||
|
4011 | } | |||
|
4012 | foreach v {tagids idtags headids idheads otherrefids idotherrefs \ | |||
|
4013 | bookmarkids idbookmarks} { | |||
|
4014 | catch {unset $v} | |||
|
4015 | } | |||
|
4016 | readrefs | |||
|
4017 | set refids [lsort -unique [concat $refids [array names idtags] \ | |||
|
4018 | [array names idheads] [array names idotherrefs] \ | |||
|
4019 | [array names idbookmarks]]] | |||
|
4020 | foreach id $refids { | |||
|
4021 | set v [listrefs $id] | |||
|
4022 | if {![info exists ref($id)] || $ref($id) != $v} { | |||
|
4023 | redrawtags $id | |||
|
4024 | } | |||
|
4025 | } | |||
|
4026 | } | |||
|
4027 | ||||
|
4028 | proc vdiff {withparent} { | |||
|
4029 | global env rowmenuid selectedline lineid hgvdiff | |||
|
4030 | ||||
|
4031 | if {![info exists rowmenuid]} return | |||
|
4032 | set curid $rowmenuid | |||
|
4033 | ||||
|
4034 | if {$withparent} { | |||
|
4035 | set parents [exec $env(HG) --config ui.report_untrusted=false parents --rev $curid --template "{node}\n"] | |||
|
4036 | set firstparent [lindex [split $parents "\n"] 0] | |||
|
4037 | set otherid $firstparent | |||
|
4038 | } else { | |||
|
4039 | if {![info exists selectedline]} return | |||
|
4040 | set otherid $lineid($selectedline) | |||
|
4041 | } | |||
|
4042 | set range "$otherid:$curid" | |||
|
4043 | if {[catch {exec $env(HG) --config ui.report_untrusted=false $hgvdiff -r $range} err]} { | |||
|
4044 | # Ignore errors, this is just visualization | |||
|
4045 | } | |||
|
4046 | } | |||
|
4047 | ||||
|
4048 | proc showtag {tag isnew} { | |||
|
4049 | global ctext cflist tagcontents tagids linknum | |||
|
4050 | ||||
|
4051 | if {$isnew} { | |||
|
4052 | addtohistory [list showtag $tag 0] | |||
|
4053 | } | |||
|
4054 | $ctext conf -state normal | |||
|
4055 | $ctext delete 0.0 end | |||
|
4056 | set linknum 0 | |||
|
4057 | if {[info exists tagcontents($tag)]} { | |||
|
4058 | set text $tagcontents($tag) | |||
|
4059 | } else { | |||
|
4060 | set text "Tag: $tag\nId: $tagids($tag)" | |||
|
4061 | } | |||
|
4062 | appendwithlinks $text | |||
|
4063 | $ctext conf -state disabled | |||
|
4064 | $cflist delete 0 end | |||
|
4065 | } | |||
|
4066 | ||||
|
4067 | proc doquit {} { | |||
|
4068 | global stopped | |||
|
4069 | set stopped 100 | |||
|
4070 | destroy . | |||
|
4071 | } | |||
|
4072 | ||||
|
4073 | proc getconfig {} { | |||
|
4074 | global env | |||
|
4075 | set config {} | |||
|
4076 | ||||
|
4077 | set lines [exec $env(HG) debugconfig] | |||
|
4078 | foreach line [split $lines \n] { | |||
|
4079 | set line [string trimright $line \r] | |||
|
4080 | if {[string match hgk.* $line]} { | |||
|
4081 | regexp {(.*)=(.*)} $line - k v | |||
|
4082 | lappend config $k $v | |||
|
4083 | } | |||
|
4084 | } | |||
|
4085 | return $config | |||
|
4086 | } | |||
|
4087 | ||||
|
4088 | # defaults... | |||
|
4089 | set datemode 0 | |||
|
4090 | set boldnames 0 | |||
|
4091 | set diffopts "-U 5 -p" | |||
|
4092 | ||||
|
4093 | set mainfont {Helvetica 9} | |||
|
4094 | set curidfont {} | |||
|
4095 | set textfont {Courier 9} | |||
|
4096 | set findmergefiles 0 | |||
|
4097 | set gaudydiff 0 | |||
|
4098 | set maxgraphpct 50 | |||
|
4099 | set maxwidth 16 | |||
|
4100 | ||||
|
4101 | set colors {green red blue magenta darkgrey brown orange} | |||
|
4102 | set authorcolors { | |||
|
4103 | black blue deeppink mediumorchid blue burlywood4 goldenrod slateblue red2 navy dimgrey | |||
|
4104 | } | |||
|
4105 | set bgcolor white | |||
|
4106 | ||||
|
4107 | # This color should probably be some system color (provided by tk), | |||
|
4108 | # but as the bgcolor has always been set to white, I choose to ignore | |||
|
4109 | set fgcolor black | |||
|
4110 | set diffaddcolor "#00a000" | |||
|
4111 | set diffremcolor red | |||
|
4112 | set diffmerge1color red | |||
|
4113 | set diffmerge2color blue | |||
|
4114 | set hunksepcolor blue | |||
|
4115 | ||||
|
4116 | catch {source ~/.hgk} | |||
|
4117 | ||||
|
4118 | if {$curidfont == ""} { # initialize late based on current mainfont | |||
|
4119 | set curidfont "$mainfont bold italic underline" | |||
|
4120 | } | |||
|
4121 | ||||
|
4122 | set namefont $mainfont | |||
|
4123 | if {$boldnames} { | |||
|
4124 | lappend namefont bold | |||
|
4125 | } | |||
|
4126 | ||||
|
4127 | set revtreeargs {} | |||
|
4128 | foreach arg $argv { | |||
|
4129 | switch -regexp -- $arg { | |||
|
4130 | "^$" { } | |||
|
4131 | "^-b" { set boldnames 1 } | |||
|
4132 | "^-d" { set datemode 1 } | |||
|
4133 | default { | |||
|
4134 | lappend revtreeargs $arg | |||
|
4135 | } | |||
|
4136 | } | |||
|
4137 | } | |||
|
4138 | ||||
|
4139 | set history {} | |||
|
4140 | set historyindex 0 | |||
|
4141 | ||||
|
4142 | set stopped 0 | |||
|
4143 | set redisplaying 0 | |||
|
4144 | set stuffsaved 0 | |||
|
4145 | set patchnum 0 | |||
|
4146 | ||||
|
4147 | set config(hgk.vdiff) "" | |||
|
4148 | array set config [getconfig] | |||
|
4149 | set hgvdiff $config(hgk.vdiff) | |||
|
4150 | setcoords | |||
|
4151 | makewindow | |||
|
4152 | readrefs | |||
|
4153 | set hgroot [exec $env(HG) root] | |||
|
4154 | wm title . "hgk $hgroot" | |||
|
4155 | getcommits $revtreeargs |
@@ -0,0 +1,97 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | # | |||
|
3 | # hgperf - measure performance of Mercurial commands | |||
|
4 | # | |||
|
5 | # Copyright 2014 Matt Mackall <mpm@selenic.com> | |||
|
6 | # | |||
|
7 | # This software may be used and distributed according to the terms of the | |||
|
8 | # GNU General Public License version 2 or any later version. | |||
|
9 | ||||
|
10 | '''measure performance of Mercurial commands | |||
|
11 | ||||
|
12 | Using ``hgperf`` instead of ``hg`` measures performance of the target | |||
|
13 | Mercurial command. For example, the execution below measures | |||
|
14 | performance of :hg:`heads --topo`:: | |||
|
15 | ||||
|
16 | $ hgperf heads --topo | |||
|
17 | ||||
|
18 | All command output via ``ui`` is suppressed, and just measurement | |||
|
19 | result is displayed: see also "perf" extension in "contrib". | |||
|
20 | ||||
|
21 | Costs of processing before dispatching to the command function like | |||
|
22 | below are not measured:: | |||
|
23 | ||||
|
24 | - parsing command line (e.g. option validity check) | |||
|
25 | - reading configuration files in | |||
|
26 | ||||
|
27 | But ``pre-`` and ``post-`` hook invocation for the target command is | |||
|
28 | measured, even though these are invoked before or after dispatching to | |||
|
29 | the command function, because these may be required to repeat | |||
|
30 | execution of the target command correctly. | |||
|
31 | ''' | |||
|
32 | ||||
|
33 | import os | |||
|
34 | import sys | |||
|
35 | ||||
|
36 | libdir = '@LIBDIR@' | |||
|
37 | ||||
|
38 | if libdir != '@' 'LIBDIR' '@': | |||
|
39 | if not os.path.isabs(libdir): | |||
|
40 | libdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), | |||
|
41 | libdir) | |||
|
42 | libdir = os.path.abspath(libdir) | |||
|
43 | sys.path.insert(0, libdir) | |||
|
44 | ||||
|
45 | # enable importing on demand to reduce startup time | |||
|
46 | try: | |||
|
47 | from mercurial import demandimport; demandimport.enable() | |||
|
48 | except ImportError: | |||
|
49 | import sys | |||
|
50 | sys.stderr.write("abort: couldn't find mercurial libraries in [%s]\n" % | |||
|
51 | ' '.join(sys.path)) | |||
|
52 | sys.stderr.write("(check your install and PYTHONPATH)\n") | |||
|
53 | sys.exit(-1) | |||
|
54 | ||||
|
55 | from mercurial import ( | |||
|
56 | dispatch, | |||
|
57 | util, | |||
|
58 | ) | |||
|
59 | ||||
|
60 | def timer(func, title=None): | |||
|
61 | results = [] | |||
|
62 | begin = util.timer() | |||
|
63 | count = 0 | |||
|
64 | while True: | |||
|
65 | ostart = os.times() | |||
|
66 | cstart = util.timer() | |||
|
67 | r = func() | |||
|
68 | cstop = util.timer() | |||
|
69 | ostop = os.times() | |||
|
70 | count += 1 | |||
|
71 | a, b = ostart, ostop | |||
|
72 | results.append((cstop - cstart, b[0] - a[0], b[1]-a[1])) | |||
|
73 | if cstop - begin > 3 and count >= 100: | |||
|
74 | break | |||
|
75 | if cstop - begin > 10 and count >= 3: | |||
|
76 | break | |||
|
77 | if title: | |||
|
78 | sys.stderr.write("! %s\n" % title) | |||
|
79 | if r: | |||
|
80 | sys.stderr.write("! result: %s\n" % r) | |||
|
81 | m = min(results) | |||
|
82 | sys.stderr.write("! wall %f comb %f user %f sys %f (best of %d)\n" | |||
|
83 | % (m[0], m[1] + m[2], m[1], m[2], count)) | |||
|
84 | ||||
|
85 | orgruncommand = dispatch.runcommand | |||
|
86 | ||||
|
87 | def runcommand(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions): | |||
|
88 | ui.pushbuffer() | |||
|
89 | lui.pushbuffer() | |||
|
90 | timer(lambda : orgruncommand(lui, repo, cmd, fullargs, ui, | |||
|
91 | options, d, cmdpats, cmdoptions)) | |||
|
92 | ui.popbuffer() | |||
|
93 | lui.popbuffer() | |||
|
94 | ||||
|
95 | dispatch.runcommand = runcommand | |||
|
96 | ||||
|
97 | dispatch.run() |
@@ -0,0 +1,13 b'' | |||||
|
1 | CC := gcc | |||
|
2 | CFLAGS := -g -O2 -Wall -Werror | |||
|
3 | ||||
|
4 | prefix ?= /usr/bin | |||
|
5 | ||||
|
6 | hgsh: hgsh.o | |||
|
7 | $(CC) -o $@ $< | |||
|
8 | ||||
|
9 | install: hgsh | |||
|
10 | install -m755 hgsh $(prefix) | |||
|
11 | ||||
|
12 | clean: | |||
|
13 | rm -f *.o hgsh |
@@ -0,0 +1,438 b'' | |||||
|
1 | /* | |||
|
2 | * hgsh.c - restricted login shell for mercurial | |||
|
3 | * | |||
|
4 | * Copyright 2006 Vadim Gelfer <vadim.gelfer@gmail.com> | |||
|
5 | * | |||
|
6 | * This software may be used and distributed according to the terms of the | |||
|
7 | * GNU General Public License, incorporated herein by reference. | |||
|
8 | * | |||
|
9 | * this program is login shell for dedicated mercurial user account. it | |||
|
10 | * only allows few actions: | |||
|
11 | * | |||
|
12 | * 1. run hg in server mode on specific repository. no other hg commands | |||
|
13 | * are allowed. we try to verify that repo to be accessed exists under | |||
|
14 | * given top-level directory. | |||
|
15 | * | |||
|
16 | * 2. (optional) forward ssh connection from firewall/gateway machine to | |||
|
17 | * "real" mercurial host, to let users outside intranet pull and push | |||
|
18 | * changes through firewall. | |||
|
19 | * | |||
|
20 | * 3. (optional) run normal shell, to allow to "su" to mercurial user, use | |||
|
21 | * "sudo" to run programs as that user, or run cron jobs as that user. | |||
|
22 | * | |||
|
23 | * only tested on linux yet. patches for non-linux systems welcome. | |||
|
24 | */ | |||
|
25 | ||||
|
26 | #ifndef _GNU_SOURCE | |||
|
27 | #define _GNU_SOURCE /* for asprintf */ | |||
|
28 | #endif | |||
|
29 | ||||
|
30 | #include <stdio.h> | |||
|
31 | #include <stdlib.h> | |||
|
32 | #include <string.h> | |||
|
33 | #include <sys/stat.h> | |||
|
34 | #include <sys/types.h> | |||
|
35 | #include <sysexits.h> | |||
|
36 | #include <unistd.h> | |||
|
37 | ||||
|
38 | /* | |||
|
39 | * user config. | |||
|
40 | * | |||
|
41 | * if you see a hostname below, just use first part of hostname. example, | |||
|
42 | * if you have host named foo.bar.com, use "foo". | |||
|
43 | */ | |||
|
44 | ||||
|
45 | /* | |||
|
46 | * HG_GATEWAY: hostname of gateway/firewall machine that people outside your | |||
|
47 | * intranet ssh into if they need to ssh to other machines. if you do not | |||
|
48 | * have such machine, set to NULL. | |||
|
49 | */ | |||
|
50 | #ifndef HG_GATEWAY | |||
|
51 | #define HG_GATEWAY "gateway" | |||
|
52 | #endif | |||
|
53 | ||||
|
54 | /* | |||
|
55 | * HG_HOST: hostname of mercurial server. if any machine is allowed, set to | |||
|
56 | * NULL. | |||
|
57 | */ | |||
|
58 | #ifndef HG_HOST | |||
|
59 | #define HG_HOST "mercurial" | |||
|
60 | #endif | |||
|
61 | ||||
|
62 | /* | |||
|
63 | * HG_USER: username to log in from HG_GATEWAY to HG_HOST. if gateway and | |||
|
64 | * host username are same, set to NULL. | |||
|
65 | */ | |||
|
66 | #ifndef HG_USER | |||
|
67 | #define HG_USER "hg" | |||
|
68 | #endif | |||
|
69 | ||||
|
70 | /* | |||
|
71 | * HG_ROOT: root of tree full of mercurial repos. if you do not want to | |||
|
72 | * validate location of repo when someone is try to access, set to NULL. | |||
|
73 | */ | |||
|
74 | #ifndef HG_ROOT | |||
|
75 | #define HG_ROOT "/home/hg/repos" | |||
|
76 | #endif | |||
|
77 | ||||
|
78 | /* | |||
|
79 | * HG: path to the mercurial executable to run. | |||
|
80 | */ | |||
|
81 | #ifndef HG | |||
|
82 | #define HG "/home/hg/bin/hg" | |||
|
83 | #endif | |||
|
84 | ||||
|
85 | /* | |||
|
86 | * HG_SHELL: shell to use for actions like "sudo" and "su" access to | |||
|
87 | * mercurial user, and cron jobs. if you want to make these things | |||
|
88 | * impossible, set to NULL. | |||
|
89 | */ | |||
|
90 | #ifndef HG_SHELL | |||
|
91 | #define HG_SHELL NULL | |||
|
92 | /* #define HG_SHELL "/bin/bash" */ | |||
|
93 | #endif | |||
|
94 | ||||
|
95 | /* | |||
|
96 | * HG_HELP: some way for users to get support if they have problem. if they | |||
|
97 | * should not get helpful message, set to NULL. | |||
|
98 | */ | |||
|
99 | #ifndef HG_HELP | |||
|
100 | #define HG_HELP "please contact support@example.com for help." | |||
|
101 | #endif | |||
|
102 | ||||
|
103 | /* | |||
|
104 | * SSH: path to ssh executable to run, if forwarding from HG_GATEWAY to | |||
|
105 | * HG_HOST. if you want to use rsh instead (why?), you need to modify | |||
|
106 | * arguments it is called with. see forward_through_gateway. | |||
|
107 | */ | |||
|
108 | #ifndef SSH | |||
|
109 | #define SSH "/usr/bin/ssh" | |||
|
110 | #endif | |||
|
111 | ||||
|
112 | /* | |||
|
113 | * tell whether to print command that is to be executed. useful for | |||
|
114 | * debugging. should not interfere with mercurial operation, since | |||
|
115 | * mercurial only cares about stdin and stdout, and this prints to stderr. | |||
|
116 | */ | |||
|
117 | static const int debug = 0; | |||
|
118 | ||||
|
119 | static void print_cmdline(int argc, char **argv) | |||
|
120 | { | |||
|
121 | FILE *fp = stderr; | |||
|
122 | int i; | |||
|
123 | ||||
|
124 | fputs("command: ", fp); | |||
|
125 | ||||
|
126 | for (i = 0; i < argc; i++) { | |||
|
127 | char *spc = strpbrk(argv[i], " \t\r\n"); | |||
|
128 | if (spc) { | |||
|
129 | fputc('\'', fp); | |||
|
130 | } | |||
|
131 | fputs(argv[i], fp); | |||
|
132 | if (spc) { | |||
|
133 | fputc('\'', fp); | |||
|
134 | } | |||
|
135 | if (i < argc - 1) { | |||
|
136 | fputc(' ', fp); | |||
|
137 | } | |||
|
138 | } | |||
|
139 | fputc('\n', fp); | |||
|
140 | fflush(fp); | |||
|
141 | } | |||
|
142 | ||||
|
143 | static void usage(const char *reason, int exitcode) | |||
|
144 | { | |||
|
145 | char *hg_help = HG_HELP; | |||
|
146 | ||||
|
147 | if (reason) { | |||
|
148 | fprintf(stderr, "*** Error: %s.\n", reason); | |||
|
149 | } | |||
|
150 | fprintf(stderr, "*** This program has been invoked incorrectly.\n"); | |||
|
151 | if (hg_help) { | |||
|
152 | fprintf(stderr, "*** %s\n", hg_help); | |||
|
153 | } | |||
|
154 | exit(exitcode ? exitcode : EX_USAGE); | |||
|
155 | } | |||
|
156 | ||||
|
157 | /* | |||
|
158 | * run on gateway host to make another ssh connection, to "real" mercurial | |||
|
159 | * server. it sends its command line unmodified to far end. | |||
|
160 | * | |||
|
161 | * never called if HG_GATEWAY is NULL. | |||
|
162 | */ | |||
|
163 | static void forward_through_gateway(int argc, char **argv) | |||
|
164 | { | |||
|
165 | char *ssh = SSH; | |||
|
166 | char *hg_host = HG_HOST; | |||
|
167 | char *hg_user = HG_USER; | |||
|
168 | char **nargv = alloca((10 + argc) * sizeof(char *)); | |||
|
169 | int i = 0, j; | |||
|
170 | ||||
|
171 | nargv[i++] = ssh; | |||
|
172 | nargv[i++] = "-q"; | |||
|
173 | nargv[i++] = "-T"; | |||
|
174 | nargv[i++] = "-x"; | |||
|
175 | if (hg_user) { | |||
|
176 | nargv[i++] = "-l"; | |||
|
177 | nargv[i++] = hg_user; | |||
|
178 | } | |||
|
179 | nargv[i++] = hg_host; | |||
|
180 | ||||
|
181 | /* | |||
|
182 | * sshd called us with added "-c", because it thinks we are a shell. | |||
|
183 | * drop it if we find it. | |||
|
184 | */ | |||
|
185 | j = 1; | |||
|
186 | if (j < argc && strcmp(argv[j], "-c") == 0) { | |||
|
187 | j++; | |||
|
188 | } | |||
|
189 | ||||
|
190 | for (; j < argc; i++, j++) { | |||
|
191 | nargv[i] = argv[j]; | |||
|
192 | } | |||
|
193 | nargv[i] = NULL; | |||
|
194 | ||||
|
195 | if (debug) { | |||
|
196 | print_cmdline(i, nargv); | |||
|
197 | } | |||
|
198 | ||||
|
199 | execv(ssh, nargv); | |||
|
200 | perror(ssh); | |||
|
201 | exit(EX_UNAVAILABLE); | |||
|
202 | } | |||
|
203 | ||||
|
204 | /* | |||
|
205 | * run shell. let administrator "su" to mercurial user's account to do | |||
|
206 | * administrative works. | |||
|
207 | * | |||
|
208 | * never called if HG_SHELL is NULL. | |||
|
209 | */ | |||
|
210 | static void run_shell(int argc, char **argv) | |||
|
211 | { | |||
|
212 | char *hg_shell = HG_SHELL; | |||
|
213 | char **nargv; | |||
|
214 | char *c; | |||
|
215 | int i; | |||
|
216 | ||||
|
217 | nargv = alloca((argc + 3) * sizeof(char *)); | |||
|
218 | c = strrchr(hg_shell, '/'); | |||
|
219 | ||||
|
220 | /* tell "real" shell it is login shell, if needed. */ | |||
|
221 | ||||
|
222 | if (argv[0][0] == '-' && c) { | |||
|
223 | nargv[0] = strdup(c); | |||
|
224 | if (nargv[0] == NULL) { | |||
|
225 | perror("malloc"); | |||
|
226 | exit(EX_OSERR); | |||
|
227 | } | |||
|
228 | nargv[0][0] = '-'; | |||
|
229 | } else { | |||
|
230 | nargv[0] = hg_shell; | |||
|
231 | } | |||
|
232 | ||||
|
233 | for (i = 1; i < argc; i++) { | |||
|
234 | nargv[i] = argv[i]; | |||
|
235 | } | |||
|
236 | nargv[i] = NULL; | |||
|
237 | ||||
|
238 | if (debug) { | |||
|
239 | print_cmdline(i, nargv); | |||
|
240 | } | |||
|
241 | ||||
|
242 | execv(hg_shell, nargv); | |||
|
243 | perror(hg_shell); | |||
|
244 | exit(EX_OSFILE); | |||
|
245 | } | |||
|
246 | ||||
|
247 | enum cmdline { | |||
|
248 | hg_init, | |||
|
249 | hg_serve, | |||
|
250 | }; | |||
|
251 | ||||
|
252 | /* | |||
|
253 | * attempt to verify that a directory is really a hg repo, by testing | |||
|
254 | * for the existence of a subdirectory. | |||
|
255 | */ | |||
|
256 | static int validate_repo(const char *repo_root, const char *subdir) | |||
|
257 | { | |||
|
258 | char *abs_path; | |||
|
259 | struct stat st; | |||
|
260 | int ret; | |||
|
261 | ||||
|
262 | if (asprintf(&abs_path, "%s.hg/%s", repo_root, subdir) == -1) { | |||
|
263 | ret = -1; | |||
|
264 | goto bail; | |||
|
265 | } | |||
|
266 | ||||
|
267 | /* verify that we really are looking at valid repo. */ | |||
|
268 | ||||
|
269 | if (stat(abs_path, &st) == -1) { | |||
|
270 | ret = 0; | |||
|
271 | } else { | |||
|
272 | ret = 1; | |||
|
273 | } | |||
|
274 | ||||
|
275 | bail: | |||
|
276 | return ret; | |||
|
277 | } | |||
|
278 | ||||
|
279 | /* | |||
|
280 | * paranoid wrapper, runs hg executable in server mode. | |||
|
281 | */ | |||
|
282 | static void serve_data(int argc, char **argv) | |||
|
283 | { | |||
|
284 | char *hg_root = HG_ROOT; | |||
|
285 | char *repo, *repo_root; | |||
|
286 | enum cmdline cmd; | |||
|
287 | char *nargv[6]; | |||
|
288 | size_t repolen; | |||
|
289 | int i; | |||
|
290 | ||||
|
291 | /* | |||
|
292 | * check argv for looking okay. we should be invoked with argv | |||
|
293 | * resembling like this: | |||
|
294 | * | |||
|
295 | * hgsh | |||
|
296 | * -c | |||
|
297 | * hg -R some/path serve --stdio | |||
|
298 | * | |||
|
299 | * the "-c" is added by sshd, because it thinks we are login shell. | |||
|
300 | */ | |||
|
301 | ||||
|
302 | if (argc != 3) { | |||
|
303 | goto badargs; | |||
|
304 | } | |||
|
305 | ||||
|
306 | if (strcmp(argv[1], "-c") != 0) { | |||
|
307 | goto badargs; | |||
|
308 | } | |||
|
309 | ||||
|
310 | if (sscanf(argv[2], "hg init %as", &repo) == 1) { | |||
|
311 | cmd = hg_init; | |||
|
312 | } else if (sscanf(argv[2], "hg -R %as serve --stdio", &repo) == 1) { | |||
|
313 | cmd = hg_serve; | |||
|
314 | } else { | |||
|
315 | goto badargs; | |||
|
316 | } | |||
|
317 | ||||
|
318 | repolen = repo ? strlen(repo) : 0; | |||
|
319 | ||||
|
320 | if (repolen == 0) { | |||
|
321 | goto badargs; | |||
|
322 | } | |||
|
323 | ||||
|
324 | if (hg_root) { | |||
|
325 | if (asprintf(&repo_root, "%s/%s/", hg_root, repo) == -1) { | |||
|
326 | goto badargs; | |||
|
327 | } | |||
|
328 | ||||
|
329 | /* | |||
|
330 | * attempt to stop break out from inside the | |||
|
331 | * repository tree. could do something more clever | |||
|
332 | * here, because e.g. we could traverse a symlink that | |||
|
333 | * looks safe, but really breaks us out of tree. | |||
|
334 | */ | |||
|
335 | ||||
|
336 | if (strstr(repo_root, "/../") != NULL) { | |||
|
337 | goto badargs; | |||
|
338 | } | |||
|
339 | ||||
|
340 | /* only hg init expects no repo. */ | |||
|
341 | ||||
|
342 | if (cmd != hg_init) { | |||
|
343 | int valid; | |||
|
344 | ||||
|
345 | valid = validate_repo(repo_root, "data"); | |||
|
346 | ||||
|
347 | if (valid == -1) { | |||
|
348 | goto badargs; | |||
|
349 | } | |||
|
350 | ||||
|
351 | if (valid == 0) { | |||
|
352 | valid = validate_repo(repo_root, "store"); | |||
|
353 | ||||
|
354 | if (valid == -1) { | |||
|
355 | goto badargs; | |||
|
356 | } | |||
|
357 | } | |||
|
358 | ||||
|
359 | if (valid == 0) { | |||
|
360 | perror(repo); | |||
|
361 | exit(EX_DATAERR); | |||
|
362 | } | |||
|
363 | } | |||
|
364 | ||||
|
365 | if (chdir(hg_root) == -1) { | |||
|
366 | perror(hg_root); | |||
|
367 | exit(EX_SOFTWARE); | |||
|
368 | } | |||
|
369 | } | |||
|
370 | ||||
|
371 | i = 0; | |||
|
372 | ||||
|
373 | switch (cmd) { | |||
|
374 | case hg_serve: | |||
|
375 | nargv[i++] = HG; | |||
|
376 | nargv[i++] = "-R"; | |||
|
377 | nargv[i++] = repo; | |||
|
378 | nargv[i++] = "serve"; | |||
|
379 | nargv[i++] = "--stdio"; | |||
|
380 | break; | |||
|
381 | case hg_init: | |||
|
382 | nargv[i++] = HG; | |||
|
383 | nargv[i++] = "init"; | |||
|
384 | nargv[i++] = repo; | |||
|
385 | break; | |||
|
386 | } | |||
|
387 | ||||
|
388 | nargv[i] = NULL; | |||
|
389 | ||||
|
390 | if (debug) { | |||
|
391 | print_cmdline(i, nargv); | |||
|
392 | } | |||
|
393 | ||||
|
394 | execv(HG, nargv); | |||
|
395 | perror(HG); | |||
|
396 | exit(EX_UNAVAILABLE); | |||
|
397 | ||||
|
398 | badargs: | |||
|
399 | /* print useless error message. */ | |||
|
400 | ||||
|
401 | usage("invalid arguments", EX_DATAERR); | |||
|
402 | } | |||
|
403 | ||||
|
404 | int main(int argc, char **argv) | |||
|
405 | { | |||
|
406 | char host[1024]; | |||
|
407 | char *c; | |||
|
408 | ||||
|
409 | if (gethostname(host, sizeof(host)) == -1) { | |||
|
410 | perror("gethostname"); | |||
|
411 | exit(EX_OSERR); | |||
|
412 | } | |||
|
413 | ||||
|
414 | if ((c = strchr(host, '.')) != NULL) { | |||
|
415 | *c = '\0'; | |||
|
416 | } | |||
|
417 | ||||
|
418 | if (getenv("SSH_CLIENT")) { | |||
|
419 | char *hg_gateway = HG_GATEWAY; | |||
|
420 | char *hg_host = HG_HOST; | |||
|
421 | ||||
|
422 | if (hg_gateway && strcmp(host, hg_gateway) == 0) { | |||
|
423 | forward_through_gateway(argc, argv); | |||
|
424 | } | |||
|
425 | ||||
|
426 | if (hg_host && strcmp(host, hg_host) != 0) { | |||
|
427 | usage("invoked on unexpected host", EX_USAGE); | |||
|
428 | } | |||
|
429 | ||||
|
430 | serve_data(argc, argv); | |||
|
431 | } else if (HG_SHELL) { | |||
|
432 | run_shell(argc, argv); | |||
|
433 | } else { | |||
|
434 | usage("invalid arguments", EX_DATAERR); | |||
|
435 | } | |||
|
436 | ||||
|
437 | return 0; | |||
|
438 | } |
@@ -0,0 +1,19 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | # | |||
|
3 | # An example FastCGI script for use with flup, edit as necessary | |||
|
4 | ||||
|
5 | # Path to repo or hgweb config to serve (see 'hg help hgweb') | |||
|
6 | config = "/path/to/repo/or/config" | |||
|
7 | ||||
|
8 | # Uncomment and adjust if Mercurial is not installed system-wide | |||
|
9 | # (consult "installed modules" path from 'hg debuginstall'): | |||
|
10 | #import sys; sys.path.insert(0, "/path/to/python/lib") | |||
|
11 | ||||
|
12 | # Uncomment to send python tracebacks to the browser if an error occurs: | |||
|
13 | #import cgitb; cgitb.enable() | |||
|
14 | ||||
|
15 | from mercurial import demandimport; demandimport.enable() | |||
|
16 | from mercurial.hgweb import hgweb | |||
|
17 | from flup.server.fcgi import WSGIServer | |||
|
18 | application = hgweb(config) | |||
|
19 | WSGIServer(application).run() |
@@ -0,0 +1,18 b'' | |||||
|
1 | # An example WSGI for use with mod_wsgi, edit as necessary | |||
|
2 | # See https://mercurial-scm.org/wiki/modwsgi for more information | |||
|
3 | ||||
|
4 | # Path to repo or hgweb config to serve (see 'hg help hgweb') | |||
|
5 | config = "/path/to/repo/or/config" | |||
|
6 | ||||
|
7 | # Uncomment and adjust if Mercurial is not installed system-wide | |||
|
8 | # (consult "installed modules" path from 'hg debuginstall'): | |||
|
9 | #import sys; sys.path.insert(0, "/path/to/python/lib") | |||
|
10 | ||||
|
11 | # Uncomment to send python tracebacks to the browser if an error occurs: | |||
|
12 | #import cgitb; cgitb.enable() | |||
|
13 | ||||
|
14 | # enable demandloading to reduce startup time | |||
|
15 | from mercurial import demandimport; demandimport.enable() | |||
|
16 | ||||
|
17 | from mercurial.hgweb import hgweb | |||
|
18 | application = hgweb(config) |
This diff has been collapsed as it changes many lines, (781 lines changed) Show them Hide them | |||||
@@ -0,0 +1,781 b'' | |||||
|
1 | #!/usr/bin/env python | |||
|
2 | ||||
|
3 | from __future__ import absolute_import, print_function | |||
|
4 | ||||
|
5 | import ast | |||
|
6 | import collections | |||
|
7 | import os | |||
|
8 | import re | |||
|
9 | import sys | |||
|
10 | ||||
|
11 | # Import a minimal set of stdlib modules needed for list_stdlib_modules() | |||
|
12 | # to work when run from a virtualenv. The modules were chosen empirically | |||
|
13 | # so that the return value matches the return value without virtualenv. | |||
|
14 | if True: # disable lexical sorting checks | |||
|
15 | try: | |||
|
16 | import BaseHTTPServer as basehttpserver | |||
|
17 | except ImportError: | |||
|
18 | basehttpserver = None | |||
|
19 | import zlib | |||
|
20 | ||||
|
21 | # Whitelist of modules that symbols can be directly imported from. | |||
|
22 | allowsymbolimports = ( | |||
|
23 | '__future__', | |||
|
24 | 'bzrlib', | |||
|
25 | 'hgclient', | |||
|
26 | 'mercurial', | |||
|
27 | 'mercurial.hgweb.common', | |||
|
28 | 'mercurial.hgweb.request', | |||
|
29 | 'mercurial.i18n', | |||
|
30 | 'mercurial.node', | |||
|
31 | # for cffi modules to re-export pure functions | |||
|
32 | 'mercurial.pure.base85', | |||
|
33 | 'mercurial.pure.bdiff', | |||
|
34 | 'mercurial.pure.mpatch', | |||
|
35 | 'mercurial.pure.osutil', | |||
|
36 | 'mercurial.pure.parsers', | |||
|
37 | # third-party imports should be directly imported | |||
|
38 | 'mercurial.thirdparty', | |||
|
39 | 'mercurial.thirdparty.cbor', | |||
|
40 | 'mercurial.thirdparty.cbor.cbor2', | |||
|
41 | 'mercurial.thirdparty.zope', | |||
|
42 | 'mercurial.thirdparty.zope.interface', | |||
|
43 | ) | |||
|
44 | ||||
|
45 | # Whitelist of symbols that can be directly imported. | |||
|
46 | directsymbols = ( | |||
|
47 | 'demandimport', | |||
|
48 | ) | |||
|
49 | ||||
|
50 | # Modules that must be aliased because they are commonly confused with | |||
|
51 | # common variables and can create aliasing and readability issues. | |||
|
52 | requirealias = { | |||
|
53 | 'ui': 'uimod', | |||
|
54 | } | |||
|
55 | ||||
|
56 | def usingabsolute(root): | |||
|
57 | """Whether absolute imports are being used.""" | |||
|
58 | if sys.version_info[0] >= 3: | |||
|
59 | return True | |||
|
60 | ||||
|
61 | for node in ast.walk(root): | |||
|
62 | if isinstance(node, ast.ImportFrom): | |||
|
63 | if node.module == '__future__': | |||
|
64 | for n in node.names: | |||
|
65 | if n.name == 'absolute_import': | |||
|
66 | return True | |||
|
67 | ||||
|
68 | return False | |||
|
69 | ||||
|
70 | def walklocal(root): | |||
|
71 | """Recursively yield all descendant nodes but not in a different scope""" | |||
|
72 | todo = collections.deque(ast.iter_child_nodes(root)) | |||
|
73 | yield root, False | |||
|
74 | while todo: | |||
|
75 | node = todo.popleft() | |||
|
76 | newscope = isinstance(node, ast.FunctionDef) | |||
|
77 | if not newscope: | |||
|
78 | todo.extend(ast.iter_child_nodes(node)) | |||
|
79 | yield node, newscope | |||
|
80 | ||||
|
81 | def dotted_name_of_path(path): | |||
|
82 | """Given a relative path to a source file, return its dotted module name. | |||
|
83 | ||||
|
84 | >>> dotted_name_of_path('mercurial/error.py') | |||
|
85 | 'mercurial.error' | |||
|
86 | >>> dotted_name_of_path('zlibmodule.so') | |||
|
87 | 'zlib' | |||
|
88 | """ | |||
|
89 | parts = path.replace(os.sep, '/').split('/') | |||
|
90 | parts[-1] = parts[-1].split('.', 1)[0] # remove .py and .so and .ARCH.so | |||
|
91 | if parts[-1].endswith('module'): | |||
|
92 | parts[-1] = parts[-1][:-6] | |||
|
93 | return '.'.join(parts) | |||
|
94 | ||||
|
95 | def fromlocalfunc(modulename, localmods): | |||
|
96 | """Get a function to examine which locally defined module the | |||
|
97 | target source imports via a specified name. | |||
|
98 | ||||
|
99 | `modulename` is an `dotted_name_of_path()`-ed source file path, | |||
|
100 | which may have `.__init__` at the end of it, of the target source. | |||
|
101 | ||||
|
102 | `localmods` is a set of absolute `dotted_name_of_path()`-ed source file | |||
|
103 | paths of locally defined (= Mercurial specific) modules. | |||
|
104 | ||||
|
105 | This function assumes that module names not existing in | |||
|
106 | `localmods` are from the Python standard library. | |||
|
107 | ||||
|
108 | This function returns the function, which takes `name` argument, | |||
|
109 | and returns `(absname, dottedpath, hassubmod)` tuple if `name` | |||
|
110 | matches against locally defined module. Otherwise, it returns | |||
|
111 | False. | |||
|
112 | ||||
|
113 | It is assumed that `name` doesn't have `.__init__`. | |||
|
114 | ||||
|
115 | `absname` is an absolute module name of specified `name` | |||
|
116 | (e.g. "hgext.convert"). This can be used to compose prefix for sub | |||
|
117 | modules or so. | |||
|
118 | ||||
|
119 | `dottedpath` is a `dotted_name_of_path()`-ed source file path | |||
|
120 | (e.g. "hgext.convert.__init__") of `name`. This is used to look | |||
|
121 | module up in `localmods` again. | |||
|
122 | ||||
|
123 | `hassubmod` is whether it may have sub modules under it (for | |||
|
124 | convenient, even though this is also equivalent to "absname != | |||
|
125 | dottednpath") | |||
|
126 | ||||
|
127 | >>> localmods = {'foo.__init__', 'foo.foo1', | |||
|
128 | ... 'foo.bar.__init__', 'foo.bar.bar1', | |||
|
129 | ... 'baz.__init__', 'baz.baz1'} | |||
|
130 | >>> fromlocal = fromlocalfunc('foo.xxx', localmods) | |||
|
131 | >>> # relative | |||
|
132 | >>> fromlocal('foo1') | |||
|
133 | ('foo.foo1', 'foo.foo1', False) | |||
|
134 | >>> fromlocal('bar') | |||
|
135 | ('foo.bar', 'foo.bar.__init__', True) | |||
|
136 | >>> fromlocal('bar.bar1') | |||
|
137 | ('foo.bar.bar1', 'foo.bar.bar1', False) | |||
|
138 | >>> # absolute | |||
|
139 | >>> fromlocal('baz') | |||
|
140 | ('baz', 'baz.__init__', True) | |||
|
141 | >>> fromlocal('baz.baz1') | |||
|
142 | ('baz.baz1', 'baz.baz1', False) | |||
|
143 | >>> # unknown = maybe standard library | |||
|
144 | >>> fromlocal('os') | |||
|
145 | False | |||
|
146 | >>> fromlocal(None, 1) | |||
|
147 | ('foo', 'foo.__init__', True) | |||
|
148 | >>> fromlocal('foo1', 1) | |||
|
149 | ('foo.foo1', 'foo.foo1', False) | |||
|
150 | >>> fromlocal2 = fromlocalfunc('foo.xxx.yyy', localmods) | |||
|
151 | >>> fromlocal2(None, 2) | |||
|
152 | ('foo', 'foo.__init__', True) | |||
|
153 | >>> fromlocal2('bar2', 1) | |||
|
154 | False | |||
|
155 | >>> fromlocal2('bar', 2) | |||
|
156 | ('foo.bar', 'foo.bar.__init__', True) | |||
|
157 | """ | |||
|
158 | if not isinstance(modulename, str): | |||
|
159 | modulename = modulename.decode('ascii') | |||
|
160 | prefix = '.'.join(modulename.split('.')[:-1]) | |||
|
161 | if prefix: | |||
|
162 | prefix += '.' | |||
|
163 | def fromlocal(name, level=0): | |||
|
164 | # name is false value when relative imports are used. | |||
|
165 | if not name: | |||
|
166 | # If relative imports are used, level must not be absolute. | |||
|
167 | assert level > 0 | |||
|
168 | candidates = ['.'.join(modulename.split('.')[:-level])] | |||
|
169 | else: | |||
|
170 | if not level: | |||
|
171 | # Check relative name first. | |||
|
172 | candidates = [prefix + name, name] | |||
|
173 | else: | |||
|
174 | candidates = ['.'.join(modulename.split('.')[:-level]) + | |||
|
175 | '.' + name] | |||
|
176 | ||||
|
177 | for n in candidates: | |||
|
178 | if n in localmods: | |||
|
179 | return (n, n, False) | |||
|
180 | dottedpath = n + '.__init__' | |||
|
181 | if dottedpath in localmods: | |||
|
182 | return (n, dottedpath, True) | |||
|
183 | return False | |||
|
184 | return fromlocal | |||
|
185 | ||||
|
186 | def populateextmods(localmods): | |||
|
187 | """Populate C extension modules based on pure modules""" | |||
|
188 | newlocalmods = set(localmods) | |||
|
189 | for n in localmods: | |||
|
190 | if n.startswith('mercurial.pure.'): | |||
|
191 | m = n[len('mercurial.pure.'):] | |||
|
192 | newlocalmods.add('mercurial.cext.' + m) | |||
|
193 | newlocalmods.add('mercurial.cffi._' + m) | |||
|
194 | return newlocalmods | |||
|
195 | ||||
|
196 | def list_stdlib_modules(): | |||
|
197 | """List the modules present in the stdlib. | |||
|
198 | ||||
|
199 | >>> py3 = sys.version_info[0] >= 3 | |||
|
200 | >>> mods = set(list_stdlib_modules()) | |||
|
201 | >>> 'BaseHTTPServer' in mods or py3 | |||
|
202 | True | |||
|
203 | ||||
|
204 | os.path isn't really a module, so it's missing: | |||
|
205 | ||||
|
206 | >>> 'os.path' in mods | |||
|
207 | False | |||
|
208 | ||||
|
209 | sys requires special treatment, because it's baked into the | |||
|
210 | interpreter, but it should still appear: | |||
|
211 | ||||
|
212 | >>> 'sys' in mods | |||
|
213 | True | |||
|
214 | ||||
|
215 | >>> 'collections' in mods | |||
|
216 | True | |||
|
217 | ||||
|
218 | >>> 'cStringIO' in mods or py3 | |||
|
219 | True | |||
|
220 | ||||
|
221 | >>> 'cffi' in mods | |||
|
222 | True | |||
|
223 | """ | |||
|
224 | for m in sys.builtin_module_names: | |||
|
225 | yield m | |||
|
226 | # These modules only exist on windows, but we should always | |||
|
227 | # consider them stdlib. | |||
|
228 | for m in ['msvcrt', '_winreg']: | |||
|
229 | yield m | |||
|
230 | yield '__builtin__' | |||
|
231 | yield 'builtins' # python3 only | |||
|
232 | yield 'importlib.abc' # python3 only | |||
|
233 | yield 'importlib.machinery' # python3 only | |||
|
234 | yield 'importlib.util' # python3 only | |||
|
235 | for m in 'fcntl', 'grp', 'pwd', 'termios': # Unix only | |||
|
236 | yield m | |||
|
237 | for m in 'cPickle', 'datetime': # in Python (not C) on PyPy | |||
|
238 | yield m | |||
|
239 | for m in ['cffi']: | |||
|
240 | yield m | |||
|
241 | stdlib_prefixes = {sys.prefix, sys.exec_prefix} | |||
|
242 | # We need to supplement the list of prefixes for the search to work | |||
|
243 | # when run from within a virtualenv. | |||
|
244 | for mod in (basehttpserver, zlib): | |||
|
245 | if mod is None: | |||
|
246 | continue | |||
|
247 | try: | |||
|
248 | # Not all module objects have a __file__ attribute. | |||
|
249 | filename = mod.__file__ | |||
|
250 | except AttributeError: | |||
|
251 | continue | |||
|
252 | dirname = os.path.dirname(filename) | |||
|
253 | for prefix in stdlib_prefixes: | |||
|
254 | if dirname.startswith(prefix): | |||
|
255 | # Then this directory is redundant. | |||
|
256 | break | |||
|
257 | else: | |||
|
258 | stdlib_prefixes.add(dirname) | |||
|
259 | for libpath in sys.path: | |||
|
260 | # We want to walk everything in sys.path that starts with | |||
|
261 | # something in stdlib_prefixes. | |||
|
262 | if not any(libpath.startswith(p) for p in stdlib_prefixes): | |||
|
263 | continue | |||
|
264 | for top, dirs, files in os.walk(libpath): | |||
|
265 | for i, d in reversed(list(enumerate(dirs))): | |||
|
266 | if (not os.path.exists(os.path.join(top, d, '__init__.py')) | |||
|
267 | or top == libpath and d in ('hgdemandimport', 'hgext', | |||
|
268 | 'mercurial')): | |||
|
269 | del dirs[i] | |||
|
270 | for name in files: | |||
|
271 | if not name.endswith(('.py', '.so', '.pyc', '.pyo', '.pyd')): | |||
|
272 | continue | |||
|
273 | if name.startswith('__init__.py'): | |||
|
274 | full_path = top | |||
|
275 | else: | |||
|
276 | full_path = os.path.join(top, name) | |||
|
277 | rel_path = full_path[len(libpath) + 1:] | |||
|
278 | mod = dotted_name_of_path(rel_path) | |||
|
279 | yield mod | |||
|
280 | ||||
|
281 | stdlib_modules = set(list_stdlib_modules()) | |||
|
282 | ||||
|
283 | def imported_modules(source, modulename, f, localmods, ignore_nested=False): | |||
|
284 | """Given the source of a file as a string, yield the names | |||
|
285 | imported by that file. | |||
|
286 | ||||
|
287 | Args: | |||
|
288 | source: The python source to examine as a string. | |||
|
289 | modulename: of specified python source (may have `__init__`) | |||
|
290 | localmods: set of locally defined module names (may have `__init__`) | |||
|
291 | ignore_nested: If true, import statements that do not start in | |||
|
292 | column zero will be ignored. | |||
|
293 | ||||
|
294 | Returns: | |||
|
295 | A list of absolute module names imported by the given source. | |||
|
296 | ||||
|
297 | >>> f = 'foo/xxx.py' | |||
|
298 | >>> modulename = 'foo.xxx' | |||
|
299 | >>> localmods = {'foo.__init__': True, | |||
|
300 | ... 'foo.foo1': True, 'foo.foo2': True, | |||
|
301 | ... 'foo.bar.__init__': True, 'foo.bar.bar1': True, | |||
|
302 | ... 'baz.__init__': True, 'baz.baz1': True } | |||
|
303 | >>> # standard library (= not locally defined ones) | |||
|
304 | >>> sorted(imported_modules( | |||
|
305 | ... 'from stdlib1 import foo, bar; import stdlib2', | |||
|
306 | ... modulename, f, localmods)) | |||
|
307 | [] | |||
|
308 | >>> # relative importing | |||
|
309 | >>> sorted(imported_modules( | |||
|
310 | ... 'import foo1; from bar import bar1', | |||
|
311 | ... modulename, f, localmods)) | |||
|
312 | ['foo.bar.bar1', 'foo.foo1'] | |||
|
313 | >>> sorted(imported_modules( | |||
|
314 | ... 'from bar.bar1 import name1, name2, name3', | |||
|
315 | ... modulename, f, localmods)) | |||
|
316 | ['foo.bar.bar1'] | |||
|
317 | >>> # absolute importing | |||
|
318 | >>> sorted(imported_modules( | |||
|
319 | ... 'from baz import baz1, name1', | |||
|
320 | ... modulename, f, localmods)) | |||
|
321 | ['baz.__init__', 'baz.baz1'] | |||
|
322 | >>> # mixed importing, even though it shouldn't be recommended | |||
|
323 | >>> sorted(imported_modules( | |||
|
324 | ... 'import stdlib, foo1, baz', | |||
|
325 | ... modulename, f, localmods)) | |||
|
326 | ['baz.__init__', 'foo.foo1'] | |||
|
327 | >>> # ignore_nested | |||
|
328 | >>> sorted(imported_modules( | |||
|
329 | ... '''import foo | |||
|
330 | ... def wat(): | |||
|
331 | ... import bar | |||
|
332 | ... ''', modulename, f, localmods)) | |||
|
333 | ['foo.__init__', 'foo.bar.__init__'] | |||
|
334 | >>> sorted(imported_modules( | |||
|
335 | ... '''import foo | |||
|
336 | ... def wat(): | |||
|
337 | ... import bar | |||
|
338 | ... ''', modulename, f, localmods, ignore_nested=True)) | |||
|
339 | ['foo.__init__'] | |||
|
340 | """ | |||
|
341 | fromlocal = fromlocalfunc(modulename, localmods) | |||
|
342 | for node in ast.walk(ast.parse(source, f)): | |||
|
343 | if ignore_nested and getattr(node, 'col_offset', 0) > 0: | |||
|
344 | continue | |||
|
345 | if isinstance(node, ast.Import): | |||
|
346 | for n in node.names: | |||
|
347 | found = fromlocal(n.name) | |||
|
348 | if not found: | |||
|
349 | # this should import standard library | |||
|
350 | continue | |||
|
351 | yield found[1] | |||
|
352 | elif isinstance(node, ast.ImportFrom): | |||
|
353 | found = fromlocal(node.module, node.level) | |||
|
354 | if not found: | |||
|
355 | # this should import standard library | |||
|
356 | continue | |||
|
357 | ||||
|
358 | absname, dottedpath, hassubmod = found | |||
|
359 | if not hassubmod: | |||
|
360 | # "dottedpath" is not a package; must be imported | |||
|
361 | yield dottedpath | |||
|
362 | # examination of "node.names" should be redundant | |||
|
363 | # e.g.: from mercurial.node import nullid, nullrev | |||
|
364 | continue | |||
|
365 | ||||
|
366 | modnotfound = False | |||
|
367 | prefix = absname + '.' | |||
|
368 | for n in node.names: | |||
|
369 | found = fromlocal(prefix + n.name) | |||
|
370 | if not found: | |||
|
371 | # this should be a function or a property of "node.module" | |||
|
372 | modnotfound = True | |||
|
373 | continue | |||
|
374 | yield found[1] | |||
|
375 | if modnotfound: | |||
|
376 | # "dottedpath" is a package, but imported because of non-module | |||
|
377 | # lookup | |||
|
378 | yield dottedpath | |||
|
379 | ||||
|
380 | def verify_import_convention(module, source, localmods): | |||
|
381 | """Verify imports match our established coding convention. | |||
|
382 | ||||
|
383 | We have 2 conventions: legacy and modern. The modern convention is in | |||
|
384 | effect when using absolute imports. | |||
|
385 | ||||
|
386 | The legacy convention only looks for mixed imports. The modern convention | |||
|
387 | is much more thorough. | |||
|
388 | """ | |||
|
389 | root = ast.parse(source) | |||
|
390 | absolute = usingabsolute(root) | |||
|
391 | ||||
|
392 | if absolute: | |||
|
393 | return verify_modern_convention(module, root, localmods) | |||
|
394 | else: | |||
|
395 | return verify_stdlib_on_own_line(root) | |||
|
396 | ||||
|
397 | def verify_modern_convention(module, root, localmods, root_col_offset=0): | |||
|
398 | """Verify a file conforms to the modern import convention rules. | |||
|
399 | ||||
|
400 | The rules of the modern convention are: | |||
|
401 | ||||
|
402 | * Ordering is stdlib followed by local imports. Each group is lexically | |||
|
403 | sorted. | |||
|
404 | * Importing multiple modules via "import X, Y" is not allowed: use | |||
|
405 | separate import statements. | |||
|
406 | * Importing multiple modules via "from X import ..." is allowed if using | |||
|
407 | parenthesis and one entry per line. | |||
|
408 | * Only 1 relative import statement per import level ("from .", "from ..") | |||
|
409 | is allowed. | |||
|
410 | * Relative imports from higher levels must occur before lower levels. e.g. | |||
|
411 | "from .." must be before "from .". | |||
|
412 | * Imports from peer packages should use relative import (e.g. do not | |||
|
413 | "import mercurial.foo" from a "mercurial.*" module). | |||
|
414 | * Symbols can only be imported from specific modules (see | |||
|
415 | `allowsymbolimports`). For other modules, first import the module then | |||
|
416 | assign the symbol to a module-level variable. In addition, these imports | |||
|
417 | must be performed before other local imports. This rule only | |||
|
418 | applies to import statements outside of any blocks. | |||
|
419 | * Relative imports from the standard library are not allowed, unless that | |||
|
420 | library is also a local module. | |||
|
421 | * Certain modules must be aliased to alternate names to avoid aliasing | |||
|
422 | and readability problems. See `requirealias`. | |||
|
423 | """ | |||
|
424 | if not isinstance(module, str): | |||
|
425 | module = module.decode('ascii') | |||
|
426 | topmodule = module.split('.')[0] | |||
|
427 | fromlocal = fromlocalfunc(module, localmods) | |||
|
428 | ||||
|
429 | # Whether a local/non-stdlib import has been performed. | |||
|
430 | seenlocal = None | |||
|
431 | # Whether a local/non-stdlib, non-symbol import has been seen. | |||
|
432 | seennonsymbollocal = False | |||
|
433 | # The last name to be imported (for sorting). | |||
|
434 | lastname = None | |||
|
435 | laststdlib = None | |||
|
436 | # Relative import levels encountered so far. | |||
|
437 | seenlevels = set() | |||
|
438 | ||||
|
439 | for node, newscope in walklocal(root): | |||
|
440 | def msg(fmt, *args): | |||
|
441 | return (fmt % args, node.lineno) | |||
|
442 | if newscope: | |||
|
443 | # Check for local imports in function | |||
|
444 | for r in verify_modern_convention(module, node, localmods, | |||
|
445 | node.col_offset + 4): | |||
|
446 | yield r | |||
|
447 | elif isinstance(node, ast.Import): | |||
|
448 | # Disallow "import foo, bar" and require separate imports | |||
|
449 | # for each module. | |||
|
450 | if len(node.names) > 1: | |||
|
451 | yield msg('multiple imported names: %s', | |||
|
452 | ', '.join(n.name for n in node.names)) | |||
|
453 | ||||
|
454 | name = node.names[0].name | |||
|
455 | asname = node.names[0].asname | |||
|
456 | ||||
|
457 | stdlib = name in stdlib_modules | |||
|
458 | ||||
|
459 | # Ignore sorting rules on imports inside blocks. | |||
|
460 | if node.col_offset == root_col_offset: | |||
|
461 | if lastname and name < lastname and laststdlib == stdlib: | |||
|
462 | yield msg('imports not lexically sorted: %s < %s', | |||
|
463 | name, lastname) | |||
|
464 | ||||
|
465 | lastname = name | |||
|
466 | laststdlib = stdlib | |||
|
467 | ||||
|
468 | # stdlib imports should be before local imports. | |||
|
469 | if stdlib and seenlocal and node.col_offset == root_col_offset: | |||
|
470 | yield msg('stdlib import "%s" follows local import: %s', | |||
|
471 | name, seenlocal) | |||
|
472 | ||||
|
473 | if not stdlib: | |||
|
474 | seenlocal = name | |||
|
475 | ||||
|
476 | # Import of sibling modules should use relative imports. | |||
|
477 | topname = name.split('.')[0] | |||
|
478 | if topname == topmodule: | |||
|
479 | yield msg('import should be relative: %s', name) | |||
|
480 | ||||
|
481 | if name in requirealias and asname != requirealias[name]: | |||
|
482 | yield msg('%s module must be "as" aliased to %s', | |||
|
483 | name, requirealias[name]) | |||
|
484 | ||||
|
485 | elif isinstance(node, ast.ImportFrom): | |||
|
486 | # Resolve the full imported module name. | |||
|
487 | if node.level > 0: | |||
|
488 | fullname = '.'.join(module.split('.')[:-node.level]) | |||
|
489 | if node.module: | |||
|
490 | fullname += '.%s' % node.module | |||
|
491 | else: | |||
|
492 | assert node.module | |||
|
493 | fullname = node.module | |||
|
494 | ||||
|
495 | topname = fullname.split('.')[0] | |||
|
496 | if topname == topmodule: | |||
|
497 | yield msg('import should be relative: %s', fullname) | |||
|
498 | ||||
|
499 | # __future__ is special since it needs to come first and use | |||
|
500 | # symbol import. | |||
|
501 | if fullname != '__future__': | |||
|
502 | if not fullname or ( | |||
|
503 | fullname in stdlib_modules | |||
|
504 | and fullname not in localmods | |||
|
505 | and fullname + '.__init__' not in localmods): | |||
|
506 | yield msg('relative import of stdlib module') | |||
|
507 | else: | |||
|
508 | seenlocal = fullname | |||
|
509 | ||||
|
510 | # Direct symbol import is only allowed from certain modules and | |||
|
511 | # must occur before non-symbol imports. | |||
|
512 | found = fromlocal(node.module, node.level) | |||
|
513 | if found and found[2]: # node.module is a package | |||
|
514 | prefix = found[0] + '.' | |||
|
515 | symbols = (n.name for n in node.names | |||
|
516 | if not fromlocal(prefix + n.name)) | |||
|
517 | else: | |||
|
518 | symbols = (n.name for n in node.names) | |||
|
519 | symbols = [sym for sym in symbols if sym not in directsymbols] | |||
|
520 | if node.module and node.col_offset == root_col_offset: | |||
|
521 | if symbols and fullname not in allowsymbolimports: | |||
|
522 | yield msg('direct symbol import %s from %s', | |||
|
523 | ', '.join(symbols), fullname) | |||
|
524 | ||||
|
525 | if symbols and seennonsymbollocal: | |||
|
526 | yield msg('symbol import follows non-symbol import: %s', | |||
|
527 | fullname) | |||
|
528 | if not symbols and fullname not in stdlib_modules: | |||
|
529 | seennonsymbollocal = True | |||
|
530 | ||||
|
531 | if not node.module: | |||
|
532 | assert node.level | |||
|
533 | ||||
|
534 | # Only allow 1 group per level. | |||
|
535 | if (node.level in seenlevels | |||
|
536 | and node.col_offset == root_col_offset): | |||
|
537 | yield msg('multiple "from %s import" statements', | |||
|
538 | '.' * node.level) | |||
|
539 | ||||
|
540 | # Higher-level groups come before lower-level groups. | |||
|
541 | if any(node.level > l for l in seenlevels): | |||
|
542 | yield msg('higher-level import should come first: %s', | |||
|
543 | fullname) | |||
|
544 | ||||
|
545 | seenlevels.add(node.level) | |||
|
546 | ||||
|
547 | # Entries in "from .X import ( ... )" lists must be lexically | |||
|
548 | # sorted. | |||
|
549 | lastentryname = None | |||
|
550 | ||||
|
551 | for n in node.names: | |||
|
552 | if lastentryname and n.name < lastentryname: | |||
|
553 | yield msg('imports from %s not lexically sorted: %s < %s', | |||
|
554 | fullname, n.name, lastentryname) | |||
|
555 | ||||
|
556 | lastentryname = n.name | |||
|
557 | ||||
|
558 | if n.name in requirealias and n.asname != requirealias[n.name]: | |||
|
559 | yield msg('%s from %s must be "as" aliased to %s', | |||
|
560 | n.name, fullname, requirealias[n.name]) | |||
|
561 | ||||
|
562 | def verify_stdlib_on_own_line(root): | |||
|
563 | """Given some python source, verify that stdlib imports are done | |||
|
564 | in separate statements from relative local module imports. | |||
|
565 | ||||
|
566 | >>> list(verify_stdlib_on_own_line(ast.parse('import sys, foo'))) | |||
|
567 | [('mixed imports\\n stdlib: sys\\n relative: foo', 1)] | |||
|
568 | >>> list(verify_stdlib_on_own_line(ast.parse('import sys, os'))) | |||
|
569 | [] | |||
|
570 | >>> list(verify_stdlib_on_own_line(ast.parse('import foo, bar'))) | |||
|
571 | [] | |||
|
572 | """ | |||
|
573 | for node in ast.walk(root): | |||
|
574 | if isinstance(node, ast.Import): | |||
|
575 | from_stdlib = {False: [], True: []} | |||
|
576 | for n in node.names: | |||
|
577 | from_stdlib[n.name in stdlib_modules].append(n.name) | |||
|
578 | if from_stdlib[True] and from_stdlib[False]: | |||
|
579 | yield ('mixed imports\n stdlib: %s\n relative: %s' % | |||
|
580 | (', '.join(sorted(from_stdlib[True])), | |||
|
581 | ', '.join(sorted(from_stdlib[False]))), node.lineno) | |||
|
582 | ||||
|
583 | class CircularImport(Exception): | |||
|
584 | pass | |||
|
585 | ||||
|
586 | def checkmod(mod, imports): | |||
|
587 | shortest = {} | |||
|
588 | visit = [[mod]] | |||
|
589 | while visit: | |||
|
590 | path = visit.pop(0) | |||
|
591 | for i in sorted(imports.get(path[-1], [])): | |||
|
592 | if len(path) < shortest.get(i, 1000): | |||
|
593 | shortest[i] = len(path) | |||
|
594 | if i in path: | |||
|
595 | if i == path[0]: | |||
|
596 | raise CircularImport(path) | |||
|
597 | continue | |||
|
598 | visit.append(path + [i]) | |||
|
599 | ||||
|
600 | def rotatecycle(cycle): | |||
|
601 | """arrange a cycle so that the lexicographically first module listed first | |||
|
602 | ||||
|
603 | >>> rotatecycle(['foo', 'bar']) | |||
|
604 | ['bar', 'foo', 'bar'] | |||
|
605 | """ | |||
|
606 | lowest = min(cycle) | |||
|
607 | idx = cycle.index(lowest) | |||
|
608 | return cycle[idx:] + cycle[:idx] + [lowest] | |||
|
609 | ||||
|
610 | def find_cycles(imports): | |||
|
611 | """Find cycles in an already-loaded import graph. | |||
|
612 | ||||
|
613 | All module names recorded in `imports` should be absolute one. | |||
|
614 | ||||
|
615 | >>> from __future__ import print_function | |||
|
616 | >>> imports = {'top.foo': ['top.bar', 'os.path', 'top.qux'], | |||
|
617 | ... 'top.bar': ['top.baz', 'sys'], | |||
|
618 | ... 'top.baz': ['top.foo'], | |||
|
619 | ... 'top.qux': ['top.foo']} | |||
|
620 | >>> print('\\n'.join(sorted(find_cycles(imports)))) | |||
|
621 | top.bar -> top.baz -> top.foo -> top.bar | |||
|
622 | top.foo -> top.qux -> top.foo | |||
|
623 | """ | |||
|
624 | cycles = set() | |||
|
625 | for mod in sorted(imports.keys()): | |||
|
626 | try: | |||
|
627 | checkmod(mod, imports) | |||
|
628 | except CircularImport as e: | |||
|
629 | cycle = e.args[0] | |||
|
630 | cycles.add(" -> ".join(rotatecycle(cycle))) | |||
|
631 | return cycles | |||
|
632 | ||||
|
633 | def _cycle_sortkey(c): | |||
|
634 | return len(c), c | |||
|
635 | ||||
|
636 | def embedded(f, modname, src): | |||
|
637 | """Extract embedded python code | |||
|
638 | ||||
|
639 | >>> def _forcestr(thing): | |||
|
640 | ... if not isinstance(thing, str): | |||
|
641 | ... return thing.decode('ascii') | |||
|
642 | ... return thing | |||
|
643 | >>> def test(fn, lines): | |||
|
644 | ... for s, m, f, l in embedded(fn, b"example", lines): | |||
|
645 | ... print("%s %s %d" % (_forcestr(m), _forcestr(f), l)) | |||
|
646 | ... print(repr(_forcestr(s))) | |||
|
647 | >>> lines = [ | |||
|
648 | ... b'comment', | |||
|
649 | ... b' >>> from __future__ import print_function', | |||
|
650 | ... b" >>> ' multiline", | |||
|
651 | ... b" ... string'", | |||
|
652 | ... b' ', | |||
|
653 | ... b'comment', | |||
|
654 | ... b' $ cat > foo.py <<EOF', | |||
|
655 | ... b' > from __future__ import print_function', | |||
|
656 | ... b' > EOF', | |||
|
657 | ... ] | |||
|
658 | >>> test(b"example.t", lines) | |||
|
659 | example[2] doctest.py 2 | |||
|
660 | "from __future__ import print_function\\n' multiline\\nstring'\\n" | |||
|
661 | example[7] foo.py 7 | |||
|
662 | 'from __future__ import print_function\\n' | |||
|
663 | """ | |||
|
664 | inlinepython = 0 | |||
|
665 | shpython = 0 | |||
|
666 | script = [] | |||
|
667 | prefix = 6 | |||
|
668 | t = '' | |||
|
669 | n = 0 | |||
|
670 | for l in src: | |||
|
671 | n += 1 | |||
|
672 | if not l.endswith(b'\n'): | |||
|
673 | l += b'\n' | |||
|
674 | if l.startswith(b' >>> '): # python inlines | |||
|
675 | if shpython: | |||
|
676 | print("%s:%d: Parse Error" % (f, n)) | |||
|
677 | if not inlinepython: | |||
|
678 | # We've just entered a Python block. | |||
|
679 | inlinepython = n | |||
|
680 | t = b'doctest.py' | |||
|
681 | script.append(l[prefix:]) | |||
|
682 | continue | |||
|
683 | if l.startswith(b' ... '): # python inlines | |||
|
684 | script.append(l[prefix:]) | |||
|
685 | continue | |||
|
686 | cat = re.search(br"\$ \s*cat\s*>\s*(\S+\.py)\s*<<\s*EOF", l) | |||
|
687 | if cat: | |||
|
688 | if inlinepython: | |||
|
689 | yield b''.join(script), (b"%s[%d]" % | |||
|
690 | (modname, inlinepython)), t, inlinepython | |||
|
691 | script = [] | |||
|
692 | inlinepython = 0 | |||
|
693 | shpython = n | |||
|
694 | t = cat.group(1) | |||
|
695 | continue | |||
|
696 | if shpython and l.startswith(b' > '): # sh continuation | |||
|
697 | if l == b' > EOF\n': | |||
|
698 | yield b''.join(script), (b"%s[%d]" % | |||
|
699 | (modname, shpython)), t, shpython | |||
|
700 | script = [] | |||
|
701 | shpython = 0 | |||
|
702 | else: | |||
|
703 | script.append(l[4:]) | |||
|
704 | continue | |||
|
705 | # If we have an empty line or a command for sh, we end the | |||
|
706 | # inline script. | |||
|
707 | if inlinepython and (l == b' \n' | |||
|
708 | or l.startswith(b' $ ')): | |||
|
709 | yield b''.join(script), (b"%s[%d]" % | |||
|
710 | (modname, inlinepython)), t, inlinepython | |||
|
711 | script = [] | |||
|
712 | inlinepython = 0 | |||
|
713 | continue | |||
|
714 | ||||
|
715 | def sources(f, modname): | |||
|
716 | """Yields possibly multiple sources from a filepath | |||
|
717 | ||||
|
718 | input: filepath, modulename | |||
|
719 | yields: script(string), modulename, filepath, linenumber | |||
|
720 | ||||
|
721 | For embedded scripts, the modulename and filepath will be different | |||
|
722 | from the function arguments. linenumber is an offset relative to | |||
|
723 | the input file. | |||
|
724 | """ | |||
|
725 | py = False | |||
|
726 | if not f.endswith('.t'): | |||
|
727 | with open(f, 'rb') as src: | |||
|
728 | yield src.read(), modname, f, 0 | |||
|
729 | py = True | |||
|
730 | if py or f.endswith('.t'): | |||
|
731 | with open(f, 'rb') as src: | |||
|
732 | for script, modname, t, line in embedded(f, modname, src): | |||
|
733 | yield script, modname, t, line | |||
|
734 | ||||
|
735 | def main(argv): | |||
|
736 | if len(argv) < 2 or (argv[1] == '-' and len(argv) > 2): | |||
|
737 | print('Usage: %s {-|file [file] [file] ...}') | |||
|
738 | return 1 | |||
|
739 | if argv[1] == '-': | |||
|
740 | argv = argv[:1] | |||
|
741 | argv.extend(l.rstrip() for l in sys.stdin.readlines()) | |||
|
742 | localmodpaths = {} | |||
|
743 | used_imports = {} | |||
|
744 | any_errors = False | |||
|
745 | for source_path in argv[1:]: | |||
|
746 | modname = dotted_name_of_path(source_path) | |||
|
747 | localmodpaths[modname] = source_path | |||
|
748 | localmods = populateextmods(localmodpaths) | |||
|
749 | for localmodname, source_path in sorted(localmodpaths.items()): | |||
|
750 | if not isinstance(localmodname, bytes): | |||
|
751 | # This is only safe because all hg's files are ascii | |||
|
752 | localmodname = localmodname.encode('ascii') | |||
|
753 | for src, modname, name, line in sources(source_path, localmodname): | |||
|
754 | try: | |||
|
755 | used_imports[modname] = sorted( | |||
|
756 | imported_modules(src, modname, name, localmods, | |||
|
757 | ignore_nested=True)) | |||
|
758 | for error, lineno in verify_import_convention(modname, src, | |||
|
759 | localmods): | |||
|
760 | any_errors = True | |||
|
761 | print('%s:%d: %s' % (source_path, lineno + line, error)) | |||
|
762 | except SyntaxError as e: | |||
|
763 | print('%s:%d: SyntaxError: %s' % | |||
|
764 | (source_path, e.lineno + line, e)) | |||
|
765 | cycles = find_cycles(used_imports) | |||
|
766 | if cycles: | |||
|
767 | firstmods = set() | |||
|
768 | for c in sorted(cycles, key=_cycle_sortkey): | |||
|
769 | first = c.split()[0] | |||
|
770 | # As a rough cut, ignore any cycle that starts with the | |||
|
771 | # same module as some other cycle. Otherwise we see lots | |||
|
772 | # of cycles that are effectively duplicates. | |||
|
773 | if first in firstmods: | |||
|
774 | continue | |||
|
775 | print('Import cycle:', c) | |||
|
776 | firstmods.add(first) | |||
|
777 | any_errors = True | |||
|
778 | return any_errors != 0 | |||
|
779 | ||||
|
780 | if __name__ == '__main__': | |||
|
781 | sys.exit(int(main(sys.argv))) |
@@ -0,0 +1,5 b'' | |||||
|
1 | <?xml version="1.0" encoding="UTF-8" standalone="no"?> | |||
|
2 | <!-- Created with Inkscape (http://www.inkscape.org/) --> | |||
|
3 | <svg id="Layer_1" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" height="120" width="100" version="1.0" xmlns:cc="http://web.resource.org/cc/" xmlns:dc="http://purl.org/dc/elements/1.1/" viewBox="0 0 124.766 152.099"><metadata id="metadata6845"><rdf:RDF><cc:Work rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/><dc:title>Mercurial "droplets" logo</dc:title><dc:creator><cc:Agent><dc:title>Cali Mastny and Matt Mackall</dc:title></cc:Agent></dc:creator><cc:license rdf:resource="http://creativecommons.org/licenses/GPL/2.0/"/><dc:date>Feb 12 2008</dc:date></cc:Work><cc:License rdf:about="http://creativecommons.org/licenses/GPL/2.0/"><cc:permits rdf:resource="http://web.resource.org/cc/Reproduction"/><cc:permits rdf:resource="http://web.resource.org/cc/Distribution"/><cc:requires rdf:resource="http://web.resource.org/cc/Notice"/><cc:permits rdf:resource="http://web.resource.org/cc/DerivativeWorks"/><cc:requires rdf:resource="http://web.resource.org/cc/ShareAlike"/><cc:requires rdf:resource="http://web.resource.org/cc/SourceCode"/></cc:License></rdf:RDF></metadata> | |||
|
4 | <rect id="rect6847" stroke-linejoin="miter" style="stroke-dasharray:none;" height="150.12" width="124.77" stroke="#000" stroke-miterlimit="4" y="0.98776" x="0.3169" stroke-width="1.9755" fill="#FFF"/><path id="text2611" style="stroke-dasharray:none;" d="M9.848,124.61c1.777-0.79,3.665-1.18,5.479-1.18,1.74,0,2.851,0.43,3.48,1.32,1.332-0.89,3.146-1.32,4.553-1.32,4.221,0,4.369,1.71,4.369,6.73v11.11c0,0.49,0.074,0.49-2.036,0.49v-11.81c0-3.63-0.074-4.74-2.48-4.74-1.073,0-2.184,0.25-3.369,1.03v15.27c-0.037,0.15-0.111,0.18-0.369,0.22-0.038,0-0.074,0.03-0.112,0.03h-1.555v-11.81c0-3.49,0-4.77-2.517-4.77-1.074,0-2.147,0.21-3.406,0.82v15.27c0,0.49,0.074,0.49-2.0361,0.49v-17.15m27.831-1.18c-3.146,0-6.626,0.89-6.626,10.4,0,7.33,2.554,8.47,6.071,8.47,2.701,0,5.034-0.89,5.034-1.32,0-0.53-0.074-1.35-0.259-1.82-1.148,0.79-2.777,1.21-4.59,1.21-2.48,0-4.146-0.71-4.184-6.22,1.629,0,5.776-0.04,8.848-0.65,0.259-1.17,0.37-2.88,0.37-4.37,0-3.56-1.444-5.7-4.664-5.7m-0.185,1.78c2.221,0,2.813,1.46,2.85,4.31,0,0.75-0.037,1.64-0.148,2.49-2.073,0.5-5.591,0.5-7.072,0.5,0.261-6.48,2.481-7.3,4.37-7.3m8.07-0.21c1.739-1.14,3.332-1.57,4.961-1.57,1.814,0,2.666,0.5,2.666,1.11,0,0.35-0.112,0.96-0.297,1.31-0.519-0.28-1.11-0.53-2.074-0.53-1.184,0-2.295,0.32-3.183,1.1v14.85c0,0.49,0.037,0.49-2.073,0.49v-16.76m18.69-0.39c0-0.47-1.554-1.18-3.11-1.18-2.999,0-6.664,1.03-6.664,9.83,0,8.33,2.222,9.07,6.109,9.07,1.924,0,3.665-1.03,3.665-1.6,0-0.32-0.074-0.82-0.26-1.24-0.778,0.56-1.962,1.1-3.22,1.1-2.665,0-4.22-0.75-4.22-7.23,0-7.15,2.554-8.15,4.775-8.15,1.258,0,1.962,0.36,2.665,0.82,0.186-0.43,0.26-1.03,0.26-1.42m14.181,16.55c-1.63,0.82-3.776,1.14-5.627,1.14-4.739,0-5.442-1.99-5.442-6.73v-11.14c0-0.46-0.037-0.46,2.074-0.46v11.82c0,3.56,0.517,4.77,3.294,4.77,1.073,0,2.554-0.22,3.665-0.86v-15.27c0-0.46-0.074-0.46,2.036-0.46v17.19m4.221-16.16c1.739-1.14,3.332-1.57,4.96-1.57,1.814,0,2.666,0.5,2.666,1.11,0,0.35-0.111,0.96-0.296,1.31-0.519-0.28-1.111-0.53-2.074-0.53-1.184,0-2.295,0.32-3.183,1.1v14.85c0,0.49,0.037,0.49-2.073,0.49v-16.76m12.379-1.03c-1.629,0-2.11,0-2.11,0.96v16.83c2.073,0,2.11,0,2.11-0.49v-17.3m-2.184-6.27c0,1.18,0.37,1.6,1.11,1.64,0.851,0,1.259-0.61,1.259-1.67,0.037-1.11-0.26-1.61-1.111-1.61-0.814,0-1.221,0.61-1.258,1.64m5.696,7.3c0-0.39,0.074-0.61,0.222-0.71,0.704-0.39,3.41-0.86,6.48-0.86,2.33,0,3.81,1.11,3.81,4.31v2.31c0,6.34-0.18,11.07-0.18,11.07-0.85,0.47-2.45,1.18-5.04,1.18-2.66,0.03-5.329-0.22-5.329-5.48,0-5.02,2.739-5.81,5.479-5.81,1.04,0,2.26,0.11,3.07,0.43v-3.31c0-2.31-1.18-2.81-2.59-2.81-1.89,0-4.514,0.35-5.662,0.89-0.222-0.39-0.26-1-0.26-1.21m8.512,7.9c-0.7-0.25-1.7-0.35-2.4-0.35-2.11,0-4.04,0.42-4.04,4.34,0,3.66,1.59,3.7,3.48,3.7,1.19,0,2.37-0.32,2.78-0.75,0,0,0.18-4.27,0.18-6.94m7.86,8.37c0,0.49,0.04,0.49-2.04,0.49v-25.2c0-0.96,0.41-0.96,2.04-0.96v25.67" stroke-miterlimit="4" stroke-width="2.02999997" fill="#010101"/><g id="g4503" transform="matrix(0.9351326,0,0,0.9351326,150.39508,-1.251766)"><path id="path2339" fill="#1b1a1b" d="M-45.75,92.692c20.04-33.321-4.232-87.363-48.614-81.873-40.096,4.958-40.746,47.165-5.405,57.191,30.583,8.685,6.318,28.084,7.027,41,0.712,12.92,26.587,17.6,46.992-16.318z"/><circle id="circle2341" transform="matrix(1.0917947,-0.2858168,0.2858168,1.0917947,-180.30817,13.494135)" cy="85.364" cx="33.728" r="15.414" fill="#1b1a1b"/><path id="path2343" fill="#1b1a1b" d="M-140.06,48.936c-6.26,0.606-10.84,6.164-10.24,12.422,0.61,6.262,6.17,10.847,12.43,10.241,6.26-0.614,10.84-6.171,10.23-12.43-0.61-6.253-6.16-10.839-12.42-10.233z"/><path id="path2561" fill="#bfbfbf" d="M-44.993,91.34c20.041-33.321-4.231-87.363-48.613-81.873-40.104,4.9568-40.744,47.166-5.406,57.193,30.583,8.684,6.318,28.083,7.027,41,0.713,12.92,26.587,17.6,46.992-16.32z"/><path id="path2563" fill="#000" d="M-86.842,112.76c-1.215-1.97,0.642-4.16,2.551-3.99,3.039,0.26,9.655-0.04,14.876-3,13.043-7.39,33.114-42.966,23.019-65.405-4.519-10.044-6.72-12.92-11.374-17.833-0.95-1.002-0.405-0.948,0.238-0.609,2.517,1.321,6.94,6.437,11.477,14.765,7.664,14.069,7.267,30.795,4.416,41.287-1.986,7.299-8.825,23.815-18.842,30.955-10.039,7.15-21.785,11.26-26.361,3.83z"/><path id="path2565" fill="#000" d="M-95.93,66.591c-6.83-2.028-15.64-4.853-20.74-11.517-3.75-4.914-5.66-10.277-6.15-13.318-0.17-1.085-0.32-1.991-0.01-2.24,0.15-0.117,2.81,5.896,6.79,10.936,3.97,5.04,9.53,7.988,14.16,9.059,4.117,0.952,12.646,3.044,15.532,5.503,2.967,2.527,3.215,7.987,2.216,8.603-1.006,0.62-3.048-4.429-11.798-7.026z"/><path id="path2567" fill="#FFF" d="M-81.841,113.72c-0.132,1.57,1.665,1.87,4.083,1.51,3.099-0.46,5.72-0.81,9.287-2.6,4.835-2.42,9.728-5.89,13.312-10.57,10.692-13.945,14.478-30.45,13.895-32.824-0.195,1.961-2.776,12.253-8.679,21.532-7.582,11.922-13.079,18.262-25.758,21.342-3.529,0.86-5.967-0.45-6.14,1.61z"/><path id="path2569" fill="#FFF" d="M-109.96,59.479c1.44,1.225,4.4,2.857,10.223,4.767,7.031,2.305,10.455,4.304,11.888,5.262,1.52,1.018,2.483,3.288,2.578,1.272,0.099-2.019-1.145-3.755-3.921-4.675-1.878-0.624-5.038-2.109-8.067-2.707-1.946-0.384-5.111-1.146-7.831-1.978-1.48-0.457-3-1.258-4.87-1.941z"/><circle id="circle2577" transform="matrix(1.0917947,-0.2858168,0.2858168,1.0917947,-180.30817,13.494135)" cy="84.375" cx="34.681" r="15.414" fill="#bfbfbf"/><path id="path2579" fill="#000" d="M-128.68,108.38c13.53,12.54,33.894-4.69,24.93-19.897-1.01-1.708-2.32-3.009-1.89-1.7,2.87,8.747,0.22,15.667-4.72,19.227-4.85,3.5-11.51,4.09-16.84,1.32-1.57-0.81-2.22,0.37-1.48,1.05z"/><path id="path2585" fill="#FFF" d="M-118.07,110.95c1.73-0.36,11.75-2.95,14.1-11.194,0.73-2.569,0.86-2.053,0.66-0.661-1.06,7.105-7.78,12.345-13.49,12.545-1.16,0.12-2.68-0.39-1.27-0.69z"/><path id="path2589" fill="#bfbfbf" d="M-139.3,47.584c-6.26,0.605-10.84,6.164-10.24,12.422,0.61,6.261,6.17,10.847,12.43,10.241,6.25-0.614,10.84-6.173,10.23-12.431-0.61-6.254-6.17-10.838-12.42-10.232z"/><path id="path2591" fill="#000" d="M-144.47,67.571c0.07,0.805,1.17,1.838,2.9,2.312,1.49,0.408,5.32,1.45,10.25-1.658,4.92-3.108,5.49-11.421,3.25-13.865-0.69-1.239-1.59-2.14-0.88-0.164,1.81,4.99-1.7,9.659-4.74,11.82-3.03,2.162-6.88,1.139-8.45,0.66s-2.4,0.064-2.33,0.895z"/><path id="path2597" fill="#FFF" d="M-138.11,68.688c0.45-0.406,2.73-0.24,4.79-1.35,2.07-1.109,4.52-3.54,4.95-6.994,0.26-2.029,0.34-1.519,0.44-0.415-0.32,5.743-5.6,8.916-8.62,9.334-0.82,0.113-2.25,0.044-1.56-0.575z"/><path id="path2561_1_" fill="#999" d="M-47.767,69.694c8.532-24.594-9.323-61.736-45.446-57.268-32.637,4.035-33.167,38.389-4.4,46.55,32.582,4.933,12.962,29.512,10.179,41.904-2.495,11.11,26.331,12.94,39.667-31.186z"/><path id="path2571" fill="#f3f3f3" d="M-70.093,88.904c-8.827-1.092-21.529,18.836-9.552,16.506,5.756-0.86,10.525-2.89,14.794-7.762,5.567-6.353,13.883-20.074,16.288-28.94,2.025-7.476,1.007-19.057-1.081-8.175-2.142,11.167-11.623,29.464-20.449,28.371z"/><path id="path2581" fill="#999" d="M-129.39,104.85c2.05,0.03,3.28,0.32,5.35,1.77,4.09,1.7,11.61,0.62,15.09-3.95,3.47-4.57,3.58-10.868,2.26-14.674-3.24-9.314-16.99-9.149-23.13-1.417-6.64,8.636-1.61,18.231,0.43,18.271z"/><path id="path2593_2_" fill="#999" d="M-147.64,61.684c0.41,1.282,1.45,3.154,3.65,3.466,2.94,0.417,3.54,1.743,7,1.055,3.47-0.688,6.09-3.528,7.14-6.67,1.21-4.347-0.59-6.591-3.31-8.595-2.71-2.003-8.67-1.788-12.23,1.458-2.53,2.305-3.24,6.163-2.25,9.286z"/><path id="path256" fill="#f3f3f3" d="M-136.11,64.558c2.66-0.697,6.18-4.325,4.44-7.096-2.16-3.413-8.17-0.491-8.37,3.309-0.21,3.802,1.11,4.526,3.93,3.787z"/><path id="path258" fill="#f3f3f3" d="M-116.12,105.51c2.28-0.6,9.24-3.43,7.93-13.547-0.66-5.126-3.46,6.361-8.63,8.077-7.85,2.61-6.97,7.48,0.7,5.47z"/></g> | |||
|
5 | </svg> |
@@ -0,0 +1,31 b'' | |||||
|
1 | # memory.py - track memory usage | |||
|
2 | # | |||
|
3 | # Copyright 2009 Matt Mackall <mpm@selenic.com> and others | |||
|
4 | # | |||
|
5 | # This software may be used and distributed according to the terms of the | |||
|
6 | # GNU General Public License version 2 or any later version. | |||
|
7 | ||||
|
8 | '''helper extension to measure memory usage | |||
|
9 | ||||
|
10 | Reads current and peak memory usage from ``/proc/self/status`` and | |||
|
11 | prints it to ``stderr`` on exit. | |||
|
12 | ''' | |||
|
13 | ||||
|
14 | from __future__ import absolute_import | |||
|
15 | ||||
|
16 | def memusage(ui): | |||
|
17 | """Report memory usage of the current process.""" | |||
|
18 | result = {'peak': 0, 'rss': 0} | |||
|
19 | with open('/proc/self/status', 'r') as status: | |||
|
20 | # This will only work on systems with a /proc file system | |||
|
21 | # (like Linux). | |||
|
22 | for line in status: | |||
|
23 | parts = line.split() | |||
|
24 | key = parts[0][2:-1].lower() | |||
|
25 | if key in result: | |||
|
26 | result[key] = int(parts[1]) | |||
|
27 | ui.write_err(", ".join(["%s: %.1f MiB" % (k, v / 1024.0) | |||
|
28 | for k, v in result.iteritems()]) + "\n") | |||
|
29 | ||||
|
30 | def extsetup(ui): | |||
|
31 | ui.atexit(memusage, ui) |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644, binary diff hidden |
|
NO CONTENT: new file 100644, binary diff hidden |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100755 |
|
NO CONTENT: new file 100755 | ||
The requested commit or file is too big and content was truncated. Show full diff |
1 | NO CONTENT: new file 100644 |
|
NO CONTENT: new file 100644 | ||
The requested commit or file is too big and content was truncated. Show full diff |
General Comments 0
You need to be logged in to leave comments.
Login now