Compare commits
6507 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d007363e7c | ||
|
|
b2acac3a41 | ||
|
|
f3db2fa262 | ||
|
|
5b4fd8e9c8 | ||
|
|
81af8f072c | ||
|
|
eb35f8cb89 | ||
|
|
65683ab241 | ||
|
|
4c4cb20bde | ||
|
|
4133526d8d | ||
|
|
12d455f3c3 | ||
|
|
615b692442 | ||
|
|
ebdf0564eb | ||
|
|
68a8d9bc91 | ||
|
|
85be7dd902 | ||
|
|
d44325affd | ||
|
|
5a8efa9a52 | ||
|
|
b62f1f00cd | ||
|
|
4545b4d323 | ||
|
|
d74eb8c188 | ||
|
|
b275fa8109 | ||
|
|
60f45c965c | ||
|
|
efad4bcb56 | ||
|
|
9435e70b37 | ||
|
|
2063fee4fe | ||
|
|
c3e1955792 | ||
|
|
838284c09f | ||
|
|
1d35b90484 | ||
|
|
f3c1a894de | ||
|
|
af1c8dc5d9 | ||
|
|
2123fbdf9b | ||
|
|
14169c5092 | ||
|
|
0555525f97 | ||
|
|
24a54cd95b | ||
|
|
a7a5f36b49 | ||
|
|
ab0155c861 | ||
|
|
53c424caf8 | ||
|
|
23cfbac4ec | ||
|
|
f23d72001d | ||
|
|
302ad5f1f9 | ||
|
|
257e6c469e | ||
|
|
ef9766eb96 | ||
|
|
aa9e524e73 | ||
|
|
3b1ae3f7d2 | ||
|
|
cccfe47bf0 | ||
|
|
87ab97b5ed | ||
|
|
3b47b1ecbd | ||
|
|
12706fd6db | ||
|
|
d8be2f1ecc | ||
|
|
b6f9d9feb0 | ||
|
|
8efa94e42a | ||
|
|
b94527f661 | ||
|
|
3adee1eda0 | ||
|
|
398e9f5195 | ||
|
|
90c063060a | ||
|
|
3bcda9268a | ||
|
|
e2b398a6bf | ||
|
|
fa10fc994a | ||
|
|
cb2b8dea96 | ||
|
|
9bcd5de8ff | ||
|
|
9f9fca1e76 | ||
|
|
fdf46c6a10 | ||
|
|
305a6ae110 | ||
|
|
10daf1d63a | ||
|
|
23aa614baf | ||
|
|
5c35fac8fe | ||
|
|
8b2f6fffc9 | ||
|
|
32479503bd | ||
|
|
b06ec734f1 | ||
|
|
b039a81375 | ||
|
|
46fe9a167e | ||
|
|
79eb971fad | ||
|
|
81e9aa4de4 | ||
|
|
6d3521c240 | ||
|
|
23e0240410 | ||
|
|
1ae24b366f | ||
|
|
2ceb58d0c4 | ||
|
|
e1f63a3346 | ||
|
|
ec0b09450c | ||
|
|
4b78ab5bcd | ||
|
|
ae554a736b | ||
|
|
f842e28b85 | ||
|
|
33aa3f0fc5 | ||
|
|
e4e042e389 | ||
|
|
f3003a97ef | ||
|
|
6550bc97ba | ||
|
|
862de3a9dc | ||
|
|
22407fc897 | ||
|
|
dba6fe8af3 | ||
|
|
ef9500a8f0 | ||
|
|
bf1ea560e9 | ||
|
|
086b59483e | ||
|
|
048bcf19f6 | ||
|
|
8797be9f89 | ||
|
|
cc64d65c2f | ||
|
|
efdb990e56 | ||
|
|
bc7c2cd3f5 | ||
|
|
1584dac00a | ||
|
|
79986e5593 | ||
|
|
b8aa8b3079 | ||
|
|
ced3bafa99 | ||
|
|
755ec552de | ||
|
|
18f9f6c159 | ||
|
|
6da7ed9706 | ||
|
|
ffac5c1299 | ||
|
|
fe5673134f | ||
|
|
1d8fdc09e7 | ||
|
|
7d6cda4916 | ||
|
|
b25cb60259 | ||
|
|
87e98f01cd | ||
|
|
22cda198ae | ||
|
|
d1c06a93df | ||
|
|
eed0d9c8d2 | ||
|
|
bf82fdb678 | ||
|
|
e1e7fbf83d | ||
|
|
c739428c30 | ||
|
|
2a7d2ffccb | ||
|
|
5eceabf810 | ||
|
|
67ad903556 | ||
|
|
36b0802789 | ||
|
|
93fdc18fd4 | ||
|
|
73b0e6c37b | ||
|
|
65aad44464 | ||
|
|
a02cf5beb7 | ||
|
|
b76b42f209 | ||
|
|
ee88b0dc35 | ||
|
|
3dc7706c45 | ||
|
|
9741af2031 | ||
|
|
487b2089a9 | ||
|
|
b28368c859 | ||
|
|
22778e6efd | ||
|
|
3d77685108 | ||
|
|
25899b72d2 | ||
|
|
f877afb74d | ||
|
|
83c76981b2 | ||
|
|
975b53b318 | ||
|
|
2f5ae85d33 | ||
|
|
51878aeca8 | ||
|
|
1d2eb0f903 | ||
|
|
7cbaf06097 | ||
|
|
1059a35bbc | ||
|
|
064e474b0a | ||
|
|
aef2b6b45f | ||
|
|
35a7a3a52b | ||
|
|
e0c6048820 | ||
|
|
ffb12d122f | ||
|
|
b08f8bab71 | ||
|
|
1a05ae2eaa | ||
|
|
961c31a747 | ||
|
|
d1a345bb03 | ||
|
|
236aed112f | ||
|
|
3d7facf6ee | ||
|
|
eee49a4995 | ||
|
|
6de1399cf0 | ||
|
|
15aeb4aec2 | ||
|
|
86f0007768 | ||
|
|
3065d10931 | ||
|
|
4c4189d631 | ||
|
|
015b409f2f | ||
|
|
e2c794ff31 | ||
|
|
2a9b51d836 | ||
|
|
510360a509 | ||
|
|
6b2a4fe8e8 | ||
|
|
49fe90874a | ||
|
|
acbaef1907 | ||
|
|
74101eaf7c | ||
|
|
8ab324988c | ||
|
|
1283461b89 | ||
|
|
38790e2c4b | ||
|
|
aa718b4dce | ||
|
|
2d09dfd34f | ||
|
|
48e4de823a | ||
|
|
65d8403a04 | ||
|
|
a8ac37f517 | ||
|
|
b2c0679a7f | ||
|
|
8db00073b4 | ||
|
|
d36c1769e0 | ||
|
|
53ecb4c1ae | ||
|
|
616dd5c4a5 | ||
|
|
2edb0ad94d | ||
|
|
f8a535c6e8 | ||
|
|
f1bd614770 | ||
|
|
c8965d0f9a | ||
|
|
53bb264375 | ||
|
|
1ea54049d0 | ||
|
|
ca8543348b | ||
|
|
cf87e8ecf5 | ||
|
|
a6afd85526 | ||
|
|
0d4c76a029 | ||
|
|
c3708b3096 | ||
|
|
22a7eaf2e7 | ||
|
|
540def2c39 | ||
|
|
bf90fbc678 | ||
|
|
2b9d260686 | ||
|
|
f6633c8189 | ||
|
|
18f704533f | ||
|
|
aedba5411c | ||
|
|
e83d13848e | ||
|
|
696fad702f | ||
|
|
724a511995 | ||
|
|
90c9c70416 | ||
|
|
f8a4661d05 | ||
|
|
dd494e648a | ||
|
|
c9d6321f38 | ||
|
|
4038b4d17e | ||
|
|
46551e9d65 | ||
|
|
1060eeb197 | ||
|
|
201d30a944 | ||
|
|
fc2a069180 | ||
|
|
392407136d | ||
|
|
ba6573af61 | ||
|
|
8d988f9582 | ||
|
|
f923edc424 | ||
|
|
2712d9ae8b | ||
|
|
3312a042dd | ||
|
|
5040570ea9 | ||
|
|
f5c5d1b1da | ||
|
|
2cd6c2e7e0 | ||
|
|
0daadc954c | ||
|
|
ec98b7d672 | ||
|
|
8c2b6b532d | ||
|
|
71d62012e1 | ||
|
|
41deea90ee | ||
|
|
a81806d3d0 | ||
|
|
5607a114f9 | ||
|
|
e81614b9e9 | ||
|
|
6f094ef215 | ||
|
|
366baea099 | ||
|
|
dc9dcd045d | ||
|
|
10c47ee27c | ||
|
|
8f0240a295 | ||
|
|
fd08c821f9 | ||
|
|
c41c771e9a | ||
|
|
fff5aa3020 | ||
|
|
f1ec270e3e | ||
|
|
a3f2f574c6 | ||
|
|
ec19a97156 | ||
|
|
9a7817a271 | ||
|
|
8a0d5aa38d | ||
|
|
a52869507e | ||
|
|
c77d72b29f | ||
|
|
76d18e7156 | ||
|
|
9e6056551d | ||
|
|
bbea698af3 | ||
|
|
9eec68985d | ||
|
|
cd82f579bd | ||
|
|
93665f49b1 | ||
|
|
dc77d555f9 | ||
|
|
dfe3806d01 | ||
|
|
cfc7710205 | ||
|
|
c60d737928 | ||
|
|
1da149d9e1 | ||
|
|
43ba563a1c | ||
|
|
05cb6048ae | ||
|
|
70d6b32e14 | ||
|
|
75940c1f5d | ||
|
|
1d27a7f93d | ||
|
|
cffcc4c7a5 | ||
|
|
c727c3c441 | ||
|
|
fb4dc77f36 | ||
|
|
9eb7b192b8 | ||
|
|
06d63dda6e | ||
|
|
e6f251011f | ||
|
|
6a813aa33d | ||
|
|
441682b598 | ||
|
|
9c672f6ec1 | ||
|
|
35c05463e7 | ||
|
|
f00cbc0aeb | ||
|
|
ee86d24797 | ||
|
|
58a9324db0 | ||
|
|
e0e8fd6637 | ||
|
|
2416ee04c8 | ||
|
|
91c6ebb06c | ||
|
|
df0ddc0b50 | ||
|
|
2e02abffc0 | ||
|
|
e47957ce6d | ||
|
|
c54e688272 | ||
|
|
37821e6d63 | ||
|
|
a3ee388b66 | ||
|
|
855e913bbd | ||
|
|
78360ece8a | ||
|
|
7c46423727 | ||
|
|
fb74d10573 | ||
|
|
430bcf192f | ||
|
|
cac723dab3 | ||
|
|
617d18e587 | ||
|
|
2b06ceda71 | ||
|
|
1bb4ca22e7 | ||
|
|
24a410ae8f | ||
|
|
673984a7db | ||
|
|
10339090b8 | ||
|
|
b6dcf6bd02 | ||
|
|
280e7bb04d | ||
|
|
03551a5961 | ||
|
|
d474eba53a | ||
|
|
392cb2a714 | ||
|
|
92ac370415 | ||
|
|
c41e3dcb91 | ||
|
|
602d1a5fbc | ||
|
|
cd80884b76 | ||
|
|
bfadc932d7 | ||
|
|
0cd2e150d5 | ||
|
|
5aaaeb05a0 | ||
|
|
26ea0bc360 | ||
|
|
a86d218891 | ||
|
|
6632f883c0 | ||
|
|
66bcae353c | ||
|
|
07d355851e | ||
|
|
8d2f350ad1 | ||
|
|
fc1891320e | ||
|
|
8a9455d901 | ||
|
|
46b6ab7db7 | ||
|
|
958f97232f | ||
|
|
05d064ca8d | ||
|
|
47f88346d2 | ||
|
|
b5fc12fb80 | ||
|
|
83f5080274 | ||
|
|
df50fa2332 | ||
|
|
ad7a1e15b4 | ||
|
|
efe6fd154b | ||
|
|
fb8296524e | ||
|
|
00957a42d4 | ||
|
|
99db89067e | ||
|
|
f1b5a265ab | ||
|
|
451e917e7d | ||
|
|
d443079cf6 | ||
|
|
163e55c0eb | ||
|
|
09f11cf66e | ||
|
|
4ea3002572 | ||
|
|
840cd7b2e1 | ||
|
|
0760528f4a | ||
|
|
7f0fe31881 | ||
|
|
2be8658034 | ||
|
|
494bee1d6b | ||
|
|
0c345e2b09 | ||
|
|
adce8c15bb | ||
|
|
7cd663bbe8 | ||
|
|
85758a2dd2 | ||
|
|
7bc15ec6c1 | ||
|
|
d9d46096dd | ||
|
|
da68f7d31a | ||
|
|
41ed0e670a | ||
|
|
579b36754a | ||
|
|
e50211572f | ||
|
|
6849bfae16 | ||
|
|
c3f1d1a647 | ||
|
|
ac674bd405 | ||
|
|
d5899aacfb | ||
|
|
9e5a8c3fc8 | ||
|
|
83707f7b35 | ||
|
|
ca8df67947 | ||
|
|
3feb6492e6 | ||
|
|
c6744925c4 | ||
|
|
88b2f48493 | ||
|
|
0d3e06e68a | ||
|
|
bf890719ff | ||
|
|
28eae1e7ff | ||
|
|
9f9f4e7fef | ||
|
|
2f6b00b6f7 | ||
|
|
35f55cabf0 | ||
|
|
0201ac24e7 | ||
|
|
731c35540f | ||
|
|
dac62ec560 | ||
|
|
2c7447eaca | ||
|
|
b170b6ec8b | ||
|
|
8a3bdb3685 | ||
|
|
85e8cba7a1 | ||
|
|
56bf9c5612 | ||
|
|
549eb15c32 | ||
|
|
03663c5b28 | ||
|
|
bbd52c0b71 | ||
|
|
995f6be2c4 | ||
|
|
5b42753b8b | ||
|
|
959714a6ef | ||
|
|
79a8017fe9 | ||
|
|
e4a24e1785 | ||
|
|
9b0da20d90 | ||
|
|
db664c61a4 | ||
|
|
c299b86983 | ||
|
|
56e53d7da2 | ||
|
|
d676840258 | ||
|
|
cca37caf33 | ||
|
|
4358687bfa | ||
|
|
ae66c3f289 | ||
|
|
d3bbc245c9 | ||
|
|
5ee1b6ca97 | ||
|
|
c522341136 | ||
|
|
2cebe151f2 | ||
|
|
ecf5b61e86 | ||
|
|
c01ab63744 | ||
|
|
72b324c95b | ||
|
|
0c5abc491d | ||
|
|
a5e2e59385 | ||
|
|
040dd91d2e | ||
|
|
c6c07599c7 | ||
|
|
04ef25b6ff | ||
|
|
05ca7158d6 | ||
|
|
c7e7a0cd16 | ||
|
|
70f7177025 | ||
|
|
c86cdb1805 | ||
|
|
bd15534360 | ||
|
|
e30745f19c | ||
|
|
bca8d6d07b | ||
|
|
0764a4313b | ||
|
|
e0ef6dd8d4 | ||
|
|
3d366c2a4c | ||
|
|
2018e30366 | ||
|
|
303cd8a5af | ||
|
|
2f7af968bf | ||
|
|
543d247af8 | ||
|
|
ca1182e783 | ||
|
|
a34a784b43 | ||
|
|
3bd4b5ccc6 | ||
|
|
f4a013946f | ||
|
|
d2fd829a58 | ||
|
|
bb6f4fff87 | ||
|
|
5ffd57695c | ||
|
|
02ae1f79f7 | ||
|
|
f42b47e65b | ||
|
|
6dc24ab2d7 | ||
|
|
fe0b7533a1 | ||
|
|
b8d861edc1 | ||
|
|
de26a17dc7 | ||
|
|
37907e4110 | ||
|
|
152e085310 | ||
|
|
372b394f5b | ||
|
|
3889052c31 | ||
|
|
43182cb1eb | ||
|
|
de5a39f320 | ||
|
|
58b91befde | ||
|
|
8f976fd980 | ||
|
|
91047ffa30 | ||
|
|
b42064acdb | ||
|
|
7e220b2b9e | ||
|
|
072f51e300 | ||
|
|
af95993d6d | ||
|
|
e6bccc5eff | ||
|
|
1b262d33f3 | ||
|
|
c555bbce3d | ||
|
|
f6d538bb98 | ||
|
|
cbefd8f8ae | ||
|
|
736ee3ffff | ||
|
|
36c583dddf | ||
|
|
70d03b7a1c | ||
|
|
0d85254a19 | ||
|
|
e3376136ca | ||
|
|
f8b4fcdc42 | ||
|
|
6c340dcb65 | ||
|
|
6b467d5b3e | ||
|
|
5372bcc7a2 | ||
|
|
0c9a19e38c | ||
|
|
8b4c7c94b8 | ||
|
|
c4440eab4c | ||
|
|
7349427189 | ||
|
|
89ea25ca08 | ||
|
|
5d652dcaef | ||
|
|
d69788c9df | ||
|
|
69c2fafa7a | ||
|
|
620e3a602d | ||
|
|
ad8dbbb559 | ||
|
|
5a241a8290 | ||
|
|
4a332065d0 | ||
|
|
0e4b70a4a8 | ||
|
|
f1d4fd3e67 | ||
|
|
7b560f9080 | ||
|
|
0ebd921bbb | ||
|
|
206cb51219 | ||
|
|
5e6485c210 | ||
|
|
65b4945548 | ||
|
|
aa98ada141 | ||
|
|
26eeb6578d | ||
|
|
8bb07124f7 | ||
|
|
bce5c447b3 | ||
|
|
34cb17546d | ||
|
|
c1cd1fedf4 | ||
|
|
5defc2a3d2 | ||
|
|
7b2a21994f | ||
|
|
7c06604f16 | ||
|
|
0762c38d35 | ||
|
|
baac7809c5 | ||
|
|
79ed99a940 | ||
|
|
bca0894f73 | ||
|
|
9316bcf307 | ||
|
|
60855643c4 | ||
|
|
650bb4c719 | ||
|
|
2244224b12 | ||
|
|
bbf4d00319 | ||
|
|
6b813b4e2a | ||
|
|
529cb43397 | ||
|
|
6bc898b215 | ||
|
|
1a433de0b4 | ||
|
|
4d802df040 | ||
|
|
04a79175bf | ||
|
|
97656d65ec | ||
|
|
ba28d2e13f | ||
|
|
711992c8e2 | ||
|
|
31624b410a | ||
|
|
00827ce921 | ||
|
|
21d2a51cd3 | ||
|
|
c0384a04f8 | ||
|
|
ee0c4cd194 | ||
|
|
07b13e24fa | ||
|
|
0855f51436 | ||
|
|
70acfb2cfd | ||
|
|
29a2b2032a | ||
|
|
af2efbe480 | ||
|
|
25b0773a94 | ||
|
|
349f6b51a5 | ||
|
|
9917de09af | ||
|
|
884eef32c9 | ||
|
|
16dbf3166d | ||
|
|
be19f8888e | ||
|
|
3bbc86bcf2 | ||
|
|
8b656f15b9 | ||
|
|
453f8b312a | ||
|
|
723bfa70db | ||
|
|
45dd9c5795 | ||
|
|
fa479afdaa | ||
|
|
1dfeb192a3 | ||
|
|
1f9c2add7c | ||
|
|
24fbcd8dea | ||
|
|
db15bf23b8 | ||
|
|
de52ca4785 | ||
|
|
2748a3fbd8 | ||
|
|
dfe36fb702 | ||
|
|
297c829bdc | ||
|
|
bd933badb1 | ||
|
|
0fb4141ce4 | ||
|
|
51de894692 | ||
|
|
7079b5d770 | ||
|
|
41e5812a22 | ||
|
|
8d5f28b33a | ||
|
|
3925bcb94c | ||
|
|
8d1ac8c7f5 | ||
|
|
9f4ad73698 | ||
|
|
0108b5eb88 | ||
|
|
0c6841bdc7 | ||
|
|
c455e501ac | ||
|
|
44c1d8c1e5 | ||
|
|
ff22f43002 | ||
|
|
4e8396dbce | ||
|
|
d38d4efc18 | ||
|
|
a8c68e33db | ||
|
|
903d1b7797 | ||
|
|
5abaf26b5f | ||
|
|
485a377800 | ||
|
|
bd21a08bc9 | ||
|
|
99ae38a232 | ||
|
|
c148e54bbd | ||
|
|
267ab822c2 | ||
|
|
39cdaf5175 | ||
|
|
80818f80a9 | ||
|
|
fde6eee4f4 | ||
|
|
14ec69a160 | ||
|
|
8ebe9d1e16 | ||
|
|
7e66d0bcc1 | ||
|
|
4515e66783 | ||
|
|
1069f485da | ||
|
|
4c4835e869 | ||
|
|
a1faaa133c | ||
|
|
805fd18b7b | ||
|
|
33f7b8479e | ||
|
|
68bd82f1b6 | ||
|
|
13471ae2c4 | ||
|
|
822bf13b7a | ||
|
|
1cce5fdfe1 | ||
|
|
6b2fedb1c2 | ||
|
|
e307ada374 | ||
|
|
4f2628c221 | ||
|
|
0f16066915 | ||
|
|
151d8db98d | ||
|
|
614b26fff6 | ||
|
|
49b2743a37 | ||
|
|
8e37de19c9 | ||
|
|
38bda92bdc | ||
|
|
83ba6638a1 | ||
|
|
4832ecf3e7 | ||
|
|
2e8ed97355 | ||
|
|
d98839fc19 | ||
|
|
0f71838fdf | ||
|
|
b6de656cf1 | ||
|
|
75555c470b | ||
|
|
4d0b14fbb4 | ||
|
|
1f9922a5aa | ||
|
|
b3f3b70b90 | ||
|
|
924800b7df | ||
|
|
d27da57b02 | ||
|
|
f1a01aed7e | ||
|
|
c1a5771fcd | ||
|
|
8ac5c36735 | ||
|
|
6355896584 | ||
|
|
6216ce455f | ||
|
|
c0832995ae | ||
|
|
9469b20cbd | ||
|
|
573457c03f | ||
|
|
5c395424c6 | ||
|
|
f6d53df282 | ||
|
|
e4374b1d56 | ||
|
|
7302ddaba5 | ||
|
|
7456514816 | ||
|
|
d9ad4cf2fc | ||
|
|
8b4efbed06 | ||
|
|
10131aa8a0 | ||
|
|
23dc85c1de | ||
|
|
338c6b5a5c | ||
|
|
c13ebce2f6 | ||
|
|
b6ccd7ffbe | ||
|
|
ad0794cc59 | ||
|
|
6961cb7440 | ||
|
|
9868edb138 | ||
|
|
e822fad505 | ||
|
|
3ab5427019 | ||
|
|
7afb6fa3e3 | ||
|
|
29dff7ba1a | ||
|
|
329ee8d9f1 | ||
|
|
f70e0003f8 | ||
|
|
bb0eb29c82 | ||
|
|
47bba71d7f | ||
|
|
6b8921c8c5 | ||
|
|
7d09579e3f | ||
|
|
e5c9a24c33 | ||
|
|
e7626befc5 | ||
|
|
905d31442c | ||
|
|
917fabbc9b | ||
|
|
963001ba1a | ||
|
|
782c484cad | ||
|
|
859ef48e51 | ||
|
|
51aed2dbc6 | ||
|
|
497e9343aa | ||
|
|
6ce934f1dd | ||
|
|
3a64a11745 | ||
|
|
f4fc3f48a7 | ||
|
|
9e15320fd0 | ||
|
|
94729745dc | ||
|
|
7031645f4b | ||
|
|
75649c49d5 | ||
|
|
f1ff044967 | ||
|
|
9c14b9672f | ||
|
|
f93b039e42 | ||
|
|
3849b59627 | ||
|
|
a5eda6a87b | ||
|
|
31441f0b43 | ||
|
|
451a8bef39 | ||
|
|
c518fdc155 | ||
|
|
ab34b174f9 | ||
|
|
6ac3bd4c7c | ||
|
|
b4a8c227cc | ||
|
|
01c6b56685 | ||
|
|
5a81cf6c17 | ||
|
|
eeb7524c0f | ||
|
|
2fd25f0093 | ||
|
|
8047f902a5 | ||
|
|
788a0154d3 | ||
|
|
a8f4b0227f | ||
|
|
cdf8c0fac9 | ||
|
|
8b5f71fb55 | ||
|
|
c100df412d | ||
|
|
cf00775bb8 | ||
|
|
97be3c05e6 | ||
|
|
4fd5552d3d | ||
|
|
12800f831a | ||
|
|
e8a209c9b5 | ||
|
|
781fed1079 | ||
|
|
ebb373eedb | ||
|
|
9f75bda8be | ||
|
|
370589d6c0 | ||
|
|
262c341bdc | ||
|
|
22b11d7d4d | ||
|
|
92f5f8dced | ||
|
|
034244217f | ||
|
|
5d9c3d595f | ||
|
|
ed62822d44 | ||
|
|
cf750c53fd | ||
|
|
d2421d964a | ||
|
|
52e2091f2c | ||
|
|
1a29a769c6 | ||
|
|
d66d25ff14 | ||
|
|
d70ef90bdd | ||
|
|
f772a5cf38 | ||
|
|
583c0f09a8 | ||
|
|
4d63b576f7 | ||
|
|
44cf66d7ff | ||
|
|
469c43ca25 | ||
|
|
bb7dc0fd93 | ||
|
|
b8baeac860 | ||
|
|
a425ce0826 | ||
|
|
513aa61d17 | ||
|
|
6a55ec6955 | ||
|
|
e470786fb9 | ||
|
|
c3d88aa53d | ||
|
|
cb5b6af9db | ||
|
|
b188a02956 | ||
|
|
604e21e32c | ||
|
|
7dbebef3ff | ||
|
|
f8a4ebd4a8 | ||
|
|
0117d9eedb | ||
|
|
cdb23cafa6 | ||
|
|
727deaf1a6 | ||
|
|
b7410ee718 | ||
|
|
583bfdf9bb | ||
|
|
41dcefb174 | ||
|
|
91bdb2f344 | ||
|
|
58b76bac0d | ||
|
|
f8efee6c2a | ||
|
|
1666415620 | ||
|
|
7f8f5f3498 | ||
|
|
a27d72b437 | ||
|
|
22126e99c1 | ||
|
|
dc7f8014a2 | ||
|
|
e112175abe | ||
|
|
f7fd1f2a89 | ||
|
|
ed1fe93648 | ||
|
|
616b8f82ee | ||
|
|
43896dc416 | ||
|
|
9b30634217 | ||
|
|
676e950fa3 | ||
|
|
90b86313db | ||
|
|
3c1e9e9a25 | ||
|
|
b39aa02b52 | ||
|
|
860e771493 | ||
|
|
e027770213 | ||
|
|
6bb001e416 | ||
|
|
43ebc172cb | ||
|
|
892e79a982 | ||
|
|
542e080f0a | ||
|
|
f35eb0f148 | ||
|
|
c764e7fd97 | ||
|
|
1c97f10d8a | ||
|
|
d8499e6941 | ||
|
|
105a678d64 | ||
|
|
a12de09533 | ||
|
|
431a610f00 | ||
|
|
6e6ebc5947 | ||
|
|
b30b78e442 | ||
|
|
cab859a0e4 | ||
|
|
a2c6469d41 | ||
|
|
55d95f9009 | ||
|
|
ab1048b7ee | ||
|
|
38a10f8be4 | ||
|
|
f165ba6480 | ||
|
|
bcc875a39c | ||
|
|
2f2029a5c1 | ||
|
|
8dd509c31b | ||
|
|
171f6422b1 | ||
|
|
5e6c3f314c | ||
|
|
efc97d177a | ||
|
|
601e90f5fe | ||
|
|
decede394a | ||
|
|
eb850ddd36 | ||
|
|
2bf305b177 | ||
|
|
d3a4b7a799 | ||
|
|
b85b5e00d4 | ||
|
|
45b90972dc | ||
|
|
4a807b6373 | ||
|
|
6ed9164c9d | ||
|
|
7180d6aa07 | ||
|
|
9d6445d4ce | ||
|
|
953f9da3b5 | ||
|
|
97b304abc9 | ||
|
|
49a1d4417d | ||
|
|
8451de8752 | ||
|
|
32bed83a17 | ||
|
|
92edce8fa1 | ||
|
|
545d3208c8 | ||
|
|
0a13b7c559 | ||
|
|
b745726462 | ||
|
|
3dbfd49414 | ||
|
|
2ee9376df2 | ||
|
|
aa62c2eff6 | ||
|
|
50d773988b | ||
|
|
d2239427f2 | ||
|
|
24a7d4f816 | ||
|
|
a4f9621473 | ||
|
|
04d142cd62 | ||
|
|
2f3627e74b | ||
|
|
d545902acc | ||
|
|
4871a8f43e | ||
|
|
32c8f495ab | ||
|
|
0c21d2c047 | ||
|
|
0964a06ab5 | ||
|
|
3e50ee6193 | ||
|
|
da98f47502 | ||
|
|
036f407d6a | ||
|
|
2c60dbd4fb | ||
|
|
b12ca1da88 | ||
|
|
d4ada51fad | ||
|
|
ef89dabb61 | ||
|
|
9be1ffd633 | ||
|
|
f0ae6a0bb1 | ||
|
|
1e44ee9e9b | ||
|
|
b3bda2aa64 | ||
|
|
82ad5a632d | ||
|
|
21213a2587 | ||
|
|
776af45c09 | ||
|
|
70b66382eb | ||
|
|
14326b626e | ||
|
|
1dabd68327 | ||
|
|
f27ce7e1e4 | ||
|
|
91c5515d5b | ||
|
|
6ab1937ff5 | ||
|
|
576a490435 | ||
|
|
0afa545b06 | ||
|
|
937cefe824 | ||
|
|
896605f838 | ||
|
|
250e98837f | ||
|
|
2cb3505dce | ||
|
|
73f11fae2e | ||
|
|
4ced5bbbc0 | ||
|
|
4421fda877 | ||
|
|
5407052e0c | ||
|
|
437b880b3e | ||
|
|
90c7943242 | ||
|
|
70d536c6c4 | ||
|
|
319b934967 | ||
|
|
61017fc204 | ||
|
|
1ff90b713f | ||
|
|
7045d06221 | ||
|
|
05cc370c55 | ||
|
|
963e202745 | ||
|
|
82b1a11820 | ||
|
|
694c6e8fd2 | ||
|
|
45186255cf | ||
|
|
a531a1709e | ||
|
|
f85a3ad44d | ||
|
|
ee7afcbe9e | ||
|
|
b3b63f836a | ||
|
|
c2ef2ef287 | ||
|
|
e65fd45c65 | ||
|
|
32a1d1445c | ||
|
|
35c853e906 | ||
|
|
481139772b | ||
|
|
5dfac9a765 | ||
|
|
ee92fee212 | ||
|
|
b06d809364 | ||
|
|
f8fb97d912 | ||
|
|
5f2f4a0897 | ||
|
|
b7d198793f | ||
|
|
991b6eafca | ||
|
|
5b75eea8cf | ||
|
|
ba48f40d21 | ||
|
|
6fafc8dba1 | ||
|
|
53312852e9 | ||
|
|
2d59112c1b | ||
|
|
637db29fad | ||
|
|
87aca5bf1b | ||
|
|
585503f9fb | ||
|
|
19e07a610a | ||
|
|
4058c85e2a | ||
|
|
b3c073ab6c | ||
|
|
6a42b95d39 | ||
|
|
30b2a7169f | ||
|
|
cb49e11eca | ||
|
|
5b5cf9f006 | ||
|
|
2bf94d8db4 | ||
|
|
7366cef1fe | ||
|
|
1854381456 | ||
|
|
8dee54bf5d | ||
|
|
bbc4c361bb | ||
|
|
83b7397398 | ||
|
|
04a887dafa | ||
|
|
4c5291f941 | ||
|
|
b73d196c6b | ||
|
|
d0564933a2 | ||
|
|
03f91e8d85 | ||
|
|
c711fb67c8 | ||
|
|
7e6314dcac | ||
|
|
10df9dc8c3 | ||
|
|
4110c7ffb0 | ||
|
|
7f79024e6a | ||
|
|
f6cbbe1e64 | ||
|
|
64312ceded | ||
|
|
98206ab49f | ||
|
|
56622ee2c6 | ||
|
|
65c0937741 | ||
|
|
8498bfd2c2 | ||
|
|
7403b94b9d | ||
|
|
d40cc32393 | ||
|
|
fc983f9751 | ||
|
|
ae255a7adf | ||
|
|
90c6b04361 | ||
|
|
86a274a7ee | ||
|
|
530b6a5088 | ||
|
|
5e52aaac6f | ||
|
|
3ea441d1a0 | ||
|
|
14df3c6249 | ||
|
|
7f8643efde | ||
|
|
bd6a68bfe5 | ||
|
|
a5a244767a | ||
|
|
273311eed2 | ||
|
|
55189200a4 | ||
|
|
5e431149cd | ||
|
|
7023dedc05 | ||
|
|
9e98c86ae1 | ||
|
|
071237d322 | ||
|
|
06468d6f43 | ||
|
|
4377e95c99 | ||
|
|
f4feb38089 | ||
|
|
82232e2530 | ||
|
|
9c2809a1a4 | ||
|
|
dd5b4a25d1 | ||
|
|
73e5c70d80 | ||
|
|
6d36641080 | ||
|
|
662dbaf8b2 | ||
|
|
e63ff1c762 | ||
|
|
084ad69c53 | ||
|
|
1ccde201be | ||
|
|
48a721e259 | ||
|
|
4c7f638f3c | ||
|
|
35e53ee511 | ||
|
|
b1881e5f54 | ||
|
|
3c39a935f8 | ||
|
|
2b0499c968 | ||
|
|
504d800a0d | ||
|
|
9d4fa87914 | ||
|
|
6016033b8b | ||
|
|
5af54c57ba | ||
|
|
cb42cfc6af | ||
|
|
9ddf22ea93 | ||
|
|
b2fe7e518f | ||
|
|
4fbe954a79 | ||
|
|
66621d762e | ||
|
|
9dd6aefcec | ||
|
|
749fd618a9 | ||
|
|
6bf05a8154 | ||
|
|
a08809f8fe | ||
|
|
57ecb276c8 | ||
|
|
79a803ea8f | ||
|
|
0f6579801d | ||
|
|
fcaf2bfdba | ||
|
|
4144f71e23 | ||
|
|
852ecd71f7 | ||
|
|
aadc6e0bbd | ||
|
|
a738945a88 | ||
|
|
9d3cbfe896 | ||
|
|
1a11f1e8c6 | ||
|
|
a12f5376b5 | ||
|
|
fd531e84fc | ||
|
|
d26d7162a5 | ||
|
|
a9cdf580a7 | ||
|
|
990acb3fd3 | ||
|
|
3486bf92eb | ||
|
|
ed1864e076 | ||
|
|
0998ce81f3 | ||
|
|
99e068643b | ||
|
|
0d7eb18d7b | ||
|
|
81c11ebb53 | ||
|
|
2e73c58338 | ||
|
|
381a48f21d | ||
|
|
a88176e060 | ||
|
|
e06756bcab | ||
|
|
9c222a445f | ||
|
|
51bde36dee | ||
|
|
e4c0c39fbf | ||
|
|
1abdd170d3 | ||
|
|
dddd155afa | ||
|
|
c411714546 | ||
|
|
cba7c1726f | ||
|
|
be8ec24106 | ||
|
|
0b3ccaff27 | ||
|
|
b273cd1339 | ||
|
|
82eb32a71e | ||
|
|
e905c2c6b5 | ||
|
|
13376d89cc | ||
|
|
2e1f26096f | ||
|
|
8f97e8d5ed | ||
|
|
92f20b9b7d | ||
|
|
3d5251d9a5 | ||
|
|
195be2742c | ||
|
|
2adc4d12be | ||
|
|
8d7b7009c3 | ||
|
|
ca5a34ad1e | ||
|
|
fbd94fc6ce | ||
|
|
953a07252a | ||
|
|
f77bd59e1d | ||
|
|
e371e03696 | ||
|
|
5b6754ce6c | ||
|
|
4aba3bc62b | ||
|
|
fc6ad2059a | ||
|
|
69c8bb1eb3 | ||
|
|
0bf721a74c | ||
|
|
c504abb84d | ||
|
|
2527289e3e | ||
|
|
581ffb862c | ||
|
|
8e70e9c1c3 | ||
|
|
4a3c19c666 | ||
|
|
d575a5ce12 | ||
|
|
53dc145ce7 | ||
|
|
0398face05 | ||
|
|
ef7d8ab90b | ||
|
|
28f4f3a8c8 | ||
|
|
3fb0b71822 | ||
|
|
40b2f00dc5 | ||
|
|
749da42ffc | ||
|
|
1f9f439acb | ||
|
|
c5a817194a | ||
|
|
c1e4d0590c | ||
|
|
85466c7ee1 | ||
|
|
43b474143c | ||
|
|
740478344b | ||
|
|
5094c1db2a | ||
|
|
f5bb2b11e5 | ||
|
|
8da702c2e7 | ||
|
|
d2b0bad1cf | ||
|
|
ece8a925a6 | ||
|
|
fc54c01f01 | ||
|
|
3fd420c901 | ||
|
|
01788e86e5 | ||
|
|
4f52bc138f | ||
|
|
2de439bd1e | ||
|
|
b989e2ce37 | ||
|
|
25f08ddd39 | ||
|
|
a16c799da9 | ||
|
|
0052e9d136 | ||
|
|
b72cf90ed4 | ||
|
|
69013ef8ad | ||
|
|
16132e86a3 | ||
|
|
047191abf0 | ||
|
|
11372ac9ff | ||
|
|
336c1b7b6e | ||
|
|
2c5abed2f1 | ||
|
|
8c6890c95f | ||
|
|
60adcedebe | ||
|
|
95de5f6fe1 | ||
|
|
788aafff3c | ||
|
|
c09d506245 | ||
|
|
18c5e90076 | ||
|
|
fee0745e98 | ||
|
|
43073da7eb | ||
|
|
0b6fee138a | ||
|
|
78b9c3004a | ||
|
|
c99aa74140 | ||
|
|
4fbff99186 | ||
|
|
8afd56575c | ||
|
|
1951f3856f | ||
|
|
8357cdf591 | ||
|
|
499bad5f53 | ||
|
|
df2a23d1a7 | ||
|
|
d6ecf74db4 | ||
|
|
6670e6cd29 | ||
|
|
d8b11adfd5 | ||
|
|
4a5b753fd8 | ||
|
|
d9231eb805 | ||
|
|
bb1e7f62a0 | ||
|
|
e5ffb2bfd2 | ||
|
|
6fff0b3e2a | ||
|
|
f0d1853a66 | ||
|
|
7224728ab8 | ||
|
|
ca7c3cc27d | ||
|
|
ac439d83fe | ||
|
|
c0b92eb5d0 | ||
|
|
5599bdf1bc | ||
|
|
de41536046 | ||
|
|
30d321998c | ||
|
|
59a02ce76a | ||
|
|
2c396d4922 | ||
|
|
3191678b14 | ||
|
|
7ecf057901 | ||
|
|
091726b374 | ||
|
|
dfaa6d8eb9 | ||
|
|
aff4bf8f6c | ||
|
|
ba1e1532ac | ||
|
|
ae3bda81c5 | ||
|
|
0ec747630d | ||
|
|
945131ccab | ||
|
|
f11b4cb481 | ||
|
|
92c6025390 | ||
|
|
138c738db9 | ||
|
|
4fae1958fa | ||
|
|
fb450385d7 | ||
|
|
7b1d827460 | ||
|
|
74ebc2d3b0 | ||
|
|
95f3e52064 | ||
|
|
da2b65cd7c | ||
|
|
2fcb8b849e | ||
|
|
d7a72e30c0 | ||
|
|
f397d0ddd7 | ||
|
|
db98632078 | ||
|
|
1509b4cb6e | ||
|
|
f20f4d130b | ||
|
|
3af4b1ff98 | ||
|
|
f80c2406a8 | ||
|
|
17006b4539 | ||
|
|
e5d400ebb9 | ||
|
|
f824004e4f | ||
|
|
453eebbac8 | ||
|
|
1a39d93b4e | ||
|
|
6fac471415 | ||
|
|
252568c91b | ||
|
|
8e11f8dc21 | ||
|
|
2475ca8f9a | ||
|
|
2a18430a45 | ||
|
|
dc4743a392 | ||
|
|
0cb57f52de | ||
|
|
d2aaa2211e | ||
|
|
f4666df7da | ||
|
|
4cd4ce504d | ||
|
|
fadfa7cc42 | ||
|
|
b912edbbef | ||
|
|
a6c6b00d7e | ||
|
|
2a557f67d2 | ||
|
|
1a6af064b0 | ||
|
|
7ef62d28a5 | ||
|
|
b8fb8cdce6 | ||
|
|
135679096b | ||
|
|
1ff428087e | ||
|
|
f6c5242a93 | ||
|
|
3d2d8f2d86 | ||
|
|
aef8dab4d9 | ||
|
|
bcb7eff6fa | ||
|
|
e16f45e494 | ||
|
|
435d0f22f5 | ||
|
|
dc2738afad | ||
|
|
08a45e9a3b | ||
|
|
02221c993e | ||
|
|
9c8d508247 | ||
|
|
8f42bec270 | ||
|
|
00c70307ad | ||
|
|
883435336c | ||
|
|
2c8e35a933 | ||
|
|
660d3fa1e9 | ||
|
|
7df18678a4 | ||
|
|
260c731f6b | ||
|
|
00b1908f3c | ||
|
|
1ef332e82c | ||
|
|
cf926134ef | ||
|
|
e73e7aea56 | ||
|
|
a72d73294c | ||
|
|
0f546a4692 | ||
|
|
dd7e215e78 | ||
|
|
fcd75422d5 | ||
|
|
ad6837ee47 | ||
|
|
01d5bc73cc | ||
|
|
f3b915c43a | ||
|
|
73a49c463d | ||
|
|
d86cb92a94 | ||
|
|
09c29cdda5 | ||
|
|
67dec6a665 | ||
|
|
b673bc1386 | ||
|
|
4b08f3909d | ||
|
|
35fc5007c8 | ||
|
|
ac499b3aff | ||
|
|
31c317f5f7 | ||
|
|
a6623357ad | ||
|
|
c6a1076e3a | ||
|
|
d318c84434 | ||
|
|
c21a210198 | ||
|
|
fc877ae0f4 | ||
|
|
1049824014 | ||
|
|
1d8222ef6a | ||
|
|
ee635be441 | ||
|
|
01d3282838 | ||
|
|
35a502f309 | ||
|
|
662579e9a9 | ||
|
|
00dd0e8a9d | ||
|
|
430c312263 | ||
|
|
8ed8bfb8bc | ||
|
|
0939371e2e | ||
|
|
f2dabd0731 | ||
|
|
e7ef79e0d3 | ||
|
|
ffda5bc0f7 | ||
|
|
737896695c | ||
|
|
ae69244ac7 | ||
|
|
8232552152 | ||
|
|
f7b481fc28 | ||
|
|
8bc1af9d1a | ||
|
|
fd1a0edf7f | ||
|
|
4c83dba183 | ||
|
|
b641720575 | ||
|
|
950455bd93 | ||
|
|
eb79436ab7 | ||
|
|
10db47bf4c | ||
|
|
4d454f8914 | ||
|
|
eb4a46b40f | ||
|
|
7df326083d | ||
|
|
48f5a61564 | ||
|
|
19f0f7535f | ||
|
|
e3e0b72b43 | ||
|
|
3435df8b9c | ||
|
|
7e12460303 | ||
|
|
9d3d0912e5 | ||
|
|
1ed4f64e60 | ||
|
|
8b64b2113e | ||
|
|
5bf2b6c382 | ||
|
|
fa0b06ac60 | ||
|
|
ef22a87fcf | ||
|
|
bfce379471 | ||
|
|
4872f6d2dc | ||
|
|
3c30870dc2 | ||
|
|
4317e4c4a2 | ||
|
|
7da57e0aa5 | ||
|
|
0da4168836 | ||
|
|
df67d57bca | ||
|
|
82e7f1a212 | ||
|
|
289521b4b7 | ||
|
|
d557beb5f1 | ||
|
|
2cf1193b56 | ||
|
|
57315f1e27 | ||
|
|
56bef637bd | ||
|
|
d1bac6cde0 | ||
|
|
23a136d9ef | ||
|
|
d8f7bce9d4 | ||
|
|
39354249e9 | ||
|
|
98e756e278 | ||
|
|
91ca5b6f2a | ||
|
|
b6ac0860c6 | ||
|
|
00dc078311 | ||
|
|
2d9a2506b4 | ||
|
|
fa73b1ce80 | ||
|
|
f4b97979c4 | ||
|
|
62b21c586d | ||
|
|
606c75162f | ||
|
|
a8c10dbc08 | ||
|
|
c6768a93c8 | ||
|
|
74949d306f | ||
|
|
77f93886da | ||
|
|
8f5a7f1764 | ||
|
|
f78f7d6b37 | ||
|
|
75541b9cf0 | ||
|
|
922b7c44ce | ||
|
|
8bc63e9029 | ||
|
|
2647f59df1 | ||
|
|
77f6449db9 | ||
|
|
f3ad71d751 | ||
|
|
2db62a211a | ||
|
|
4e6c1335d5 | ||
|
|
f185528f1c | ||
|
|
2b668e628a | ||
|
|
0688d7ca9f | ||
|
|
0135dff001 | ||
|
|
efe25db40f | ||
|
|
773a5631c5 | ||
|
|
5d5f5cd9a6 | ||
|
|
ad9b2ab617 | ||
|
|
cb8b038795 | ||
|
|
078e69d06d | ||
|
|
df8e56ddf8 | ||
|
|
f44d6e063c | ||
|
|
113509a4e9 | ||
|
|
839c675cb9 | ||
|
|
854c360def | ||
|
|
0cbb95ed1e | ||
|
|
d8929b1d3e | ||
|
|
fa99a6745d | ||
|
|
b79217be1e | ||
|
|
d27a0f5b0c | ||
|
|
97c27668bc | ||
|
|
e5970e83ff | ||
|
|
d3c022f89e | ||
|
|
3624587f08 | ||
|
|
56c080417a | ||
|
|
da4e3784e9 | ||
|
|
35f7a71f9a | ||
|
|
bf22b4cbfe | ||
|
|
4741152f05 | ||
|
|
fb33cf4576 | ||
|
|
1fb38abf6b | ||
|
|
4299feee37 | ||
|
|
86b1906798 | ||
|
|
18a0a85df6 | ||
|
|
05ba32b552 | ||
|
|
c30c12d369 | ||
|
|
09dfaf9875 | ||
|
|
ae604b6289 | ||
|
|
fc8146b53d | ||
|
|
641845519d | ||
|
|
b32809d03f | ||
|
|
02b2c7482a | ||
|
|
6fd0d5e267 | ||
|
|
a4ecacb9b5 | ||
|
|
b9e0fcdf85 | ||
|
|
4ef79d250d | ||
|
|
18c57ea230 | ||
|
|
a883424d25 | ||
|
|
7fa170cee9 | ||
|
|
8925329950 | ||
|
|
4aa5dab62d | ||
|
|
936dd2eaaa | ||
|
|
09e80f0390 | ||
|
|
63dfa303e5 | ||
|
|
599b1eb689 | ||
|
|
4a636b6da7 | ||
|
|
d92172f50c | ||
|
|
2623240635 | ||
|
|
908e8577bb | ||
|
|
f90fda8e6f | ||
|
|
f4037667fa | ||
|
|
a1fd12ef42 | ||
|
|
517721eaa4 | ||
|
|
b56a2c14bb | ||
|
|
62d703fdf7 | ||
|
|
f29899e566 | ||
|
|
9cebcc45c1 | ||
|
|
3125177e5c | ||
|
|
7810413699 | ||
|
|
261db14c4b | ||
|
|
16783bff16 | ||
|
|
352cdc137d | ||
|
|
bd2e1ef67e | ||
|
|
7f970bbc7b | ||
|
|
35609fe3d1 | ||
|
|
4fcca7c61b | ||
|
|
d55dc92502 | ||
|
|
c148d89004 | ||
|
|
8e7a127792 | ||
|
|
6afe2c4e9f | ||
|
|
be69e2c02c | ||
|
|
e3be9f7fe9 | ||
|
|
ca3cb07fcb | ||
|
|
b98e5690eb | ||
|
|
45e6187c1a | ||
|
|
c521182ceb | ||
|
|
83662b5195 | ||
|
|
8db7cf49a6 | ||
|
|
30f3b55baf | ||
|
|
8750ba94c8 | ||
|
|
b5beac879e | ||
|
|
e8b6995cc7 | ||
|
|
7ca8db15d9 | ||
|
|
9d96382ecc | ||
|
|
b86b8965f1 | ||
|
|
f6c49daaa6 | ||
|
|
a129a6192a | ||
|
|
22ae259cf5 | ||
|
|
e627820d3d | ||
|
|
65711f4bfe | ||
|
|
4531f39c30 | ||
|
|
3db1188444 | ||
|
|
be3d38ac92 | ||
|
|
b490bdfe33 | ||
|
|
95725e407e | ||
|
|
f6457a2023 | ||
|
|
7dcb85010a | ||
|
|
0525bf5d4e | ||
|
|
7207068181 | ||
|
|
59d2fe8aa4 | ||
|
|
be92c8bde1 | ||
|
|
a3e22091be | ||
|
|
17b7dfb27b | ||
|
|
06173b9194 | ||
|
|
2a45e879bb | ||
|
|
ce6c67f9bc | ||
|
|
87cb0c2aec | ||
|
|
d0b191af18 | ||
|
|
b607adadcf | ||
|
|
e7828c1e5e | ||
|
|
c051cb8be1 | ||
|
|
6f51fc34c3 | ||
|
|
02b02c51e8 | ||
|
|
a414dd028c | ||
|
|
c2439b04c9 | ||
|
|
ed550a894f | ||
|
|
8b51f58fe7 | ||
|
|
310b0e888d | ||
|
|
c189c20164 | ||
|
|
0811338370 | ||
|
|
ecc22757b8 | ||
|
|
5e553e40fa | ||
|
|
26c5029256 | ||
|
|
75454b02c0 | ||
|
|
bbc079e57b | ||
|
|
83bbffd491 | ||
|
|
fc5e1d97af | ||
|
|
85041d297c | ||
|
|
17c7ce9b40 | ||
|
|
6506161107 | ||
|
|
590da0cab3 | ||
|
|
44b6a3a054 | ||
|
|
a11396c901 | ||
|
|
cd52c24e87 | ||
|
|
2e52008542 | ||
|
|
a6a5f393cc | ||
|
|
b3f2f0fa1e | ||
|
|
f788c8cb37 | ||
|
|
deaeec0bc7 | ||
|
|
16656af847 | ||
|
|
3b279983e6 | ||
|
|
55d4392d90 | ||
|
|
acfc119409 | ||
|
|
18fcb23371 | ||
|
|
1ae2fc648d | ||
|
|
2215095be8 | ||
|
|
28d2966819 | ||
|
|
92efd17952 | ||
|
|
3a7ec2a26e | ||
|
|
56a05d78bd | ||
|
|
fa5cf602f5 | ||
|
|
c94659f552 | ||
|
|
1164510004 | ||
|
|
f24867029c | ||
|
|
680ff95b8e | ||
|
|
31ea5f550f | ||
|
|
fc62af6b3a | ||
|
|
f8533e6641 | ||
|
|
87fec9d434 | ||
|
|
b1e9327a2b | ||
|
|
0aa4b47d59 | ||
|
|
b9d50fa144 | ||
|
|
3231d767d5 | ||
|
|
3f05b4bb1e | ||
|
|
9eabd956b7 | ||
|
|
eb58414600 | ||
|
|
cb83c237f4 | ||
|
|
773a13dc26 | ||
|
|
8c2f7ac083 | ||
|
|
f375c3000d | ||
|
|
ea4ce0ce1f | ||
|
|
c9fe2bab60 | ||
|
|
6c617ba28c | ||
|
|
b98c826e95 | ||
|
|
2034d4b971 | ||
|
|
f225bb0032 | ||
|
|
69b87fdb9a | ||
|
|
6f70445654 | ||
|
|
145c14ed57 | ||
|
|
b9843fe6d1 | ||
|
|
ab9757082e | ||
|
|
d6e4fb46cf | ||
|
|
a93fe5b2b2 | ||
|
|
8f9c3c8381 | ||
|
|
363f36dfae | ||
|
|
7328f4d3fd | ||
|
|
8f3b6a23f6 | ||
|
|
cc4fdd6d0c | ||
|
|
3781a099dd | ||
|
|
e4d52b2851 | ||
|
|
ac45ccbad7 | ||
|
|
1a412378db | ||
|
|
17904a6e8b | ||
|
|
9c47fdeb2f | ||
|
|
808ac2cefc | ||
|
|
aaf6dd2cd6 | ||
|
|
08f7ccff38 | ||
|
|
13720759a5 | ||
|
|
a2731da987 | ||
|
|
a8e1572955 | ||
|
|
3ca8e8a6d2 | ||
|
|
bf4a00b663 | ||
|
|
4ab041f79e | ||
|
|
f3fe1a5320 | ||
|
|
f808baafa7 | ||
|
|
1f28ff6890 | ||
|
|
640c9a49d8 | ||
|
|
5d51b439d2 | ||
|
|
9ae050f0e5 | ||
|
|
c77f91213c | ||
|
|
0f7d6a780a | ||
|
|
ab4957684f | ||
|
|
1dbaabffbc | ||
|
|
d42bfc2570 | ||
|
|
9ed45ba761 | ||
|
|
9d893eec01 | ||
|
|
52241b8e0b | ||
|
|
701a2fdcf3 | ||
|
|
995f17493e | ||
|
|
eb787adccd | ||
|
|
57e6e0092d | ||
|
|
a685e46fb6 | ||
|
|
1144988443 | ||
|
|
27dc32e2e8 | ||
|
|
6721cec73f | ||
|
|
18bbefee1c | ||
|
|
bd0357b637 | ||
|
|
49507ea377 | ||
|
|
2c0b191ef5 | ||
|
|
02ac7a4001 | ||
|
|
fbe422008a | ||
|
|
d0d21ba9a6 | ||
|
|
c78669353f | ||
|
|
afb62638a8 | ||
|
|
4a062b6d00 | ||
|
|
6590e6fae8 | ||
|
|
ab7bbd5a44 | ||
|
|
317f2d043f | ||
|
|
c21b353042 | ||
|
|
a73ef353f0 | ||
|
|
d769f6c084 | ||
|
|
ed58474c37 | ||
|
|
4c3048964d | ||
|
|
cacf14a41e | ||
|
|
e24e34619a | ||
|
|
ac1648c946 | ||
|
|
65f9cc986a | ||
|
|
252cd4901b | ||
|
|
a2b69e96b9 | ||
|
|
3a0a8810d1 | ||
|
|
b9c60125e8 | ||
|
|
cae975cb39 | ||
|
|
2f2326006d | ||
|
|
d183c11e69 | ||
|
|
653d4b1d6a | ||
|
|
d1f6bbf32f | ||
|
|
22fac87473 | ||
|
|
3003a8cb6e | ||
|
|
f4908b6315 | ||
|
|
63ca9f6f5a | ||
|
|
b9059181fd | ||
|
|
25ca751ab8 | ||
|
|
08c1def8b7 | ||
|
|
71210dd624 | ||
|
|
fee9df4c2b | ||
|
|
5d7d165be5 | ||
|
|
b5d4a678d4 | ||
|
|
8193d50da7 | ||
|
|
ffc9a8322b | ||
|
|
f28eec8be3 | ||
|
|
807c052fea | ||
|
|
45e232ef62 | ||
|
|
9accb962aa | ||
|
|
4ab3542c88 | ||
|
|
5a67ca255f | ||
|
|
c97dbf390e | ||
|
|
008a031493 | ||
|
|
b05939ec9a | ||
|
|
84e50f9003 | ||
|
|
7c917156ee | ||
|
|
6a7e9134a5 | ||
|
|
86ef33f84f | ||
|
|
6f794b7d11 | ||
|
|
febad7b1d7 | ||
|
|
48c5e26acd | ||
|
|
3f0679896b | ||
|
|
96e98f6d4c | ||
|
|
b067317595 | ||
|
|
1febd578a4 | ||
|
|
4131d8b57a | ||
|
|
36f4f1d0f3 | ||
|
|
1cd3985913 | ||
|
|
058c905432 | ||
|
|
41b775561a | ||
|
|
0ee7ac2c5e | ||
|
|
3fd6ae597d | ||
|
|
14312d225c | ||
|
|
262a03667e | ||
|
|
422decde3b | ||
|
|
6fc2b69697 | ||
|
|
594ab0e2b5 | ||
|
|
ea9ac0d2d2 | ||
|
|
9045be0c12 | ||
|
|
bc4c71a7c6 | ||
|
|
18079aaced | ||
|
|
47644f2755 | ||
|
|
43b91ea0d6 | ||
|
|
83bf63641c | ||
|
|
1e891f434d | ||
|
|
746257710b | ||
|
|
30ddfc7a28 | ||
|
|
5447bd007a | ||
|
|
f8e233e400 | ||
|
|
9c50b89d64 | ||
|
|
063b54aefe | ||
|
|
c961d6218d | ||
|
|
1176b68c6a | ||
|
|
5adac86b43 | ||
|
|
580cd510d5 | ||
|
|
d59beec354 | ||
|
|
c11322a016 | ||
|
|
fe4cdc59be | ||
|
|
35a1a04f50 | ||
|
|
6e7813f2f8 | ||
|
|
7c9728df47 | ||
|
|
da8782a9d0 | ||
|
|
d523d45124 | ||
|
|
c4d6051477 | ||
|
|
cd060c64d5 | ||
|
|
f881ada45c | ||
|
|
b9b3b75c0c | ||
|
|
37b031afcf | ||
|
|
fcc3a7f6e4 | ||
|
|
5836a6ec4b | ||
|
|
9e0ed7bc8e | ||
|
|
50c79df70f | ||
|
|
f888716d81 | ||
|
|
5274f93db7 | ||
|
|
e32ee9f02e | ||
|
|
48c936e9a9 | ||
|
|
b77bce1961 | ||
|
|
f3d277cbab | ||
|
|
afa4ee9a28 | ||
|
|
92f4442356 | ||
|
|
47b6f01c8b | ||
|
|
68225d64aa | ||
|
|
fa06040ed2 | ||
|
|
eae4bb74dd | ||
|
|
caa765ec32 | ||
|
|
e00f9611f4 | ||
|
|
1004515bda | ||
|
|
7d75e0e53c | ||
|
|
f7e3297a0f | ||
|
|
14952de2ee | ||
|
|
f98dbd249e | ||
|
|
b369b7e495 | ||
|
|
23167a0bb3 | ||
|
|
8c1195b277 | ||
|
|
6cdc1e4d37 | ||
|
|
e7a202fe4d | ||
|
|
b5dc1727d2 | ||
|
|
53f5cb6553 | ||
|
|
f797b19825 | ||
|
|
814ca99e3d | ||
|
|
c483b2ff98 | ||
|
|
2496202417 | ||
|
|
3c6fadb6f8 | ||
|
|
055e5aff2a | ||
|
|
692878b0c0 | ||
|
|
a6061ce555 | ||
|
|
2ea548850e | ||
|
|
87fc83678c | ||
|
|
d8b43a3d76 | ||
|
|
6189208fa5 | ||
|
|
daf8db71a8 | ||
|
|
c186d8b2be | ||
|
|
cd40362d47 | ||
|
|
81ad469533 | ||
|
|
bb77070aab | ||
|
|
c051ff3eac | ||
|
|
ff913333a2 | ||
|
|
ac5f7ecdea | ||
|
|
4e33e80957 | ||
|
|
bf1b60564e | ||
|
|
50ddf7913a | ||
|
|
39bb9ce118 | ||
|
|
2d8180fc9c | ||
|
|
fac51d92c5 | ||
|
|
c3fc340c09 | ||
|
|
581fb8ebfd | ||
|
|
0fa0b3b256 | ||
|
|
3b21e9fcf0 | ||
|
|
4c35c83b84 | ||
|
|
37c6a1ddf0 | ||
|
|
9c0b89b9b0 | ||
|
|
ae39ec8585 | ||
|
|
e37817285a | ||
|
|
dfe0e258cd | ||
|
|
eda23252e1 | ||
|
|
257b824d4f | ||
|
|
b469904c7f | ||
|
|
509b37eb91 | ||
|
|
9dac382fbf | ||
|
|
ddbdb54c04 | ||
|
|
181a671bfb | ||
|
|
1ce34ed907 | ||
|
|
f9e7b14f2c | ||
|
|
dad394523f | ||
|
|
1c50eb345c | ||
|
|
5c7689388d | ||
|
|
baff9b0267 | ||
|
|
fe2e6b8a80 | ||
|
|
fb74ebb4ea | ||
|
|
8784be9a14 | ||
|
|
fba3d7cb0f | ||
|
|
f953033ba7 | ||
|
|
72415be2db | ||
|
|
9653f43466 | ||
|
|
1acbd5b7d8 | ||
|
|
f0ecbd3878 | ||
|
|
9dcfe6dc39 | ||
|
|
397e4e4766 | ||
|
|
5b9ed82d29 | ||
|
|
0def04ad34 | ||
|
|
e9982bb27e | ||
|
|
18eb9d6076 | ||
|
|
e7ff018487 | ||
|
|
6ba5471bd4 | ||
|
|
ddb1d0c684 | ||
|
|
7d89cf228c | ||
|
|
5775c0a341 | ||
|
|
d750908e36 | ||
|
|
b1a648608b | ||
|
|
b7147a8bd2 | ||
|
|
82d5d1b003 | ||
|
|
f4e90df406 | ||
|
|
2cce057df1 | ||
|
|
dea2234b14 | ||
|
|
99a053bbdd | ||
|
|
b7fd6bcf7d | ||
|
|
a3b6efdbfa | ||
|
|
3a1dff6636 | ||
|
|
cf92011fb9 | ||
|
|
0106033293 | ||
|
|
4a43cc1df6 | ||
|
|
0f52b4397f | ||
|
|
9c0da733e8 | ||
|
|
de90ad8967 | ||
|
|
2f3d1ec2ef | ||
|
|
73bed3880f | ||
|
|
edebdb166e | ||
|
|
7f83be3d0d | ||
|
|
50920b1423 | ||
|
|
42b1c8c80d | ||
|
|
a5d1e9ee43 | ||
|
|
ff4dbea19d | ||
|
|
1bd58bc1c0 | ||
|
|
21b0945d08 | ||
|
|
89ef019b7c | ||
|
|
801129530e | ||
|
|
23fa5fa1c7 | ||
|
|
020277c045 | ||
|
|
f8b3c0a64c | ||
|
|
d03ae3bfe5 | ||
|
|
6f9896c2fe | ||
|
|
853cd16336 | ||
|
|
0fab210ad2 | ||
|
|
9fc0a83b83 | ||
|
|
aa8bd044c5 | ||
|
|
0201b9769c | ||
|
|
4ff6748eb4 | ||
|
|
59cb429d2d | ||
|
|
454ccb451b | ||
|
|
273fbaac68 | ||
|
|
8ff997594f | ||
|
|
616a6bec38 | ||
|
|
a6c736b8a2 | ||
|
|
5b02d63c89 | ||
|
|
c1fc8995ce | ||
|
|
34f261588f | ||
|
|
f188900379 | ||
|
|
f80d5f8c03 | ||
|
|
fcc960e9a2 | ||
|
|
db27bbb162 | ||
|
|
1bce8f6669 | ||
|
|
15fb56e607 | ||
|
|
714129c8e3 | ||
|
|
59a384b453 | ||
|
|
b5a5b7b912 | ||
|
|
a167eb4fa1 | ||
|
|
660ce3a61d | ||
|
|
edf5868c38 | ||
|
|
5588e7597c | ||
|
|
68a5fb66ff | ||
|
|
33dc9fdd76 | ||
|
|
316e1aac67 | ||
|
|
2ed3cd7f1a | ||
|
|
14cc771cbe | ||
|
|
2a8b96b680 | ||
|
|
6f923ecd17 | ||
|
|
501f21b16c | ||
|
|
f4ad673b6d | ||
|
|
37ff432f9d | ||
|
|
20283a46f9 | ||
|
|
634699c8e2 | ||
|
|
7d97f381cf | ||
|
|
7a1326ff14 | ||
|
|
ee84d4371b | ||
|
|
f8b05e0f42 | ||
|
|
a4e5b7ea37 | ||
|
|
a20443b577 | ||
|
|
e96d72d669 | ||
|
|
defb15bea1 | ||
|
|
10016d9d38 | ||
|
|
73ec486434 | ||
|
|
ccb063df06 | ||
|
|
b90a078be0 | ||
|
|
80e15dd754 | ||
|
|
de394311e0 | ||
|
|
908765e0e7 | ||
|
|
c465e594d7 | ||
|
|
0da733de9c | ||
|
|
2fc8da7a87 | ||
|
|
0bea6aba63 | ||
|
|
fe2c096166 | ||
|
|
c90619c665 | ||
|
|
952e4dab3e | ||
|
|
eecf844ca2 | ||
|
|
8952c7c9d1 | ||
|
|
c6ab63ec47 | ||
|
|
05dfccbb74 | ||
|
|
fc829b32d9 | ||
|
|
f2700822e9 | ||
|
|
21f6c07686 | ||
|
|
4bafb88720 | ||
|
|
7c61ed99ae | ||
|
|
356f7b9db6 | ||
|
|
822c8f1575 | ||
|
|
efdd4a6682 | ||
|
|
eaaf9246b7 | ||
|
|
00a6efa15e | ||
|
|
c5377fb429 | ||
|
|
0583ec0f93 | ||
|
|
12f487e223 | ||
|
|
30a8a434a1 | ||
|
|
79db997e8c | ||
|
|
137ef1f781 | ||
|
|
338afc80d5 | ||
|
|
78598df96e | ||
|
|
e737dab5ca | ||
|
|
84609a4a3b | ||
|
|
0b25a29a9c | ||
|
|
b1bfd35968 | ||
|
|
a053552fee | ||
|
|
6886faa944 | ||
|
|
c843637a6a | ||
|
|
2f78584cdb | ||
|
|
6b7491e111 | ||
|
|
2e20c680cb | ||
|
|
f33de8e911 | ||
|
|
fbc90e038c | ||
|
|
bf943ddba3 | ||
|
|
3f945e886b | ||
|
|
931d7cd039 | ||
|
|
3f5b33b060 | ||
|
|
fa63d26485 | ||
|
|
d617d029d2 | ||
|
|
98082a940c | ||
|
|
12460af0ec | ||
|
|
34eb5acee7 | ||
|
|
9ec3216ab0 | ||
|
|
92c2f8d556 | ||
|
|
eef506d8c4 | ||
|
|
7f15e2c167 | ||
|
|
03aea09ce9 | ||
|
|
2897f618a6 | ||
|
|
5f2aba6c5b | ||
|
|
21632d22ab | ||
|
|
f59f6a5486 | ||
|
|
32989f4cca | ||
|
|
b5ef793ae4 | ||
|
|
d405176367 | ||
|
|
74cb4b6590 | ||
|
|
15087251fb | ||
|
|
73d6b95339 | ||
|
|
c3032f7ba3 | ||
|
|
339e73ee3d | ||
|
|
a2c00f1cc5 | ||
|
|
6da3f87736 | ||
|
|
6ae464f33a | ||
|
|
74decb4bdc | ||
|
|
2e9272c778 | ||
|
|
6fe850e2c1 | ||
|
|
bb3360e92a | ||
|
|
f46eee96a9 | ||
|
|
3ed8870362 | ||
|
|
605f0fa24a | ||
|
|
5a4e48fa99 | ||
|
|
79e7ae4424 | ||
|
|
35071649e0 | ||
|
|
d27bb4d3fb | ||
|
|
64a18874e1 | ||
|
|
05e8c576a2 | ||
|
|
ea7c2e73ad | ||
|
|
b6f276265d | ||
|
|
3c3d3c9ec6 | ||
|
|
d66932a8a2 | ||
|
|
34141363ae | ||
|
|
3ccf7c8006 | ||
|
|
56c76f380b | ||
|
|
f36ade2959 | ||
|
|
85ad5f1d37 | ||
|
|
64fa9a6394 | ||
|
|
a00231a1c2 | ||
|
|
9914714eeb | ||
|
|
600ffa727e | ||
|
|
a7de2ceae4 | ||
|
|
972ac99b7c | ||
|
|
9bd3b417c4 | ||
|
|
a985f21d44 | ||
|
|
7c005e8f0b | ||
|
|
6e886735a3 | ||
|
|
b30dcce4bc | ||
|
|
58121d89fc | ||
|
|
6a1192172d | ||
|
|
8bd07287f8 | ||
|
|
753fd164d7 | ||
|
|
307c86fc28 | ||
|
|
72a64388b5 | ||
|
|
1210fca8e5 | ||
|
|
97ac81aa9c | ||
|
|
c8727db03b | ||
|
|
57d22fb93f | ||
|
|
f0f7da9ff0 | ||
|
|
6c4791b48d | ||
|
|
9c1217cd2c | ||
|
|
448437c342 | ||
|
|
251bf7a2b4 | ||
|
|
f1efce56aa | ||
|
|
34b82caaa8 | ||
|
|
a1b5aae958 | ||
|
|
70c42ddcff | ||
|
|
75ab2e026d | ||
|
|
f43e1ab2ff | ||
|
|
12dfee544f | ||
|
|
0ea651f1df | ||
|
|
8ed9e2e5cc | ||
|
|
a352af5b9f | ||
|
|
51a32a2bfa | ||
|
|
e6013353d2 | ||
|
|
aac190eaa9 | ||
|
|
ebba7a0327 | ||
|
|
13d993a836 | ||
|
|
f384538959 | ||
|
|
269583a6a1 | ||
|
|
0b05d39804 | ||
|
|
2ca7da06a3 | ||
|
|
4b59cee17a | ||
|
|
bf817281a5 | ||
|
|
98982b7a74 | ||
|
|
2114cbcf0b | ||
|
|
979807feee | ||
|
|
add7078f66 | ||
|
|
ab4d020212 | ||
|
|
aa251fc9ce | ||
|
|
c105a07bab | ||
|
|
09de46e5ac | ||
|
|
cc375f48c7 | ||
|
|
e59b0c0694 | ||
|
|
07fee0a810 | ||
|
|
29185eeef7 | ||
|
|
53dc21c69b | ||
|
|
b0dd79cbfd | ||
|
|
442db7fee1 | ||
|
|
be2e2577b8 | ||
|
|
c8c337cead | ||
|
|
92cba94031 | ||
|
|
c30b1b126d | ||
|
|
52403ca17e | ||
|
|
05868bc1df | ||
|
|
092bb69c41 | ||
|
|
40d946a6e3 | ||
|
|
5f1fe13530 | ||
|
|
d8bb7c3094 | ||
|
|
9c6698e87b | ||
|
|
1cac6ecedb | ||
|
|
40088cd4fe | ||
|
|
b939a27a8d | ||
|
|
73af4df96d | ||
|
|
70cd9265bf | ||
|
|
cd1b2e2841 | ||
|
|
b0a24ae4aa | ||
|
|
11e35f7b68 | ||
|
|
8f4cf6c797 | ||
|
|
2190392e05 | ||
|
|
a621c0d273 | ||
|
|
4c12703e0c | ||
|
|
da67afa51e | ||
|
|
3e14f8a0e5 | ||
|
|
a950ff9795 | ||
|
|
4132cf12e3 | ||
|
|
4f7fb40d9b | ||
|
|
c7fae5386d | ||
|
|
42802ac710 | ||
|
|
a85bda13db | ||
|
|
ecdc730de7 | ||
|
|
8927042421 | ||
|
|
32f78d465b | ||
|
|
ab3b586838 | ||
|
|
94a7e9b185 | ||
|
|
1a708da155 | ||
|
|
f94599cd29 | ||
|
|
d9d4e6c82f | ||
|
|
0796b2c0e3 | ||
|
|
bbfdbaf952 | ||
|
|
7b4fe824ec | ||
|
|
28fabadeae | ||
|
|
37495dd1c6 | ||
|
|
e5e8e2021f | ||
|
|
dfd4fbc566 | ||
|
|
08f02397b6 | ||
|
|
d3f90dcfcc | ||
|
|
ba65b89bbb | ||
|
|
3d353c7d6d | ||
|
|
bc05cc4977 | ||
|
|
cbb5811d8b | ||
|
|
6461981aa4 | ||
|
|
c260c319ee | ||
|
|
d13957cb72 | ||
|
|
4a8f82ca9b | ||
|
|
cdcc7a7172 | ||
|
|
f2ce8f266b | ||
|
|
dcde1422b7 | ||
|
|
423eca6e7d | ||
|
|
fd52320460 | ||
|
|
462608517b | ||
|
|
9586493632 | ||
|
|
b150452db3 | ||
|
|
1bca28ad12 | ||
|
|
9e121ef0c8 | ||
|
|
5f5fcc0e04 | ||
|
|
a854f0c4d4 | ||
|
|
1979143e7c | ||
|
|
32ffedccda | ||
|
|
4f7f03a28c | ||
|
|
d0074b25db | ||
|
|
8dd118bd86 | ||
|
|
fb82425d3e | ||
|
|
aa1d28835d | ||
|
|
f30df8bb57 | ||
|
|
281ec60085 | ||
|
|
09f5e6f4dc | ||
|
|
e26cd21048 | ||
|
|
1c5be92259 | ||
|
|
6e99eed417 | ||
|
|
92a085550e | ||
|
|
c4a0ec844c | ||
|
|
3e3b996963 | ||
|
|
36e99ac531 | ||
|
|
7a26d309b1 | ||
|
|
ca55d1f315 | ||
|
|
41fd0ed467 | ||
|
|
bcb44b7b31 | ||
|
|
1ab1154010 | ||
|
|
6b85a6fd78 | ||
|
|
8f067a5ed2 | ||
|
|
db1ba30df7 | ||
|
|
1952ebf7c4 | ||
|
|
70481953fd | ||
|
|
870775e863 | ||
|
|
54383a9a0c | ||
|
|
510a21195a | ||
|
|
3b5a583903 | ||
|
|
a9e05c77d1 | ||
|
|
3418db1dcd | ||
|
|
d94896cf10 | ||
|
|
eb8871a4bd | ||
|
|
389dd12ab4 | ||
|
|
4a54edd8bb | ||
|
|
1d4803cff0 | ||
|
|
6fc972ab1e | ||
|
|
66eebd1ac3 | ||
|
|
568832c5af | ||
|
|
4ff7b0f49b | ||
|
|
c12aa0e8ce | ||
|
|
61a655f199 | ||
|
|
88e9161e57 | ||
|
|
10adc57b3f | ||
|
|
62ae02bdd1 | ||
|
|
dca503bcbd | ||
|
|
bc21862661 | ||
|
|
1e06f3f5f4 | ||
|
|
00802d035a | ||
|
|
edcef7d078 | ||
|
|
899a44a735 | ||
|
|
6a95963c89 | ||
|
|
a35bf497be | ||
|
|
9b42b33648 | ||
|
|
053868f593 | ||
|
|
1adb7b286c | ||
|
|
30c19d525e | ||
|
|
8161a0943d | ||
|
|
a8e3f731b7 | ||
|
|
0cb68b86fc | ||
|
|
723be4f612 | ||
|
|
070af40487 | ||
|
|
0a58404584 | ||
|
|
c201f4c63e | ||
|
|
317b5e6d86 | ||
|
|
38ddc88b20 | ||
|
|
7ad72ba905 | ||
|
|
36e8af05a2 | ||
|
|
2bfded3c5f | ||
|
|
842a59535d | ||
|
|
d4e1a715eb | ||
|
|
954c0e9fae | ||
|
|
f6a3b53fb5 | ||
|
|
01d47fb280 | ||
|
|
dfcb82d233 | ||
|
|
83346a29aa | ||
|
|
317c5ba88d | ||
|
|
caa26f594e | ||
|
|
aa9a92d2e0 | ||
|
|
4f227ae92e | ||
|
|
cd0256d40d | ||
|
|
2ccc19185c | ||
|
|
b4d595e561 | ||
|
|
88a132b878 | ||
|
|
b5726a8d5a | ||
|
|
b7f4a5c198 | ||
|
|
1d9ad9be33 | ||
|
|
2b7a26dabd | ||
|
|
a233570777 | ||
|
|
6fae264222 | ||
|
|
8699d49f93 | ||
|
|
c4ce3293a2 | ||
|
|
dbafc8c9db | ||
|
|
6c6c3a5081 | ||
|
|
d420cb38d1 | ||
|
|
b55f8215ec | ||
|
|
08caf4bbde | ||
|
|
59c928acc2 | ||
|
|
e38e8c740f | ||
|
|
4ceab4abc7 | ||
|
|
8ff48c126a | ||
|
|
6da3af5e89 | ||
|
|
77c362af8d | ||
|
|
2cf0dc2cb2 | ||
|
|
bdb67d4909 | ||
|
|
4fe72ebf69 | ||
|
|
49fdf8427a | ||
|
|
534bc83173 | ||
|
|
87f6d7da11 | ||
|
|
cdd341af64 | ||
|
|
f70252f013 | ||
|
|
ed989ecc8d | ||
|
|
a147015e96 | ||
|
|
8cf7fb7f80 | ||
|
|
c317149a08 | ||
|
|
ff8b25a50a | ||
|
|
afa539368f | ||
|
|
dc427d5a2c | ||
|
|
a87b5f757d | ||
|
|
4db57cc0bb | ||
|
|
44f0242157 | ||
|
|
e5b3f27a30 | ||
|
|
a15984b663 | ||
|
|
f7fecdc6de | ||
|
|
cabefa4fff | ||
|
|
1ec97e5199 | ||
|
|
458d15063d | ||
|
|
e8786b0747 | ||
|
|
d0bcd1d87c | ||
|
|
c8bd9fd6cc | ||
|
|
4c59e48cc2 | ||
|
|
85a463faab | ||
|
|
feca2871eb | ||
|
|
144c703c7b | ||
|
|
ae6cae0771 | ||
|
|
2b99b64ec5 | ||
|
|
ffe1407217 | ||
|
|
7d8519f5f0 | ||
|
|
b79f04493d | ||
|
|
7e7d9457ea | ||
|
|
07fdf6491c | ||
|
|
fb4bb7f53e | ||
|
|
1da1849de6 | ||
|
|
98dccb8641 | ||
|
|
8a38991270 | ||
|
|
2fe58461d5 | ||
|
|
16cd27282f | ||
|
|
e081a5c5a0 | ||
|
|
0ea01f24a8 | ||
|
|
882980ada7 | ||
|
|
66f7a2be15 | ||
|
|
908b2d151f | ||
|
|
d3bc52278d | ||
|
|
012d1378d4 | ||
|
|
4da31291d2 | ||
|
|
c1e94e61d0 | ||
|
|
ab79348af5 | ||
|
|
d83e24572a | ||
|
|
1ffcea1952 | ||
|
|
35f40b7312 | ||
|
|
b76449d151 | ||
|
|
15546dd84e | ||
|
|
ca3405afc5 | ||
|
|
36ebfc747a | ||
|
|
bc328cbed7 | ||
|
|
7ae81a2195 | ||
|
|
cf98a16db0 | ||
|
|
f813b4c58f | ||
|
|
c5635f9c89 | ||
|
|
d932653c7f | ||
|
|
39aca0f038 | ||
|
|
9943b9a226 | ||
|
|
3bb20dbf2e | ||
|
|
7a8b3c419b | ||
|
|
60e7c6d150 | ||
|
|
a9aaa5ad73 | ||
|
|
6c1fee736b | ||
|
|
f81d2595f9 | ||
|
|
1896bd0920 | ||
|
|
183f32390c | ||
|
|
455948ad14 | ||
|
|
0918063c55 | ||
|
|
22c001c8a6 | ||
|
|
d15b0bf4c4 | ||
|
|
01a910fedc | ||
|
|
8c05067f88 | ||
|
|
f67563e9ee | ||
|
|
d0841919ea | ||
|
|
a23e60ab69 | ||
|
|
ab30297d02 | ||
|
|
3362d6bc56 | ||
|
|
e5f391ab53 | ||
|
|
19a5e425cf | ||
|
|
69d0e82453 | ||
|
|
f84737d7d4 | ||
|
|
0ee0ea554d | ||
|
|
40845578c6 | ||
|
|
f4e22e49b6 | ||
|
|
8a2af9b818 | ||
|
|
255901ca7c | ||
|
|
52644bb28a | ||
|
|
7cad3c89d3 | ||
|
|
bcdddfe4e8 | ||
|
|
c4ca1444f9 | ||
|
|
f5565d4814 | ||
|
|
f20ee6b482 | ||
|
|
6c8d084664 | ||
|
|
412e7bcdae | ||
|
|
3b65fc0107 | ||
|
|
5792a16222 | ||
|
|
6a9f451091 | ||
|
|
a559d59d80 | ||
|
|
de20a8930e | ||
|
|
9343b0378d | ||
|
|
3fabd2ea1b | ||
|
|
5de69b288f | ||
|
|
5eea02b17a | ||
|
|
5c0812ab6f | ||
|
|
5af3fe93f2 | ||
|
|
ee400df930 | ||
|
|
09b8401324 | ||
|
|
be1fb13162 | ||
|
|
aa83dc15e2 | ||
|
|
7c482064df | ||
|
|
c93a3ce227 | ||
|
|
03c10ef885 | ||
|
|
cc1ed98fc4 | ||
|
|
ebf0bd5fc9 | ||
|
|
be48caf59f | ||
|
|
c0cf0cb802 | ||
|
|
3d60d0dfa5 | ||
|
|
b68df56b03 | ||
|
|
6fbba13ab3 | ||
|
|
311624beaa | ||
|
|
ca5099f53b | ||
|
|
5877e5e11a | ||
|
|
69eb62c09f | ||
|
|
ec36e28368 | ||
|
|
4da56b65ab | ||
|
|
71febeb71f | ||
|
|
a292aedd9c | ||
|
|
b58e605b99 | ||
|
|
7776803890 | ||
|
|
cd23ab9955 | ||
|
|
aa32459bc2 | ||
|
|
41a0995db7 | ||
|
|
3f9f0679ec | ||
|
|
d1145ed3fb | ||
|
|
f074c1eaff | ||
|
|
ea566fff24 | ||
|
|
b8cb5e0367 | ||
|
|
7a87c900ee | ||
|
|
e95170e9fd | ||
|
|
d0dead0a08 | ||
|
|
71d718a6e2 | ||
|
|
ad94f99d57 | ||
|
|
bcaaedf2ff | ||
|
|
3dc3d363fd | ||
|
|
690a6e1a59 | ||
|
|
eacc46da6d | ||
|
|
0903d5541b | ||
|
|
c19a2e5b45 | ||
|
|
10a764c4f2 | ||
|
|
0a9f705308 | ||
|
|
dabd680d6b | ||
|
|
4522b02925 | ||
|
|
fabaf5cc04 | ||
|
|
f7888886e9 | ||
|
|
dfd5413b10 | ||
|
|
1b341f8000 | ||
|
|
af9b864b83 | ||
|
|
93e424de4c | ||
|
|
e7a0ab76c3 | ||
|
|
d8b90721b3 | ||
|
|
cb5c1bd24d | ||
|
|
af371249f9 | ||
|
|
0dd7fb7361 | ||
|
|
22fd2aed02 | ||
|
|
c433167950 | ||
|
|
e0ffcda32e | ||
|
|
d34ba416a6 | ||
|
|
3d15ee6d74 | ||
|
|
48cf56b69a | ||
|
|
406ee43ae5 | ||
|
|
488165ec73 | ||
|
|
545c39356a | ||
|
|
42db1378e0 | ||
|
|
c35b51a268 | ||
|
|
df1e52e394 | ||
|
|
246b04f904 | ||
|
|
333f9101a0 | ||
|
|
24acea7261 | ||
|
|
08ca72399b | ||
|
|
e29e3416db | ||
|
|
83ce40191c | ||
|
|
7c06b5cc22 | ||
|
|
3b8e478a6a | ||
|
|
9498c78576 | ||
|
|
746e203f7b | ||
|
|
a7d7f31e76 | ||
|
|
16847fdb41 | ||
|
|
28e7f0f74f | ||
|
|
80d757b371 | ||
|
|
5bdf0cd136 | ||
|
|
e498503428 | ||
|
|
26f70a5fd7 | ||
|
|
ef46b23250 | ||
|
|
39ccf1526f | ||
|
|
12889a9509 | ||
|
|
c24935b519 | ||
|
|
3693473f40 | ||
|
|
2cb83cf19d | ||
|
|
8c02a7bd6b | ||
|
|
8ee0e5d11f | ||
|
|
c87b425639 | ||
|
|
e320bd025f | ||
|
|
d465c445fc | ||
|
|
dc30b9d37b | ||
|
|
37cfe2a3cb | ||
|
|
26abce647d | ||
|
|
ca84ef38f8 | ||
|
|
78fe588330 | ||
|
|
ddf72fa53f | ||
|
|
3a6e8a535c | ||
|
|
d882af9f94 | ||
|
|
48539c851e | ||
|
|
a701bba839 | ||
|
|
c7ba60162b | ||
|
|
d4e98cd9bc | ||
|
|
05ec24e7b8 | ||
|
|
e44ef7f823 | ||
|
|
04ff97cd72 | ||
|
|
8e6fdf62fb | ||
|
|
74d7a946a7 | ||
|
|
2b58b6b5d7 | ||
|
|
7ee290cc57 | ||
|
|
3868a796a4 | ||
|
|
b99ea80b58 | ||
|
|
ce2ae31950 | ||
|
|
f355f36d09 | ||
|
|
5aa11b4578 | ||
|
|
c48da9b5cf | ||
|
|
12d65bfdfa | ||
|
|
cba471b09b | ||
|
|
f1b897b3de | ||
|
|
0589134006 | ||
|
|
6ed36e01ac | ||
|
|
25d93d1041 | ||
|
|
e28c9b3309 | ||
|
|
5335a6b636 | ||
|
|
f83d5f4280 | ||
|
|
28ec6b4d60 | ||
|
|
27a0ef7ee8 | ||
|
|
5eab5dc47b | ||
|
|
2ec5bc77d7 | ||
|
|
2f3587ee8a | ||
|
|
9ece45caa5 | ||
|
|
f163ceffd0 | ||
|
|
31de9faaf2 | ||
|
|
d302c82c82 | ||
|
|
6fa5e681aa | ||
|
|
e631940d9e | ||
|
|
e22e20fa9d | ||
|
|
79c8556927 | ||
|
|
7d16307db4 | ||
|
|
1626982a3a | ||
|
|
6beb9be42c | ||
|
|
bf41eb824d | ||
|
|
38f4cfb7a2 | ||
|
|
aca9d3965d | ||
|
|
4cc06ad779 | ||
|
|
79d56f779d | ||
|
|
280f9befae | ||
|
|
201f50b121 | ||
|
|
1cfa523f49 | ||
|
|
548ee47aa7 | ||
|
|
55448de92a | ||
|
|
b63471ebe9 | ||
|
|
33395d530d | ||
|
|
fcd3af30ec | ||
|
|
e334107c7d | ||
|
|
f5eb54e595 | ||
|
|
56c3dd3652 | ||
|
|
6ddd458402 | ||
|
|
ee328667d0 | ||
|
|
bc2bc1f2ac | ||
|
|
3dee75603c | ||
|
|
c7e3ed096f | ||
|
|
62fe5cdbaa | ||
|
|
10f66fa78f | ||
|
|
0cbc493113 | ||
|
|
c30c9fbca9 | ||
|
|
f4fd3f48f0 | ||
|
|
4ee9e48e7c | ||
|
|
55fab0493d | ||
|
|
22c4e605cf | ||
|
|
67737b1556 | ||
|
|
cdfd3449ed | ||
|
|
fab1062c0b | ||
|
|
766b9d5270 | ||
|
|
023fa2b2cc | ||
|
|
8910351f5c | ||
|
|
1b42e3015e | ||
|
|
4e9e18d4c0 | ||
|
|
ba5b127684 | ||
|
|
225e7a6a32 | ||
|
|
7e9963ae05 | ||
|
|
b7c0f3ea95 | ||
|
|
a8e2610d7d | ||
|
|
b934ace1fc | ||
|
|
82cbfc9905 | ||
|
|
9f294e3565 | ||
|
|
68775182f0 | ||
|
|
dc3e172eb4 | ||
|
|
5bd128ba85 | ||
|
|
1a8579cd6d | ||
|
|
5921bb0589 | ||
|
|
c8e894e8f8 | ||
|
|
141f22bedf | ||
|
|
d9844350fe | ||
|
|
2d9d11a89c | ||
|
|
4fa92198a0 | ||
|
|
662430d5db | ||
|
|
139b19f9ac | ||
|
|
6e50e2412e | ||
|
|
005e14a060 | ||
|
|
c8c9e0a7e7 | ||
|
|
0f65cb2b79 | ||
|
|
85094fc74d | ||
|
|
5227dc679d | ||
|
|
77c510c364 | ||
|
|
2d2ad8b237 | ||
|
|
6ea00a4f7c | ||
|
|
1bb0530c69 | ||
|
|
b36f644628 | ||
|
|
2dee9c8d74 | ||
|
|
9c6eb7736f | ||
|
|
e86dfcf55c | ||
|
|
d6311aefb7 | ||
|
|
8e18f2c5d2 | ||
|
|
0644bfe27c | ||
|
|
0b285845d1 | ||
|
|
d3ff4bf75e | ||
|
|
aa4ac9fa05 | ||
|
|
0339a5ad01 | ||
|
|
bffb217d37 | ||
|
|
40f85e5ca3 | ||
|
|
2dba2f4a95 | ||
|
|
70542fb730 | ||
|
|
cd742979b1 | ||
|
|
736d58e35f | ||
|
|
64138bd424 | ||
|
|
f51d74fa68 | ||
|
|
78c6ce842e | ||
|
|
ad79df9b74 | ||
|
|
b4763290de | ||
|
|
8264c76642 | ||
|
|
6edd6c8f03 | ||
|
|
f1bc87133d | ||
|
|
dd7a13930f | ||
|
|
8ad10149ab | ||
|
|
0731064375 | ||
|
|
e194461420 | ||
|
|
b97b23647e | ||
|
|
7bdeceff36 | ||
|
|
45c69fa638 | ||
|
|
d7f3869959 | ||
|
|
cdc36dd171 | ||
|
|
ed16914715 | ||
|
|
a1d66d98dc | ||
|
|
dd3295da60 | ||
|
|
282aaa5cf0 | ||
|
|
462a939438 | ||
|
|
030f902ca5 | ||
|
|
58093941c0 | ||
|
|
005271d24b | ||
|
|
2b263bcb5d | ||
|
|
79d0f47ee7 | ||
|
|
1ebb18ae57 | ||
|
|
fad4875f11 | ||
|
|
42d1205260 | ||
|
|
3d90340446 | ||
|
|
d68e1fd308 | ||
|
|
217d5df276 | ||
|
|
d1ccf83236 | ||
|
|
28968144d6 | ||
|
|
4c5cfd51d7 | ||
|
|
b6044910ec | ||
|
|
5aa90eb086 | ||
|
|
ce58486850 | ||
|
|
7e63978a3f | ||
|
|
c9674f84e8 | ||
|
|
0697274695 | ||
|
|
654d1f939e | ||
|
|
477b876a1f | ||
|
|
523cf21b4a | ||
|
|
df0a5cf52f | ||
|
|
caa6337952 | ||
|
|
700a3f9f84 | ||
|
|
f9b13791de | ||
|
|
7886318341 | ||
|
|
3c13901695 | ||
|
|
573632012e | ||
|
|
002455da07 | ||
|
|
e9e6ac64bd | ||
|
|
36ab8ae19c | ||
|
|
df366da721 | ||
|
|
67dc761344 | ||
|
|
0b4552a8e7 | ||
|
|
2345b41a74 | ||
|
|
141e395489 | ||
|
|
91139672cc | ||
|
|
3d178c8eb6 | ||
|
|
c9bd45ba13 | ||
|
|
db9c288050 | ||
|
|
f1cb8f2f25 | ||
|
|
7ec2c09249 | ||
|
|
354bfcea15 | ||
|
|
891d7c134c | ||
|
|
eb5822bc7c | ||
|
|
154d70e4e2 | ||
|
|
c4a0fe0234 | ||
|
|
0011beb654 | ||
|
|
419251ed35 | ||
|
|
bd850d8158 | ||
|
|
d7c7f27207 | ||
|
|
0fb95297a2 | ||
|
|
cf1f43dc9d | ||
|
|
d6935847b4 | ||
|
|
0715ba3e5e | ||
|
|
efbbb31370 | ||
|
|
207c1a20ee | ||
|
|
579bc1c2c8 | ||
|
|
bd4cb549d6 | ||
|
|
fd392a2422 | ||
|
|
13864853a8 | ||
|
|
d86b2c4fb4 | ||
|
|
a1f103576a | ||
|
|
aa766e3e18 | ||
|
|
ee0e4d2b69 | ||
|
|
8eb3e48bc7 | ||
|
|
384292b647 | ||
|
|
1bb1ddcd29 | ||
|
|
24324939e1 | ||
|
|
2436cda7ac | ||
|
|
75b83af08f | ||
|
|
82d8e3c2b6 | ||
|
|
c351f46e47 | ||
|
|
fb9e8d2166 | ||
|
|
3668cb6dd4 | ||
|
|
93f3e30cac | ||
|
|
52af346ec8 | ||
|
|
8e0bba4f99 | ||
|
|
4cc61d10ff | ||
|
|
8deb6d9246 | ||
|
|
20eb6df9e8 | ||
|
|
a921eeb5e2 | ||
|
|
f3f34e1835 | ||
|
|
4a29d459da | ||
|
|
0f867a3484 | ||
|
|
6eeddaa564 | ||
|
|
d80458ef81 | ||
|
|
ad15df7222 | ||
|
|
98f7febed1 | ||
|
|
4f04eaec3a | ||
|
|
5a2b9b1f44 | ||
|
|
721b37a08e | ||
|
|
b3d494d4c8 | ||
|
|
85ec70e92b | ||
|
|
e2f0ff9e88 | ||
|
|
0dbd7d0e17 | ||
|
|
8cdaa044e1 | ||
|
|
712a420217 | ||
|
|
b38dc70c71 | ||
|
|
72d9fcdcb4 | ||
|
|
5a6981e7af | ||
|
|
79d29db18b | ||
|
|
4f6a52503d | ||
|
|
1b5c40dd1f | ||
|
|
700b77c450 | ||
|
|
8449017592 | ||
|
|
5cf3425b93 | ||
|
|
aa13a80d83 | ||
|
|
9e2ef543ed | ||
|
|
2aabb387b1 | ||
|
|
f972863f49 | ||
|
|
f00320c8b9 | ||
|
|
1f57cf08a7 | ||
|
|
0ff5ff5dbe | ||
|
|
5ba19144d5 | ||
|
|
c9ba856c52 | ||
|
|
a30ceefa6b | ||
|
|
31e2a8b8e9 | ||
|
|
9b4150509c | ||
|
|
c68cd7d19a | ||
|
|
85382dc2e0 | ||
|
|
7315a0ecec | ||
|
|
411bd55cd4 | ||
|
|
9c0141e84e | ||
|
|
ca5d0496ee | ||
|
|
24b9bc1e55 | ||
|
|
cf1e167430 | ||
|
|
a1afd2328d | ||
|
|
ada9bfcae8 | ||
|
|
f88588db90 | ||
|
|
5930dc6354 | ||
|
|
9c64da4323 | ||
|
|
c863ea4aa1 | ||
|
|
e1432f4339 | ||
|
|
890c527ae5 | ||
|
|
1fa8b74595 | ||
|
|
5559ad1238 | ||
|
|
bd8f5e9bfd | ||
|
|
29f6283eab | ||
|
|
396f53d20e | ||
|
|
4a69de1f30 | ||
|
|
bd6e2d6ca4 | ||
|
|
fc78e42a78 | ||
|
|
9d1906d333 | ||
|
|
4a3f50cef7 | ||
|
|
4751e4b94e | ||
|
|
1b7f4f31ca | ||
|
|
ca01604b43 | ||
|
|
93f9a0c39c | ||
|
|
93977316ce | ||
|
|
7e49bdf5a8 | ||
|
|
df0bc7bbc4 | ||
|
|
63b50ab9b1 | ||
|
|
c0beef7572 | ||
|
|
5ec448861d | ||
|
|
7d4326a397 | ||
|
|
cc43b94864 | ||
|
|
57a31828f8 | ||
|
|
0c7fccdcbe | ||
|
|
a1fcd3c5b6 | ||
|
|
c4048f8f22 | ||
|
|
15dc30edf6 | ||
|
|
4254aa5f5a | ||
|
|
09ff042986 | ||
|
|
924ecce2c3 | ||
|
|
69daede583 | ||
|
|
a6e8d61e8e | ||
|
|
65a7fa320a | ||
|
|
be5e6d55fc | ||
|
|
b0c01369c5 | ||
|
|
f6772bb896 | ||
|
|
b21fa2daa0 | ||
|
|
730d4857ba | ||
|
|
0e1c12e65f | ||
|
|
37b125ca98 | ||
|
|
2e9303cb6c | ||
|
|
7db38c80fc | ||
|
|
aad824a562 | ||
|
|
f0087c93b8 | ||
|
|
ae7e7e9656 | ||
|
|
e008473e47 | ||
|
|
79313aa268 | ||
|
|
1c35d4b26b | ||
|
|
a56f657fb1 | ||
|
|
f5db9950f8 | ||
|
|
e5931e264b | ||
|
|
9485e8cfee | ||
|
|
22b139d9f8 | ||
|
|
2a600b25e7 | ||
|
|
393891d6ea | ||
|
|
1bbd056797 | ||
|
|
add5bb47d5 | ||
|
|
305f8d6982 | ||
|
|
93851a9a0f | ||
|
|
8a184e9d30 | ||
|
|
3a66d7c453 | ||
|
|
00a479de6f | ||
|
|
32f9f8fcce | ||
|
|
e4208441b3 | ||
|
|
ee5ebe2e81 | ||
|
|
a71b681e80 | ||
|
|
2cbc62d6c0 | ||
|
|
cc125f5fd7 | ||
|
|
7f9c8a1935 | ||
|
|
3c54d14460 | ||
|
|
c5b39a5100 | ||
|
|
7888c1c614 | ||
|
|
b43315c36d | ||
|
|
fbd6417c8a | ||
|
|
850ad1c0fb | ||
|
|
dbe35bfed1 | ||
|
|
f1caae126e | ||
|
|
bad6a40a12 | ||
|
|
5bc194e1f0 | ||
|
|
d315ff2b96 | ||
|
|
163b45cf37 | ||
|
|
87c718f549 | ||
|
|
e04678f33c | ||
|
|
bbdf75bdfa | ||
|
|
5c0cf9f5d7 | ||
|
|
8a61ec4b4e | ||
|
|
874a6e86fd | ||
|
|
ef4bec1c6d | ||
|
|
4da99d14e6 | ||
|
|
cc80191cd1 | ||
|
|
3cdb3f0d54 | ||
|
|
437b957be1 | ||
|
|
9f17e4ee2c | ||
|
|
509c3dc715 | ||
|
|
4051f04e66 | ||
|
|
d503c5d83d | ||
|
|
02a37d670c | ||
|
|
a7deca1df5 | ||
|
|
1bec6c2aae | ||
|
|
a66825c71f | ||
|
|
0fb110a4af | ||
|
|
167c02d773 | ||
|
|
0c50a7437b | ||
|
|
5339ec66b7 | ||
|
|
2371dcf694 | ||
|
|
65bc194c42 | ||
|
|
99ee38cea3 | ||
|
|
5d8a51c307 | ||
|
|
6325635fce | ||
|
|
7612e47aee | ||
|
|
d06b9401ea | ||
|
|
ecb1552c10 | ||
|
|
9f066d01b1 | ||
|
|
673ae1edc0 | ||
|
|
b25b31e4a0 | ||
|
|
f65fde8bb7 | ||
|
|
0a04b135ca | ||
|
|
88d27fe649 | ||
|
|
5d166dc8cb | ||
|
|
8f81c97aaa | ||
|
|
b5f35261a0 | ||
|
|
f55e24cd12 | ||
|
|
efc0b60d41 | ||
|
|
f3bc726001 | ||
|
|
60e797ccc4 | ||
|
|
20b553461b | ||
|
|
0bff097afb | ||
|
|
b0cb6d6d4c | ||
|
|
b345c7cf46 | ||
|
|
56e2082205 | ||
|
|
fe2d8f1ea0 | ||
|
|
e16bbc660d | ||
|
|
2676f24e0a | ||
|
|
b8e6fcfeae | ||
|
|
b5f18561ab | ||
|
|
22c3ec2d63 | ||
|
|
b678daa744 | ||
|
|
e1433ebb41 | ||
|
|
1b83742e3e | ||
|
|
90cca93951 | ||
|
|
4e37290a7f | ||
|
|
7d3146ed8d | ||
|
|
0a1af65a4c | ||
|
|
4de9ac133a | ||
|
|
60c7bfe9a7 | ||
|
|
9bafc4fea1 | ||
|
|
7387f2e490 | ||
|
|
93b4f3fac8 | ||
|
|
fdeeb73587 | ||
|
|
6062930f9a | ||
|
|
867b838053 | ||
|
|
58dc282ca0 | ||
|
|
d7ee7cb88f | ||
|
|
da9c792ca2 | ||
|
|
8171cd51c4 | ||
|
|
74b10a42ee | ||
|
|
f14ef22bb6 | ||
|
|
e8c9b0806a | ||
|
|
36c4d01ef8 | ||
|
|
e51d403420 | ||
|
|
f54615ed46 | ||
|
|
4c1b6f3059 | ||
|
|
ada641090f | ||
|
|
eb6c8a3521 | ||
|
|
3a021a87a1 | ||
|
|
5100339604 | ||
|
|
8448e3970b | ||
|
|
dbed679904 | ||
|
|
acb5340ffb | ||
|
|
6a01cd56ca | ||
|
|
ae38705bed | ||
|
|
db083c43dd | ||
|
|
c5435596ad | ||
|
|
03130e1217 | ||
|
|
2ca6acc1e9 | ||
|
|
d8f68eb118 | ||
|
|
97697b93ed | ||
|
|
152b484eb5 | ||
|
|
97de8c1cc2 | ||
|
|
6cf46b1635 | ||
|
|
1665cb4282 | ||
|
|
1113081aab | ||
|
|
39bc3cb532 | ||
|
|
0a0a0776e4 | ||
|
|
59d199a148 | ||
|
|
8b9d13491f | ||
|
|
4dcd2ceb01 | ||
|
|
6004ba6554 | ||
|
|
f1847d4501 | ||
|
|
e63ff167a7 | ||
|
|
a27186e34f | ||
|
|
2a8904f844 | ||
|
|
59fc72d37e | ||
|
|
34e3683ded | ||
|
|
13760b1bdd | ||
|
|
8a252774ce | ||
|
|
963f9fdf40 | ||
|
|
b4a2b96e32 | ||
|
|
299a2457cd | ||
|
|
3de4707c98 | ||
|
|
603ec65e91 | ||
|
|
cdcffcd31e | ||
|
|
f8a1c7c8a1 | ||
|
|
5d64568f3e | ||
|
|
374fbad06d | ||
|
|
aa31336c64 | ||
|
|
135ba68ff5 | ||
|
|
d3ee81bb5a | ||
|
|
e0b585779d | ||
|
|
4729bea1a2 | ||
|
|
e1393f9780 | ||
|
|
ad7e66cdae | ||
|
|
2f09ef2970 | ||
|
|
6ea2c08ecb | ||
|
|
b82f1edd63 | ||
|
|
1685e7cea4 | ||
|
|
287d8ca367 | ||
|
|
6397b8c1ef | ||
|
|
89eedd59a8 | ||
|
|
af65a81d5b | ||
|
|
03e2f25adb | ||
|
|
aa9093bcf6 | ||
|
|
dc4f347ae1 | ||
|
|
23599814a3 | ||
|
|
89ce1a5159 | ||
|
|
22a4ef42fc | ||
|
|
358ba395ac | ||
|
|
e7d5ea8a6c | ||
|
|
a36711e640 | ||
|
|
2b6df412b7 | ||
|
|
6fabff4769 | ||
|
|
6af86152e6 | ||
|
|
06d97c78c8 | ||
|
|
da31fffb16 | ||
|
|
c97e3ec7ae | ||
|
|
09b3433e32 | ||
|
|
323e84375b | ||
|
|
3b67a6a222 | ||
|
|
da3d5375b8 | ||
|
|
38bd0d1aec | ||
|
|
59bd029e46 | ||
|
|
1dbf0ad976 | ||
|
|
3b4c095b49 | ||
|
|
2e155bdeda | ||
|
|
8305fd0451 | ||
|
|
7477667df1 | ||
|
|
a066d7ddcb | ||
|
|
a5c742cee5 | ||
|
|
cac142b134 | ||
|
|
da7ae2b0ab | ||
|
|
052c9aca15 | ||
|
|
e4fecb48e3 | ||
|
|
b0e975bfce | ||
|
|
d4664507f1 | ||
|
|
21f3f859b9 | ||
|
|
54be4c5e2c | ||
|
|
45cdbe0a18 | ||
|
|
6c76e9728e | ||
|
|
0a6a3f9ab7 | ||
|
|
bad8ab232d | ||
|
|
91a814d295 | ||
|
|
7205cf8ce1 | ||
|
|
6fe6a33da3 | ||
|
|
9b59fc1c94 | ||
|
|
e7834b885a | ||
|
|
4ec6691ea9 | ||
|
|
6b9b08da30 | ||
|
|
184307816f | ||
|
|
c1d592b72c | ||
|
|
2d23251da9 | ||
|
|
5b01e9ec97 | ||
|
|
8526230b59 | ||
|
|
9d04a4c4f0 | ||
|
|
ae93f2b936 | ||
|
|
fcaecf4782 | ||
|
|
0b28db7fae | ||
|
|
87715d6231 | ||
|
|
3228c4f41a | ||
|
|
ce5b4089b5 | ||
|
|
0903aa4596 | ||
|
|
26a45c8dc0 | ||
|
|
62c908a905 | ||
|
|
eb8c2d9053 | ||
|
|
1e2e4ba3ad | ||
|
|
aaf4b1a399 | ||
|
|
a5e3d7a94b | ||
|
|
58497ed596 | ||
|
|
ae81fbdffe | ||
|
|
fc0705e87c | ||
|
|
c489d806dc | ||
|
|
f3ecdc5af4 | ||
|
|
6fecb4bf3e | ||
|
|
867ac5df67 | ||
|
|
1ff3c3be84 | ||
|
|
1cb9de07a6 | ||
|
|
43ca50ebbe | ||
|
|
b70b730cb9 | ||
|
|
dbc1a9cf82 | ||
|
|
c95a991cb3 | ||
|
|
c320e9d583 | ||
|
|
e507afc3d5 | ||
|
|
bd77fd92bb | ||
|
|
882a988143 | ||
|
|
0b3e33e226 | ||
|
|
524f5d45ec | ||
|
|
85887ad1cf | ||
|
|
d94b6635af | ||
|
|
3c7a483f5c | ||
|
|
dc5c3a3939 | ||
|
|
9185c94a2d | ||
|
|
70269c8196 | ||
|
|
51a589f5a6 | ||
|
|
cf89b565a6 | ||
|
|
7d24c5fda2 | ||
|
|
0bc85d27f8 | ||
|
|
43c2ca2d7d | ||
|
|
e3e21a251f | ||
|
|
267417d6a8 | ||
|
|
e8256f0ad7 | ||
|
|
458e6da700 | ||
|
|
a906fa178a | ||
|
|
4588c5a19a | ||
|
|
23404decea | ||
|
|
e873574e8c | ||
|
|
d09bff9039 | ||
|
|
c0da52aac8 | ||
|
|
7e2f653bc7 | ||
|
|
c831369974 | ||
|
|
f0a13b2a0d | ||
|
|
b68987dcde | ||
|
|
c1f77eeaea | ||
|
|
9b5a0a54cf | ||
|
|
14f3a68215 | ||
|
|
bf25b9f443 | ||
|
|
3435aaea45 | ||
|
|
9fc91b7aa1 | ||
|
|
04eefb8480 | ||
|
|
8789be7671 | ||
|
|
fe46410c31 | ||
|
|
aef644bd21 | ||
|
|
df4d5ea8a6 | ||
|
|
c34c3ac845 | ||
|
|
4bb656b704 | ||
|
|
a94720878b | ||
|
|
59a2042a31 | ||
|
|
f680c15283 | ||
|
|
f11785001c | ||
|
|
106fe4854f | ||
|
|
44d377b810 | ||
|
|
a2bf3e056d | ||
|
|
2d722e26de | ||
|
|
182e079d25 | ||
|
|
318af9b418 | ||
|
|
0bcda4a2eb | ||
|
|
0dc0e03c4c | ||
|
|
0db2d07a1a | ||
|
|
3d52095765 | ||
|
|
0912cec0e5 | ||
|
|
180ba33ac8 | ||
|
|
04f4454974 | ||
|
|
91285baea5 | ||
|
|
875d80aa72 | ||
|
|
5e19fdb492 | ||
|
|
bddcc6491a | ||
|
|
d37e18fdcf | ||
|
|
af8d12124a | ||
|
|
5e34823e7c | ||
|
|
f44eaae88a | ||
|
|
3cc69112c1 | ||
|
|
205d4232b9 | ||
|
|
3c6a06a327 | ||
|
|
057b533a39 | ||
|
|
b774b91b92 | ||
|
|
7dc923a292 | ||
|
|
ef2094f817 | ||
|
|
f0f791d226 | ||
|
|
7ca261e33e | ||
|
|
228aac2d48 | ||
|
|
d0b744387b | ||
|
|
7cadb9012a | ||
|
|
0c222c4e8c | ||
|
|
83052352dc | ||
|
|
73516c0c97 | ||
|
|
b90e4057ba | ||
|
|
67f253830f | ||
|
|
59dbe45784 | ||
|
|
f053b41645 | ||
|
|
84615ad299 | ||
|
|
2e291d73aa | ||
|
|
055efa3904 | ||
|
|
daee7970f3 | ||
|
|
2dc8fcd3be | ||
|
|
2f55c18d56 | ||
|
|
cf0748895e | ||
|
|
6e66b8a0fa | ||
|
|
e70b99a706 | ||
|
|
42e7a70d99 | ||
|
|
ee85eb2779 | ||
|
|
6c1adf9187 | ||
|
|
81a660eae4 | ||
|
|
8b029388a5 | ||
|
|
c816ed2527 | ||
|
|
866ea7f942 | ||
|
|
d9d3da4def | ||
|
|
be6cb24e10 | ||
|
|
1a63d9eb3b | ||
|
|
bf98cfeadc | ||
|
|
8a39b32b5c | ||
|
|
7d2646f60a | ||
|
|
1a8bc1dd60 | ||
|
|
7e434fc019 | ||
|
|
49d57cf596 | ||
|
|
8dfbc55851 | ||
|
|
3cbfe21b2c | ||
|
|
cb7424ce5e | ||
|
|
a567939f78 | ||
|
|
a3748d4b97 | ||
|
|
b80dc92ca5 | ||
|
|
57dee76c88 | ||
|
|
2513639499 | ||
|
|
9ae6ac25f5 | ||
|
|
01ec8d0bcb | ||
|
|
d09e8a12b4 | ||
|
|
5dd64b97d2 | ||
|
|
9600b1f103 | ||
|
|
ca9861e749 | ||
|
|
38bf07f4da | ||
|
|
189796891e | ||
|
|
8134905a86 | ||
|
|
45fb760a35 | ||
|
|
026fffa19f | ||
|
|
9da5ef3cbf | ||
|
|
ea7fe0c761 | ||
|
|
25d7b8d08d | ||
|
|
f467cb8cd2 | ||
|
|
f4e3c0a2e4 | ||
|
|
9cdf0601eb | ||
|
|
28ef972c9f | ||
|
|
c66476f6b6 | ||
|
|
3f90220208 | ||
|
|
81ebaae12e | ||
|
|
71984b25e9 | ||
|
|
4100c9881a | ||
|
|
075d01820c | ||
|
|
6f43cbf665 | ||
|
|
866f48f92d | ||
|
|
2790e4e819 | ||
|
|
8bb2b5e290 | ||
|
|
63290d0f5d | ||
|
|
5c55617585 | ||
|
|
0e0caabf7d | ||
|
|
024a319512 | ||
|
|
f632b3b029 | ||
|
|
b37f9a7db0 | ||
|
|
6f9c306260 | ||
|
|
c369350ca7 | ||
|
|
bc3c394210 | ||
|
|
e9df31b650 | ||
|
|
e49bb1ccc0 | ||
|
|
0ef8e086a2 | ||
|
|
63665dccae | ||
|
|
792b194d0e | ||
|
|
e694a74c9d | ||
|
|
9de016bfe3 | ||
|
|
3eddfc028e | ||
|
|
2125648798 | ||
|
|
24bff6e04d | ||
|
|
cdab0d208e | ||
|
|
20f04ab352 | ||
|
|
7f1af24318 | ||
|
|
8d87db58c6 | ||
|
|
feae4c6c8b | ||
|
|
00c89b8354 | ||
|
|
fb767f5680 | ||
|
|
c7d22aafd2 | ||
|
|
b5f237a69b | ||
|
|
b4093ccf59 | ||
|
|
a23217cc6f | ||
|
|
f4f7f47901 | ||
|
|
2f68687de9 | ||
|
|
86f4907cc4 | ||
|
|
bffb795d7a | ||
|
|
c21cffa6d4 | ||
|
|
96b0e70ddd | ||
|
|
febe56b062 | ||
|
|
f5e6722826 | ||
|
|
cea13b1823 | ||
|
|
3d85e85f29 | ||
|
|
923df8244b | ||
|
|
69db9e0d45 | ||
|
|
d1534d4dcf | ||
|
|
a8a94ef87b | ||
|
|
f93215f4ec | ||
|
|
9af460600d | ||
|
|
e1576b7131 | ||
|
|
5d05de8bda | ||
|
|
5e949b0564 | ||
|
|
2a52d9bdf6 | ||
|
|
ebf49d0668 | ||
|
|
f42955ab99 | ||
|
|
5d516592d9 | ||
|
|
7dc2b36413 | ||
|
|
5eefa36111 | ||
|
|
c26209d579 | ||
|
|
a30f73fe36 | ||
|
|
1a9c52e17f | ||
|
|
5ad38ee9f8 | ||
|
|
4c79591403 | ||
|
|
a9812167d7 | ||
|
|
a7cc36f741 | ||
|
|
4c0262cbd0 | ||
|
|
a0a98cb035 | ||
|
|
4fccfbf543 | ||
|
|
62ae80eeae | ||
|
|
d705108be5 | ||
|
|
3912eb7b26 | ||
|
|
1f959272c5 | ||
|
|
f9cd942363 | ||
|
|
1282da52eb | ||
|
|
10c099a52d | ||
|
|
fa0542ca8b | ||
|
|
3926226417 | ||
|
|
6a30511fc4 | ||
|
|
4ffa26cf2c | ||
|
|
1ad10914ce | ||
|
|
86ed85aa6e | ||
|
|
b7de847236 | ||
|
|
3cf2cd4684 | ||
|
|
2b95cd5081 | ||
|
|
8f45324bce | ||
|
|
5545cdbf4d | ||
|
|
9dec50832d | ||
|
|
64973f1d57 | ||
|
|
d7bfb727b0 | ||
|
|
37ad58c69e | ||
|
|
de753bf330 | ||
|
|
d17f8538b2 | ||
|
|
1900c81d9f | ||
|
|
9db6f82628 | ||
|
|
d96a6a59ee | ||
|
|
7535677ed4 | ||
|
|
6488324cf1 | ||
|
|
812e4c7cd4 | ||
|
|
85baae1ebd | ||
|
|
8174b9f041 | ||
|
|
fb9e91e486 | ||
|
|
1429737a60 | ||
|
|
286b4c0e46 | ||
|
|
166a3c4d64 | ||
|
|
d4a701aad0 | ||
|
|
47bf1bd21a | ||
|
|
852f9bd277 | ||
|
|
555cbeffa5 | ||
|
|
3d4d822528 | ||
|
|
c238130842 | ||
|
|
76e9ebde36 | ||
|
|
0688050552 | ||
|
|
9023171940 | ||
|
|
84371f03b5 | ||
|
|
20407bca89 | ||
|
|
96af2debfc | ||
|
|
6e532231dc | ||
|
|
dceec44671 | ||
|
|
0b5f40e66c | ||
|
|
da832368f0 | ||
|
|
abac8bccc6 | ||
|
|
82061c7c3b | ||
|
|
ec3a684be2 | ||
|
|
5572588c54 | ||
|
|
a8197df1c1 | ||
|
|
005e1e002b | ||
|
|
9603dce469 | ||
|
|
13190f6f15 | ||
|
|
eaa061d90c | ||
|
|
1ab374008f | ||
|
|
8c9d551826 | ||
|
|
c4c3f9dc1f | ||
|
|
5b722deb39 | ||
|
|
b61b7f0c3b | ||
|
|
3c40310e9b | ||
|
|
7a167742d0 | ||
|
|
d2a798eb3d | ||
|
|
3e9e34afb8 | ||
|
|
26d8a041ef | ||
|
|
7c25edc7b2 | ||
|
|
2725053c82 | ||
|
|
e2cb66f8d7 | ||
|
|
fad1d4cf98 | ||
|
|
daf64421f2 | ||
|
|
fa3329271d | ||
|
|
fdcb4473af | ||
|
|
41154d6d11 | ||
|
|
9904d01958 | ||
|
|
171ed497f9 | ||
|
|
212a8ad6a6 | ||
|
|
f2c518ba24 | ||
|
|
f8b61a4ebe | ||
|
|
35cc3837a0 | ||
|
|
572a80d1d1 | ||
|
|
2aa695fb66 | ||
|
|
f361f324da | ||
|
|
3999a3caa2 | ||
|
|
efc3def7f2 | ||
|
|
6c304924f7 | ||
|
|
f90714f8fe | ||
|
|
0960360b35 | ||
|
|
8db47e335f | ||
|
|
c609f67e16 | ||
|
|
14cb2b0143 | ||
|
|
b24c539206 | ||
|
|
52eeefa6d9 | ||
|
|
f942ec952e | ||
|
|
3e9aca3ed4 | ||
|
|
2d832e10b0 | ||
|
|
f1e995ec79 | ||
|
|
756ec8ccd7 | ||
|
|
c48f24d269 | ||
|
|
0d2e13549a | ||
|
|
f9ce9bdcec | ||
|
|
e339dbf473 | ||
|
|
f27f028d44 | ||
|
|
697aaf7e70 | ||
|
|
cc1e3d0101 | ||
|
|
9daa3997e9 | ||
|
|
83930ec9d1 | ||
|
|
b83a1bf4cc | ||
|
|
668b47cc6e | ||
|
|
f29471521c | ||
|
|
5beced458c | ||
|
|
ead451a979 | ||
|
|
97d42991a7 | ||
|
|
cd6bdc1a78 | ||
|
|
977f538420 | ||
|
|
590b155c6c | ||
|
|
7e9f11ea1c | ||
|
|
64cee145e0 | ||
|
|
525724cc1f | ||
|
|
63f9dc826f | ||
|
|
b3bda02063 | ||
|
|
df1d56e7b1 | ||
|
|
b80adcc00a | ||
|
|
68a7c3fa3b | ||
|
|
d099d8950f | ||
|
|
ae7093e0bb | ||
|
|
d932a877e8 | ||
|
|
745a7b4461 | ||
|
|
9e1a9723c2 | ||
|
|
e48754c73c | ||
|
|
096a554bfb | ||
|
|
74da5a610c | ||
|
|
ea7c6edcd0 | ||
|
|
27d5f02329 | ||
|
|
d56e7787f2 | ||
|
|
6d7c8431be | ||
|
|
3ed63d09d9 | ||
|
|
4b4299604b | ||
|
|
3842bcb921 | ||
|
|
f9b98767e7 | ||
|
|
6989c6332d | ||
|
|
209e9ebda7 | ||
|
|
e27e9dc2aa | ||
|
|
28474d9340 | ||
|
|
aa89416bca | ||
|
|
6c04ee1abd | ||
|
|
e93fba206d | ||
|
|
822a689b82 | ||
|
|
ffbf70af25 | ||
|
|
d3e307b102 | ||
|
|
a3e4abfd5e | ||
|
|
56d1411253 | ||
|
|
7bccd17bbe | ||
|
|
c193208cd2 | ||
|
|
923f9345a7 | ||
|
|
d618526037 | ||
|
|
a1dcd5f069 | ||
|
|
3dfa28570f | ||
|
|
d78c9fa2d2 | ||
|
|
6fac241404 | ||
|
|
99bb9d4fcf | ||
|
|
d19e101e6b | ||
|
|
13c70ac02c | ||
|
|
3405e44a1d | ||
|
|
8c5a28c0b8 | ||
|
|
7229c59b8e | ||
|
|
14884d5a2b | ||
|
|
688ed405df | ||
|
|
d3c79c9b49 | ||
|
|
de0f04ec3c | ||
|
|
c61b22cefb | ||
|
|
24dfa55465 | ||
|
|
d25624a8ad | ||
|
|
41f1e5f7c9 | ||
|
|
be3f657073 | ||
|
|
7e44a8ed1d | ||
|
|
874503ca68 | ||
|
|
29c833d623 | ||
|
|
46c0215b1f | ||
|
|
7c6e49ec65 | ||
|
|
9a142cea7a | ||
|
|
7b911aea46 | ||
|
|
af95daadf4 | ||
|
|
6e8d5cd873 | ||
|
|
48686cf9f7 | ||
|
|
b7fc3059b6 | ||
|
|
64ce5e0fad | ||
|
|
d815d06c1c | ||
|
|
c0c8465ec2 | ||
|
|
364d9de751 | ||
|
|
ca5e8c73d7 | ||
|
|
3e0c66edab | ||
|
|
e74be5887c | ||
|
|
253d0c834c | ||
|
|
feb19adb8f | ||
|
|
5d69c69b7c | ||
|
|
06077faa6a | ||
|
|
fcc369e854 | ||
|
|
ea187961da | ||
|
|
c9b2cec5ff | ||
|
|
960a4f71a3 | ||
|
|
292db86c9e | ||
|
|
6d3b36d61b | ||
|
|
c876aa537a | ||
|
|
f1e5238e16 | ||
|
|
d75d4a5c08 | ||
|
|
266fe876ba | ||
|
|
ca53ae4fc5 | ||
|
|
8f35683ccb | ||
|
|
30cd782e92 | ||
|
|
3d37c9c9a3 | ||
|
|
7072af7c14 | ||
|
|
c72bddf15e | ||
|
|
74ea266157 | ||
|
|
235bbc9c7e | ||
|
|
abd7c15ba8 | ||
|
|
a4ff1e4f33 | ||
|
|
5b9ea96dc5 | ||
|
|
e86c87f7bc | ||
|
|
e5794ed1c1 | ||
|
|
269441fe3d | ||
|
|
00f76ecaf6 | ||
|
|
952a69abca | ||
|
|
aa21bfd8a8 | ||
|
|
5768762591 | ||
|
|
ca9c11486e | ||
|
|
01d9849e44 | ||
|
|
0339026674 | ||
|
|
2f5115ca45 | ||
|
|
66878a9b48 | ||
|
|
333952a231 | ||
|
|
50281f12b9 | ||
|
|
4f8cea6e2d | ||
|
|
1c6b7203cc | ||
|
|
bf5081ec8c | ||
|
|
4f7587492d | ||
|
|
9a9c9b2b12 | ||
|
|
d4432ddd64 | ||
|
|
5c2d49f7ce | ||
|
|
28ccd63255 | ||
|
|
0dc263d919 | ||
|
|
3de041a411 | ||
|
|
00f5f8b2a0 | ||
|
|
95f1343a59 | ||
|
|
b4115b0362 | ||
|
|
6ee0f2c6a7 | ||
|
|
af39e4de3e | ||
|
|
0d8303cf5d | ||
|
|
4a6b5274bc | ||
|
|
f7ea420a3f | ||
|
|
56d5b0b12a | ||
|
|
bb81248eaa | ||
|
|
0e18eafcfb | ||
|
|
c138f390ac | ||
|
|
a16c63a43e | ||
|
|
9e21a089d2 | ||
|
|
3105215425 | ||
|
|
e916f93787 | ||
|
|
1332ddbc93 | ||
|
|
b30dfcf28a | ||
|
|
b9cfade18c | ||
|
|
ad1fa110ff | ||
|
|
ed49962120 | ||
|
|
0651f134e4 | ||
|
|
16fa5c4df3 | ||
|
|
2f849be9d8 | ||
|
|
6c49ab932e | ||
|
|
dc9c2773cb | ||
|
|
60eec49e95 | ||
|
|
f784551e20 | ||
|
|
a3d9169930 | ||
|
|
e87502285b | ||
|
|
caccacf52b | ||
|
|
5aee981590 | ||
|
|
e6d09b3266 | ||
|
|
8fcaa4997d | ||
|
|
7370af9a82 | ||
|
|
e4baef94bc | ||
|
|
8c05f9cf3e | ||
|
|
ebcab0f26e | ||
|
|
14996bd08b | ||
|
|
dd9fb9d526 | ||
|
|
f3ffed673b | ||
|
|
5b342dd229 | ||
|
|
e626bbf415 | ||
|
|
04795709a3 | ||
|
|
745162c589 | ||
|
|
089508db8e | ||
|
|
a912323d01 | ||
|
|
511a592ec8 | ||
|
|
d132d3abfd | ||
|
|
fb9b5e4274 | ||
|
|
8dcc5645db | ||
|
|
c6798892b8 | ||
|
|
eea5b026ce | ||
|
|
331e858ed3 | ||
|
|
3d602a2558 | ||
|
|
14386a2f62 | ||
|
|
4e91e05470 | ||
|
|
ea0bec8bf2 | ||
|
|
c2e8a1d733 | ||
|
|
c6155723a1 | ||
|
|
8c64afc81e | ||
|
|
eafd1d8c53 | ||
|
|
df0673f907 | ||
|
|
fe093c6385 | ||
|
|
ed536f18ee | ||
|
|
96590f591c | ||
|
|
32bfcbcdbc | ||
|
|
82feeff3aa | ||
|
|
3af451caeb | ||
|
|
ae953f2420 | ||
|
|
43ef9f909a | ||
|
|
4f42dae3cb | ||
|
|
e01c68dcea | ||
|
|
234d1291f9 | ||
|
|
90169d6a05 | ||
|
|
809562c874 | ||
|
|
be7a3a0940 | ||
|
|
1ea0b5371a | ||
|
|
74932e6311 | ||
|
|
b0b96aa410 | ||
|
|
deedd166db | ||
|
|
6ffab821b2 | ||
|
|
e53c8100a3 | ||
|
|
6705902a94 | ||
|
|
fd96e30c9c | ||
|
|
2b59724ea8 | ||
|
|
aa4d6d6f0f | ||
|
|
ca65671553 | ||
|
|
2d99308219 | ||
|
|
a4be75f410 | ||
|
|
4439545428 | ||
|
|
835fd383ad | ||
|
|
dfd1bff389 | ||
|
|
e53c1e39d3 | ||
|
|
775e044e69 | ||
|
|
4f3a3329e2 | ||
|
|
19f64bc561 | ||
|
|
1b2c1270a8 | ||
|
|
4b849243ce | ||
|
|
e7fc72067a | ||
|
|
ca6476a57f | ||
|
|
696f8451cf | ||
|
|
fb9f954882 | ||
|
|
a4af30675d | ||
|
|
95cad91bae | ||
|
|
166a56828d | ||
|
|
3d197abf83 | ||
|
|
950d4bb24e | ||
|
|
42caf02fb0 | ||
|
|
e59ea1aa02 | ||
|
|
4bd83443f8 | ||
|
|
5a906e0f3e | ||
|
|
a51d900da0 | ||
|
|
9a9902cea9 | ||
|
|
81790aed13 | ||
|
|
1f7ac11baa | ||
|
|
0ed4744a33 | ||
|
|
776ca86a60 | ||
|
|
90400bf5ad | ||
|
|
c43f2bbb86 | ||
|
|
f3fc128ec3 | ||
|
|
6a697eed2f | ||
|
|
862e52a830 | ||
|
|
1e2e65b40d | ||
|
|
41e13fab55 | ||
|
|
134819cb45 | ||
|
|
f62d743407 | ||
|
|
9dc779927b | ||
|
|
88ce05976e | ||
|
|
956a2bbdbe | ||
|
|
bd7ae3dc71 | ||
|
|
91e5fcf8f1 | ||
|
|
93b8287d23 | ||
|
|
5c7f34fee2 | ||
|
|
b64c550989 | ||
|
|
997bd030f9 | ||
|
|
bf6444c585 | ||
|
|
9d25d2674b | ||
|
|
8c1b145358 | ||
|
|
925ead51b6 | ||
|
|
85b606b7d2 | ||
|
|
5302d3bb31 | ||
|
|
775a805959 | ||
|
|
0586dbaf8b | ||
|
|
dd6a34e60a | ||
|
|
49c1d1a4ca | ||
|
|
6d6c9b782b | ||
|
|
733332a8f4 | ||
|
|
6b6b102079 | ||
|
|
50895c7e37 | ||
|
|
66a37aa945 | ||
|
|
0fd4c3bd00 | ||
|
|
0d3321c686 | ||
|
|
7cae087eb9 | ||
|
|
4c7e52288d | ||
|
|
e108fecdd6 | ||
|
|
be6ddb08bd | ||
|
|
2cc53f328b | ||
|
|
aaae23e9f0 | ||
|
|
fb81a4f318 | ||
|
|
95bce39751 | ||
|
|
a34af84176 | ||
|
|
610a94ea03 | ||
|
|
5a160f426e | ||
|
|
0367edf898 | ||
|
|
4279c0b77f | ||
|
|
cae06f6cf4 | ||
|
|
07b5995e85 | ||
|
|
0f7a77f45b | ||
|
|
cd832ea77c | ||
|
|
82c7764679 | ||
|
|
a386733c04 | ||
|
|
381e9dac34 | ||
|
|
736aadb186 | ||
|
|
6d6af09296 | ||
|
|
4acfa1faef | ||
|
|
b9085c1522 | ||
|
|
55af0ce297 | ||
|
|
6b25453f11 | ||
|
|
06a32ce7be | ||
|
|
75c1c1bccc | ||
|
|
0c25c1f0ca | ||
|
|
1b12e3fbf9 | ||
|
|
a7a2a166e6 | ||
|
|
0d7aba2502 | ||
|
|
ce45879efb | ||
|
|
ab54971763 | ||
|
|
d75f96fdd5 | ||
|
|
024c112944 | ||
|
|
3242354a4b | ||
|
|
f465a79924 | ||
|
|
fc28423141 | ||
|
|
4ac652b127 | ||
|
|
6088f83408 | ||
|
|
e92f2ecea1 | ||
|
|
a82aa8203b | ||
|
|
0a59d6ab2f | ||
|
|
9bf9bb0273 | ||
|
|
5744c70399 | ||
|
|
f3342ae7d3 | ||
|
|
2c7e807738 | ||
|
|
39430e1cee | ||
|
|
142a323efd | ||
|
|
ea198fea6e | ||
|
|
666013b010 | ||
|
|
c7dafd4b42 | ||
|
|
2724cf5db8 | ||
|
|
ea623cb5a1 | ||
|
|
0ffcce1b5d | ||
|
|
8ac47b4e24 | ||
|
|
444807c35b | ||
|
|
5b0585ac7f | ||
|
|
c3a5822a40 | ||
|
|
2f4d3be303 | ||
|
|
9afdea8d2a | ||
|
|
57c78bc603 | ||
|
|
a065f93777 | ||
|
|
f76374cd8f | ||
|
|
e1345337ac | ||
|
|
494810393a | ||
|
|
8daec7bde2 | ||
|
|
b891677ba5 | ||
|
|
d63a77d8b1 | ||
|
|
2cbe6cdfd8 | ||
|
|
ddd20e5376 | ||
|
|
08cd949d6f | ||
|
|
0b5ba55131 | ||
|
|
262a09bb2d | ||
|
|
0320baeb5b | ||
|
|
42670c27d5 | ||
|
|
fe41a4e6fa | ||
|
|
a7b1df34c5 | ||
|
|
567a42a756 | ||
|
|
2fa9311eee | ||
|
|
14f439f8ba | ||
|
|
bfe7b77313 | ||
|
|
a69086a718 | ||
|
|
3e3980dbac | ||
|
|
9f6c9cd6ff | ||
|
|
eb88a53223 | ||
|
|
76c18e50a4 | ||
|
|
ca1cd89190 | ||
|
|
9f8eae908d | ||
|
|
db1847bc1d | ||
|
|
d9936f2dff | ||
|
|
3774114a4c | ||
|
|
4bc5b37c09 | ||
|
|
ac1ca639d6 | ||
|
|
83b67c0693 | ||
|
|
244e682c2b | ||
|
|
0ef7271326 | ||
|
|
3fa228dcbb | ||
|
|
14e25100d4 | ||
|
|
b2c0eefbbc | ||
|
|
8eee0d574c | ||
|
|
150fd869a0 | ||
|
|
50795adcf0 | ||
|
|
3f2c1de28d | ||
|
|
dca45f177f | ||
|
|
597c1f6a41 | ||
|
|
c2da54139a | ||
|
|
afcc388d8a | ||
|
|
5cd1c5c522 | ||
|
|
63f8800007 | ||
|
|
a958965e64 | ||
|
|
5d7c485991 | ||
|
|
d97f24cfc3 | ||
|
|
3b39c43193 | ||
|
|
b746b63036 | ||
|
|
7c707017e7 | ||
|
|
ce155a1d87 | ||
|
|
48975e6533 | ||
|
|
3e05eb23fd | ||
|
|
3980d25c23 | ||
|
|
2255cb53f0 | ||
|
|
521072daea | ||
|
|
66ba19b7ba | ||
|
|
ac37b54ddb | ||
|
|
56c332a3dd | ||
|
|
cd53c78449 | ||
|
|
f237cac074 | ||
|
|
f6ad386ba7 | ||
|
|
24e527ae02 | ||
|
|
8d7ac3862c | ||
|
|
af50188a60 | ||
|
|
572d35506b | ||
|
|
a4b8a88ae5 | ||
|
|
dbd46a523f | ||
|
|
3c86c9908c | ||
|
|
37d75905ed | ||
|
|
19812feb62 | ||
|
|
90ecb4c544 | ||
|
|
42926c48e5 | ||
|
|
e20e2117f7 | ||
|
|
7f602feff4 | ||
|
|
a79c1cb23f | ||
|
|
582ebf25f9 | ||
|
|
896bbd00e1 | ||
|
|
4a9949e643 | ||
|
|
fc81cda971 | ||
|
|
7a030e0c3b | ||
|
|
69c027156c | ||
|
|
2ac07f12b0 | ||
|
|
5494be4493 | ||
|
|
8ed0df64c7 | ||
|
|
e8c65dc384 | ||
|
|
e508db994e | ||
|
|
f7b7401a53 | ||
|
|
f58e228d11 | ||
|
|
97f54ac385 | ||
|
|
aedaae852b | ||
|
|
ae0f8c77d1 | ||
|
|
d0e7d53c69 | ||
|
|
647e43dcbd | ||
|
|
0d856cc135 | ||
|
|
df33cbc8c5 | ||
|
|
a38a06a077 | ||
|
|
15e6a4266c | ||
|
|
11170dd34c | ||
|
|
68a45608e6 | ||
|
|
0838f432ca | ||
|
|
c0d2241523 | ||
|
|
6e8505ae61 | ||
|
|
aaeab3177e | ||
|
|
b18921cd07 | ||
|
|
c776db5485 | ||
|
|
f14c6efaf8 | ||
|
|
9d4cce74b2 | ||
|
|
194273a643 | ||
|
|
05fc34533f | ||
|
|
ca42d976a7 | ||
|
|
20d5d0eee6 | ||
|
|
693af182c7 | ||
|
|
2dbb370955 | ||
|
|
aba824a317 | ||
|
|
5f513773c1 | ||
|
|
999894cccb | ||
|
|
906e70e599 | ||
|
|
3f167d7fd1 | ||
|
|
dd8d6bc705 | ||
|
|
43afd7dff9 | ||
|
|
9266d3789b | ||
|
|
dc70894d83 | ||
|
|
24bab47f14 | ||
|
|
74b8e8244a | ||
|
|
7806da11e6 | ||
|
|
ec98f9181b | ||
|
|
ba2deb5f7b | ||
|
|
7794442277 | ||
|
|
fb8775124c | ||
|
|
680865f13c | ||
|
|
5373a699dd | ||
|
|
177acf835c | ||
|
|
f3ba491a73 | ||
|
|
0e73c1bf78 | ||
|
|
98a07eff81 | ||
|
|
3f917b0af5 | ||
|
|
d3c6db1ba8 | ||
|
|
2a693f7f08 | ||
|
|
fb7b475457 | ||
|
|
26e5d7a3de | ||
|
|
cfeba99776 | ||
|
|
c0b4f7b6d2 | ||
|
|
021c6ac1cb | ||
|
|
261e5ebbd4 | ||
|
|
388fba4569 | ||
|
|
eda13a9626 | ||
|
|
5da656e559 | ||
|
|
d23762e06b | ||
|
|
5e6d876bd0 | ||
|
|
5e9c44b23b | ||
|
|
196b7846cc | ||
|
|
311946900e | ||
|
|
9b12350855 | ||
|
|
fd319bd5f5 | ||
|
|
6f982b2791 | ||
|
|
05f934548b | ||
|
|
f22bffe98a | ||
|
|
87c65bcea0 | ||
|
|
6f4b206a99 | ||
|
|
2c88b418fd | ||
|
|
66e60357dc | ||
|
|
30db7e64fb | ||
|
|
c6c733a40b | ||
|
|
4a9bc70ca0 | ||
|
|
a815511aef | ||
|
|
bae1e2f0c1 | ||
|
|
7ce31bfaa0 | ||
|
|
48175101c6 | ||
|
|
e5280d55b3 | ||
|
|
3675b3fcaa | ||
|
|
5962bcbc6c | ||
|
|
b39f8fb4de | ||
|
|
6deaa87a4c | ||
|
|
5562651ef0 | ||
|
|
2c00267d58 | ||
|
|
b5418c40ba | ||
|
|
2266ef6809 | ||
|
|
ca67b49d67 | ||
|
|
63cc794f37 | ||
|
|
fca6c85abb | ||
|
|
604f8a22f7 | ||
|
|
f6845cd107 | ||
|
|
c20fa85b82 | ||
|
|
bb2d810709 | ||
|
|
95fd34ed14 | ||
|
|
db0c442eaf | ||
|
|
42fc68baa5 | ||
|
|
c8bc0b3bf8 | ||
|
|
aa4d60c21e | ||
|
|
4f0a4ea7e7 | ||
|
|
e40b462040 | ||
|
|
89418a155a | ||
|
|
901685bb63 | ||
|
|
c709a28f02 | ||
|
|
463a750c07 | ||
|
|
10abf61383 | ||
|
|
fcba62894b | ||
|
|
77215182f7 | ||
|
|
3706d0dedd | ||
|
|
3f5ab189cd | ||
|
|
eb793f7feb | ||
|
|
4d0c04b80d | ||
|
|
e9a842259a | ||
|
|
2c7d33cdfa | ||
|
|
83279604c6 | ||
|
|
c821568ac7 | ||
|
|
1c38619d8c | ||
|
|
8cfe89eaf9 | ||
|
|
cb63344394 | ||
|
|
8934c83742 | ||
|
|
b0451dc1b3 | ||
|
|
b5a846154a | ||
|
|
f48d0fcb13 | ||
|
|
650d3d5046 | ||
|
|
0992b6a616 | ||
|
|
53ed407448 | ||
|
|
d96f5598ca | ||
|
|
137cbe5bb4 | ||
|
|
6f783f5a3b | ||
|
|
6ed17fe62f | ||
|
|
7d25d6f191 | ||
|
|
0bd50c06d7 | ||
|
|
9a74105103 | ||
|
|
a433e0e79c | ||
|
|
483ef20527 | ||
|
|
c5d3eb53f0 | ||
|
|
f582ac88b3 | ||
|
|
7b69b789b8 | ||
|
|
5c8b571c3f | ||
|
|
bfe5a56a47 | ||
|
|
8cfbd2f8bf | ||
|
|
50a1feb90a | ||
|
|
6df9012141 | ||
|
|
dc607b8e8a | ||
|
|
1a71da417c | ||
|
|
2446168356 | ||
|
|
153ab4afaa | ||
|
|
ff3843bc7f | ||
|
|
86f5152092 | ||
|
|
83e7c48767 | ||
|
|
85c3a0aa14 | ||
|
|
50645cc36b | ||
|
|
afede880e6 | ||
|
|
e2f6633d57 | ||
|
|
fc43ce657c | ||
|
|
8f9eeb5ebd | ||
|
|
db2ff68fef | ||
|
|
ed974a808b | ||
|
|
0108dfa803 | ||
|
|
cf147cdeaf | ||
|
|
57fac6b9aa | ||
|
|
aeb8bc8755 | ||
|
|
96bd66e811 | ||
|
|
494ede5bbf | ||
|
|
e76d2ec9c2 | ||
|
|
7b972926ae | ||
|
|
4a71a79cb8 | ||
|
|
99556057d1 | ||
|
|
921d672a2c | ||
|
|
5f004f95f2 | ||
|
|
284106b8a8 | ||
|
|
abed438d7d | ||
|
|
0047ce067d | ||
|
|
58f743f87d | ||
|
|
867e333464 | ||
|
|
de683b3360 | ||
|
|
b2a0ae0f83 | ||
|
|
b55d9350e7 | ||
|
|
3dc2a114fa | ||
|
|
57bacb339c | ||
|
|
2191921690 | ||
|
|
23fcf85500 | ||
|
|
3c6b647398 | ||
|
|
1821809e69 | ||
|
|
ba3f6f9d3e | ||
|
|
9bedd83f39 | ||
|
|
592330b5a7 | ||
|
|
2202094e41 | ||
|
|
3354365177 | ||
|
|
a39e484aaa | ||
|
|
51af06edf7 | ||
|
|
7cf9046dc5 | ||
|
|
25c6b64fed | ||
|
|
a8aab0cb2b | ||
|
|
788e7fd36d | ||
|
|
74bf1f23fb | ||
|
|
bf9e51928d | ||
|
|
bfe6d5434e | ||
|
|
f81bde5643 | ||
|
|
fbc6bb2112 | ||
|
|
62e8841e8c | ||
|
|
5270c4bc74 | ||
|
|
a993bc1331 | ||
|
|
e9f38b9fc0 | ||
|
|
5896903bd3 | ||
|
|
f41c314329 | ||
|
|
84618a6076 | ||
|
|
b61f30de94 | ||
|
|
afe76ba260 | ||
|
|
1302630abe | ||
|
|
a6d993ecdc | ||
|
|
65796d7477 | ||
|
|
41a73a7adb | ||
|
|
05d725d0b8 | ||
|
|
7a41ecb63f | ||
|
|
6fd37779b8 | ||
|
|
d14b570d76 | ||
|
|
2af28b90c2 | ||
|
|
09b0e6e388 | ||
|
|
5ca8d590bd | ||
|
|
11c8e80ea9 | ||
|
|
ea993b6404 | ||
|
|
a258e2e608 | ||
|
|
e69bacaee1 | ||
|
|
8c0e1060e6 | ||
|
|
fb56bc59f2 | ||
|
|
1c9993f185 | ||
|
|
2dac975805 | ||
|
|
2bb63835b6 | ||
|
|
bfafb83604 | ||
|
|
ea54f6923b | ||
|
|
1a401780ba | ||
|
|
448a8b8d1c | ||
|
|
c8146e759f | ||
|
|
bb7d79e6d2 | ||
|
|
fb35f7210c | ||
|
|
187834b17c | ||
|
|
4822d02787 | ||
|
|
35cc0a1cc0 | ||
|
|
b3be51f17f | ||
|
|
a40299b4dc | ||
|
|
1a9f630710 | ||
|
|
48ddd7213f | ||
|
|
582e680b12 | ||
|
|
a04a403539 | ||
|
|
564162442d | ||
|
|
7da3ee72c7 | ||
|
|
823294f055 | ||
|
|
5aa495d0e4 | ||
|
|
2e6c2347eb | ||
|
|
a256d71ef9 | ||
|
|
b7a8551290 | ||
|
|
8f0269de76 | ||
|
|
1a6e6f405d | ||
|
|
59a2109cab | ||
|
|
31781bc509 | ||
|
|
db2161c7e6 | ||
|
|
7d4e676cfd | ||
|
|
2dcb98a8ed | ||
|
|
0bde1bb857 | ||
|
|
d685644dee | ||
|
|
e906a1979c | ||
|
|
0a9958c74e | ||
|
|
04f9a6fdd0 | ||
|
|
5eee33a11f | ||
|
|
4b4f398e83 | ||
|
|
9655014041 | ||
|
|
85e65e61d3 | ||
|
|
e32259ccc9 | ||
|
|
15137422a6 | ||
|
|
1f48c07395 | ||
|
|
26c9a19392 | ||
|
|
2c3aad785d | ||
|
|
ece9e8dcea | ||
|
|
85c45c2b8f | ||
|
|
8149381f01 | ||
|
|
e221cbfbd6 | ||
|
|
0c56ae4f32 | ||
|
|
1e196fc091 | ||
|
|
d4c0d5d81b | ||
|
|
12c770f0ab | ||
|
|
637988b104 | ||
|
|
71edd9ff1b | ||
|
|
34539c0c13 | ||
|
|
1f2cba81eb | ||
|
|
e458ca7b47 | ||
|
|
b915bb98fb | ||
|
|
8aef297e71 | ||
|
|
c628ac9bbb | ||
|
|
385048b620 | ||
|
|
e5c1169120 | ||
|
|
38d851eb98 | ||
|
|
73ee8a5985 | ||
|
|
020d7d4939 | ||
|
|
697529d0e8 | ||
|
|
b51a8f11d5 | ||
|
|
a4a8cd05d2 | ||
|
|
38fc85d619 | ||
|
|
be589d81c7 | ||
|
|
ba883d25fe | ||
|
|
f416e2d1ac | ||
|
|
cb8110cd48 | ||
|
|
8d081a081d | ||
|
|
d1e9b6d6ae | ||
|
|
e7ac367392 | ||
|
|
7a8851c5ab | ||
|
|
e771d8e944 | ||
|
|
b48b11e902 | ||
|
|
5de9230924 | ||
|
|
59fcd3914d | ||
|
|
95fcddcd95 | ||
|
|
293d0c3093 | ||
|
|
e17f56b4ad | ||
|
|
32e0ce1beb | ||
|
|
25ef49494b | ||
|
|
3ee1ea28e1 | ||
|
|
0a8cf26731 | ||
|
|
a8b2074fc6 | ||
|
|
14be5e3ff7 | ||
|
|
6de071a5f3 | ||
|
|
0a2b03ba52 | ||
|
|
dbc64c21a7 | ||
|
|
294f7f1f0d | ||
|
|
d10ce90936 | ||
|
|
fe0bf876d9 | ||
|
|
c5be95e46c | ||
|
|
b762f56aee | ||
|
|
74a8fa61f2 | ||
|
|
964d47d517 | ||
|
|
a38da2f7c6 | ||
|
|
593f2e0851 | ||
|
|
9ae3d66da7 | ||
|
|
4c7545e909 | ||
|
|
a0e80e5869 | ||
|
|
75e6947c5a | ||
|
|
3007add4ca | ||
|
|
67fbb173e3 | ||
|
|
0d3fbb8659 | ||
|
|
32fa8180fa | ||
|
|
884dc53f8a | ||
|
|
d812414621 | ||
|
|
52c32d8b10 | ||
|
|
eace358f1c | ||
|
|
e7c43bf614 | ||
|
|
81636d8634 | ||
|
|
b72eba1ef2 | ||
|
|
1fdc5277ae | ||
|
|
1d7f945268 | ||
|
|
eb37fc089b | ||
|
|
979d0ca70f | ||
|
|
7ea579bb71 | ||
|
|
a0dad38974 | ||
|
|
e5844afb0f | ||
|
|
c4ac3d61b1 | ||
|
|
8c14e565a7 | ||
|
|
53cb0feda9 | ||
|
|
14e8c15a3a | ||
|
|
aaea80e053 | ||
|
|
f6a61c1ec5 | ||
|
|
5768f10769 | ||
|
|
bcb80eb38f | ||
|
|
9590f485f1 | ||
|
|
32fe723da6 | ||
|
|
48b25bc327 | ||
|
|
3044a74a52 | ||
|
|
ca7aa294e0 | ||
|
|
5175cf70ef | ||
|
|
5cb7721ab2 | ||
|
|
158b77d54e | ||
|
|
f8f302faad | ||
|
|
3f97bd8212 | ||
|
|
bf6f0f1a65 | ||
|
|
8a986ec340 | ||
|
|
b0ef659add | ||
|
|
29a7490af2 | ||
|
|
ad45b63e79 | ||
|
|
16fc6e8b42 | ||
|
|
af277f560f | ||
|
|
ff403efe09 | ||
|
|
df9403809b | ||
|
|
d86814b6c5 | ||
|
|
d66e510c42 | ||
|
|
87007994af | ||
|
|
03e4afa736 | ||
|
|
f120e96eeb | ||
|
|
7e044e29ba | ||
|
|
63ac6640e6 | ||
|
|
e410fbb558 | ||
|
|
4eeaa6bf9d | ||
|
|
5d57931060 | ||
|
|
f227002a80 | ||
|
|
d84d92f73c | ||
|
|
a0cbca4cad | ||
|
|
0a23a996bc | ||
|
|
380b7f4d94 | ||
|
|
bad2d1a974 | ||
|
|
4fd2c0570c | ||
|
|
fd274592d4 | ||
|
|
7064d87106 | ||
|
|
f8ceb341d6 | ||
|
|
3fdab59029 | ||
|
|
2d7c7871b0 | ||
|
|
9fd3ef2687 | ||
|
|
b6a4db3f8a | ||
|
|
b99ee2562e | ||
|
|
8526025792 | ||
|
|
236c4e65f8 | ||
|
|
d92fae07a5 | ||
|
|
968b1b4308 | ||
|
|
e9a174d1c5 | ||
|
|
2c52224013 | ||
|
|
869cf705e0 | ||
|
|
0b05f88543 | ||
|
|
e395211654 | ||
|
|
9f6a348851 | ||
|
|
aa52f6675c | ||
|
|
9cc5e981dd | ||
|
|
da74fa0862 | ||
|
|
1dfc576263 | ||
|
|
170e8a5d76 | ||
|
|
bd0bf3747e | ||
|
|
a11b180480 | ||
|
|
f8cfbedefd | ||
|
|
90a77bdf85 | ||
|
|
e438d21cc0 | ||
|
|
dc88fff704 | ||
|
|
8ff316252e | ||
|
|
dabdf1b7fd | ||
|
|
6fb6e44ece | ||
|
|
6df299886e | ||
|
|
b25411ef6b | ||
|
|
dfa5b005cc | ||
|
|
73b512859a | ||
|
|
c2a4e4720b | ||
|
|
74c5015648 | ||
|
|
5bddf79d09 | ||
|
|
05bed2fd8a | ||
|
|
c3f0ef4126 | ||
|
|
e549a9c09c | ||
|
|
8ef3ee1319 | ||
|
|
c762ad8db2 | ||
|
|
929dc2b29c | ||
|
|
a5d3c1a655 | ||
|
|
a933192b56 | ||
|
|
41565335ed | ||
|
|
9540e12e2e | ||
|
|
9766106686 | ||
|
|
3d8beb918b | ||
|
|
123ea331e6 | ||
|
|
b5a77d4f4a | ||
|
|
9852972db8 | ||
|
|
b286ed6bb8 | ||
|
|
b56a084810 | ||
|
|
c9a28ddd38 | ||
|
|
bb7ee1c5a3 | ||
|
|
1772e15b46 | ||
|
|
360efdf71f | ||
|
|
56d1e6834a | ||
|
|
f1e267498e | ||
|
|
4ba6bf8e27 | ||
|
|
101c44f22d | ||
|
|
7f967524b9 | ||
|
|
01e171373c | ||
|
|
229a4a8aab | ||
|
|
f6feb455a9 | ||
|
|
fbf4eac257 | ||
|
|
48b5d235d8 | ||
|
|
0d8e024c18 | ||
|
|
cc9d2fc139 | ||
|
|
dbc07827cf | ||
|
|
05c27d8340 | ||
|
|
d57ffad5e1 | ||
|
|
ebdbbbc000 | ||
|
|
1edb13d715 | ||
|
|
aa8beda4ec | ||
|
|
7178dcad35 | ||
|
|
76b517b361 | ||
|
|
ddaac50a25 | ||
|
|
a446286869 | ||
|
|
c54f0fe58b | ||
|
|
7c8166cad2 | ||
|
|
3db2aaada6 | ||
|
|
649d40ed66 | ||
|
|
d71b626114 | ||
|
|
fc47fb8f64 | ||
|
|
10e5e5c400 | ||
|
|
942e8fdba8 | ||
|
|
6ba8854854 | ||
|
|
b7c0d99cdf | ||
|
|
bc4584d9fe | ||
|
|
53b1d6a5b2 | ||
|
|
836e4b4911 | ||
|
|
e9afd30b47 | ||
|
|
aefbcb7049 | ||
|
|
4fd2622e55 | ||
|
|
d048e39cde | ||
|
|
140f1307b4 | ||
|
|
9d10b5ab52 | ||
|
|
edb39a072e | ||
|
|
d66d989308 | ||
|
|
05c3b96202 | ||
|
|
e9c7264fd9 | ||
|
|
0b1c1bb8b4 | ||
|
|
47a18bba99 | ||
|
|
7ffdb488c1 | ||
|
|
2c1188f664 | ||
|
|
60ab08ed1b | ||
|
|
2bb85d216e | ||
|
|
7be8fb8432 | ||
|
|
a4ef1e22d6 | ||
|
|
3335041d39 | ||
|
|
19e881513b | ||
|
|
41777c01f1 | ||
|
|
6b26c8d46f | ||
|
|
d4339ae9d2 | ||
|
|
bdc4d14036 | ||
|
|
ed82f6c681 | ||
|
|
d4e6ae2804 | ||
|
|
32275cb009 | ||
|
|
ff353197fb | ||
|
|
88bf0cdb9e | ||
|
|
a2b751976e | ||
|
|
ddb4b928a0 | ||
|
|
2b5fa599fb | ||
|
|
ae2201ef6f | ||
|
|
ed69ddedbf | ||
|
|
66f5411402 | ||
|
|
a60bf642e1 | ||
|
|
be8a72c35b | ||
|
|
cc14705404 | ||
|
|
6de584aafc | ||
|
|
cc427b1307 | ||
|
|
00cdb5e36a | ||
|
|
437cd50039 | ||
|
|
61add0ecc6 | ||
|
|
8accb8865a | ||
|
|
c44248440e | ||
|
|
d32c03ed11 | ||
|
|
3e49609099 | ||
|
|
c47f4bc97c | ||
|
|
8ee7d5c2d5 | ||
|
|
2020fedfdb | ||
|
|
40b2535728 | ||
|
|
2d016c5a3f | ||
|
|
ba3bb57926 | ||
|
|
4c6d7630cd | ||
|
|
d1767144a8 | ||
|
|
a991cda233 | ||
|
|
9c2040aa9b | ||
|
|
96ee1c17a3 | ||
|
|
6911572fa1 | ||
|
|
059db533d5 | ||
|
|
f28af4f369 | ||
|
|
1bd238191c | ||
|
|
c07d48d930 | ||
|
|
00a713c42e | ||
|
|
01c97e69dd | ||
|
|
646298f5c5 | ||
|
|
8f73328e25 | ||
|
|
b5112aeee2 | ||
|
|
22adf0d06e | ||
|
|
382f7066d9 | ||
|
|
08c19692ea | ||
|
|
eb575685aa | ||
|
|
7a95451288 | ||
|
|
538ec7c0a0 | ||
|
|
ea800dd838 | ||
|
|
b8c378f2f0 | ||
|
|
e86bedddb2 | ||
|
|
1e1a6df480 | ||
|
|
7aa1ab855e | ||
|
|
776f15055a | ||
|
|
b291b18a87 | ||
|
|
e6492f7db9 | ||
|
|
3b737999d6 | ||
|
|
00fa7f5e86 | ||
|
|
fde5ba85a0 | ||
|
|
a96e4a343c | ||
|
|
36110d0977 | ||
|
|
1f330d7753 | ||
|
|
cf877e6567 | ||
|
|
c3fa68ade8 | ||
|
|
5422d13607 | ||
|
|
d8f614ed98 | ||
|
|
4ca125da41 | ||
|
|
3c2bfbfc1c | ||
|
|
03e336ba9e | ||
|
|
76ea0f432a | ||
|
|
7eb45e1799 | ||
|
|
4af1dcd54f | ||
|
|
463c519954 | ||
|
|
1d0a3660bd | ||
|
|
b83367063e | ||
|
|
aa724fc11e | ||
|
|
cedb11ebab | ||
|
|
ffe389af4a | ||
|
|
b01b121a4b | ||
|
|
b313637848 | ||
|
|
2eeae21777 | ||
|
|
2af9dfebea | ||
|
|
dade6fc191 | ||
|
|
fb0629a913 | ||
|
|
060d0b777b | ||
|
|
dc03ca8879 | ||
|
|
de51aeab7b | ||
|
|
b46f8bad6d | ||
|
|
8982dc5ed3 | ||
|
|
2d2462fe63 | ||
|
|
b1fedca46e | ||
|
|
929187a934 | ||
|
|
7f34462f9a | ||
|
|
2c54937104 | ||
|
|
472b8c6e8d | ||
|
|
8e33c2c4d3 | ||
|
|
795cee13c8 | ||
|
|
15188c4a88 | ||
|
|
48f5a77e24 | ||
|
|
c42d09b267 | ||
|
|
0f791c9fa8 | ||
|
|
ceb079a7ea | ||
|
|
607b273b28 | ||
|
|
ce99e7b294 | ||
|
|
a20c276c84 | ||
|
|
2186b09ed7 | ||
|
|
38db91c7be | ||
|
|
902f5d895a | ||
|
|
6d565cb355 | ||
|
|
6a9256bb00 | ||
|
|
b48b2ac656 | ||
|
|
fde11be279 | ||
|
|
adb5d6da84 | ||
|
|
92d869e85c | ||
|
|
e8e83bdbce | ||
|
|
bb8f8fccca | ||
|
|
1824caa5ea | ||
|
|
dfac87db05 | ||
|
|
15c8a5e351 | ||
|
|
8e9a0eddf5 | ||
|
|
1200dd4b75 | ||
|
|
f969fce4d4 | ||
|
|
45419195aa | ||
|
|
80c771c945 | ||
|
|
6bd2736116 | ||
|
|
f7b4f331f3 | ||
|
|
618d4f0a9d | ||
|
|
c01efad997 | ||
|
|
2933b89a82 | ||
|
|
1d64ba3b5d | ||
|
|
e646ae8be4 | ||
|
|
d3db49ae3e | ||
|
|
7be7aeb70a | ||
|
|
541cd2e430 | ||
|
|
4322f29f34 | ||
|
|
7d0ae23c0e | ||
|
|
0122a9ab18 | ||
|
|
165647184d | ||
|
|
2ca86b6085 | ||
|
|
b04c50537d | ||
|
|
fcac4c057c | ||
|
|
71aa2ef2c2 | ||
|
|
03aa997673 | ||
|
|
df4a00f8ef | ||
|
|
f343a46ca4 | ||
|
|
b1f85dc8f1 | ||
|
|
722d74a41b | ||
|
|
86a9fe6024 | ||
|
|
68701c5cf9 | ||
|
|
f4280ca517 | ||
|
|
afeb65b3bf | ||
|
|
d9e56b678a | ||
|
|
aa60edd9fe | ||
|
|
c4b8a9853e | ||
|
|
e640c51f84 | ||
|
|
b37e100058 | ||
|
|
cb3593e472 | ||
|
|
2e6d28027a | ||
|
|
9c5e116d09 | ||
|
|
10618637e2 | ||
|
|
4e97df06a3 | ||
|
|
abe529b5be | ||
|
|
e31a3a64e1 | ||
|
|
152b01064a | ||
|
|
f235b516dc | ||
|
|
1f6d5bfd53 | ||
|
|
da833cbc58 | ||
|
|
9268ecf3e9 | ||
|
|
c8687560d6 | ||
|
|
5286f0856d | ||
|
|
789363b0ad | ||
|
|
e6918c4b99 | ||
|
|
f9cf673f81 | ||
|
|
cc71b1f07d | ||
|
|
7919d79347 | ||
|
|
22b78aa037 | ||
|
|
a5c3855233 | ||
|
|
ddd3df26b1 | ||
|
|
c27db7a347 | ||
|
|
527e802b05 | ||
|
|
d758729633 | ||
|
|
3e9adeefbc | ||
|
|
5f0e7cd52a | ||
|
|
98c0209976 | ||
|
|
6f2a8e27b8 | ||
|
|
41820ccb05 | ||
|
|
4d13a5bffb | ||
|
|
7614ddb318 | ||
|
|
a5fac17f2b | ||
|
|
49a0ea53c7 | ||
|
|
44bc2b2d56 | ||
|
|
a26436f59b | ||
|
|
1e4c62a70d | ||
|
|
526f3e1a31 | ||
|
|
c67291da33 | ||
|
|
9c9ebb4987 | ||
|
|
d987532262 | ||
|
|
7d4293f849 | ||
|
|
c658189c85 | ||
|
|
a8d9ec426b | ||
|
|
9bae19a7ec | ||
|
|
bf898138b7 | ||
|
|
245c6dbff0 | ||
|
|
f48f5428e5 | ||
|
|
964f0861d6 | ||
|
|
a76758255f | ||
|
|
7db3703275 | ||
|
|
306358e73c | ||
|
|
2bd2605ae9 | ||
|
|
7010df0fe8 | ||
|
|
36a948965b | ||
|
|
5d6583ef7b | ||
|
|
0aab51a73f | ||
|
|
86e9d2cf07 | ||
|
|
c7b4041879 | ||
|
|
6e0947c0d9 | ||
|
|
3334e36397 | ||
|
|
35888c814c | ||
|
|
0d817e0664 | ||
|
|
a8363f02b8 | ||
|
|
94c3a07115 | ||
|
|
01148ac1b9 | ||
|
|
30047e6a9f | ||
|
|
c1d6fcd18d | ||
|
|
94415e2b60 | ||
|
|
d81d0c8c44 | ||
|
|
eb8b9c4ac3 | ||
|
|
080847ec4d | ||
|
|
d08144e730 | ||
|
|
bb5eeee82e | ||
|
|
741a1736a4 | ||
|
|
9f729900f2 | ||
|
|
422324723a | ||
|
|
5de499c7f6 | ||
|
|
12e033976b | ||
|
|
fc5839d8f1 | ||
|
|
32071445af | ||
|
|
bce62c49d0 | ||
|
|
7235bd19ea | ||
|
|
6a09a7c398 | ||
|
|
068ccf1c0f | ||
|
|
2a1434ce49 | ||
|
|
1b59fb5be9 | ||
|
|
3fe54894a5 | ||
|
|
2fec2c2fa0 | ||
|
|
ea4dbeaeb9 | ||
|
|
d705ee70f0 | ||
|
|
448717a757 | ||
|
|
4b3224702c | ||
|
|
ab307ec7f3 | ||
|
|
3dc9f792e6 | ||
|
|
9faa1fadcb | ||
|
|
cb04b7f4e2 | ||
|
|
de94b48d77 | ||
|
|
aca83479be | ||
|
|
d5564b476f | ||
|
|
3693f36e59 | ||
|
|
17063df3cc | ||
|
|
f417d9aa19 | ||
|
|
b91b47fc46 | ||
|
|
13206fbb69 | ||
|
|
d3d896dccd | ||
|
|
e78b358643 | ||
|
|
b757048544 | ||
|
|
ebe41fca53 | ||
|
|
96ad3a04d4 | ||
|
|
43ba5842bb | ||
|
|
b8979a7253 | ||
|
|
813b851c10 | ||
|
|
c1d7bef768 | ||
|
|
434a237764 | ||
|
|
945cb3254c | ||
|
|
9c2edba12b | ||
|
|
477e035f2e | ||
|
|
f3d4d2782f | ||
|
|
4f03a86414 | ||
|
|
6336edbc18 | ||
|
|
1f550be949 | ||
|
|
5f5bb8541b | ||
|
|
70ce5d0a32 | ||
|
|
5f22e7da1f | ||
|
|
2c28f8cdca | ||
|
|
4244ed33c8 | ||
|
|
0c62ab0683 | ||
|
|
aaa98e13b6 | ||
|
|
0ff99dddb9 | ||
|
|
2b22d11923 | ||
|
|
fa2e074b94 | ||
|
|
e75acce6ed | ||
|
|
390589fae2 | ||
|
|
ae41fa3011 | ||
|
|
b693c7515c | ||
|
|
3119d15de5 | ||
|
|
b99e7ed97e | ||
|
|
f32c34c726 | ||
|
|
15cb1d8980 | ||
|
|
99259d246b | ||
|
|
8c7076c04a | ||
|
|
81bae9a844 | ||
|
|
d7ce7271fe | ||
|
|
5ab64987eb | ||
|
|
dc46148ab6 | ||
|
|
1b1bbcecec | ||
|
|
ebad9cb502 | ||
|
|
d8005af8ee | ||
|
|
ba3ba0aca7 | ||
|
|
880893914a | ||
|
|
07a21e921d | ||
|
|
2193f222c5 | ||
|
|
f36ea13cb2 | ||
|
|
595a1fe852 | ||
|
|
3334e6bf61 | ||
|
|
0a82b75f2a | ||
|
|
5b563e3841 | ||
|
|
3a98ce775a | ||
|
|
8c27a10612 | ||
|
|
e3ce8048ad | ||
|
|
0d367d4b54 | ||
|
|
028ae7053b | ||
|
|
3f3b14130b | ||
|
|
820051d40b | ||
|
|
97499aaa75 | ||
|
|
cc89bc02f4 | ||
|
|
4cbcee7e15 | ||
|
|
ab47c2c734 | ||
|
|
3e6ec19fd4 | ||
|
|
5719e437ef | ||
|
|
dba7062fbc | ||
|
|
6786ffffac | ||
|
|
16320d66f2 | ||
|
|
ec6dd35098 | ||
|
|
f5f4689e7c | ||
|
|
259d330822 | ||
|
|
79be106711 | ||
|
|
5ccd3e2f84 | ||
|
|
4f8d22796a | ||
|
|
5be5ee9b1b | ||
|
|
679f2aa262 | ||
|
|
58034c24ce | ||
|
|
1ac9b50f21 | ||
|
|
af9dc4c277 | ||
|
|
f817a8ca3c | ||
|
|
97e5a04621 | ||
|
|
30294740bd | ||
|
|
6bf4edade1 | ||
|
|
de1e762528 | ||
|
|
d043ee9407 | ||
|
|
14766ad38e | ||
|
|
dfcf68f21d | ||
|
|
433070a135 | ||
|
|
d89c77af54 | ||
|
|
2d7d70b90f | ||
|
|
5dc905e35d | ||
|
|
660d44b6ad | ||
|
|
d3d39b3e17 | ||
|
|
3fd2f87b15 | ||
|
|
9e7a0f8d83 | ||
|
|
6703f0514d | ||
|
|
02f4eb53dd | ||
|
|
04597b3f54 | ||
|
|
4379f58213 | ||
|
|
2906d643a5 | ||
|
|
bec9504cd8 | ||
|
|
7a8889e7f5 | ||
|
|
8054f6a2d1 | ||
|
|
f2595917c6 | ||
|
|
55b40aeb65 | ||
|
|
4f2bca08f1 | ||
|
|
48d83a4dc4 | ||
|
|
2362f9574e | ||
|
|
8ba9b8d7bd | ||
|
|
c6d4b5cc86 | ||
|
|
0db55b6194 | ||
|
|
59da4a0b3b | ||
|
|
9192acf250 | ||
|
|
7e0f1a57af | ||
|
|
f5cd3d853d | ||
|
|
04d25dc58a | ||
|
|
56c83cefe9 | ||
|
|
6850a4d25d | ||
|
|
ad2065afc7 | ||
|
|
9710771f16 | ||
|
|
ea1164322b | ||
|
|
bee501da4a | ||
|
|
57b5b4c376 | ||
|
|
2c3d3d0fe3 | ||
|
|
d0d995da09 | ||
|
|
a3fe1efa2b | ||
|
|
e84d0dd6b3 | ||
|
|
0f3bf488f2 | ||
|
|
04ca85fe89 | ||
|
|
962b316bcf | ||
|
|
ae3b9617b6 | ||
|
|
3c554953a2 | ||
|
|
0b1044b46f | ||
|
|
ba56535fa6 | ||
|
|
2e0e8ba705 | ||
|
|
c283f0996d | ||
|
|
232f980c72 | ||
|
|
4a72c37fc1 | ||
|
|
dcfad7d61b | ||
|
|
9e892bddf0 | ||
|
|
109dd3240a | ||
|
|
c198242292 | ||
|
|
5bd5713a52 | ||
|
|
5c39a3d004 | ||
|
|
4e607876ea | ||
|
|
011fdf7ab6 | ||
|
|
708ddf5387 | ||
|
|
c75aa23092 | ||
|
|
6a2a6afc1d | ||
|
|
7c241fd617 | ||
|
|
c14a90a3d0 | ||
|
|
528f54153c | ||
|
|
ae7f18f981 | ||
|
|
f5f07bd552 | ||
|
|
bbbd3320ef | ||
|
|
32450640e2 | ||
|
|
3f96afba73 | ||
|
|
9e789e6d82 | ||
|
|
e1d078f2c1 | ||
|
|
563d5e3ad8 | ||
|
|
16fd256225 | ||
|
|
f3f79792ab | ||
|
|
ed68a4bb9a | ||
|
|
02a89c752b | ||
|
|
b9b63f695d | ||
|
|
7293ee0894 | ||
|
|
da41d99aa7 | ||
|
|
26e4809e2e | ||
|
|
e9e2fa2927 | ||
|
|
5b2715515f | ||
|
|
a8c90e2365 | ||
|
|
f66968ae02 | ||
|
|
a5fd40ed80 | ||
|
|
8cc4dae00b | ||
|
|
2c5f19253c | ||
|
|
09f2950256 | ||
|
|
65307c463a | ||
|
|
2ae0ef94de | ||
|
|
138e720695 | ||
|
|
12e28c1895 | ||
|
|
1a106e5c38 | ||
|
|
15c52cacfb | ||
|
|
4a93d205bb | ||
|
|
a146a24c06 | ||
|
|
6347b9b0d7 | ||
|
|
fea6b970e5 | ||
|
|
afeaa9fecd | ||
|
|
7e82626b17 | ||
|
|
9b9aab27ca | ||
|
|
31e5271921 | ||
|
|
8c977e37a9 | ||
|
|
9c8134f8bc | ||
|
|
36ec15be8f | ||
|
|
c29bf31f2b | ||
|
|
5b1727bcba | ||
|
|
7a14054057 | ||
|
|
481a4b0f1b | ||
|
|
fe34c8f2e0 | ||
|
|
923e18b2b9 | ||
|
|
596dfc304d | ||
|
|
47c6c6e1b7 | ||
|
|
afc52f57a2 | ||
|
|
0786977bcf | ||
|
|
181542249d | ||
|
|
0d165e67c9 | ||
|
|
978b12b0dc | ||
|
|
2ca849c0c4 | ||
|
|
3991d9dc06 | ||
|
|
60ae4afe87 | ||
|
|
4ed54f6aa9 | ||
|
|
17004ce3ae | ||
|
|
596ce18aeb | ||
|
|
5c9ef9d9da | ||
|
|
ad13fd0542 | ||
|
|
26eb6e559e | ||
|
|
946afccbb5 | ||
|
|
ea8307f79e | ||
|
|
83d798dbad | ||
|
|
7f5f6763ea | ||
|
|
8828db4fce | ||
|
|
56d8fe4a22 | ||
|
|
b6428b08d0 | ||
|
|
9223c95481 | ||
|
|
a3925e8aa0 | ||
|
|
7c8fa067a2 | ||
|
|
f2e9ec63df | ||
|
|
b97361b193 | ||
|
|
22652889b2 | ||
|
|
04a970eda2 | ||
|
|
f443b7087c | ||
|
|
9cb1170361 | ||
|
|
dda760b9b5 | ||
|
|
ca4124940a | ||
|
|
90cd10e034 | ||
|
|
c1d4acc01e | ||
|
|
81531a29eb | ||
|
|
7d4c319fcb | ||
|
|
ca37b24455 | ||
|
|
f6c07fdabd | ||
|
|
ed0fabd9de | ||
|
|
0767992662 | ||
|
|
a88187023d | ||
|
|
57dc12ee17 | ||
|
|
c9e5da48a4 | ||
|
|
7d69885e06 | ||
|
|
55ba8ad0c4 | ||
|
|
6263ec1d38 | ||
|
|
1d86d4b94f | ||
|
|
8aef2c13ec | ||
|
|
8722ee8ad6 | ||
|
|
1a44036148 | ||
|
|
e65a6cc063 | ||
|
|
29607d8951 | ||
|
|
366a9f71ad | ||
|
|
79f798f67b | ||
|
|
2c16b0f0f3 | ||
|
|
4df6668416 | ||
|
|
0140a00884 | ||
|
|
2a31f16b76 | ||
|
|
793eda7640 | ||
|
|
8230279932 | ||
|
|
a6df991b76 | ||
|
|
9cc0be0fc2 | ||
|
|
0d0d802526 | ||
|
|
71f09ddd94 | ||
|
|
17f1224a5d | ||
|
|
441e2ad2f3 | ||
|
|
39a6bf9784 | ||
|
|
8d130421c4 | ||
|
|
add4adeec9 | ||
|
|
e165e2af95 | ||
|
|
088ad881e0 | ||
|
|
c5afcd8e09 | ||
|
|
5c795e9a50 | ||
|
|
cd8f938cab | ||
|
|
2de6f3434c | ||
|
|
5269422f7c | ||
|
|
c9f06e1da1 | ||
|
|
c4fe9d50bf | ||
|
|
2c5828528f | ||
|
|
b1a95cacff | ||
|
|
20b64d9b7e | ||
|
|
ab55412264 | ||
|
|
f82cb3aefe | ||
|
|
48e5a82e7f | ||
|
|
727fc9d3a6 | ||
|
|
51c640d409 | ||
|
|
7ab83bf47f | ||
|
|
9818f81c5f | ||
|
|
8f4e440179 | ||
|
|
83bf68ecad | ||
|
|
23bbc5160e | ||
|
|
ed6d50d6ba | ||
|
|
b3a1bb2017 | ||
|
|
a0a4b04007 | ||
|
|
ddfb36b511 | ||
|
|
28f7806d19 | ||
|
|
72f6dc1e0c | ||
|
|
9a45a25e17 | ||
|
|
9cadf0aa97 | ||
|
|
397dfc54cd | ||
|
|
eeba128f8a | ||
|
|
396b687e4b | ||
|
|
cbe72ba9f4 | ||
|
|
85c1c97ea2 | ||
|
|
503e04d375 | ||
|
|
4e5d5cd1a9 | ||
|
|
9cdd9e6d5f | ||
|
|
f8a10fa7af | ||
|
|
e3764ad951 | ||
|
|
edb7722ad6 | ||
|
|
39ee394068 | ||
|
|
f4e26bba3f | ||
|
|
102c896046 | ||
|
|
e5fbbe96fd | ||
|
|
8e1b753664 | ||
|
|
b6d5f49c0f | ||
|
|
2cc9515fd6 | ||
|
|
0f63c04beb | ||
|
|
861e45aedf | ||
|
|
10820f31c2 | ||
|
|
3ab7b5c3f7 | ||
|
|
076905d14e | ||
|
|
d5471c153a | ||
|
|
69e7279cff | ||
|
|
9e58921b23 | ||
|
|
7fa6527ca8 | ||
|
|
2fa8096569 | ||
|
|
ff47eccf4b | ||
|
|
5a6c04e3b0 | ||
|
|
896e6d4662 | ||
|
|
d8db5189c1 | ||
|
|
525179eb85 | ||
|
|
dace35d31d | ||
|
|
3752379106 | ||
|
|
048b26a0fd | ||
|
|
07ec00641f | ||
|
|
60541a455f | ||
|
|
882ee4d49f | ||
|
|
f0b13153ac | ||
|
|
df51be02bf | ||
|
|
96798ac70c | ||
|
|
a28e4de3bd | ||
|
|
ac73e78b3a | ||
|
|
613e209af3 | ||
|
|
1ac3355b03 | ||
|
|
5e4b026668 | ||
|
|
9d5979c01d | ||
|
|
a712f1a231 | ||
|
|
42a5aefb23 | ||
|
|
bc673fd969 | ||
|
|
a127f2d572 | ||
|
|
16acdfc7c3 | ||
|
|
858d7be8cf | ||
|
|
1ca4ecc241 | ||
|
|
bd470abcf0 | ||
|
|
dfef4727b6 | ||
|
|
3e5223b98d | ||
|
|
0fe83d5198 | ||
|
|
6b6b97c8d8 | ||
|
|
5c3e366192 | ||
|
|
68a6a1bc15 | ||
|
|
7fef460fa2 | ||
|
|
4b7d802a9d | ||
|
|
04ec222462 | ||
|
|
97758380e0 | ||
|
|
b67f4dc390 | ||
|
|
ad3d15e28d | ||
|
|
1e3970c6e5 | ||
|
|
706481b1a3 | ||
|
|
66d9c4f1af | ||
|
|
cd17278c64 | ||
|
|
f424abf87c | ||
|
|
8a5c91021d | ||
|
|
ddc32d3cad | ||
|
|
26535e163f | ||
|
|
cefdd86634 | ||
|
|
56aa8ae6e0 | ||
|
|
aa613bc767 | ||
|
|
d272b0f56d | ||
|
|
6bc524dff8 | ||
|
|
496e5bdad9 | ||
|
|
f00e5936c9 | ||
|
|
6ea35fce66 | ||
|
|
3da90e09d5 | ||
|
|
20c6925470 | ||
|
|
465c72d98e | ||
|
|
59ade61687 | ||
|
|
1ddc2e68bf | ||
|
|
fcba5a6eeb | ||
|
|
2f7770b165 | ||
|
|
04d03f73b3 | ||
|
|
740709da04 | ||
|
|
2feab76a6f | ||
|
|
d95c5e6674 | ||
|
|
1d6413bfae | ||
|
|
3b5c813be7 | ||
|
|
e02e60171e | ||
|
|
b25bf363b3 | ||
|
|
9d0982f2f7 | ||
|
|
25316cbe0e | ||
|
|
cf5595bd64 | ||
|
|
12f2ca9262 | ||
|
|
5631d52f50 | ||
|
|
a7a8ea3077 | ||
|
|
1cff564483 | ||
|
|
c75e669204 | ||
|
|
1758412a76 | ||
|
|
aa261bbe23 | ||
|
|
017eab8dcd | ||
|
|
7e26d7a4bf | ||
|
|
c6e110100a | ||
|
|
a5e450a0dd | ||
|
|
757b185398 | ||
|
|
257519490a | ||
|
|
4572747bd6 | ||
|
|
6e5ef561eb | ||
|
|
95305e7e11 | ||
|
|
951ce0a102 | ||
|
|
11b74baf79 | ||
|
|
c0353ab5d8 | ||
|
|
9fa0a4c973 | ||
|
|
db371d2a5d | ||
|
|
01cce09ef2 | ||
|
|
d2f21bc93e | ||
|
|
5ba2423626 | ||
|
|
a6b0856020 | ||
|
|
9a641ee7c0 | ||
|
|
ab7e2f89fb | ||
|
|
71ab8d6afc | ||
|
|
ea5da627af | ||
|
|
1c8ef716a2 | ||
|
|
6fc451da9e | ||
|
|
b940f4a97d | ||
|
|
c2c81e7e6a | ||
|
|
1508d0ac23 | ||
|
|
d3c37bda71 | ||
|
|
c82e2d74bf | ||
|
|
1a11b400b0 | ||
|
|
1d8bb45d3a | ||
|
|
fc9de68ee9 | ||
|
|
1fb9bbba91 | ||
|
|
cd4fc78aec | ||
|
|
4e6a04923a | ||
|
|
83899eb884 | ||
|
|
3744bc3228 | ||
|
|
a0c8d3fa6f | ||
|
|
d3c13a1d8c | ||
|
|
3c8c53194f | ||
|
|
8ed9212401 | ||
|
|
5cef73331c | ||
|
|
5760fa104c | ||
|
|
4786e0f882 | ||
|
|
3bf7f6ed5f | ||
|
|
9e6df378c3 | ||
|
|
9667f324f1 | ||
|
|
eec178458b | ||
|
|
4ea5d80099 | ||
|
|
d9a33680a6 | ||
|
|
0a695ba17a | ||
|
|
afb847acc8 | ||
|
|
8bb9126b77 | ||
|
|
2379c5b770 | ||
|
|
581efa857b | ||
|
|
590c3b4b50 | ||
|
|
e750508d76 | ||
|
|
efe7279ead | ||
|
|
90925273a0 | ||
|
|
f1996a9f1f | ||
|
|
e411b8e423 | ||
|
|
d8e5be5782 | ||
|
|
7d70ffe201 | ||
|
|
a64a38d7dd | ||
|
|
8bfed7508c | ||
|
|
68a77c4051 | ||
|
|
38f237efcb | ||
|
|
2daffe2a15 | ||
|
|
1f987c1903 | ||
|
|
9a29b04561 | ||
|
|
1c5f902770 | ||
|
|
3be11b9861 | ||
|
|
c970e82758 | ||
|
|
a0036179d5 | ||
|
|
1532eb4278 | ||
|
|
64f98d2409 | ||
|
|
ed879df1f4 | ||
|
|
2b05dac071 | ||
|
|
507bff8b59 | ||
|
|
3912ed5023 | ||
|
|
984ece646f | ||
|
|
22156fe309 | ||
|
|
9637efd5ee | ||
|
|
52992928d5 | ||
|
|
aa9ca68883 | ||
|
|
aaa717aac2 | ||
|
|
4ece7fc038 | ||
|
|
9feb8a73fd | ||
|
|
d3cc6e518d | ||
|
|
f858f6b621 | ||
|
|
500e000661 | ||
|
|
4c73d970e5 | ||
|
|
becdaafdca | ||
|
|
3887aa72cb | ||
|
|
72d7a7d91d | ||
|
|
e1f410d32e | ||
|
|
cd5843e977 | ||
|
|
af3aa81d71 | ||
|
|
04bbdbad12 | ||
|
|
9d1dacb8d4 | ||
|
|
f3bb2d41a7 | ||
|
|
804bff55ec | ||
|
|
5b93e09714 | ||
|
|
fdfcc3ab2a | ||
|
|
cf344abff2 | ||
|
|
5ec07db143 | ||
|
|
67b935188b | ||
|
|
0dfd09ed0e | ||
|
|
6f63d63ee0 | ||
|
|
961ebbde6b | ||
|
|
50a5355de0 | ||
|
|
f25cffd24e | ||
|
|
5e18afe916 | ||
|
|
733a9af629 | ||
|
|
166ce7d2ae | ||
|
|
5833867b44 | ||
|
|
6cc1502c89 | ||
|
|
ced5e5500e | ||
|
|
7b17e38f5d | ||
|
|
e58cd91487 | ||
|
|
10fd66b7c5 | ||
|
|
9f4ea7301a | ||
|
|
14e1bc8702 | ||
|
|
cc21c66b3a | ||
|
|
1e9c51072a | ||
|
|
4544f79471 | ||
|
|
a3da11c5bc | ||
|
|
66631da1c7 | ||
|
|
d6f9ff34ce | ||
|
|
a1e39ce24d | ||
|
|
c39f9ed2f3 | ||
|
|
3a27b610d5 | ||
|
|
3dc30e4d8b | ||
|
|
1a49d51d42 | ||
|
|
0b46196ff5 | ||
|
|
ea6cea6f29 | ||
|
|
93fb02509b | ||
|
|
09a0ef2013 | ||
|
|
ccbe055e5b | ||
|
|
8e65f36131 | ||
|
|
b66894f727 | ||
|
|
dc16c8c60c | ||
|
|
92c3d80189 | ||
|
|
68cc3f86dd | ||
|
|
1d769fe41c | ||
|
|
4edf0c9768 | ||
|
|
d562dcd90c | ||
|
|
f99e1ba441 | ||
|
|
1b9b8ba2bf | ||
|
|
16f7f68636 | ||
|
|
c1272de462 | ||
|
|
31cf8812f6 | ||
|
|
a81a5315e1 | ||
|
|
f332f22bed | ||
|
|
08ae183877 | ||
|
|
c4ce553936 | ||
|
|
6f987253ac | ||
|
|
1f1244f285 | ||
|
|
3cf775a1f6 | ||
|
|
979349388c | ||
|
|
cdcf88cbdf | ||
|
|
d573ee22f1 | ||
|
|
18ff1569b9 | ||
|
|
3226a3a58e | ||
|
|
164435f71d | ||
|
|
6d814af0cc | ||
|
|
ffbbb5bc9e | ||
|
|
d3e11cabd5 | ||
|
|
35326e1d92 | ||
|
|
9d629f2780 | ||
|
|
1ae52d2472 | ||
|
|
37ba2511d5 | ||
|
|
bcdbec61d7 | ||
|
|
d03949a735 | ||
|
|
63fa9f4535 | ||
|
|
3f266a3e1b | ||
|
|
a5c8bbfe1f | ||
|
|
584f40d0c4 | ||
|
|
72974719ac | ||
|
|
d4c3463f68 | ||
|
|
47e4b77140 | ||
|
|
3e07605260 | ||
|
|
49b18e17d7 | ||
|
|
7c6f0ad445 | ||
|
|
0e3f91508e | ||
|
|
34427f34e8 | ||
|
|
4131b75562 | ||
|
|
62af885c09 | ||
|
|
344812f1e0 | ||
|
|
d06174fb56 | ||
|
|
72d9532207 | ||
|
|
ab052a5ed3 | ||
|
|
6ebf766342 | ||
|
|
d1b31bb3d6 | ||
|
|
19c70a126f | ||
|
|
4cc8a9bd18 | ||
|
|
9be53f0a79 | ||
|
|
f25a415a9e | ||
|
|
5feed2344a | ||
|
|
9ba34aabab | ||
|
|
0b855aeac9 | ||
|
|
176c042cb6 | ||
|
|
db4ab8d8a7 | ||
|
|
836f48b24c | ||
|
|
9e01740193 | ||
|
|
b77a2d0f42 | ||
|
|
c83b0f2680 | ||
|
|
5a3d3f5098 | ||
|
|
30c7cb80f9 | ||
|
|
a71e54113e | ||
|
|
dff19db58d | ||
|
|
31520844b4 | ||
|
|
282b3b3170 | ||
|
|
55bc150701 | ||
|
|
fc88429282 | ||
|
|
ee443d91dd | ||
|
|
318338f967 | ||
|
|
29c9330965 | ||
|
|
7c72705bc5 | ||
|
|
ad4cf373a6 | ||
|
|
33e3fc70b2 | ||
|
|
9c3cd87bee | ||
|
|
f8ddfec98c | ||
|
|
53ff171436 | ||
|
|
75c77a44c9 | ||
|
|
11b44f2b01 | ||
|
|
d1e33ec071 | ||
|
|
39f3cfc1eb | ||
|
|
2f811375bb | ||
|
|
8d7390e765 | ||
|
|
8268c65c57 | ||
|
|
f9b0a01c74 | ||
|
|
0a4ccdcef2 | ||
|
|
2b02c87b16 | ||
|
|
e738a67e06 | ||
|
|
b2f70c12b9 | ||
|
|
c4a48b35c0 | ||
|
|
9cc47b6b58 | ||
|
|
41083b08ce | ||
|
|
8d6b09e995 | ||
|
|
599a77c776 | ||
|
|
d7e796097a | ||
|
|
79e5dd3794 | ||
|
|
ef90f1dca6 | ||
|
|
aafe2c5b98 | ||
|
|
e9fcca16bd | ||
|
|
c04a2ababd | ||
|
|
8faa806c90 | ||
|
|
164d11c816 | ||
|
|
27b11b1d79 | ||
|
|
d9386cc2c3 | ||
|
|
38f348e642 | ||
|
|
656ec9c48f | ||
|
|
ec98c201e4 | ||
|
|
47f226be3b | ||
|
|
f3132b4513 | ||
|
|
cfabccc5f2 | ||
|
|
f5e8f9334b | ||
|
|
7be2105fd9 | ||
|
|
49ee388dcf | ||
|
|
6cb4b4061c | ||
|
|
85e50ece2e | ||
|
|
32ae0ea13e | ||
|
|
a55a606a55 | ||
|
|
22bf20a135 | ||
|
|
5dcf6ff2d3 | ||
|
|
dede578c7d | ||
|
|
607b0c0c0e | ||
|
|
d5a59ac6b7 | ||
|
|
ccba95542b | ||
|
|
36c46112df | ||
|
|
1b3bddd622 | ||
|
|
e5811e29b1 | ||
|
|
525b367a6f | ||
|
|
a7c816c65e | ||
|
|
a2a0e0394d | ||
|
|
d69258e28f | ||
|
|
4e542d8b83 | ||
|
|
731bb6ba03 | ||
|
|
fed06ef97d | ||
|
|
ce947d4793 | ||
|
|
ad91093902 | ||
|
|
a58330f4d8 | ||
|
|
5a46c2397b | ||
|
|
adf4e72cf8 | ||
|
|
0e97030716 | ||
|
|
c7ed348ee8 | ||
|
|
27f07e9de2 | ||
|
|
adb1502e72 | ||
|
|
f79588c191 | ||
|
|
b70a3f0958 | ||
|
|
b3b096e204 | ||
|
|
f665a30d28 | ||
|
|
53b00d80d6 | ||
|
|
705455d5d6 | ||
|
|
973b9cad36 | ||
|
|
1663cbbb34 | ||
|
|
26ec858903 | ||
|
|
9f766557f1 | ||
|
|
6c351c724d | ||
|
|
373118c5ee | ||
|
|
a40c6e65dd | ||
|
|
29749809d2 | ||
|
|
846cf934f5 | ||
|
|
162eb4ca35 | ||
|
|
2f18444a43 | ||
|
|
8a4ff5bddc | ||
|
|
4ae7648bea | ||
|
|
dc75559758 | ||
|
|
acd944a649 | ||
|
|
3c1b30e3c1 | ||
|
|
5daefc8b8e | ||
|
|
715b9cbad0 | ||
|
|
7194e91d3b | ||
|
|
69d56b8ed7 | ||
|
|
982a5b1a39 | ||
|
|
6b8cb4ac7f | ||
|
|
397f253180 | ||
|
|
f93b6f7d85 | ||
|
|
edb2cf2cf2 | ||
|
|
fb12dd4688 | ||
|
|
0a561e5aeb | ||
|
|
c140c8cac9 | ||
|
|
06ab063671 | ||
|
|
1591a486cc | ||
|
|
b53efed1ef | ||
|
|
7a202db5ad | ||
|
|
af1ae7cab4 | ||
|
|
24519cbf78 | ||
|
|
01305462aa | ||
|
|
90ae59ccaf | ||
|
|
ff6a2d014a | ||
|
|
246f41b88a | ||
|
|
a799fac983 | ||
|
|
50164324f3 | ||
|
|
634d8c9978 | ||
|
|
e5eb0e3874 | ||
|
|
63273f4ccf | ||
|
|
7a4077405e | ||
|
|
9594effb6c | ||
|
|
e750498696 | ||
|
|
69e18905f5 | ||
|
|
ac4524cf9b | ||
|
|
7baad7ff10 | ||
|
|
d7ef6daeb8 | ||
|
|
d8d5516e24 | ||
|
|
93e3908a63 | ||
|
|
d7ee4b4573 | ||
|
|
bf5f6ce97c | ||
|
|
ed2ca5fced | ||
|
|
8dfe85f23e | ||
|
|
a492eceff0 | ||
|
|
be781bdb98 | ||
|
|
a8f915f049 | ||
|
|
e750080f00 | ||
|
|
79beefe57c | ||
|
|
fcdcd63dc7 | ||
|
|
846992930c | ||
|
|
a1d652d578 | ||
|
|
d0e057722b | ||
|
|
f04932aa67 | ||
|
|
d1be4e2a90 | ||
|
|
3cde783d1d | ||
|
|
e933369f56 | ||
|
|
e109f8d69c | ||
|
|
d198057eaf | ||
|
|
88c2f18b20 | ||
|
|
a30a604228 | ||
|
|
4eefa73441 | ||
|
|
00b4d233cc | ||
|
|
eb2c078898 | ||
|
|
4b5eadf7b5 | ||
|
|
9b68911d00 | ||
|
|
62b58d8bb0 | ||
|
|
a5951592f7 | ||
|
|
6392d6514e | ||
|
|
91d6641326 | ||
|
|
dd398f73c2 | ||
|
|
de10bd4ef6 | ||
|
|
56321da9c1 | ||
|
|
d0d1c5ea5f | ||
|
|
e16872c864 | ||
|
|
1e425244d2 | ||
|
|
0c6618d2f6 | ||
|
|
a9d7823186 | ||
|
|
6c0f5329aa | ||
|
|
a677a4feff | ||
|
|
4f674c8d19 | ||
|
|
e197163019 | ||
|
|
7ba0099fa9 | ||
|
|
f45797ec4b | ||
|
|
02e1ac12b2 | ||
|
|
bde138177d | ||
|
|
2423f470ef | ||
|
|
e5219af481 | ||
|
|
21a4f3cc05 | ||
|
|
a9d9939bdd | ||
|
|
41fb2b4cc4 | ||
|
|
526e232c09 | ||
|
|
f2ed3d3ff2 | ||
|
|
f5b1b192a0 | ||
|
|
a77c33d9b7 | ||
|
|
640c558446 | ||
|
|
c11ce99bb3 | ||
|
|
8ad83b8d58 | ||
|
|
873d3d7c4a | ||
|
|
d4adaaaf2b | ||
|
|
104493e725 | ||
|
|
b172e7afdc | ||
|
|
b1efbeb220 | ||
|
|
f2a6657b72 | ||
|
|
4eb4974909 | ||
|
|
3e2c898881 | ||
|
|
2fb176a244 | ||
|
|
53a6a7b305 | ||
|
|
2045380223 | ||
|
|
1c0fc3c924 | ||
|
|
0b966b7a28 | ||
|
|
882a477c0f | ||
|
|
ebcf2c3f68 | ||
|
|
54fafb3a76 | ||
|
|
01bd662046 | ||
|
|
98d934c8a4 | ||
|
|
9e26d3e85d | ||
|
|
17114778b7 | ||
|
|
98037ca0c6 | ||
|
|
4ec59e8211 | ||
|
|
1e6a5ff8ec | ||
|
|
c12d830162 | ||
|
|
a49a9b3b64 | ||
|
|
5da3da5962 | ||
|
|
8bb51d47f8 | ||
|
|
381b9ee7ee | ||
|
|
a301c96c9d | ||
|
|
f9c3cdab67 | ||
|
|
27ec0d532e | ||
|
|
3aa619b617 | ||
|
|
ef92272bee | ||
|
|
815ef05daf | ||
|
|
2ab19148c1 | ||
|
|
d12f4a4aee | ||
|
|
81b1939f92 | ||
|
|
834daeecd0 | ||
|
|
6aa0208316 | ||
|
|
aa87d8eb22 | ||
|
|
cd21fa7016 | ||
|
|
7ba4f6b93f | ||
|
|
e16a51ad06 | ||
|
|
6861dc137f | ||
|
|
e530e4d4bc | ||
|
|
d150bc1e52 | ||
|
|
cc8961360a | ||
|
|
c0539e483e | ||
|
|
f0b7099be3 | ||
|
|
ee183d4574 | ||
|
|
fa813024ca | ||
|
|
37176fa42d | ||
|
|
7ff8931def | ||
|
|
2a962bf8fd | ||
|
|
bbbcba8b98 | ||
|
|
ecdcd10612 | ||
|
|
10ea140358 | ||
|
|
74e0309241 | ||
|
|
c88bfbbf82 | ||
|
|
4edb89eeb9 | ||
|
|
cdb4b3cc7d | ||
|
|
ed8dd03fa1 | ||
|
|
e5bb7f7c2d | ||
|
|
a7b0f6dc9f | ||
|
|
c42986c07d | ||
|
|
a982dd1765 | ||
|
|
c3900398fc | ||
|
|
4b79a5e9da | ||
|
|
eed2feea97 | ||
|
|
60a2d9f624 | ||
|
|
3cd33b6ffc | ||
|
|
e3942b3438 | ||
|
|
0bf37b8c00 | ||
|
|
0e5dbf3889 | ||
|
|
785f96aabe | ||
|
|
5cec936128 | ||
|
|
02861142cb | ||
|
|
1cfc4d2f31 | ||
|
|
08e816a539 | ||
|
|
272cf64aac | ||
|
|
ed57a4099b | ||
|
|
79c5d48a3c | ||
|
|
6c70122e55 | ||
|
|
6c83699e6f | ||
|
|
ff254ce08d | ||
|
|
8a80ea26b8 | ||
|
|
b85fe62389 | ||
|
|
31a4d9204c | ||
|
|
69fdfd5cb3 | ||
|
|
16e7980982 | ||
|
|
e3e08cf8e7 | ||
|
|
cae6626b06 | ||
|
|
956d93e871 | ||
|
|
7c4d1b7b01 | ||
|
|
9866e0851b | ||
|
|
0a97a2435b | ||
|
|
5c80f03eae | ||
|
|
dd03a4b011 | ||
|
|
6cd1bc32fe | ||
|
|
dd0193a9a8 | ||
|
|
123faa6f8e | ||
|
|
f743288ce0 | ||
|
|
a1d764bd26 | ||
|
|
61f6bd2c80 | ||
|
|
fe620d8e44 | ||
|
|
22db28d3e7 | ||
|
|
1330488e13 | ||
|
|
22297be3cf | ||
|
|
29d7d6994a | ||
|
|
87e8162a2d | ||
|
|
38b71bf386 | ||
|
|
920689b80e | ||
|
|
e9c7523646 | ||
|
|
88bbc720ca | ||
|
|
1bf1469c80 | ||
|
|
c74eda20dc | ||
|
|
db0a5bd537 | ||
|
|
c6cb01aa3b | ||
|
|
7463f91878 | ||
|
|
482b31298f | ||
|
|
ce46ca2f39 | ||
|
|
de00d18a7e | ||
|
|
b0cf0c558d | ||
|
|
920e5c93e1 | ||
|
|
0aae78c6bd | ||
|
|
7fb048f423 | ||
|
|
e86207bb28 | ||
|
|
d7cd2b970e | ||
|
|
450d242d5f | ||
|
|
2783196547 | ||
|
|
e84f06b503 | ||
|
|
75d60ccb69 | ||
|
|
9245cd6aae | ||
|
|
d8183b60c3 | ||
|
|
a24272690d | ||
|
|
40b088d6a2 | ||
|
|
f1125d64de | ||
|
|
0cba818364 | ||
|
|
4285c751b3 | ||
|
|
1b0cddfa72 | ||
|
|
231a599f09 | ||
|
|
7ffc4d388a | ||
|
|
1f24171238 | ||
|
|
24917a6df5 | ||
|
|
67fde17209 | ||
|
|
6abad666db | ||
|
|
222319d924 | ||
|
|
2d3f396571 | ||
|
|
201e1d3e6d | ||
|
|
2c72831be1 | ||
|
|
a4204880e8 | ||
|
|
51bcbdac75 | ||
|
|
5d120de70e | ||
|
|
e63889d5c4 | ||
|
|
fe6a7c58bf | ||
|
|
5f1b4e6183 | ||
|
|
1e81f8ecfc | ||
|
|
dac3cb15c4 | ||
|
|
ca654ccaf7 | ||
|
|
30512b7032 | ||
|
|
bc8fd62cff | ||
|
|
a9a51ee3c6 | ||
|
|
28c5fc48ee | ||
|
|
2d2da7c881 | ||
|
|
d22d8c4905 | ||
|
|
bcdc8eafa6 | ||
|
|
9cf6ace979 | ||
|
|
eef063cec2 | ||
|
|
8b9bdf9054 | ||
|
|
05f9e5eef1 | ||
|
|
eb28e63c08 | ||
|
|
1c7b898b01 | ||
|
|
7ad18da08e | ||
|
|
5530915b49 | ||
|
|
4a73e2d0e9 | ||
|
|
b499bdea3b | ||
|
|
de1de852fc | ||
|
|
77f380c94b | ||
|
|
c34d2f91cc | ||
|
|
ee42ea5f3b | ||
|
|
c79ab84fdf | ||
|
|
d77448d84e | ||
|
|
8fc5a2785f | ||
|
|
27da2b026f | ||
|
|
2e9cc2a74e | ||
|
|
ffd370176d | ||
|
|
44f2a375f6 | ||
|
|
05cb97819c | ||
|
|
282c834d9f | ||
|
|
4a6ff9e2aa | ||
|
|
ce972d4f19 | ||
|
|
b250d10320 | ||
|
|
8a2541c220 | ||
|
|
6991e5f3ef | ||
|
|
f63706d118 | ||
|
|
c41aa64719 | ||
|
|
285d246c65 | ||
|
|
2c85205259 | ||
|
|
2d866b9298 | ||
|
|
7a7629acf7 | ||
|
|
debf820037 | ||
|
|
f908ae8c40 | ||
|
|
022cbdda31 | ||
|
|
ae2523aa59 | ||
|
|
bf361d2b02 | ||
|
|
64f3303711 | ||
|
|
06f382c454 | ||
|
|
5f164d99ac | ||
|
|
2473ae3b47 | ||
|
|
3fb457ccd1 | ||
|
|
51333c9eda | ||
|
|
1aaf3961ff | ||
|
|
af4f3f62e9 | ||
|
|
cc31a12b8c | ||
|
|
bc9989f9be | ||
|
|
7f33bec71c | ||
|
|
3ea94c3484 | ||
|
|
68adaea128 | ||
|
|
4997068a0d | ||
|
|
4c59ec815e | ||
|
|
440ea666d9 | ||
|
|
6f1a6d5a56 | ||
|
|
69e80fd11c | ||
|
|
bef8cc2d70 | ||
|
|
eaa899e9cf | ||
|
|
743c95d0f9 | ||
|
|
a08cb52ad9 | ||
|
|
b9604bf3bc | ||
|
|
978a345ad8 | ||
|
|
d5ffe6acef | ||
|
|
622c1a1dad | ||
|
|
79fea549ef | ||
|
|
bce6e75cfa | ||
|
|
34f36fff5c | ||
|
|
f4e24038fe | ||
|
|
81747e1623 | ||
|
|
d6f1c379c0 | ||
|
|
6794260e3f | ||
|
|
1be840f19d | ||
|
|
f59bb6461a | ||
|
|
bd3bae3af0 | ||
|
|
0fbace7285 | ||
|
|
af8fec941c | ||
|
|
139791b0d8 | ||
|
|
7fe76d32d0 | ||
|
|
352ad3385a | ||
|
|
010baad532 | ||
|
|
69d2a8f4fa | ||
|
|
3bba8b2c26 | ||
|
|
d584076b93 | ||
|
|
b0b77d667c | ||
|
|
071ac0dc85 | ||
|
|
ed8f5dbd22 | ||
|
|
5dfeddf583 | ||
|
|
cd9306df45 | ||
|
|
e0dc530e94 | ||
|
|
af52b20c4a | ||
|
|
e82d171041 | ||
|
|
19a35673fa | ||
|
|
639a44d996 | ||
|
|
4f261389db | ||
|
|
6003fee33f | ||
|
|
b56c3eb035 | ||
|
|
015c929bd7 | ||
|
|
992efda7f6 | ||
|
|
32036d017e | ||
|
|
40ff57d8c4 | ||
|
|
cdabe50320 | ||
|
|
c62ee78cba | ||
|
|
a19a2c70ab | ||
|
|
40a491a80b | ||
|
|
a9a06ad51d | ||
|
|
c65b7d1591 | ||
|
|
c287405471 | ||
|
|
06ec91c899 | ||
|
|
10f9022d7c | ||
|
|
e78c48620f | ||
|
|
563dd898c1 | ||
|
|
a97bcc3ca7 | ||
|
|
fa31fc046e | ||
|
|
a68a179c1e | ||
|
|
77b0d36b55 | ||
|
|
1705734435 | ||
|
|
e5fd35db34 | ||
|
|
158b708eac | ||
|
|
aa47eeffb2 | ||
|
|
df00ac736f | ||
|
|
f2a6fc4d5a | ||
|
|
c9501d1119 | ||
|
|
323ff3d491 | ||
|
|
98b3126e32 | ||
|
|
88ea524f44 | ||
|
|
a0ab9113fc | ||
|
|
31398718e5 | ||
|
|
4dfe8b6f69 | ||
|
|
6dae8f44b9 | ||
|
|
4f798cfe56 | ||
|
|
d8ea970f18 | ||
|
|
ecafc7bf8f | ||
|
|
bba3f3000f | ||
|
|
4b382e0faf | ||
|
|
2380a26987 | ||
|
|
d40e21a7e0 | ||
|
|
94d2ae2a6a | ||
|
|
3099198e47 | ||
|
|
48e9b5f4be | ||
|
|
430e2e439b | ||
|
|
81a21c03b2 | ||
|
|
064a97e734 | ||
|
|
5e9ed95684 | ||
|
|
017d5617a5 | ||
|
|
26bb2e0193 | ||
|
|
ff91430fcc | ||
|
|
32a41a8422 | ||
|
|
8b93e20a0b | ||
|
|
92bec31ccb | ||
|
|
f133a9de79 | ||
|
|
9b2476451e | ||
|
|
b876d193c4 | ||
|
|
3944c37627 | ||
|
|
14080d1531 | ||
|
|
96a0d0aefa | ||
|
|
15f2b2cf9a | ||
|
|
bf9eaea334 | ||
|
|
7b45a2ec51 | ||
|
|
48eb2083f2 | ||
|
|
2c6ea276c1 | ||
|
|
5a3db0505f | ||
|
|
6ca73f6df0 | ||
|
|
762dab618a | ||
|
|
a65c61442e | ||
|
|
4883b2a296 | ||
|
|
b1abe72ab6 | ||
|
|
a640d55297 | ||
|
|
99009a11ed | ||
|
|
2150bbf191 | ||
|
|
6f8cb743b5 | ||
|
|
682d2a1675 | ||
|
|
6022784e42 | ||
|
|
4d4478d969 | ||
|
|
c0935c84ee | ||
|
|
17e040abe4 | ||
|
|
6152a5e3c2 | ||
|
|
4558486cbd | ||
|
|
3df592c702 | ||
|
|
05fabc73c2 | ||
|
|
e949761107 | ||
|
|
4311a20c5f | ||
|
|
1440d1a147 | ||
|
|
4b170ca9a3 | ||
|
|
d6e844c67c | ||
|
|
71a307270a | ||
|
|
0f88b470e8 | ||
|
|
4798aa4789 | ||
|
|
a9d96ccc8c | ||
|
|
e0c9ddbfba | ||
|
|
bbc5dae1d2 | ||
|
|
9e7c55728f | ||
|
|
a6fa01f89b | ||
|
|
6c71754e51 | ||
|
|
e729b3734d | ||
|
|
6337c77532 | ||
|
|
fb08b71884 | ||
|
|
d749549135 | ||
|
|
58a2ab4fbd | ||
|
|
cc96cfe0c7 | ||
|
|
656b3e53a8 | ||
|
|
4e5dcafa1b | ||
|
|
afc8380f23 | ||
|
|
0319051891 | ||
|
|
4805a3bc23 | ||
|
|
dc63f0ddd0 | ||
|
|
6ff188e4d9 | ||
|
|
44edaad19d | ||
|
|
5304221e46 | ||
|
|
c6b1fe5349 | ||
|
|
80574334cf | ||
|
|
dd4eaa0758 | ||
|
|
93550e9ea5 | ||
|
|
3157fc651d | ||
|
|
dd4f27e3fa | ||
|
|
455e80513b | ||
|
|
65af872ec6 | ||
|
|
917cd35005 | ||
|
|
b989183fce | ||
|
|
0845d5d451 | ||
|
|
f002ef105e | ||
|
|
3d202c2ef9 | ||
|
|
953eec7326 | ||
|
|
c3956b4d6f | ||
|
|
d2421bb216 | ||
|
|
afdc19ce9d | ||
|
|
4a9380cc95 | ||
|
|
9f60745e57 | ||
|
|
666d640216 | ||
|
|
cb479d737b | ||
|
|
4ee455fad2 | ||
|
|
2da04e72f5 | ||
|
|
141ea7ba91 | ||
|
|
5ae0239c26 | ||
|
|
2dc4434a49 | ||
|
|
39c068bd53 | ||
|
|
b26dfd8246 | ||
|
|
3185db9609 | ||
|
|
61a618e473 | ||
|
|
c4a4ecfc81 | ||
|
|
f9b0ce0f75 | ||
|
|
20607c00b1 | ||
|
|
12e2bf2f85 | ||
|
|
685a2fec6c | ||
|
|
f9cd4a4470 | ||
|
|
b761aad903 | ||
|
|
9ee4fcb36c | ||
|
|
1929490deb | ||
|
|
bb3b31829f | ||
|
|
e0a58dd1fe | ||
|
|
7d6e04ac77 | ||
|
|
6502cff8fe | ||
|
|
fdffb03eba | ||
|
|
d4d3ae7530 | ||
|
|
647feb7b33 | ||
|
|
625781c7f4 | ||
|
|
02ef6c4e07 | ||
|
|
43eba6cc31 | ||
|
|
3775991ac8 | ||
|
|
08d2492839 | ||
|
|
d0d0e8349f | ||
|
|
1a97f79d54 | ||
|
|
9fc6c4888f | ||
|
|
f2de18508a | ||
|
|
6342571afe | ||
|
|
00e5bb61fc | ||
|
|
b506e7c267 | ||
|
|
061d1262d4 | ||
|
|
8b3c89e267 | ||
|
|
c634ee81fc | ||
|
|
6969a4121c | ||
|
|
4f8b2ad245 | ||
|
|
03353cb652 | ||
|
|
6f80862517 | ||
|
|
edd8d63caf | ||
|
|
ffbdea78ee | ||
|
|
47a20e6a2f | ||
|
|
c00384ad06 | ||
|
|
31fe471da5 | ||
|
|
c684b1ddab | ||
|
|
477f66f56b | ||
|
|
359bca0634 | ||
|
|
8a80623d0c | ||
|
|
adbe8142b6 | ||
|
|
3579a18da8 | ||
|
|
36882ea2a4 | ||
|
|
3fec2cdfd6 | ||
|
|
07d8b542bf | ||
|
|
06de80f2a7 | ||
|
|
ef351bb9a3 | ||
|
|
28de5cbd97 | ||
|
|
39cdf85788 | ||
|
|
37e19cee20 | ||
|
|
b39fbff8fa | ||
|
|
5ff15f27b7 | ||
|
|
baf99e8650 | ||
|
|
7c3046e011 | ||
|
|
1bc8526640 | ||
|
|
0795af8d42 | ||
|
|
bd7c045b1c | ||
|
|
c6812f569f | ||
|
|
17ffb167e2 | ||
|
|
019d077f5a | ||
|
|
c000f438ae | ||
|
|
c0d7ddf1fb | ||
|
|
5bf794e24e | ||
|
|
a9cfb160c9 | ||
|
|
468c9a9061 | ||
|
|
da1279aa5b | ||
|
|
3ec053bea7 | ||
|
|
b2f9f81eaf | ||
|
|
939e957fda | ||
|
|
062fe72030 | ||
|
|
cdcbb872d5 | ||
|
|
048763053c | ||
|
|
c6489d9b01 | ||
|
|
299053f2d5 | ||
|
|
937ac84538 | ||
|
|
5c0d1355a5 | ||
|
|
a64604de6b | ||
|
|
1a3dac0c17 | ||
|
|
ffd73e8bfb | ||
|
|
27c536b1a1 | ||
|
|
631c7adf12 | ||
|
|
d8dca20332 | ||
|
|
dc5973a0f3 | ||
|
|
efed13b9fe | ||
|
|
34ab1e529b | ||
|
|
b812b1c579 | ||
|
|
c892d9d6f6 | ||
|
|
b89480a284 | ||
|
|
9951c3825e | ||
|
|
9ac1f6b26b | ||
|
|
dac4954215 | ||
|
|
5846c71095 | ||
|
|
142f081d1e | ||
|
|
ec2b4f584c | ||
|
|
88d991ef45 | ||
|
|
dc382a6df7 | ||
|
|
c6e57d64d7 | ||
|
|
dc3cd430c8 | ||
|
|
9848600335 | ||
|
|
cd79b73cb0 | ||
|
|
21aa1b43fd | ||
|
|
2f3a96f7a7 | ||
|
|
b761dcde45 | ||
|
|
b6cdb0f885 | ||
|
|
472969ae2a | ||
|
|
9e3514a993 | ||
|
|
aee3ddd06a | ||
|
|
9558d404fa | ||
|
|
0ca6b67132 | ||
|
|
9390b1eef5 | ||
|
|
0198167b27 | ||
|
|
83e9bc4816 | ||
|
|
87bf6b3800 | ||
|
|
7b3df02640 | ||
|
|
499246abae | ||
|
|
71f78cc895 | ||
|
|
5896eee693 | ||
|
|
ce6b60653c | ||
|
|
2b865e3505 | ||
|
|
dee0e5fce7 | ||
|
|
56269758c4 | ||
|
|
436f6bda3e | ||
|
|
4d1102db0b | ||
|
|
4987a2158e | ||
|
|
435a5a67bc | ||
|
|
fc686ca618 | ||
|
|
ec99096d52 | ||
|
|
9e30599f1f | ||
|
|
472e1c6d8e | ||
|
|
46edd6008f | ||
|
|
68e520fa2d | ||
|
|
d46e612cb1 | ||
|
|
e7ce371ee8 | ||
|
|
bfe1ef0733 | ||
|
|
56d449b2ce | ||
|
|
c690d4aae8 | ||
|
|
4966b10a0f | ||
|
|
c48df8522a | ||
|
|
b0a2c26b22 | ||
|
|
24579d86d2 | ||
|
|
71573fb5a0 | ||
|
|
f865da6d6a | ||
|
|
3a5f718da8 | ||
|
|
8699dec571 | ||
|
|
6f0c6281e7 | ||
|
|
58e4dc1b6c | ||
|
|
17c03bed21 | ||
|
|
4bfc5355db | ||
|
|
37b3b1fc3a | ||
|
|
d865618051 | ||
|
|
a995857cca | ||
|
|
fdbdebac32 | ||
|
|
a242c40b23 | ||
|
|
f82b84eac7 | ||
|
|
70be333691 | ||
|
|
3d9a4dcbf3 | ||
|
|
577efbf0c2 | ||
|
|
a3fca638ee | ||
|
|
027855f891 | ||
|
|
b9b04fd932 | ||
|
|
2b1dcaf5e3 | ||
|
|
9e32a5613d | ||
|
|
61b43a0828 | ||
|
|
7fc1fed91e | ||
|
|
1fd97f8732 | ||
|
|
aa03de8e52 | ||
|
|
eb9a7267bd | ||
|
|
21b7c6a2c0 | ||
|
|
4cd53ce119 | ||
|
|
e2283e53b6 | ||
|
|
d51d5af992 | ||
|
|
b98a8ee83a | ||
|
|
21cf1f6c47 | ||
|
|
918ea5d12f | ||
|
|
3b7551e1e4 | ||
|
|
5dbc0aedcc | ||
|
|
8819d559b7 | ||
|
|
448a5c00fd | ||
|
|
8194c62f4e | ||
|
|
e75debbf81 | ||
|
|
380f707285 | ||
|
|
1bc277fd87 | ||
|
|
5b475a05ef | ||
|
|
f69dcf38ef | ||
|
|
c669f8c612 | ||
|
|
966ba97b2c | ||
|
|
675688cb80 | ||
|
|
f068b2c1d3 | ||
|
|
3dd383ba11 | ||
|
|
3a0983d8bf | ||
|
|
59c7edfd90 | ||
|
|
660fbfd73c | ||
|
|
bc7ef28644 | ||
|
|
7b011c1d96 | ||
|
|
a0780ce48a | ||
|
|
8154b4f60d | ||
|
|
91a6ae756f | ||
|
|
3fffd08ae4 | ||
|
|
abc8077a96 | ||
|
|
eb6099a93f | ||
|
|
5a125c7fe5 | ||
|
|
02fb2baf62 | ||
|
|
23c9f973cc | ||
|
|
db90fa71d4 | ||
|
|
c416b09089 | ||
|
|
f144593c06 | ||
|
|
c3a6ae1622 | ||
|
|
76aab2a2ac | ||
|
|
5337756792 | ||
|
|
8ed4859bb5 | ||
|
|
a02effc32e | ||
|
|
965c1f0353 | ||
|
|
e7086cf6df | ||
|
|
af073dad46 | ||
|
|
1e7beffafd | ||
|
|
c2c16b6bd2 | ||
|
|
b79e8b8130 | ||
|
|
72e5a40e7e | ||
|
|
3b25200868 | ||
|
|
3985e52a3a | ||
|
|
fee44d83c8 | ||
|
|
d70c81f03b | ||
|
|
387ec89b95 | ||
|
|
60dd68490c | ||
|
|
378e55ed0c | ||
|
|
16900ad421 | ||
|
|
0bf1e8f252 | ||
|
|
0aa5505d7f | ||
|
|
60f68abd31 | ||
|
|
0a677449dc | ||
|
|
6e9723325f | ||
|
|
e9a046e74d | ||
|
|
44f0c749d5 | ||
|
|
082d2c739e | ||
|
|
6354b1aec0 | ||
|
|
512dbf1980 | ||
|
|
ed491b0caf | ||
|
|
d6814587ad | ||
|
|
586399a814 | ||
|
|
867186fd66 | ||
|
|
48c18ee8d1 | ||
|
|
f5d5d9a504 | ||
|
|
f958924b79 | ||
|
|
67582aaee4 | ||
|
|
8ebe260628 | ||
|
|
a6d2590834 | ||
|
|
923cd045cd | ||
|
|
f64bcf0d08 | ||
|
|
c48b6e23eb | ||
|
|
b2eabda5b6 | ||
|
|
305e12be1d | ||
|
|
30ad784d95 | ||
|
|
7be7b07c19 | ||
|
|
88c46f4612 | ||
|
|
1c1b9b5c9d | ||
|
|
f5f3256824 | ||
|
|
d056b1f1e1 | ||
|
|
c86a30921f | ||
|
|
14f09e3787 | ||
|
|
d2a342a94e | ||
|
|
c61e4c02bd | ||
|
|
b8ce61ae45 | ||
|
|
5a25b0885c | ||
|
|
337cbb2844 | ||
|
|
fa3b84a615 | ||
|
|
4e47447dec | ||
|
|
a1772d26b5 | ||
|
|
77e5e75b2f | ||
|
|
77bfd85e9e | ||
|
|
272ea9fe17 | ||
|
|
8aed1aa634 | ||
|
|
2bec41b80e | ||
|
|
38633b6db4 | ||
|
|
e62dc00d7b | ||
|
|
f619fc3e7e | ||
|
|
6c7d74c43b | ||
|
|
268cead331 | ||
|
|
70521f0756 | ||
|
|
1f283d93ca | ||
|
|
7dc422887c | ||
|
|
7dea0dcfc4 | ||
|
|
ab11604bfb | ||
|
|
0e8c026854 | ||
|
|
3b1cc1cc34 | ||
|
|
85a8f2f147 | ||
|
|
37c43199ca | ||
|
|
f22fcc2e59 | ||
|
|
05d7d58cd5 | ||
|
|
10e89f6802 | ||
|
|
551b802d89 | ||
|
|
5ae8607771 | ||
|
|
7b47f40979 | ||
|
|
a9a76b9010 | ||
|
|
cf68725c89 | ||
|
|
989d703d1d | ||
|
|
cf2ef0955d | ||
|
|
2fe3b0de55 | ||
|
|
b47047a91d | ||
|
|
1c56ac7e48 | ||
|
|
47fb553d38 | ||
|
|
bd6362f09f | ||
|
|
9cc735bdf2 | ||
|
|
f5d992f609 | ||
|
|
25407fb5f0 | ||
|
|
9eb9bd8488 | ||
|
|
7d6eafb2f2 | ||
|
|
bfdf25a162 | ||
|
|
6e0e6f5ec4 | ||
|
|
dce8b15937 | ||
|
|
25e2e07631 | ||
|
|
b5fb8b6d82 | ||
|
|
171c5aa50c | ||
|
|
b5d378c425 | ||
|
|
145d65fd60 | ||
|
|
5c78fe1070 | ||
|
|
31b1203317 | ||
|
|
eaa200a766 | ||
|
|
f422c84414 | ||
|
|
4562f31b6b | ||
|
|
6911e184f9 | ||
|
|
9627212510 | ||
|
|
0fc8c4e071 | ||
|
|
6c93dc6a4c | ||
|
|
1dbbfbbba6 | ||
|
|
88ab36c45b | ||
|
|
14247ddabb | ||
|
|
fd8561ac55 | ||
|
|
e1e6ba36ca | ||
|
|
435a50de4b | ||
|
|
93b2b9b7b0 | ||
|
|
faa5199a9a | ||
|
|
5768d7a247 | ||
|
|
d9f2fca66d | ||
|
|
91b48258f0 | ||
|
|
2ac7b9dabf | ||
|
|
505f0f65d0 | ||
|
|
8262a8dea2 | ||
|
|
406286b970 | ||
|
|
6346f835af | ||
|
|
73fc437c7d | ||
|
|
af66739207 | ||
|
|
65bb6a8b73 | ||
|
|
8bda5aa2a7 | ||
|
|
dd2b43dc73 | ||
|
|
c925014bb5 | ||
|
|
32b11b104f | ||
|
|
e25a73f9af | ||
|
|
15c1b48b25 | ||
|
|
d14a86069a | ||
|
|
186f753aec | ||
|
|
f180707b6f | ||
|
|
9a53779b6c | ||
|
|
551771c6cf | ||
|
|
a3aca0bae4 | ||
|
|
ed0c71fa56 | ||
|
|
574ecdb512 | ||
|
|
7848a35941 | ||
|
|
dfe0314ba0 | ||
|
|
4618ef0cbf | ||
|
|
bb281649fc | ||
|
|
012ffcf6f6 | ||
|
|
bef61cf019 | ||
|
|
5ce6464461 | ||
|
|
a0c3f99d80 | ||
|
|
f6ba577cf4 | ||
|
|
6ef03b7c6c | ||
|
|
05303dab45 | ||
|
|
9edaa407f2 | ||
|
|
be03f6adb6 | ||
|
|
c37496f2b0 | ||
|
|
8743ba2886 | ||
|
|
c100054d68 | ||
|
|
2fbb87e17a | ||
|
|
1eadf52f5e | ||
|
|
810f46c450 | ||
|
|
393dfd1e96 | ||
|
|
011e95b331 | ||
|
|
9f3681642a | ||
|
|
a4ca679b65 | ||
|
|
d198095d7a | ||
|
|
da451d013a | ||
|
|
d18244a8a1 | ||
|
|
6214872e0c | ||
|
|
6885cea0fd | ||
|
|
438455bc8c | ||
|
|
7914f65f68 | ||
|
|
d0b79ad335 | ||
|
|
7dc4484f6a | ||
|
|
257ea391da | ||
|
|
4c64bcfae7 | ||
|
|
99d2f537c2 | ||
|
|
6c32365e00 | ||
|
|
95925aafb1 | ||
|
|
77bfaa4245 | ||
|
|
0a3d4a5ab0 | ||
|
|
e8c11251de | ||
|
|
87a8b1b3f5 | ||
|
|
2328c60d12 | ||
|
|
61cd5cf4e6 | ||
|
|
1eb9efe2d5 | ||
|
|
d5882f2efe | ||
|
|
5f3991127b | ||
|
|
c5d2590293 | ||
|
|
b995dc54f1 | ||
|
|
79404e754e | ||
|
|
92318d5804 | ||
|
|
191f9daf4d | ||
|
|
b67280f0d4 | ||
|
|
ce8bdabab8 | ||
|
|
b40af07103 | ||
|
|
f3698cd625 | ||
|
|
c928618d1a | ||
|
|
3cc83ced93 | ||
|
|
0ad4f3b85e | ||
|
|
2d061ce45a | ||
|
|
6e2348d2b1 | ||
|
|
525c4d529e | ||
|
|
ea84149c87 | ||
|
|
af1855601b | ||
|
|
1409065005 | ||
|
|
623019ee56 | ||
|
|
740d477801 | ||
|
|
c2b8f21fd9 | ||
|
|
442ed87cfa | ||
|
|
c48b3ded2f | ||
|
|
5bed5b9870 | ||
|
|
2a261a32e2 | ||
|
|
7137a9986f | ||
|
|
4ce386c6dd | ||
|
|
8911da8380 | ||
|
|
a3384d514f | ||
|
|
b38f6e8062 | ||
|
|
6c006d0a78 | ||
|
|
0f7a55d031 | ||
|
|
62af77979b | ||
|
|
384687e19b | ||
|
|
f799ded434 | ||
|
|
d499f4e0d0 | ||
|
|
fc7b4df98a | ||
|
|
3f9a8ecc7e | ||
|
|
71a801bbb7 | ||
|
|
f333ef803a | ||
|
|
36b1dce7e4 | ||
|
|
877ef36bc7 | ||
|
|
6ce242df4d | ||
|
|
9640f0251c | ||
|
|
53846a15de | ||
|
|
1e4ff1e774 | ||
|
|
0f40e06d93 | ||
|
|
86b204ac08 | ||
|
|
8cd5a9963f | ||
|
|
df796e32eb | ||
|
|
e2dae1f484 | ||
|
|
8ca06e11de | ||
|
|
9f548b9dee | ||
|
|
31c75886c3 | ||
|
|
3e24a87ead | ||
|
|
992bcccee9 | ||
|
|
02bf5f9a58 | ||
|
|
adaf9cbc90 | ||
|
|
f9ede4bae9 | ||
|
|
1fe9132761 | ||
|
|
fe89c101df | ||
|
|
6cc7f012d8 | ||
|
|
3b82ac00d8 | ||
|
|
9b4c64298b | ||
|
|
4a4708e3fd | ||
|
|
f231af07f9 | ||
|
|
3da1c27692 | ||
|
|
beca72cc40 | ||
|
|
5ea07d0f07 | ||
|
|
674390dfa2 | ||
|
|
e47994013a | ||
|
|
6bbf2ff876 | ||
|
|
f7f567adc8 | ||
|
|
e737b51e9d | ||
|
|
6f2dd2e2a5 | ||
|
|
36b44d6971 | ||
|
|
dcea2c5f4e | ||
|
|
ed76d718cd | ||
|
|
00e1a1c442 | ||
|
|
f2b9ea1034 | ||
|
|
1cbc352c6c | ||
|
|
51b70a7884 | ||
|
|
d04f2d5e2b | ||
|
|
b1c9d5fd4a | ||
|
|
4b8b961705 | ||
|
|
2e26130d96 | ||
|
|
63c75f714f | ||
|
|
03095dfa74 | ||
|
|
f70bf61ff6 | ||
|
|
4a362704fd | ||
|
|
2c43fdc409 | ||
|
|
2a6a3a3af5 | ||
|
|
d8e2192179 | ||
|
|
cfc5fa87d0 | ||
|
|
5ad95a1c3e | ||
|
|
de8d456089 | ||
|
|
07610a5f92 | ||
|
|
5d6998cf0b | ||
|
|
21b96068e4 | ||
|
|
c9df61c43c | ||
|
|
c1266abb98 | ||
|
|
9dfb03aa0f | ||
|
|
3a35dee0e3 | ||
|
|
f4568ef589 | ||
|
|
f80871ce7e | ||
|
|
8fe4422d21 | ||
|
|
c19fafa581 | ||
|
|
cc43f15eab | ||
|
|
bfecb04697 | ||
|
|
52e1f5273c | ||
|
|
2b5e974132 | ||
|
|
e3d7e3c195 | ||
|
|
11446b3e53 | ||
|
|
637c720de5 | ||
|
|
0dae8f9977 | ||
|
|
9c5674a076 | ||
|
|
35368442ec | ||
|
|
035b5163fb | ||
|
|
a1d5e26f6b | ||
|
|
bdd2c9d033 | ||
|
|
8ad00faebc | ||
|
|
061bfffd4d | ||
|
|
bfb2376aa3 | ||
|
|
9e4656e43f | ||
|
|
c26926148c | ||
|
|
827e1846a8 | ||
|
|
2f58aa280c | ||
|
|
66db99faf8 | ||
|
|
0efafc50dc | ||
|
|
595aab4edf | ||
|
|
02696c8bca | ||
|
|
01f3d728ef | ||
|
|
bba76cac4d | ||
|
|
72ab721f22 | ||
|
|
f98db943a5 | ||
|
|
f122da58c1 | ||
|
|
125db1777a | ||
|
|
c592db4024 | ||
|
|
02af2dbe73 | ||
|
|
b1bd04566e | ||
|
|
15288b0e84 | ||
|
|
dfaa529fa3 | ||
|
|
ef54bb1b7c | ||
|
|
b3e459863e | ||
|
|
ada56ea8ce | ||
|
|
8ca589cdf5 | ||
|
|
390c4eed7e | ||
|
|
9fc93e285c | ||
|
|
1f417f0606 | ||
|
|
30bf838065 | ||
|
|
0019101f0e | ||
|
|
75b2e383c2 | ||
|
|
b5830e0cde | ||
|
|
e9dcf0e00b | ||
|
|
ccd5c01d91 | ||
|
|
2ea3f7a558 | ||
|
|
993a2daccc | ||
|
|
541baac49e | ||
|
|
d69b04e9ed | ||
|
|
78fab41310 | ||
|
|
4502ed068d | ||
|
|
5495e0f96a | ||
|
|
60a8fe31f1 | ||
|
|
93ab2a93d4 | ||
|
|
688c21cd94 | ||
|
|
39e19fdfba | ||
|
|
5525ccc409 | ||
|
|
db9949d403 | ||
|
|
f36d91336a | ||
|
|
da13de6af5 | ||
|
|
4029dc3165 | ||
|
|
6795383461 | ||
|
|
305d5c5aa9 | ||
|
|
49492e7bca | ||
|
|
bd0e96f166 | ||
|
|
2e7b145a81 | ||
|
|
6f114b17d6 | ||
|
|
5cd73cea4b | ||
|
|
347f6aed3f | ||
|
|
24ea23ce83 | ||
|
|
5cb4cfcdd2 | ||
|
|
58ef61a0bb | ||
|
|
58a494f33f | ||
|
|
c97213f177 | ||
|
|
a9abd2ff5c | ||
|
|
8cba594070 | ||
|
|
f2c9cc17df | ||
|
|
1a34c2eee3 | ||
|
|
a1632e4874 | ||
|
|
9534fccebf | ||
|
|
ae9d9ea284 | ||
|
|
8ea4351797 | ||
|
|
34a18514b6 | ||
|
|
7248358ac1 | ||
|
|
9e1e7be574 | ||
|
|
18e0a60b9e | ||
|
|
c727863616 | ||
|
|
75fc0c7017 | ||
|
|
e3b046aecf | ||
|
|
046f80b9f2 | ||
|
|
b1b54740f4 | ||
|
|
0c1bc378ba | ||
|
|
d067b69d20 | ||
|
|
ba928e18bf | ||
|
|
2d89cb0978 | ||
|
|
c7c88902bd | ||
|
|
8d7669bc08 | ||
|
|
1cff3a6751 | ||
|
|
6100336b2a | ||
|
|
da7455f859 | ||
|
|
5ec525a430 | ||
|
|
863e58a8e7 | ||
|
|
e441e97030 | ||
|
|
2b0152f6f4 | ||
|
|
eb20c5bb43 | ||
|
|
89c8547820 | ||
|
|
5087cd2b19 | ||
|
|
06e9256050 | ||
|
|
8aff6f50db | ||
|
|
b2aca66e2d | ||
|
|
add61cf783 | ||
|
|
a549bd73f9 | ||
|
|
f849b8cd4b | ||
|
|
d8cf427425 | ||
|
|
517ac3f111 | ||
|
|
43f1cfba5a | ||
|
|
dd18b6c836 | ||
|
|
d8b86a899d | ||
|
|
ed9e336c51 | ||
|
|
94fea502b9 | ||
|
|
1e79e39161 | ||
|
|
6f9c2211fa | ||
|
|
2e1e7462dc | ||
|
|
6fb36acc9a | ||
|
|
f35baffbef | ||
|
|
69b9189220 | ||
|
|
06fe572113 | ||
|
|
dfd1d09641 | ||
|
|
6d981afcbc | ||
|
|
f90db0ed50 | ||
|
|
9894023177 | ||
|
|
5ac6d28abf | ||
|
|
b813f48a7e | ||
|
|
a3b4e40982 | ||
|
|
0c42b9a68e | ||
|
|
48d3317136 | ||
|
|
30b62e172d | ||
|
|
5a0fa8c09f | ||
|
|
0a6b393b35 | ||
|
|
dadae53e51 | ||
|
|
c22c4b864c | ||
|
|
aa27c13b20 | ||
|
|
50771b0762 | ||
|
|
336cf768d8 | ||
|
|
a76d9b87f0 | ||
|
|
5794fc533f | ||
|
|
9ebf769b4d | ||
|
|
2ea21e1f96 | ||
|
|
b396563235 | ||
|
|
c5b992e330 | ||
|
|
ec6fae9e65 | ||
|
|
7f5c6ca18d | ||
|
|
9de60a9a7c | ||
|
|
3f64f5a5fc | ||
|
|
7b036cbe3c | ||
|
|
5100834156 | ||
|
|
a387d48b48 | ||
|
|
adfa341d6e | ||
|
|
0b03ca158b | ||
|
|
d9e6fcd730 | ||
|
|
feb20243e5 | ||
|
|
e3e6f511e7 | ||
|
|
293a2db369 | ||
|
|
1c72e0c40c | ||
|
|
3e6a4362ee | ||
|
|
3b327bab8f | ||
|
|
a50b594aac | ||
|
|
e186c9b8bc | ||
|
|
a5502a3751 | ||
|
|
bd0f694f6a | ||
|
|
c018b4bd6e | ||
|
|
2be71c577c | ||
|
|
238de4d8b4 | ||
|
|
6664890381 | ||
|
|
5221db5aa6 | ||
|
|
1e6d998a9c | ||
|
|
da62a5653a | ||
|
|
125ff957f5 | ||
|
|
73dcd9e11a | ||
|
|
50fd5512d6 | ||
|
|
291dd9bd48 | ||
|
|
549eeeb29d | ||
|
|
6d59d21770 | ||
|
|
2ee1063485 | ||
|
|
75bec29dbc | ||
|
|
20bc1afec8 | ||
|
|
e3f56f2645 | ||
|
|
ed2770e380 | ||
|
|
bb6d8ec99f | ||
|
|
ddb81de58b | ||
|
|
cf9a8a15cd | ||
|
|
c4219ba0ad | ||
|
|
47e54b2399 | ||
|
|
215fe16341 | ||
|
|
218d481209 | ||
|
|
78f4a83d05 | ||
|
|
733181a6b8 | ||
|
|
d79dcb952d | ||
|
|
bb64e812d8 | ||
|
|
9a324e35a4 | ||
|
|
605888bb78 | ||
|
|
ef69d692ef | ||
|
|
a54f05e287 | ||
|
|
4b0cd0776d | ||
|
|
4b75d67732 | ||
|
|
1ca61a948e | ||
|
|
e13c81e25b | ||
|
|
b69652fc0c | ||
|
|
0949b7ec0a | ||
|
|
75683c423d | ||
|
|
3f2c69aea3 | ||
|
|
9adc3941b9 | ||
|
|
8904a6f4e9 | ||
|
|
b49803855e | ||
|
|
7b906aa229 | ||
|
|
f0f4c8cc52 | ||
|
|
47db82d69b | ||
|
|
af0374d5f4 | ||
|
|
f2b987b96b | ||
|
|
7f28157b32 | ||
|
|
c0c49350f6 | ||
|
|
700d60058f | ||
|
|
bda5ae5b90 | ||
|
|
53075e0ec7 | ||
|
|
64c7c9f712 | ||
|
|
8846f63dcf | ||
|
|
d10bf9f993 | ||
|
|
4152c0653f | ||
|
|
e2d7ead815 | ||
|
|
36f56f3695 | ||
|
|
5961d54aa8 | ||
|
|
207bf183c8 | ||
|
|
6f0ce35ca2 | ||
|
|
39bbd5604d | ||
|
|
75e493363d | ||
|
|
2c414d8e45 | ||
|
|
cac70a10fe | ||
|
|
9794c2ebbb | ||
|
|
975051b8e1 | ||
|
|
33ec638323 | ||
|
|
f9f259195d | ||
|
|
dceda6e27d | ||
|
|
ef264920db | ||
|
|
e9b1c92911 | ||
|
|
123f90d24d | ||
|
|
ff01764f95 | ||
|
|
4132dd940a | ||
|
|
9fc6d3d6f0 | ||
|
|
7d9141a055 | ||
|
|
2214c0cdf8 | ||
|
|
11c5fdc328 | ||
|
|
c81c4f184b | ||
|
|
a35ed05bc3 | ||
|
|
e574314472 | ||
|
|
45ab6d7c5e | ||
|
|
48325b6452 | ||
|
|
4a1c9ac390 | ||
|
|
a868bab24e | ||
|
|
1fada5dd0b | ||
|
|
a55b9bb8e1 | ||
|
|
6c0f3d701f | ||
|
|
e86f4f94ef | ||
|
|
ca258deb7a | ||
|
|
79ca016409 | ||
|
|
869bebed6e | ||
|
|
0e3c0fcc2e | ||
|
|
bf9c0bb914 | ||
|
|
8669599089 | ||
|
|
775c0ff2f1 | ||
|
|
98ab75029e | ||
|
|
682740a020 | ||
|
|
278decfb87 | ||
|
|
b8a0ca082a | ||
|
|
f03e4be683 | ||
|
|
ba6a6292f9 | ||
|
|
16599a07a9 | ||
|
|
a9ac11216d | ||
|
|
8e2008f821 | ||
|
|
0a8b9bad4f | ||
|
|
bd4b75f5d8 | ||
|
|
084e7e7d73 | ||
|
|
76f4e3c5b4 | ||
|
|
adb97a0f3e | ||
|
|
f2f435b4cb | ||
|
|
0015f81645 | ||
|
|
ed76335c96 | ||
|
|
e0a35a3958 | ||
|
|
d9ec9ed1ef | ||
|
|
0032f934c9 | ||
|
|
8816e18027 | ||
|
|
e8be950752 | ||
|
|
aea4b37760 | ||
|
|
1aff1a0000 | ||
|
|
df54c17dca | ||
|
|
73c5883f0d | ||
|
|
e3561ce555 | ||
|
|
a5feb639d9 | ||
|
|
ac33286c8c | ||
|
|
19d5d32229 | ||
|
|
d90f2537a4 | ||
|
|
487aa1f2c3 | ||
|
|
be9ab15c4e | ||
|
|
7d4f0d24d5 | ||
|
|
bafa334b94 | ||
|
|
80c5f99f3b | ||
|
|
212bf5df98 | ||
|
|
32189afc67 | ||
|
|
0fa6b34f1a | ||
|
|
4d6bb8b6be | ||
|
|
82da75bc0c | ||
|
|
beda378314 | ||
|
|
6734864acd | ||
|
|
9f548870d0 | ||
|
|
d2bae43d26 | ||
|
|
e77e43faab | ||
|
|
224d2f92c3 | ||
|
|
250e354659 | ||
|
|
2e59587c8e | ||
|
|
6f4520254b | ||
|
|
b939c02da0 | ||
|
|
9e900d5885 | ||
|
|
38d3450160 | ||
|
|
2c5bfec089 | ||
|
|
a56a2b0057 | ||
|
|
89224401a9 | ||
|
|
1c17c8661a | ||
|
|
4ed65891c2 | ||
|
|
49e131ce21 | ||
|
|
06f4b017d6 | ||
|
|
f52450aef4 | ||
|
|
6476843e95 | ||
|
|
67d11dffb9 | ||
|
|
58dbb01e76 |
17
.bra.toml
Normal file
17
.bra.toml
Normal file
@@ -0,0 +1,17 @@
|
||||
[run]
|
||||
init_cmds = [
|
||||
["go", "build", "-o", "./bin/grafana-server", "./pkg/cmd/grafana-server"],
|
||||
["./bin/grafana-server"]
|
||||
]
|
||||
watch_all = true
|
||||
watch_dirs = [
|
||||
"$WORKDIR/pkg",
|
||||
"$WORKDIR/public/views",
|
||||
"$WORKDIR/conf",
|
||||
]
|
||||
watch_exts = [".go", ".ini", ".toml", ".html"]
|
||||
build_delay = 1500
|
||||
cmds = [
|
||||
["go", "build", "-o", "./bin/grafana-server", "./pkg/cmd/grafana-server"],
|
||||
["./bin/grafana-server"]
|
||||
]
|
||||
19
.editorconfig
Normal file
19
.editorconfig
Normal file
@@ -0,0 +1,19 @@
|
||||
# http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*.go]
|
||||
indent_style = tabs
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*]
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
charset = utf-8
|
||||
trim_trailing_whitespace = true
|
||||
insert_final_newline = true
|
||||
|
||||
[*.md]
|
||||
trim_trailing_whitespace = false
|
||||
12
.flooignore
Normal file
12
.flooignore
Normal file
@@ -0,0 +1,12 @@
|
||||
#*
|
||||
*.o
|
||||
*.pyc
|
||||
*.pyo
|
||||
*~
|
||||
extern/
|
||||
node_modules/
|
||||
tmp/
|
||||
data/
|
||||
vendor/
|
||||
public_gen/
|
||||
dist/
|
||||
22
.github/CONTRIBUTING.md
vendored
Normal file
22
.github/CONTRIBUTING.md
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
Follow the setup guide in README.md
|
||||
|
||||
### Rebuild frontend assets on source change
|
||||
```
|
||||
grunt && grunt watch
|
||||
```
|
||||
|
||||
### Rerun tests on source change
|
||||
```
|
||||
grunt karma:dev
|
||||
```
|
||||
|
||||
### Run tests for backend assets before commit
|
||||
```
|
||||
test -z "$(gofmt -s -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)"
|
||||
```
|
||||
|
||||
### Run tests for frontend assets before commit
|
||||
```
|
||||
grunt test
|
||||
godep go test -v ./pkg/...
|
||||
```
|
||||
17
.github/ISSUE_TEMPLATE.md
vendored
Normal file
17
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,17 @@
|
||||
* **I'm submitting a ...**
|
||||
- [ ] Bug report
|
||||
- [ ] Feature request
|
||||
- [ ] Question / Support request: **Please do not** open a github issue. [Support Options](http://grafana.org/support/)
|
||||
|
||||
Please include this information:
|
||||
- What Grafana version are you using?
|
||||
- What datasource are you using?
|
||||
- What OS are you running grafana on?
|
||||
- What did you do?
|
||||
- What was the expected result?
|
||||
- What happened instead?
|
||||
|
||||
**IMPORTANT** If it relates to metric data viz:
|
||||
- An image or text representation of your metric query
|
||||
- The raw query and response for the network request (check this in chrome dev tools network tab, here you can see metric requests and other request, please include the request body and request response)
|
||||
|
||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
* Link the PR to an issue for new features
|
||||
* Rebase your PR if it gets out of sync with master
|
||||
42
.gitignore
vendored
42
.gitignore
vendored
@@ -1,6 +1,40 @@
|
||||
node_modules
|
||||
npm-debug.log
|
||||
coverage/
|
||||
.aws-config.json
|
||||
dist
|
||||
web.config
|
||||
config.dev.js
|
||||
*.sublime-workspace
|
||||
awsconfig
|
||||
/dist
|
||||
/emails/dist
|
||||
/public_gen
|
||||
/public/vendor/npm
|
||||
/tmp
|
||||
vendor/phantomjs/phantomjs
|
||||
|
||||
docs/AWS_S3_BUCKET
|
||||
docs/GIT_BRANCH
|
||||
docs/VERSION
|
||||
docs/GITCOMMIT
|
||||
docs/changed-files
|
||||
docs/changed-files
|
||||
|
||||
# locally required config files
|
||||
public/css/*.min.css
|
||||
|
||||
# Editor junk
|
||||
*.sublime-workspace
|
||||
*.swp
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
/data/*
|
||||
/bin/*
|
||||
|
||||
conf/custom.ini
|
||||
fig.yml
|
||||
docker-compose.yml
|
||||
profile.cov
|
||||
/grafana
|
||||
.notouch
|
||||
/pkg/cmd/grafana-cli/grafana-cli
|
||||
/pkg/cmd/grafana-server/grafana-server
|
||||
/examples/*/dist
|
||||
10
.hooks/pre-commit
Executable file
10
.hooks/pre-commit
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
test -z "$(gofmt -s -l . | grep -v Godeps/_workspace/src/ | tee /dev/stderr)"
|
||||
if [ $? -gt 0 ]; then
|
||||
echo "Some files aren't formatted, please run 'go fmt ./pkg/...' to format your source code before committing"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
grunt test
|
||||
13
.jscs.json
Normal file
13
.jscs.json
Normal file
@@ -0,0 +1,13 @@
|
||||
{
|
||||
"disallowImplicitTypeConversion": ["string"],
|
||||
"disallowKeywords": ["with"],
|
||||
"disallowMultipleLineBreaks": true,
|
||||
"disallowMixedSpacesAndTabs": true,
|
||||
"disallowTrailingWhitespace": true,
|
||||
"requireSpacesInFunctionExpression": {
|
||||
"beforeOpeningCurlyBrace": true
|
||||
},
|
||||
"disallowSpacesInsideArrayBrackets": true,
|
||||
"disallowSpacesInsideParentheses": true,
|
||||
"validateIndentation": 2
|
||||
}
|
||||
21
.jsfmtrc
Normal file
21
.jsfmtrc
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"preset" : "default",
|
||||
|
||||
"lineBreak" : {
|
||||
"before" : {
|
||||
"VariableDeclarationWithoutInit" : 0,
|
||||
},
|
||||
|
||||
"after": {
|
||||
"AssignmentOperator": -1,
|
||||
"ArgumentListArrayExpression": ">=1"
|
||||
}
|
||||
},
|
||||
|
||||
"whiteSpace" : {
|
||||
"before" : {
|
||||
},
|
||||
"after" : {
|
||||
}
|
||||
}
|
||||
}
|
||||
12
.jshintrc
12
.jshintrc
@@ -4,7 +4,7 @@
|
||||
"bitwise":false,
|
||||
"curly": true,
|
||||
"eqnull": true,
|
||||
"globalstrict": true,
|
||||
"strict": true,
|
||||
"devel": true,
|
||||
"eqeqeq": true,
|
||||
"forin": false,
|
||||
@@ -12,24 +12,26 @@
|
||||
"supernew": true,
|
||||
"expr": true,
|
||||
"indent": 2,
|
||||
"latedef": true,
|
||||
"latedef": false,
|
||||
"newcap": true,
|
||||
"noarg": true,
|
||||
"noempty": true,
|
||||
"undef": true,
|
||||
"boss": true,
|
||||
"trailing": false,
|
||||
"trailing": true,
|
||||
"laxbreak": true,
|
||||
"laxcomma": true,
|
||||
"sub": true,
|
||||
"unused": true,
|
||||
|
||||
"maxdepth": 6,
|
||||
"maxlen": 140,
|
||||
|
||||
"globals": {
|
||||
"System": true,
|
||||
"Promise": true,
|
||||
"define": true,
|
||||
"require": true,
|
||||
"Chromath": false,
|
||||
"setImmediate": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
883
CHANGELOG.md
Normal file
883
CHANGELOG.md
Normal file
@@ -0,0 +1,883 @@
|
||||
# 3.1.0-beta1 (2016-06-23)
|
||||
|
||||
### Enhancements
|
||||
* **Dashboard Export/Import**: Dashboard export now templetize data sources and constant variables, users pick these on import, closes [#5084](https://github.com/grafana/grafana/issues/5084)
|
||||
* **Dashboard Url**: Time range changes updates url, closes [#458](https://github.com/grafana/grafana/issues/458)
|
||||
* **Dashboard Url**: Template variable change updates url, closes [#5002](https://github.com/grafana/grafana/issues/5002)
|
||||
* **Singlestat**: Add support for range to text mappings, closes [#1319](https://github.com/grafana/grafana/issues/1319)
|
||||
* **Graph**: Adds sort order options for graph tooltip, closes [#1189](https://github.com/grafana/grafana/issues/1189)
|
||||
* **Theme**: Add default theme to config file [#5011](https://github.com/grafana/grafana/pull/5011)
|
||||
* **Page Footer**: Added page footer with links to docs, shows Grafana version and info if new version is available, closes [#4889](https://github.com/grafana/grafana/pull/4889)
|
||||
* **InfluxDB**: Add spread function, closes [#5211](https://github.com/grafana/grafana/issues/5211)
|
||||
* **Scripts**: Use restart instead of start for deb package script, closes [#5282](https://github.com/grafana/grafana/pull/5282)
|
||||
* **Logging**: Moved to structured logging lib, and moved to component specific level filters via config file, closes [#4590](https://github.com/grafana/grafana/issues/4590)
|
||||
* **OpenTSDB**: Support nested template variables in tag_values function, closes [4398](https://github.com/grafana/grafana/issues/4398)
|
||||
* **Datasource**: Pending data source requests are cancelled before new ones are issues (Graphite & Prometheus), closes [5321](https://github.com/grafana/grafana/issues/5321)
|
||||
|
||||
### Breaking changes
|
||||
* **Logging** : Changed default logging output format (now structured into message, and key value pairs, with logger key acting as component). You can also no change in config to json log ouput.
|
||||
* **Graphite** : The Graph panel no longer have a Graphite PNG option. closes [#5367](https://github.com/grafana/grafana/issues/5367)
|
||||
|
||||
### Bug fixes
|
||||
* **PNG rendering**: Fixed phantomjs rendering and y-axis label rotation. fixes [#5220](https://github.com/grafana/grafana/issues/5220)
|
||||
* **CLI**: The cli tool now supports reading plugin.json from dist/plugin.json. fixes [#5410](https://github.com/grafana/grafana/issues/5410)
|
||||
|
||||
# 3.0.4 Patch release (2016-05-25)
|
||||
* **Panel**: Fixed blank dashboard issue when switching to other dashboard while in fullscreen edit mode, fixes [#5163](https://github.com/grafana/grafana/pull/5163)
|
||||
* **Templating**: Fixed issue with nested multi select variables and cascading and updating child variable selection state, fixes [#4861](https://github.com/grafana/grafana/pull/4861)
|
||||
* **Templating**: Fixed issue with using templated data source in another template variable query, fixes [#5165](https://github.com/grafana/grafana/pull/5165)
|
||||
* **Singlestat gauge**: Fixed issue with gauge render position, fixes [#5143](https://github.com/grafana/grafana/pull/5143)
|
||||
* **Home dashboard**: Fixes broken home dashboard api, fixes [#5167](https://github.com/grafana/grafana/issues/5167)
|
||||
|
||||
# 3.0.3 Patch release (2016-05-23)
|
||||
* **Annotations**: Annotations can now use a template variable as data source, closes [#5054](https://github.com/grafana/grafana/issues/5054)
|
||||
* **Time picker**: Fixed issue timepicker and UTC when reading time from URL, fixes [#5078](https://github.com/grafana/grafana/issues/5078)
|
||||
* **CloudWatch**: Support for Multiple Account by AssumeRole, closes [#3522](https://github.com/grafana/grafana/issues/3522)
|
||||
* **Singlestat**: Fixed alignment and minium height issue, fixes [#5113](https://github.com/grafana/grafana/issues/5113), fixes [#4679](https://github.com/grafana/grafana/issues/4679)
|
||||
* **Share modal**: Fixed link when using grafana under dashboard sub url, fixes [#5109](https://github.com/grafana/grafana/issues/5109)
|
||||
* **Prometheus**: Fixed bug in query editor that caused it not to load when reloading page, fixes [#5107](https://github.com/grafana/grafana/issues/5107)
|
||||
* **Elasticsearch**: Fixed bug when template variable query returns numeric values, fixes [#5097](https://github.com/grafana/grafana/issues/5097), fixes [#5088](https://github.com/grafana/grafana/issues/5088)
|
||||
* **Logging**: Fixed issue with reading logging level value, fixes [#5079](https://github.com/grafana/grafana/issues/5079)
|
||||
* **Timepicker**: Fixed issue with timepicker and UTC when reading time from URL, fixes [#5078](https://github.com/grafana/grafana/issues/5078)
|
||||
* **Docs**: Added docs for org & user preferences HTTP API, closes [#5069](https://github.com/grafana/grafana/issues/5069)
|
||||
* **Plugin list panel**: Now shows correct enable state for apps when not enabled, fixes [#5068](https://github.com/grafana/grafana/issues/5068)
|
||||
* **Elasticsearch**: Templating & Annotation queries that use template variables are now formatted correctly, fixes [#5135](https://github.com/grafana/grafana/issues/5135)
|
||||
|
||||
# 3.0.2 Patch release (2016-05-16)
|
||||
|
||||
* **Templating**: Fixed issue mixing row repeat and panel repeats, fixes [#4988](https://github.com/grafana/grafana/issues/4988)
|
||||
* **Templating**: Fixed issue detecting dependencies in nested variables, fixes [#4987](https://github.com/grafana/grafana/issues/4987), fixes [#4986](https://github.com/grafana/grafana/issues/4986)
|
||||
* **Graph**: Fixed broken PNG rendering in graph panel, fixes [#5025](https://github.com/grafana/grafana/issues/5025)
|
||||
* **Graph**: Fixed broken xaxis on graph panel, fixes [#5024](https://github.com/grafana/grafana/issues/5024)
|
||||
|
||||
* **Influxdb**: Fixes crash when hiding middle serie, fixes [#5005](https://github.com/grafana/grafana/issues/5005)
|
||||
|
||||
# 3.0.1 Stable (2016-05-11)
|
||||
|
||||
### Bug fixes
|
||||
* **Templating**: Fixed issue with new data source variable not persisting current selected value, fixes [#4934](https://github.com/grafana/grafana/issues/4934)
|
||||
|
||||
# 3.0.0-beta7 (2016-05-02)
|
||||
|
||||
### Bug fixes
|
||||
* **Dashboard title**: Fixed max dashboard title width (media query) for large screens, fixes [#4859](https://github.com/grafana/grafana/issues/4859)
|
||||
* **Annotations**: Fixed issue with entering annotation edit view, fixes [#4857](https://github.com/grafana/grafana/issues/4857)
|
||||
* **Remove query**: Fixed issue with removing query for data sources without collapsable query editors, fixes [#4856](https://github.com/grafana/grafana/issues/4856)
|
||||
* **Graphite PNG**: Fixed issue graphite png rendering option, fixes [#4864](https://github.com/grafana/grafana/issues/4864)
|
||||
* **InfluxDB**: Fixed issue missing plus group by iconn, fixes [#4862](https://github.com/grafana/grafana/issues/4862)
|
||||
* **Graph**: Fixes missing line mode for thresholds, fixes [#4902](https://github.com/grafana/grafana/pull/4902)
|
||||
|
||||
### Enhancements
|
||||
* **InfluxDB**: Added new functions moving_average and difference to query editor, closes [#4698](https://github.com/grafana/grafana/issues/4698)
|
||||
|
||||
# 3.0.0-beta6 (2016-04-29)
|
||||
|
||||
### Enhancements
|
||||
* **Singlestat**: Support for gauges in singlestat panel. closes [#3688](https://github.com/grafana/grafana/pull/3688)
|
||||
* **Templating**: Support for data source as variable, closes [#816](https://github.com/grafana/grafana/pull/816)
|
||||
|
||||
### Bug fixes
|
||||
* **InfluxDB 0.12**: Fixed issue templating and `show tag values` query only returning tags for first measurement, fixes [#4726](https://github.com/grafana/grafana/issues/4726)
|
||||
* **Templating**: Fixed issue with regex formating when matching multiple values, fixes [#4755](https://github.com/grafana/grafana/issues/4755)
|
||||
* **Templating**: Fixed issue with custom all value and escaping, fixes [#4736](https://github.com/grafana/grafana/issues/4736)
|
||||
* **Dashlist**: Fixed issue dashboard list panel and caching tags, fixes [#4768](https://github.com/grafana/grafana/issues/4768)
|
||||
* **Graph**: Fixed issue with unneeded scrollbar in legend for Firefox, fixes [#4760](https://github.com/grafana/grafana/issues/4760)
|
||||
* **Table panel**: Fixed issue table panel formating string array properties, fixes [#4791](https://github.com/grafana/grafana/issues/4791)
|
||||
* **grafana-cli**: Improve error message when failing to install plugins due to corrupt response, fixes [#4651](https://github.com/grafana/grafana/issues/4651)
|
||||
* **Singlestat**: Fixes prefix an postfix for gauges, fixes [#4812](https://github.com/grafana/grafana/issues/4812)
|
||||
* **Singlestat**: Fixes auto-refresh on change for some options, fixes [#4809](https://github.com/grafana/grafana/issues/4809)
|
||||
|
||||
### Breaking changes
|
||||
**Data Source Query Editors**: Issue [#3900](https://github.com/grafana/grafana/issues/3900)
|
||||
|
||||
Query editors have been updated to use the new form styles. External data source plugins needs to be
|
||||
updated to work. Sorry to introduce breaking change this late in beta phase. We wanted to get this change
|
||||
in before 3.0 stable is released so we don't have to break data sources in next release (3.1). If you are
|
||||
a data source plugin author and want help for how the new form styles work please ask for help in
|
||||
slack channel (link to slack channel in readme).
|
||||
|
||||
# 3.0.0-beta5 (2016-04-15)
|
||||
|
||||
### Bug fixes
|
||||
* **grafana-cli**: Fixed issue grafana-cli tool, did not detect the right plugin dir, fixes [#4723](https://github.com/grafana/grafana/issues/4723)
|
||||
* **Graph**: Fixed issue with light theme text color issue in tooltip, fixes [#4702](https://github.com/grafana/grafana/issues/4702)
|
||||
* **Snapshot**: Fixed issue with empty snapshots, fixes [#4706](https://github.com/grafana/grafana/issues/4706)
|
||||
|
||||
# 3.0.0-beta4 (2016-04-13)
|
||||
|
||||
### Bug fixes
|
||||
* **Home dashboard**: Fixed issue with permission denied error on home dashboard, fixes [#4686](https://github.com/grafana/grafana/issues/4686)
|
||||
* **Templating**: Fixed issue templating variables that use regex extraction, fixes [#4672](https://github.com/grafana/grafana/issues/4672)
|
||||
|
||||
# 3.0.0-beta3 (2016-04-12)
|
||||
|
||||
### Enhancements
|
||||
* **InfluxDB**: Changed multi query encoding to work with InfluxDB 0.11 & 0.12, closes [#4533](https://github.com/grafana/grafana/issues/4533)
|
||||
* **Timepicker**: Add arrows and shortcuts for moving back and forth in current dashboard, closes [#119](https://github.com/grafana/grafana/issues/119)
|
||||
|
||||
### Bug fixes
|
||||
* **Postgres**: Fixed page render crash when using postgres, fixes [#4558](https://github.com/grafana/grafana/issues/4558)
|
||||
* **Table panel**: Fixed table panel bug when trying to show annotations in table panel, fixes [#4563](https://github.com/grafana/grafana/issues/4563)
|
||||
* **App Config**: Fixed app config issue showing content of other app config, fixes [#4575](https://github.com/grafana/grafana/issues/4575)
|
||||
* **Graph Panel**: Fixed legend option max not updating, fixes [#4601](https://github.com/grafana/grafana/issues/4601)
|
||||
* **Graph Panel**: Fixed issue where newly added graph panels shared same axes config, fixes [#4582](https://github.com/grafana/grafana/issues/4582)
|
||||
* **Graph Panel**: Fixed issue with axis labels overlapping Y-axis, fixes [#4626](https://github.com/grafana/grafana/issues/4626)
|
||||
* **InfluxDB**: Fixed issue with templating query containing template variable, fixes [#4602](https://github.com/grafana/grafana/issues/4602)
|
||||
* **Graph Panel**: Fixed issue with hiding series and stacking, fixes [#4557](https://github.com/grafana/grafana/issues/4557)
|
||||
* **Graph Panel**: Fixed issue with legend height in table mode with few series, affected iframe embedding as well, fixes [#4640](https://github.com/grafana/grafana/issues/4640)
|
||||
|
||||
# 3.0.0-beta2 (2016-04-04)
|
||||
|
||||
### New Features (introduces since 3.0-beta1)
|
||||
* **Preferences**: Set home dashboard on user and org level, closes [#1678](https://github.com/grafana/grafana/issues/1678)
|
||||
* **Preferences**: Set timezone on user and org level, closes [#3214](https://github.com/grafana/grafana/issues/3214), [#1200](https://github.com/grafana/grafana/issues/1200)
|
||||
* **Preferences**: Set theme on user and org level, closes [#3214](https://github.com/grafana/grafana/issues/3214), [#1917](https://github.com/grafana/grafana/issues/1917)
|
||||
|
||||
### Bug fixes
|
||||
* **Dashboard**: Fixed dashboard panel layout for mobile devices, fixes [#4529](https://github.com/grafana/grafana/issues/4529)
|
||||
* **Table Panel**: Fixed issue with table panel sort, fixes [#4532](https://github.com/grafana/grafana/issues/4532)
|
||||
* **Page Load Crash**: A Datasource with null jsonData would make Grafana fail to load page, fixes [#4536](https://github.com/grafana/grafana/issues/4536)
|
||||
* **Metrics tab**: Fix for missing datasource name in datasource selector, fixes [#4541](https://github.com/grafana/grafana/issues/4540)
|
||||
* **Graph**: Fix legend in table mode with series on right-y axis, fixes [#4551](https://github.com/grafana/grafana/issues/4551), [#1145](https://github.com/grafana/grafana/issues/1145)
|
||||
|
||||
# 3.0.0-beta1 (2016-03-31)
|
||||
|
||||
### New Features
|
||||
* **Playlists**: Playlists can now be persisted and started from urls, closes [#3655](https://github.com/grafana/grafana/issues/3655)
|
||||
* **Metadata**: Settings panel now shows dashboard metadata, closes [#3304](https://github.com/grafana/grafana/issues/3304)
|
||||
* **InfluxDB**: Support for policy selection in query editor, closes [#2018](https://github.com/grafana/grafana/issues/2018)
|
||||
* **Snapshots UI**: Dashboard snapshots list can be managed through UI, closes[#1984](https://github.com/grafana/grafana/issues/1984)
|
||||
* **Prometheus**: Prometheus annotation support, closes[#2883](https://github.com/grafana/grafana/pull/2883)
|
||||
* **Cli**: New cli tool for downloading and updating plugins
|
||||
* **Annotations**: Annotations can now contain links that can be clicked (you can navigate on to annotation popovers), closes [#1588](https://github.com/grafana/grafana/issues/1588)
|
||||
* **Opentsdb**: Opentsdb 2.2 filters support, closes[#3077](https://github.com/grafana/grafana/issues/3077)
|
||||
|
||||
### Breaking changes
|
||||
* **Plugin API**: Both datasource and panel plugin api (and plugin.json schema) have been updated, requiring an update to plugins. See [plugin api](https://github.com/grafana/grafana/blob/master/public/app/plugins/plugin_api.md) for more info.
|
||||
* **InfluxDB 0.8.x** The data source for the old version of influxdb (0.8.x) is no longer included in default builds, but can easily be installed via improved plugin system, closes [#3523](https://github.com/grafana/grafana/issues/3523)
|
||||
* **KairosDB** The data source is no longer included in default builds, but can easily be installed via improved plugin system, closes [#3524](https://github.com/grafana/grafana/issues/3524)
|
||||
* **Templating**: Templating value formats (glob/regex/pipe etc) are now handled automatically and not specified by the user, this makes variable values possible to reuse in many contexts. It can in some edge cases break existing dashboards that have template variables that do not reload on dashboard load. To fix any issue just go into template variable options and update the variable (so it's values are reloaded.).
|
||||
|
||||
### Enhancements
|
||||
* **LDAP**: Support for nested LDAP Groups, closes [#4401](https://github.com/grafana/grafana/issues/4401), [#3808](https://github.com/grafana/grafana/issues/3808)
|
||||
* **Sessions**: Support for memcached as session storage, closes [#3458](https://github.com/grafana/grafana/issues/3458)
|
||||
* **mysql**: Grafana now supports ssl for mysql, closes [#3584](https://github.com/grafana/grafana/issues/3584)
|
||||
* **snapshot**: Annotations are now included in snapshots, closes [#3635](https://github.com/grafana/grafana/issues/3635)
|
||||
* **Admin**: Admin can now have global overview of Grafana setup, closes [#3812](https://github.com/grafana/grafana/issues/3812)
|
||||
* **graph**: Right side legend height is now fixed at row height, closes [#1277](https://github.com/grafana/grafana/issues/1277)
|
||||
* **Table**: All content in table panel is now html escaped, closes [#3673](https://github.com/grafana/grafana/issues/3673)
|
||||
* **graph**: Template variables can now be used in TimeShift and TimeFrom, closes[#1960](https://github.com/grafana/grafana/issues/1960)
|
||||
* **Tooltip**: Optionally add milliseconds to timestamp in tool tip, closes[#2248](https://github.com/grafana/grafana/issues/2248)
|
||||
* **Opentsdb**: Support milliseconds when using openTSDB datasource, closes [#2865](https://github.com/grafana/grafana/issues/2865)
|
||||
* **Opentsdb**: Add support for annotations, closes[#664](https://github.com/grafana/grafana/issues/664)
|
||||
|
||||
### Bug fixes
|
||||
* **Playlist**: Fix for memory leak when running a playlist, closes [#3794](https://github.com/grafana/grafana/pull/3794)
|
||||
* **InfluxDB**: Fix for InfluxDB and table panel when using Format As Table and having group by time, fixes [#3928](https://github.com/grafana/grafana/issues/3928)
|
||||
* **Panel Time shift**: Fix for panel time range and using dashboard times liek `Today` and `This Week`, fixes [#3941](https://github.com/grafana/grafana/issues/3941)
|
||||
* **Row repeat**: Repeated rows will now appear next to each other and not by the bottom of the dashboard, fixes [#3942](https://github.com/grafana/grafana/issues/3942)
|
||||
* **Png renderer**: Fix for phantomjs path on windows, fixes [#3657](https://github.com/grafana/grafana/issues/3657)
|
||||
|
||||
# 2.6.1 (unrelased, 2.6.x branch)
|
||||
|
||||
### New Features
|
||||
* **Elasticsearch**: Support for derivative unit option, closes [#3512](https://github.com/grafana/grafana/issues/3512)
|
||||
|
||||
### Bug fixes
|
||||
* **Graph Panel**: Fixed typehead when adding series style override, closes [#3554](https://github.com/grafana/grafana/issues/3554)
|
||||
|
||||
# 2.6.0 (2015-12-14)
|
||||
|
||||
### New Features
|
||||
* **Elasticsearch**: Support for pipeline aggregations Moving average and derivative, closes [#2715](https://github.com/grafana/grafana/issues/2715)
|
||||
* **Elasticsearch**: Support for inline script and missing options for metrics, closes [#3500](https://github.com/grafana/grafana/issues/3500)
|
||||
* **Syslog**: Support for syslog logging, closes [#3161](https://github.com/grafana/grafana/pull/3161)
|
||||
* **Timepicker**: Always show refresh button even with refresh rate, closes [#3498](https://github.com/grafana/grafana/pull/3498)
|
||||
* **Login**: Make it possible to change the login hint on the login page, closes [#2571](https://github.com/grafana/grafana/pull/2571)
|
||||
|
||||
### Bug Fixes
|
||||
* **metric editors**: Fix for clicking typeahead auto dropdown option, fixes [#3428](https://github.com/grafana/grafana/issues/3428)
|
||||
* **influxdb**: Fixed issue showing Group By label only on first query, fixes [#3453](https://github.com/grafana/grafana/issues/3453)
|
||||
* **logging**: Add more verbose info logging for http reqeusts, closes [#3405](https://github.com/grafana/grafana/pull/3405)
|
||||
|
||||
# 2.6.0-Beta1 (2015-12-04)
|
||||
|
||||
### New Table Panel
|
||||
* **table**: New powerful and flexible table panel, closes [#215](https://github.com/grafana/grafana/issues/215)
|
||||
|
||||
### Enhancements
|
||||
* **CloudWatch**: Support for multiple AWS Credentials, closes [#3053](https://github.com/grafana/grafana/issues/3053), [#3080](https://github.com/grafana/grafana/issues/3080)
|
||||
* **Elasticsearch**: Support for dynamic daily indices for annotations, closes [#3061](https://github.com/grafana/grafana/issues/3061)
|
||||
* **Elasticsearch**: Support for setting min_doc_count for date histogram, closes [#3416](https://github.com/grafana/grafana/issues/3416)
|
||||
* **Graph Panel**: Option to hide series with all zeroes from legend and tooltip, closes [#1381](https://github.com/grafana/grafana/issues/1381), [#3336](https://github.com/grafana/grafana/issues/3336)
|
||||
|
||||
### Bug Fixes
|
||||
* **cloudwatch**: fix for handling of period for long time ranges, fixes [#3086](https://github.com/grafana/grafana/issues/3086)
|
||||
* **dashboard**: fix for collapse row by clicking on row title, fixes [#3065](https://github.com/grafana/grafana/issues/3065)
|
||||
* **influxdb**: fix for relative time ranges `last x months` and `last x years`, fixes [#3067](https://github.com/grafana/grafana/issues/3067)
|
||||
* **graph**: layout fix for color picker when right side legend was enabled, fixes [#3093](https://github.com/grafana/grafana/issues/3093)
|
||||
* **elasticsearch**: disabling elastic query (via eye) caused error, fixes [#3300](https://github.com/grafana/grafana/issues/3300)
|
||||
|
||||
### Breaking changes
|
||||
* **elasticsearch**: Manual json edited queries are not supported any more (They very barely worked in 2.5)
|
||||
|
||||
# 2.5 (2015-10-28)
|
||||
|
||||
**New Feature: Mix data sources**
|
||||
- A built in data source is now available named `-- Mixed --`, When picked in the metrics tab,
|
||||
it allows you to add queries of differnet data source types & instances to the same graph/panel!
|
||||
[Issue #436](https://github.com/grafana/grafana/issues/436)
|
||||
|
||||
**New Feature: Elasticsearch Metrics Query Editor and Viz Support**
|
||||
- Feature rich query editor and processing features enables you to issues all kind of metric queries to Elasticsearch
|
||||
- See [Issue #1034](https://github.com/grafana/grafana/issues/1034) for more info.
|
||||
|
||||
**New Feature: New and much improved time picker**
|
||||
- Support for quick ranges like `Today`, `This day last week`, `This week`, `The day so far`, etc.
|
||||
- Improved UI and improved support for UTC, [Issue #2761](https://github.com/grafana/grafana/issues/2761) for more info.
|
||||
|
||||
**User Onboarding**
|
||||
- Org admin can now send email invites (or invite links) to people who are not yet Grafana users
|
||||
- Sign up flow now supports email verification (if enabled)
|
||||
- See [Issue #2353](https://github.com/grafana/grafana/issues/2353) for more info.
|
||||
|
||||
**Other new Features && Enhancements**
|
||||
- [Pull #2720](https://github.com/grafana/grafana/pull/2720). Admin: Initial basic quota support (per Org)
|
||||
- [Issue #2577](https://github.com/grafana/grafana/issues/2577). Panel: Resize handles in panel bottom right corners for easy width and height change
|
||||
- [Issue #2457](https://github.com/grafana/grafana/issues/2457). Admin: admin page for all grafana organizations (list / edit view)
|
||||
- [Issue #1186](https://github.com/grafana/grafana/issues/1186). Time Picker: New option `today`, will set time range from midnight to now
|
||||
- [Issue #2647](https://github.com/grafana/grafana/issues/2647). InfluxDB: You can now set group by time interval on each query
|
||||
- [Issue #2599](https://github.com/grafana/grafana/issues/2599). InfluxDB: Improved alias support, you can now use the `AS` clause for each select statement
|
||||
- [Issue #2708](https://github.com/grafana/grafana/issues/2708). InfluxDB: You can now set math expression for select clauses.
|
||||
- [Issue #1575](https://github.com/grafana/grafana/issues/1575). Drilldown link: now you can click on the external link icon in the panel header to access drilldown links!
|
||||
- [Issue #1646](https://github.com/grafana/grafana/issues/1646). OpenTSDB: Fetch list of aggregators from OpenTSDB
|
||||
- [Issue #2955](https://github.com/grafana/grafana/issues/2955). Graph: More axis units (Length, Volume, Temperature, Pressure, etc), thanks @greglook
|
||||
- [Issue #2928](https://github.com/grafana/grafana/issues/2928). LDAP: Support for searching for groups memberships, i.e. POSIX (no memberOf) schemas, also multiple ldap servers, and root ca cert, thanks @abligh
|
||||
|
||||
**Fixes**
|
||||
- [Issue #2413](https://github.com/grafana/grafana/issues/2413). InfluxDB 0.9: Fix for handling empty series object in response from influxdb
|
||||
- [Issue #2574](https://github.com/grafana/grafana/issues/2574). Snapshot: Fix for snapshot with expire 7 days option, 7 days option not correct, was 7 hours
|
||||
- [Issue #2568](https://github.com/grafana/grafana/issues/2568). AuthProxy: Fix for server side rendering of panel when using auth proxy
|
||||
- [Issue #2490](https://github.com/grafana/grafana/issues/2490). Graphite: Dashboard import was broken in 2.1 and 2.1.1, working now
|
||||
- [Issue #2565](https://github.com/grafana/grafana/issues/2565). TimePicker: Fix for when you applied custom time range it did not refreh dashboard
|
||||
- [Issue #2563](https://github.com/grafana/grafana/issues/2563). Annotations: Fixed issue when html sanitizer failes for title to annotation body, now fallbacks to html escaping title and text
|
||||
- [Issue #2564](https://github.com/grafana/grafana/issues/2564). Templating: Another atempt at fixing #2534 (Init multi value template var used in repeat panel from url)
|
||||
- [Issue #2620](https://github.com/grafana/grafana/issues/2620). Graph: multi series tooltip did no highlight correct point when stacking was enabled and series were of different resolution
|
||||
- [Issue #2636](https://github.com/grafana/grafana/issues/2636). InfluxDB: Do no show template vars in dropdown for tag keys and group by keys
|
||||
- [Issue #2604](https://github.com/grafana/grafana/issues/2604). InfluxDB: More alias options, can now use `$[0-9]` syntax to reference part of a measurement name (seperated by dots)
|
||||
|
||||
**Breaking Changes**
|
||||
- Notice to makers/users of custom data sources, there is a minor breaking change in 2.2 that
|
||||
require an update to custom data sources for them to work in 2.2. [Read this doc](https://github.com/grafana/grafana/tree/master/docs/sources/datasources/plugin_api.md) for more on the
|
||||
data source api change.
|
||||
- Data source api changes, [PLUGIN_CHANGES.md](https://github.com/grafana/grafana/blob/master/public/app/plugins/PLUGIN_CHANGES.md)
|
||||
- The duplicate query function used in data source editors is changed, and moveMetricQuery function was renamed
|
||||
|
||||
**Tech (Note for devs)**
|
||||
Started using Typescript (transpiled to ES5), uncompiled typescript files and less files are in public folder (in source tree)
|
||||
This folder is never modified by build steps. Compiled css and javascript files are put in public_gen, all other files
|
||||
that do not undergo transformation are just copied from public to public_gen, it is public_gen that is used by grafana-server
|
||||
if it is found.
|
||||
|
||||
Grunt & Watch tasks:
|
||||
- `grunt` : default task, will remove public_gen, copy over all files from public, do less & typescript compilation
|
||||
- `grunt watch`: will watch for changes to less, and typescript files and compile them to public_gen, and for other files it will just copy them to public_gen
|
||||
|
||||
|
||||
# 2.1.3 (2015-08-24)
|
||||
|
||||
**Fixes**
|
||||
- [Issue #2580](https://github.com/grafana/grafana/issues/2580). Packaging: ldap.toml was not marked as config file and could be overwritten in upgrade
|
||||
- [Issue #2564](https://github.com/grafana/grafana/issues/2564). Templating: Another atempt at fixing #2534 (Init multi value template var used in repeat panel from url)
|
||||
|
||||
# 2.1.2 (2015-08-20)
|
||||
|
||||
**Fixes**
|
||||
- [Issue #2558](https://github.com/grafana/grafana/issues/2558). DragDrop: Fix for broken drag drop behavior
|
||||
- [Issue #2534](https://github.com/grafana/grafana/issues/2534). Templating: fix for setting template variable value via url and having repeated panels or rows
|
||||
|
||||
# 2.1.1 (2015-08-11)
|
||||
|
||||
**Fixes**
|
||||
- [Issue #2443](https://github.com/grafana/grafana/issues/2443). Templating: Fix for buggy repeat row behavior when combined with with repeat panel due to recent change before 2.1 release
|
||||
- [Issue #2442](https://github.com/grafana/grafana/issues/2442). Templating: Fix text panel when using template variables in text in in repeated panel
|
||||
- [Issue #2446](https://github.com/grafana/grafana/issues/2446). InfluxDB: Fix for using template vars inside alias field (InfluxDB 0.9)
|
||||
- [Issue #2460](https://github.com/grafana/grafana/issues/2460). SinglestatPanel: Fix to handle series with no data points
|
||||
- [Issue #2461](https://github.com/grafana/grafana/issues/2461). LDAP: Fix for ldap users with empty email address
|
||||
- [Issue #2484](https://github.com/grafana/grafana/issues/2484). Graphite: Fix bug when using series ref (#A-Z) and referenced series is hidden in query editor.
|
||||
- [Issue #1896](https://github.com/grafana/grafana/issues/1896). Postgres: Dashboard search is now case insensitive when using Postgres
|
||||
|
||||
**Enhancements**
|
||||
- [Issue #2477](https://github.com/grafana/grafana/issues/2477). InfluxDB(0.9): Added more condition operators (`<`, `>`, `<>`, `!~`), thx @thuck
|
||||
- [Issue #2483](https://github.com/grafana/grafana/issues/2484). InfluxDB(0.9): Use $col as option in alias patterns, thx @thuck
|
||||
|
||||
# 2.1.0 (2015-08-04)
|
||||
|
||||
**Data sources**
|
||||
- [Issue #1525](https://github.com/grafana/grafana/issues/1525). InfluxDB: Full support for InfluxDB 0.9 with new adapted query editor
|
||||
- [Issue #2191](https://github.com/grafana/grafana/issues/2191). KariosDB: Grafana now ships with a KariosDB data source plugin, thx @masaori335
|
||||
- [Issue #1177](https://github.com/grafana/grafana/issues/1177). OpenTSDB: Limit tags by metric, OpenTSDB config option tsd.core.meta.enable_realtime_ts must enabled for OpenTSDB lookup api
|
||||
- [Issue #1250](https://github.com/grafana/grafana/issues/1250). OpenTSDB: Support for template variable values lookup queries
|
||||
|
||||
**New dashboard features**
|
||||
- [Issue #1144](https://github.com/grafana/grafana/issues/1144). Templating: You can now select multiple template variables values at the same time.
|
||||
- [Issue #1922](https://github.com/grafana/grafana/issues/1922). Templating: Specify multiple variable values via URL params.
|
||||
- [Issue #1888](https://github.com/grafana/grafana/issues/1144). Templating: Repeat panel or row for each selected template variable value
|
||||
- [Issue #1888](https://github.com/grafana/grafana/issues/1944). Dashboard: Custom Navigation links & dynamic links to related dashboards
|
||||
- [Issue #590](https://github.com/grafana/grafana/issues/590). Graph: Define series color using regex rule
|
||||
- [Issue #2162](https://github.com/grafana/grafana/issues/2162). Graph: New series style override, negative-y transform and stack groups
|
||||
- [Issue #2096](https://github.com/grafana/grafana/issues/2096). Dashboard list panel: Now supports search by multiple tags
|
||||
- [Issue #2203](https://github.com/grafana/grafana/issues/2203). Singlestat: Now support string values
|
||||
|
||||
**User or Organization admin**
|
||||
- [Issue #1899](https://github.com/grafana/grafana/issues/1899). Organization: You can now update the organization user role directly (without removing and readding the organization user).
|
||||
- [Issue #2088](https://github.com/grafana/grafana/issues/2088). Roles: New user role `Read Only Editor` that replaces the old `Viewer` role behavior
|
||||
|
||||
**Backend**
|
||||
- [Issue #2218](https://github.com/grafana/grafana/issues/2218). Auth: You can now authenicate against api with username / password using basic auth
|
||||
- [Issue #2095](https://github.com/grafana/grafana/issues/2095). Search: Search now supports filtering by multiple dashboard tags
|
||||
- [Issue #1905](https://github.com/grafana/grafana/issues/1905). Github OAuth: You can now configure a Github team membership requirement, thx @dewski
|
||||
- [Issue #2052](https://github.com/grafana/grafana/issues/2052). Github OAuth: You can now configure a Github organization requirement, thx @indrekj
|
||||
- [Issue #1891](https://github.com/grafana/grafana/issues/1891). Security: New config option to disable the use of gravatar for profile images
|
||||
- [Issue #1921](https://github.com/grafana/grafana/issues/1921). Auth: Support for user authentication via reverse proxy header (like X-Authenticated-User, or X-WEBAUTH-USER)
|
||||
- [Issue #960](https://github.com/grafana/grafana/issues/960). Search: Backend can now index a folder with json files, will be available in search (saving back to folder is not supported, this feature is meant for static generated json dashboards)
|
||||
|
||||
**Breaking changes**
|
||||
- [Issue #1826](https://github.com/grafana/grafana/issues/1826). User role 'Viewer' are now prohibited from entering edit mode (and doing other transient dashboard edits). A new role `Read Only Editor` will replace the old Viewer behavior
|
||||
- [Issue #1928](https://github.com/grafana/grafana/issues/1928). HTTP API: GET /api/dashboards/db/:slug response changed property `model` to `dashboard` to match the POST request nameing
|
||||
- Backend render URL changed from `/render/dashboard/solo` `render/dashboard-solo/` (in order to have consistent dashboard url `/dashboard/:type/:slug`)
|
||||
- Search HTTP API response has changed (simplified), tags list moved to seperate HTTP resource URI
|
||||
- Datasource HTTP api breaking change, ADD datasource is now POST /api/datasources/, update is now PUT /api/datasources/:id
|
||||
|
||||
**Fixes**
|
||||
- [Issue #2185](https://github.com/grafana/grafana/issues/2185). Graph: fixed PNG rendering of panels with legend table to the right
|
||||
- [Issue #2163](https://github.com/grafana/grafana/issues/2163). Backend: Load dashboards with capital letters in the dashboard url slug (url id)
|
||||
|
||||
# 2.0.3 (unreleased - 2.0.x branch)
|
||||
|
||||
**Fixes**
|
||||
- [Issue #1872](https://github.com/grafana/grafana/issues/1872). Firefox/IE issue, invisible text in dashboard search fixed
|
||||
- [Issue #1857](https://github.com/grafana/grafana/issues/1857). /api/login/ping Fix for issue when behind reverse proxy and subpath
|
||||
- [Issue #1863](https://github.com/grafana/grafana/issues/1863). MySQL: Dashboard.data column type changed to mediumtext (sql migration added)
|
||||
|
||||
# 2.0.2 (2015-04-22)
|
||||
|
||||
**Fixes**
|
||||
- [Issue #1832](https://github.com/grafana/grafana/issues/1832). Graph Panel + Legend Table mode: Many series casued zero height graph, now legend will never reduce the height of the graph below 50% of row height.
|
||||
- [Issue #1846](https://github.com/grafana/grafana/issues/1846). Snapshots: Fixed issue with snapshoting dashboards with an interval template variable
|
||||
- [Issue #1848](https://github.com/grafana/grafana/issues/1848). Panel timeshift: You can now use panel timeshift without a relative time override
|
||||
|
||||
# 2.0.1 (2015-04-20)
|
||||
|
||||
**Fixes**
|
||||
- [Issue #1784](https://github.com/grafana/grafana/issues/1784). Data source proxy: Fixed issue with using data source proxy when grafana is behind nginx suburl
|
||||
- [Issue #1749](https://github.com/grafana/grafana/issues/1749). Graph Panel: Table legends are now visible when rendered to PNG
|
||||
- [Issue #1786](https://github.com/grafana/grafana/issues/1786). Graph Panel: Legend in table mode now aligns, graph area is reduced depending on how many series
|
||||
- [Issue #1734](https://github.com/grafana/grafana/issues/1734). Support for unicode / international characters in dashboard title (improved slugify)
|
||||
- [Issue #1782](https://github.com/grafana/grafana/issues/1782). Github OAuth: Now works with Github for Enterprise, thanks @williamjoy
|
||||
- [Issue #1780](https://github.com/grafana/grafana/issues/1780). Dashboard snapshot: Should not require login to view snapshot, Fixes #1780
|
||||
|
||||
# 2.0.0-Beta3 (2015-04-12)
|
||||
|
||||
**RPM / DEB Package changes (to follow HFS)**
|
||||
- binary name changed to grafana-server
|
||||
- does not install to `/opt/grafana` any more, installs to `/usr/share/grafana`
|
||||
- binary to `/usr/sbin/grafana-server`
|
||||
- init.d script improvements, renamed to `/etc/init.d/grafana-server`
|
||||
- added default file with environment variables,
|
||||
- `/etc/default/grafana-server` (deb/ubuntu)
|
||||
- `/etc/sysconfig/grafana-server` (centos/redhat)
|
||||
|
||||
- added systemd service file, tested on debian jessie and centos7
|
||||
- config file in same location `/etc/grafana/grafana.ini` (now complete config file but with every setting commented out)
|
||||
- data directory (where sqlite3) file is stored is now by default `/var/lib/grafana`
|
||||
- no symlinking current to versions anymore
|
||||
- For more info see [Issue #1758](https://github.com/grafana/grafana/issues/1758).
|
||||
|
||||
**Config breaking change (setting rename)**
|
||||
- `[log] root_path` has changed to `[paths] logs`
|
||||
|
||||
# 2.0.0-Beta2 (...)
|
||||
|
||||
**Enhancements**
|
||||
- [Issue #1701](https://github.com/grafana/grafana/issues/1701). Share modal: Override UI theme via URL param for Share link, rendered panel, or embedded panel
|
||||
- [Issue #1660](https://github.com/grafana/grafana/issues/1660). OAuth: Specify allowed email address domains for google or and github oauth logins
|
||||
|
||||
**Fixes**
|
||||
- [Issue #1649](https://github.com/grafana/grafana/issues/1649). HTTP API: grafana /render calls nows with api keys
|
||||
- [Issue #1667](https://github.com/grafana/grafana/issues/1667). Datasource proxy & session timeout fix (casued 401 Unauthorized error after a while)
|
||||
- [Issue #1707](https://github.com/grafana/grafana/issues/1707). Unsaved changes: Do not show for snapshots, scripted and file based dashboards
|
||||
- [Issue #1703](https://github.com/grafana/grafana/issues/1703). Unsaved changes: Do not show for users with role `Viewer`
|
||||
- [Issue #1675](https://github.com/grafana/grafana/issues/1675). Data source proxy: Fixed issue with Gzip enabled and data source proxy
|
||||
- [Issue #1681](https://github.com/grafana/grafana/issues/1681). MySQL session: fixed problem using mysql as session store
|
||||
- [Issue #1671](https://github.com/grafana/grafana/issues/1671). Data sources: Fixed issue with changing default data source (should not require full page load to take effect, now fixed)
|
||||
- [Issue #1685](https://github.com/grafana/grafana/issues/1685). Search: Dashboard results should be sorted alphabetically
|
||||
- [Issue #1673](https://github.com/grafana/grafana/issues/1673). Basic auth: Fixed issue when using basic auth proxy infront of Grafana
|
||||
|
||||
# 2.0.0-Beta1 (2015-03-30)
|
||||
|
||||
**Important Note**
|
||||
|
||||
Grafana 2.x is fundamentally different from 1.x; it now ships with an integrated backend server. Please read the [Documentation](http://docs.grafana.org) for more detailed about this SIGNIFCANT change to Grafana
|
||||
|
||||
**New features**
|
||||
- [Issue #1623](https://github.com/grafana/grafana/issues/1623). Share Dashboard: Dashboard snapshot sharing (dash and data snapshot), save to local or save to public snapshot dashboard snapshots.raintank.io site
|
||||
- [Issue #1622](https://github.com/grafana/grafana/issues/1622). Share Panel: The share modal now has an embed option, gives you an iframe that you can use to embedd a single graph on another web site
|
||||
- [Issue #718](https://github.com/grafana/grafana/issues/718). Dashboard: When saving a dashboard and another user has made changes inbetween the user is promted with a warning if he really wants to overwrite the other's changes
|
||||
- [Issue #1331](https://github.com/grafana/grafana/issues/1331). Graph & Singlestat: New axis/unit format selector and more units (kbytes, Joule, Watt, eV), and new design for graph axis & grid tab and single stat options tab views
|
||||
- [Issue #1241](https://github.com/grafana/grafana/issues/1242). Timepicker: New option in timepicker (under dashboard settings), to change ``now`` to be for example ``now-1m``, usefull when you want to ignore last minute because it contains incomplete data
|
||||
- [Issue #171](https://github.com/grafana/grafana/issues/171). Panel: Different time periods, panels can override dashboard relative time and/or add a time shift
|
||||
- [Issue #1488](https://github.com/grafana/grafana/issues/1488). Dashboard: Clone dashboard / Save as
|
||||
- [Issue #1458](https://github.com/grafana/grafana/issues/1458). User: persisted user option for dark or light theme (no longer an option on a dashboard)
|
||||
- [Issue #452](https://github.com/grafana/grafana/issues/452). Graph: Adds logarithmic scale option for base 10, base 16 and base 1024
|
||||
|
||||
**Enhancements**
|
||||
- [Issue #1366](https://github.com/grafana/grafana/issues/1366). Graph & Singlestat: Support for additional units, Fahrenheit (°F) and Celsius (°C), Humidity (%H), kW, watt-hour (Wh), kilowatt-hour (kWh), velocities (m/s, km/h, mpg, knot)
|
||||
- [Issue #978](https://github.com/grafana/grafana/issues/978). Graph: Shared tooltip improvement, can now support metrics of different resolution/intervals
|
||||
- [Issue #1297](https://github.com/grafana/grafana/issues/1297). Graphite: Added cumulative and minimumBelow graphite functions
|
||||
- [Issue #1296](https://github.com/grafana/grafana/issues/1296). InfluxDB: Auto escape column names with special characters. Thanks @steven-aerts
|
||||
- [Issue #1321](https://github.com/grafana/grafana/issues/1321). SingleStatPanel: You can now use template variables in pre & postfix
|
||||
- [Issue #599](https://github.com/grafana/grafana/issues/599). Graph: Added right y axis label setting and graph support
|
||||
- [Issue #1253](https://github.com/grafana/grafana/issues/1253). Graph & Singlestat: Users can now set decimal precision for legend and tooltips (override auto precision)
|
||||
- [Issue #1255](https://github.com/grafana/grafana/issues/1255). Templating: Dashboard will now wait to load until all template variables that have refresh on load set or are initialized via url to be fully loaded and so all variables are in valid state before panels start issuing metric requests.
|
||||
- [Issue #1344](https://github.com/grafana/grafana/issues/1344). OpenTSDB: Alias patterns (reference tag values), syntax is: $tag_tagname or [[tag_tagname]]
|
||||
|
||||
**Fixes**
|
||||
- [Issue #1298](https://github.com/grafana/grafana/issues/1298). InfluxDB: Fix handling of empty array in templating variable query
|
||||
- [Issue #1309](https://github.com/grafana/grafana/issues/1309). Graph: Fixed issue when using zero as a grid threshold
|
||||
- [Issue #1345](https://github.com/grafana/grafana/issues/1345). UI: Fixed position of confirm modal when scrolled down
|
||||
- [Issue #1372](https://github.com/grafana/grafana/issues/1372). Graphite: Fix for nested complex queries, where a query references a query that references another query (ie the #[A-Z] syntax)
|
||||
- [Issue #1363](https://github.com/grafana/grafana/issues/1363). Templating: Fix to allow custom template variables to contain white space, now only splits on ','
|
||||
- [Issue #1359](https://github.com/grafana/grafana/issues/1359). Graph: Fix for all series tooltip showing series with all null values when ``Hide Empty`` option is enabled
|
||||
- [Issue #1497](https://github.com/grafana/grafana/issues/1497). Dashboard: Fixed memory leak when switching dashboards
|
||||
|
||||
**Changes**
|
||||
- Dashboard title change & save will no longer create a new dashboard, it will just change the title.
|
||||
|
||||
**OpenTSDB breaking change**
|
||||
- [Issue #1438](https://github.com/grafana/grafana/issues/1438). OpenTSDB: Automatic downsample interval passed to OpenTSDB (depends on timespan and graph width)
|
||||
- NOTICE, Downsampling is now enabled by default, so if you have not picked a downsample aggregator in your metric query do so or your graphs will be missleading
|
||||
- This will make Grafana a lot quicker for OpenTSDB users when viewing large time spans without having to change the downsample interval manually.
|
||||
|
||||
**Tech**
|
||||
- [Issue #1311](https://github.com/grafana/grafana/issues/1311). Tech: Updated Font-Awesome from 3.2 to 4.2
|
||||
|
||||
# 1.9.1 (2014-12-29)
|
||||
|
||||
**Enhancements**
|
||||
- [Issue #1028](https://github.com/grafana/grafana/issues/1028). Graph: New legend option ``hideEmtpy`` to hide series with only null values from legend
|
||||
- [Issue #1242](https://github.com/grafana/grafana/issues/1242). OpenTSDB: Downsample query field now supports interval template variable
|
||||
- [Issue #1126](https://github.com/grafana/grafana/issues/1126). InfluxDB: Support more than 10 series name segments when using alias ``$number`` patterns
|
||||
|
||||
**Fixes**
|
||||
- [Issue #1251](https://github.com/grafana/grafana/issues/1251). Graph: Fix for y axis and scaled units (GiB etc) caused rounding, for example 400 GiB instead of 378 GiB
|
||||
- [Issue #1199](https://github.com/grafana/grafana/issues/1199). Graph: fix for series tooltip when one series is hidden/disabled
|
||||
- [Issue #1207](https://github.com/grafana/grafana/issues/1207). Graphite: movingAverage / movingMedian parameter type impovement, now handles int and interval parameter
|
||||
|
||||
# 1.9.0 (2014-12-02)
|
||||
|
||||
**Enhancements**
|
||||
- [Issue #1130](https://github.com/grafana/grafana/issues/1130). SinglestatPanel: Added null point handling, and value to text mapping
|
||||
|
||||
|
||||
**Fixes**
|
||||
- [Issue #1087](https://github.com/grafana/grafana/issues/1087). Panel: Fixed IE9 crash due to angular drag drop
|
||||
- [Issue #1093](https://github.com/grafana/grafana/issues/1093). SingleStatPanel: Fixed position for drilldown link tooltip when dashboard requires scrolling
|
||||
- [Issue #1095](https://github.com/grafana/grafana/issues/1095). DrilldownLink: template variables in params property was not interpolated
|
||||
- [Issue #1114](https://github.com/grafana/grafana/issues/1114). Graphite: Lexer fix, allow equal sign (=) in metric paths
|
||||
- [Issue #1136](https://github.com/grafana/grafana/issues/1136). Graph: Fix to legend value Max and negative values
|
||||
- [Issue #1150](https://github.com/grafana/grafana/issues/1150). SinglestatPanel: Fixed absolute drilldown link issue
|
||||
- [Issue #1123](https://github.com/grafana/grafana/issues/1123). Firefox: Workaround for Firefox bug, casued input text fields to not be selectable and not have placeable cursor
|
||||
- [Issue #1108](https://github.com/grafana/grafana/issues/1108). Graph: Fix for tooltip series order when series draw order was changed with zindex property
|
||||
|
||||
# 1.9.0-rc1 (2014-11-17)
|
||||
|
||||
**UI Improvements**
|
||||
- [Issue #770](https://github.com/grafana/grafana/issues/770). UI: Panel dropdown menu replaced with a new panel menu
|
||||
|
||||
**Graph**
|
||||
- [Issue #877](https://github.com/grafana/grafana/issues/877). Graph: Smart auto decimal precision when using scaled unit formats
|
||||
- [Issue #850](https://github.com/grafana/grafana/issues/850). Graph: Shared tooltip that shows multiple series & crosshair line, thx @toni-moreno
|
||||
- [Issue #940](https://github.com/grafana/grafana/issues/940). Graph: New series style override option "Fill below to", useful to visualize max & min as a shadow for the mean
|
||||
- [Issue #1030](https://github.com/grafana/grafana/issues/1030). Graph: Legend table display/look changed, now includes column headers for min/max/avg, and full width (unless on right side)
|
||||
- [Issue #861](https://github.com/grafana/grafana/issues/861). Graph: Export graph time series data as csv file
|
||||
|
||||
**New Panels**
|
||||
- [Issue #951](https://github.com/grafana/grafana/issues/951). SingleStat: New singlestat panel
|
||||
|
||||
**Misc**
|
||||
- [Issue #864](https://github.com/grafana/grafana/issues/846). Panel: Share panel feature, get a link to panel with the current time range
|
||||
- [Issue #938](https://github.com/grafana/grafana/issues/938). Panel: Plugin panels now reside outside of app/panels directory
|
||||
- [Issue #952](https://github.com/grafana/grafana/issues/952). Help: Shortcut "?" to open help modal with list of all shortcuts
|
||||
- [Issue #991](https://github.com/grafana/grafana/issues/991). ScriptedDashboard: datasource services are now available in scripted dashboards, you can query datasource for metric keys, generate dashboards, and even save them in a scripted dashboard (see scripted_gen_and_save.js for example)
|
||||
- [Issue #1041](https://github.com/grafana/grafana/issues/1041). Panel: All panels can now have links to other dashboards or absolute links, these links are available in the panel menu.
|
||||
|
||||
**Changes**
|
||||
- [Issue #1007](https://github.com/grafana/grafana/issues/1007). Graph: Series hide/show toggle changed to be default exclusive, so clicking on a series name will show only that series. (SHIFT or meta)+click will toggle hide/show.
|
||||
|
||||
**OpenTSDB**
|
||||
- [Issue #930](https://github.com/grafana/grafana/issues/930). OpenTSDB: Adding counter max and counter reset value to open tsdb query editor, thx @rsimiciuc
|
||||
- [Issue #917](https://github.com/grafana/grafana/issues/917). OpenTSDB: Templating support for OpenTSDB series name and tags, thx @mchataigner
|
||||
|
||||
**InfluxDB**
|
||||
- [Issue #714](https://github.com/grafana/grafana/issues/714). InfluxDB: Support for sub second resolution graphs
|
||||
|
||||
**Fixes**
|
||||
- [Issue #925](https://github.com/grafana/grafana/issues/925). Graph: bar width calculation fix for some edge cases (bars would render on top of each other)
|
||||
- [Issue #505](https://github.com/grafana/grafana/issues/505). Graph: fix for second y axis tick unit labels wrapping on the next line
|
||||
- [Issue #987](https://github.com/grafana/grafana/issues/987). Dashboard: Collapsed rows became invisible when hide controls was enabled
|
||||
|
||||
=======
|
||||
# 1.8.1 (2014-09-30)
|
||||
|
||||
**Fixes**
|
||||
- [Issue #855](https://github.com/grafana/grafana/issues/855). Graph: Fix for scroll issue in graph edit mode when dropdown goes below screen
|
||||
- [Issue #847](https://github.com/grafana/grafana/issues/847). Graph: Fix for series draw order not being the same after hiding/unhiding series
|
||||
- [Issue #851](https://github.com/grafana/grafana/issues/851). Annotations: Fix for annotations not reloaded when switching between 2 dashboards with annotations
|
||||
- [Issue #846](https://github.com/grafana/grafana/issues/846). Edit panes: Issue when open row or json editor when scrolled down the page, unable to scroll and you did not see editor
|
||||
- [Issue #840](https://github.com/grafana/grafana/issues/840). Import: Fixes to import from json file and import from graphite. Issues was lingering state from previous dashboard.
|
||||
- [Issue #859](https://github.com/grafana/grafana/issues/859). InfluxDB: Fix for bug when saving dashboard where title is the same as slugified url id
|
||||
- [Issue #852](https://github.com/grafana/grafana/issues/852). White theme: Fixes for hidden series legend text and disabled annotations color
|
||||
|
||||
# 1.8.0 (2014-09-22)
|
||||
|
||||
Read this [blog post](http://grafana.org/blog/2014/09/11/grafana-1-8-0-rc1-released.html) for an overview of all improvements.
|
||||
|
||||
**Fixes**
|
||||
- [Issue #802](https://github.com/grafana/grafana/issues/802). Annotations: Fix when using InfluxDB datasource
|
||||
- [Issue #795](https://github.com/grafana/grafana/issues/795). Chrome: Fix for display issue in chrome beta & chrome canary when entering edit mode
|
||||
- [Issue #818](https://github.com/grafana/grafana/issues/818). Graph: Added percent y-axis format
|
||||
- [Issue #828](https://github.com/grafana/grafana/issues/828). Elasticsearch: saving new dashboard with title equal to slugified url would cause it to deleted.
|
||||
- [Issue #830](https://github.com/grafana/grafana/issues/830). Annotations: Fix for elasticsearch annotations and mapping nested fields
|
||||
|
||||
# 1.8.0-RC1 (2014-09-12)
|
||||
|
||||
**UI polish / changes**
|
||||
- [Issue #725](https://github.com/grafana/grafana/issues/725). UI: All modal editors are removed and replaced by an edit pane under menu. The look of editors is also updated and polished. Search dropdown is also shown as pane under menu and has seen some UI polish.
|
||||
|
||||
**Filtering/Templating feature overhaul**
|
||||
- Filtering renamed to Templating, and filter items to variables
|
||||
- Filter editing has gotten its own edit pane with much improved UI and options
|
||||
- [Issue #296](https://github.com/grafana/grafana/issues/296). Templating: Can now retrieve variable values from a non-default data source
|
||||
- [Issue #219](https://github.com/grafana/grafana/issues/219). Templating: Template variable value selection is now a typeahead autocomplete dropdown
|
||||
- [Issue #760](https://github.com/grafana/grafana/issues/760). Templating: Extend template variable syntax to include $variable syntax replacement
|
||||
- [Issue #234](https://github.com/grafana/grafana/issues/234). Templating: Interval variable type for time intervals summarize/group by parameter, included "auto" option, and auto step counts option.
|
||||
- [Issue #262](https://github.com/grafana/grafana/issues/262). Templating: Ability to use template variables for function parameters via custom variable type, can be used as parameter for movingAverage or scaleToSeconds for example
|
||||
- [Issue #312](https://github.com/grafana/grafana/issues/312). Templating: Can now use template variables in panel titles
|
||||
- [Issue #613](https://github.com/grafana/grafana/issues/613). Templating: Full support for InfluxDB, filter by part of series names, extract series substrings, nested queries, multipe where clauses!
|
||||
- Template variables can be initialized from url, with var-my_varname=value, breaking change, before it was just my_varname.
|
||||
- Templating and url state sync has some issues that are not solved for this release, see [Issue #772](https://github.com/grafana/grafana/issues/772) for more details.
|
||||
|
||||
**InfluxDB Breaking changes**
|
||||
- To better support templating, fill(0) and group by time low limit some changes has been made to the editor and query model schema
|
||||
- Currently some of these changes are breaking
|
||||
- If you used custom condition filter you need to open the graph in edit mode, the editor will update the schema, and the queries should work again
|
||||
- If you used a raw query you need to remove the time filter and replace it with $timeFilter (this is done automatically when you switch from query editor to raw query, but old raw queries needs to updated)
|
||||
- If you used group by and later removed the group by the graph could break, open in editor and should correct it
|
||||
- InfluxDB annotation queries that used [[timeFilter]] should be updated to use $timeFilter syntax instead
|
||||
- Might write an upgrade tool to update dashboards automatically, but right now master (1.8) includes the above breaking changes
|
||||
|
||||
**InfluxDB query editor enhancements**
|
||||
- [Issue #756](https://github.com/grafana/grafana/issues/756). InfluxDB: Add option for fill(0) and fill(null), integrated help in editor for why this option is important when stacking series
|
||||
- [Issue #743](https://github.com/grafana/grafana/issues/743). InfluxDB: A group by time option for all queries in graph panel that supports a low limit for auto group by time, very important for stacking and fill(0)
|
||||
- The above to enhancements solves the problems associated with stacked bars and lines when points are missing, these issues are solved:
|
||||
- [Issue #673](https://github.com/grafana/grafana/issues/673). InfluxDB: stacked bars missing intermediate data points, unless lines also enabled
|
||||
- [Issue #674](https://github.com/grafana/grafana/issues/674). InfluxDB: stacked chart ignoring series without latest values
|
||||
- [Issue #534](https://github.com/grafana/grafana/issues/534). InfluxDB: No order in stacked bars mode
|
||||
|
||||
**New features and improvements**
|
||||
- [Issue #117](https://github.com/grafana/grafana/issues/117). Graphite: Graphite query builder can now handle functions that multiple series as arguments!
|
||||
- [Issue #281](https://github.com/grafana/grafana/issues/281). Graphite: Metric node/segment selection is now a textbox with autocomplete dropdown, allow for custom glob expression for single node segment without entering text editor mode.
|
||||
- [Issue #304](https://github.com/grafana/grafana/issues/304). Dashboard: View dashboard json, edit/update any panel using json editor, makes it possible to quickly copy a graph from one dashboard to another.
|
||||
- [Issue #578](https://github.com/grafana/grafana/issues/578). Dashboard: Row option to display row title even when the row is visible
|
||||
- [Issue #672](https://github.com/grafana/grafana/issues/672). Dashboard: panel fullscreen & edit state is present in url, can now link to graph in edit & fullscreen mode.
|
||||
- [Issue #709](https://github.com/grafana/grafana/issues/709). Dashboard: Small UI look polish to search results, made dashboard title link are larger
|
||||
- [Issue #425](https://github.com/grafana/grafana/issues/425). Graph: New section in 'Display Styles' tab to override any display setting on per series bases (mix and match lines, bars, points, fill, stack, line width etc)
|
||||
- [Issue #634](https://github.com/grafana/grafana/issues/634). Dashboard: Dashboard tags now in different colors (from fixed palette) determined by tag name.
|
||||
- [Issue #685](https://github.com/grafana/grafana/issues/685). Dashboard: New config.js option to change/remove window title prefix.
|
||||
- [Issue #781](https://github.com/grafana/grafana/issues/781). Dashboard: Title URL is now slugified for greater URL readability, works with both ES & InfluxDB storage, is backward compatible
|
||||
- [Issue #785](https://github.com/grafana/grafana/issues/785). Elasticsearch: Support for full elasticsearch lucene search grammar when searching for dashboards, better async search
|
||||
- [Issue #787](https://github.com/grafana/grafana/issues/787). Dashboard: time range can now be read from URL parameters, will override dashboard saved time range
|
||||
|
||||
**Fixes**
|
||||
- [Issue #696](https://github.com/grafana/grafana/issues/696). Graph: Fix for y-axis format 'none' when values are in scientific notation (ex 2.3e-13)
|
||||
- [Issue #733](https://github.com/grafana/grafana/issues/733). Graph: Fix for tooltip current value decimal precision when 'none' axis format was selected
|
||||
- [Issue #697](https://github.com/grafana/grafana/issues/697). Graphite: Fix for Glob syntax in graphite queries ([1-9] and ?) that made the query editor / parser bail and fallback to a text box.
|
||||
- [Issue #702](https://github.com/grafana/grafana/issues/702). Graphite: Fix for nonNegativeDerivative function, now possible to not include optional first parameter maxValue
|
||||
- [Issue #277](https://github.com/grafana/grafana/issues/277). Dashboard: Fix for timepicker date & tooltip when UTC timezone selected.
|
||||
- [Issue #699](https://github.com/grafana/grafana/issues/699). Dashboard: Fix for bug when adding rows from dashboard settings dialog.
|
||||
- [Issue #723](https://github.com/grafana/grafana/issues/723). Dashboard: Fix for hide controls setting not used/initialized on dashboard load
|
||||
- [Issue #724](https://github.com/grafana/grafana/issues/724). Dashboard: Fix for zoom out causing right hand "to" range to be set in the future.
|
||||
|
||||
**Tech**
|
||||
- Upgraded from angularjs 1.1.5 to 1.3 beta 17;
|
||||
- Switch from underscore to lodash
|
||||
- helpers to easily unit test angularjs controllers and services
|
||||
- Test coverage through coveralls
|
||||
- Upgrade from jquery 1.8.0 to 2.1.1 (**Removes support for IE7 & IE8**)
|
||||
|
||||
# 1.7.1 (unreleased)
|
||||
|
||||
**Fixes**
|
||||
- [Issue #691](https://github.com/grafana/grafana/issues/691). Dashboard: Tooltip fixes, sometimes they would not show, and sometimes they would get stuck.
|
||||
- [Issue #695](https://github.com/grafana/grafana/issues/695). Dashboard: Tooltip on goto home menu icon would get stuck after clicking on it
|
||||
|
||||
# 1.7.0 (2014-08-11)
|
||||
|
||||
**Fixes**
|
||||
- [Issue #652](https://github.com/grafana/grafana/issues/652). Timepicker: Entering custom date range impossible when refresh is low (now is constantly reset)
|
||||
- [Issue #450](https://github.com/grafana/grafana/issues/450). Graph: Tooltip does not disappear sometimes and would get stuck
|
||||
- [Issue #655](https://github.com/grafana/grafana/issues/655). General: Auto refresh not initiated / started after dashboard loading
|
||||
- [Issue #657](https://github.com/grafana/grafana/issues/657). General: Fix for refresh icon in IE browsers
|
||||
- [Issue #661](https://github.com/grafana/grafana/issues/661). Annotations: Elasticsearch querystring with filter template replacements was not interpolated
|
||||
- [Issue #660](https://github.com/grafana/grafana/issues/660). OpenTSDB: fix opentsdb queries that returned more than one series
|
||||
|
||||
**Change**
|
||||
- [Issue #681](https://github.com/grafana/grafana/issues/681). Dashboard: The panel error bar has been replaced with a small error indicator, this indicator does not change panel height and is a lot less intrusive. Hover over it for short details, click on it for more details.
|
||||
|
||||
# 1.7.0-rc1 (2014-08-05)
|
||||
|
||||
**New features or improvements**
|
||||
- [Issue #581](https://github.com/grafana/grafana/issues/581). InfluxDB: Add continuous query in series results (series typeahead).
|
||||
- [Issue #584](https://github.com/grafana/grafana/issues/584). InfluxDB: Support for alias & alias patterns when using raw query mode
|
||||
- [Issue #394](https://github.com/grafana/grafana/issues/394). InfluxDB: Annotation support
|
||||
- [Issue #633](https://github.com/grafana/grafana/issues/633). InfluxDB: InfluxDB can now act as a datastore for dashboards
|
||||
- [Issue #610](https://github.com/grafana/grafana/issues/610). InfluxDB: Support for InfluxdB v0.8 list series response schemea (series typeahead)
|
||||
- [Issue #525](https://github.com/grafana/grafana/issues/525). InfluxDB: Enhanced series aliasing (legend names) with pattern replacements
|
||||
- [Issue #266](https://github.com/grafana/grafana/issues/266). Graphite: New option cacheTimeout to override graphite default memcache timeout
|
||||
- [Issue #606](https://github.com/grafana/grafana/issues/606). General: New global option in config.js to specify admin password (useful to hinder users from accidentally make changes)
|
||||
- [Issue #201](https://github.com/grafana/grafana/issues/201). Annotations: Elasticsearch datasource support for events
|
||||
- [Issue #344](https://github.com/grafana/grafana/issues/344). Annotations: Annotations can now be fetched from non default datasources
|
||||
- [Issue #631](https://github.com/grafana/grafana/issues/631). Search: max_results config.js option & scroll in search results (To show more or all dashboards)
|
||||
- [Issue #511](https://github.com/grafana/grafana/issues/511). Text panel: Allow [[..]] filter notation in all text panels (markdown/html/text)
|
||||
- [Issue #136](https://github.com/grafana/grafana/issues/136). Graph: New legend display option "Align as table"
|
||||
- [Issue #556](https://github.com/grafana/grafana/issues/556). Graph: New legend display option "Right side", will show legend to the right of the graph
|
||||
- [Issue #604](https://github.com/grafana/grafana/issues/604). Graph: New axis format, 'bps' (SI unit in steps of 1000) useful for network gear metics
|
||||
- [Issue #626](https://github.com/grafana/grafana/issues/626). Graph: Downscale y axis to more precise unit, value of 0.1 for seconds format will be formated as 100 ms. Thanks @kamaradclimber
|
||||
- [Issue #618](https://github.com/grafana/grafana/issues/618). OpenTSDB: Series alias option to override metric name returned from opentsdb. Thanks @heldr
|
||||
|
||||
**Documentation**
|
||||
- [Issue #635](https://github.com/grafana/grafana/issues/635). Docs for features and changes in v1.7, new troubleshooting guide, new Getting started guide, improved install & config guide.
|
||||
|
||||
|
||||
**Changes**
|
||||
- [Issue #536](https://github.com/grafana/grafana/issues/536). Graphite: Use unix epoch for Graphite from/to for absolute time ranges
|
||||
- [Issue #641](https://github.com/grafana/grafana/issues/536). General: Dashboard save temp copy feature settings moved from dashboard to config.js, default is enabled, and ttl to 30 days
|
||||
- [Issue #532](https://github.com/grafana/grafana/issues/532). Schema: Dashboard schema changes, "Unsaved changes" should not appear for schema changes. All changes are backward compatible with old schema.
|
||||
|
||||
**Fixes**
|
||||
- [Issue #545](https://github.com/grafana/grafana/issues/545). Graph: Fix formatting negative values (axis formats, legend values)
|
||||
- [Issue #460](https://github.com/grafana/grafana/issues/460). Graph: fix for max legend value when max value is zero
|
||||
- [Issue #628](https://github.com/grafana/grafana/issues/628). Filtering: Fix for nested filters, changing a child filter could result in infinite recursion in some cases
|
||||
- [Issue #528](https://github.com/grafana/grafana/issues/528). Graphite: Fix for graphite expressions parser failure when metric expressions starts with curly brace segment
|
||||
|
||||
# 1.6.1 (2014-06-24)
|
||||
|
||||
**New features or improvements**
|
||||
- [Issue #360](https://github.com/grafana/grafana/issues/360). Ability to set y min/max for right y-axis (RR #519)
|
||||
|
||||
**Fixes**
|
||||
|
||||
- [Issue #500](https://github.com/grafana/grafana/issues/360). Fixes regex InfluxDB queries intoduced in 1.6.0
|
||||
- [Issue #506](https://github.com/grafana/grafana/issues/506). Bug in when using % sign in legends (aliases), fixed by removing url decoding of metric names
|
||||
- [Issue #522](https://github.com/grafana/grafana/issues/522). Series names and column name typeahead cache fix
|
||||
- [Issue #504](https://github.com/grafana/grafana/issues/504). Fixed influxdb issue with raw query that caused wrong value column detection
|
||||
- [Issue #526](https://github.com/grafana/grafana/issues/526). Default property that marks which datasource is default in config.js is now optional
|
||||
- [Issue #342](https://github.com/grafana/grafana/issues/342). Auto-refresh caused 2 refreshes (and hence mulitple queries) each time (at least in firefox)
|
||||
|
||||
# 1.6.0 (2014-06-16)
|
||||
|
||||
#### New features or improvements
|
||||
- [Issue #427](https://github.com/grafana/grafana/issues/427). New Y-axis formater for metric values that represent seconds, Thanks @jippi
|
||||
- [Issue #390](https://github.com/grafana/grafana/issues/390). Allow special characters in serie names (influxdb datasource), Thanks @majst01
|
||||
- [Issue #428](https://github.com/grafana/grafana/issues/428). Refactoring of filterSrv, Thanks @Tetha
|
||||
- [Issue #445](https://github.com/grafana/grafana/issues/445). New config for playlist feature. Set playlist_timespan to set default playlist interval, Thanks @rmca
|
||||
- [Issue #461](https://github.com/grafana/grafana/issues/461). New graphite function definition added isNonNull, Thanks @tmonk42
|
||||
- [Issue #455](https://github.com/grafana/grafana/issues/455). New InfluxDB function difference add to function dropdown
|
||||
- [Issue #459](https://github.com/grafana/grafana/issues/459). Added parameter to keepLastValue graphite function definition (default 100)
|
||||
[Issue #418](https://github.com/grafana/grafana/issues/418). to the browser cache when upgrading grafana and improve load performance
|
||||
- [Issue #327](https://github.com/grafana/grafana/issues/327). Partial support for url encoded metrics when using Graphite datasource. Thanks @axe-felix
|
||||
- [Issue #473](https://github.com/grafana/grafana/issues/473). Improvement to InfluxDB query editor and function/value column selection
|
||||
- [Issue #375](https://github.com/grafana/grafana/issues/375). Initial support for filtering (templated queries) for InfluxDB. Thanks @mavimo
|
||||
- [Issue #475](https://github.com/grafana/grafana/issues/475). Row editing and adding new panel is now a lot quicker and easier with the new row menu
|
||||
- [Issue #211](https://github.com/grafana/grafana/issues/211). New datasource! Initial support for OpenTSDB, Thanks @mpage
|
||||
- [Issue #492](https://github.com/grafana/grafana/issues/492). Improvement and polish to the OpenTSDB query editor
|
||||
- [Issue #441](https://github.com/grafana/grafana/issues/441). Influxdb group by support, Thanks @piis3
|
||||
- improved asset (css/js) build pipeline, added revision to css and js. Will remove issues related
|
||||
|
||||
|
||||
#### Changes
|
||||
- [Issue #475](https://github.com/grafana/grafana/issues/475). Add panel icon and Row edit button is replaced by the Row edit menu
|
||||
- New graphs now have a default empty query
|
||||
- Add Row button now creates a row with default height of 250px (no longer opens dashboard settings modal)
|
||||
- Clean up of config.sample.js, graphiteUrl removed (still works, but depricated, removed in future)
|
||||
Use datasources config instead. panel_names removed from config.js. Use plugins.panels to add custom panels
|
||||
- Graphite panel is now renamed graph (Existing dashboards will still work)
|
||||
|
||||
#### Fixes
|
||||
- [Issue #126](https://github.com/grafana/grafana/issues/126). Graphite query lexer change, can now handle regex parameters for aliasSub function
|
||||
- [Issue #447](https://github.com/grafana/grafana/issues/447). Filter option loading when having muliple nested filters now works better. Options are now reloaded correctly and there are no multiple renders/refresh inbetween.
|
||||
- [Issue #412](https://github.com/grafana/grafana/issues/412). After a filter option is changed and a nested template param is reloaded, if the current value exists after the options are reloaded the current selected value is kept.
|
||||
- [Issue #460](https://github.com/grafana/grafana/issues/460). Legend Current value did not display when value was zero
|
||||
- [Issue #328](https://github.com/grafana/grafana/issues/328). Fix to series toggling bug that caused annotations to be hidden when toggling/hiding series.
|
||||
- [Issue #293](https://github.com/grafana/grafana/issues/293). Fix for graphite function selection menu that some times draws outside screen. It now displays upward
|
||||
- [Issue #350](https://github.com/grafana/grafana/issues/350). Fix for exclusive series toggling (hold down CTRL, SHIFT or META key) and left click a series for exclusive toggling
|
||||
- [Issue #472](https://github.com/grafana/grafana/issues/472). CTRL does not work on MAC OSX but SHIFT or META should (depending on browser)
|
||||
|
||||
# 1.5.4 (2014-05-13)
|
||||
### New features and improvements
|
||||
- InfluxDB enhancement: support for multiple hosts (with retries) and raw queries ([Issue #318](https://github.com/grafana/grafana/issues/318), thx @toddboom)
|
||||
- Added rounding for graphites from and to time range filters
|
||||
for very short absolute ranges ([Issue #320](https://github.com/grafana/grafana/issues/320))
|
||||
- Increased resolution for graphite datapoints (maxDataPoints), now equal to panel pixel width. ([Issue #5](https://github.com/grafana/grafana/issues/5))
|
||||
- Improvement to influxdb query editor, can now add where clause and alias ([Issue #331](https://github.com/grafana/grafana/issues/331), thanks @mavimo)
|
||||
- New config setting for graphite datasource to control if json render request is POST or GET ([Issue #345](https://github.com/grafana/grafana/issues/345))
|
||||
- Unsaved changes warning feature ([Issue #324](https://github.com/grafana/grafana/issues/324))
|
||||
- Improvement to series toggling, CTRL+MouseClick on series name will now hide all others ([Issue #350](https://github.com/grafana/grafana/issues/350))
|
||||
|
||||
### Changes
|
||||
- Graph default setting for Y-Min changed from zero to auto scalling (will not effect existing dashboards). ([Issue #386](https://github.com/grafana/grafana/issues/386)) - thx @kamaradclimber
|
||||
|
||||
### Fixes
|
||||
- Fixes to filters and "All" option. It now never uses "*" as value, but all options in a {node1, node2, node3} expression ([Issue #228](https://github.com/grafana/grafana/issues/228), #359)
|
||||
- Fix for InfluxDB query generation with columns containing dots or dashes ([Issue #369](https://github.com/grafana/grafana/issues/369), #348) - Thanks to @jbripley
|
||||
|
||||
|
||||
# 1.5.3 (2014-04-17)
|
||||
- Add support for async scripted dashboards ([Issue #274](https://github.com/grafana/grafana/issues/274))
|
||||
- Text panel now accepts html (for links to other dashboards, etc) ([Issue #236](https://github.com/grafana/grafana/issues/236))
|
||||
- Fix for Text panel, now changes take effect directly ([Issue #251](https://github.com/grafana/grafana/issues/251))
|
||||
- Fix when adding functions without params that did not cause graph to update ([Issue #267](https://github.com/grafana/grafana/issues/267))
|
||||
- Graphite errors are now much easier to see and troubleshoot with the new inspector ([Issue #265](https://github.com/grafana/grafana/issues/265))
|
||||
- Use influxdb aliases to distinguish between multiple columns ([Issue #283](https://github.com/grafana/grafana/issues/283))
|
||||
- Correction to ms axis formater, now formats days correctly. ([Issue #189](https://github.com/grafana/grafana/issues/189))
|
||||
- Css fix for Firefox and using top menu dropdowns in panel fullscren / edit mode ([Issue #106](https://github.com/grafana/grafana/issues/106))
|
||||
- Browser page title is now Grafana - {{dashboard title}} ([Issue #294](https://github.com/grafana/grafana/issues/294))
|
||||
- Disable auto refresh zooming in (every time you change to an absolute time range), refresh will be restored when you change time range back to relative ([Issue #282](https://github.com/grafana/grafana/issues/282))
|
||||
- More graphite functions
|
||||
|
||||
# 1.5.2 (2014-03-24)
|
||||
### New Features and improvements
|
||||
- Support for second optional params for functions like aliasByNode ([Issue #167](https://github.com/grafana/grafana/issues/167)). Read the wiki on the [Function Editor](https://github.com/torkelo/grafana/wiki/Graphite-Function-Editor) for more info.
|
||||
- More functions added to InfluxDB query editor ([Issue #218](https://github.com/grafana/grafana/issues/218))
|
||||
- Filters can now be used inside other filters (templated segments) ([Issue #128](https://github.com/grafana/grafana/issues/128))
|
||||
- More graphite functions added
|
||||
|
||||
### Fixes
|
||||
- Float arguments now work for functions like scale ([Issue #223](https://github.com/grafana/grafana/issues/223))
|
||||
- Fix for graphite function editor, the graph & target was not updated after adding a function and leaving default params as is #191
|
||||
|
||||
The zip files now contains a sub folder with project name and version prefix. ([Issue #209](https://github.com/grafana/grafana/issues/209))
|
||||
|
||||
# 1.5.1 (2014-03-10)
|
||||
### Fixes
|
||||
- maxDataPoints must be an integer #184 (thanks @frejsoya for fixing this)
|
||||
|
||||
For people who are find Grafana slow for large time spans or high resolution metrics. This is most likely due to graphite returning a large number of datapoints. The maxDataPoints parameter solves this issue. For maxDataPoints to work you need to run the latest graphite-web (some builds of 0.9.12 does not include this feature).
|
||||
|
||||
Read this for more info:
|
||||
[Performance for large time spans](https://github.com/torkelo/grafana/wiki/Performance-for-large-time-spans)
|
||||
|
||||
# 1.5.0 (2014-03-09)
|
||||
### New Features and improvements
|
||||
- New function editor [video demo](http://youtu.be/I90WHRwE1ZM) ([Issue #178](https://github.com/grafana/grafana/issues/178))
|
||||
- Links to function documentation from function editor ([Issue #3](https://github.com/grafana/grafana/issues/3))
|
||||
- Reorder functions ([Issue #130](https://github.com/grafana/grafana/issues/130))
|
||||
- [Initial support for InfluxDB](https://github.com/torkelo/grafana/wiki/InfluxDB) as metric datasource (#103), need feedback!
|
||||
- [Dashboard playlist](https://github.com/torkelo/grafana/wiki/Dashboard-playlist) ([Issue #36](https://github.com/grafana/grafana/issues/36))
|
||||
- When adding aliasByNode smartly set node number ([Issue #175](https://github.com/grafana/grafana/issues/175))
|
||||
- Support graphite identifiers with embedded colons ([Issue #173](https://github.com/grafana/grafana/issues/173))
|
||||
- Typeahead & autocomplete when adding new function ([Issue #164](https://github.com/grafana/grafana/issues/164))
|
||||
- More graphite function definitions
|
||||
- Make "ms" axis format include hour, day, weeks, month and year ([Issue #149](https://github.com/grafana/grafana/issues/149))
|
||||
- Microsecond axis format ([Issue #146](https://github.com/grafana/grafana/issues/146))
|
||||
- Specify template parameters in URL ([Issue #123](https://github.com/grafana/grafana/issues/123))
|
||||
|
||||
### Fixes
|
||||
- Basic Auth fix ([Issue #152](https://github.com/grafana/grafana/issues/152))
|
||||
- Fix to annotations with graphite source & null values ([Issue #138](https://github.com/grafana/grafana/issues/138))
|
||||
|
||||
# 1.4.0 (2014-02-21)
|
||||
### New Features
|
||||
- #44 Annotations! Required a lot of work to get right. Read wiki article for more info. Supported annotations data sources are graphite metrics and graphite events. Support for more will be added in the future!
|
||||
- #35 Support for multiple graphite servers! (Read wiki article for more)
|
||||
- #116 Back to dashboard link in top menu to easily exist full screen / edit mode.
|
||||
- #114, #97 Legend values now use the same y axes formatter
|
||||
- #77 Improvements and polish to the light theme
|
||||
|
||||
### Changes
|
||||
- #98 Stack is no longer by default turned on in graph display settings.
|
||||
- Hide controls (Ctrl+h) now hides the sub menu row (where filtering, and annotations are). So if you had filtering enabled and hide controls enabled you will not see the filtering sub menu.
|
||||
|
||||
### Fixes:
|
||||
- #94 Fix for bug that caused dashboard settings to sometimes not contain timepicker tab.
|
||||
- #110 Graph with many many metrics caused legend to push down graph editor below screen. You can now scroll in edit mode & full screen mode for graphs with lots of series & legends.
|
||||
- #104 Improvement to graphite target editor, select wildcard now gives you a "select metric" link for the next node.
|
||||
- #105 Added zero as a possible node value in groupByAlias function
|
||||
|
||||
# 1.3.0 (2014-02-13)
|
||||
### New features or improvements
|
||||
- #86 Dashboard tags and search (see wiki article for details)
|
||||
- #54 Enhancement to filter / template. "Include All" improvement
|
||||
- #82 Dashboard search result sorted in alphabetical order
|
||||
|
||||
### Fixes
|
||||
- #91 Custom date selector is one day behind
|
||||
- #89 Filter / template does not work after switching dashboard
|
||||
- #88 Closed / Minimized row css bug
|
||||
- #85 Added all parameters to summarize function
|
||||
- #83 Stack as percent should now work a lot better!
|
||||
|
||||
# 1.2.0 (2014-02-10)
|
||||
### New features
|
||||
- #70 Grid Thresholds (warning and error regions or lines in graph)
|
||||
- #72 Added an example of a scripted dashboard and a short wiki article documenting scripted dashboards.
|
||||
|
||||
### Fixes
|
||||
- #81 Grid min/max values are ignored bug
|
||||
- #80 "stacked as percent" graphs should always use "max" value of 100 bug
|
||||
- #73 Left Y format change did not work
|
||||
- #42 Fixes to grid min/max auto scaling
|
||||
- #69 Fixes to lexer/parser for metrics segments like "10-20".
|
||||
- #67 Allow decimal input for scale function
|
||||
- #68 Bug when trying to open dashboard while in edit mode
|
||||
|
||||
# 1.1.0 (2014-02-06)
|
||||
### New features:
|
||||
|
||||
- #22 Support for native graphite png renderer, does not support click and select zoom yet
|
||||
- #60 Support for legend values (cactiStyle, min, max, current, total, avg). The options for these are found in the new "Axes & Grid" tab for now.
|
||||
- #62 There is now a "New" button in the search/open dashboard view to quickly open a clean empty dashboard.
|
||||
- #55 Basic auth is now supported for elastic search as well
|
||||
- some new function definitions added (will focus more on this for next release).
|
||||
|
||||
### Fixes
|
||||
- #45 zero values from graphite was handled as null.
|
||||
- #63 Kibana / Grafana on same host would use same localStorage keys, now fixed
|
||||
- #46 Impossible to edit graph without a name fixed.
|
||||
- #24 fix for dashboard search when elastic search is configured to disable _all field.
|
||||
- #38 Improvement to lexer / parser to support pure numeric literals in metric segments
|
||||
|
||||
Thanks to everyone who contributed fixes and provided feedback :+1:
|
||||
|
||||
# 1.0.4 (2014-01-24)
|
||||
- [Issue #28](https://github.com/grafana/grafana/issues/28) - Relative time range caused 500 graphite error in some cases (thx rsommer for the fix)
|
||||
|
||||
# 1.0.3 (2014-01-23)
|
||||
- #9 Add Y-axis format for milliseconds
|
||||
- #16 Add support for Basic Auth (use http://username:password@yourgraphitedomain.com)
|
||||
- #13 Relative time ranges now uses relative time ranges when issuing graphite query
|
||||
|
||||
# 1.0.2 (2014-01-21)
|
||||
- [Issue #12](https://github.com/grafana/grafana/issues/12), should now work ok without ElasticSearch
|
||||
|
||||
# 1.0.1 (2014-01-21)
|
||||
- Resize fix
|
||||
- Improvements to drag & drop
|
||||
- Added a few graphite function definitions
|
||||
- Fixed duplicate panel bug
|
||||
- Updated default dashboard with welcome message and randomWalk graph
|
||||
|
||||
# 1.0.0 (2014-01-19)
|
||||
|
||||
First public release
|
||||
372
Godeps/Godeps.json
generated
Normal file
372
Godeps/Godeps.json
generated
Normal file
@@ -0,0 +1,372 @@
|
||||
{
|
||||
"ImportPath": "github.com/grafana/grafana",
|
||||
"GoVersion": "go1.5.1",
|
||||
"GodepVersion": "v60",
|
||||
"Packages": [
|
||||
"./pkg/..."
|
||||
],
|
||||
"Deps": [
|
||||
{
|
||||
"ImportPath": "github.com/BurntSushi/toml",
|
||||
"Comment": "v0.1.0-21-g056c9bc",
|
||||
"Rev": "056c9bc7be7190eaa7715723883caffa5f8fa3e4"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/Unknwon/com",
|
||||
"Rev": "d9bcf409c8a368d06c9b347705c381e7c12d54df"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/awserr",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/awsutil",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/client",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/client/metadata",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/corehandlers",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/credentials/ec2rolecreds",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/defaults",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/ec2metadata",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/request",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/aws/session",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/endpoints",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/ec2query",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/query/queryutil",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/rest",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/signer/v4",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/private/waiter",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/service/cloudwatch",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/service/ec2",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/aws/aws-sdk-go/service/sts",
|
||||
"Comment": "v1.0.0",
|
||||
"Rev": "abb928e07c4108683d6b4d0b6ca08fe6bc0eee5f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/bmizerany/assert",
|
||||
"Comment": "release.r60-6-ge17e998",
|
||||
"Rev": "e17e99893cb6509f428e1728281c2ad60a6b31e3"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/bradfitz/gomemcache/memcache",
|
||||
"Comment": "release.r60-40-g72a6864",
|
||||
"Rev": "72a68649ba712ee7c4b5b4a943a626bcd7d90eb8"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/codegangsta/cli",
|
||||
"Comment": "1.2.0-187-gc31a797",
|
||||
"Rev": "c31a7975863e7810c92e2e288a9ab074f9a88f29"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/davecgh/go-spew/spew",
|
||||
"Rev": "2df174808ee097f90d259e432cc04442cf60be21"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/fatih/color",
|
||||
"Comment": "v0.1-16-g4f7bcef",
|
||||
"Rev": "4f7bcef27eec7925456d0c30c5e7b0408b3339be"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/franela/goreq",
|
||||
"Rev": "3ddeded65be21dacb5a2e2d0b95af9ff6862a2b5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-ini/ini",
|
||||
"Comment": "v0-48-g060d7da",
|
||||
"Rev": "060d7da055ba6ec5ea7a31f116332fe5efa04ce0"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-ldap/ldap",
|
||||
"Comment": "v2.2.1",
|
||||
"Rev": "07a7330929b9ee80495c88a4439657d89c7dbd87"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-macaron/binding",
|
||||
"Rev": "2502aaf4bce3a4e6451b4610847bfb8dffdb6266"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-macaron/gzip",
|
||||
"Rev": "4938e9be6b279d8426cb1c89a6bcf7af70b0c21d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-macaron/inject",
|
||||
"Rev": "c5ab7bf3a307593cd44cb272d1a5beea473dd072"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-macaron/session",
|
||||
"Rev": "66031fcb37a0fff002a1f028eb0b3a815c78306b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-macaron/session/memcache",
|
||||
"Rev": "66031fcb37a0fff002a1f028eb0b3a815c78306b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-macaron/session/mysql",
|
||||
"Rev": "66031fcb37a0fff002a1f028eb0b3a815c78306b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-macaron/session/postgres",
|
||||
"Rev": "66031fcb37a0fff002a1f028eb0b3a815c78306b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-macaron/session/redis",
|
||||
"Rev": "66031fcb37a0fff002a1f028eb0b3a815c78306b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-sql-driver/mysql",
|
||||
"Comment": "v1.2-171-g267b128",
|
||||
"Rev": "267b128680c46286b9ca13475c3cca5de8f79bd7"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-stack/stack",
|
||||
"Comment": "v1.5.2",
|
||||
"Rev": "100eb0c0a9c5b306ca2fb4f165df21d80ada4b82"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-xorm/core",
|
||||
"Comment": "v0.4.4-7-g9e608f7",
|
||||
"Rev": "9e608f7330b9d16fe2818cfe731128b3f156cb9a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/go-xorm/xorm",
|
||||
"Comment": "v0.4.4-44-gf561133",
|
||||
"Rev": "f56113384f2c63dfe4cd8e768e349f1c35122b58"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gorilla/websocket",
|
||||
"Rev": "c45a635370221f34fea2d5163fd156fcb4e38e8a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/gosimple/slug",
|
||||
"Rev": "8d258463b4459f161f51d6a357edacd3eef9d663"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/hashicorp/go-version",
|
||||
"Rev": "7e3c02b30806fa5779d3bdfc152ce4c6f40e7b38"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/inconshreveable/log15",
|
||||
"Comment": "v2.3-61-g20bca5a",
|
||||
"Rev": "20bca5a7a57282e241fac83ec9ea42538027f1c1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/inconshreveable/log15/term",
|
||||
"Comment": "v2.3-61-g20bca5a",
|
||||
"Rev": "20bca5a7a57282e241fac83ec9ea42538027f1c1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/jmespath/go-jmespath",
|
||||
"Comment": "0.2.2",
|
||||
"Rev": "3433f3ea46d9f8019119e7dd41274e112a2359a9"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/jtolds/gls",
|
||||
"Rev": "f1ac7f4f24f50328e6bc838ca4437d1612a0243c"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/klauspost/compress/flate",
|
||||
"Rev": "7b02889a2005228347aef0e76beeaee564d82f8c"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/klauspost/compress/gzip",
|
||||
"Rev": "7b02889a2005228347aef0e76beeaee564d82f8c"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/klauspost/cpuid",
|
||||
"Rev": "349c675778172472f5e8f3a3e0fe187e302e5a10"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/klauspost/crc32",
|
||||
"Rev": "6834731faf32e62a2dd809d99fb24d1e4ae5a92d"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/kr/pretty",
|
||||
"Comment": "go.weekly.2011-12-22-27-ge6ac2fc",
|
||||
"Rev": "e6ac2fc51e89a3249e82157fa0bb7a18ef9dd5bb"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/kr/text",
|
||||
"Rev": "bb797dc4fb8320488f47bf11de07a733d7233e1f"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/lib/pq",
|
||||
"Comment": "go1.0-cutoff-13-g19eeca3",
|
||||
"Rev": "19eeca3e30d2577b1761db471ec130810e67f532"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/lib/pq/oid",
|
||||
"Comment": "go1.0-cutoff-13-g19eeca3",
|
||||
"Rev": "19eeca3e30d2577b1761db471ec130810e67f532"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/mattn/go-colorable",
|
||||
"Rev": "9cbef7c35391cca05f15f8181dc0b18bc9736dbb"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/mattn/go-isatty",
|
||||
"Rev": "56b76bdf51f7708750eac80fa38b952bb9f32639"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/mattn/go-sqlite3",
|
||||
"Comment": "v1.1.0-67-g7204887",
|
||||
"Rev": "7204887cf3a42df1cfaa5505dc3a3427f6dded8b"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/rainycape/unidecode",
|
||||
"Rev": "836ef0a715aedf08a12d595ed73ec8ed5b288cac"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/smartystreets/goconvey/convey",
|
||||
"Comment": "1.5.0-356-gfbc0a1c",
|
||||
"Rev": "fbc0a1c888f9f96263f9a559d1769905245f1123"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/smartystreets/goconvey/convey/assertions",
|
||||
"Comment": "1.5.0-356-gfbc0a1c",
|
||||
"Rev": "fbc0a1c888f9f96263f9a559d1769905245f1123"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/smartystreets/goconvey/convey/assertions/oglematchers",
|
||||
"Comment": "1.5.0-356-gfbc0a1c",
|
||||
"Rev": "fbc0a1c888f9f96263f9a559d1769905245f1123"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/smartystreets/goconvey/convey/gotest",
|
||||
"Comment": "1.5.0-356-gfbc0a1c",
|
||||
"Rev": "fbc0a1c888f9f96263f9a559d1769905245f1123"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/smartystreets/goconvey/convey/reporting",
|
||||
"Comment": "1.5.0-356-gfbc0a1c",
|
||||
"Rev": "fbc0a1c888f9f96263f9a559d1769905245f1123"
|
||||
},
|
||||
{
|
||||
"ImportPath": "github.com/streadway/amqp",
|
||||
"Rev": "150b7f24d6ad507e6026c13d85ce1f1391ac7400"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/net/context",
|
||||
"Rev": "972f0c5fbe4ae29e666c3f78c3ed42ae7a448b0a"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/oauth2",
|
||||
"Rev": "c58fcf0ffc1c772aa2e1ee4894bc19f2649263b2"
|
||||
},
|
||||
{
|
||||
"ImportPath": "golang.org/x/sys/unix",
|
||||
"Rev": "7a56174f0086b32866ebd746a794417edbc678a1"
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/asn1-ber.v1",
|
||||
"Comment": "v1",
|
||||
"Rev": "9eae18c3681ae3d3c677ac2b80a8fe57de45fc09"
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/bufio.v1",
|
||||
"Comment": "v1",
|
||||
"Rev": "567b2bfa514e796916c4747494d6ff5132a1dfce"
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/ini.v1",
|
||||
"Comment": "v0-16-g1772191",
|
||||
"Rev": "177219109c97e7920c933e21c9b25f874357b237"
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/macaron.v1",
|
||||
"Rev": "1c6dd87797ae9319b4658cbd48d1d0420b279fd5"
|
||||
},
|
||||
{
|
||||
"ImportPath": "gopkg.in/redis.v2",
|
||||
"Comment": "v2.3.2",
|
||||
"Rev": "e6179049628164864e6e84e973cfb56335748dea"
|
||||
}
|
||||
]
|
||||
}
|
||||
5
Godeps/Readme
generated
Normal file
5
Godeps/Readme
generated
Normal file
@@ -0,0 +1,5 @@
|
||||
This directory tree is generated automatically by godep.
|
||||
|
||||
Please do not edit.
|
||||
|
||||
See https://github.com/tools/godep for more information.
|
||||
2
Godeps/_workspace/.gitignore
generated
vendored
Normal file
2
Godeps/_workspace/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
/pkg
|
||||
/bin
|
||||
5
Godeps/_workspace/src/github.com/BurntSushi/toml/.gitignore
generated
vendored
Normal file
5
Godeps/_workspace/src/github.com/BurntSushi/toml/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
TAGS
|
||||
tags
|
||||
.*.swp
|
||||
tomlcheck/tomlcheck
|
||||
toml.test
|
||||
12
Godeps/_workspace/src/github.com/BurntSushi/toml/.travis.yml
generated
vendored
Normal file
12
Godeps/_workspace/src/github.com/BurntSushi/toml/.travis.yml
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
language: go
|
||||
go:
|
||||
- 1.1
|
||||
- 1.2
|
||||
- tip
|
||||
install:
|
||||
- go install ./...
|
||||
- go get github.com/BurntSushi/toml-test
|
||||
script:
|
||||
- export PATH="$PATH:$HOME/gopath/bin"
|
||||
- make test
|
||||
|
||||
3
Godeps/_workspace/src/github.com/BurntSushi/toml/COMPATIBLE
generated
vendored
Normal file
3
Godeps/_workspace/src/github.com/BurntSushi/toml/COMPATIBLE
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
Compatible with TOML version
|
||||
[v0.2.0](https://github.com/mojombo/toml/blob/master/versions/toml-v0.2.0.md)
|
||||
|
||||
14
Godeps/_workspace/src/github.com/BurntSushi/toml/COPYING
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/BurntSushi/toml/COPYING
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
||||
19
Godeps/_workspace/src/github.com/BurntSushi/toml/Makefile
generated
vendored
Normal file
19
Godeps/_workspace/src/github.com/BurntSushi/toml/Makefile
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
install:
|
||||
go install ./...
|
||||
|
||||
test: install
|
||||
go test -v
|
||||
toml-test toml-test-decoder
|
||||
toml-test -encoder toml-test-encoder
|
||||
|
||||
fmt:
|
||||
gofmt -w *.go */*.go
|
||||
colcheck *.go */*.go
|
||||
|
||||
tags:
|
||||
find ./ -name '*.go' -print0 | xargs -0 gotags > TAGS
|
||||
|
||||
push:
|
||||
git push origin master
|
||||
git push github master
|
||||
|
||||
220
Godeps/_workspace/src/github.com/BurntSushi/toml/README.md
generated
vendored
Normal file
220
Godeps/_workspace/src/github.com/BurntSushi/toml/README.md
generated
vendored
Normal file
@@ -0,0 +1,220 @@
|
||||
## TOML parser and encoder for Go with reflection
|
||||
|
||||
TOML stands for Tom's Obvious, Minimal Language. This Go package provides a
|
||||
reflection interface similar to Go's standard library `json` and `xml`
|
||||
packages. This package also supports the `encoding.TextUnmarshaler` and
|
||||
`encoding.TextMarshaler` interfaces so that you can define custom data
|
||||
representations. (There is an example of this below.)
|
||||
|
||||
Spec: https://github.com/mojombo/toml
|
||||
|
||||
Compatible with TOML version
|
||||
[v0.2.0](https://github.com/toml-lang/toml/blob/master/versions/en/toml-v0.2.0.md)
|
||||
|
||||
Documentation: http://godoc.org/github.com/BurntSushi/toml
|
||||
|
||||
Installation:
|
||||
|
||||
```bash
|
||||
go get github.com/BurntSushi/toml
|
||||
```
|
||||
|
||||
Try the toml validator:
|
||||
|
||||
```bash
|
||||
go get github.com/BurntSushi/toml/cmd/tomlv
|
||||
tomlv some-toml-file.toml
|
||||
```
|
||||
|
||||
[](https://travis-ci.org/BurntSushi/toml)
|
||||
|
||||
|
||||
### Testing
|
||||
|
||||
This package passes all tests in
|
||||
[toml-test](https://github.com/BurntSushi/toml-test) for both the decoder
|
||||
and the encoder.
|
||||
|
||||
### Examples
|
||||
|
||||
This package works similarly to how the Go standard library handles `XML`
|
||||
and `JSON`. Namely, data is loaded into Go values via reflection.
|
||||
|
||||
For the simplest example, consider some TOML file as just a list of keys
|
||||
and values:
|
||||
|
||||
```toml
|
||||
Age = 25
|
||||
Cats = [ "Cauchy", "Plato" ]
|
||||
Pi = 3.14
|
||||
Perfection = [ 6, 28, 496, 8128 ]
|
||||
DOB = 1987-07-05T05:45:00Z
|
||||
```
|
||||
|
||||
Which could be defined in Go as:
|
||||
|
||||
```go
|
||||
type Config struct {
|
||||
Age int
|
||||
Cats []string
|
||||
Pi float64
|
||||
Perfection []int
|
||||
DOB time.Time // requires `import time`
|
||||
}
|
||||
```
|
||||
|
||||
And then decoded with:
|
||||
|
||||
```go
|
||||
var conf Config
|
||||
if _, err := toml.Decode(tomlData, &conf); err != nil {
|
||||
// handle error
|
||||
}
|
||||
```
|
||||
|
||||
You can also use struct tags if your struct field name doesn't map to a TOML
|
||||
key value directly:
|
||||
|
||||
```toml
|
||||
some_key_NAME = "wat"
|
||||
```
|
||||
|
||||
```go
|
||||
type TOML struct {
|
||||
ObscureKey string `toml:"some_key_NAME"`
|
||||
}
|
||||
```
|
||||
|
||||
### Using the `encoding.TextUnmarshaler` interface
|
||||
|
||||
Here's an example that automatically parses duration strings into
|
||||
`time.Duration` values:
|
||||
|
||||
```toml
|
||||
[[song]]
|
||||
name = "Thunder Road"
|
||||
duration = "4m49s"
|
||||
|
||||
[[song]]
|
||||
name = "Stairway to Heaven"
|
||||
duration = "8m03s"
|
||||
```
|
||||
|
||||
Which can be decoded with:
|
||||
|
||||
```go
|
||||
type song struct {
|
||||
Name string
|
||||
Duration duration
|
||||
}
|
||||
type songs struct {
|
||||
Song []song
|
||||
}
|
||||
var favorites songs
|
||||
if _, err := toml.Decode(blob, &favorites); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, s := range favorites.Song {
|
||||
fmt.Printf("%s (%s)\n", s.Name, s.Duration)
|
||||
}
|
||||
```
|
||||
|
||||
And you'll also need a `duration` type that satisfies the
|
||||
`encoding.TextUnmarshaler` interface:
|
||||
|
||||
```go
|
||||
type duration struct {
|
||||
time.Duration
|
||||
}
|
||||
|
||||
func (d *duration) UnmarshalText(text []byte) error {
|
||||
var err error
|
||||
d.Duration, err = time.ParseDuration(string(text))
|
||||
return err
|
||||
}
|
||||
```
|
||||
|
||||
### More complex usage
|
||||
|
||||
Here's an example of how to load the example from the official spec page:
|
||||
|
||||
```toml
|
||||
# This is a TOML document. Boom.
|
||||
|
||||
title = "TOML Example"
|
||||
|
||||
[owner]
|
||||
name = "Tom Preston-Werner"
|
||||
organization = "GitHub"
|
||||
bio = "GitHub Cofounder & CEO\nLikes tater tots and beer."
|
||||
dob = 1979-05-27T07:32:00Z # First class dates? Why not?
|
||||
|
||||
[database]
|
||||
server = "192.168.1.1"
|
||||
ports = [ 8001, 8001, 8002 ]
|
||||
connection_max = 5000
|
||||
enabled = true
|
||||
|
||||
[servers]
|
||||
|
||||
# You can indent as you please. Tabs or spaces. TOML don't care.
|
||||
[servers.alpha]
|
||||
ip = "10.0.0.1"
|
||||
dc = "eqdc10"
|
||||
|
||||
[servers.beta]
|
||||
ip = "10.0.0.2"
|
||||
dc = "eqdc10"
|
||||
|
||||
[clients]
|
||||
data = [ ["gamma", "delta"], [1, 2] ] # just an update to make sure parsers support it
|
||||
|
||||
# Line breaks are OK when inside arrays
|
||||
hosts = [
|
||||
"alpha",
|
||||
"omega"
|
||||
]
|
||||
```
|
||||
|
||||
And the corresponding Go types are:
|
||||
|
||||
```go
|
||||
type tomlConfig struct {
|
||||
Title string
|
||||
Owner ownerInfo
|
||||
DB database `toml:"database"`
|
||||
Servers map[string]server
|
||||
Clients clients
|
||||
}
|
||||
|
||||
type ownerInfo struct {
|
||||
Name string
|
||||
Org string `toml:"organization"`
|
||||
Bio string
|
||||
DOB time.Time
|
||||
}
|
||||
|
||||
type database struct {
|
||||
Server string
|
||||
Ports []int
|
||||
ConnMax int `toml:"connection_max"`
|
||||
Enabled bool
|
||||
}
|
||||
|
||||
type server struct {
|
||||
IP string
|
||||
DC string
|
||||
}
|
||||
|
||||
type clients struct {
|
||||
Data [][]interface{}
|
||||
Hosts []string
|
||||
}
|
||||
```
|
||||
|
||||
Note that a case insensitive match will be tried if an exact match can't be
|
||||
found.
|
||||
|
||||
A working example of the above can be found in `_examples/example.{go,toml}`.
|
||||
|
||||
14
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/COPYING
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
||||
14
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/README.md
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/README.md
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# Implements the TOML test suite interface
|
||||
|
||||
This is an implementation of the interface expected by
|
||||
[toml-test](https://github.com/BurntSushi/toml-test) for my
|
||||
[toml parser written in Go](https://github.com/BurntSushi/toml).
|
||||
In particular, it maps TOML data on `stdin` to a JSON format on `stdout`.
|
||||
|
||||
|
||||
Compatible with TOML version
|
||||
[v0.2.0](https://github.com/mojombo/toml/blob/master/versions/toml-v0.2.0.md)
|
||||
|
||||
Compatible with `toml-test` version
|
||||
[v0.2.0](https://github.com/BurntSushi/toml-test/tree/v0.2.0)
|
||||
|
||||
90
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/main.go
generated
vendored
Normal file
90
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-decoder/main.go
generated
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
// Command toml-test-decoder satisfies the toml-test interface for testing
|
||||
// TOML decoders. Namely, it accepts TOML on stdin and outputs JSON on stdout.
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"time"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
func init() {
|
||||
log.SetFlags(0)
|
||||
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func usage() {
|
||||
log.Printf("Usage: %s < toml-file\n", path.Base(os.Args[0]))
|
||||
flag.PrintDefaults()
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
if flag.NArg() != 0 {
|
||||
flag.Usage()
|
||||
}
|
||||
|
||||
var tmp interface{}
|
||||
if _, err := toml.DecodeReader(os.Stdin, &tmp); err != nil {
|
||||
log.Fatalf("Error decoding TOML: %s", err)
|
||||
}
|
||||
|
||||
typedTmp := translate(tmp)
|
||||
if err := json.NewEncoder(os.Stdout).Encode(typedTmp); err != nil {
|
||||
log.Fatalf("Error encoding JSON: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func translate(tomlData interface{}) interface{} {
|
||||
switch orig := tomlData.(type) {
|
||||
case map[string]interface{}:
|
||||
typed := make(map[string]interface{}, len(orig))
|
||||
for k, v := range orig {
|
||||
typed[k] = translate(v)
|
||||
}
|
||||
return typed
|
||||
case []map[string]interface{}:
|
||||
typed := make([]map[string]interface{}, len(orig))
|
||||
for i, v := range orig {
|
||||
typed[i] = translate(v).(map[string]interface{})
|
||||
}
|
||||
return typed
|
||||
case []interface{}:
|
||||
typed := make([]interface{}, len(orig))
|
||||
for i, v := range orig {
|
||||
typed[i] = translate(v)
|
||||
}
|
||||
|
||||
// We don't really need to tag arrays, but let's be future proof.
|
||||
// (If TOML ever supports tuples, we'll need this.)
|
||||
return tag("array", typed)
|
||||
case time.Time:
|
||||
return tag("datetime", orig.Format("2006-01-02T15:04:05Z"))
|
||||
case bool:
|
||||
return tag("bool", fmt.Sprintf("%v", orig))
|
||||
case int64:
|
||||
return tag("integer", fmt.Sprintf("%d", orig))
|
||||
case float64:
|
||||
return tag("float", fmt.Sprintf("%v", orig))
|
||||
case string:
|
||||
return tag("string", orig)
|
||||
}
|
||||
|
||||
panic(fmt.Sprintf("Unknown type: %T", tomlData))
|
||||
}
|
||||
|
||||
func tag(typeName string, data interface{}) map[string]interface{} {
|
||||
return map[string]interface{}{
|
||||
"type": typeName,
|
||||
"value": data,
|
||||
}
|
||||
}
|
||||
14
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/COPYING
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
||||
14
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/README.md
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/README.md
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
# Implements the TOML test suite interface for TOML encoders
|
||||
|
||||
This is an implementation of the interface expected by
|
||||
[toml-test](https://github.com/BurntSushi/toml-test) for the
|
||||
[TOML encoder](https://github.com/BurntSushi/toml).
|
||||
In particular, it maps JSON data on `stdin` to a TOML format on `stdout`.
|
||||
|
||||
|
||||
Compatible with TOML version
|
||||
[v0.2.0](https://github.com/mojombo/toml/blob/master/versions/toml-v0.2.0.md)
|
||||
|
||||
Compatible with `toml-test` version
|
||||
[v0.2.0](https://github.com/BurntSushi/toml-test/tree/v0.2.0)
|
||||
|
||||
131
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/main.go
generated
vendored
Normal file
131
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/toml-test-encoder/main.go
generated
vendored
Normal file
@@ -0,0 +1,131 @@
|
||||
// Command toml-test-encoder satisfies the toml-test interface for testing
|
||||
// TOML encoders. Namely, it accepts JSON on stdin and outputs TOML on stdout.
|
||||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
func init() {
|
||||
log.SetFlags(0)
|
||||
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func usage() {
|
||||
log.Printf("Usage: %s < json-file\n", path.Base(os.Args[0]))
|
||||
flag.PrintDefaults()
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
if flag.NArg() != 0 {
|
||||
flag.Usage()
|
||||
}
|
||||
|
||||
var tmp interface{}
|
||||
if err := json.NewDecoder(os.Stdin).Decode(&tmp); err != nil {
|
||||
log.Fatalf("Error decoding JSON: %s", err)
|
||||
}
|
||||
|
||||
tomlData := translate(tmp)
|
||||
if err := toml.NewEncoder(os.Stdout).Encode(tomlData); err != nil {
|
||||
log.Fatalf("Error encoding TOML: %s", err)
|
||||
}
|
||||
}
|
||||
|
||||
func translate(typedJson interface{}) interface{} {
|
||||
switch v := typedJson.(type) {
|
||||
case map[string]interface{}:
|
||||
if len(v) == 2 && in("type", v) && in("value", v) {
|
||||
return untag(v)
|
||||
}
|
||||
m := make(map[string]interface{}, len(v))
|
||||
for k, v2 := range v {
|
||||
m[k] = translate(v2)
|
||||
}
|
||||
return m
|
||||
case []interface{}:
|
||||
tabArray := make([]map[string]interface{}, len(v))
|
||||
for i := range v {
|
||||
if m, ok := translate(v[i]).(map[string]interface{}); ok {
|
||||
tabArray[i] = m
|
||||
} else {
|
||||
log.Fatalf("JSON arrays may only contain objects. This " +
|
||||
"corresponds to only tables being allowed in " +
|
||||
"TOML table arrays.")
|
||||
}
|
||||
}
|
||||
return tabArray
|
||||
}
|
||||
log.Fatalf("Unrecognized JSON format '%T'.", typedJson)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func untag(typed map[string]interface{}) interface{} {
|
||||
t := typed["type"].(string)
|
||||
v := typed["value"]
|
||||
switch t {
|
||||
case "string":
|
||||
return v.(string)
|
||||
case "integer":
|
||||
v := v.(string)
|
||||
n, err := strconv.Atoi(v)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not parse '%s' as integer: %s", v, err)
|
||||
}
|
||||
return n
|
||||
case "float":
|
||||
v := v.(string)
|
||||
f, err := strconv.ParseFloat(v, 64)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not parse '%s' as float64: %s", v, err)
|
||||
}
|
||||
return f
|
||||
case "datetime":
|
||||
v := v.(string)
|
||||
t, err := time.Parse("2006-01-02T15:04:05Z", v)
|
||||
if err != nil {
|
||||
log.Fatalf("Could not parse '%s' as a datetime: %s", v, err)
|
||||
}
|
||||
return t
|
||||
case "bool":
|
||||
v := v.(string)
|
||||
switch v {
|
||||
case "true":
|
||||
return true
|
||||
case "false":
|
||||
return false
|
||||
}
|
||||
log.Fatalf("Could not parse '%s' as a boolean.", v)
|
||||
case "array":
|
||||
v := v.([]interface{})
|
||||
array := make([]interface{}, len(v))
|
||||
for i := range v {
|
||||
if m, ok := v[i].(map[string]interface{}); ok {
|
||||
array[i] = untag(m)
|
||||
} else {
|
||||
log.Fatalf("Arrays may only contain other arrays or "+
|
||||
"primitive values, but found a '%T'.", m)
|
||||
}
|
||||
}
|
||||
return array
|
||||
}
|
||||
log.Fatalf("Unrecognized tag type '%s'.", t)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
func in(key string, m map[string]interface{}) bool {
|
||||
_, ok := m[key]
|
||||
return ok
|
||||
}
|
||||
14
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/COPYING
generated
vendored
Normal file
14
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/COPYING
generated
vendored
Normal file
@@ -0,0 +1,14 @@
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
||||
22
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/README.md
generated
vendored
Normal file
22
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/README.md
generated
vendored
Normal file
@@ -0,0 +1,22 @@
|
||||
# TOML Validator
|
||||
|
||||
If Go is installed, it's simple to try it out:
|
||||
|
||||
```bash
|
||||
go get github.com/BurntSushi/toml/cmd/tomlv
|
||||
tomlv some-toml-file.toml
|
||||
```
|
||||
|
||||
You can see the types of every key in a TOML file with:
|
||||
|
||||
```bash
|
||||
tomlv -types some-toml-file.toml
|
||||
```
|
||||
|
||||
At the moment, only one error message is reported at a time. Error messages
|
||||
include line numbers. No output means that the files given are valid TOML, or
|
||||
there is a bug in `tomlv`.
|
||||
|
||||
Compatible with TOML version
|
||||
[v0.1.0](https://github.com/mojombo/toml/blob/master/versions/toml-v0.1.0.md)
|
||||
|
||||
61
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/main.go
generated
vendored
Normal file
61
Godeps/_workspace/src/github.com/BurntSushi/toml/cmd/tomlv/main.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
// Command tomlv validates TOML documents and prints each key's type.
|
||||
package main
|
||||
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"text/tabwriter"
|
||||
|
||||
"github.com/BurntSushi/toml"
|
||||
)
|
||||
|
||||
var (
|
||||
flagTypes = false
|
||||
)
|
||||
|
||||
func init() {
|
||||
log.SetFlags(0)
|
||||
|
||||
flag.BoolVar(&flagTypes, "types", flagTypes,
|
||||
"When set, the types of every defined key will be shown.")
|
||||
|
||||
flag.Usage = usage
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
func usage() {
|
||||
log.Printf("Usage: %s toml-file [ toml-file ... ]\n",
|
||||
path.Base(os.Args[0]))
|
||||
flag.PrintDefaults()
|
||||
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
func main() {
|
||||
if flag.NArg() < 1 {
|
||||
flag.Usage()
|
||||
}
|
||||
for _, f := range flag.Args() {
|
||||
var tmp interface{}
|
||||
md, err := toml.DecodeFile(f, &tmp)
|
||||
if err != nil {
|
||||
log.Fatalf("Error in '%s': %s", f, err)
|
||||
}
|
||||
if flagTypes {
|
||||
printTypes(md)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printTypes(md toml.MetaData) {
|
||||
tabw := tabwriter.NewWriter(os.Stdout, 0, 0, 2, ' ', 0)
|
||||
for _, key := range md.Keys() {
|
||||
fmt.Fprintf(tabw, "%s%s\t%s\n",
|
||||
strings.Repeat(" ", len(key)-1), key, md.Type(key...))
|
||||
}
|
||||
tabw.Flush()
|
||||
}
|
||||
492
Godeps/_workspace/src/github.com/BurntSushi/toml/decode.go
generated
vendored
Normal file
492
Godeps/_workspace/src/github.com/BurntSushi/toml/decode.go
generated
vendored
Normal file
@@ -0,0 +1,492 @@
|
||||
package toml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
var e = fmt.Errorf
|
||||
|
||||
// Unmarshaler is the interface implemented by objects that can unmarshal a
|
||||
// TOML description of themselves.
|
||||
type Unmarshaler interface {
|
||||
UnmarshalTOML(interface{}) error
|
||||
}
|
||||
|
||||
// Unmarshal decodes the contents of `p` in TOML format into a pointer `v`.
|
||||
func Unmarshal(p []byte, v interface{}) error {
|
||||
_, err := Decode(string(p), v)
|
||||
return err
|
||||
}
|
||||
|
||||
// Primitive is a TOML value that hasn't been decoded into a Go value.
|
||||
// When using the various `Decode*` functions, the type `Primitive` may
|
||||
// be given to any value, and its decoding will be delayed.
|
||||
//
|
||||
// A `Primitive` value can be decoded using the `PrimitiveDecode` function.
|
||||
//
|
||||
// The underlying representation of a `Primitive` value is subject to change.
|
||||
// Do not rely on it.
|
||||
//
|
||||
// N.B. Primitive values are still parsed, so using them will only avoid
|
||||
// the overhead of reflection. They can be useful when you don't know the
|
||||
// exact type of TOML data until run time.
|
||||
type Primitive struct {
|
||||
undecoded interface{}
|
||||
context Key
|
||||
}
|
||||
|
||||
// DEPRECATED!
|
||||
//
|
||||
// Use MetaData.PrimitiveDecode instead.
|
||||
func PrimitiveDecode(primValue Primitive, v interface{}) error {
|
||||
md := MetaData{decoded: make(map[string]bool)}
|
||||
return md.unify(primValue.undecoded, rvalue(v))
|
||||
}
|
||||
|
||||
// PrimitiveDecode is just like the other `Decode*` functions, except it
|
||||
// decodes a TOML value that has already been parsed. Valid primitive values
|
||||
// can *only* be obtained from values filled by the decoder functions,
|
||||
// including this method. (i.e., `v` may contain more `Primitive`
|
||||
// values.)
|
||||
//
|
||||
// Meta data for primitive values is included in the meta data returned by
|
||||
// the `Decode*` functions with one exception: keys returned by the Undecoded
|
||||
// method will only reflect keys that were decoded. Namely, any keys hidden
|
||||
// behind a Primitive will be considered undecoded. Executing this method will
|
||||
// update the undecoded keys in the meta data. (See the example.)
|
||||
func (md *MetaData) PrimitiveDecode(primValue Primitive, v interface{}) error {
|
||||
md.context = primValue.context
|
||||
defer func() { md.context = nil }()
|
||||
return md.unify(primValue.undecoded, rvalue(v))
|
||||
}
|
||||
|
||||
// Decode will decode the contents of `data` in TOML format into a pointer
|
||||
// `v`.
|
||||
//
|
||||
// TOML hashes correspond to Go structs or maps. (Dealer's choice. They can be
|
||||
// used interchangeably.)
|
||||
//
|
||||
// TOML arrays of tables correspond to either a slice of structs or a slice
|
||||
// of maps.
|
||||
//
|
||||
// TOML datetimes correspond to Go `time.Time` values.
|
||||
//
|
||||
// All other TOML types (float, string, int, bool and array) correspond
|
||||
// to the obvious Go types.
|
||||
//
|
||||
// An exception to the above rules is if a type implements the
|
||||
// encoding.TextUnmarshaler interface. In this case, any primitive TOML value
|
||||
// (floats, strings, integers, booleans and datetimes) will be converted to
|
||||
// a byte string and given to the value's UnmarshalText method. See the
|
||||
// Unmarshaler example for a demonstration with time duration strings.
|
||||
//
|
||||
// Key mapping
|
||||
//
|
||||
// TOML keys can map to either keys in a Go map or field names in a Go
|
||||
// struct. The special `toml` struct tag may be used to map TOML keys to
|
||||
// struct fields that don't match the key name exactly. (See the example.)
|
||||
// A case insensitive match to struct names will be tried if an exact match
|
||||
// can't be found.
|
||||
//
|
||||
// The mapping between TOML values and Go values is loose. That is, there
|
||||
// may exist TOML values that cannot be placed into your representation, and
|
||||
// there may be parts of your representation that do not correspond to
|
||||
// TOML values. This loose mapping can be made stricter by using the IsDefined
|
||||
// and/or Undecoded methods on the MetaData returned.
|
||||
//
|
||||
// This decoder will not handle cyclic types. If a cyclic type is passed,
|
||||
// `Decode` will not terminate.
|
||||
func Decode(data string, v interface{}) (MetaData, error) {
|
||||
p, err := parse(data)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
md := MetaData{
|
||||
p.mapping, p.types, p.ordered,
|
||||
make(map[string]bool, len(p.ordered)), nil,
|
||||
}
|
||||
return md, md.unify(p.mapping, rvalue(v))
|
||||
}
|
||||
|
||||
// DecodeFile is just like Decode, except it will automatically read the
|
||||
// contents of the file at `fpath` and decode it for you.
|
||||
func DecodeFile(fpath string, v interface{}) (MetaData, error) {
|
||||
bs, err := ioutil.ReadFile(fpath)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
return Decode(string(bs), v)
|
||||
}
|
||||
|
||||
// DecodeReader is just like Decode, except it will consume all bytes
|
||||
// from the reader and decode it for you.
|
||||
func DecodeReader(r io.Reader, v interface{}) (MetaData, error) {
|
||||
bs, err := ioutil.ReadAll(r)
|
||||
if err != nil {
|
||||
return MetaData{}, err
|
||||
}
|
||||
return Decode(string(bs), v)
|
||||
}
|
||||
|
||||
// unify performs a sort of type unification based on the structure of `rv`,
|
||||
// which is the client representation.
|
||||
//
|
||||
// Any type mismatch produces an error. Finding a type that we don't know
|
||||
// how to handle produces an unsupported type error.
|
||||
func (md *MetaData) unify(data interface{}, rv reflect.Value) error {
|
||||
|
||||
// Special case. Look for a `Primitive` value.
|
||||
if rv.Type() == reflect.TypeOf((*Primitive)(nil)).Elem() {
|
||||
// Save the undecoded data and the key context into the primitive
|
||||
// value.
|
||||
context := make(Key, len(md.context))
|
||||
copy(context, md.context)
|
||||
rv.Set(reflect.ValueOf(Primitive{
|
||||
undecoded: data,
|
||||
context: context,
|
||||
}))
|
||||
return nil
|
||||
}
|
||||
|
||||
// Special case. Unmarshaler Interface support.
|
||||
if rv.CanAddr() {
|
||||
if v, ok := rv.Addr().Interface().(Unmarshaler); ok {
|
||||
return v.UnmarshalTOML(data)
|
||||
}
|
||||
}
|
||||
|
||||
// Special case. Handle time.Time values specifically.
|
||||
// TODO: Remove this code when we decide to drop support for Go 1.1.
|
||||
// This isn't necessary in Go 1.2 because time.Time satisfies the encoding
|
||||
// interfaces.
|
||||
if rv.Type().AssignableTo(rvalue(time.Time{}).Type()) {
|
||||
return md.unifyDatetime(data, rv)
|
||||
}
|
||||
|
||||
// Special case. Look for a value satisfying the TextUnmarshaler interface.
|
||||
if v, ok := rv.Interface().(TextUnmarshaler); ok {
|
||||
return md.unifyText(data, v)
|
||||
}
|
||||
// BUG(burntsushi)
|
||||
// The behavior here is incorrect whenever a Go type satisfies the
|
||||
// encoding.TextUnmarshaler interface but also corresponds to a TOML
|
||||
// hash or array. In particular, the unmarshaler should only be applied
|
||||
// to primitive TOML values. But at this point, it will be applied to
|
||||
// all kinds of values and produce an incorrect error whenever those values
|
||||
// are hashes or arrays (including arrays of tables).
|
||||
|
||||
k := rv.Kind()
|
||||
|
||||
// laziness
|
||||
if k >= reflect.Int && k <= reflect.Uint64 {
|
||||
return md.unifyInt(data, rv)
|
||||
}
|
||||
switch k {
|
||||
case reflect.Ptr:
|
||||
elem := reflect.New(rv.Type().Elem())
|
||||
err := md.unify(data, reflect.Indirect(elem))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rv.Set(elem)
|
||||
return nil
|
||||
case reflect.Struct:
|
||||
return md.unifyStruct(data, rv)
|
||||
case reflect.Map:
|
||||
return md.unifyMap(data, rv)
|
||||
case reflect.Array:
|
||||
return md.unifyArray(data, rv)
|
||||
case reflect.Slice:
|
||||
return md.unifySlice(data, rv)
|
||||
case reflect.String:
|
||||
return md.unifyString(data, rv)
|
||||
case reflect.Bool:
|
||||
return md.unifyBool(data, rv)
|
||||
case reflect.Interface:
|
||||
// we only support empty interfaces.
|
||||
if rv.NumMethod() > 0 {
|
||||
return e("Unsupported type '%s'.", rv.Kind())
|
||||
}
|
||||
return md.unifyAnything(data, rv)
|
||||
case reflect.Float32:
|
||||
fallthrough
|
||||
case reflect.Float64:
|
||||
return md.unifyFloat64(data, rv)
|
||||
}
|
||||
return e("Unsupported type '%s'.", rv.Kind())
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyStruct(mapping interface{}, rv reflect.Value) error {
|
||||
tmap, ok := mapping.(map[string]interface{})
|
||||
if !ok {
|
||||
return mismatch(rv, "map", mapping)
|
||||
}
|
||||
|
||||
for key, datum := range tmap {
|
||||
var f *field
|
||||
fields := cachedTypeFields(rv.Type())
|
||||
for i := range fields {
|
||||
ff := &fields[i]
|
||||
if ff.name == key {
|
||||
f = ff
|
||||
break
|
||||
}
|
||||
if f == nil && strings.EqualFold(ff.name, key) {
|
||||
f = ff
|
||||
}
|
||||
}
|
||||
if f != nil {
|
||||
subv := rv
|
||||
for _, i := range f.index {
|
||||
subv = indirect(subv.Field(i))
|
||||
}
|
||||
if isUnifiable(subv) {
|
||||
md.decoded[md.context.add(key).String()] = true
|
||||
md.context = append(md.context, key)
|
||||
if err := md.unify(datum, subv); err != nil {
|
||||
return e("Type mismatch for '%s.%s': %s",
|
||||
rv.Type().String(), f.name, err)
|
||||
}
|
||||
md.context = md.context[0 : len(md.context)-1]
|
||||
} else if f.name != "" {
|
||||
// Bad user! No soup for you!
|
||||
return e("Field '%s.%s' is unexported, and therefore cannot "+
|
||||
"be loaded with reflection.", rv.Type().String(), f.name)
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyMap(mapping interface{}, rv reflect.Value) error {
|
||||
tmap, ok := mapping.(map[string]interface{})
|
||||
if !ok {
|
||||
return badtype("map", mapping)
|
||||
}
|
||||
if rv.IsNil() {
|
||||
rv.Set(reflect.MakeMap(rv.Type()))
|
||||
}
|
||||
for k, v := range tmap {
|
||||
md.decoded[md.context.add(k).String()] = true
|
||||
md.context = append(md.context, k)
|
||||
|
||||
rvkey := indirect(reflect.New(rv.Type().Key()))
|
||||
rvval := reflect.Indirect(reflect.New(rv.Type().Elem()))
|
||||
if err := md.unify(v, rvval); err != nil {
|
||||
return err
|
||||
}
|
||||
md.context = md.context[0 : len(md.context)-1]
|
||||
|
||||
rvkey.SetString(k)
|
||||
rv.SetMapIndex(rvkey, rvval)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyArray(data interface{}, rv reflect.Value) error {
|
||||
datav := reflect.ValueOf(data)
|
||||
if datav.Kind() != reflect.Slice {
|
||||
return badtype("slice", data)
|
||||
}
|
||||
sliceLen := datav.Len()
|
||||
if sliceLen != rv.Len() {
|
||||
return e("expected array length %d; got TOML array of length %d",
|
||||
rv.Len(), sliceLen)
|
||||
}
|
||||
return md.unifySliceArray(datav, rv)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifySlice(data interface{}, rv reflect.Value) error {
|
||||
datav := reflect.ValueOf(data)
|
||||
if datav.Kind() != reflect.Slice {
|
||||
return badtype("slice", data)
|
||||
}
|
||||
sliceLen := datav.Len()
|
||||
if rv.IsNil() {
|
||||
rv.Set(reflect.MakeSlice(rv.Type(), sliceLen, sliceLen))
|
||||
}
|
||||
return md.unifySliceArray(datav, rv)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifySliceArray(data, rv reflect.Value) error {
|
||||
sliceLen := data.Len()
|
||||
for i := 0; i < sliceLen; i++ {
|
||||
v := data.Index(i).Interface()
|
||||
sliceval := indirect(rv.Index(i))
|
||||
if err := md.unify(v, sliceval); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyDatetime(data interface{}, rv reflect.Value) error {
|
||||
if _, ok := data.(time.Time); ok {
|
||||
rv.Set(reflect.ValueOf(data))
|
||||
return nil
|
||||
}
|
||||
return badtype("time.Time", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyString(data interface{}, rv reflect.Value) error {
|
||||
if s, ok := data.(string); ok {
|
||||
rv.SetString(s)
|
||||
return nil
|
||||
}
|
||||
return badtype("string", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyFloat64(data interface{}, rv reflect.Value) error {
|
||||
if num, ok := data.(float64); ok {
|
||||
switch rv.Kind() {
|
||||
case reflect.Float32:
|
||||
fallthrough
|
||||
case reflect.Float64:
|
||||
rv.SetFloat(num)
|
||||
default:
|
||||
panic("bug")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return badtype("float", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyInt(data interface{}, rv reflect.Value) error {
|
||||
if num, ok := data.(int64); ok {
|
||||
if rv.Kind() >= reflect.Int && rv.Kind() <= reflect.Int64 {
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int64:
|
||||
// No bounds checking necessary.
|
||||
case reflect.Int8:
|
||||
if num < math.MinInt8 || num > math.MaxInt8 {
|
||||
return e("Value '%d' is out of range for int8.", num)
|
||||
}
|
||||
case reflect.Int16:
|
||||
if num < math.MinInt16 || num > math.MaxInt16 {
|
||||
return e("Value '%d' is out of range for int16.", num)
|
||||
}
|
||||
case reflect.Int32:
|
||||
if num < math.MinInt32 || num > math.MaxInt32 {
|
||||
return e("Value '%d' is out of range for int32.", num)
|
||||
}
|
||||
}
|
||||
rv.SetInt(num)
|
||||
} else if rv.Kind() >= reflect.Uint && rv.Kind() <= reflect.Uint64 {
|
||||
unum := uint64(num)
|
||||
switch rv.Kind() {
|
||||
case reflect.Uint, reflect.Uint64:
|
||||
// No bounds checking necessary.
|
||||
case reflect.Uint8:
|
||||
if num < 0 || unum > math.MaxUint8 {
|
||||
return e("Value '%d' is out of range for uint8.", num)
|
||||
}
|
||||
case reflect.Uint16:
|
||||
if num < 0 || unum > math.MaxUint16 {
|
||||
return e("Value '%d' is out of range for uint16.", num)
|
||||
}
|
||||
case reflect.Uint32:
|
||||
if num < 0 || unum > math.MaxUint32 {
|
||||
return e("Value '%d' is out of range for uint32.", num)
|
||||
}
|
||||
}
|
||||
rv.SetUint(unum)
|
||||
} else {
|
||||
panic("unreachable")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return badtype("integer", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyBool(data interface{}, rv reflect.Value) error {
|
||||
if b, ok := data.(bool); ok {
|
||||
rv.SetBool(b)
|
||||
return nil
|
||||
}
|
||||
return badtype("boolean", data)
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyAnything(data interface{}, rv reflect.Value) error {
|
||||
rv.Set(reflect.ValueOf(data))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (md *MetaData) unifyText(data interface{}, v TextUnmarshaler) error {
|
||||
var s string
|
||||
switch sdata := data.(type) {
|
||||
case TextMarshaler:
|
||||
text, err := sdata.MarshalText()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
s = string(text)
|
||||
case fmt.Stringer:
|
||||
s = sdata.String()
|
||||
case string:
|
||||
s = sdata
|
||||
case bool:
|
||||
s = fmt.Sprintf("%v", sdata)
|
||||
case int64:
|
||||
s = fmt.Sprintf("%d", sdata)
|
||||
case float64:
|
||||
s = fmt.Sprintf("%f", sdata)
|
||||
default:
|
||||
return badtype("primitive (string-like)", data)
|
||||
}
|
||||
if err := v.UnmarshalText([]byte(s)); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// rvalue returns a reflect.Value of `v`. All pointers are resolved.
|
||||
func rvalue(v interface{}) reflect.Value {
|
||||
return indirect(reflect.ValueOf(v))
|
||||
}
|
||||
|
||||
// indirect returns the value pointed to by a pointer.
|
||||
// Pointers are followed until the value is not a pointer.
|
||||
// New values are allocated for each nil pointer.
|
||||
//
|
||||
// An exception to this rule is if the value satisfies an interface of
|
||||
// interest to us (like encoding.TextUnmarshaler).
|
||||
func indirect(v reflect.Value) reflect.Value {
|
||||
if v.Kind() != reflect.Ptr {
|
||||
if v.CanAddr() {
|
||||
pv := v.Addr()
|
||||
if _, ok := pv.Interface().(TextUnmarshaler); ok {
|
||||
return pv
|
||||
}
|
||||
}
|
||||
return v
|
||||
}
|
||||
if v.IsNil() {
|
||||
v.Set(reflect.New(v.Type().Elem()))
|
||||
}
|
||||
return indirect(reflect.Indirect(v))
|
||||
}
|
||||
|
||||
func isUnifiable(rv reflect.Value) bool {
|
||||
if rv.CanSet() {
|
||||
return true
|
||||
}
|
||||
if _, ok := rv.Interface().(TextUnmarshaler); ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func badtype(expected string, data interface{}) error {
|
||||
return e("Expected %s but found '%T'.", expected, data)
|
||||
}
|
||||
|
||||
func mismatch(user reflect.Value, expected string, data interface{}) error {
|
||||
return e("Type mismatch for %s. Expected %s but found '%T'.",
|
||||
user.Type().String(), expected, data)
|
||||
}
|
||||
122
Godeps/_workspace/src/github.com/BurntSushi/toml/decode_meta.go
generated
vendored
Normal file
122
Godeps/_workspace/src/github.com/BurntSushi/toml/decode_meta.go
generated
vendored
Normal file
@@ -0,0 +1,122 @@
|
||||
package toml
|
||||
|
||||
import "strings"
|
||||
|
||||
// MetaData allows access to meta information about TOML data that may not
|
||||
// be inferrable via reflection. In particular, whether a key has been defined
|
||||
// and the TOML type of a key.
|
||||
type MetaData struct {
|
||||
mapping map[string]interface{}
|
||||
types map[string]tomlType
|
||||
keys []Key
|
||||
decoded map[string]bool
|
||||
context Key // Used only during decoding.
|
||||
}
|
||||
|
||||
// IsDefined returns true if the key given exists in the TOML data. The key
|
||||
// should be specified hierarchially. e.g.,
|
||||
//
|
||||
// // access the TOML key 'a.b.c'
|
||||
// IsDefined("a", "b", "c")
|
||||
//
|
||||
// IsDefined will return false if an empty key given. Keys are case sensitive.
|
||||
func (md *MetaData) IsDefined(key ...string) bool {
|
||||
if len(key) == 0 {
|
||||
return false
|
||||
}
|
||||
|
||||
var hash map[string]interface{}
|
||||
var ok bool
|
||||
var hashOrVal interface{} = md.mapping
|
||||
for _, k := range key {
|
||||
if hash, ok = hashOrVal.(map[string]interface{}); !ok {
|
||||
return false
|
||||
}
|
||||
if hashOrVal, ok = hash[k]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// Type returns a string representation of the type of the key specified.
|
||||
//
|
||||
// Type will return the empty string if given an empty key or a key that
|
||||
// does not exist. Keys are case sensitive.
|
||||
func (md *MetaData) Type(key ...string) string {
|
||||
fullkey := strings.Join(key, ".")
|
||||
if typ, ok := md.types[fullkey]; ok {
|
||||
return typ.typeString()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Key is the type of any TOML key, including key groups. Use (MetaData).Keys
|
||||
// to get values of this type.
|
||||
type Key []string
|
||||
|
||||
func (k Key) String() string {
|
||||
return strings.Join(k, ".")
|
||||
}
|
||||
|
||||
func (k Key) maybeQuotedAll() string {
|
||||
var ss []string
|
||||
for i := range k {
|
||||
ss = append(ss, k.maybeQuoted(i))
|
||||
}
|
||||
return strings.Join(ss, ".")
|
||||
}
|
||||
|
||||
func (k Key) maybeQuoted(i int) string {
|
||||
quote := false
|
||||
for _, c := range k[i] {
|
||||
if !isBareKeyChar(c) {
|
||||
quote = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if quote {
|
||||
return "\"" + strings.Replace(k[i], "\"", "\\\"", -1) + "\""
|
||||
} else {
|
||||
return k[i]
|
||||
}
|
||||
}
|
||||
|
||||
func (k Key) add(piece string) Key {
|
||||
newKey := make(Key, len(k)+1)
|
||||
copy(newKey, k)
|
||||
newKey[len(k)] = piece
|
||||
return newKey
|
||||
}
|
||||
|
||||
// Keys returns a slice of every key in the TOML data, including key groups.
|
||||
// Each key is itself a slice, where the first element is the top of the
|
||||
// hierarchy and the last is the most specific.
|
||||
//
|
||||
// The list will have the same order as the keys appeared in the TOML data.
|
||||
//
|
||||
// All keys returned are non-empty.
|
||||
func (md *MetaData) Keys() []Key {
|
||||
return md.keys
|
||||
}
|
||||
|
||||
// Undecoded returns all keys that have not been decoded in the order in which
|
||||
// they appear in the original TOML document.
|
||||
//
|
||||
// This includes keys that haven't been decoded because of a Primitive value.
|
||||
// Once the Primitive value is decoded, the keys will be considered decoded.
|
||||
//
|
||||
// Also note that decoding into an empty interface will result in no decoding,
|
||||
// and so no keys will be considered decoded.
|
||||
//
|
||||
// In this sense, the Undecoded keys correspond to keys in the TOML document
|
||||
// that do not have a concrete type in your representation.
|
||||
func (md *MetaData) Undecoded() []Key {
|
||||
undecoded := make([]Key, 0, len(md.keys))
|
||||
for _, key := range md.keys {
|
||||
if !md.decoded[key.String()] {
|
||||
undecoded = append(undecoded, key)
|
||||
}
|
||||
}
|
||||
return undecoded
|
||||
}
|
||||
950
Godeps/_workspace/src/github.com/BurntSushi/toml/decode_test.go
generated
vendored
Normal file
950
Godeps/_workspace/src/github.com/BurntSushi/toml/decode_test.go
generated
vendored
Normal file
@@ -0,0 +1,950 @@
|
||||
package toml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"reflect"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func init() {
|
||||
log.SetFlags(0)
|
||||
}
|
||||
|
||||
func TestDecodeSimple(t *testing.T) {
|
||||
var testSimple = `
|
||||
age = 250
|
||||
andrew = "gallant"
|
||||
kait = "brady"
|
||||
now = 1987-07-05T05:45:00Z
|
||||
yesOrNo = true
|
||||
pi = 3.14
|
||||
colors = [
|
||||
["red", "green", "blue"],
|
||||
["cyan", "magenta", "yellow", "black"],
|
||||
]
|
||||
|
||||
[My.Cats]
|
||||
plato = "cat 1"
|
||||
cauchy = "cat 2"
|
||||
`
|
||||
|
||||
type cats struct {
|
||||
Plato string
|
||||
Cauchy string
|
||||
}
|
||||
type simple struct {
|
||||
Age int
|
||||
Colors [][]string
|
||||
Pi float64
|
||||
YesOrNo bool
|
||||
Now time.Time
|
||||
Andrew string
|
||||
Kait string
|
||||
My map[string]cats
|
||||
}
|
||||
|
||||
var val simple
|
||||
_, err := Decode(testSimple, &val)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
now, err := time.Parse("2006-01-02T15:04:05", "1987-07-05T05:45:00")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var answer = simple{
|
||||
Age: 250,
|
||||
Andrew: "gallant",
|
||||
Kait: "brady",
|
||||
Now: now,
|
||||
YesOrNo: true,
|
||||
Pi: 3.14,
|
||||
Colors: [][]string{
|
||||
{"red", "green", "blue"},
|
||||
{"cyan", "magenta", "yellow", "black"},
|
||||
},
|
||||
My: map[string]cats{
|
||||
"Cats": cats{Plato: "cat 1", Cauchy: "cat 2"},
|
||||
},
|
||||
}
|
||||
if !reflect.DeepEqual(val, answer) {
|
||||
t.Fatalf("Expected\n-----\n%#v\n-----\nbut got\n-----\n%#v\n",
|
||||
answer, val)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeEmbedded(t *testing.T) {
|
||||
type Dog struct{ Name string }
|
||||
type Age int
|
||||
|
||||
tests := map[string]struct {
|
||||
input string
|
||||
decodeInto interface{}
|
||||
wantDecoded interface{}
|
||||
}{
|
||||
"embedded struct": {
|
||||
input: `Name = "milton"`,
|
||||
decodeInto: &struct{ Dog }{},
|
||||
wantDecoded: &struct{ Dog }{Dog{"milton"}},
|
||||
},
|
||||
"embedded non-nil pointer to struct": {
|
||||
input: `Name = "milton"`,
|
||||
decodeInto: &struct{ *Dog }{},
|
||||
wantDecoded: &struct{ *Dog }{&Dog{"milton"}},
|
||||
},
|
||||
"embedded nil pointer to struct": {
|
||||
input: ``,
|
||||
decodeInto: &struct{ *Dog }{},
|
||||
wantDecoded: &struct{ *Dog }{nil},
|
||||
},
|
||||
"embedded int": {
|
||||
input: `Age = -5`,
|
||||
decodeInto: &struct{ Age }{},
|
||||
wantDecoded: &struct{ Age }{-5},
|
||||
},
|
||||
}
|
||||
|
||||
for label, test := range tests {
|
||||
_, err := Decode(test.input, test.decodeInto)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(test.wantDecoded, test.decodeInto) {
|
||||
t.Errorf("%s: want decoded == %+v, got %+v",
|
||||
label, test.wantDecoded, test.decodeInto)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTableArrays(t *testing.T) {
|
||||
var tomlTableArrays = `
|
||||
[[albums]]
|
||||
name = "Born to Run"
|
||||
|
||||
[[albums.songs]]
|
||||
name = "Jungleland"
|
||||
|
||||
[[albums.songs]]
|
||||
name = "Meeting Across the River"
|
||||
|
||||
[[albums]]
|
||||
name = "Born in the USA"
|
||||
|
||||
[[albums.songs]]
|
||||
name = "Glory Days"
|
||||
|
||||
[[albums.songs]]
|
||||
name = "Dancing in the Dark"
|
||||
`
|
||||
|
||||
type Song struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
type Album struct {
|
||||
Name string
|
||||
Songs []Song
|
||||
}
|
||||
|
||||
type Music struct {
|
||||
Albums []Album
|
||||
}
|
||||
|
||||
expected := Music{[]Album{
|
||||
{"Born to Run", []Song{{"Jungleland"}, {"Meeting Across the River"}}},
|
||||
{"Born in the USA", []Song{{"Glory Days"}, {"Dancing in the Dark"}}},
|
||||
}}
|
||||
var got Music
|
||||
if _, err := Decode(tomlTableArrays, &got); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(expected, got) {
|
||||
t.Fatalf("\n%#v\n!=\n%#v\n", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
// Case insensitive matching tests.
|
||||
// A bit more comprehensive than needed given the current implementation,
|
||||
// but implementations change.
|
||||
// Probably still missing demonstrations of some ugly corner cases regarding
|
||||
// case insensitive matching and multiple fields.
|
||||
func TestCase(t *testing.T) {
|
||||
var caseToml = `
|
||||
tOpString = "string"
|
||||
tOpInt = 1
|
||||
tOpFloat = 1.1
|
||||
tOpBool = true
|
||||
tOpdate = 2006-01-02T15:04:05Z
|
||||
tOparray = [ "array" ]
|
||||
Match = "i should be in Match only"
|
||||
MatcH = "i should be in MatcH only"
|
||||
once = "just once"
|
||||
[nEst.eD]
|
||||
nEstedString = "another string"
|
||||
`
|
||||
|
||||
type InsensitiveEd struct {
|
||||
NestedString string
|
||||
}
|
||||
|
||||
type InsensitiveNest struct {
|
||||
Ed InsensitiveEd
|
||||
}
|
||||
|
||||
type Insensitive struct {
|
||||
TopString string
|
||||
TopInt int
|
||||
TopFloat float64
|
||||
TopBool bool
|
||||
TopDate time.Time
|
||||
TopArray []string
|
||||
Match string
|
||||
MatcH string
|
||||
Once string
|
||||
OncE string
|
||||
Nest InsensitiveNest
|
||||
}
|
||||
|
||||
tme, err := time.Parse(time.RFC3339, time.RFC3339[:len(time.RFC3339)-5])
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
expected := Insensitive{
|
||||
TopString: "string",
|
||||
TopInt: 1,
|
||||
TopFloat: 1.1,
|
||||
TopBool: true,
|
||||
TopDate: tme,
|
||||
TopArray: []string{"array"},
|
||||
MatcH: "i should be in MatcH only",
|
||||
Match: "i should be in Match only",
|
||||
Once: "just once",
|
||||
OncE: "",
|
||||
Nest: InsensitiveNest{
|
||||
Ed: InsensitiveEd{NestedString: "another string"},
|
||||
},
|
||||
}
|
||||
var got Insensitive
|
||||
if _, err := Decode(caseToml, &got); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !reflect.DeepEqual(expected, got) {
|
||||
t.Fatalf("\n%#v\n!=\n%#v\n", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func TestPointers(t *testing.T) {
|
||||
type Object struct {
|
||||
Type string
|
||||
Description string
|
||||
}
|
||||
|
||||
type Dict struct {
|
||||
NamedObject map[string]*Object
|
||||
BaseObject *Object
|
||||
Strptr *string
|
||||
Strptrs []*string
|
||||
}
|
||||
s1, s2, s3 := "blah", "abc", "def"
|
||||
expected := &Dict{
|
||||
Strptr: &s1,
|
||||
Strptrs: []*string{&s2, &s3},
|
||||
NamedObject: map[string]*Object{
|
||||
"foo": {"FOO", "fooooo!!!"},
|
||||
"bar": {"BAR", "ba-ba-ba-ba-barrrr!!!"},
|
||||
},
|
||||
BaseObject: &Object{"BASE", "da base"},
|
||||
}
|
||||
|
||||
ex1 := `
|
||||
Strptr = "blah"
|
||||
Strptrs = ["abc", "def"]
|
||||
|
||||
[NamedObject.foo]
|
||||
Type = "FOO"
|
||||
Description = "fooooo!!!"
|
||||
|
||||
[NamedObject.bar]
|
||||
Type = "BAR"
|
||||
Description = "ba-ba-ba-ba-barrrr!!!"
|
||||
|
||||
[BaseObject]
|
||||
Type = "BASE"
|
||||
Description = "da base"
|
||||
`
|
||||
dict := new(Dict)
|
||||
_, err := Decode(ex1, dict)
|
||||
if err != nil {
|
||||
t.Errorf("Decode error: %v", err)
|
||||
}
|
||||
if !reflect.DeepEqual(expected, dict) {
|
||||
t.Fatalf("\n%#v\n!=\n%#v\n", expected, dict)
|
||||
}
|
||||
}
|
||||
|
||||
type sphere struct {
|
||||
Center [3]float64
|
||||
Radius float64
|
||||
}
|
||||
|
||||
func TestDecodeSimpleArray(t *testing.T) {
|
||||
var s1 sphere
|
||||
if _, err := Decode(`center = [0.0, 1.5, 0.0]`, &s1); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeArrayWrongSize(t *testing.T) {
|
||||
var s1 sphere
|
||||
if _, err := Decode(`center = [0.1, 2.3]`, &s1); err == nil {
|
||||
t.Fatal("Expected array type mismatch error")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeLargeIntoSmallInt(t *testing.T) {
|
||||
type table struct {
|
||||
Value int8
|
||||
}
|
||||
var tab table
|
||||
if _, err := Decode(`value = 500`, &tab); err == nil {
|
||||
t.Fatal("Expected integer out-of-bounds error.")
|
||||
}
|
||||
}
|
||||
|
||||
func TestDecodeSizedInts(t *testing.T) {
|
||||
type table struct {
|
||||
U8 uint8
|
||||
U16 uint16
|
||||
U32 uint32
|
||||
U64 uint64
|
||||
U uint
|
||||
I8 int8
|
||||
I16 int16
|
||||
I32 int32
|
||||
I64 int64
|
||||
I int
|
||||
}
|
||||
answer := table{1, 1, 1, 1, 1, -1, -1, -1, -1, -1}
|
||||
toml := `
|
||||
u8 = 1
|
||||
u16 = 1
|
||||
u32 = 1
|
||||
u64 = 1
|
||||
u = 1
|
||||
i8 = -1
|
||||
i16 = -1
|
||||
i32 = -1
|
||||
i64 = -1
|
||||
i = -1
|
||||
`
|
||||
var tab table
|
||||
if _, err := Decode(toml, &tab); err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
if answer != tab {
|
||||
t.Fatalf("Expected %#v but got %#v", answer, tab)
|
||||
}
|
||||
}
|
||||
|
||||
func TestUnmarshaler(t *testing.T) {
|
||||
|
||||
var tomlBlob = `
|
||||
[dishes.hamboogie]
|
||||
name = "Hamboogie with fries"
|
||||
price = 10.99
|
||||
|
||||
[[dishes.hamboogie.ingredients]]
|
||||
name = "Bread Bun"
|
||||
|
||||
[[dishes.hamboogie.ingredients]]
|
||||
name = "Lettuce"
|
||||
|
||||
[[dishes.hamboogie.ingredients]]
|
||||
name = "Real Beef Patty"
|
||||
|
||||
[[dishes.hamboogie.ingredients]]
|
||||
name = "Tomato"
|
||||
|
||||
[dishes.eggsalad]
|
||||
name = "Egg Salad with rice"
|
||||
price = 3.99
|
||||
|
||||
[[dishes.eggsalad.ingredients]]
|
||||
name = "Egg"
|
||||
|
||||
[[dishes.eggsalad.ingredients]]
|
||||
name = "Mayo"
|
||||
|
||||
[[dishes.eggsalad.ingredients]]
|
||||
name = "Rice"
|
||||
`
|
||||
m := &menu{}
|
||||
if _, err := Decode(tomlBlob, m); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
if len(m.Dishes) != 2 {
|
||||
t.Log("two dishes should be loaded with UnmarshalTOML()")
|
||||
t.Errorf("expected %d but got %d", 2, len(m.Dishes))
|
||||
}
|
||||
|
||||
eggSalad := m.Dishes["eggsalad"]
|
||||
if _, ok := interface{}(eggSalad).(dish); !ok {
|
||||
t.Errorf("expected a dish")
|
||||
}
|
||||
|
||||
if eggSalad.Name != "Egg Salad with rice" {
|
||||
t.Errorf("expected the dish to be named 'Egg Salad with rice'")
|
||||
}
|
||||
|
||||
if len(eggSalad.Ingredients) != 3 {
|
||||
t.Log("dish should be loaded with UnmarshalTOML()")
|
||||
t.Errorf("expected %d but got %d", 3, len(eggSalad.Ingredients))
|
||||
}
|
||||
|
||||
found := false
|
||||
for _, i := range eggSalad.Ingredients {
|
||||
if i.Name == "Rice" {
|
||||
found = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !found {
|
||||
t.Error("Rice was not loaded in UnmarshalTOML()")
|
||||
}
|
||||
|
||||
// test on a value - must be passed as *
|
||||
o := menu{}
|
||||
if _, err := Decode(tomlBlob, &o); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
type menu struct {
|
||||
Dishes map[string]dish
|
||||
}
|
||||
|
||||
func (m *menu) UnmarshalTOML(p interface{}) error {
|
||||
m.Dishes = make(map[string]dish)
|
||||
data, _ := p.(map[string]interface{})
|
||||
dishes := data["dishes"].(map[string]interface{})
|
||||
for n, v := range dishes {
|
||||
if d, ok := v.(map[string]interface{}); ok {
|
||||
nd := dish{}
|
||||
nd.UnmarshalTOML(d)
|
||||
m.Dishes[n] = nd
|
||||
} else {
|
||||
return fmt.Errorf("not a dish")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type dish struct {
|
||||
Name string
|
||||
Price float32
|
||||
Ingredients []ingredient
|
||||
}
|
||||
|
||||
func (d *dish) UnmarshalTOML(p interface{}) error {
|
||||
data, _ := p.(map[string]interface{})
|
||||
d.Name, _ = data["name"].(string)
|
||||
d.Price, _ = data["price"].(float32)
|
||||
ingredients, _ := data["ingredients"].([]map[string]interface{})
|
||||
for _, e := range ingredients {
|
||||
n, _ := interface{}(e).(map[string]interface{})
|
||||
name, _ := n["name"].(string)
|
||||
i := ingredient{name}
|
||||
d.Ingredients = append(d.Ingredients, i)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type ingredient struct {
|
||||
Name string
|
||||
}
|
||||
|
||||
func ExampleMetaData_PrimitiveDecode() {
|
||||
var md MetaData
|
||||
var err error
|
||||
|
||||
var tomlBlob = `
|
||||
ranking = ["Springsteen", "J Geils"]
|
||||
|
||||
[bands.Springsteen]
|
||||
started = 1973
|
||||
albums = ["Greetings", "WIESS", "Born to Run", "Darkness"]
|
||||
|
||||
[bands."J Geils"]
|
||||
started = 1970
|
||||
albums = ["The J. Geils Band", "Full House", "Blow Your Face Out"]
|
||||
`
|
||||
|
||||
type band struct {
|
||||
Started int
|
||||
Albums []string
|
||||
}
|
||||
type classics struct {
|
||||
Ranking []string
|
||||
Bands map[string]Primitive
|
||||
}
|
||||
|
||||
// Do the initial decode. Reflection is delayed on Primitive values.
|
||||
var music classics
|
||||
if md, err = Decode(tomlBlob, &music); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// MetaData still includes information on Primitive values.
|
||||
fmt.Printf("Is `bands.Springsteen` defined? %v\n",
|
||||
md.IsDefined("bands", "Springsteen"))
|
||||
|
||||
// Decode primitive data into Go values.
|
||||
for _, artist := range music.Ranking {
|
||||
// A band is a primitive value, so we need to decode it to get a
|
||||
// real `band` value.
|
||||
primValue := music.Bands[artist]
|
||||
|
||||
var aBand band
|
||||
if err = md.PrimitiveDecode(primValue, &aBand); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Printf("%s started in %d.\n", artist, aBand.Started)
|
||||
}
|
||||
// Check to see if there were any fields left undecoded.
|
||||
// Note that this won't be empty before decoding the Primitive value!
|
||||
fmt.Printf("Undecoded: %q\n", md.Undecoded())
|
||||
|
||||
// Output:
|
||||
// Is `bands.Springsteen` defined? true
|
||||
// Springsteen started in 1973.
|
||||
// J Geils started in 1970.
|
||||
// Undecoded: []
|
||||
}
|
||||
|
||||
func ExampleDecode() {
|
||||
var tomlBlob = `
|
||||
# Some comments.
|
||||
[alpha]
|
||||
ip = "10.0.0.1"
|
||||
|
||||
[alpha.config]
|
||||
Ports = [ 8001, 8002 ]
|
||||
Location = "Toronto"
|
||||
Created = 1987-07-05T05:45:00Z
|
||||
|
||||
[beta]
|
||||
ip = "10.0.0.2"
|
||||
|
||||
[beta.config]
|
||||
Ports = [ 9001, 9002 ]
|
||||
Location = "New Jersey"
|
||||
Created = 1887-01-05T05:55:00Z
|
||||
`
|
||||
|
||||
type serverConfig struct {
|
||||
Ports []int
|
||||
Location string
|
||||
Created time.Time
|
||||
}
|
||||
|
||||
type server struct {
|
||||
IP string `toml:"ip"`
|
||||
Config serverConfig `toml:"config"`
|
||||
}
|
||||
|
||||
type servers map[string]server
|
||||
|
||||
var config servers
|
||||
if _, err := Decode(tomlBlob, &config); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
for _, name := range []string{"alpha", "beta"} {
|
||||
s := config[name]
|
||||
fmt.Printf("Server: %s (ip: %s) in %s created on %s\n",
|
||||
name, s.IP, s.Config.Location,
|
||||
s.Config.Created.Format("2006-01-02"))
|
||||
fmt.Printf("Ports: %v\n", s.Config.Ports)
|
||||
}
|
||||
|
||||
// Output:
|
||||
// Server: alpha (ip: 10.0.0.1) in Toronto created on 1987-07-05
|
||||
// Ports: [8001 8002]
|
||||
// Server: beta (ip: 10.0.0.2) in New Jersey created on 1887-01-05
|
||||
// Ports: [9001 9002]
|
||||
}
|
||||
|
||||
type duration struct {
|
||||
time.Duration
|
||||
}
|
||||
|
||||
func (d *duration) UnmarshalText(text []byte) error {
|
||||
var err error
|
||||
d.Duration, err = time.ParseDuration(string(text))
|
||||
return err
|
||||
}
|
||||
|
||||
// Example Unmarshaler shows how to decode TOML strings into your own
|
||||
// custom data type.
|
||||
func Example_unmarshaler() {
|
||||
blob := `
|
||||
[[song]]
|
||||
name = "Thunder Road"
|
||||
duration = "4m49s"
|
||||
|
||||
[[song]]
|
||||
name = "Stairway to Heaven"
|
||||
duration = "8m03s"
|
||||
`
|
||||
type song struct {
|
||||
Name string
|
||||
Duration duration
|
||||
}
|
||||
type songs struct {
|
||||
Song []song
|
||||
}
|
||||
var favorites songs
|
||||
if _, err := Decode(blob, &favorites); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Code to implement the TextUnmarshaler interface for `duration`:
|
||||
//
|
||||
// type duration struct {
|
||||
// time.Duration
|
||||
// }
|
||||
//
|
||||
// func (d *duration) UnmarshalText(text []byte) error {
|
||||
// var err error
|
||||
// d.Duration, err = time.ParseDuration(string(text))
|
||||
// return err
|
||||
// }
|
||||
|
||||
for _, s := range favorites.Song {
|
||||
fmt.Printf("%s (%s)\n", s.Name, s.Duration)
|
||||
}
|
||||
// Output:
|
||||
// Thunder Road (4m49s)
|
||||
// Stairway to Heaven (8m3s)
|
||||
}
|
||||
|
||||
// Example StrictDecoding shows how to detect whether there are keys in the
|
||||
// TOML document that weren't decoded into the value given. This is useful
|
||||
// for returning an error to the user if they've included extraneous fields
|
||||
// in their configuration.
|
||||
func Example_strictDecoding() {
|
||||
var blob = `
|
||||
key1 = "value1"
|
||||
key2 = "value2"
|
||||
key3 = "value3"
|
||||
`
|
||||
type config struct {
|
||||
Key1 string
|
||||
Key3 string
|
||||
}
|
||||
|
||||
var conf config
|
||||
md, err := Decode(blob, &conf)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Printf("Undecoded keys: %q\n", md.Undecoded())
|
||||
// Output:
|
||||
// Undecoded keys: ["key2"]
|
||||
}
|
||||
|
||||
// Example UnmarshalTOML shows how to implement a struct type that knows how to
|
||||
// unmarshal itself. The struct must take full responsibility for mapping the
|
||||
// values passed into the struct. The method may be used with interfaces in a
|
||||
// struct in cases where the actual type is not known until the data is
|
||||
// examined.
|
||||
func Example_unmarshalTOML() {
|
||||
|
||||
var blob = `
|
||||
[[parts]]
|
||||
type = "valve"
|
||||
id = "valve-1"
|
||||
size = 1.2
|
||||
rating = 4
|
||||
|
||||
[[parts]]
|
||||
type = "valve"
|
||||
id = "valve-2"
|
||||
size = 2.1
|
||||
rating = 5
|
||||
|
||||
[[parts]]
|
||||
type = "pipe"
|
||||
id = "pipe-1"
|
||||
length = 2.1
|
||||
diameter = 12
|
||||
|
||||
[[parts]]
|
||||
type = "cable"
|
||||
id = "cable-1"
|
||||
length = 12
|
||||
rating = 3.1
|
||||
`
|
||||
o := &order{}
|
||||
err := Unmarshal([]byte(blob), o)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
fmt.Println(len(o.parts))
|
||||
|
||||
for _, part := range o.parts {
|
||||
fmt.Println(part.Name())
|
||||
}
|
||||
|
||||
// Code to implement UmarshalJSON.
|
||||
|
||||
// type order struct {
|
||||
// // NOTE `order.parts` is a private slice of type `part` which is an
|
||||
// // interface and may only be loaded from toml using the
|
||||
// // UnmarshalTOML() method of the Umarshaler interface.
|
||||
// parts parts
|
||||
// }
|
||||
|
||||
// func (o *order) UnmarshalTOML(data interface{}) error {
|
||||
|
||||
// // NOTE the example below contains detailed type casting to show how
|
||||
// // the 'data' is retrieved. In operational use, a type cast wrapper
|
||||
// // may be prefered e.g.
|
||||
// //
|
||||
// // func AsMap(v interface{}) (map[string]interface{}, error) {
|
||||
// // return v.(map[string]interface{})
|
||||
// // }
|
||||
// //
|
||||
// // resulting in:
|
||||
// // d, _ := AsMap(data)
|
||||
// //
|
||||
|
||||
// d, _ := data.(map[string]interface{})
|
||||
// parts, _ := d["parts"].([]map[string]interface{})
|
||||
|
||||
// for _, p := range parts {
|
||||
|
||||
// typ, _ := p["type"].(string)
|
||||
// id, _ := p["id"].(string)
|
||||
|
||||
// // detect the type of part and handle each case
|
||||
// switch p["type"] {
|
||||
// case "valve":
|
||||
|
||||
// size := float32(p["size"].(float64))
|
||||
// rating := int(p["rating"].(int64))
|
||||
|
||||
// valve := &valve{
|
||||
// Type: typ,
|
||||
// ID: id,
|
||||
// Size: size,
|
||||
// Rating: rating,
|
||||
// }
|
||||
|
||||
// o.parts = append(o.parts, valve)
|
||||
|
||||
// case "pipe":
|
||||
|
||||
// length := float32(p["length"].(float64))
|
||||
// diameter := int(p["diameter"].(int64))
|
||||
|
||||
// pipe := &pipe{
|
||||
// Type: typ,
|
||||
// ID: id,
|
||||
// Length: length,
|
||||
// Diameter: diameter,
|
||||
// }
|
||||
|
||||
// o.parts = append(o.parts, pipe)
|
||||
|
||||
// case "cable":
|
||||
|
||||
// length := int(p["length"].(int64))
|
||||
// rating := float32(p["rating"].(float64))
|
||||
|
||||
// cable := &cable{
|
||||
// Type: typ,
|
||||
// ID: id,
|
||||
// Length: length,
|
||||
// Rating: rating,
|
||||
// }
|
||||
|
||||
// o.parts = append(o.parts, cable)
|
||||
|
||||
// }
|
||||
// }
|
||||
|
||||
// return nil
|
||||
// }
|
||||
|
||||
// type parts []part
|
||||
|
||||
// type part interface {
|
||||
// Name() string
|
||||
// }
|
||||
|
||||
// type valve struct {
|
||||
// Type string
|
||||
// ID string
|
||||
// Size float32
|
||||
// Rating int
|
||||
// }
|
||||
|
||||
// func (v *valve) Name() string {
|
||||
// return fmt.Sprintf("VALVE: %s", v.ID)
|
||||
// }
|
||||
|
||||
// type pipe struct {
|
||||
// Type string
|
||||
// ID string
|
||||
// Length float32
|
||||
// Diameter int
|
||||
// }
|
||||
|
||||
// func (p *pipe) Name() string {
|
||||
// return fmt.Sprintf("PIPE: %s", p.ID)
|
||||
// }
|
||||
|
||||
// type cable struct {
|
||||
// Type string
|
||||
// ID string
|
||||
// Length int
|
||||
// Rating float32
|
||||
// }
|
||||
|
||||
// func (c *cable) Name() string {
|
||||
// return fmt.Sprintf("CABLE: %s", c.ID)
|
||||
// }
|
||||
|
||||
// Output:
|
||||
// 4
|
||||
// VALVE: valve-1
|
||||
// VALVE: valve-2
|
||||
// PIPE: pipe-1
|
||||
// CABLE: cable-1
|
||||
|
||||
}
|
||||
|
||||
type order struct {
|
||||
// NOTE `order.parts` is a private slice of type `part` which is an
|
||||
// interface and may only be loaded from toml using the UnmarshalTOML()
|
||||
// method of the Umarshaler interface.
|
||||
parts parts
|
||||
}
|
||||
|
||||
func (o *order) UnmarshalTOML(data interface{}) error {
|
||||
|
||||
// NOTE the example below contains detailed type casting to show how
|
||||
// the 'data' is retrieved. In operational use, a type cast wrapper
|
||||
// may be prefered e.g.
|
||||
//
|
||||
// func AsMap(v interface{}) (map[string]interface{}, error) {
|
||||
// return v.(map[string]interface{})
|
||||
// }
|
||||
//
|
||||
// resulting in:
|
||||
// d, _ := AsMap(data)
|
||||
//
|
||||
|
||||
d, _ := data.(map[string]interface{})
|
||||
parts, _ := d["parts"].([]map[string]interface{})
|
||||
|
||||
for _, p := range parts {
|
||||
|
||||
typ, _ := p["type"].(string)
|
||||
id, _ := p["id"].(string)
|
||||
|
||||
// detect the type of part and handle each case
|
||||
switch p["type"] {
|
||||
case "valve":
|
||||
|
||||
size := float32(p["size"].(float64))
|
||||
rating := int(p["rating"].(int64))
|
||||
|
||||
valve := &valve{
|
||||
Type: typ,
|
||||
ID: id,
|
||||
Size: size,
|
||||
Rating: rating,
|
||||
}
|
||||
|
||||
o.parts = append(o.parts, valve)
|
||||
|
||||
case "pipe":
|
||||
|
||||
length := float32(p["length"].(float64))
|
||||
diameter := int(p["diameter"].(int64))
|
||||
|
||||
pipe := &pipe{
|
||||
Type: typ,
|
||||
ID: id,
|
||||
Length: length,
|
||||
Diameter: diameter,
|
||||
}
|
||||
|
||||
o.parts = append(o.parts, pipe)
|
||||
|
||||
case "cable":
|
||||
|
||||
length := int(p["length"].(int64))
|
||||
rating := float32(p["rating"].(float64))
|
||||
|
||||
cable := &cable{
|
||||
Type: typ,
|
||||
ID: id,
|
||||
Length: length,
|
||||
Rating: rating,
|
||||
}
|
||||
|
||||
o.parts = append(o.parts, cable)
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type parts []part
|
||||
|
||||
type part interface {
|
||||
Name() string
|
||||
}
|
||||
|
||||
type valve struct {
|
||||
Type string
|
||||
ID string
|
||||
Size float32
|
||||
Rating int
|
||||
}
|
||||
|
||||
func (v *valve) Name() string {
|
||||
return fmt.Sprintf("VALVE: %s", v.ID)
|
||||
}
|
||||
|
||||
type pipe struct {
|
||||
Type string
|
||||
ID string
|
||||
Length float32
|
||||
Diameter int
|
||||
}
|
||||
|
||||
func (p *pipe) Name() string {
|
||||
return fmt.Sprintf("PIPE: %s", p.ID)
|
||||
}
|
||||
|
||||
type cable struct {
|
||||
Type string
|
||||
ID string
|
||||
Length int
|
||||
Rating float32
|
||||
}
|
||||
|
||||
func (c *cable) Name() string {
|
||||
return fmt.Sprintf("CABLE: %s", c.ID)
|
||||
}
|
||||
27
Godeps/_workspace/src/github.com/BurntSushi/toml/doc.go
generated
vendored
Normal file
27
Godeps/_workspace/src/github.com/BurntSushi/toml/doc.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
Package toml provides facilities for decoding and encoding TOML configuration
|
||||
files via reflection. There is also support for delaying decoding with
|
||||
the Primitive type, and querying the set of keys in a TOML document with the
|
||||
MetaData type.
|
||||
|
||||
The specification implemented: https://github.com/mojombo/toml
|
||||
|
||||
The sub-command github.com/BurntSushi/toml/cmd/tomlv can be used to verify
|
||||
whether a file is a valid TOML document. It can also be used to print the
|
||||
type of each key in a TOML document.
|
||||
|
||||
Testing
|
||||
|
||||
There are two important types of tests used for this package. The first is
|
||||
contained inside '*_test.go' files and uses the standard Go unit testing
|
||||
framework. These tests are primarily devoted to holistically testing the
|
||||
decoder and encoder.
|
||||
|
||||
The second type of testing is used to verify the implementation's adherence
|
||||
to the TOML specification. These tests have been factored into their own
|
||||
project: https://github.com/BurntSushi/toml-test
|
||||
|
||||
The reason the tests are in a separate project is so that they can be used by
|
||||
any implementation of TOML. Namely, it is language agnostic.
|
||||
*/
|
||||
package toml
|
||||
551
Godeps/_workspace/src/github.com/BurntSushi/toml/encode.go
generated
vendored
Normal file
551
Godeps/_workspace/src/github.com/BurntSushi/toml/encode.go
generated
vendored
Normal file
@@ -0,0 +1,551 @@
|
||||
package toml
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
type tomlEncodeError struct{ error }
|
||||
|
||||
var (
|
||||
errArrayMixedElementTypes = errors.New(
|
||||
"can't encode array with mixed element types")
|
||||
errArrayNilElement = errors.New(
|
||||
"can't encode array with nil element")
|
||||
errNonString = errors.New(
|
||||
"can't encode a map with non-string key type")
|
||||
errAnonNonStruct = errors.New(
|
||||
"can't encode an anonymous field that is not a struct")
|
||||
errArrayNoTable = errors.New(
|
||||
"TOML array element can't contain a table")
|
||||
errNoKey = errors.New(
|
||||
"top-level values must be a Go map or struct")
|
||||
errAnything = errors.New("") // used in testing
|
||||
)
|
||||
|
||||
var quotedReplacer = strings.NewReplacer(
|
||||
"\t", "\\t",
|
||||
"\n", "\\n",
|
||||
"\r", "\\r",
|
||||
"\"", "\\\"",
|
||||
"\\", "\\\\",
|
||||
)
|
||||
|
||||
// Encoder controls the encoding of Go values to a TOML document to some
|
||||
// io.Writer.
|
||||
//
|
||||
// The indentation level can be controlled with the Indent field.
|
||||
type Encoder struct {
|
||||
// A single indentation level. By default it is two spaces.
|
||||
Indent string
|
||||
|
||||
// hasWritten is whether we have written any output to w yet.
|
||||
hasWritten bool
|
||||
w *bufio.Writer
|
||||
}
|
||||
|
||||
// NewEncoder returns a TOML encoder that encodes Go values to the io.Writer
|
||||
// given. By default, a single indentation level is 2 spaces.
|
||||
func NewEncoder(w io.Writer) *Encoder {
|
||||
return &Encoder{
|
||||
w: bufio.NewWriter(w),
|
||||
Indent: " ",
|
||||
}
|
||||
}
|
||||
|
||||
// Encode writes a TOML representation of the Go value to the underlying
|
||||
// io.Writer. If the value given cannot be encoded to a valid TOML document,
|
||||
// then an error is returned.
|
||||
//
|
||||
// The mapping between Go values and TOML values should be precisely the same
|
||||
// as for the Decode* functions. Similarly, the TextMarshaler interface is
|
||||
// supported by encoding the resulting bytes as strings. (If you want to write
|
||||
// arbitrary binary data then you will need to use something like base64 since
|
||||
// TOML does not have any binary types.)
|
||||
//
|
||||
// When encoding TOML hashes (i.e., Go maps or structs), keys without any
|
||||
// sub-hashes are encoded first.
|
||||
//
|
||||
// If a Go map is encoded, then its keys are sorted alphabetically for
|
||||
// deterministic output. More control over this behavior may be provided if
|
||||
// there is demand for it.
|
||||
//
|
||||
// Encoding Go values without a corresponding TOML representation---like map
|
||||
// types with non-string keys---will cause an error to be returned. Similarly
|
||||
// for mixed arrays/slices, arrays/slices with nil elements, embedded
|
||||
// non-struct types and nested slices containing maps or structs.
|
||||
// (e.g., [][]map[string]string is not allowed but []map[string]string is OK
|
||||
// and so is []map[string][]string.)
|
||||
func (enc *Encoder) Encode(v interface{}) error {
|
||||
rv := eindirect(reflect.ValueOf(v))
|
||||
if err := enc.safeEncode(Key([]string{}), rv); err != nil {
|
||||
return err
|
||||
}
|
||||
return enc.w.Flush()
|
||||
}
|
||||
|
||||
func (enc *Encoder) safeEncode(key Key, rv reflect.Value) (err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if terr, ok := r.(tomlEncodeError); ok {
|
||||
err = terr.error
|
||||
return
|
||||
}
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
enc.encode(key, rv)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (enc *Encoder) encode(key Key, rv reflect.Value) {
|
||||
// Special case. Time needs to be in ISO8601 format.
|
||||
// Special case. If we can marshal the type to text, then we used that.
|
||||
// Basically, this prevents the encoder for handling these types as
|
||||
// generic structs (or whatever the underlying type of a TextMarshaler is).
|
||||
switch rv.Interface().(type) {
|
||||
case time.Time, TextMarshaler:
|
||||
enc.keyEqElement(key, rv)
|
||||
return
|
||||
}
|
||||
|
||||
k := rv.Kind()
|
||||
switch k {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
|
||||
reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
|
||||
reflect.Uint64,
|
||||
reflect.Float32, reflect.Float64, reflect.String, reflect.Bool:
|
||||
enc.keyEqElement(key, rv)
|
||||
case reflect.Array, reflect.Slice:
|
||||
if typeEqual(tomlArrayHash, tomlTypeOfGo(rv)) {
|
||||
enc.eArrayOfTables(key, rv)
|
||||
} else {
|
||||
enc.keyEqElement(key, rv)
|
||||
}
|
||||
case reflect.Interface:
|
||||
if rv.IsNil() {
|
||||
return
|
||||
}
|
||||
enc.encode(key, rv.Elem())
|
||||
case reflect.Map:
|
||||
if rv.IsNil() {
|
||||
return
|
||||
}
|
||||
enc.eTable(key, rv)
|
||||
case reflect.Ptr:
|
||||
if rv.IsNil() {
|
||||
return
|
||||
}
|
||||
enc.encode(key, rv.Elem())
|
||||
case reflect.Struct:
|
||||
enc.eTable(key, rv)
|
||||
default:
|
||||
panic(e("Unsupported type for key '%s': %s", key, k))
|
||||
}
|
||||
}
|
||||
|
||||
// eElement encodes any value that can be an array element (primitives and
|
||||
// arrays).
|
||||
func (enc *Encoder) eElement(rv reflect.Value) {
|
||||
switch v := rv.Interface().(type) {
|
||||
case time.Time:
|
||||
// Special case time.Time as a primitive. Has to come before
|
||||
// TextMarshaler below because time.Time implements
|
||||
// encoding.TextMarshaler, but we need to always use UTC.
|
||||
enc.wf(v.In(time.FixedZone("UTC", 0)).Format("2006-01-02T15:04:05Z"))
|
||||
return
|
||||
case TextMarshaler:
|
||||
// Special case. Use text marshaler if it's available for this value.
|
||||
if s, err := v.MarshalText(); err != nil {
|
||||
encPanic(err)
|
||||
} else {
|
||||
enc.writeQuoted(string(s))
|
||||
}
|
||||
return
|
||||
}
|
||||
switch rv.Kind() {
|
||||
case reflect.Bool:
|
||||
enc.wf(strconv.FormatBool(rv.Bool()))
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
|
||||
reflect.Int64:
|
||||
enc.wf(strconv.FormatInt(rv.Int(), 10))
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16,
|
||||
reflect.Uint32, reflect.Uint64:
|
||||
enc.wf(strconv.FormatUint(rv.Uint(), 10))
|
||||
case reflect.Float32:
|
||||
enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 32)))
|
||||
case reflect.Float64:
|
||||
enc.wf(floatAddDecimal(strconv.FormatFloat(rv.Float(), 'f', -1, 64)))
|
||||
case reflect.Array, reflect.Slice:
|
||||
enc.eArrayOrSliceElement(rv)
|
||||
case reflect.Interface:
|
||||
enc.eElement(rv.Elem())
|
||||
case reflect.String:
|
||||
enc.writeQuoted(rv.String())
|
||||
default:
|
||||
panic(e("Unexpected primitive type: %s", rv.Kind()))
|
||||
}
|
||||
}
|
||||
|
||||
// By the TOML spec, all floats must have a decimal with at least one
|
||||
// number on either side.
|
||||
func floatAddDecimal(fstr string) string {
|
||||
if !strings.Contains(fstr, ".") {
|
||||
return fstr + ".0"
|
||||
}
|
||||
return fstr
|
||||
}
|
||||
|
||||
func (enc *Encoder) writeQuoted(s string) {
|
||||
enc.wf("\"%s\"", quotedReplacer.Replace(s))
|
||||
}
|
||||
|
||||
func (enc *Encoder) eArrayOrSliceElement(rv reflect.Value) {
|
||||
length := rv.Len()
|
||||
enc.wf("[")
|
||||
for i := 0; i < length; i++ {
|
||||
elem := rv.Index(i)
|
||||
enc.eElement(elem)
|
||||
if i != length-1 {
|
||||
enc.wf(", ")
|
||||
}
|
||||
}
|
||||
enc.wf("]")
|
||||
}
|
||||
|
||||
func (enc *Encoder) eArrayOfTables(key Key, rv reflect.Value) {
|
||||
if len(key) == 0 {
|
||||
encPanic(errNoKey)
|
||||
}
|
||||
for i := 0; i < rv.Len(); i++ {
|
||||
trv := rv.Index(i)
|
||||
if isNil(trv) {
|
||||
continue
|
||||
}
|
||||
panicIfInvalidKey(key)
|
||||
enc.newline()
|
||||
enc.wf("%s[[%s]]", enc.indentStr(key), key.maybeQuotedAll())
|
||||
enc.newline()
|
||||
enc.eMapOrStruct(key, trv)
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *Encoder) eTable(key Key, rv reflect.Value) {
|
||||
panicIfInvalidKey(key)
|
||||
if len(key) == 1 {
|
||||
// Output an extra new line between top-level tables.
|
||||
// (The newline isn't written if nothing else has been written though.)
|
||||
enc.newline()
|
||||
}
|
||||
if len(key) > 0 {
|
||||
enc.wf("%s[%s]", enc.indentStr(key), key.maybeQuotedAll())
|
||||
enc.newline()
|
||||
}
|
||||
enc.eMapOrStruct(key, rv)
|
||||
}
|
||||
|
||||
func (enc *Encoder) eMapOrStruct(key Key, rv reflect.Value) {
|
||||
switch rv := eindirect(rv); rv.Kind() {
|
||||
case reflect.Map:
|
||||
enc.eMap(key, rv)
|
||||
case reflect.Struct:
|
||||
enc.eStruct(key, rv)
|
||||
default:
|
||||
panic("eTable: unhandled reflect.Value Kind: " + rv.Kind().String())
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *Encoder) eMap(key Key, rv reflect.Value) {
|
||||
rt := rv.Type()
|
||||
if rt.Key().Kind() != reflect.String {
|
||||
encPanic(errNonString)
|
||||
}
|
||||
|
||||
// Sort keys so that we have deterministic output. And write keys directly
|
||||
// underneath this key first, before writing sub-structs or sub-maps.
|
||||
var mapKeysDirect, mapKeysSub []string
|
||||
for _, mapKey := range rv.MapKeys() {
|
||||
k := mapKey.String()
|
||||
if typeIsHash(tomlTypeOfGo(rv.MapIndex(mapKey))) {
|
||||
mapKeysSub = append(mapKeysSub, k)
|
||||
} else {
|
||||
mapKeysDirect = append(mapKeysDirect, k)
|
||||
}
|
||||
}
|
||||
|
||||
var writeMapKeys = func(mapKeys []string) {
|
||||
sort.Strings(mapKeys)
|
||||
for _, mapKey := range mapKeys {
|
||||
mrv := rv.MapIndex(reflect.ValueOf(mapKey))
|
||||
if isNil(mrv) {
|
||||
// Don't write anything for nil fields.
|
||||
continue
|
||||
}
|
||||
enc.encode(key.add(mapKey), mrv)
|
||||
}
|
||||
}
|
||||
writeMapKeys(mapKeysDirect)
|
||||
writeMapKeys(mapKeysSub)
|
||||
}
|
||||
|
||||
func (enc *Encoder) eStruct(key Key, rv reflect.Value) {
|
||||
// Write keys for fields directly under this key first, because if we write
|
||||
// a field that creates a new table, then all keys under it will be in that
|
||||
// table (not the one we're writing here).
|
||||
rt := rv.Type()
|
||||
var fieldsDirect, fieldsSub [][]int
|
||||
var addFields func(rt reflect.Type, rv reflect.Value, start []int)
|
||||
addFields = func(rt reflect.Type, rv reflect.Value, start []int) {
|
||||
for i := 0; i < rt.NumField(); i++ {
|
||||
f := rt.Field(i)
|
||||
// skip unexporded fields
|
||||
if f.PkgPath != "" {
|
||||
continue
|
||||
}
|
||||
frv := rv.Field(i)
|
||||
if f.Anonymous {
|
||||
frv := eindirect(frv)
|
||||
t := frv.Type()
|
||||
if t.Kind() != reflect.Struct {
|
||||
encPanic(errAnonNonStruct)
|
||||
}
|
||||
addFields(t, frv, f.Index)
|
||||
} else if typeIsHash(tomlTypeOfGo(frv)) {
|
||||
fieldsSub = append(fieldsSub, append(start, f.Index...))
|
||||
} else {
|
||||
fieldsDirect = append(fieldsDirect, append(start, f.Index...))
|
||||
}
|
||||
}
|
||||
}
|
||||
addFields(rt, rv, nil)
|
||||
|
||||
var writeFields = func(fields [][]int) {
|
||||
for _, fieldIndex := range fields {
|
||||
sft := rt.FieldByIndex(fieldIndex)
|
||||
sf := rv.FieldByIndex(fieldIndex)
|
||||
if isNil(sf) {
|
||||
// Don't write anything for nil fields.
|
||||
continue
|
||||
}
|
||||
|
||||
keyName := sft.Tag.Get("toml")
|
||||
if keyName == "-" {
|
||||
continue
|
||||
}
|
||||
if keyName == "" {
|
||||
keyName = sft.Name
|
||||
}
|
||||
|
||||
keyName, opts := getOptions(keyName)
|
||||
if _, ok := opts["omitempty"]; ok && isEmpty(sf) {
|
||||
continue
|
||||
} else if _, ok := opts["omitzero"]; ok && isZero(sf) {
|
||||
continue
|
||||
}
|
||||
|
||||
enc.encode(key.add(keyName), sf)
|
||||
}
|
||||
}
|
||||
writeFields(fieldsDirect)
|
||||
writeFields(fieldsSub)
|
||||
}
|
||||
|
||||
// tomlTypeName returns the TOML type name of the Go value's type. It is
|
||||
// used to determine whether the types of array elements are mixed (which is
|
||||
// forbidden). If the Go value is nil, then it is illegal for it to be an array
|
||||
// element, and valueIsNil is returned as true.
|
||||
|
||||
// Returns the TOML type of a Go value. The type may be `nil`, which means
|
||||
// no concrete TOML type could be found.
|
||||
func tomlTypeOfGo(rv reflect.Value) tomlType {
|
||||
if isNil(rv) || !rv.IsValid() {
|
||||
return nil
|
||||
}
|
||||
switch rv.Kind() {
|
||||
case reflect.Bool:
|
||||
return tomlBool
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32,
|
||||
reflect.Int64,
|
||||
reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32,
|
||||
reflect.Uint64:
|
||||
return tomlInteger
|
||||
case reflect.Float32, reflect.Float64:
|
||||
return tomlFloat
|
||||
case reflect.Array, reflect.Slice:
|
||||
if typeEqual(tomlHash, tomlArrayType(rv)) {
|
||||
return tomlArrayHash
|
||||
} else {
|
||||
return tomlArray
|
||||
}
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
return tomlTypeOfGo(rv.Elem())
|
||||
case reflect.String:
|
||||
return tomlString
|
||||
case reflect.Map:
|
||||
return tomlHash
|
||||
case reflect.Struct:
|
||||
switch rv.Interface().(type) {
|
||||
case time.Time:
|
||||
return tomlDatetime
|
||||
case TextMarshaler:
|
||||
return tomlString
|
||||
default:
|
||||
return tomlHash
|
||||
}
|
||||
default:
|
||||
panic("unexpected reflect.Kind: " + rv.Kind().String())
|
||||
}
|
||||
}
|
||||
|
||||
// tomlArrayType returns the element type of a TOML array. The type returned
|
||||
// may be nil if it cannot be determined (e.g., a nil slice or a zero length
|
||||
// slize). This function may also panic if it finds a type that cannot be
|
||||
// expressed in TOML (such as nil elements, heterogeneous arrays or directly
|
||||
// nested arrays of tables).
|
||||
func tomlArrayType(rv reflect.Value) tomlType {
|
||||
if isNil(rv) || !rv.IsValid() || rv.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
firstType := tomlTypeOfGo(rv.Index(0))
|
||||
if firstType == nil {
|
||||
encPanic(errArrayNilElement)
|
||||
}
|
||||
|
||||
rvlen := rv.Len()
|
||||
for i := 1; i < rvlen; i++ {
|
||||
elem := rv.Index(i)
|
||||
switch elemType := tomlTypeOfGo(elem); {
|
||||
case elemType == nil:
|
||||
encPanic(errArrayNilElement)
|
||||
case !typeEqual(firstType, elemType):
|
||||
encPanic(errArrayMixedElementTypes)
|
||||
}
|
||||
}
|
||||
// If we have a nested array, then we must make sure that the nested
|
||||
// array contains ONLY primitives.
|
||||
// This checks arbitrarily nested arrays.
|
||||
if typeEqual(firstType, tomlArray) || typeEqual(firstType, tomlArrayHash) {
|
||||
nest := tomlArrayType(eindirect(rv.Index(0)))
|
||||
if typeEqual(nest, tomlHash) || typeEqual(nest, tomlArrayHash) {
|
||||
encPanic(errArrayNoTable)
|
||||
}
|
||||
}
|
||||
return firstType
|
||||
}
|
||||
|
||||
func getOptions(keyName string) (string, map[string]struct{}) {
|
||||
opts := make(map[string]struct{})
|
||||
ss := strings.Split(keyName, ",")
|
||||
name := ss[0]
|
||||
if len(ss) > 1 {
|
||||
for _, opt := range ss {
|
||||
opts[opt] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
return name, opts
|
||||
}
|
||||
|
||||
func isZero(rv reflect.Value) bool {
|
||||
switch rv.Kind() {
|
||||
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
||||
if rv.Int() == 0 {
|
||||
return true
|
||||
}
|
||||
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
|
||||
if rv.Uint() == 0 {
|
||||
return true
|
||||
}
|
||||
case reflect.Float32, reflect.Float64:
|
||||
if rv.Float() == 0.0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func isEmpty(rv reflect.Value) bool {
|
||||
switch rv.Kind() {
|
||||
case reflect.String:
|
||||
if len(strings.TrimSpace(rv.String())) == 0 {
|
||||
return true
|
||||
}
|
||||
case reflect.Array, reflect.Slice, reflect.Map:
|
||||
if rv.Len() == 0 {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (enc *Encoder) newline() {
|
||||
if enc.hasWritten {
|
||||
enc.wf("\n")
|
||||
}
|
||||
}
|
||||
|
||||
func (enc *Encoder) keyEqElement(key Key, val reflect.Value) {
|
||||
if len(key) == 0 {
|
||||
encPanic(errNoKey)
|
||||
}
|
||||
panicIfInvalidKey(key)
|
||||
enc.wf("%s%s = ", enc.indentStr(key), key.maybeQuoted(len(key)-1))
|
||||
enc.eElement(val)
|
||||
enc.newline()
|
||||
}
|
||||
|
||||
func (enc *Encoder) wf(format string, v ...interface{}) {
|
||||
if _, err := fmt.Fprintf(enc.w, format, v...); err != nil {
|
||||
encPanic(err)
|
||||
}
|
||||
enc.hasWritten = true
|
||||
}
|
||||
|
||||
func (enc *Encoder) indentStr(key Key) string {
|
||||
return strings.Repeat(enc.Indent, len(key)-1)
|
||||
}
|
||||
|
||||
func encPanic(err error) {
|
||||
panic(tomlEncodeError{err})
|
||||
}
|
||||
|
||||
func eindirect(v reflect.Value) reflect.Value {
|
||||
switch v.Kind() {
|
||||
case reflect.Ptr, reflect.Interface:
|
||||
return eindirect(v.Elem())
|
||||
default:
|
||||
return v
|
||||
}
|
||||
}
|
||||
|
||||
func isNil(rv reflect.Value) bool {
|
||||
switch rv.Kind() {
|
||||
case reflect.Interface, reflect.Map, reflect.Ptr, reflect.Slice:
|
||||
return rv.IsNil()
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
func panicIfInvalidKey(key Key) {
|
||||
for _, k := range key {
|
||||
if len(k) == 0 {
|
||||
encPanic(e("Key '%s' is not a valid table name. Key names "+
|
||||
"cannot be empty.", key.maybeQuotedAll()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func isValidKeyName(s string) bool {
|
||||
return len(s) != 0
|
||||
}
|
||||
542
Godeps/_workspace/src/github.com/BurntSushi/toml/encode_test.go
generated
vendored
Normal file
542
Godeps/_workspace/src/github.com/BurntSushi/toml/encode_test.go
generated
vendored
Normal file
@@ -0,0 +1,542 @@
|
||||
package toml
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"log"
|
||||
"net"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestEncodeRoundTrip(t *testing.T) {
|
||||
type Config struct {
|
||||
Age int
|
||||
Cats []string
|
||||
Pi float64
|
||||
Perfection []int
|
||||
DOB time.Time
|
||||
Ipaddress net.IP
|
||||
}
|
||||
|
||||
var inputs = Config{
|
||||
13,
|
||||
[]string{"one", "two", "three"},
|
||||
3.145,
|
||||
[]int{11, 2, 3, 4},
|
||||
time.Now(),
|
||||
net.ParseIP("192.168.59.254"),
|
||||
}
|
||||
|
||||
var firstBuffer bytes.Buffer
|
||||
e := NewEncoder(&firstBuffer)
|
||||
err := e.Encode(inputs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
var outputs Config
|
||||
if _, err := Decode(firstBuffer.String(), &outputs); err != nil {
|
||||
log.Printf("Could not decode:\n-----\n%s\n-----\n",
|
||||
firstBuffer.String())
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// could test each value individually, but I'm lazy
|
||||
var secondBuffer bytes.Buffer
|
||||
e2 := NewEncoder(&secondBuffer)
|
||||
err = e2.Encode(outputs)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if firstBuffer.String() != secondBuffer.String() {
|
||||
t.Error(
|
||||
firstBuffer.String(),
|
||||
"\n\n is not identical to\n\n",
|
||||
secondBuffer.String())
|
||||
}
|
||||
}
|
||||
|
||||
// XXX(burntsushi)
|
||||
// I think these tests probably should be removed. They are good, but they
|
||||
// ought to be obsolete by toml-test.
|
||||
func TestEncode(t *testing.T) {
|
||||
type Embedded struct {
|
||||
Int int `toml:"_int"`
|
||||
}
|
||||
type NonStruct int
|
||||
|
||||
date := time.Date(2014, 5, 11, 20, 30, 40, 0, time.FixedZone("IST", 3600))
|
||||
dateStr := "2014-05-11T19:30:40Z"
|
||||
|
||||
tests := map[string]struct {
|
||||
input interface{}
|
||||
wantOutput string
|
||||
wantError error
|
||||
}{
|
||||
"bool field": {
|
||||
input: struct {
|
||||
BoolTrue bool
|
||||
BoolFalse bool
|
||||
}{true, false},
|
||||
wantOutput: "BoolTrue = true\nBoolFalse = false\n",
|
||||
},
|
||||
"int fields": {
|
||||
input: struct {
|
||||
Int int
|
||||
Int8 int8
|
||||
Int16 int16
|
||||
Int32 int32
|
||||
Int64 int64
|
||||
}{1, 2, 3, 4, 5},
|
||||
wantOutput: "Int = 1\nInt8 = 2\nInt16 = 3\nInt32 = 4\nInt64 = 5\n",
|
||||
},
|
||||
"uint fields": {
|
||||
input: struct {
|
||||
Uint uint
|
||||
Uint8 uint8
|
||||
Uint16 uint16
|
||||
Uint32 uint32
|
||||
Uint64 uint64
|
||||
}{1, 2, 3, 4, 5},
|
||||
wantOutput: "Uint = 1\nUint8 = 2\nUint16 = 3\nUint32 = 4" +
|
||||
"\nUint64 = 5\n",
|
||||
},
|
||||
"float fields": {
|
||||
input: struct {
|
||||
Float32 float32
|
||||
Float64 float64
|
||||
}{1.5, 2.5},
|
||||
wantOutput: "Float32 = 1.5\nFloat64 = 2.5\n",
|
||||
},
|
||||
"string field": {
|
||||
input: struct{ String string }{"foo"},
|
||||
wantOutput: "String = \"foo\"\n",
|
||||
},
|
||||
"string field and unexported field": {
|
||||
input: struct {
|
||||
String string
|
||||
unexported int
|
||||
}{"foo", 0},
|
||||
wantOutput: "String = \"foo\"\n",
|
||||
},
|
||||
"datetime field in UTC": {
|
||||
input: struct{ Date time.Time }{date},
|
||||
wantOutput: fmt.Sprintf("Date = %s\n", dateStr),
|
||||
},
|
||||
"datetime field as primitive": {
|
||||
// Using a map here to fail if isStructOrMap() returns true for
|
||||
// time.Time.
|
||||
input: map[string]interface{}{
|
||||
"Date": date,
|
||||
"Int": 1,
|
||||
},
|
||||
wantOutput: fmt.Sprintf("Date = %s\nInt = 1\n", dateStr),
|
||||
},
|
||||
"array fields": {
|
||||
input: struct {
|
||||
IntArray0 [0]int
|
||||
IntArray3 [3]int
|
||||
}{[0]int{}, [3]int{1, 2, 3}},
|
||||
wantOutput: "IntArray0 = []\nIntArray3 = [1, 2, 3]\n",
|
||||
},
|
||||
"slice fields": {
|
||||
input: struct{ IntSliceNil, IntSlice0, IntSlice3 []int }{
|
||||
nil, []int{}, []int{1, 2, 3},
|
||||
},
|
||||
wantOutput: "IntSlice0 = []\nIntSlice3 = [1, 2, 3]\n",
|
||||
},
|
||||
"datetime slices": {
|
||||
input: struct{ DatetimeSlice []time.Time }{
|
||||
[]time.Time{date, date},
|
||||
},
|
||||
wantOutput: fmt.Sprintf("DatetimeSlice = [%s, %s]\n",
|
||||
dateStr, dateStr),
|
||||
},
|
||||
"nested arrays and slices": {
|
||||
input: struct {
|
||||
SliceOfArrays [][2]int
|
||||
ArrayOfSlices [2][]int
|
||||
SliceOfArraysOfSlices [][2][]int
|
||||
ArrayOfSlicesOfArrays [2][][2]int
|
||||
SliceOfMixedArrays [][2]interface{}
|
||||
ArrayOfMixedSlices [2][]interface{}
|
||||
}{
|
||||
[][2]int{{1, 2}, {3, 4}},
|
||||
[2][]int{{1, 2}, {3, 4}},
|
||||
[][2][]int{
|
||||
{
|
||||
{1, 2}, {3, 4},
|
||||
},
|
||||
{
|
||||
{5, 6}, {7, 8},
|
||||
},
|
||||
},
|
||||
[2][][2]int{
|
||||
{
|
||||
{1, 2}, {3, 4},
|
||||
},
|
||||
{
|
||||
{5, 6}, {7, 8},
|
||||
},
|
||||
},
|
||||
[][2]interface{}{
|
||||
{1, 2}, {"a", "b"},
|
||||
},
|
||||
[2][]interface{}{
|
||||
{1, 2}, {"a", "b"},
|
||||
},
|
||||
},
|
||||
wantOutput: `SliceOfArrays = [[1, 2], [3, 4]]
|
||||
ArrayOfSlices = [[1, 2], [3, 4]]
|
||||
SliceOfArraysOfSlices = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
|
||||
ArrayOfSlicesOfArrays = [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]
|
||||
SliceOfMixedArrays = [[1, 2], ["a", "b"]]
|
||||
ArrayOfMixedSlices = [[1, 2], ["a", "b"]]
|
||||
`,
|
||||
},
|
||||
"empty slice": {
|
||||
input: struct{ Empty []interface{} }{[]interface{}{}},
|
||||
wantOutput: "Empty = []\n",
|
||||
},
|
||||
"(error) slice with element type mismatch (string and integer)": {
|
||||
input: struct{ Mixed []interface{} }{[]interface{}{1, "a"}},
|
||||
wantError: errArrayMixedElementTypes,
|
||||
},
|
||||
"(error) slice with element type mismatch (integer and float)": {
|
||||
input: struct{ Mixed []interface{} }{[]interface{}{1, 2.5}},
|
||||
wantError: errArrayMixedElementTypes,
|
||||
},
|
||||
"slice with elems of differing Go types, same TOML types": {
|
||||
input: struct {
|
||||
MixedInts []interface{}
|
||||
MixedFloats []interface{}
|
||||
}{
|
||||
[]interface{}{
|
||||
int(1), int8(2), int16(3), int32(4), int64(5),
|
||||
uint(1), uint8(2), uint16(3), uint32(4), uint64(5),
|
||||
},
|
||||
[]interface{}{float32(1.5), float64(2.5)},
|
||||
},
|
||||
wantOutput: "MixedInts = [1, 2, 3, 4, 5, 1, 2, 3, 4, 5]\n" +
|
||||
"MixedFloats = [1.5, 2.5]\n",
|
||||
},
|
||||
"(error) slice w/ element type mismatch (one is nested array)": {
|
||||
input: struct{ Mixed []interface{} }{
|
||||
[]interface{}{1, []interface{}{2}},
|
||||
},
|
||||
wantError: errArrayMixedElementTypes,
|
||||
},
|
||||
"(error) slice with 1 nil element": {
|
||||
input: struct{ NilElement1 []interface{} }{[]interface{}{nil}},
|
||||
wantError: errArrayNilElement,
|
||||
},
|
||||
"(error) slice with 1 nil element (and other non-nil elements)": {
|
||||
input: struct{ NilElement []interface{} }{
|
||||
[]interface{}{1, nil},
|
||||
},
|
||||
wantError: errArrayNilElement,
|
||||
},
|
||||
"simple map": {
|
||||
input: map[string]int{"a": 1, "b": 2},
|
||||
wantOutput: "a = 1\nb = 2\n",
|
||||
},
|
||||
"map with interface{} value type": {
|
||||
input: map[string]interface{}{"a": 1, "b": "c"},
|
||||
wantOutput: "a = 1\nb = \"c\"\n",
|
||||
},
|
||||
"map with interface{} value type, some of which are structs": {
|
||||
input: map[string]interface{}{
|
||||
"a": struct{ Int int }{2},
|
||||
"b": 1,
|
||||
},
|
||||
wantOutput: "b = 1\n\n[a]\n Int = 2\n",
|
||||
},
|
||||
"nested map": {
|
||||
input: map[string]map[string]int{
|
||||
"a": {"b": 1},
|
||||
"c": {"d": 2},
|
||||
},
|
||||
wantOutput: "[a]\n b = 1\n\n[c]\n d = 2\n",
|
||||
},
|
||||
"nested struct": {
|
||||
input: struct{ Struct struct{ Int int } }{
|
||||
struct{ Int int }{1},
|
||||
},
|
||||
wantOutput: "[Struct]\n Int = 1\n",
|
||||
},
|
||||
"nested struct and non-struct field": {
|
||||
input: struct {
|
||||
Struct struct{ Int int }
|
||||
Bool bool
|
||||
}{struct{ Int int }{1}, true},
|
||||
wantOutput: "Bool = true\n\n[Struct]\n Int = 1\n",
|
||||
},
|
||||
"2 nested structs": {
|
||||
input: struct{ Struct1, Struct2 struct{ Int int } }{
|
||||
struct{ Int int }{1}, struct{ Int int }{2},
|
||||
},
|
||||
wantOutput: "[Struct1]\n Int = 1\n\n[Struct2]\n Int = 2\n",
|
||||
},
|
||||
"deeply nested structs": {
|
||||
input: struct {
|
||||
Struct1, Struct2 struct{ Struct3 *struct{ Int int } }
|
||||
}{
|
||||
struct{ Struct3 *struct{ Int int } }{&struct{ Int int }{1}},
|
||||
struct{ Struct3 *struct{ Int int } }{nil},
|
||||
},
|
||||
wantOutput: "[Struct1]\n [Struct1.Struct3]\n Int = 1" +
|
||||
"\n\n[Struct2]\n",
|
||||
},
|
||||
"nested struct with nil struct elem": {
|
||||
input: struct {
|
||||
Struct struct{ Inner *struct{ Int int } }
|
||||
}{
|
||||
struct{ Inner *struct{ Int int } }{nil},
|
||||
},
|
||||
wantOutput: "[Struct]\n",
|
||||
},
|
||||
"nested struct with no fields": {
|
||||
input: struct {
|
||||
Struct struct{ Inner struct{} }
|
||||
}{
|
||||
struct{ Inner struct{} }{struct{}{}},
|
||||
},
|
||||
wantOutput: "[Struct]\n [Struct.Inner]\n",
|
||||
},
|
||||
"struct with tags": {
|
||||
input: struct {
|
||||
Struct struct {
|
||||
Int int `toml:"_int"`
|
||||
} `toml:"_struct"`
|
||||
Bool bool `toml:"_bool"`
|
||||
}{
|
||||
struct {
|
||||
Int int `toml:"_int"`
|
||||
}{1}, true,
|
||||
},
|
||||
wantOutput: "_bool = true\n\n[_struct]\n _int = 1\n",
|
||||
},
|
||||
"embedded struct": {
|
||||
input: struct{ Embedded }{Embedded{1}},
|
||||
wantOutput: "_int = 1\n",
|
||||
},
|
||||
"embedded *struct": {
|
||||
input: struct{ *Embedded }{&Embedded{1}},
|
||||
wantOutput: "_int = 1\n",
|
||||
},
|
||||
"nested embedded struct": {
|
||||
input: struct {
|
||||
Struct struct{ Embedded } `toml:"_struct"`
|
||||
}{struct{ Embedded }{Embedded{1}}},
|
||||
wantOutput: "[_struct]\n _int = 1\n",
|
||||
},
|
||||
"nested embedded *struct": {
|
||||
input: struct {
|
||||
Struct struct{ *Embedded } `toml:"_struct"`
|
||||
}{struct{ *Embedded }{&Embedded{1}}},
|
||||
wantOutput: "[_struct]\n _int = 1\n",
|
||||
},
|
||||
"array of tables": {
|
||||
input: struct {
|
||||
Structs []*struct{ Int int } `toml:"struct"`
|
||||
}{
|
||||
[]*struct{ Int int }{{1}, {3}},
|
||||
},
|
||||
wantOutput: "[[struct]]\n Int = 1\n\n[[struct]]\n Int = 3\n",
|
||||
},
|
||||
"array of tables order": {
|
||||
input: map[string]interface{}{
|
||||
"map": map[string]interface{}{
|
||||
"zero": 5,
|
||||
"arr": []map[string]int{
|
||||
map[string]int{
|
||||
"friend": 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
wantOutput: "[map]\n zero = 5\n\n [[map.arr]]\n friend = 5\n",
|
||||
},
|
||||
"(error) top-level slice": {
|
||||
input: []struct{ Int int }{{1}, {2}, {3}},
|
||||
wantError: errNoKey,
|
||||
},
|
||||
"(error) slice of slice": {
|
||||
input: struct {
|
||||
Slices [][]struct{ Int int }
|
||||
}{
|
||||
[][]struct{ Int int }{{{1}}, {{2}}, {{3}}},
|
||||
},
|
||||
wantError: errArrayNoTable,
|
||||
},
|
||||
"(error) map no string key": {
|
||||
input: map[int]string{1: ""},
|
||||
wantError: errNonString,
|
||||
},
|
||||
"(error) anonymous non-struct": {
|
||||
input: struct{ NonStruct }{5},
|
||||
wantError: errAnonNonStruct,
|
||||
},
|
||||
"(error) empty key name": {
|
||||
input: map[string]int{"": 1},
|
||||
wantError: errAnything,
|
||||
},
|
||||
"(error) empty map name": {
|
||||
input: map[string]interface{}{
|
||||
"": map[string]int{"v": 1},
|
||||
},
|
||||
wantError: errAnything,
|
||||
},
|
||||
}
|
||||
for label, test := range tests {
|
||||
encodeExpected(t, label, test.input, test.wantOutput, test.wantError)
|
||||
}
|
||||
}
|
||||
|
||||
func TestEncodeNestedTableArrays(t *testing.T) {
|
||||
type song struct {
|
||||
Name string `toml:"name"`
|
||||
}
|
||||
type album struct {
|
||||
Name string `toml:"name"`
|
||||
Songs []song `toml:"songs"`
|
||||
}
|
||||
type springsteen struct {
|
||||
Albums []album `toml:"albums"`
|
||||
}
|
||||
value := springsteen{
|
||||
[]album{
|
||||
{"Born to Run",
|
||||
[]song{{"Jungleland"}, {"Meeting Across the River"}}},
|
||||
{"Born in the USA",
|
||||
[]song{{"Glory Days"}, {"Dancing in the Dark"}}},
|
||||
},
|
||||
}
|
||||
expected := `[[albums]]
|
||||
name = "Born to Run"
|
||||
|
||||
[[albums.songs]]
|
||||
name = "Jungleland"
|
||||
|
||||
[[albums.songs]]
|
||||
name = "Meeting Across the River"
|
||||
|
||||
[[albums]]
|
||||
name = "Born in the USA"
|
||||
|
||||
[[albums.songs]]
|
||||
name = "Glory Days"
|
||||
|
||||
[[albums.songs]]
|
||||
name = "Dancing in the Dark"
|
||||
`
|
||||
encodeExpected(t, "nested table arrays", value, expected, nil)
|
||||
}
|
||||
|
||||
func TestEncodeArrayHashWithNormalHashOrder(t *testing.T) {
|
||||
type Alpha struct {
|
||||
V int
|
||||
}
|
||||
type Beta struct {
|
||||
V int
|
||||
}
|
||||
type Conf struct {
|
||||
V int
|
||||
A Alpha
|
||||
B []Beta
|
||||
}
|
||||
|
||||
val := Conf{
|
||||
V: 1,
|
||||
A: Alpha{2},
|
||||
B: []Beta{{3}},
|
||||
}
|
||||
expected := "V = 1\n\n[A]\n V = 2\n\n[[B]]\n V = 3\n"
|
||||
encodeExpected(t, "array hash with normal hash order", val, expected, nil)
|
||||
}
|
||||
|
||||
func TestEncodeWithOmitEmpty(t *testing.T) {
|
||||
type simple struct {
|
||||
User string `toml:"user"`
|
||||
Pass string `toml:"password,omitempty"`
|
||||
}
|
||||
|
||||
value := simple{"Testing", ""}
|
||||
expected := fmt.Sprintf("user = %q\n", value.User)
|
||||
encodeExpected(t, "simple with omitempty, is empty", value, expected, nil)
|
||||
value.Pass = "some password"
|
||||
expected = fmt.Sprintf("user = %q\npassword = %q\n", value.User, value.Pass)
|
||||
encodeExpected(t, "simple with omitempty, not empty", value, expected, nil)
|
||||
}
|
||||
|
||||
func TestEncodeWithOmitZero(t *testing.T) {
|
||||
type simple struct {
|
||||
Number int `toml:"number,omitzero"`
|
||||
Real float64 `toml:"real,omitzero"`
|
||||
Unsigned uint `toml:"unsigned,omitzero"`
|
||||
}
|
||||
|
||||
value := simple{0, 0.0, uint(0)}
|
||||
expected := ""
|
||||
|
||||
encodeExpected(t, "simple with omitzero, all zero", value, expected, nil)
|
||||
|
||||
value.Number = 10
|
||||
value.Real = 20
|
||||
value.Unsigned = 5
|
||||
expected = `number = 10
|
||||
real = 20.0
|
||||
unsigned = 5
|
||||
`
|
||||
encodeExpected(t, "simple with omitzero, non-zero", value, expected, nil)
|
||||
}
|
||||
|
||||
func encodeExpected(
|
||||
t *testing.T, label string, val interface{}, wantStr string, wantErr error,
|
||||
) {
|
||||
var buf bytes.Buffer
|
||||
enc := NewEncoder(&buf)
|
||||
err := enc.Encode(val)
|
||||
if err != wantErr {
|
||||
if wantErr != nil {
|
||||
if wantErr == errAnything && err != nil {
|
||||
return
|
||||
}
|
||||
t.Errorf("%s: want Encode error %v, got %v", label, wantErr, err)
|
||||
} else {
|
||||
t.Errorf("%s: Encode failed: %s", label, err)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if got := buf.String(); wantStr != got {
|
||||
t.Errorf("%s: want\n-----\n%q\n-----\nbut got\n-----\n%q\n-----\n",
|
||||
label, wantStr, got)
|
||||
}
|
||||
}
|
||||
|
||||
func ExampleEncoder_Encode() {
|
||||
date, _ := time.Parse(time.RFC822, "14 Mar 10 18:00 UTC")
|
||||
var config = map[string]interface{}{
|
||||
"date": date,
|
||||
"counts": []int{1, 1, 2, 3, 5, 8},
|
||||
"hash": map[string]string{
|
||||
"key1": "val1",
|
||||
"key2": "val2",
|
||||
},
|
||||
}
|
||||
buf := new(bytes.Buffer)
|
||||
if err := NewEncoder(buf).Encode(config); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Println(buf.String())
|
||||
|
||||
// Output:
|
||||
// counts = [1, 1, 2, 3, 5, 8]
|
||||
// date = 2010-03-14T18:00:00Z
|
||||
//
|
||||
// [hash]
|
||||
// key1 = "val1"
|
||||
// key2 = "val2"
|
||||
}
|
||||
19
Godeps/_workspace/src/github.com/BurntSushi/toml/encoding_types.go
generated
vendored
Normal file
19
Godeps/_workspace/src/github.com/BurntSushi/toml/encoding_types.go
generated
vendored
Normal file
@@ -0,0 +1,19 @@
|
||||
// +build go1.2
|
||||
|
||||
package toml
|
||||
|
||||
// In order to support Go 1.1, we define our own TextMarshaler and
|
||||
// TextUnmarshaler types. For Go 1.2+, we just alias them with the
|
||||
// standard library interfaces.
|
||||
|
||||
import (
|
||||
"encoding"
|
||||
)
|
||||
|
||||
// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here
|
||||
// so that Go 1.1 can be supported.
|
||||
type TextMarshaler encoding.TextMarshaler
|
||||
|
||||
// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined
|
||||
// here so that Go 1.1 can be supported.
|
||||
type TextUnmarshaler encoding.TextUnmarshaler
|
||||
18
Godeps/_workspace/src/github.com/BurntSushi/toml/encoding_types_1.1.go
generated
vendored
Normal file
18
Godeps/_workspace/src/github.com/BurntSushi/toml/encoding_types_1.1.go
generated
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
// +build !go1.2
|
||||
|
||||
package toml
|
||||
|
||||
// These interfaces were introduced in Go 1.2, so we add them manually when
|
||||
// compiling for Go 1.1.
|
||||
|
||||
// TextMarshaler is a synonym for encoding.TextMarshaler. It is defined here
|
||||
// so that Go 1.1 can be supported.
|
||||
type TextMarshaler interface {
|
||||
MarshalText() (text []byte, err error)
|
||||
}
|
||||
|
||||
// TextUnmarshaler is a synonym for encoding.TextUnmarshaler. It is defined
|
||||
// here so that Go 1.1 can be supported.
|
||||
type TextUnmarshaler interface {
|
||||
UnmarshalText(text []byte) error
|
||||
}
|
||||
874
Godeps/_workspace/src/github.com/BurntSushi/toml/lex.go
generated
vendored
Normal file
874
Godeps/_workspace/src/github.com/BurntSushi/toml/lex.go
generated
vendored
Normal file
@@ -0,0 +1,874 @@
|
||||
package toml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type itemType int
|
||||
|
||||
const (
|
||||
itemError itemType = iota
|
||||
itemNIL // used in the parser to indicate no type
|
||||
itemEOF
|
||||
itemText
|
||||
itemString
|
||||
itemRawString
|
||||
itemMultilineString
|
||||
itemRawMultilineString
|
||||
itemBool
|
||||
itemInteger
|
||||
itemFloat
|
||||
itemDatetime
|
||||
itemArray // the start of an array
|
||||
itemArrayEnd
|
||||
itemTableStart
|
||||
itemTableEnd
|
||||
itemArrayTableStart
|
||||
itemArrayTableEnd
|
||||
itemKeyStart
|
||||
itemCommentStart
|
||||
)
|
||||
|
||||
const (
|
||||
eof = 0
|
||||
tableStart = '['
|
||||
tableEnd = ']'
|
||||
arrayTableStart = '['
|
||||
arrayTableEnd = ']'
|
||||
tableSep = '.'
|
||||
keySep = '='
|
||||
arrayStart = '['
|
||||
arrayEnd = ']'
|
||||
arrayValTerm = ','
|
||||
commentStart = '#'
|
||||
stringStart = '"'
|
||||
stringEnd = '"'
|
||||
rawStringStart = '\''
|
||||
rawStringEnd = '\''
|
||||
)
|
||||
|
||||
type stateFn func(lx *lexer) stateFn
|
||||
|
||||
type lexer struct {
|
||||
input string
|
||||
start int
|
||||
pos int
|
||||
width int
|
||||
line int
|
||||
state stateFn
|
||||
items chan item
|
||||
|
||||
// A stack of state functions used to maintain context.
|
||||
// The idea is to reuse parts of the state machine in various places.
|
||||
// For example, values can appear at the top level or within arbitrarily
|
||||
// nested arrays. The last state on the stack is used after a value has
|
||||
// been lexed. Similarly for comments.
|
||||
stack []stateFn
|
||||
}
|
||||
|
||||
type item struct {
|
||||
typ itemType
|
||||
val string
|
||||
line int
|
||||
}
|
||||
|
||||
func (lx *lexer) nextItem() item {
|
||||
for {
|
||||
select {
|
||||
case item := <-lx.items:
|
||||
return item
|
||||
default:
|
||||
lx.state = lx.state(lx)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func lex(input string) *lexer {
|
||||
lx := &lexer{
|
||||
input: input + "\n",
|
||||
state: lexTop,
|
||||
line: 1,
|
||||
items: make(chan item, 10),
|
||||
stack: make([]stateFn, 0, 10),
|
||||
}
|
||||
return lx
|
||||
}
|
||||
|
||||
func (lx *lexer) push(state stateFn) {
|
||||
lx.stack = append(lx.stack, state)
|
||||
}
|
||||
|
||||
func (lx *lexer) pop() stateFn {
|
||||
if len(lx.stack) == 0 {
|
||||
return lx.errorf("BUG in lexer: no states to pop.")
|
||||
}
|
||||
last := lx.stack[len(lx.stack)-1]
|
||||
lx.stack = lx.stack[0 : len(lx.stack)-1]
|
||||
return last
|
||||
}
|
||||
|
||||
func (lx *lexer) current() string {
|
||||
return lx.input[lx.start:lx.pos]
|
||||
}
|
||||
|
||||
func (lx *lexer) emit(typ itemType) {
|
||||
lx.items <- item{typ, lx.current(), lx.line}
|
||||
lx.start = lx.pos
|
||||
}
|
||||
|
||||
func (lx *lexer) emitTrim(typ itemType) {
|
||||
lx.items <- item{typ, strings.TrimSpace(lx.current()), lx.line}
|
||||
lx.start = lx.pos
|
||||
}
|
||||
|
||||
func (lx *lexer) next() (r rune) {
|
||||
if lx.pos >= len(lx.input) {
|
||||
lx.width = 0
|
||||
return eof
|
||||
}
|
||||
|
||||
if lx.input[lx.pos] == '\n' {
|
||||
lx.line++
|
||||
}
|
||||
r, lx.width = utf8.DecodeRuneInString(lx.input[lx.pos:])
|
||||
lx.pos += lx.width
|
||||
return r
|
||||
}
|
||||
|
||||
// ignore skips over the pending input before this point.
|
||||
func (lx *lexer) ignore() {
|
||||
lx.start = lx.pos
|
||||
}
|
||||
|
||||
// backup steps back one rune. Can be called only once per call of next.
|
||||
func (lx *lexer) backup() {
|
||||
lx.pos -= lx.width
|
||||
if lx.pos < len(lx.input) && lx.input[lx.pos] == '\n' {
|
||||
lx.line--
|
||||
}
|
||||
}
|
||||
|
||||
// accept consumes the next rune if it's equal to `valid`.
|
||||
func (lx *lexer) accept(valid rune) bool {
|
||||
if lx.next() == valid {
|
||||
return true
|
||||
}
|
||||
lx.backup()
|
||||
return false
|
||||
}
|
||||
|
||||
// peek returns but does not consume the next rune in the input.
|
||||
func (lx *lexer) peek() rune {
|
||||
r := lx.next()
|
||||
lx.backup()
|
||||
return r
|
||||
}
|
||||
|
||||
// errorf stops all lexing by emitting an error and returning `nil`.
|
||||
// Note that any value that is a character is escaped if it's a special
|
||||
// character (new lines, tabs, etc.).
|
||||
func (lx *lexer) errorf(format string, values ...interface{}) stateFn {
|
||||
lx.items <- item{
|
||||
itemError,
|
||||
fmt.Sprintf(format, values...),
|
||||
lx.line,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// lexTop consumes elements at the top level of TOML data.
|
||||
func lexTop(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if isWhitespace(r) || isNL(r) {
|
||||
return lexSkip(lx, lexTop)
|
||||
}
|
||||
|
||||
switch r {
|
||||
case commentStart:
|
||||
lx.push(lexTop)
|
||||
return lexCommentStart
|
||||
case tableStart:
|
||||
return lexTableStart
|
||||
case eof:
|
||||
if lx.pos > lx.start {
|
||||
return lx.errorf("Unexpected EOF.")
|
||||
}
|
||||
lx.emit(itemEOF)
|
||||
return nil
|
||||
}
|
||||
|
||||
// At this point, the only valid item can be a key, so we back up
|
||||
// and let the key lexer do the rest.
|
||||
lx.backup()
|
||||
lx.push(lexTopEnd)
|
||||
return lexKeyStart
|
||||
}
|
||||
|
||||
// lexTopEnd is entered whenever a top-level item has been consumed. (A value
|
||||
// or a table.) It must see only whitespace, and will turn back to lexTop
|
||||
// upon a new line. If it sees EOF, it will quit the lexer successfully.
|
||||
func lexTopEnd(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch {
|
||||
case r == commentStart:
|
||||
// a comment will read to a new line for us.
|
||||
lx.push(lexTop)
|
||||
return lexCommentStart
|
||||
case isWhitespace(r):
|
||||
return lexTopEnd
|
||||
case isNL(r):
|
||||
lx.ignore()
|
||||
return lexTop
|
||||
case r == eof:
|
||||
lx.ignore()
|
||||
return lexTop
|
||||
}
|
||||
return lx.errorf("Expected a top-level item to end with a new line, "+
|
||||
"comment or EOF, but got %q instead.", r)
|
||||
}
|
||||
|
||||
// lexTable lexes the beginning of a table. Namely, it makes sure that
|
||||
// it starts with a character other than '.' and ']'.
|
||||
// It assumes that '[' has already been consumed.
|
||||
// It also handles the case that this is an item in an array of tables.
|
||||
// e.g., '[[name]]'.
|
||||
func lexTableStart(lx *lexer) stateFn {
|
||||
if lx.peek() == arrayTableStart {
|
||||
lx.next()
|
||||
lx.emit(itemArrayTableStart)
|
||||
lx.push(lexArrayTableEnd)
|
||||
} else {
|
||||
lx.emit(itemTableStart)
|
||||
lx.push(lexTableEnd)
|
||||
}
|
||||
return lexTableNameStart
|
||||
}
|
||||
|
||||
func lexTableEnd(lx *lexer) stateFn {
|
||||
lx.emit(itemTableEnd)
|
||||
return lexTopEnd
|
||||
}
|
||||
|
||||
func lexArrayTableEnd(lx *lexer) stateFn {
|
||||
if r := lx.next(); r != arrayTableEnd {
|
||||
return lx.errorf("Expected end of table array name delimiter %q, "+
|
||||
"but got %q instead.", arrayTableEnd, r)
|
||||
}
|
||||
lx.emit(itemArrayTableEnd)
|
||||
return lexTopEnd
|
||||
}
|
||||
|
||||
func lexTableNameStart(lx *lexer) stateFn {
|
||||
switch r := lx.peek(); {
|
||||
case r == tableEnd || r == eof:
|
||||
return lx.errorf("Unexpected end of table name. (Table names cannot " +
|
||||
"be empty.)")
|
||||
case r == tableSep:
|
||||
return lx.errorf("Unexpected table separator. (Table names cannot " +
|
||||
"be empty.)")
|
||||
case r == stringStart || r == rawStringStart:
|
||||
lx.ignore()
|
||||
lx.push(lexTableNameEnd)
|
||||
return lexValue // reuse string lexing
|
||||
case isWhitespace(r):
|
||||
return lexTableNameStart
|
||||
default:
|
||||
return lexBareTableName
|
||||
}
|
||||
}
|
||||
|
||||
// lexTableName lexes the name of a table. It assumes that at least one
|
||||
// valid character for the table has already been read.
|
||||
func lexBareTableName(lx *lexer) stateFn {
|
||||
switch r := lx.next(); {
|
||||
case isBareKeyChar(r):
|
||||
return lexBareTableName
|
||||
case r == tableSep || r == tableEnd:
|
||||
lx.backup()
|
||||
lx.emitTrim(itemText)
|
||||
return lexTableNameEnd
|
||||
default:
|
||||
return lx.errorf("Bare keys cannot contain %q.", r)
|
||||
}
|
||||
}
|
||||
|
||||
// lexTableNameEnd reads the end of a piece of a table name, optionally
|
||||
// consuming whitespace.
|
||||
func lexTableNameEnd(lx *lexer) stateFn {
|
||||
switch r := lx.next(); {
|
||||
case isWhitespace(r):
|
||||
return lexTableNameEnd
|
||||
case r == tableSep:
|
||||
lx.ignore()
|
||||
return lexTableNameStart
|
||||
case r == tableEnd:
|
||||
return lx.pop()
|
||||
default:
|
||||
return lx.errorf("Expected '.' or ']' to end table name, but got %q "+
|
||||
"instead.", r)
|
||||
}
|
||||
}
|
||||
|
||||
// lexKeyStart consumes a key name up until the first non-whitespace character.
|
||||
// lexKeyStart will ignore whitespace.
|
||||
func lexKeyStart(lx *lexer) stateFn {
|
||||
r := lx.peek()
|
||||
switch {
|
||||
case r == keySep:
|
||||
return lx.errorf("Unexpected key separator %q.", keySep)
|
||||
case isWhitespace(r) || isNL(r):
|
||||
lx.next()
|
||||
return lexSkip(lx, lexKeyStart)
|
||||
case r == stringStart || r == rawStringStart:
|
||||
lx.ignore()
|
||||
lx.emit(itemKeyStart)
|
||||
lx.push(lexKeyEnd)
|
||||
return lexValue // reuse string lexing
|
||||
default:
|
||||
lx.ignore()
|
||||
lx.emit(itemKeyStart)
|
||||
return lexBareKey
|
||||
}
|
||||
}
|
||||
|
||||
// lexBareKey consumes the text of a bare key. Assumes that the first character
|
||||
// (which is not whitespace) has not yet been consumed.
|
||||
func lexBareKey(lx *lexer) stateFn {
|
||||
switch r := lx.next(); {
|
||||
case isBareKeyChar(r):
|
||||
return lexBareKey
|
||||
case isWhitespace(r):
|
||||
lx.emitTrim(itemText)
|
||||
return lexKeyEnd
|
||||
case r == keySep:
|
||||
lx.backup()
|
||||
lx.emitTrim(itemText)
|
||||
return lexKeyEnd
|
||||
default:
|
||||
return lx.errorf("Bare keys cannot contain %q.", r)
|
||||
}
|
||||
}
|
||||
|
||||
// lexKeyEnd consumes the end of a key and trims whitespace (up to the key
|
||||
// separator).
|
||||
func lexKeyEnd(lx *lexer) stateFn {
|
||||
switch r := lx.next(); {
|
||||
case r == keySep:
|
||||
return lexSkip(lx, lexValue)
|
||||
case isWhitespace(r):
|
||||
return lexSkip(lx, lexKeyEnd)
|
||||
default:
|
||||
return lx.errorf("Expected key separator %q, but got %q instead.",
|
||||
keySep, r)
|
||||
}
|
||||
}
|
||||
|
||||
// lexValue starts the consumption of a value anywhere a value is expected.
|
||||
// lexValue will ignore whitespace.
|
||||
// After a value is lexed, the last state on the next is popped and returned.
|
||||
func lexValue(lx *lexer) stateFn {
|
||||
// We allow whitespace to precede a value, but NOT new lines.
|
||||
// In array syntax, the array states are responsible for ignoring new
|
||||
// lines.
|
||||
r := lx.next()
|
||||
if isWhitespace(r) {
|
||||
return lexSkip(lx, lexValue)
|
||||
}
|
||||
|
||||
switch {
|
||||
case r == arrayStart:
|
||||
lx.ignore()
|
||||
lx.emit(itemArray)
|
||||
return lexArrayValue
|
||||
case r == stringStart:
|
||||
if lx.accept(stringStart) {
|
||||
if lx.accept(stringStart) {
|
||||
lx.ignore() // Ignore """
|
||||
return lexMultilineString
|
||||
}
|
||||
lx.backup()
|
||||
}
|
||||
lx.ignore() // ignore the '"'
|
||||
return lexString
|
||||
case r == rawStringStart:
|
||||
if lx.accept(rawStringStart) {
|
||||
if lx.accept(rawStringStart) {
|
||||
lx.ignore() // Ignore """
|
||||
return lexMultilineRawString
|
||||
}
|
||||
lx.backup()
|
||||
}
|
||||
lx.ignore() // ignore the "'"
|
||||
return lexRawString
|
||||
case r == 't':
|
||||
return lexTrue
|
||||
case r == 'f':
|
||||
return lexFalse
|
||||
case r == '-':
|
||||
return lexNumberStart
|
||||
case isDigit(r):
|
||||
lx.backup() // avoid an extra state and use the same as above
|
||||
return lexNumberOrDateStart
|
||||
case r == '.': // special error case, be kind to users
|
||||
return lx.errorf("Floats must start with a digit, not '.'.")
|
||||
}
|
||||
return lx.errorf("Expected value but found %q instead.", r)
|
||||
}
|
||||
|
||||
// lexArrayValue consumes one value in an array. It assumes that '[' or ','
|
||||
// have already been consumed. All whitespace and new lines are ignored.
|
||||
func lexArrayValue(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch {
|
||||
case isWhitespace(r) || isNL(r):
|
||||
return lexSkip(lx, lexArrayValue)
|
||||
case r == commentStart:
|
||||
lx.push(lexArrayValue)
|
||||
return lexCommentStart
|
||||
case r == arrayValTerm:
|
||||
return lx.errorf("Unexpected array value terminator %q.",
|
||||
arrayValTerm)
|
||||
case r == arrayEnd:
|
||||
return lexArrayEnd
|
||||
}
|
||||
|
||||
lx.backup()
|
||||
lx.push(lexArrayValueEnd)
|
||||
return lexValue
|
||||
}
|
||||
|
||||
// lexArrayValueEnd consumes the cruft between values of an array. Namely,
|
||||
// it ignores whitespace and expects either a ',' or a ']'.
|
||||
func lexArrayValueEnd(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch {
|
||||
case isWhitespace(r) || isNL(r):
|
||||
return lexSkip(lx, lexArrayValueEnd)
|
||||
case r == commentStart:
|
||||
lx.push(lexArrayValueEnd)
|
||||
return lexCommentStart
|
||||
case r == arrayValTerm:
|
||||
lx.ignore()
|
||||
return lexArrayValue // move on to the next value
|
||||
case r == arrayEnd:
|
||||
return lexArrayEnd
|
||||
}
|
||||
return lx.errorf("Expected an array value terminator %q or an array "+
|
||||
"terminator %q, but got %q instead.", arrayValTerm, arrayEnd, r)
|
||||
}
|
||||
|
||||
// lexArrayEnd finishes the lexing of an array. It assumes that a ']' has
|
||||
// just been consumed.
|
||||
func lexArrayEnd(lx *lexer) stateFn {
|
||||
lx.ignore()
|
||||
lx.emit(itemArrayEnd)
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexString consumes the inner contents of a string. It assumes that the
|
||||
// beginning '"' has already been consumed and ignored.
|
||||
func lexString(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch {
|
||||
case isNL(r):
|
||||
return lx.errorf("Strings cannot contain new lines.")
|
||||
case r == '\\':
|
||||
lx.push(lexString)
|
||||
return lexStringEscape
|
||||
case r == stringEnd:
|
||||
lx.backup()
|
||||
lx.emit(itemString)
|
||||
lx.next()
|
||||
lx.ignore()
|
||||
return lx.pop()
|
||||
}
|
||||
return lexString
|
||||
}
|
||||
|
||||
// lexMultilineString consumes the inner contents of a string. It assumes that
|
||||
// the beginning '"""' has already been consumed and ignored.
|
||||
func lexMultilineString(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch {
|
||||
case r == '\\':
|
||||
return lexMultilineStringEscape
|
||||
case r == stringEnd:
|
||||
if lx.accept(stringEnd) {
|
||||
if lx.accept(stringEnd) {
|
||||
lx.backup()
|
||||
lx.backup()
|
||||
lx.backup()
|
||||
lx.emit(itemMultilineString)
|
||||
lx.next()
|
||||
lx.next()
|
||||
lx.next()
|
||||
lx.ignore()
|
||||
return lx.pop()
|
||||
}
|
||||
lx.backup()
|
||||
}
|
||||
}
|
||||
return lexMultilineString
|
||||
}
|
||||
|
||||
// lexRawString consumes a raw string. Nothing can be escaped in such a string.
|
||||
// It assumes that the beginning "'" has already been consumed and ignored.
|
||||
func lexRawString(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch {
|
||||
case isNL(r):
|
||||
return lx.errorf("Strings cannot contain new lines.")
|
||||
case r == rawStringEnd:
|
||||
lx.backup()
|
||||
lx.emit(itemRawString)
|
||||
lx.next()
|
||||
lx.ignore()
|
||||
return lx.pop()
|
||||
}
|
||||
return lexRawString
|
||||
}
|
||||
|
||||
// lexMultilineRawString consumes a raw string. Nothing can be escaped in such
|
||||
// a string. It assumes that the beginning "'" has already been consumed and
|
||||
// ignored.
|
||||
func lexMultilineRawString(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch {
|
||||
case r == rawStringEnd:
|
||||
if lx.accept(rawStringEnd) {
|
||||
if lx.accept(rawStringEnd) {
|
||||
lx.backup()
|
||||
lx.backup()
|
||||
lx.backup()
|
||||
lx.emit(itemRawMultilineString)
|
||||
lx.next()
|
||||
lx.next()
|
||||
lx.next()
|
||||
lx.ignore()
|
||||
return lx.pop()
|
||||
}
|
||||
lx.backup()
|
||||
}
|
||||
}
|
||||
return lexMultilineRawString
|
||||
}
|
||||
|
||||
// lexMultilineStringEscape consumes an escaped character. It assumes that the
|
||||
// preceding '\\' has already been consumed.
|
||||
func lexMultilineStringEscape(lx *lexer) stateFn {
|
||||
// Handle the special case first:
|
||||
if isNL(lx.next()) {
|
||||
lx.next()
|
||||
return lexMultilineString
|
||||
} else {
|
||||
lx.backup()
|
||||
lx.push(lexMultilineString)
|
||||
return lexStringEscape(lx)
|
||||
}
|
||||
}
|
||||
|
||||
func lexStringEscape(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch r {
|
||||
case 'b':
|
||||
fallthrough
|
||||
case 't':
|
||||
fallthrough
|
||||
case 'n':
|
||||
fallthrough
|
||||
case 'f':
|
||||
fallthrough
|
||||
case 'r':
|
||||
fallthrough
|
||||
case '"':
|
||||
fallthrough
|
||||
case '\\':
|
||||
return lx.pop()
|
||||
case 'u':
|
||||
return lexShortUnicodeEscape
|
||||
case 'U':
|
||||
return lexLongUnicodeEscape
|
||||
}
|
||||
return lx.errorf("Invalid escape character %q. Only the following "+
|
||||
"escape characters are allowed: "+
|
||||
"\\b, \\t, \\n, \\f, \\r, \\\", \\/, \\\\, "+
|
||||
"\\uXXXX and \\UXXXXXXXX.", r)
|
||||
}
|
||||
|
||||
func lexShortUnicodeEscape(lx *lexer) stateFn {
|
||||
var r rune
|
||||
for i := 0; i < 4; i++ {
|
||||
r = lx.next()
|
||||
if !isHexadecimal(r) {
|
||||
return lx.errorf("Expected four hexadecimal digits after '\\u', "+
|
||||
"but got '%s' instead.", lx.current())
|
||||
}
|
||||
}
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
func lexLongUnicodeEscape(lx *lexer) stateFn {
|
||||
var r rune
|
||||
for i := 0; i < 8; i++ {
|
||||
r = lx.next()
|
||||
if !isHexadecimal(r) {
|
||||
return lx.errorf("Expected eight hexadecimal digits after '\\U', "+
|
||||
"but got '%s' instead.", lx.current())
|
||||
}
|
||||
}
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexNumberOrDateStart consumes either a (positive) integer, float or
|
||||
// datetime. It assumes that NO negative sign has been consumed.
|
||||
func lexNumberOrDateStart(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if !isDigit(r) {
|
||||
if r == '.' {
|
||||
return lx.errorf("Floats must start with a digit, not '.'.")
|
||||
} else {
|
||||
return lx.errorf("Expected a digit but got %q.", r)
|
||||
}
|
||||
}
|
||||
return lexNumberOrDate
|
||||
}
|
||||
|
||||
// lexNumberOrDate consumes either a (positive) integer, float or datetime.
|
||||
func lexNumberOrDate(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch {
|
||||
case r == '-':
|
||||
if lx.pos-lx.start != 5 {
|
||||
return lx.errorf("All ISO8601 dates must be in full Zulu form.")
|
||||
}
|
||||
return lexDateAfterYear
|
||||
case isDigit(r):
|
||||
return lexNumberOrDate
|
||||
case r == '.':
|
||||
return lexFloatStart
|
||||
}
|
||||
|
||||
lx.backup()
|
||||
lx.emit(itemInteger)
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexDateAfterYear consumes a full Zulu Datetime in ISO8601 format.
|
||||
// It assumes that "YYYY-" has already been consumed.
|
||||
func lexDateAfterYear(lx *lexer) stateFn {
|
||||
formats := []rune{
|
||||
// digits are '0'.
|
||||
// everything else is direct equality.
|
||||
'0', '0', '-', '0', '0',
|
||||
'T',
|
||||
'0', '0', ':', '0', '0', ':', '0', '0',
|
||||
'Z',
|
||||
}
|
||||
for _, f := range formats {
|
||||
r := lx.next()
|
||||
if f == '0' {
|
||||
if !isDigit(r) {
|
||||
return lx.errorf("Expected digit in ISO8601 datetime, "+
|
||||
"but found %q instead.", r)
|
||||
}
|
||||
} else if f != r {
|
||||
return lx.errorf("Expected %q in ISO8601 datetime, "+
|
||||
"but found %q instead.", f, r)
|
||||
}
|
||||
}
|
||||
lx.emit(itemDatetime)
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexNumberStart consumes either an integer or a float. It assumes that
|
||||
// a negative sign has already been read, but that *no* digits have been
|
||||
// consumed. lexNumberStart will move to the appropriate integer or float
|
||||
// states.
|
||||
func lexNumberStart(lx *lexer) stateFn {
|
||||
// we MUST see a digit. Even floats have to start with a digit.
|
||||
r := lx.next()
|
||||
if !isDigit(r) {
|
||||
if r == '.' {
|
||||
return lx.errorf("Floats must start with a digit, not '.'.")
|
||||
} else {
|
||||
return lx.errorf("Expected a digit but got %q.", r)
|
||||
}
|
||||
}
|
||||
return lexNumber
|
||||
}
|
||||
|
||||
// lexNumber consumes an integer or a float after seeing the first digit.
|
||||
func lexNumber(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
switch {
|
||||
case isDigit(r):
|
||||
return lexNumber
|
||||
case r == '.':
|
||||
return lexFloatStart
|
||||
}
|
||||
|
||||
lx.backup()
|
||||
lx.emit(itemInteger)
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexFloatStart starts the consumption of digits of a float after a '.'.
|
||||
// Namely, at least one digit is required.
|
||||
func lexFloatStart(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if !isDigit(r) {
|
||||
return lx.errorf("Floats must have a digit after the '.', but got "+
|
||||
"%q instead.", r)
|
||||
}
|
||||
return lexFloat
|
||||
}
|
||||
|
||||
// lexFloat consumes the digits of a float after a '.'.
|
||||
// Assumes that one digit has been consumed after a '.' already.
|
||||
func lexFloat(lx *lexer) stateFn {
|
||||
r := lx.next()
|
||||
if isDigit(r) {
|
||||
return lexFloat
|
||||
}
|
||||
|
||||
lx.backup()
|
||||
lx.emit(itemFloat)
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexConst consumes the s[1:] in s. It assumes that s[0] has already been
|
||||
// consumed.
|
||||
func lexConst(lx *lexer, s string) stateFn {
|
||||
for i := range s[1:] {
|
||||
if r := lx.next(); r != rune(s[i+1]) {
|
||||
return lx.errorf("Expected %q, but found %q instead.", s[:i+1],
|
||||
s[:i]+string(r))
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// lexTrue consumes the "rue" in "true". It assumes that 't' has already
|
||||
// been consumed.
|
||||
func lexTrue(lx *lexer) stateFn {
|
||||
if fn := lexConst(lx, "true"); fn != nil {
|
||||
return fn
|
||||
}
|
||||
lx.emit(itemBool)
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexFalse consumes the "alse" in "false". It assumes that 'f' has already
|
||||
// been consumed.
|
||||
func lexFalse(lx *lexer) stateFn {
|
||||
if fn := lexConst(lx, "false"); fn != nil {
|
||||
return fn
|
||||
}
|
||||
lx.emit(itemBool)
|
||||
return lx.pop()
|
||||
}
|
||||
|
||||
// lexCommentStart begins the lexing of a comment. It will emit
|
||||
// itemCommentStart and consume no characters, passing control to lexComment.
|
||||
func lexCommentStart(lx *lexer) stateFn {
|
||||
lx.ignore()
|
||||
lx.emit(itemCommentStart)
|
||||
return lexComment
|
||||
}
|
||||
|
||||
// lexComment lexes an entire comment. It assumes that '#' has been consumed.
|
||||
// It will consume *up to* the first new line character, and pass control
|
||||
// back to the last state on the stack.
|
||||
func lexComment(lx *lexer) stateFn {
|
||||
r := lx.peek()
|
||||
if isNL(r) || r == eof {
|
||||
lx.emit(itemText)
|
||||
return lx.pop()
|
||||
}
|
||||
lx.next()
|
||||
return lexComment
|
||||
}
|
||||
|
||||
// lexSkip ignores all slurped input and moves on to the next state.
|
||||
func lexSkip(lx *lexer, nextState stateFn) stateFn {
|
||||
return func(lx *lexer) stateFn {
|
||||
lx.ignore()
|
||||
return nextState
|
||||
}
|
||||
}
|
||||
|
||||
// isWhitespace returns true if `r` is a whitespace character according
|
||||
// to the spec.
|
||||
func isWhitespace(r rune) bool {
|
||||
return r == '\t' || r == ' '
|
||||
}
|
||||
|
||||
func isNL(r rune) bool {
|
||||
return r == '\n' || r == '\r'
|
||||
}
|
||||
|
||||
func isDigit(r rune) bool {
|
||||
return r >= '0' && r <= '9'
|
||||
}
|
||||
|
||||
func isHexadecimal(r rune) bool {
|
||||
return (r >= '0' && r <= '9') ||
|
||||
(r >= 'a' && r <= 'f') ||
|
||||
(r >= 'A' && r <= 'F')
|
||||
}
|
||||
|
||||
func isBareKeyChar(r rune) bool {
|
||||
return (r >= 'A' && r <= 'Z') ||
|
||||
(r >= 'a' && r <= 'z') ||
|
||||
(r >= '0' && r <= '9') ||
|
||||
r == '_' ||
|
||||
r == '-'
|
||||
}
|
||||
|
||||
func (itype itemType) String() string {
|
||||
switch itype {
|
||||
case itemError:
|
||||
return "Error"
|
||||
case itemNIL:
|
||||
return "NIL"
|
||||
case itemEOF:
|
||||
return "EOF"
|
||||
case itemText:
|
||||
return "Text"
|
||||
case itemString:
|
||||
return "String"
|
||||
case itemRawString:
|
||||
return "String"
|
||||
case itemMultilineString:
|
||||
return "String"
|
||||
case itemRawMultilineString:
|
||||
return "String"
|
||||
case itemBool:
|
||||
return "Bool"
|
||||
case itemInteger:
|
||||
return "Integer"
|
||||
case itemFloat:
|
||||
return "Float"
|
||||
case itemDatetime:
|
||||
return "DateTime"
|
||||
case itemTableStart:
|
||||
return "TableStart"
|
||||
case itemTableEnd:
|
||||
return "TableEnd"
|
||||
case itemKeyStart:
|
||||
return "KeyStart"
|
||||
case itemArray:
|
||||
return "Array"
|
||||
case itemArrayEnd:
|
||||
return "ArrayEnd"
|
||||
case itemCommentStart:
|
||||
return "CommentStart"
|
||||
}
|
||||
panic(fmt.Sprintf("BUG: Unknown type '%d'.", int(itype)))
|
||||
}
|
||||
|
||||
func (item item) String() string {
|
||||
return fmt.Sprintf("(%s, %s)", item.typ.String(), item.val)
|
||||
}
|
||||
498
Godeps/_workspace/src/github.com/BurntSushi/toml/parse.go
generated
vendored
Normal file
498
Godeps/_workspace/src/github.com/BurntSushi/toml/parse.go
generated
vendored
Normal file
@@ -0,0 +1,498 @@
|
||||
package toml
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"log"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"unicode"
|
||||
"unicode/utf8"
|
||||
)
|
||||
|
||||
type parser struct {
|
||||
mapping map[string]interface{}
|
||||
types map[string]tomlType
|
||||
lx *lexer
|
||||
|
||||
// A list of keys in the order that they appear in the TOML data.
|
||||
ordered []Key
|
||||
|
||||
// the full key for the current hash in scope
|
||||
context Key
|
||||
|
||||
// the base key name for everything except hashes
|
||||
currentKey string
|
||||
|
||||
// rough approximation of line number
|
||||
approxLine int
|
||||
|
||||
// A map of 'key.group.names' to whether they were created implicitly.
|
||||
implicits map[string]bool
|
||||
}
|
||||
|
||||
type parseError string
|
||||
|
||||
func (pe parseError) Error() string {
|
||||
return string(pe)
|
||||
}
|
||||
|
||||
func parse(data string) (p *parser, err error) {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
var ok bool
|
||||
if err, ok = r.(parseError); ok {
|
||||
return
|
||||
}
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
|
||||
p = &parser{
|
||||
mapping: make(map[string]interface{}),
|
||||
types: make(map[string]tomlType),
|
||||
lx: lex(data),
|
||||
ordered: make([]Key, 0),
|
||||
implicits: make(map[string]bool),
|
||||
}
|
||||
for {
|
||||
item := p.next()
|
||||
if item.typ == itemEOF {
|
||||
break
|
||||
}
|
||||
p.topLevel(item)
|
||||
}
|
||||
|
||||
return p, nil
|
||||
}
|
||||
|
||||
func (p *parser) panicf(format string, v ...interface{}) {
|
||||
msg := fmt.Sprintf("Near line %d (last key parsed '%s'): %s",
|
||||
p.approxLine, p.current(), fmt.Sprintf(format, v...))
|
||||
panic(parseError(msg))
|
||||
}
|
||||
|
||||
func (p *parser) next() item {
|
||||
it := p.lx.nextItem()
|
||||
if it.typ == itemError {
|
||||
p.panicf("%s", it.val)
|
||||
}
|
||||
return it
|
||||
}
|
||||
|
||||
func (p *parser) bug(format string, v ...interface{}) {
|
||||
log.Fatalf("BUG: %s\n\n", fmt.Sprintf(format, v...))
|
||||
}
|
||||
|
||||
func (p *parser) expect(typ itemType) item {
|
||||
it := p.next()
|
||||
p.assertEqual(typ, it.typ)
|
||||
return it
|
||||
}
|
||||
|
||||
func (p *parser) assertEqual(expected, got itemType) {
|
||||
if expected != got {
|
||||
p.bug("Expected '%s' but got '%s'.", expected, got)
|
||||
}
|
||||
}
|
||||
|
||||
func (p *parser) topLevel(item item) {
|
||||
switch item.typ {
|
||||
case itemCommentStart:
|
||||
p.approxLine = item.line
|
||||
p.expect(itemText)
|
||||
case itemTableStart:
|
||||
kg := p.next()
|
||||
p.approxLine = kg.line
|
||||
|
||||
var key Key
|
||||
for ; kg.typ != itemTableEnd && kg.typ != itemEOF; kg = p.next() {
|
||||
key = append(key, p.keyString(kg))
|
||||
}
|
||||
p.assertEqual(itemTableEnd, kg.typ)
|
||||
|
||||
p.establishContext(key, false)
|
||||
p.setType("", tomlHash)
|
||||
p.ordered = append(p.ordered, key)
|
||||
case itemArrayTableStart:
|
||||
kg := p.next()
|
||||
p.approxLine = kg.line
|
||||
|
||||
var key Key
|
||||
for ; kg.typ != itemArrayTableEnd && kg.typ != itemEOF; kg = p.next() {
|
||||
key = append(key, p.keyString(kg))
|
||||
}
|
||||
p.assertEqual(itemArrayTableEnd, kg.typ)
|
||||
|
||||
p.establishContext(key, true)
|
||||
p.setType("", tomlArrayHash)
|
||||
p.ordered = append(p.ordered, key)
|
||||
case itemKeyStart:
|
||||
kname := p.next()
|
||||
p.approxLine = kname.line
|
||||
p.currentKey = p.keyString(kname)
|
||||
|
||||
val, typ := p.value(p.next())
|
||||
p.setValue(p.currentKey, val)
|
||||
p.setType(p.currentKey, typ)
|
||||
p.ordered = append(p.ordered, p.context.add(p.currentKey))
|
||||
p.currentKey = ""
|
||||
default:
|
||||
p.bug("Unexpected type at top level: %s", item.typ)
|
||||
}
|
||||
}
|
||||
|
||||
// Gets a string for a key (or part of a key in a table name).
|
||||
func (p *parser) keyString(it item) string {
|
||||
switch it.typ {
|
||||
case itemText:
|
||||
return it.val
|
||||
case itemString, itemMultilineString,
|
||||
itemRawString, itemRawMultilineString:
|
||||
s, _ := p.value(it)
|
||||
return s.(string)
|
||||
default:
|
||||
p.bug("Unexpected key type: %s", it.typ)
|
||||
panic("unreachable")
|
||||
}
|
||||
}
|
||||
|
||||
// value translates an expected value from the lexer into a Go value wrapped
|
||||
// as an empty interface.
|
||||
func (p *parser) value(it item) (interface{}, tomlType) {
|
||||
switch it.typ {
|
||||
case itemString:
|
||||
return p.replaceEscapes(it.val), p.typeOfPrimitive(it)
|
||||
case itemMultilineString:
|
||||
trimmed := stripFirstNewline(stripEscapedWhitespace(it.val))
|
||||
return p.replaceEscapes(trimmed), p.typeOfPrimitive(it)
|
||||
case itemRawString:
|
||||
return it.val, p.typeOfPrimitive(it)
|
||||
case itemRawMultilineString:
|
||||
return stripFirstNewline(it.val), p.typeOfPrimitive(it)
|
||||
case itemBool:
|
||||
switch it.val {
|
||||
case "true":
|
||||
return true, p.typeOfPrimitive(it)
|
||||
case "false":
|
||||
return false, p.typeOfPrimitive(it)
|
||||
}
|
||||
p.bug("Expected boolean value, but got '%s'.", it.val)
|
||||
case itemInteger:
|
||||
num, err := strconv.ParseInt(it.val, 10, 64)
|
||||
if err != nil {
|
||||
// See comment below for floats describing why we make a
|
||||
// distinction between a bug and a user error.
|
||||
if e, ok := err.(*strconv.NumError); ok &&
|
||||
e.Err == strconv.ErrRange {
|
||||
|
||||
p.panicf("Integer '%s' is out of the range of 64-bit "+
|
||||
"signed integers.", it.val)
|
||||
} else {
|
||||
p.bug("Expected integer value, but got '%s'.", it.val)
|
||||
}
|
||||
}
|
||||
return num, p.typeOfPrimitive(it)
|
||||
case itemFloat:
|
||||
num, err := strconv.ParseFloat(it.val, 64)
|
||||
if err != nil {
|
||||
// Distinguish float values. Normally, it'd be a bug if the lexer
|
||||
// provides an invalid float, but it's possible that the float is
|
||||
// out of range of valid values (which the lexer cannot determine).
|
||||
// So mark the former as a bug but the latter as a legitimate user
|
||||
// error.
|
||||
//
|
||||
// This is also true for integers.
|
||||
if e, ok := err.(*strconv.NumError); ok &&
|
||||
e.Err == strconv.ErrRange {
|
||||
|
||||
p.panicf("Float '%s' is out of the range of 64-bit "+
|
||||
"IEEE-754 floating-point numbers.", it.val)
|
||||
} else {
|
||||
p.bug("Expected float value, but got '%s'.", it.val)
|
||||
}
|
||||
}
|
||||
return num, p.typeOfPrimitive(it)
|
||||
case itemDatetime:
|
||||
t, err := time.Parse("2006-01-02T15:04:05Z", it.val)
|
||||
if err != nil {
|
||||
p.bug("Expected Zulu formatted DateTime, but got '%s'.", it.val)
|
||||
}
|
||||
return t, p.typeOfPrimitive(it)
|
||||
case itemArray:
|
||||
array := make([]interface{}, 0)
|
||||
types := make([]tomlType, 0)
|
||||
|
||||
for it = p.next(); it.typ != itemArrayEnd; it = p.next() {
|
||||
if it.typ == itemCommentStart {
|
||||
p.expect(itemText)
|
||||
continue
|
||||
}
|
||||
|
||||
val, typ := p.value(it)
|
||||
array = append(array, val)
|
||||
types = append(types, typ)
|
||||
}
|
||||
return array, p.typeOfArray(types)
|
||||
}
|
||||
p.bug("Unexpected value type: %s", it.typ)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// establishContext sets the current context of the parser,
|
||||
// where the context is either a hash or an array of hashes. Which one is
|
||||
// set depends on the value of the `array` parameter.
|
||||
//
|
||||
// Establishing the context also makes sure that the key isn't a duplicate, and
|
||||
// will create implicit hashes automatically.
|
||||
func (p *parser) establishContext(key Key, array bool) {
|
||||
var ok bool
|
||||
|
||||
// Always start at the top level and drill down for our context.
|
||||
hashContext := p.mapping
|
||||
keyContext := make(Key, 0)
|
||||
|
||||
// We only need implicit hashes for key[0:-1]
|
||||
for _, k := range key[0 : len(key)-1] {
|
||||
_, ok = hashContext[k]
|
||||
keyContext = append(keyContext, k)
|
||||
|
||||
// No key? Make an implicit hash and move on.
|
||||
if !ok {
|
||||
p.addImplicit(keyContext)
|
||||
hashContext[k] = make(map[string]interface{})
|
||||
}
|
||||
|
||||
// If the hash context is actually an array of tables, then set
|
||||
// the hash context to the last element in that array.
|
||||
//
|
||||
// Otherwise, it better be a table, since this MUST be a key group (by
|
||||
// virtue of it not being the last element in a key).
|
||||
switch t := hashContext[k].(type) {
|
||||
case []map[string]interface{}:
|
||||
hashContext = t[len(t)-1]
|
||||
case map[string]interface{}:
|
||||
hashContext = t
|
||||
default:
|
||||
p.panicf("Key '%s' was already created as a hash.", keyContext)
|
||||
}
|
||||
}
|
||||
|
||||
p.context = keyContext
|
||||
if array {
|
||||
// If this is the first element for this array, then allocate a new
|
||||
// list of tables for it.
|
||||
k := key[len(key)-1]
|
||||
if _, ok := hashContext[k]; !ok {
|
||||
hashContext[k] = make([]map[string]interface{}, 0, 5)
|
||||
}
|
||||
|
||||
// Add a new table. But make sure the key hasn't already been used
|
||||
// for something else.
|
||||
if hash, ok := hashContext[k].([]map[string]interface{}); ok {
|
||||
hashContext[k] = append(hash, make(map[string]interface{}))
|
||||
} else {
|
||||
p.panicf("Key '%s' was already created and cannot be used as "+
|
||||
"an array.", keyContext)
|
||||
}
|
||||
} else {
|
||||
p.setValue(key[len(key)-1], make(map[string]interface{}))
|
||||
}
|
||||
p.context = append(p.context, key[len(key)-1])
|
||||
}
|
||||
|
||||
// setValue sets the given key to the given value in the current context.
|
||||
// It will make sure that the key hasn't already been defined, account for
|
||||
// implicit key groups.
|
||||
func (p *parser) setValue(key string, value interface{}) {
|
||||
var tmpHash interface{}
|
||||
var ok bool
|
||||
|
||||
hash := p.mapping
|
||||
keyContext := make(Key, 0)
|
||||
for _, k := range p.context {
|
||||
keyContext = append(keyContext, k)
|
||||
if tmpHash, ok = hash[k]; !ok {
|
||||
p.bug("Context for key '%s' has not been established.", keyContext)
|
||||
}
|
||||
switch t := tmpHash.(type) {
|
||||
case []map[string]interface{}:
|
||||
// The context is a table of hashes. Pick the most recent table
|
||||
// defined as the current hash.
|
||||
hash = t[len(t)-1]
|
||||
case map[string]interface{}:
|
||||
hash = t
|
||||
default:
|
||||
p.bug("Expected hash to have type 'map[string]interface{}', but "+
|
||||
"it has '%T' instead.", tmpHash)
|
||||
}
|
||||
}
|
||||
keyContext = append(keyContext, key)
|
||||
|
||||
if _, ok := hash[key]; ok {
|
||||
// Typically, if the given key has already been set, then we have
|
||||
// to raise an error since duplicate keys are disallowed. However,
|
||||
// it's possible that a key was previously defined implicitly. In this
|
||||
// case, it is allowed to be redefined concretely. (See the
|
||||
// `tests/valid/implicit-and-explicit-after.toml` test in `toml-test`.)
|
||||
//
|
||||
// But we have to make sure to stop marking it as an implicit. (So that
|
||||
// another redefinition provokes an error.)
|
||||
//
|
||||
// Note that since it has already been defined (as a hash), we don't
|
||||
// want to overwrite it. So our business is done.
|
||||
if p.isImplicit(keyContext) {
|
||||
p.removeImplicit(keyContext)
|
||||
return
|
||||
}
|
||||
|
||||
// Otherwise, we have a concrete key trying to override a previous
|
||||
// key, which is *always* wrong.
|
||||
p.panicf("Key '%s' has already been defined.", keyContext)
|
||||
}
|
||||
hash[key] = value
|
||||
}
|
||||
|
||||
// setType sets the type of a particular value at a given key.
|
||||
// It should be called immediately AFTER setValue.
|
||||
//
|
||||
// Note that if `key` is empty, then the type given will be applied to the
|
||||
// current context (which is either a table or an array of tables).
|
||||
func (p *parser) setType(key string, typ tomlType) {
|
||||
keyContext := make(Key, 0, len(p.context)+1)
|
||||
for _, k := range p.context {
|
||||
keyContext = append(keyContext, k)
|
||||
}
|
||||
if len(key) > 0 { // allow type setting for hashes
|
||||
keyContext = append(keyContext, key)
|
||||
}
|
||||
p.types[keyContext.String()] = typ
|
||||
}
|
||||
|
||||
// addImplicit sets the given Key as having been created implicitly.
|
||||
func (p *parser) addImplicit(key Key) {
|
||||
p.implicits[key.String()] = true
|
||||
}
|
||||
|
||||
// removeImplicit stops tagging the given key as having been implicitly
|
||||
// created.
|
||||
func (p *parser) removeImplicit(key Key) {
|
||||
p.implicits[key.String()] = false
|
||||
}
|
||||
|
||||
// isImplicit returns true if the key group pointed to by the key was created
|
||||
// implicitly.
|
||||
func (p *parser) isImplicit(key Key) bool {
|
||||
return p.implicits[key.String()]
|
||||
}
|
||||
|
||||
// current returns the full key name of the current context.
|
||||
func (p *parser) current() string {
|
||||
if len(p.currentKey) == 0 {
|
||||
return p.context.String()
|
||||
}
|
||||
if len(p.context) == 0 {
|
||||
return p.currentKey
|
||||
}
|
||||
return fmt.Sprintf("%s.%s", p.context, p.currentKey)
|
||||
}
|
||||
|
||||
func stripFirstNewline(s string) string {
|
||||
if len(s) == 0 || s[0] != '\n' {
|
||||
return s
|
||||
}
|
||||
return s[1:len(s)]
|
||||
}
|
||||
|
||||
func stripEscapedWhitespace(s string) string {
|
||||
esc := strings.Split(s, "\\\n")
|
||||
if len(esc) > 1 {
|
||||
for i := 1; i < len(esc); i++ {
|
||||
esc[i] = strings.TrimLeftFunc(esc[i], unicode.IsSpace)
|
||||
}
|
||||
}
|
||||
return strings.Join(esc, "")
|
||||
}
|
||||
|
||||
func (p *parser) replaceEscapes(str string) string {
|
||||
var replaced []rune
|
||||
s := []byte(str)
|
||||
r := 0
|
||||
for r < len(s) {
|
||||
if s[r] != '\\' {
|
||||
c, size := utf8.DecodeRune(s[r:])
|
||||
r += size
|
||||
replaced = append(replaced, c)
|
||||
continue
|
||||
}
|
||||
r += 1
|
||||
if r >= len(s) {
|
||||
p.bug("Escape sequence at end of string.")
|
||||
return ""
|
||||
}
|
||||
switch s[r] {
|
||||
default:
|
||||
p.bug("Expected valid escape code after \\, but got %q.", s[r])
|
||||
return ""
|
||||
case 'b':
|
||||
replaced = append(replaced, rune(0x0008))
|
||||
r += 1
|
||||
case 't':
|
||||
replaced = append(replaced, rune(0x0009))
|
||||
r += 1
|
||||
case 'n':
|
||||
replaced = append(replaced, rune(0x000A))
|
||||
r += 1
|
||||
case 'f':
|
||||
replaced = append(replaced, rune(0x000C))
|
||||
r += 1
|
||||
case 'r':
|
||||
replaced = append(replaced, rune(0x000D))
|
||||
r += 1
|
||||
case '"':
|
||||
replaced = append(replaced, rune(0x0022))
|
||||
r += 1
|
||||
case '\\':
|
||||
replaced = append(replaced, rune(0x005C))
|
||||
r += 1
|
||||
case 'u':
|
||||
// At this point, we know we have a Unicode escape of the form
|
||||
// `uXXXX` at [r, r+5). (Because the lexer guarantees this
|
||||
// for us.)
|
||||
escaped := p.asciiEscapeToUnicode(s[r+1 : r+5])
|
||||
replaced = append(replaced, escaped)
|
||||
r += 5
|
||||
case 'U':
|
||||
// At this point, we know we have a Unicode escape of the form
|
||||
// `uXXXX` at [r, r+9). (Because the lexer guarantees this
|
||||
// for us.)
|
||||
escaped := p.asciiEscapeToUnicode(s[r+1 : r+9])
|
||||
replaced = append(replaced, escaped)
|
||||
r += 9
|
||||
}
|
||||
}
|
||||
return string(replaced)
|
||||
}
|
||||
|
||||
func (p *parser) asciiEscapeToUnicode(bs []byte) rune {
|
||||
s := string(bs)
|
||||
hex, err := strconv.ParseUint(strings.ToLower(s), 16, 32)
|
||||
if err != nil {
|
||||
p.bug("Could not parse '%s' as a hexadecimal number, but the "+
|
||||
"lexer claims it's OK: %s", s, err)
|
||||
}
|
||||
|
||||
// BUG(burntsushi)
|
||||
// I honestly don't understand how this works. I can't seem
|
||||
// to find a way to make this fail. I figured this would fail on invalid
|
||||
// UTF-8 characters like U+DCFF, but it doesn't.
|
||||
if !utf8.ValidString(string(rune(hex))) {
|
||||
p.panicf("Escaped character '\\u%s' is not valid UTF-8.", s)
|
||||
}
|
||||
return rune(hex)
|
||||
}
|
||||
|
||||
func isStringType(ty itemType) bool {
|
||||
return ty == itemString || ty == itemMultilineString ||
|
||||
ty == itemRawString || ty == itemRawMultilineString
|
||||
}
|
||||
1
Godeps/_workspace/src/github.com/BurntSushi/toml/session.vim
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/BurntSushi/toml/session.vim
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
au BufWritePost *.go silent!make tags > /dev/null 2>&1
|
||||
91
Godeps/_workspace/src/github.com/BurntSushi/toml/type_check.go
generated
vendored
Normal file
91
Godeps/_workspace/src/github.com/BurntSushi/toml/type_check.go
generated
vendored
Normal file
@@ -0,0 +1,91 @@
|
||||
package toml
|
||||
|
||||
// tomlType represents any Go type that corresponds to a TOML type.
|
||||
// While the first draft of the TOML spec has a simplistic type system that
|
||||
// probably doesn't need this level of sophistication, we seem to be militating
|
||||
// toward adding real composite types.
|
||||
type tomlType interface {
|
||||
typeString() string
|
||||
}
|
||||
|
||||
// typeEqual accepts any two types and returns true if they are equal.
|
||||
func typeEqual(t1, t2 tomlType) bool {
|
||||
if t1 == nil || t2 == nil {
|
||||
return false
|
||||
}
|
||||
return t1.typeString() == t2.typeString()
|
||||
}
|
||||
|
||||
func typeIsHash(t tomlType) bool {
|
||||
return typeEqual(t, tomlHash) || typeEqual(t, tomlArrayHash)
|
||||
}
|
||||
|
||||
type tomlBaseType string
|
||||
|
||||
func (btype tomlBaseType) typeString() string {
|
||||
return string(btype)
|
||||
}
|
||||
|
||||
func (btype tomlBaseType) String() string {
|
||||
return btype.typeString()
|
||||
}
|
||||
|
||||
var (
|
||||
tomlInteger tomlBaseType = "Integer"
|
||||
tomlFloat tomlBaseType = "Float"
|
||||
tomlDatetime tomlBaseType = "Datetime"
|
||||
tomlString tomlBaseType = "String"
|
||||
tomlBool tomlBaseType = "Bool"
|
||||
tomlArray tomlBaseType = "Array"
|
||||
tomlHash tomlBaseType = "Hash"
|
||||
tomlArrayHash tomlBaseType = "ArrayHash"
|
||||
)
|
||||
|
||||
// typeOfPrimitive returns a tomlType of any primitive value in TOML.
|
||||
// Primitive values are: Integer, Float, Datetime, String and Bool.
|
||||
//
|
||||
// Passing a lexer item other than the following will cause a BUG message
|
||||
// to occur: itemString, itemBool, itemInteger, itemFloat, itemDatetime.
|
||||
func (p *parser) typeOfPrimitive(lexItem item) tomlType {
|
||||
switch lexItem.typ {
|
||||
case itemInteger:
|
||||
return tomlInteger
|
||||
case itemFloat:
|
||||
return tomlFloat
|
||||
case itemDatetime:
|
||||
return tomlDatetime
|
||||
case itemString:
|
||||
return tomlString
|
||||
case itemMultilineString:
|
||||
return tomlString
|
||||
case itemRawString:
|
||||
return tomlString
|
||||
case itemRawMultilineString:
|
||||
return tomlString
|
||||
case itemBool:
|
||||
return tomlBool
|
||||
}
|
||||
p.bug("Cannot infer primitive type of lex item '%s'.", lexItem)
|
||||
panic("unreachable")
|
||||
}
|
||||
|
||||
// typeOfArray returns a tomlType for an array given a list of types of its
|
||||
// values.
|
||||
//
|
||||
// In the current spec, if an array is homogeneous, then its type is always
|
||||
// "Array". If the array is not homogeneous, an error is generated.
|
||||
func (p *parser) typeOfArray(types []tomlType) tomlType {
|
||||
// Empty arrays are cool.
|
||||
if len(types) == 0 {
|
||||
return tomlArray
|
||||
}
|
||||
|
||||
theType := types[0]
|
||||
for _, t := range types[1:] {
|
||||
if !typeEqual(theType, t) {
|
||||
p.panicf("Array contains values of type '%s' and '%s', but "+
|
||||
"arrays must be homogeneous.", theType, t)
|
||||
}
|
||||
}
|
||||
return tomlArray
|
||||
}
|
||||
241
Godeps/_workspace/src/github.com/BurntSushi/toml/type_fields.go
generated
vendored
Normal file
241
Godeps/_workspace/src/github.com/BurntSushi/toml/type_fields.go
generated
vendored
Normal file
@@ -0,0 +1,241 @@
|
||||
package toml
|
||||
|
||||
// Struct field handling is adapted from code in encoding/json:
|
||||
//
|
||||
// Copyright 2010 The Go Authors. All rights reserved.
|
||||
// Use of this source code is governed by a BSD-style
|
||||
// license that can be found in the Go distribution.
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"sort"
|
||||
"sync"
|
||||
)
|
||||
|
||||
// A field represents a single field found in a struct.
|
||||
type field struct {
|
||||
name string // the name of the field (`toml` tag included)
|
||||
tag bool // whether field has a `toml` tag
|
||||
index []int // represents the depth of an anonymous field
|
||||
typ reflect.Type // the type of the field
|
||||
}
|
||||
|
||||
// byName sorts field by name, breaking ties with depth,
|
||||
// then breaking ties with "name came from toml tag", then
|
||||
// breaking ties with index sequence.
|
||||
type byName []field
|
||||
|
||||
func (x byName) Len() int { return len(x) }
|
||||
|
||||
func (x byName) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
|
||||
func (x byName) Less(i, j int) bool {
|
||||
if x[i].name != x[j].name {
|
||||
return x[i].name < x[j].name
|
||||
}
|
||||
if len(x[i].index) != len(x[j].index) {
|
||||
return len(x[i].index) < len(x[j].index)
|
||||
}
|
||||
if x[i].tag != x[j].tag {
|
||||
return x[i].tag
|
||||
}
|
||||
return byIndex(x).Less(i, j)
|
||||
}
|
||||
|
||||
// byIndex sorts field by index sequence.
|
||||
type byIndex []field
|
||||
|
||||
func (x byIndex) Len() int { return len(x) }
|
||||
|
||||
func (x byIndex) Swap(i, j int) { x[i], x[j] = x[j], x[i] }
|
||||
|
||||
func (x byIndex) Less(i, j int) bool {
|
||||
for k, xik := range x[i].index {
|
||||
if k >= len(x[j].index) {
|
||||
return false
|
||||
}
|
||||
if xik != x[j].index[k] {
|
||||
return xik < x[j].index[k]
|
||||
}
|
||||
}
|
||||
return len(x[i].index) < len(x[j].index)
|
||||
}
|
||||
|
||||
// typeFields returns a list of fields that TOML should recognize for the given
|
||||
// type. The algorithm is breadth-first search over the set of structs to
|
||||
// include - the top struct and then any reachable anonymous structs.
|
||||
func typeFields(t reflect.Type) []field {
|
||||
// Anonymous fields to explore at the current level and the next.
|
||||
current := []field{}
|
||||
next := []field{{typ: t}}
|
||||
|
||||
// Count of queued names for current level and the next.
|
||||
count := map[reflect.Type]int{}
|
||||
nextCount := map[reflect.Type]int{}
|
||||
|
||||
// Types already visited at an earlier level.
|
||||
visited := map[reflect.Type]bool{}
|
||||
|
||||
// Fields found.
|
||||
var fields []field
|
||||
|
||||
for len(next) > 0 {
|
||||
current, next = next, current[:0]
|
||||
count, nextCount = nextCount, map[reflect.Type]int{}
|
||||
|
||||
for _, f := range current {
|
||||
if visited[f.typ] {
|
||||
continue
|
||||
}
|
||||
visited[f.typ] = true
|
||||
|
||||
// Scan f.typ for fields to include.
|
||||
for i := 0; i < f.typ.NumField(); i++ {
|
||||
sf := f.typ.Field(i)
|
||||
if sf.PkgPath != "" { // unexported
|
||||
continue
|
||||
}
|
||||
name := sf.Tag.Get("toml")
|
||||
if name == "-" {
|
||||
continue
|
||||
}
|
||||
index := make([]int, len(f.index)+1)
|
||||
copy(index, f.index)
|
||||
index[len(f.index)] = i
|
||||
|
||||
ft := sf.Type
|
||||
if ft.Name() == "" && ft.Kind() == reflect.Ptr {
|
||||
// Follow pointer.
|
||||
ft = ft.Elem()
|
||||
}
|
||||
|
||||
// Record found field and index sequence.
|
||||
if name != "" || !sf.Anonymous || ft.Kind() != reflect.Struct {
|
||||
tagged := name != ""
|
||||
if name == "" {
|
||||
name = sf.Name
|
||||
}
|
||||
fields = append(fields, field{name, tagged, index, ft})
|
||||
if count[f.typ] > 1 {
|
||||
// If there were multiple instances, add a second,
|
||||
// so that the annihilation code will see a duplicate.
|
||||
// It only cares about the distinction between 1 or 2,
|
||||
// so don't bother generating any more copies.
|
||||
fields = append(fields, fields[len(fields)-1])
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Record new anonymous struct to explore in next round.
|
||||
nextCount[ft]++
|
||||
if nextCount[ft] == 1 {
|
||||
f := field{name: ft.Name(), index: index, typ: ft}
|
||||
next = append(next, f)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sort.Sort(byName(fields))
|
||||
|
||||
// Delete all fields that are hidden by the Go rules for embedded fields,
|
||||
// except that fields with TOML tags are promoted.
|
||||
|
||||
// The fields are sorted in primary order of name, secondary order
|
||||
// of field index length. Loop over names; for each name, delete
|
||||
// hidden fields by choosing the one dominant field that survives.
|
||||
out := fields[:0]
|
||||
for advance, i := 0, 0; i < len(fields); i += advance {
|
||||
// One iteration per name.
|
||||
// Find the sequence of fields with the name of this first field.
|
||||
fi := fields[i]
|
||||
name := fi.name
|
||||
for advance = 1; i+advance < len(fields); advance++ {
|
||||
fj := fields[i+advance]
|
||||
if fj.name != name {
|
||||
break
|
||||
}
|
||||
}
|
||||
if advance == 1 { // Only one field with this name
|
||||
out = append(out, fi)
|
||||
continue
|
||||
}
|
||||
dominant, ok := dominantField(fields[i : i+advance])
|
||||
if ok {
|
||||
out = append(out, dominant)
|
||||
}
|
||||
}
|
||||
|
||||
fields = out
|
||||
sort.Sort(byIndex(fields))
|
||||
|
||||
return fields
|
||||
}
|
||||
|
||||
// dominantField looks through the fields, all of which are known to
|
||||
// have the same name, to find the single field that dominates the
|
||||
// others using Go's embedding rules, modified by the presence of
|
||||
// TOML tags. If there are multiple top-level fields, the boolean
|
||||
// will be false: This condition is an error in Go and we skip all
|
||||
// the fields.
|
||||
func dominantField(fields []field) (field, bool) {
|
||||
// The fields are sorted in increasing index-length order. The winner
|
||||
// must therefore be one with the shortest index length. Drop all
|
||||
// longer entries, which is easy: just truncate the slice.
|
||||
length := len(fields[0].index)
|
||||
tagged := -1 // Index of first tagged field.
|
||||
for i, f := range fields {
|
||||
if len(f.index) > length {
|
||||
fields = fields[:i]
|
||||
break
|
||||
}
|
||||
if f.tag {
|
||||
if tagged >= 0 {
|
||||
// Multiple tagged fields at the same level: conflict.
|
||||
// Return no field.
|
||||
return field{}, false
|
||||
}
|
||||
tagged = i
|
||||
}
|
||||
}
|
||||
if tagged >= 0 {
|
||||
return fields[tagged], true
|
||||
}
|
||||
// All remaining fields have the same length. If there's more than one,
|
||||
// we have a conflict (two fields named "X" at the same level) and we
|
||||
// return no field.
|
||||
if len(fields) > 1 {
|
||||
return field{}, false
|
||||
}
|
||||
return fields[0], true
|
||||
}
|
||||
|
||||
var fieldCache struct {
|
||||
sync.RWMutex
|
||||
m map[reflect.Type][]field
|
||||
}
|
||||
|
||||
// cachedTypeFields is like typeFields but uses a cache to avoid repeated work.
|
||||
func cachedTypeFields(t reflect.Type) []field {
|
||||
fieldCache.RLock()
|
||||
f := fieldCache.m[t]
|
||||
fieldCache.RUnlock()
|
||||
if f != nil {
|
||||
return f
|
||||
}
|
||||
|
||||
// Compute fields without lock.
|
||||
// Might duplicate effort but won't hold other computations back.
|
||||
f = typeFields(t)
|
||||
if f == nil {
|
||||
f = []field{}
|
||||
}
|
||||
|
||||
fieldCache.Lock()
|
||||
if fieldCache.m == nil {
|
||||
fieldCache.m = map[reflect.Type][]field{}
|
||||
}
|
||||
fieldCache.m[t] = f
|
||||
fieldCache.Unlock()
|
||||
return f
|
||||
}
|
||||
24
Godeps/_workspace/src/github.com/Unknwon/com/.gitignore
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/Unknwon/com/.gitignore
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
# Compiled Object files, Static and Dynamic libs (Shared Objects)
|
||||
*.o
|
||||
*.a
|
||||
*.so
|
||||
|
||||
# Folders
|
||||
_obj
|
||||
_test
|
||||
.idea
|
||||
|
||||
# Architecture specific extensions/prefixes
|
||||
*.[568vq]
|
||||
[568vq].out
|
||||
|
||||
*.cgo1.go
|
||||
*.cgo2.c
|
||||
_cgo_defun.c
|
||||
_cgo_gotypes.go
|
||||
_cgo_export.*
|
||||
|
||||
_testmain.go
|
||||
|
||||
*.exe
|
||||
*.iml
|
||||
191
Godeps/_workspace/src/github.com/Unknwon/com/LICENSE
generated
vendored
Normal file
191
Godeps/_workspace/src/github.com/Unknwon/com/LICENSE
generated
vendored
Normal file
@@ -0,0 +1,191 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction, and
|
||||
distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by the copyright
|
||||
owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all other entities
|
||||
that control, are controlled by, or are under common control with that entity.
|
||||
For the purposes of this definition, "control" means (i) the power, direct or
|
||||
indirect, to cause the direction or management of such entity, whether by
|
||||
contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity exercising
|
||||
permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications, including
|
||||
but not limited to software source code, documentation source, and configuration
|
||||
files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical transformation or
|
||||
translation of a Source form, including but not limited to compiled object code,
|
||||
generated documentation, and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or Object form, made
|
||||
available under the License, as indicated by a copyright notice that is included
|
||||
in or attached to the work (an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object form, that
|
||||
is based on (or derived from) the Work and for which the editorial revisions,
|
||||
annotations, elaborations, or other modifications represent, as a whole, an
|
||||
original work of authorship. For the purposes of this License, Derivative Works
|
||||
shall not include works that remain separable from, or merely link (or bind by
|
||||
name) to the interfaces of, the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including the original version
|
||||
of the Work and any modifications or additions to that Work or Derivative Works
|
||||
thereof, that is intentionally submitted to Licensor for inclusion in the Work
|
||||
by the copyright owner or by an individual or Legal Entity authorized to submit
|
||||
on behalf of the copyright owner. For the purposes of this definition,
|
||||
"submitted" means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems, and
|
||||
issue tracking systems that are managed by, or on behalf of, the Licensor for
|
||||
the purpose of discussing and improving the Work, but excluding communication
|
||||
that is conspicuously marked or otherwise designated in writing by the copyright
|
||||
owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity on behalf
|
||||
of whom a Contribution has been received by Licensor and subsequently
|
||||
incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the Work and such
|
||||
Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License.
|
||||
|
||||
Subject to the terms and conditions of this License, each Contributor hereby
|
||||
grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,
|
||||
irrevocable (except as stated in this section) patent license to make, have
|
||||
made, use, offer to sell, sell, import, and otherwise transfer the Work, where
|
||||
such license applies only to those patent claims licensable by such Contributor
|
||||
that are necessarily infringed by their Contribution(s) alone or by combination
|
||||
of their Contribution(s) with the Work to which such Contribution(s) was
|
||||
submitted. If You institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work or a
|
||||
Contribution incorporated within the Work constitutes direct or contributory
|
||||
patent infringement, then any patent licenses granted to You under this License
|
||||
for that Work shall terminate as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution.
|
||||
|
||||
You may reproduce and distribute copies of the Work or Derivative Works thereof
|
||||
in any medium, with or without modifications, and in Source or Object form,
|
||||
provided that You meet the following conditions:
|
||||
|
||||
You must give any other recipients of the Work or Derivative Works a copy of
|
||||
this License; and
|
||||
You must cause any modified files to carry prominent notices stating that You
|
||||
changed the files; and
|
||||
You must retain, in the Source form of any Derivative Works that You distribute,
|
||||
all copyright, patent, trademark, and attribution notices from the Source form
|
||||
of the Work, excluding those notices that do not pertain to any part of the
|
||||
Derivative Works; and
|
||||
If the Work includes a "NOTICE" text file as part of its distribution, then any
|
||||
Derivative Works that You distribute must include a readable copy of the
|
||||
attribution notices contained within such NOTICE file, excluding those notices
|
||||
that do not pertain to any part of the Derivative Works, in at least one of the
|
||||
following places: within a NOTICE text file distributed as part of the
|
||||
Derivative Works; within the Source form or documentation, if provided along
|
||||
with the Derivative Works; or, within a display generated by the Derivative
|
||||
Works, if and wherever such third-party notices normally appear. The contents of
|
||||
the NOTICE file are for informational purposes only and do not modify the
|
||||
License. You may add Your own attribution notices within Derivative Works that
|
||||
You distribute, alongside or as an addendum to the NOTICE text from the Work,
|
||||
provided that such additional attribution notices cannot be construed as
|
||||
modifying the License.
|
||||
You may add Your own copyright statement to Your modifications and may provide
|
||||
additional or different license terms and conditions for use, reproduction, or
|
||||
distribution of Your modifications, or for any such Derivative Works as a whole,
|
||||
provided Your use, reproduction, and distribution of the Work otherwise complies
|
||||
with the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions.
|
||||
|
||||
Unless You explicitly state otherwise, any Contribution intentionally submitted
|
||||
for inclusion in the Work by You to the Licensor shall be under the terms and
|
||||
conditions of this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify the terms of
|
||||
any separate license agreement you may have executed with Licensor regarding
|
||||
such Contributions.
|
||||
|
||||
6. Trademarks.
|
||||
|
||||
This License does not grant permission to use the trade names, trademarks,
|
||||
service marks, or product names of the Licensor, except as required for
|
||||
reasonable and customary use in describing the origin of the Work and
|
||||
reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty.
|
||||
|
||||
Unless required by applicable law or agreed to in writing, Licensor provides the
|
||||
Work (and each Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
|
||||
including, without limitation, any warranties or conditions of TITLE,
|
||||
NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are
|
||||
solely responsible for determining the appropriateness of using or
|
||||
redistributing the Work and assume any risks associated with Your exercise of
|
||||
permissions under this License.
|
||||
|
||||
8. Limitation of Liability.
|
||||
|
||||
In no event and under no legal theory, whether in tort (including negligence),
|
||||
contract, or otherwise, unless required by applicable law (such as deliberate
|
||||
and grossly negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special, incidental,
|
||||
or consequential damages of any character arising as a result of this License or
|
||||
out of the use or inability to use the Work (including but not limited to
|
||||
damages for loss of goodwill, work stoppage, computer failure or malfunction, or
|
||||
any and all other commercial damages or losses), even if such Contributor has
|
||||
been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability.
|
||||
|
||||
While redistributing the Work or Derivative Works thereof, You may choose to
|
||||
offer, and charge a fee for, acceptance of support, warranty, indemnity, or
|
||||
other liability obligations and/or rights consistent with this License. However,
|
||||
in accepting such obligations, You may act only on Your own behalf and on Your
|
||||
sole responsibility, not on behalf of any other Contributor, and only if You
|
||||
agree to indemnify, defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason of your
|
||||
accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work
|
||||
|
||||
To apply the Apache License to your work, attach the following boilerplate
|
||||
notice, with the fields enclosed by brackets "[]" replaced with your own
|
||||
identifying information. (Don't include the brackets!) The text should be
|
||||
enclosed in the appropriate comment syntax for the file format. We also
|
||||
recommend that a file or class name and description of purpose be included on
|
||||
the same "printed page" as the copyright notice for easier identification within
|
||||
third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
24
Godeps/_workspace/src/github.com/Unknwon/com/README.md
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/Unknwon/com/README.md
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
Common functions
|
||||
===
|
||||
|
||||
[](https://drone.io/github.com/Unknwon/com/latest) [](http://gowalker.org/github.com/Unknwon/com)
|
||||
|
||||
This is an open source project for commonly used functions for the Go programming language.
|
||||
|
||||
This package need >= **go 1.2**
|
||||
|
||||
Code Convention: based on [Go Code Convention](https://github.com/Unknwon/go-code-convention).
|
||||
|
||||
## Contribute
|
||||
|
||||
Your contribute is welcome, but you have to check following steps after you added some functions and commit them:
|
||||
|
||||
1. Make sure you wrote user-friendly comments for **all functions** .
|
||||
2. Make sure you wrote test cases with any possible condition for **all functions** in file `*_test.go`.
|
||||
3. Make sure you wrote benchmarks for **all functions** in file `*_test.go`.
|
||||
4. Make sure you wrote useful examples for **all functions** in file `example_test.go`.
|
||||
5. Make sure you ran `go test -bench="."` and got **PASS** .
|
||||
|
||||
## Performance
|
||||
|
||||
See results on [drone.io](https://drone.io/github.com/Unknwon/com/latest) by `go test -bench="."`.
|
||||
161
Godeps/_workspace/src/github.com/Unknwon/com/cmd.go
generated
vendored
Normal file
161
Godeps/_workspace/src/github.com/Unknwon/com/cmd.go
generated
vendored
Normal file
@@ -0,0 +1,161 @@
|
||||
// +build go1.2
|
||||
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
// Package com is an open source project for commonly used functions for the Go programming language.
|
||||
package com
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// ExecCmdDirBytes executes system command in given directory
|
||||
// and return stdout, stderr in bytes type, along with possible error.
|
||||
func ExecCmdDirBytes(dir, cmdName string, args ...string) ([]byte, []byte, error) {
|
||||
bufOut := new(bytes.Buffer)
|
||||
bufErr := new(bytes.Buffer)
|
||||
|
||||
cmd := exec.Command(cmdName, args...)
|
||||
cmd.Dir = dir
|
||||
cmd.Stdout = bufOut
|
||||
cmd.Stderr = bufErr
|
||||
|
||||
err := cmd.Run()
|
||||
return bufOut.Bytes(), bufErr.Bytes(), err
|
||||
}
|
||||
|
||||
// ExecCmdBytes executes system command
|
||||
// and return stdout, stderr in bytes type, along with possible error.
|
||||
func ExecCmdBytes(cmdName string, args ...string) ([]byte, []byte, error) {
|
||||
return ExecCmdDirBytes("", cmdName, args...)
|
||||
}
|
||||
|
||||
// ExecCmdDir executes system command in given directory
|
||||
// and return stdout, stderr in string type, along with possible error.
|
||||
func ExecCmdDir(dir, cmdName string, args ...string) (string, string, error) {
|
||||
bufOut, bufErr, err := ExecCmdDirBytes(dir, cmdName, args...)
|
||||
return string(bufOut), string(bufErr), err
|
||||
}
|
||||
|
||||
// ExecCmd executes system command
|
||||
// and return stdout, stderr in string type, along with possible error.
|
||||
func ExecCmd(cmdName string, args ...string) (string, string, error) {
|
||||
return ExecCmdDir("", cmdName, args...)
|
||||
}
|
||||
|
||||
// _________ .__ .____
|
||||
// \_ ___ \ ____ | | ___________ | | ____ ____
|
||||
// / \ \/ / _ \| | / _ \_ __ \ | | / _ \ / ___\
|
||||
// \ \___( <_> ) |_( <_> ) | \/ | |__( <_> ) /_/ >
|
||||
// \______ /\____/|____/\____/|__| |_______ \____/\___ /
|
||||
// \/ \/ /_____/
|
||||
|
||||
// Color number constants.
|
||||
const (
|
||||
Gray = uint8(iota + 90)
|
||||
Red
|
||||
Green
|
||||
Yellow
|
||||
Blue
|
||||
Magenta
|
||||
//NRed = uint8(31) // Normal
|
||||
EndColor = "\033[0m"
|
||||
)
|
||||
|
||||
// getColorLevel returns colored level string by given level.
|
||||
func getColorLevel(level string) string {
|
||||
level = strings.ToUpper(level)
|
||||
switch level {
|
||||
case "TRAC":
|
||||
return fmt.Sprintf("\033[%dm%s\033[0m", Blue, level)
|
||||
case "ERRO":
|
||||
return fmt.Sprintf("\033[%dm%s\033[0m", Red, level)
|
||||
case "WARN":
|
||||
return fmt.Sprintf("\033[%dm%s\033[0m", Magenta, level)
|
||||
case "SUCC":
|
||||
return fmt.Sprintf("\033[%dm%s\033[0m", Green, level)
|
||||
default:
|
||||
return level
|
||||
}
|
||||
}
|
||||
|
||||
// ColorLogS colors log and return colored content.
|
||||
// Log format: <level> <content [highlight][path]> [ error ].
|
||||
// Level: TRAC -> blue; ERRO -> red; WARN -> Magenta; SUCC -> green; others -> default.
|
||||
// Content: default; path: yellow; error -> red.
|
||||
// Level has to be surrounded by "[" and "]".
|
||||
// Highlights have to be surrounded by "# " and " #"(space), "#" will be deleted.
|
||||
// Paths have to be surrounded by "( " and " )"(space).
|
||||
// Errors have to be surrounded by "[ " and " ]"(space).
|
||||
// Note: it hasn't support windows yet, contribute is welcome.
|
||||
func ColorLogS(format string, a ...interface{}) string {
|
||||
log := fmt.Sprintf(format, a...)
|
||||
|
||||
var clog string
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
// Level.
|
||||
i := strings.Index(log, "]")
|
||||
if log[0] == '[' && i > -1 {
|
||||
clog += "[" + getColorLevel(log[1:i]) + "]"
|
||||
}
|
||||
|
||||
log = log[i+1:]
|
||||
|
||||
// Error.
|
||||
log = strings.Replace(log, "[ ", fmt.Sprintf("[\033[%dm", Red), -1)
|
||||
log = strings.Replace(log, " ]", EndColor+"]", -1)
|
||||
|
||||
// Path.
|
||||
log = strings.Replace(log, "( ", fmt.Sprintf("(\033[%dm", Yellow), -1)
|
||||
log = strings.Replace(log, " )", EndColor+")", -1)
|
||||
|
||||
// Highlights.
|
||||
log = strings.Replace(log, "# ", fmt.Sprintf("\033[%dm", Gray), -1)
|
||||
log = strings.Replace(log, " #", EndColor, -1)
|
||||
|
||||
} else {
|
||||
// Level.
|
||||
i := strings.Index(log, "]")
|
||||
if log[0] == '[' && i > -1 {
|
||||
clog += "[" + log[1:i] + "]"
|
||||
}
|
||||
|
||||
log = log[i+1:]
|
||||
|
||||
// Error.
|
||||
log = strings.Replace(log, "[ ", "[", -1)
|
||||
log = strings.Replace(log, " ]", "]", -1)
|
||||
|
||||
// Path.
|
||||
log = strings.Replace(log, "( ", "(", -1)
|
||||
log = strings.Replace(log, " )", ")", -1)
|
||||
|
||||
// Highlights.
|
||||
log = strings.Replace(log, "# ", "", -1)
|
||||
log = strings.Replace(log, " #", "", -1)
|
||||
}
|
||||
return clog + log
|
||||
}
|
||||
|
||||
// ColorLog prints colored log to stdout.
|
||||
// See color rules in function 'ColorLogS'.
|
||||
func ColorLog(format string, a ...interface{}) {
|
||||
fmt.Print(ColorLogS(format, a...))
|
||||
}
|
||||
140
Godeps/_workspace/src/github.com/Unknwon/com/cmd_test.go
generated
vendored
Normal file
140
Godeps/_workspace/src/github.com/Unknwon/com/cmd_test.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestColorLogS(t *testing.T) {
|
||||
if runtime.GOOS != "windows" {
|
||||
// Trace + path.
|
||||
cls := ColorLogS("[TRAC] Trace level test with path( %s )", "/path/to/somethere")
|
||||
clsR := fmt.Sprintf(
|
||||
"[\033[%dmTRAC%s] Trace level test with path(\033[%dm%s%s)",
|
||||
Blue, EndColor, Yellow, "/path/to/somethere", EndColor)
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Error + error.
|
||||
cls = ColorLogS("[ERRO] Error level test with error[ %s ]", "test error")
|
||||
clsR = fmt.Sprintf(
|
||||
"[\033[%dmERRO%s] Error level test with error[\033[%dm%s%s]",
|
||||
Red, EndColor, Red, "test error", EndColor)
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Warning + highlight.
|
||||
cls = ColorLogS("[WARN] Warnning level test with highlight # %s #", "special offer!")
|
||||
clsR = fmt.Sprintf(
|
||||
"[\033[%dmWARN%s] Warnning level test with highlight \033[%dm%s%s",
|
||||
Magenta, EndColor, Gray, "special offer!", EndColor)
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Success.
|
||||
cls = ColorLogS("[SUCC] Success level test")
|
||||
clsR = fmt.Sprintf(
|
||||
"[\033[%dmSUCC%s] Success level test",
|
||||
Green, EndColor)
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Default.
|
||||
cls = ColorLogS("[INFO] Default level test")
|
||||
clsR = fmt.Sprintf(
|
||||
"[INFO] Default level test")
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
} else {
|
||||
// Trace + path.
|
||||
cls := ColorLogS("[TRAC] Trace level test with path( %s )", "/path/to/somethere")
|
||||
clsR := fmt.Sprintf(
|
||||
"[TRAC] Trace level test with path(%s)",
|
||||
"/path/to/somethere")
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Error + error.
|
||||
cls = ColorLogS("[ERRO] Error level test with error[ %s ]", "test error")
|
||||
clsR = fmt.Sprintf(
|
||||
"[ERRO] Error level test with error[%s]",
|
||||
"test error")
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Warning + highlight.
|
||||
cls = ColorLogS("[WARN] Warnning level test with highlight # %s #", "special offer!")
|
||||
clsR = fmt.Sprintf(
|
||||
"[WARN] Warnning level test with highlight %s",
|
||||
"special offer!")
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Success.
|
||||
cls = ColorLogS("[SUCC] Success level test")
|
||||
clsR = fmt.Sprintf(
|
||||
"[SUCC] Success level test")
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
|
||||
// Default.
|
||||
cls = ColorLogS("[INFO] Default level test")
|
||||
clsR = fmt.Sprintf(
|
||||
"[INFO] Default level test")
|
||||
if cls != clsR {
|
||||
t.Errorf("ColorLogS:\n Expect => %s\n Got => %s\n", clsR, cls)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestExecCmd(t *testing.T) {
|
||||
stdout, stderr, err := ExecCmd("go", "help", "get")
|
||||
if err != nil {
|
||||
t.Errorf("ExecCmd:\n Expect => %v\n Got => %v\n", nil, err)
|
||||
} else if len(stderr) != 0 {
|
||||
t.Errorf("ExecCmd:\n Expect => %s\n Got => %s\n", "", stderr)
|
||||
} else if !strings.HasPrefix(stdout, "usage: go get") {
|
||||
t.Errorf("ExecCmd:\n Expect => %s\n Got => %s\n", "usage: go get", stdout)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkColorLogS(b *testing.B) {
|
||||
log := fmt.Sprintf(
|
||||
"[WARN] This is a tesing log that should be colored, path( %s ),"+
|
||||
" highlight # %s #, error [ %s ].",
|
||||
"path to somewhere", "highlighted content", "tesing error")
|
||||
for i := 0; i < b.N; i++ {
|
||||
ColorLogS(log)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkExecCmd(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
ExecCmd("go", "help", "get")
|
||||
}
|
||||
}
|
||||
157
Godeps/_workspace/src/github.com/Unknwon/com/convert.go
generated
vendored
Normal file
157
Godeps/_workspace/src/github.com/Unknwon/com/convert.go
generated
vendored
Normal file
@@ -0,0 +1,157 @@
|
||||
// Copyright 2014 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Convert string to specify type.
|
||||
type StrTo string
|
||||
|
||||
func (f StrTo) Exist() bool {
|
||||
return string(f) != string(0x1E)
|
||||
}
|
||||
|
||||
func (f StrTo) Uint8() (uint8, error) {
|
||||
v, err := strconv.ParseUint(f.String(), 10, 8)
|
||||
return uint8(v), err
|
||||
}
|
||||
|
||||
func (f StrTo) Int() (int, error) {
|
||||
v, err := strconv.ParseInt(f.String(), 10, 32)
|
||||
return int(v), err
|
||||
}
|
||||
|
||||
func (f StrTo) Int64() (int64, error) {
|
||||
v, err := strconv.ParseInt(f.String(), 10, 64)
|
||||
return int64(v), err
|
||||
}
|
||||
|
||||
func (f StrTo) MustUint8() uint8 {
|
||||
v, _ := f.Uint8()
|
||||
return v
|
||||
}
|
||||
|
||||
func (f StrTo) MustInt() int {
|
||||
v, _ := f.Int()
|
||||
return v
|
||||
}
|
||||
|
||||
func (f StrTo) MustInt64() int64 {
|
||||
v, _ := f.Int64()
|
||||
return v
|
||||
}
|
||||
|
||||
func (f StrTo) String() string {
|
||||
if f.Exist() {
|
||||
return string(f)
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// Convert any type to string.
|
||||
func ToStr(value interface{}, args ...int) (s string) {
|
||||
switch v := value.(type) {
|
||||
case bool:
|
||||
s = strconv.FormatBool(v)
|
||||
case float32:
|
||||
s = strconv.FormatFloat(float64(v), 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 32))
|
||||
case float64:
|
||||
s = strconv.FormatFloat(v, 'f', argInt(args).Get(0, -1), argInt(args).Get(1, 64))
|
||||
case int:
|
||||
s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
|
||||
case int8:
|
||||
s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
|
||||
case int16:
|
||||
s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
|
||||
case int32:
|
||||
s = strconv.FormatInt(int64(v), argInt(args).Get(0, 10))
|
||||
case int64:
|
||||
s = strconv.FormatInt(v, argInt(args).Get(0, 10))
|
||||
case uint:
|
||||
s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
|
||||
case uint8:
|
||||
s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
|
||||
case uint16:
|
||||
s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
|
||||
case uint32:
|
||||
s = strconv.FormatUint(uint64(v), argInt(args).Get(0, 10))
|
||||
case uint64:
|
||||
s = strconv.FormatUint(v, argInt(args).Get(0, 10))
|
||||
case string:
|
||||
s = v
|
||||
case []byte:
|
||||
s = string(v)
|
||||
default:
|
||||
s = fmt.Sprintf("%v", v)
|
||||
}
|
||||
return s
|
||||
}
|
||||
|
||||
type argInt []int
|
||||
|
||||
func (a argInt) Get(i int, args ...int) (r int) {
|
||||
if i >= 0 && i < len(a) {
|
||||
r = a[i]
|
||||
} else if len(args) > 0 {
|
||||
r = args[0]
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// HexStr2int converts hex format string to decimal number.
|
||||
func HexStr2int(hexStr string) (int, error) {
|
||||
num := 0
|
||||
length := len(hexStr)
|
||||
for i := 0; i < length; i++ {
|
||||
char := hexStr[length-i-1]
|
||||
factor := -1
|
||||
|
||||
switch {
|
||||
case char >= '0' && char <= '9':
|
||||
factor = int(char) - '0'
|
||||
case char >= 'a' && char <= 'f':
|
||||
factor = int(char) - 'a' + 10
|
||||
default:
|
||||
return -1, fmt.Errorf("invalid hex: %s", string(char))
|
||||
}
|
||||
|
||||
num += factor * PowInt(16, i)
|
||||
}
|
||||
return num, nil
|
||||
}
|
||||
|
||||
// Int2HexStr converts decimal number to hex format string.
|
||||
func Int2HexStr(num int) (hex string) {
|
||||
if num == 0 {
|
||||
return "0"
|
||||
}
|
||||
|
||||
for num > 0 {
|
||||
r := num % 16
|
||||
|
||||
c := "?"
|
||||
if r >= 0 && r <= 9 {
|
||||
c = string(r + '0')
|
||||
} else {
|
||||
c = string(r + 'a' - 10)
|
||||
}
|
||||
hex = c + hex
|
||||
num = num / 16
|
||||
}
|
||||
return hex
|
||||
}
|
||||
56
Godeps/_workspace/src/github.com/Unknwon/com/convert_test.go
generated
vendored
Normal file
56
Godeps/_workspace/src/github.com/Unknwon/com/convert_test.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright 2014 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestHexStr2int(t *testing.T) {
|
||||
Convey("Convert hex format string to decimal", t, func() {
|
||||
hexDecs := map[string]int{
|
||||
"1": 1,
|
||||
"002": 2,
|
||||
"011": 17,
|
||||
"0a1": 161,
|
||||
"35e": 862,
|
||||
}
|
||||
|
||||
for hex, dec := range hexDecs {
|
||||
val, err := HexStr2int(hex)
|
||||
So(err, ShouldBeNil)
|
||||
So(val, ShouldEqual, dec)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func TestInt2HexStr(t *testing.T) {
|
||||
Convey("Convert decimal to hex format string", t, func() {
|
||||
decHexs := map[int]string{
|
||||
1: "1",
|
||||
2: "2",
|
||||
17: "11",
|
||||
161: "a1",
|
||||
862: "35e",
|
||||
}
|
||||
|
||||
for dec, hex := range decHexs {
|
||||
val := Int2HexStr(dec)
|
||||
So(val, ShouldEqual, hex)
|
||||
}
|
||||
})
|
||||
}
|
||||
173
Godeps/_workspace/src/github.com/Unknwon/com/dir.go
generated
vendored
Normal file
173
Godeps/_workspace/src/github.com/Unknwon/com/dir.go
generated
vendored
Normal file
@@ -0,0 +1,173 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// IsDir returns true if given path is a directory,
|
||||
// or returns false when it's a file or does not exist.
|
||||
func IsDir(dir string) bool {
|
||||
f, e := os.Stat(dir)
|
||||
if e != nil {
|
||||
return false
|
||||
}
|
||||
return f.IsDir()
|
||||
}
|
||||
|
||||
func statDir(dirPath, recPath string, includeDir, isDirOnly bool) ([]string, error) {
|
||||
dir, err := os.Open(dirPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer dir.Close()
|
||||
|
||||
fis, err := dir.Readdir(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
statList := make([]string, 0)
|
||||
for _, fi := range fis {
|
||||
if strings.Contains(fi.Name(), ".DS_Store") {
|
||||
continue
|
||||
}
|
||||
|
||||
relPath := path.Join(recPath, fi.Name())
|
||||
curPath := path.Join(dirPath, fi.Name())
|
||||
if fi.IsDir() {
|
||||
if includeDir {
|
||||
statList = append(statList, relPath+"/")
|
||||
}
|
||||
s, err := statDir(curPath, relPath, includeDir, isDirOnly)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
statList = append(statList, s...)
|
||||
} else if !isDirOnly {
|
||||
statList = append(statList, relPath)
|
||||
}
|
||||
}
|
||||
return statList, nil
|
||||
}
|
||||
|
||||
// StatDir gathers information of given directory by depth-first.
|
||||
// It returns slice of file list and includes subdirectories if enabled;
|
||||
// it returns error and nil slice when error occurs in underlying functions,
|
||||
// or given path is not a directory or does not exist.
|
||||
//
|
||||
// Slice does not include given path itself.
|
||||
// If subdirectories is enabled, they will have suffix '/'.
|
||||
func StatDir(rootPath string, includeDir ...bool) ([]string, error) {
|
||||
if !IsDir(rootPath) {
|
||||
return nil, errors.New("not a directory or does not exist: " + rootPath)
|
||||
}
|
||||
|
||||
isIncludeDir := false
|
||||
if len(includeDir) >= 1 {
|
||||
isIncludeDir = includeDir[0]
|
||||
}
|
||||
return statDir(rootPath, "", isIncludeDir, false)
|
||||
}
|
||||
|
||||
// GetAllSubDirs returns all subdirectories of given root path.
|
||||
// Slice does not include given path itself.
|
||||
func GetAllSubDirs(rootPath string) ([]string, error) {
|
||||
if !IsDir(rootPath) {
|
||||
return nil, errors.New("not a directory or does not exist: " + rootPath)
|
||||
}
|
||||
return statDir(rootPath, "", true, true)
|
||||
}
|
||||
|
||||
// GetFileListBySuffix returns an ordered list of file paths.
|
||||
// It recognize if given path is a file, and don't do recursive find.
|
||||
func GetFileListBySuffix(dirPath, suffix string) ([]string, error) {
|
||||
if !IsExist(dirPath) {
|
||||
return nil, fmt.Errorf("given path does not exist: %s", dirPath)
|
||||
} else if IsFile(dirPath) {
|
||||
return []string{dirPath}, nil
|
||||
}
|
||||
|
||||
// Given path is a directory.
|
||||
dir, err := os.Open(dirPath)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fis, err := dir.Readdir(0)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
files := make([]string, 0, len(fis))
|
||||
for _, fi := range fis {
|
||||
if strings.HasSuffix(fi.Name(), suffix) {
|
||||
files = append(files, path.Join(dirPath, fi.Name()))
|
||||
}
|
||||
}
|
||||
|
||||
return files, nil
|
||||
}
|
||||
|
||||
// CopyDir copy files recursively from source to target directory.
|
||||
//
|
||||
// The filter accepts a function that process the path info.
|
||||
// and should return true for need to filter.
|
||||
//
|
||||
// It returns error when error occurs in underlying functions.
|
||||
func CopyDir(srcPath, destPath string, filters ...func(filePath string) bool) error {
|
||||
// Check if target directory exists.
|
||||
if IsExist(destPath) {
|
||||
return errors.New("file or directory alreay exists: " + destPath)
|
||||
}
|
||||
|
||||
err := os.MkdirAll(destPath, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Gather directory info.
|
||||
infos, err := StatDir(srcPath, true)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var filter func(filePath string) bool
|
||||
if len(filters) > 0 {
|
||||
filter = filters[0]
|
||||
}
|
||||
|
||||
for _, info := range infos {
|
||||
if filter != nil && filter(info) {
|
||||
continue
|
||||
}
|
||||
|
||||
curPath := path.Join(destPath, info)
|
||||
if strings.HasSuffix(info, "/") {
|
||||
err = os.MkdirAll(curPath, os.ModePerm)
|
||||
} else {
|
||||
err = Copy(path.Join(srcPath, info), curPath)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
58
Godeps/_workspace/src/github.com/Unknwon/com/dir_test.go
generated
vendored
Normal file
58
Godeps/_workspace/src/github.com/Unknwon/com/dir_test.go
generated
vendored
Normal file
@@ -0,0 +1,58 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestIsDir(t *testing.T) {
|
||||
Convey("Check if given path is a directory", t, func() {
|
||||
Convey("Pass a file name", func() {
|
||||
So(IsDir("file.go"), ShouldEqual, false)
|
||||
})
|
||||
Convey("Pass a directory name", func() {
|
||||
So(IsDir("testdata"), ShouldEqual, true)
|
||||
})
|
||||
Convey("Pass a invalid path", func() {
|
||||
So(IsDir("foo"), ShouldEqual, false)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestCopyDir(t *testing.T) {
|
||||
Convey("Items of two slices should be same", t, func() {
|
||||
s1, err := StatDir("testdata", true)
|
||||
So(err, ShouldEqual, nil)
|
||||
|
||||
err = CopyDir("testdata", "testdata2")
|
||||
So(err, ShouldEqual, nil)
|
||||
|
||||
s2, err := StatDir("testdata2", true)
|
||||
os.RemoveAll("testdata2")
|
||||
So(err, ShouldEqual, nil)
|
||||
|
||||
So(CompareSliceStr(s1, s2), ShouldEqual, true)
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkIsDir(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsDir("file.go")
|
||||
}
|
||||
}
|
||||
299
Godeps/_workspace/src/github.com/Unknwon/com/example_test.go
generated
vendored
Normal file
299
Godeps/_workspace/src/github.com/Unknwon/com/example_test.go
generated
vendored
Normal file
@@ -0,0 +1,299 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com_test
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
|
||||
"github.com/Unknwon/com"
|
||||
)
|
||||
|
||||
// ------------------------------
|
||||
// cmd.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleColorLogS() {
|
||||
coloredLog := com.ColorLogS(fmt.Sprintf(
|
||||
"[WARN] This is a tesing log that should be colored, path( %s ),"+
|
||||
" highlight # %s #, error [ %s ].",
|
||||
"path to somewhere", "highlighted content", "tesing error"))
|
||||
fmt.Println(coloredLog)
|
||||
}
|
||||
|
||||
func ExampleColorLog() {
|
||||
com.ColorLog(fmt.Sprintf(
|
||||
"[WARN] This is a tesing log that should be colored, path( %s ),"+
|
||||
" highlight # %s #, error [ %s ].",
|
||||
"path to somewhere", "highlighted content", "tesing error"))
|
||||
}
|
||||
|
||||
func ExampleExecCmd() {
|
||||
stdout, stderr, err := com.ExecCmd("go", "help", "get")
|
||||
fmt.Println(stdout, stderr, err)
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// html.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleHtml2JS() {
|
||||
htm := "<div id=\"button\" class=\"btn\">Click me</div>\n\r"
|
||||
js := string(com.Html2JS([]byte(htm)))
|
||||
fmt.Println(js)
|
||||
// Output: <div id=\"button\" class=\"btn\">Click me</div>\n
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// path.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleGetGOPATHs() {
|
||||
gps := com.GetGOPATHs()
|
||||
fmt.Println(gps)
|
||||
}
|
||||
|
||||
func ExampleGetSrcPath() {
|
||||
srcPath, err := com.GetSrcPath("github.com/Unknwon/com")
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return
|
||||
}
|
||||
fmt.Println(srcPath)
|
||||
}
|
||||
|
||||
func ExampleHomeDir() {
|
||||
hd, err := com.HomeDir()
|
||||
fmt.Println(hd, err)
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// file.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleIsFile() {
|
||||
if com.IsFile("file.go") {
|
||||
fmt.Println("file.go exists")
|
||||
return
|
||||
}
|
||||
fmt.Println("file.go is not a file or does not exist")
|
||||
}
|
||||
|
||||
func ExampleIsExist() {
|
||||
if com.IsExist("file.go") {
|
||||
fmt.Println("file.go exists")
|
||||
return
|
||||
}
|
||||
fmt.Println("file.go does not exist")
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// dir.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleIsDir() {
|
||||
if com.IsDir("files") {
|
||||
fmt.Println("directory 'files' exists")
|
||||
return
|
||||
}
|
||||
fmt.Println("'files' is not a directory or does not exist")
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// string.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleIsLetter() {
|
||||
fmt.Println(com.IsLetter('1'))
|
||||
fmt.Println(com.IsLetter('['))
|
||||
fmt.Println(com.IsLetter('a'))
|
||||
fmt.Println(com.IsLetter('Z'))
|
||||
// Output:
|
||||
// false
|
||||
// false
|
||||
// true
|
||||
// true
|
||||
}
|
||||
|
||||
func ExampleExpand() {
|
||||
match := map[string]string{
|
||||
"domain": "gowalker.org",
|
||||
"subdomain": "github.com",
|
||||
}
|
||||
s := "http://{domain}/{subdomain}/{0}/{1}"
|
||||
fmt.Println(com.Expand(s, match, "Unknwon", "gowalker"))
|
||||
// Output: http://gowalker.org/github.com/Unknwon/gowalker
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// http.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleHttpGet() ([]byte, error) {
|
||||
rc, err := com.HttpGet(&http.Client{}, "http://gowalker.org", nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
p, err := ioutil.ReadAll(rc)
|
||||
rc.Close()
|
||||
return p, err
|
||||
}
|
||||
|
||||
func ExampleHttpGetBytes() ([]byte, error) {
|
||||
p, err := com.HttpGetBytes(&http.Client{}, "http://gowalker.org", nil)
|
||||
return p, err
|
||||
}
|
||||
|
||||
func ExampleHttpGetJSON() interface{} {
|
||||
j := com.HttpGetJSON(&http.Client{}, "http://gowalker.org", nil)
|
||||
return j
|
||||
}
|
||||
|
||||
type rawFile struct {
|
||||
name string
|
||||
rawURL string
|
||||
data []byte
|
||||
}
|
||||
|
||||
func (rf *rawFile) Name() string {
|
||||
return rf.name
|
||||
}
|
||||
|
||||
func (rf *rawFile) RawUrl() string {
|
||||
return rf.rawURL
|
||||
}
|
||||
|
||||
func (rf *rawFile) Data() []byte {
|
||||
return rf.data
|
||||
}
|
||||
|
||||
func (rf *rawFile) SetData(p []byte) {
|
||||
rf.data = p
|
||||
}
|
||||
|
||||
func ExampleFetchFiles() {
|
||||
// Code that should be outside of your function body.
|
||||
// type rawFile struct {
|
||||
// name string
|
||||
// rawURL string
|
||||
// data []byte
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) Name() string {
|
||||
// return rf.name
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) RawUrl() string {
|
||||
// return rf.rawURL
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) Data() []byte {
|
||||
// return rf.data
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) SetData(p []byte) {
|
||||
// rf.data = p
|
||||
// }
|
||||
|
||||
files := []com.RawFile{
|
||||
&rawFile{rawURL: "http://example.com"},
|
||||
&rawFile{rawURL: "http://example.com/foo"},
|
||||
}
|
||||
err := com.FetchFiles(&http.Client{}, files, nil)
|
||||
fmt.Println(err, len(files[0].Data()), len(files[1].Data()))
|
||||
}
|
||||
|
||||
func ExampleFetchFilesCurl() {
|
||||
// Code that should be outside of your function body.
|
||||
// type rawFile struct {
|
||||
// name string
|
||||
// rawURL string
|
||||
// data []byte
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) Name() string {
|
||||
// return rf.name
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) RawUrl() string {
|
||||
// return rf.rawURL
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) Data() []byte {
|
||||
// return rf.data
|
||||
// }
|
||||
|
||||
// func (rf *rawFile) SetData(p []byte) {
|
||||
// rf.data = p
|
||||
// }
|
||||
|
||||
files := []com.RawFile{
|
||||
&rawFile{rawURL: "http://example.com"},
|
||||
&rawFile{rawURL: "http://example.com/foo"},
|
||||
}
|
||||
err := com.FetchFilesCurl(files)
|
||||
fmt.Println(err, len(files[0].Data()), len(files[1].Data()))
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// regex.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleIsEmail() {
|
||||
fmt.Println(com.IsEmail("test@example.com"))
|
||||
fmt.Println(com.IsEmail("@example.com"))
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
func ExampleIsUrl() {
|
||||
fmt.Println(com.IsUrl("http://example.com"))
|
||||
fmt.Println(com.IsUrl("http//example.com"))
|
||||
// Output:
|
||||
// true
|
||||
// false
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
|
||||
// ------------------------------
|
||||
// slice.go
|
||||
// ------------------------------
|
||||
|
||||
func ExampleAppendStr() {
|
||||
s := []string{"a"}
|
||||
s = com.AppendStr(s, "a")
|
||||
s = com.AppendStr(s, "b")
|
||||
fmt.Println(s)
|
||||
// Output: [a b]
|
||||
}
|
||||
|
||||
// ------------- END ------------
|
||||
145
Godeps/_workspace/src/github.com/Unknwon/com/file.go
generated
vendored
Normal file
145
Godeps/_workspace/src/github.com/Unknwon/com/file.go
generated
vendored
Normal file
@@ -0,0 +1,145 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"math"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
// Storage unit constants.
|
||||
const (
|
||||
Byte = 1
|
||||
KByte = Byte * 1024
|
||||
MByte = KByte * 1024
|
||||
GByte = MByte * 1024
|
||||
TByte = GByte * 1024
|
||||
PByte = TByte * 1024
|
||||
EByte = PByte * 1024
|
||||
)
|
||||
|
||||
func logn(n, b float64) float64 {
|
||||
return math.Log(n) / math.Log(b)
|
||||
}
|
||||
|
||||
func humanateBytes(s uint64, base float64, sizes []string) string {
|
||||
if s < 10 {
|
||||
return fmt.Sprintf("%dB", s)
|
||||
}
|
||||
e := math.Floor(logn(float64(s), base))
|
||||
suffix := sizes[int(e)]
|
||||
val := float64(s) / math.Pow(base, math.Floor(e))
|
||||
f := "%.0f"
|
||||
if val < 10 {
|
||||
f = "%.1f"
|
||||
}
|
||||
|
||||
return fmt.Sprintf(f+"%s", val, suffix)
|
||||
}
|
||||
|
||||
// HumaneFileSize calculates the file size and generate user-friendly string.
|
||||
func HumaneFileSize(s uint64) string {
|
||||
sizes := []string{"B", "KB", "MB", "GB", "TB", "PB", "EB"}
|
||||
return humanateBytes(s, 1024, sizes)
|
||||
}
|
||||
|
||||
// FileMTime returns file modified time and possible error.
|
||||
func FileMTime(file string) (int64, error) {
|
||||
f, err := os.Stat(file)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return f.ModTime().Unix(), nil
|
||||
}
|
||||
|
||||
// FileSize returns file size in bytes and possible error.
|
||||
func FileSize(file string) (int64, error) {
|
||||
f, err := os.Stat(file)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return f.Size(), nil
|
||||
}
|
||||
|
||||
// Copy copies file from source to target path.
|
||||
func Copy(src, dest string) error {
|
||||
// Gather file information to set back later.
|
||||
si, err := os.Lstat(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Handle symbolic link.
|
||||
if si.Mode()&os.ModeSymlink != 0 {
|
||||
target, err := os.Readlink(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// NOTE: os.Chmod and os.Chtimes don't recoganize symbolic link,
|
||||
// which will lead "no such file or directory" error.
|
||||
return os.Symlink(target, dest)
|
||||
}
|
||||
|
||||
sr, err := os.Open(src)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer sr.Close()
|
||||
|
||||
dw, err := os.Create(dest)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer dw.Close()
|
||||
|
||||
if _, err = io.Copy(dw, sr); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Set back file information.
|
||||
if err = os.Chtimes(dest, si.ModTime(), si.ModTime()); err != nil {
|
||||
return err
|
||||
}
|
||||
return os.Chmod(dest, si.Mode())
|
||||
}
|
||||
|
||||
// WriteFile writes data to a file named by filename.
|
||||
// If the file does not exist, WriteFile creates it
|
||||
// and its upper level paths.
|
||||
func WriteFile(filename string, data []byte) error {
|
||||
os.MkdirAll(path.Dir(filename), os.ModePerm)
|
||||
return ioutil.WriteFile(filename, data, 0655)
|
||||
}
|
||||
|
||||
// IsFile returns true if given path is a file,
|
||||
// or returns false when it's a directory or does not exist.
|
||||
func IsFile(filePath string) bool {
|
||||
f, e := os.Stat(filePath)
|
||||
if e != nil {
|
||||
return false
|
||||
}
|
||||
return !f.IsDir()
|
||||
}
|
||||
|
||||
// IsExist checks whether a file or directory exists.
|
||||
// It returns false when the file or directory does not exist.
|
||||
func IsExist(path string) bool {
|
||||
_, err := os.Stat(path)
|
||||
return err == nil || os.IsExist(err)
|
||||
}
|
||||
61
Godeps/_workspace/src/github.com/Unknwon/com/file_test.go
generated
vendored
Normal file
61
Godeps/_workspace/src/github.com/Unknwon/com/file_test.go
generated
vendored
Normal file
@@ -0,0 +1,61 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestIsFile(t *testing.T) {
|
||||
if !IsFile("file.go") {
|
||||
t.Errorf("IsExist:\n Expect => %v\n Got => %v\n", true, false)
|
||||
}
|
||||
|
||||
if IsFile("testdata") {
|
||||
t.Errorf("IsExist:\n Expect => %v\n Got => %v\n", false, true)
|
||||
}
|
||||
|
||||
if IsFile("files.go") {
|
||||
t.Errorf("IsExist:\n Expect => %v\n Got => %v\n", false, true)
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsExist(t *testing.T) {
|
||||
Convey("Check if file or directory exists", t, func() {
|
||||
Convey("Pass a file name that exists", func() {
|
||||
So(IsExist("file.go"), ShouldEqual, true)
|
||||
})
|
||||
Convey("Pass a directory name that exists", func() {
|
||||
So(IsExist("testdata"), ShouldEqual, true)
|
||||
})
|
||||
Convey("Pass a directory name that does not exist", func() {
|
||||
So(IsExist(".hg"), ShouldEqual, false)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkIsFile(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsFile("file.go")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIsExist(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsExist("file.go")
|
||||
}
|
||||
}
|
||||
60
Godeps/_workspace/src/github.com/Unknwon/com/html.go
generated
vendored
Normal file
60
Godeps/_workspace/src/github.com/Unknwon/com/html.go
generated
vendored
Normal file
@@ -0,0 +1,60 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"html"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Html2JS converts []byte type of HTML content into JS format.
|
||||
func Html2JS(data []byte) []byte {
|
||||
s := string(data)
|
||||
s = strings.Replace(s, `\`, `\\`, -1)
|
||||
s = strings.Replace(s, "\n", `\n`, -1)
|
||||
s = strings.Replace(s, "\r", "", -1)
|
||||
s = strings.Replace(s, "\"", `\"`, -1)
|
||||
s = strings.Replace(s, "<table>", "<table>", -1)
|
||||
return []byte(s)
|
||||
}
|
||||
|
||||
// encode html chars to string
|
||||
func HtmlEncode(str string) string {
|
||||
return html.EscapeString(str)
|
||||
}
|
||||
|
||||
// decode string to html chars
|
||||
func HtmlDecode(str string) string {
|
||||
return html.UnescapeString(str)
|
||||
}
|
||||
|
||||
// strip tags in html string
|
||||
func StripTags(src string) string {
|
||||
//去除style,script,html tag
|
||||
re := regexp.MustCompile(`(?s)<(?:style|script)[^<>]*>.*?</(?:style|script)>|</?[a-z][a-z0-9]*[^<>]*>|<!--.*?-->`)
|
||||
src = re.ReplaceAllString(src, "")
|
||||
|
||||
//trim all spaces(2+) into \n
|
||||
re = regexp.MustCompile(`\s{2,}`)
|
||||
src = re.ReplaceAllString(src, "\n")
|
||||
|
||||
return strings.TrimSpace(src)
|
||||
}
|
||||
|
||||
// change \n to <br/>
|
||||
func Nl2br(str string) string {
|
||||
return strings.Replace(str, "\n", "<br/>", -1)
|
||||
}
|
||||
35
Godeps/_workspace/src/github.com/Unknwon/com/html_test.go
generated
vendored
Normal file
35
Godeps/_workspace/src/github.com/Unknwon/com/html_test.go
generated
vendored
Normal file
@@ -0,0 +1,35 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestHtml2JS(t *testing.T) {
|
||||
htm := "<div id=\"button\" class=\"btn\">Click me</div>\n\r"
|
||||
js := string(Html2JS([]byte(htm)))
|
||||
jsR := `<div id=\"button\" class=\"btn\">Click me</div>\n`
|
||||
if js != jsR {
|
||||
t.Errorf("Html2JS:\n Expect => %s\n Got => %s\n", jsR, js)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHtml2JS(b *testing.B) {
|
||||
htm := "<div id=\"button\" class=\"btn\">Click me</div>\n\r"
|
||||
for i := 0; i < b.N; i++ {
|
||||
Html2JS([]byte(htm))
|
||||
}
|
||||
}
|
||||
201
Godeps/_workspace/src/github.com/Unknwon/com/http.go
generated
vendored
Normal file
201
Godeps/_workspace/src/github.com/Unknwon/com/http.go
generated
vendored
Normal file
@@ -0,0 +1,201 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
)
|
||||
|
||||
type NotFoundError struct {
|
||||
Message string
|
||||
}
|
||||
|
||||
func (e NotFoundError) Error() string {
|
||||
return e.Message
|
||||
}
|
||||
|
||||
type RemoteError struct {
|
||||
Host string
|
||||
Err error
|
||||
}
|
||||
|
||||
func (e *RemoteError) Error() string {
|
||||
return e.Err.Error()
|
||||
}
|
||||
|
||||
var UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/29.0.1541.0 Safari/537.36"
|
||||
|
||||
// HttpCall makes HTTP method call.
|
||||
func HttpCall(client *http.Client, method, url string, header http.Header, body io.Reader) (io.ReadCloser, error) {
|
||||
req, err := http.NewRequest(method, url, body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req.Header.Set("User-Agent", UserAgent)
|
||||
for k, vs := range header {
|
||||
req.Header[k] = vs
|
||||
}
|
||||
resp, err := client.Do(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if resp.StatusCode == 200 {
|
||||
return resp.Body, nil
|
||||
}
|
||||
resp.Body.Close()
|
||||
if resp.StatusCode == 404 { // 403 can be rate limit error. || resp.StatusCode == 403 {
|
||||
err = fmt.Errorf("resource not found: %s", url)
|
||||
} else {
|
||||
err = fmt.Errorf("%s %s -> %d", method, url, resp.StatusCode)
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// HttpGet gets the specified resource.
|
||||
// ErrNotFound is returned if the server responds with status 404.
|
||||
func HttpGet(client *http.Client, url string, header http.Header) (io.ReadCloser, error) {
|
||||
return HttpCall(client, "GET", url, header, nil)
|
||||
}
|
||||
|
||||
// HttpPost posts the specified resource.
|
||||
// ErrNotFound is returned if the server responds with status 404.
|
||||
func HttpPost(client *http.Client, url string, header http.Header, body []byte) (io.ReadCloser, error) {
|
||||
return HttpCall(client, "POST", url, header, bytes.NewBuffer(body))
|
||||
}
|
||||
|
||||
// HttpGetToFile gets the specified resource and writes to file.
|
||||
// ErrNotFound is returned if the server responds with status 404.
|
||||
func HttpGetToFile(client *http.Client, url string, header http.Header, fileName string) error {
|
||||
rc, err := HttpGet(client, url, header)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
|
||||
os.MkdirAll(path.Dir(fileName), os.ModePerm)
|
||||
f, err := os.Create(fileName)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer f.Close()
|
||||
_, err = io.Copy(f, rc)
|
||||
return err
|
||||
}
|
||||
|
||||
// HttpGetBytes gets the specified resource. ErrNotFound is returned if the server
|
||||
// responds with status 404.
|
||||
func HttpGetBytes(client *http.Client, url string, header http.Header) ([]byte, error) {
|
||||
rc, err := HttpGet(client, url, header)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rc.Close()
|
||||
return ioutil.ReadAll(rc)
|
||||
}
|
||||
|
||||
// HttpGetJSON gets the specified resource and mapping to struct.
|
||||
// ErrNotFound is returned if the server responds with status 404.
|
||||
func HttpGetJSON(client *http.Client, url string, v interface{}) error {
|
||||
rc, err := HttpGet(client, url, nil)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
err = json.NewDecoder(rc).Decode(v)
|
||||
if _, ok := err.(*json.SyntaxError); ok {
|
||||
return fmt.Errorf("JSON syntax error at %s", url)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// HttpPostJSON posts the specified resource with struct values,
|
||||
// and maps results to struct.
|
||||
// ErrNotFound is returned if the server responds with status 404.
|
||||
func HttpPostJSON(client *http.Client, url string, body, v interface{}) error {
|
||||
data, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
rc, err := HttpPost(client, url, http.Header{"content-type": []string{"application/json"}}, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer rc.Close()
|
||||
err = json.NewDecoder(rc).Decode(v)
|
||||
if _, ok := err.(*json.SyntaxError); ok {
|
||||
return fmt.Errorf("JSON syntax error at %s", url)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// A RawFile describes a file that can be downloaded.
|
||||
type RawFile interface {
|
||||
Name() string
|
||||
RawUrl() string
|
||||
Data() []byte
|
||||
SetData([]byte)
|
||||
}
|
||||
|
||||
// FetchFiles fetches files specified by the rawURL field in parallel.
|
||||
func FetchFiles(client *http.Client, files []RawFile, header http.Header) error {
|
||||
ch := make(chan error, len(files))
|
||||
for i := range files {
|
||||
go func(i int) {
|
||||
p, err := HttpGetBytes(client, files[i].RawUrl(), nil)
|
||||
if err != nil {
|
||||
ch <- err
|
||||
return
|
||||
}
|
||||
files[i].SetData(p)
|
||||
ch <- nil
|
||||
}(i)
|
||||
}
|
||||
for _ = range files {
|
||||
if err := <-ch; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// FetchFiles uses command `curl` to fetch files specified by the rawURL field in parallel.
|
||||
func FetchFilesCurl(files []RawFile, curlOptions ...string) error {
|
||||
ch := make(chan error, len(files))
|
||||
for i := range files {
|
||||
go func(i int) {
|
||||
stdout, _, err := ExecCmd("curl", append(curlOptions, files[i].RawUrl())...)
|
||||
if err != nil {
|
||||
ch <- err
|
||||
return
|
||||
}
|
||||
|
||||
files[i].SetData([]byte(stdout))
|
||||
ch <- nil
|
||||
}(i)
|
||||
}
|
||||
for _ = range files {
|
||||
if err := <-ch; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
111
Godeps/_workspace/src/github.com/Unknwon/com/http_test.go
generated
vendored
Normal file
111
Godeps/_workspace/src/github.com/Unknwon/com/http_test.go
generated
vendored
Normal file
@@ -0,0 +1,111 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
var examplePrefix = `<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<title>Example Domain</title>
|
||||
`
|
||||
|
||||
func TestHttpGet(t *testing.T) {
|
||||
// 200.
|
||||
rc, err := HttpGet(&http.Client{}, "http://example.com", nil)
|
||||
if err != nil {
|
||||
t.Fatalf("HttpGet:\n Expect => %v\n Got => %s\n", nil, err)
|
||||
}
|
||||
p, err := ioutil.ReadAll(rc)
|
||||
if err != nil {
|
||||
t.Errorf("HttpGet:\n Expect => %v\n Got => %s\n", nil, err)
|
||||
}
|
||||
s := string(p)
|
||||
if !strings.HasPrefix(s, examplePrefix) {
|
||||
t.Errorf("HttpGet:\n Expect => %s\n Got => %s\n", examplePrefix, s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHttpGetBytes(t *testing.T) {
|
||||
p, err := HttpGetBytes(&http.Client{}, "http://example.com", nil)
|
||||
if err != nil {
|
||||
t.Errorf("HttpGetBytes:\n Expect => %v\n Got => %s\n", nil, err)
|
||||
}
|
||||
s := string(p)
|
||||
if !strings.HasPrefix(s, examplePrefix) {
|
||||
t.Errorf("HttpGet:\n Expect => %s\n Got => %s\n", examplePrefix, s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestHttpGetJSON(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
type rawFile struct {
|
||||
name string
|
||||
rawURL string
|
||||
data []byte
|
||||
}
|
||||
|
||||
func (rf *rawFile) Name() string {
|
||||
return rf.name
|
||||
}
|
||||
|
||||
func (rf *rawFile) RawUrl() string {
|
||||
return rf.rawURL
|
||||
}
|
||||
|
||||
func (rf *rawFile) Data() []byte {
|
||||
return rf.data
|
||||
}
|
||||
|
||||
func (rf *rawFile) SetData(p []byte) {
|
||||
rf.data = p
|
||||
}
|
||||
|
||||
func TestFetchFiles(t *testing.T) {
|
||||
files := []RawFile{
|
||||
&rawFile{rawURL: "http://example.com"},
|
||||
&rawFile{rawURL: "http://example.com"},
|
||||
}
|
||||
err := FetchFiles(&http.Client{}, files, nil)
|
||||
if err != nil {
|
||||
t.Errorf("FetchFiles:\n Expect => %v\n Got => %s\n", nil, err)
|
||||
} else if len(files[0].Data()) != 1270 {
|
||||
t.Errorf("FetchFiles:\n Expect => %d\n Got => %d\n", 1270, len(files[0].Data()))
|
||||
} else if len(files[1].Data()) != 1270 {
|
||||
t.Errorf("FetchFiles:\n Expect => %d\n Got => %d\n", 1270, len(files[1].Data()))
|
||||
}
|
||||
}
|
||||
|
||||
func TestFetchFilesCurl(t *testing.T) {
|
||||
files := []RawFile{
|
||||
&rawFile{rawURL: "http://example.com"},
|
||||
&rawFile{rawURL: "http://example.com"},
|
||||
}
|
||||
err := FetchFilesCurl(files)
|
||||
if err != nil {
|
||||
t.Errorf("FetchFilesCurl:\n Expect => %v\n Got => %s\n", nil, err)
|
||||
} else if len(files[0].Data()) != 1270 {
|
||||
t.Errorf("FetchFilesCurl:\n Expect => %d\n Got => %d\n", 1270, len(files[0].Data()))
|
||||
} else if len(files[1].Data()) != 1270 {
|
||||
t.Errorf("FetchFilesCurl:\n Expect => %d\n Got => %d\n", 1270, len(files[1].Data()))
|
||||
}
|
||||
}
|
||||
24
Godeps/_workspace/src/github.com/Unknwon/com/math.go
generated
vendored
Normal file
24
Godeps/_workspace/src/github.com/Unknwon/com/math.go
generated
vendored
Normal file
@@ -0,0 +1,24 @@
|
||||
// Copyright 2014 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
// PowInt is int type of math.Pow function.
|
||||
func PowInt(x int, y int) int {
|
||||
num := 1
|
||||
for i := 0; i < y; i++ {
|
||||
num *= x
|
||||
}
|
||||
return num
|
||||
}
|
||||
80
Godeps/_workspace/src/github.com/Unknwon/com/path.go
generated
vendored
Normal file
80
Godeps/_workspace/src/github.com/Unknwon/com/path.go
generated
vendored
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// GetGOPATHs returns all paths in GOPATH variable.
|
||||
func GetGOPATHs() []string {
|
||||
gopath := os.Getenv("GOPATH")
|
||||
var paths []string
|
||||
if runtime.GOOS == "windows" {
|
||||
gopath = strings.Replace(gopath, "\\", "/", -1)
|
||||
paths = strings.Split(gopath, ";")
|
||||
} else {
|
||||
paths = strings.Split(gopath, ":")
|
||||
}
|
||||
return paths
|
||||
}
|
||||
|
||||
// GetSrcPath returns app. source code path.
|
||||
// It only works when you have src. folder in GOPATH,
|
||||
// it returns error not able to locate source folder path.
|
||||
func GetSrcPath(importPath string) (appPath string, err error) {
|
||||
paths := GetGOPATHs()
|
||||
for _, p := range paths {
|
||||
if IsExist(p + "/src/" + importPath + "/") {
|
||||
appPath = p + "/src/" + importPath + "/"
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if len(appPath) == 0 {
|
||||
return "", errors.New("Unable to locate source folder path")
|
||||
}
|
||||
|
||||
appPath = filepath.Dir(appPath) + "/"
|
||||
if runtime.GOOS == "windows" {
|
||||
// Replace all '\' to '/'.
|
||||
appPath = strings.Replace(appPath, "\\", "/", -1)
|
||||
}
|
||||
|
||||
return appPath, nil
|
||||
}
|
||||
|
||||
// HomeDir returns path of '~'(in Linux) on Windows,
|
||||
// it returns error when the variable does not exist.
|
||||
func HomeDir() (home string, err error) {
|
||||
if runtime.GOOS == "windows" {
|
||||
home = os.Getenv("HOMEDRIVE") + os.Getenv("HOMEPATH")
|
||||
if home == "" {
|
||||
home = os.Getenv("USERPROFILE")
|
||||
}
|
||||
} else {
|
||||
home = os.Getenv("HOME")
|
||||
}
|
||||
|
||||
if len(home) == 0 {
|
||||
return "", errors.New("Cannot specify home directory because it's empty")
|
||||
}
|
||||
|
||||
return home, nil
|
||||
}
|
||||
67
Godeps/_workspace/src/github.com/Unknwon/com/path_test.go
generated
vendored
Normal file
67
Godeps/_workspace/src/github.com/Unknwon/com/path_test.go
generated
vendored
Normal file
@@ -0,0 +1,67 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"os"
|
||||
"runtime"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestGetGOPATHs(t *testing.T) {
|
||||
var gpsR []string
|
||||
|
||||
if runtime.GOOS != "windows" {
|
||||
gpsR = []string{"path/to/gopath1", "path/to/gopath2", "path/to/gopath3"}
|
||||
os.Setenv("GOPATH", "path/to/gopath1:path/to/gopath2:path/to/gopath3")
|
||||
} else {
|
||||
gpsR = []string{"path/to/gopath1", "path/to/gopath2", "path/to/gopath3"}
|
||||
os.Setenv("GOPATH", "path\\to\\gopath1;path\\to\\gopath2;path\\to\\gopath3")
|
||||
}
|
||||
|
||||
gps := GetGOPATHs()
|
||||
if !CompareSliceStr(gps, gpsR) {
|
||||
t.Errorf("GetGOPATHs:\n Expect => %s\n Got => %s\n", gpsR, gps)
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetSrcPath(t *testing.T) {
|
||||
|
||||
}
|
||||
|
||||
func TestHomeDir(t *testing.T) {
|
||||
_, err := HomeDir()
|
||||
if err != nil {
|
||||
t.Errorf("HomeDir:\n Expect => %v\n Got => %s\n", nil, err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGetGOPATHs(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
GetGOPATHs()
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkGetSrcPath(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
GetSrcPath("github.com/Unknwon/com")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkHomeDir(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
HomeDir()
|
||||
}
|
||||
}
|
||||
56
Godeps/_workspace/src/github.com/Unknwon/com/regex.go
generated
vendored
Normal file
56
Godeps/_workspace/src/github.com/Unknwon/com/regex.go
generated
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import "regexp"
|
||||
|
||||
const (
|
||||
regex_email_pattern = `(?i)[A-Z0-9._%+-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,6}`
|
||||
regex_strict_email_pattern = `(?i)[A-Z0-9!#$%&'*+/=?^_{|}~-]+` +
|
||||
`(?:\.[A-Z0-9!#$%&'*+/=?^_{|}~-]+)*` +
|
||||
`@(?:[A-Z0-9](?:[A-Z0-9-]*[A-Z0-9])?\.)+` +
|
||||
`[A-Z0-9](?:[A-Z0-9-]*[A-Z0-9])?`
|
||||
regex_url_pattern = `(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?`
|
||||
)
|
||||
|
||||
var (
|
||||
regex_email *regexp.Regexp
|
||||
regex_strict_email *regexp.Regexp
|
||||
regex_url *regexp.Regexp
|
||||
)
|
||||
|
||||
func init() {
|
||||
regex_email = regexp.MustCompile(regex_email_pattern)
|
||||
regex_strict_email = regexp.MustCompile(regex_strict_email_pattern)
|
||||
regex_url = regexp.MustCompile(regex_url_pattern)
|
||||
}
|
||||
|
||||
// validate string is an email address, if not return false
|
||||
// basically validation can match 99% cases
|
||||
func IsEmail(email string) bool {
|
||||
return regex_email.MatchString(email)
|
||||
}
|
||||
|
||||
// validate string is an email address, if not return false
|
||||
// this validation omits RFC 2822
|
||||
func IsEmailRFC(email string) bool {
|
||||
return regex_strict_email.MatchString(email)
|
||||
}
|
||||
|
||||
// validate string is a url link, if not return false
|
||||
// simple validation can match 99% cases
|
||||
func IsUrl(url string) bool {
|
||||
return regex_url.MatchString(url)
|
||||
}
|
||||
70
Godeps/_workspace/src/github.com/Unknwon/com/regex_test.go
generated
vendored
Normal file
70
Godeps/_workspace/src/github.com/Unknwon/com/regex_test.go
generated
vendored
Normal file
@@ -0,0 +1,70 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsEmail(t *testing.T) {
|
||||
emails := map[string]bool{
|
||||
`test@example.com`: true,
|
||||
`single-character@b.org`: true,
|
||||
`uncommon_address@test.museum`: true,
|
||||
`local@sld.UPPER`: true,
|
||||
`@missing.org`: false,
|
||||
`missing@.com`: false,
|
||||
`missing@qq.`: false,
|
||||
`wrong-ip@127.1.1.1.26`: false,
|
||||
}
|
||||
for e, r := range emails {
|
||||
b := IsEmail(e)
|
||||
if b != r {
|
||||
t.Errorf("IsEmail:\n Expect => %v\n Got => %v\n", r, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestIsUrl(t *testing.T) {
|
||||
urls := map[string]bool{
|
||||
"http://www.example.com": true,
|
||||
"http://example.com": true,
|
||||
"http://example.com?user=test&password=test": true,
|
||||
"http://example.com?user=test#login": true,
|
||||
"ftp://example.com": true,
|
||||
"https://example.com": true,
|
||||
"htp://example.com": false,
|
||||
"http//example.com": false,
|
||||
"http://example": true,
|
||||
}
|
||||
for u, r := range urls {
|
||||
b := IsUrl(u)
|
||||
if b != r {
|
||||
t.Errorf("IsUrl:\n Expect => %v\n Got => %v\n", r, b)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIsEmail(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsEmail("test@example.com")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIsUrl(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsEmail("http://example.com")
|
||||
}
|
||||
}
|
||||
87
Godeps/_workspace/src/github.com/Unknwon/com/slice.go
generated
vendored
Normal file
87
Godeps/_workspace/src/github.com/Unknwon/com/slice.go
generated
vendored
Normal file
@@ -0,0 +1,87 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"strings"
|
||||
)
|
||||
|
||||
// AppendStr appends string to slice with no duplicates.
|
||||
func AppendStr(strs []string, str string) []string {
|
||||
for _, s := range strs {
|
||||
if s == str {
|
||||
return strs
|
||||
}
|
||||
}
|
||||
return append(strs, str)
|
||||
}
|
||||
|
||||
// CompareSliceStr compares two 'string' type slices.
|
||||
// It returns true if elements and order are both the same.
|
||||
func CompareSliceStr(s1, s2 []string) bool {
|
||||
if len(s1) != len(s2) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range s1 {
|
||||
if s1[i] != s2[i] {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// CompareSliceStr compares two 'string' type slices.
|
||||
// It returns true if elements are the same, and ignores the order.
|
||||
func CompareSliceStrU(s1, s2 []string) bool {
|
||||
if len(s1) != len(s2) {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := range s1 {
|
||||
for j := len(s2) - 1; j >= 0; j-- {
|
||||
if s1[i] == s2[j] {
|
||||
s2 = append(s2[:j], s2[j+1:]...)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if len(s2) > 0 {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
// IsSliceContainsStr returns true if the string exists in given slice, ignore case.
|
||||
func IsSliceContainsStr(sl []string, str string) bool {
|
||||
str = strings.ToLower(str)
|
||||
for _, s := range sl {
|
||||
if strings.ToLower(s) == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// IsSliceContainsInt64 returns true if the int64 exists in given slice.
|
||||
func IsSliceContainsInt64(sl []int64, i int64) bool {
|
||||
for _, s := range sl {
|
||||
if s == i {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
99
Godeps/_workspace/src/github.com/Unknwon/com/slice_test.go
generated
vendored
Normal file
99
Godeps/_workspace/src/github.com/Unknwon/com/slice_test.go
generated
vendored
Normal file
@@ -0,0 +1,99 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
|
||||
. "github.com/smartystreets/goconvey/convey"
|
||||
)
|
||||
|
||||
func TestAppendStr(t *testing.T) {
|
||||
Convey("Append a string to a slice with no duplicates", t, func() {
|
||||
s := []string{"a"}
|
||||
|
||||
Convey("Append a string that does not exist in slice", func() {
|
||||
s = AppendStr(s, "b")
|
||||
So(len(s), ShouldEqual, 2)
|
||||
})
|
||||
|
||||
Convey("Append a string that does exist in slice", func() {
|
||||
s = AppendStr(s, "b")
|
||||
So(len(s), ShouldEqual, 2)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestCompareSliceStr(t *testing.T) {
|
||||
Convey("Compares two 'string' type slices with elements and order", t, func() {
|
||||
Convey("Compare two slices that do have same elements and order", func() {
|
||||
So(CompareSliceStr(
|
||||
[]string{"1", "2", "3"}, []string{"1", "2", "3"}), ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("Compare two slices that do have same elements but does not have same order", func() {
|
||||
So(!CompareSliceStr(
|
||||
[]string{"2", "1", "3"}, []string{"1", "2", "3"}), ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("Compare two slices that have different number of elements", func() {
|
||||
So(!CompareSliceStr(
|
||||
[]string{"2", "1"}, []string{"1", "2", "3"}), ShouldBeTrue)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func TestCompareSliceStrU(t *testing.T) {
|
||||
Convey("Compare two 'string' type slices with elements and ignore the order", t, func() {
|
||||
Convey("Compare two slices that do have same elements and order", func() {
|
||||
So(CompareSliceStrU(
|
||||
[]string{"1", "2", "3"}, []string{"1", "2", "3"}), ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("Compare two slices that do have same elements but does not have same order", func() {
|
||||
So(CompareSliceStrU(
|
||||
[]string{"2", "1", "3"}, []string{"1", "2", "3"}), ShouldBeTrue)
|
||||
})
|
||||
|
||||
Convey("Compare two slices that have different number of elements", func() {
|
||||
So(!CompareSliceStrU(
|
||||
[]string{"2", "1"}, []string{"1", "2", "3"}), ShouldBeTrue)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
func BenchmarkAppendStr(b *testing.B) {
|
||||
s := []string{"a"}
|
||||
for i := 0; i < b.N; i++ {
|
||||
s = AppendStr(s, fmt.Sprint(b.N%3))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompareSliceStr(b *testing.B) {
|
||||
s1 := []string{"1", "2", "3"}
|
||||
s2 := []string{"1", "2", "3"}
|
||||
for i := 0; i < b.N; i++ {
|
||||
CompareSliceStr(s1, s2)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkCompareSliceStrU(b *testing.B) {
|
||||
s1 := []string{"1", "4", "2", "3"}
|
||||
s2 := []string{"1", "2", "3", "4"}
|
||||
for i := 0; i < b.N; i++ {
|
||||
CompareSliceStrU(s1, s2)
|
||||
}
|
||||
}
|
||||
140
Godeps/_workspace/src/github.com/Unknwon/com/string.go
generated
vendored
Normal file
140
Godeps/_workspace/src/github.com/Unknwon/com/string.go
generated
vendored
Normal file
@@ -0,0 +1,140 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/rand"
|
||||
"encoding/base64"
|
||||
"errors"
|
||||
"io"
|
||||
r "math/rand"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// AESEncrypt encrypts text and given key with AES.
|
||||
func AESEncrypt(key, text []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b := base64.StdEncoding.EncodeToString(text)
|
||||
ciphertext := make([]byte, aes.BlockSize+len(b))
|
||||
iv := ciphertext[:aes.BlockSize]
|
||||
if _, err := io.ReadFull(rand.Reader, iv); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
cfb := cipher.NewCFBEncrypter(block, iv)
|
||||
cfb.XORKeyStream(ciphertext[aes.BlockSize:], []byte(b))
|
||||
return ciphertext, nil
|
||||
}
|
||||
|
||||
// AESDecrypt decrypts text and given key with AES.
|
||||
func AESDecrypt(key, text []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(text) < aes.BlockSize {
|
||||
return nil, errors.New("ciphertext too short")
|
||||
}
|
||||
iv := text[:aes.BlockSize]
|
||||
text = text[aes.BlockSize:]
|
||||
cfb := cipher.NewCFBDecrypter(block, iv)
|
||||
cfb.XORKeyStream(text, text)
|
||||
data, err := base64.StdEncoding.DecodeString(string(text))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// IsLetter returns true if the 'l' is an English letter.
|
||||
func IsLetter(l uint8) bool {
|
||||
n := (l | 0x20) - 'a'
|
||||
if n >= 0 && n < 26 {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// Expand replaces {k} in template with match[k] or subs[atoi(k)] if k is not in match.
|
||||
func Expand(template string, match map[string]string, subs ...string) string {
|
||||
var p []byte
|
||||
var i int
|
||||
for {
|
||||
i = strings.Index(template, "{")
|
||||
if i < 0 {
|
||||
break
|
||||
}
|
||||
p = append(p, template[:i]...)
|
||||
template = template[i+1:]
|
||||
i = strings.Index(template, "}")
|
||||
if s, ok := match[template[:i]]; ok {
|
||||
p = append(p, s...)
|
||||
} else {
|
||||
j, _ := strconv.Atoi(template[:i])
|
||||
if j >= len(subs) {
|
||||
p = append(p, []byte("Missing")...)
|
||||
} else {
|
||||
p = append(p, subs[j]...)
|
||||
}
|
||||
}
|
||||
template = template[i+1:]
|
||||
}
|
||||
p = append(p, template...)
|
||||
return string(p)
|
||||
}
|
||||
|
||||
// Reverse s string, support unicode
|
||||
func Reverse(s string) string {
|
||||
n := len(s)
|
||||
runes := make([]rune, n)
|
||||
for _, rune := range s {
|
||||
n--
|
||||
runes[n] = rune
|
||||
}
|
||||
return string(runes[n:])
|
||||
}
|
||||
|
||||
// RandomCreateBytes generate random []byte by specify chars.
|
||||
func RandomCreateBytes(n int, alphabets ...byte) []byte {
|
||||
const alphanum = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||||
var bytes = make([]byte, n)
|
||||
var randby bool
|
||||
if num, err := rand.Read(bytes); num != n || err != nil {
|
||||
r.Seed(time.Now().UnixNano())
|
||||
randby = true
|
||||
}
|
||||
for i, b := range bytes {
|
||||
if len(alphabets) == 0 {
|
||||
if randby {
|
||||
bytes[i] = alphanum[r.Intn(len(alphanum))]
|
||||
} else {
|
||||
bytes[i] = alphanum[b%byte(len(alphanum))]
|
||||
}
|
||||
} else {
|
||||
if randby {
|
||||
bytes[i] = alphabets[r.Intn(len(alphabets))]
|
||||
} else {
|
||||
bytes[i] = alphabets[b%byte(len(alphabets))]
|
||||
}
|
||||
}
|
||||
}
|
||||
return bytes
|
||||
}
|
||||
82
Godeps/_workspace/src/github.com/Unknwon/com/string_test.go
generated
vendored
Normal file
82
Godeps/_workspace/src/github.com/Unknwon/com/string_test.go
generated
vendored
Normal file
@@ -0,0 +1,82 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestIsLetter(t *testing.T) {
|
||||
if IsLetter('1') {
|
||||
t.Errorf("IsLetter:\n Expect => %v\n Got => %v\n", false, true)
|
||||
}
|
||||
|
||||
if IsLetter('[') {
|
||||
t.Errorf("IsLetter:\n Expect => %v\n Got => %v\n", false, true)
|
||||
}
|
||||
|
||||
if !IsLetter('a') {
|
||||
t.Errorf("IsLetter:\n Expect => %v\n Got => %v\n", true, false)
|
||||
}
|
||||
|
||||
if !IsLetter('Z') {
|
||||
t.Errorf("IsLetter:\n Expect => %v\n Got => %v\n", true, false)
|
||||
}
|
||||
}
|
||||
|
||||
func TestExpand(t *testing.T) {
|
||||
match := map[string]string{
|
||||
"domain": "gowalker.org",
|
||||
"subdomain": "github.com",
|
||||
}
|
||||
s := "http://{domain}/{subdomain}/{0}/{1}"
|
||||
sR := "http://gowalker.org/github.com/Unknwon/gowalker"
|
||||
if Expand(s, match, "Unknwon", "gowalker") != sR {
|
||||
t.Errorf("Expand:\n Expect => %s\n Got => %s\n", sR, s)
|
||||
}
|
||||
}
|
||||
|
||||
func TestReverse(t *testing.T) {
|
||||
if Reverse("abcdefg") != "gfedcba" {
|
||||
t.Errorf("Reverse:\n Except => %s\n Got =>%s\n", "gfedcba", Reverse("abcdefg"))
|
||||
}
|
||||
if Reverse("上善若水厚德载物") != "物载德厚水若善上" {
|
||||
t.Errorf("Reverse:\n Except => %s\n Got =>%s\n", "物载德厚水若善上", Reverse("上善若水厚德载物"))
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkIsLetter(b *testing.B) {
|
||||
for i := 0; i < b.N; i++ {
|
||||
IsLetter('a')
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkExpand(b *testing.B) {
|
||||
match := map[string]string{
|
||||
"domain": "gowalker.org",
|
||||
"subdomain": "github.com",
|
||||
}
|
||||
s := "http://{domain}/{subdomain}/{0}/{1}"
|
||||
for i := 0; i < b.N; i++ {
|
||||
Expand(s, match, "Unknwon", "gowalker")
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkReverse(b *testing.B) {
|
||||
s := "abscef中文"
|
||||
for i := 0; i < b.N; i++ {
|
||||
Reverse(s)
|
||||
}
|
||||
}
|
||||
1
Godeps/_workspace/src/github.com/Unknwon/com/testdata/SaveFile.txt
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/Unknwon/com/testdata/SaveFile.txt
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
TestSaveFile
|
||||
1
Godeps/_workspace/src/github.com/Unknwon/com/testdata/SaveFileS.txt
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/Unknwon/com/testdata/SaveFileS.txt
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
TestSaveFileS
|
||||
0
Godeps/_workspace/src/github.com/Unknwon/com/testdata/sample_file.txt
generated
vendored
Normal file
0
Godeps/_workspace/src/github.com/Unknwon/com/testdata/sample_file.txt
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/Unknwon/com/testdata/statDir/SaveFile.txt
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/Unknwon/com/testdata/statDir/SaveFile.txt
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
TestSaveFile
|
||||
1
Godeps/_workspace/src/github.com/Unknwon/com/testdata/statDir/SaveFileS.txt
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/Unknwon/com/testdata/statDir/SaveFileS.txt
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
TestSaveFileS
|
||||
0
Godeps/_workspace/src/github.com/Unknwon/com/testdata/statDir/sample_file.txt
generated
vendored
Normal file
0
Godeps/_workspace/src/github.com/Unknwon/com/testdata/statDir/sample_file.txt
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/Unknwon/com/testdata/statDir/secondLevel/SaveFile.txt
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/Unknwon/com/testdata/statDir/secondLevel/SaveFile.txt
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
TestSaveFile
|
||||
1
Godeps/_workspace/src/github.com/Unknwon/com/testdata/statDir/secondLevel/SaveFileS.txt
generated
vendored
Normal file
1
Godeps/_workspace/src/github.com/Unknwon/com/testdata/statDir/secondLevel/SaveFileS.txt
generated
vendored
Normal file
@@ -0,0 +1 @@
|
||||
TestSaveFileS
|
||||
0
Godeps/_workspace/src/github.com/Unknwon/com/testdata/statDir/secondLevel/sample_file.txt
generated
vendored
Normal file
0
Godeps/_workspace/src/github.com/Unknwon/com/testdata/statDir/secondLevel/sample_file.txt
generated
vendored
Normal file
115
Godeps/_workspace/src/github.com/Unknwon/com/time.go
generated
vendored
Normal file
115
Godeps/_workspace/src/github.com/Unknwon/com/time.go
generated
vendored
Normal file
@@ -0,0 +1,115 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// Format unix time int64 to string
|
||||
func Date(ti int64, format string) string {
|
||||
t := time.Unix(int64(ti), 0)
|
||||
return DateT(t, format)
|
||||
}
|
||||
|
||||
// Format unix time string to string
|
||||
func DateS(ts string, format string) string {
|
||||
i, _ := strconv.ParseInt(ts, 10, 64)
|
||||
return Date(i, format)
|
||||
}
|
||||
|
||||
// Format time.Time struct to string
|
||||
// MM - month - 01
|
||||
// M - month - 1, single bit
|
||||
// DD - day - 02
|
||||
// D - day 2
|
||||
// YYYY - year - 2006
|
||||
// YY - year - 06
|
||||
// HH - 24 hours - 03
|
||||
// H - 24 hours - 3
|
||||
// hh - 12 hours - 03
|
||||
// h - 12 hours - 3
|
||||
// mm - minute - 04
|
||||
// m - minute - 4
|
||||
// ss - second - 05
|
||||
// s - second = 5
|
||||
func DateT(t time.Time, format string) string {
|
||||
res := strings.Replace(format, "MM", t.Format("01"), -1)
|
||||
res = strings.Replace(res, "M", t.Format("1"), -1)
|
||||
res = strings.Replace(res, "DD", t.Format("02"), -1)
|
||||
res = strings.Replace(res, "D", t.Format("2"), -1)
|
||||
res = strings.Replace(res, "YYYY", t.Format("2006"), -1)
|
||||
res = strings.Replace(res, "YY", t.Format("06"), -1)
|
||||
res = strings.Replace(res, "HH", fmt.Sprintf("%02d", t.Hour()), -1)
|
||||
res = strings.Replace(res, "H", fmt.Sprintf("%d", t.Hour()), -1)
|
||||
res = strings.Replace(res, "hh", t.Format("03"), -1)
|
||||
res = strings.Replace(res, "h", t.Format("3"), -1)
|
||||
res = strings.Replace(res, "mm", t.Format("04"), -1)
|
||||
res = strings.Replace(res, "m", t.Format("4"), -1)
|
||||
res = strings.Replace(res, "ss", t.Format("05"), -1)
|
||||
res = strings.Replace(res, "s", t.Format("5"), -1)
|
||||
return res
|
||||
}
|
||||
|
||||
// DateFormat pattern rules.
|
||||
var datePatterns = []string{
|
||||
// year
|
||||
"Y", "2006", // A full numeric representation of a year, 4 digits Examples: 1999 or 2003
|
||||
"y", "06", //A two digit representation of a year Examples: 99 or 03
|
||||
|
||||
// month
|
||||
"m", "01", // Numeric representation of a month, with leading zeros 01 through 12
|
||||
"n", "1", // Numeric representation of a month, without leading zeros 1 through 12
|
||||
"M", "Jan", // A short textual representation of a month, three letters Jan through Dec
|
||||
"F", "January", // A full textual representation of a month, such as January or March January through December
|
||||
|
||||
// day
|
||||
"d", "02", // Day of the month, 2 digits with leading zeros 01 to 31
|
||||
"j", "2", // Day of the month without leading zeros 1 to 31
|
||||
|
||||
// week
|
||||
"D", "Mon", // A textual representation of a day, three letters Mon through Sun
|
||||
"l", "Monday", // A full textual representation of the day of the week Sunday through Saturday
|
||||
|
||||
// time
|
||||
"g", "3", // 12-hour format of an hour without leading zeros 1 through 12
|
||||
"G", "15", // 24-hour format of an hour without leading zeros 0 through 23
|
||||
"h", "03", // 12-hour format of an hour with leading zeros 01 through 12
|
||||
"H", "15", // 24-hour format of an hour with leading zeros 00 through 23
|
||||
|
||||
"a", "pm", // Lowercase Ante meridiem and Post meridiem am or pm
|
||||
"A", "PM", // Uppercase Ante meridiem and Post meridiem AM or PM
|
||||
|
||||
"i", "04", // Minutes with leading zeros 00 to 59
|
||||
"s", "05", // Seconds, with leading zeros 00 through 59
|
||||
|
||||
// time zone
|
||||
"T", "MST",
|
||||
"P", "-07:00",
|
||||
"O", "-0700",
|
||||
|
||||
// RFC 2822
|
||||
"r", time.RFC1123Z,
|
||||
}
|
||||
|
||||
// Parse Date use PHP time format.
|
||||
func DateParse(dateString, format string) (time.Time, error) {
|
||||
replacer := strings.NewReplacer(datePatterns...)
|
||||
format = replacer.Replace(format)
|
||||
return time.ParseInLocation(format, dateString, time.Local)
|
||||
}
|
||||
41
Godeps/_workspace/src/github.com/Unknwon/com/url.go
generated
vendored
Normal file
41
Godeps/_workspace/src/github.com/Unknwon/com/url.go
generated
vendored
Normal file
@@ -0,0 +1,41 @@
|
||||
// Copyright 2013 com authors
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License"): you may
|
||||
// not use this file except in compliance with the License. You may obtain
|
||||
// a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
// License for the specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package com
|
||||
|
||||
import (
|
||||
"encoding/base64"
|
||||
"net/url"
|
||||
)
|
||||
|
||||
// url encode string, is + not %20
|
||||
func UrlEncode(str string) string {
|
||||
return url.QueryEscape(str)
|
||||
}
|
||||
|
||||
// url decode string
|
||||
func UrlDecode(str string) (string, error) {
|
||||
return url.QueryUnescape(str)
|
||||
}
|
||||
|
||||
// base64 encode
|
||||
func Base64Encode(str string) string {
|
||||
return base64.StdEncoding.EncodeToString([]byte(str))
|
||||
}
|
||||
|
||||
// base64 decode
|
||||
func Base64Decode(str string) (string, error) {
|
||||
s, e := base64.StdEncoding.DecodeString(str)
|
||||
return string(s), e
|
||||
}
|
||||
202
Godeps/_workspace/src/github.com/aws/aws-sdk-go/LICENSE.txt
generated
vendored
Normal file
202
Godeps/_workspace/src/github.com/aws/aws-sdk-go/LICENSE.txt
generated
vendored
Normal file
@@ -0,0 +1,202 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
3
Godeps/_workspace/src/github.com/aws/aws-sdk-go/NOTICE.txt
generated
vendored
Normal file
3
Godeps/_workspace/src/github.com/aws/aws-sdk-go/NOTICE.txt
generated
vendored
Normal file
@@ -0,0 +1,3 @@
|
||||
AWS SDK for Go
|
||||
Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
||||
Copyright 2014-2015 Stripe, Inc.
|
||||
105
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr/error.go
generated
vendored
Normal file
105
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr/error.go
generated
vendored
Normal file
@@ -0,0 +1,105 @@
|
||||
// Package awserr represents API error interface accessors for the SDK.
|
||||
package awserr
|
||||
|
||||
// An Error wraps lower level errors with code, message and an original error.
|
||||
// The underlying concrete error type may also satisfy other interfaces which
|
||||
// can be to used to obtain more specific information about the error.
|
||||
//
|
||||
// Calling Error() or String() will always include the full information about
|
||||
// an error based on its underlying type.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// output, err := s3manage.Upload(svc, input, opts)
|
||||
// if err != nil {
|
||||
// if awsErr, ok := err.(awserr.Error); ok {
|
||||
// // Get error details
|
||||
// log.Println("Error:", err.Code(), err.Message())
|
||||
//
|
||||
// // Prints out full error message, including original error if there was one.
|
||||
// log.Println("Error:", err.Error())
|
||||
//
|
||||
// // Get original error
|
||||
// if origErr := err.Err(); origErr != nil {
|
||||
// // operate on original error.
|
||||
// }
|
||||
// } else {
|
||||
// fmt.Println(err.Error())
|
||||
// }
|
||||
// }
|
||||
//
|
||||
type Error interface {
|
||||
// Satisfy the generic error interface.
|
||||
error
|
||||
|
||||
// Returns the short phrase depicting the classification of the error.
|
||||
Code() string
|
||||
|
||||
// Returns the error details message.
|
||||
Message() string
|
||||
|
||||
// Returns the original error if one was set. Nil is returned if not set.
|
||||
OrigErr() error
|
||||
}
|
||||
|
||||
// New returns an Error object described by the code, message, and origErr.
|
||||
//
|
||||
// If origErr satisfies the Error interface it will not be wrapped within a new
|
||||
// Error object and will instead be returned.
|
||||
func New(code, message string, origErr error) Error {
|
||||
if e, ok := origErr.(Error); ok && e != nil {
|
||||
return e
|
||||
}
|
||||
return newBaseError(code, message, origErr)
|
||||
}
|
||||
|
||||
// A RequestFailure is an interface to extract request failure information from
|
||||
// an Error such as the request ID of the failed request returned by a service.
|
||||
// RequestFailures may not always have a requestID value if the request failed
|
||||
// prior to reaching the service such as a connection error.
|
||||
//
|
||||
// Example:
|
||||
//
|
||||
// output, err := s3manage.Upload(svc, input, opts)
|
||||
// if err != nil {
|
||||
// if reqerr, ok := err.(RequestFailure); ok {
|
||||
// log.Printf("Request failed", reqerr.Code(), reqerr.Message(), reqerr.RequestID())
|
||||
// } else {
|
||||
// log.Printf("Error:", err.Error()
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// Combined with awserr.Error:
|
||||
//
|
||||
// output, err := s3manage.Upload(svc, input, opts)
|
||||
// if err != nil {
|
||||
// if awsErr, ok := err.(awserr.Error); ok {
|
||||
// // Generic AWS Error with Code, Message, and original error (if any)
|
||||
// fmt.Println(awsErr.Code(), awsErr.Message(), awsErr.OrigErr())
|
||||
//
|
||||
// if reqErr, ok := err.(awserr.RequestFailure); ok {
|
||||
// // A service error occurred
|
||||
// fmt.Println(reqErr.StatusCode(), reqErr.RequestID())
|
||||
// }
|
||||
// } else {
|
||||
// fmt.Println(err.Error())
|
||||
// }
|
||||
// }
|
||||
//
|
||||
type RequestFailure interface {
|
||||
Error
|
||||
|
||||
// The status code of the HTTP response.
|
||||
StatusCode() int
|
||||
|
||||
// The request ID returned by the service for a request failure. This will
|
||||
// be empty if no request ID is available such as the request failed due
|
||||
// to a connection error.
|
||||
RequestID() string
|
||||
}
|
||||
|
||||
// NewRequestFailure returns a new request error wrapper for the given Error
|
||||
// provided.
|
||||
func NewRequestFailure(err Error, statusCode int, reqID string) RequestFailure {
|
||||
return newRequestError(err, statusCode, reqID)
|
||||
}
|
||||
135
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr/types.go
generated
vendored
Normal file
135
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awserr/types.go
generated
vendored
Normal file
@@ -0,0 +1,135 @@
|
||||
package awserr
|
||||
|
||||
import "fmt"
|
||||
|
||||
// SprintError returns a string of the formatted error code.
|
||||
//
|
||||
// Both extra and origErr are optional. If they are included their lines
|
||||
// will be added, but if they are not included their lines will be ignored.
|
||||
func SprintError(code, message, extra string, origErr error) string {
|
||||
msg := fmt.Sprintf("%s: %s", code, message)
|
||||
if extra != "" {
|
||||
msg = fmt.Sprintf("%s\n\t%s", msg, extra)
|
||||
}
|
||||
if origErr != nil {
|
||||
msg = fmt.Sprintf("%s\ncaused by: %s", msg, origErr.Error())
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
// A baseError wraps the code and message which defines an error. It also
|
||||
// can be used to wrap an original error object.
|
||||
//
|
||||
// Should be used as the root for errors satisfying the awserr.Error. Also
|
||||
// for any error which does not fit into a specific error wrapper type.
|
||||
type baseError struct {
|
||||
// Classification of error
|
||||
code string
|
||||
|
||||
// Detailed information about error
|
||||
message string
|
||||
|
||||
// Optional original error this error is based off of. Allows building
|
||||
// chained errors.
|
||||
origErr error
|
||||
}
|
||||
|
||||
// newBaseError returns an error object for the code, message, and err.
|
||||
//
|
||||
// code is a short no whitespace phrase depicting the classification of
|
||||
// the error that is being created.
|
||||
//
|
||||
// message is the free flow string containing detailed information about the error.
|
||||
//
|
||||
// origErr is the error object which will be nested under the new error to be returned.
|
||||
func newBaseError(code, message string, origErr error) *baseError {
|
||||
return &baseError{
|
||||
code: code,
|
||||
message: message,
|
||||
origErr: origErr,
|
||||
}
|
||||
}
|
||||
|
||||
// Error returns the string representation of the error.
|
||||
//
|
||||
// See ErrorWithExtra for formatting.
|
||||
//
|
||||
// Satisfies the error interface.
|
||||
func (b baseError) Error() string {
|
||||
return SprintError(b.code, b.message, "", b.origErr)
|
||||
}
|
||||
|
||||
// String returns the string representation of the error.
|
||||
// Alias for Error to satisfy the stringer interface.
|
||||
func (b baseError) String() string {
|
||||
return b.Error()
|
||||
}
|
||||
|
||||
// Code returns the short phrase depicting the classification of the error.
|
||||
func (b baseError) Code() string {
|
||||
return b.code
|
||||
}
|
||||
|
||||
// Message returns the error details message.
|
||||
func (b baseError) Message() string {
|
||||
return b.message
|
||||
}
|
||||
|
||||
// OrigErr returns the original error if one was set. Nil is returned if no error
|
||||
// was set.
|
||||
func (b baseError) OrigErr() error {
|
||||
return b.origErr
|
||||
}
|
||||
|
||||
// So that the Error interface type can be included as an anonymous field
|
||||
// in the requestError struct and not conflict with the error.Error() method.
|
||||
type awsError Error
|
||||
|
||||
// A requestError wraps a request or service error.
|
||||
//
|
||||
// Composed of baseError for code, message, and original error.
|
||||
type requestError struct {
|
||||
awsError
|
||||
statusCode int
|
||||
requestID string
|
||||
}
|
||||
|
||||
// newRequestError returns a wrapped error with additional information for request
|
||||
// status code, and service requestID.
|
||||
//
|
||||
// Should be used to wrap all request which involve service requests. Even if
|
||||
// the request failed without a service response, but had an HTTP status code
|
||||
// that may be meaningful.
|
||||
//
|
||||
// Also wraps original errors via the baseError.
|
||||
func newRequestError(err Error, statusCode int, requestID string) *requestError {
|
||||
return &requestError{
|
||||
awsError: err,
|
||||
statusCode: statusCode,
|
||||
requestID: requestID,
|
||||
}
|
||||
}
|
||||
|
||||
// Error returns the string representation of the error.
|
||||
// Satisfies the error interface.
|
||||
func (r requestError) Error() string {
|
||||
extra := fmt.Sprintf("status code: %d, request id: %s",
|
||||
r.statusCode, r.requestID)
|
||||
return SprintError(r.Code(), r.Message(), extra, r.OrigErr())
|
||||
}
|
||||
|
||||
// String returns the string representation of the error.
|
||||
// Alias for Error to satisfy the stringer interface.
|
||||
func (r requestError) String() string {
|
||||
return r.Error()
|
||||
}
|
||||
|
||||
// StatusCode returns the wrapped status code for the error
|
||||
func (r requestError) StatusCode() int {
|
||||
return r.statusCode
|
||||
}
|
||||
|
||||
// RequestID returns the wrapped requestID
|
||||
func (r requestError) RequestID() string {
|
||||
return r.requestID
|
||||
}
|
||||
100
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy.go
generated
vendored
Normal file
100
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy.go
generated
vendored
Normal file
@@ -0,0 +1,100 @@
|
||||
package awsutil
|
||||
|
||||
import (
|
||||
"io"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// Copy deeply copies a src structure to dst. Useful for copying request and
|
||||
// response structures.
|
||||
//
|
||||
// Can copy between structs of different type, but will only copy fields which
|
||||
// are assignable, and exist in both structs. Fields which are not assignable,
|
||||
// or do not exist in both structs are ignored.
|
||||
func Copy(dst, src interface{}) {
|
||||
dstval := reflect.ValueOf(dst)
|
||||
if !dstval.IsValid() {
|
||||
panic("Copy dst cannot be nil")
|
||||
}
|
||||
|
||||
rcopy(dstval, reflect.ValueOf(src), true)
|
||||
}
|
||||
|
||||
// CopyOf returns a copy of src while also allocating the memory for dst.
|
||||
// src must be a pointer type or this operation will fail.
|
||||
func CopyOf(src interface{}) (dst interface{}) {
|
||||
dsti := reflect.New(reflect.TypeOf(src).Elem())
|
||||
dst = dsti.Interface()
|
||||
rcopy(dsti, reflect.ValueOf(src), true)
|
||||
return
|
||||
}
|
||||
|
||||
// rcopy performs a recursive copy of values from the source to destination.
|
||||
//
|
||||
// root is used to skip certain aspects of the copy which are not valid
|
||||
// for the root node of a object.
|
||||
func rcopy(dst, src reflect.Value, root bool) {
|
||||
if !src.IsValid() {
|
||||
return
|
||||
}
|
||||
|
||||
switch src.Kind() {
|
||||
case reflect.Ptr:
|
||||
if _, ok := src.Interface().(io.Reader); ok {
|
||||
if dst.Kind() == reflect.Ptr && dst.Elem().CanSet() {
|
||||
dst.Elem().Set(src)
|
||||
} else if dst.CanSet() {
|
||||
dst.Set(src)
|
||||
}
|
||||
} else {
|
||||
e := src.Type().Elem()
|
||||
if dst.CanSet() && !src.IsNil() {
|
||||
dst.Set(reflect.New(e))
|
||||
}
|
||||
if src.Elem().IsValid() {
|
||||
// Keep the current root state since the depth hasn't changed
|
||||
rcopy(dst.Elem(), src.Elem(), root)
|
||||
}
|
||||
}
|
||||
case reflect.Struct:
|
||||
t := dst.Type()
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
name := t.Field(i).Name
|
||||
srcVal := src.FieldByName(name)
|
||||
dstVal := dst.FieldByName(name)
|
||||
if srcVal.IsValid() && dstVal.CanSet() {
|
||||
rcopy(dstVal, srcVal, false)
|
||||
}
|
||||
}
|
||||
case reflect.Slice:
|
||||
if src.IsNil() {
|
||||
break
|
||||
}
|
||||
|
||||
s := reflect.MakeSlice(src.Type(), src.Len(), src.Cap())
|
||||
dst.Set(s)
|
||||
for i := 0; i < src.Len(); i++ {
|
||||
rcopy(dst.Index(i), src.Index(i), false)
|
||||
}
|
||||
case reflect.Map:
|
||||
if src.IsNil() {
|
||||
break
|
||||
}
|
||||
|
||||
s := reflect.MakeMap(src.Type())
|
||||
dst.Set(s)
|
||||
for _, k := range src.MapKeys() {
|
||||
v := src.MapIndex(k)
|
||||
v2 := reflect.New(v.Type()).Elem()
|
||||
rcopy(v2, v, false)
|
||||
dst.SetMapIndex(k, v2)
|
||||
}
|
||||
default:
|
||||
// Assign the value if possible. If its not assignable, the value would
|
||||
// need to be converted and the impact of that may be unexpected, or is
|
||||
// not compatible with the dst type.
|
||||
if src.Type().AssignableTo(dst.Type()) {
|
||||
dst.Set(src)
|
||||
}
|
||||
}
|
||||
}
|
||||
233
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go
generated
vendored
Normal file
233
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/copy_test.go
generated
vendored
Normal file
@@ -0,0 +1,233 @@
|
||||
package awsutil_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func ExampleCopy() {
|
||||
type Foo struct {
|
||||
A int
|
||||
B []*string
|
||||
}
|
||||
|
||||
// Create the initial value
|
||||
str1 := "hello"
|
||||
str2 := "bye bye"
|
||||
f1 := &Foo{A: 1, B: []*string{&str1, &str2}}
|
||||
|
||||
// Do the copy
|
||||
var f2 Foo
|
||||
awsutil.Copy(&f2, f1)
|
||||
|
||||
// Print the result
|
||||
fmt.Println(awsutil.Prettify(f2))
|
||||
|
||||
// Output:
|
||||
// {
|
||||
// A: 1,
|
||||
// B: ["hello","bye bye"]
|
||||
// }
|
||||
}
|
||||
|
||||
func TestCopy(t *testing.T) {
|
||||
type Foo struct {
|
||||
A int
|
||||
B []*string
|
||||
C map[string]*int
|
||||
}
|
||||
|
||||
// Create the initial value
|
||||
str1 := "hello"
|
||||
str2 := "bye bye"
|
||||
int1 := 1
|
||||
int2 := 2
|
||||
f1 := &Foo{
|
||||
A: 1,
|
||||
B: []*string{&str1, &str2},
|
||||
C: map[string]*int{
|
||||
"A": &int1,
|
||||
"B": &int2,
|
||||
},
|
||||
}
|
||||
|
||||
// Do the copy
|
||||
var f2 Foo
|
||||
awsutil.Copy(&f2, f1)
|
||||
|
||||
// Values are equal
|
||||
assert.Equal(t, f2.A, f1.A)
|
||||
assert.Equal(t, f2.B, f1.B)
|
||||
assert.Equal(t, f2.C, f1.C)
|
||||
|
||||
// But pointers are not!
|
||||
str3 := "nothello"
|
||||
int3 := 57
|
||||
f2.A = 100
|
||||
f2.B[0] = &str3
|
||||
f2.C["B"] = &int3
|
||||
assert.NotEqual(t, f2.A, f1.A)
|
||||
assert.NotEqual(t, f2.B, f1.B)
|
||||
assert.NotEqual(t, f2.C, f1.C)
|
||||
}
|
||||
|
||||
func TestCopyNestedWithUnexported(t *testing.T) {
|
||||
type Bar struct {
|
||||
a int
|
||||
B int
|
||||
}
|
||||
type Foo struct {
|
||||
A string
|
||||
B Bar
|
||||
}
|
||||
|
||||
f1 := &Foo{A: "string", B: Bar{a: 1, B: 2}}
|
||||
|
||||
var f2 Foo
|
||||
awsutil.Copy(&f2, f1)
|
||||
|
||||
// Values match
|
||||
assert.Equal(t, f2.A, f1.A)
|
||||
assert.NotEqual(t, f2.B, f1.B)
|
||||
assert.NotEqual(t, f2.B.a, f1.B.a)
|
||||
assert.Equal(t, f2.B.B, f2.B.B)
|
||||
}
|
||||
|
||||
func TestCopyIgnoreNilMembers(t *testing.T) {
|
||||
type Foo struct {
|
||||
A *string
|
||||
B []string
|
||||
C map[string]string
|
||||
}
|
||||
|
||||
f := &Foo{}
|
||||
assert.Nil(t, f.A)
|
||||
assert.Nil(t, f.B)
|
||||
assert.Nil(t, f.C)
|
||||
|
||||
var f2 Foo
|
||||
awsutil.Copy(&f2, f)
|
||||
assert.Nil(t, f2.A)
|
||||
assert.Nil(t, f2.B)
|
||||
assert.Nil(t, f2.C)
|
||||
|
||||
fcopy := awsutil.CopyOf(f)
|
||||
f3 := fcopy.(*Foo)
|
||||
assert.Nil(t, f3.A)
|
||||
assert.Nil(t, f3.B)
|
||||
assert.Nil(t, f3.C)
|
||||
}
|
||||
|
||||
func TestCopyPrimitive(t *testing.T) {
|
||||
str := "hello"
|
||||
var s string
|
||||
awsutil.Copy(&s, &str)
|
||||
assert.Equal(t, "hello", s)
|
||||
}
|
||||
|
||||
func TestCopyNil(t *testing.T) {
|
||||
var s string
|
||||
awsutil.Copy(&s, nil)
|
||||
assert.Equal(t, "", s)
|
||||
}
|
||||
|
||||
func TestCopyReader(t *testing.T) {
|
||||
var buf io.Reader = bytes.NewReader([]byte("hello world"))
|
||||
var r io.Reader
|
||||
awsutil.Copy(&r, buf)
|
||||
b, err := ioutil.ReadAll(r)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte("hello world"), b)
|
||||
|
||||
// empty bytes because this is not a deep copy
|
||||
b, err = ioutil.ReadAll(buf)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, []byte(""), b)
|
||||
}
|
||||
|
||||
func TestCopyDifferentStructs(t *testing.T) {
|
||||
type SrcFoo struct {
|
||||
A int
|
||||
B []*string
|
||||
C map[string]*int
|
||||
SrcUnique string
|
||||
SameNameDiffType int
|
||||
unexportedPtr *int
|
||||
ExportedPtr *int
|
||||
}
|
||||
type DstFoo struct {
|
||||
A int
|
||||
B []*string
|
||||
C map[string]*int
|
||||
DstUnique int
|
||||
SameNameDiffType string
|
||||
unexportedPtr *int
|
||||
ExportedPtr *int
|
||||
}
|
||||
|
||||
// Create the initial value
|
||||
str1 := "hello"
|
||||
str2 := "bye bye"
|
||||
int1 := 1
|
||||
int2 := 2
|
||||
f1 := &SrcFoo{
|
||||
A: 1,
|
||||
B: []*string{&str1, &str2},
|
||||
C: map[string]*int{
|
||||
"A": &int1,
|
||||
"B": &int2,
|
||||
},
|
||||
SrcUnique: "unique",
|
||||
SameNameDiffType: 1,
|
||||
unexportedPtr: &int1,
|
||||
ExportedPtr: &int2,
|
||||
}
|
||||
|
||||
// Do the copy
|
||||
var f2 DstFoo
|
||||
awsutil.Copy(&f2, f1)
|
||||
|
||||
// Values are equal
|
||||
assert.Equal(t, f2.A, f1.A)
|
||||
assert.Equal(t, f2.B, f1.B)
|
||||
assert.Equal(t, f2.C, f1.C)
|
||||
assert.Equal(t, "unique", f1.SrcUnique)
|
||||
assert.Equal(t, 1, f1.SameNameDiffType)
|
||||
assert.Equal(t, 0, f2.DstUnique)
|
||||
assert.Equal(t, "", f2.SameNameDiffType)
|
||||
assert.Equal(t, int1, *f1.unexportedPtr)
|
||||
assert.Nil(t, f2.unexportedPtr)
|
||||
assert.Equal(t, int2, *f1.ExportedPtr)
|
||||
assert.Equal(t, int2, *f2.ExportedPtr)
|
||||
}
|
||||
|
||||
func ExampleCopyOf() {
|
||||
type Foo struct {
|
||||
A int
|
||||
B []*string
|
||||
}
|
||||
|
||||
// Create the initial value
|
||||
str1 := "hello"
|
||||
str2 := "bye bye"
|
||||
f1 := &Foo{A: 1, B: []*string{&str1, &str2}}
|
||||
|
||||
// Do the copy
|
||||
v := awsutil.CopyOf(f1)
|
||||
var f2 *Foo = v.(*Foo)
|
||||
|
||||
// Print the result
|
||||
fmt.Println(awsutil.Prettify(f2))
|
||||
|
||||
// Output:
|
||||
// {
|
||||
// A: 1,
|
||||
// B: ["hello","bye bye"]
|
||||
// }
|
||||
}
|
||||
27
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/equal.go
generated
vendored
Normal file
27
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/equal.go
generated
vendored
Normal file
@@ -0,0 +1,27 @@
|
||||
package awsutil
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// DeepEqual returns if the two values are deeply equal like reflect.DeepEqual.
|
||||
// In addition to this, this method will also dereference the input values if
|
||||
// possible so the DeepEqual performed will not fail if one parameter is a
|
||||
// pointer and the other is not.
|
||||
//
|
||||
// DeepEqual will not perform indirection of nested values of the input parameters.
|
||||
func DeepEqual(a, b interface{}) bool {
|
||||
ra := reflect.Indirect(reflect.ValueOf(a))
|
||||
rb := reflect.Indirect(reflect.ValueOf(b))
|
||||
|
||||
if raValid, rbValid := ra.IsValid(), rb.IsValid(); !raValid && !rbValid {
|
||||
// If the elements are both nil, and of the same type the are equal
|
||||
// If they are of different types they are not equal
|
||||
return reflect.TypeOf(a) == reflect.TypeOf(b)
|
||||
} else if raValid != rbValid {
|
||||
// Both values must be valid to be equal
|
||||
return false
|
||||
}
|
||||
|
||||
return reflect.DeepEqual(ra.Interface(), rb.Interface())
|
||||
}
|
||||
29
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go
generated
vendored
Normal file
29
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/equal_test.go
generated
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
package awsutil_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestDeepEqual(t *testing.T) {
|
||||
cases := []struct {
|
||||
a, b interface{}
|
||||
equal bool
|
||||
}{
|
||||
{"a", "a", true},
|
||||
{"a", "b", false},
|
||||
{"a", aws.String(""), false},
|
||||
{"a", nil, false},
|
||||
{"a", aws.String("a"), true},
|
||||
{(*bool)(nil), (*bool)(nil), true},
|
||||
{(*bool)(nil), (*string)(nil), false},
|
||||
{nil, nil, true},
|
||||
}
|
||||
|
||||
for i, c := range cases {
|
||||
assert.Equal(t, c.equal, awsutil.DeepEqual(c.a, c.b), "%d, a:%v b:%v, %t", i, c.a, c.b, c.equal)
|
||||
}
|
||||
}
|
||||
222
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
generated
vendored
Normal file
222
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value.go
generated
vendored
Normal file
@@ -0,0 +1,222 @@
|
||||
package awsutil
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/jmespath/go-jmespath"
|
||||
)
|
||||
|
||||
var indexRe = regexp.MustCompile(`(.+)\[(-?\d+)?\]$`)
|
||||
|
||||
// rValuesAtPath returns a slice of values found in value v. The values
|
||||
// in v are explored recursively so all nested values are collected.
|
||||
func rValuesAtPath(v interface{}, path string, createPath, caseSensitive, nilTerm bool) []reflect.Value {
|
||||
pathparts := strings.Split(path, "||")
|
||||
if len(pathparts) > 1 {
|
||||
for _, pathpart := range pathparts {
|
||||
vals := rValuesAtPath(v, pathpart, createPath, caseSensitive, nilTerm)
|
||||
if len(vals) > 0 {
|
||||
return vals
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
values := []reflect.Value{reflect.Indirect(reflect.ValueOf(v))}
|
||||
components := strings.Split(path, ".")
|
||||
for len(values) > 0 && len(components) > 0 {
|
||||
var index *int64
|
||||
var indexStar bool
|
||||
c := strings.TrimSpace(components[0])
|
||||
if c == "" { // no actual component, illegal syntax
|
||||
return nil
|
||||
} else if caseSensitive && c != "*" && strings.ToLower(c[0:1]) == c[0:1] {
|
||||
// TODO normalize case for user
|
||||
return nil // don't support unexported fields
|
||||
}
|
||||
|
||||
// parse this component
|
||||
if m := indexRe.FindStringSubmatch(c); m != nil {
|
||||
c = m[1]
|
||||
if m[2] == "" {
|
||||
index = nil
|
||||
indexStar = true
|
||||
} else {
|
||||
i, _ := strconv.ParseInt(m[2], 10, 32)
|
||||
index = &i
|
||||
indexStar = false
|
||||
}
|
||||
}
|
||||
|
||||
nextvals := []reflect.Value{}
|
||||
for _, value := range values {
|
||||
// pull component name out of struct member
|
||||
if value.Kind() != reflect.Struct {
|
||||
continue
|
||||
}
|
||||
|
||||
if c == "*" { // pull all members
|
||||
for i := 0; i < value.NumField(); i++ {
|
||||
if f := reflect.Indirect(value.Field(i)); f.IsValid() {
|
||||
nextvals = append(nextvals, f)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
value = value.FieldByNameFunc(func(name string) bool {
|
||||
if c == name {
|
||||
return true
|
||||
} else if !caseSensitive && strings.ToLower(name) == strings.ToLower(c) {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
if nilTerm && value.Kind() == reflect.Ptr && len(components[1:]) == 0 {
|
||||
if !value.IsNil() {
|
||||
value.Set(reflect.Zero(value.Type()))
|
||||
}
|
||||
return []reflect.Value{value}
|
||||
}
|
||||
|
||||
if createPath && value.Kind() == reflect.Ptr && value.IsNil() {
|
||||
// TODO if the value is the terminus it should not be created
|
||||
// if the value to be set to its position is nil.
|
||||
value.Set(reflect.New(value.Type().Elem()))
|
||||
value = value.Elem()
|
||||
} else {
|
||||
value = reflect.Indirect(value)
|
||||
}
|
||||
|
||||
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
||||
if !createPath && value.IsNil() {
|
||||
value = reflect.ValueOf(nil)
|
||||
}
|
||||
}
|
||||
|
||||
if value.IsValid() {
|
||||
nextvals = append(nextvals, value)
|
||||
}
|
||||
}
|
||||
values = nextvals
|
||||
|
||||
if indexStar || index != nil {
|
||||
nextvals = []reflect.Value{}
|
||||
for _, value := range values {
|
||||
value := reflect.Indirect(value)
|
||||
if value.Kind() != reflect.Slice {
|
||||
continue
|
||||
}
|
||||
|
||||
if indexStar { // grab all indices
|
||||
for i := 0; i < value.Len(); i++ {
|
||||
idx := reflect.Indirect(value.Index(i))
|
||||
if idx.IsValid() {
|
||||
nextvals = append(nextvals, idx)
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// pull out index
|
||||
i := int(*index)
|
||||
if i >= value.Len() { // check out of bounds
|
||||
if createPath {
|
||||
// TODO resize slice
|
||||
} else {
|
||||
continue
|
||||
}
|
||||
} else if i < 0 { // support negative indexing
|
||||
i = value.Len() + i
|
||||
}
|
||||
value = reflect.Indirect(value.Index(i))
|
||||
|
||||
if value.Kind() == reflect.Slice || value.Kind() == reflect.Map {
|
||||
if !createPath && value.IsNil() {
|
||||
value = reflect.ValueOf(nil)
|
||||
}
|
||||
}
|
||||
|
||||
if value.IsValid() {
|
||||
nextvals = append(nextvals, value)
|
||||
}
|
||||
}
|
||||
values = nextvals
|
||||
}
|
||||
|
||||
components = components[1:]
|
||||
}
|
||||
return values
|
||||
}
|
||||
|
||||
// ValuesAtPath returns a list of values at the case insensitive lexical
|
||||
// path inside of a structure.
|
||||
func ValuesAtPath(i interface{}, path string) ([]interface{}, error) {
|
||||
result, err := jmespath.Search(path, i)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
v := reflect.ValueOf(result)
|
||||
if !v.IsValid() || (v.Kind() == reflect.Ptr && v.IsNil()) {
|
||||
return nil, nil
|
||||
}
|
||||
if s, ok := result.([]interface{}); ok {
|
||||
return s, err
|
||||
}
|
||||
if v.Kind() == reflect.Map && v.Len() == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
if v.Kind() == reflect.Slice {
|
||||
out := make([]interface{}, v.Len())
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
out[i] = v.Index(i).Interface()
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
return []interface{}{result}, nil
|
||||
}
|
||||
|
||||
// SetValueAtPath sets a value at the case insensitive lexical path inside
|
||||
// of a structure.
|
||||
func SetValueAtPath(i interface{}, path string, v interface{}) {
|
||||
if rvals := rValuesAtPath(i, path, true, false, v == nil); rvals != nil {
|
||||
for _, rval := range rvals {
|
||||
if rval.Kind() == reflect.Ptr && rval.IsNil() {
|
||||
continue
|
||||
}
|
||||
setValue(rval, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func setValue(dstVal reflect.Value, src interface{}) {
|
||||
if dstVal.Kind() == reflect.Ptr {
|
||||
dstVal = reflect.Indirect(dstVal)
|
||||
}
|
||||
srcVal := reflect.ValueOf(src)
|
||||
|
||||
if !srcVal.IsValid() { // src is literal nil
|
||||
if dstVal.CanAddr() {
|
||||
// Convert to pointer so that pointer's value can be nil'ed
|
||||
// dstVal = dstVal.Addr()
|
||||
}
|
||||
dstVal.Set(reflect.Zero(dstVal.Type()))
|
||||
|
||||
} else if srcVal.Kind() == reflect.Ptr {
|
||||
if srcVal.IsNil() {
|
||||
srcVal = reflect.Zero(dstVal.Type())
|
||||
} else {
|
||||
srcVal = reflect.ValueOf(src).Elem()
|
||||
}
|
||||
dstVal.Set(srcVal)
|
||||
} else {
|
||||
dstVal.Set(srcVal)
|
||||
}
|
||||
|
||||
}
|
||||
142
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go
generated
vendored
Normal file
142
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/path_value_test.go
generated
vendored
Normal file
@@ -0,0 +1,142 @@
|
||||
package awsutil_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/awsutil"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
type Struct struct {
|
||||
A []Struct
|
||||
z []Struct
|
||||
B *Struct
|
||||
D *Struct
|
||||
C string
|
||||
E map[string]string
|
||||
}
|
||||
|
||||
var data = Struct{
|
||||
A: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}},
|
||||
z: []Struct{{C: "value1"}, {C: "value2"}, {C: "value3"}},
|
||||
B: &Struct{B: &Struct{C: "terminal"}, D: &Struct{C: "terminal2"}},
|
||||
C: "initial",
|
||||
}
|
||||
var data2 = Struct{A: []Struct{
|
||||
{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}},
|
||||
{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}},
|
||||
}}
|
||||
|
||||
func TestValueAtPathSuccess(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
expect []interface{}
|
||||
data interface{}
|
||||
path string
|
||||
}{
|
||||
{[]interface{}{"initial"}, data, "C"},
|
||||
{[]interface{}{"value1"}, data, "A[0].C"},
|
||||
{[]interface{}{"value2"}, data, "A[1].C"},
|
||||
{[]interface{}{"value3"}, data, "A[2].C"},
|
||||
{[]interface{}{"value3"}, data, "a[2].c"},
|
||||
{[]interface{}{"value3"}, data, "A[-1].C"},
|
||||
{[]interface{}{"value1", "value2", "value3"}, data, "A[].C"},
|
||||
{[]interface{}{"terminal"}, data, "B . B . C"},
|
||||
{[]interface{}{"initial"}, data, "A.D.X || C"},
|
||||
{[]interface{}{"initial"}, data, "A[0].B || C"},
|
||||
{[]interface{}{
|
||||
Struct{A: []Struct{{C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}, {C: "1"}}},
|
||||
Struct{A: []Struct{{C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}, {C: "2"}}},
|
||||
}, data2, "A"},
|
||||
}
|
||||
for i, c := range testCases {
|
||||
v, err := awsutil.ValuesAtPath(c.data, c.path)
|
||||
assert.NoError(t, err, "case %d, expected no error, %s", i, c.path)
|
||||
assert.Equal(t, c.expect, v, "case %d, %s", i, c.path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestValueAtPathFailure(t *testing.T) {
|
||||
var testCases = []struct {
|
||||
expect []interface{}
|
||||
errContains string
|
||||
data interface{}
|
||||
path string
|
||||
}{
|
||||
{nil, "", data, "C.x"},
|
||||
{nil, "SyntaxError: Invalid token: tDot", data, ".x"},
|
||||
{nil, "", data, "X.Y.Z"},
|
||||
{nil, "", data, "A[100].C"},
|
||||
{nil, "", data, "A[3].C"},
|
||||
{nil, "", data, "B.B.C.Z"},
|
||||
{nil, "", data, "z[-1].C"},
|
||||
{nil, "", nil, "A.B.C"},
|
||||
{[]interface{}{}, "", Struct{}, "A"},
|
||||
{nil, "", data, "A[0].B.C"},
|
||||
{nil, "", data, "D"},
|
||||
}
|
||||
|
||||
for i, c := range testCases {
|
||||
v, err := awsutil.ValuesAtPath(c.data, c.path)
|
||||
if c.errContains != "" {
|
||||
assert.Contains(t, err.Error(), c.errContains, "case %d, expected error, %s", i, c.path)
|
||||
continue
|
||||
} else {
|
||||
assert.NoError(t, err, "case %d, expected no error, %s", i, c.path)
|
||||
}
|
||||
assert.Equal(t, c.expect, v, "case %d, %s", i, c.path)
|
||||
}
|
||||
}
|
||||
|
||||
func TestSetValueAtPathSuccess(t *testing.T) {
|
||||
var s Struct
|
||||
awsutil.SetValueAtPath(&s, "C", "test1")
|
||||
awsutil.SetValueAtPath(&s, "B.B.C", "test2")
|
||||
awsutil.SetValueAtPath(&s, "B.D.C", "test3")
|
||||
assert.Equal(t, "test1", s.C)
|
||||
assert.Equal(t, "test2", s.B.B.C)
|
||||
assert.Equal(t, "test3", s.B.D.C)
|
||||
|
||||
awsutil.SetValueAtPath(&s, "B.*.C", "test0")
|
||||
assert.Equal(t, "test0", s.B.B.C)
|
||||
assert.Equal(t, "test0", s.B.D.C)
|
||||
|
||||
var s2 Struct
|
||||
awsutil.SetValueAtPath(&s2, "b.b.c", "test0")
|
||||
assert.Equal(t, "test0", s2.B.B.C)
|
||||
awsutil.SetValueAtPath(&s2, "A", []Struct{{}})
|
||||
assert.Equal(t, []Struct{{}}, s2.A)
|
||||
|
||||
str := "foo"
|
||||
|
||||
s3 := Struct{}
|
||||
awsutil.SetValueAtPath(&s3, "b.b.c", str)
|
||||
assert.Equal(t, "foo", s3.B.B.C)
|
||||
|
||||
s3 = Struct{B: &Struct{B: &Struct{C: str}}}
|
||||
awsutil.SetValueAtPath(&s3, "b.b.c", nil)
|
||||
assert.Equal(t, "", s3.B.B.C)
|
||||
|
||||
s3 = Struct{}
|
||||
awsutil.SetValueAtPath(&s3, "b.b.c", nil)
|
||||
assert.Equal(t, "", s3.B.B.C)
|
||||
|
||||
s3 = Struct{}
|
||||
awsutil.SetValueAtPath(&s3, "b.b.c", &str)
|
||||
assert.Equal(t, "foo", s3.B.B.C)
|
||||
|
||||
var s4 struct{ Name *string }
|
||||
awsutil.SetValueAtPath(&s4, "Name", str)
|
||||
assert.Equal(t, str, *s4.Name)
|
||||
|
||||
s4 = struct{ Name *string }{}
|
||||
awsutil.SetValueAtPath(&s4, "Name", nil)
|
||||
assert.Equal(t, (*string)(nil), s4.Name)
|
||||
|
||||
s4 = struct{ Name *string }{Name: &str}
|
||||
awsutil.SetValueAtPath(&s4, "Name", nil)
|
||||
assert.Equal(t, (*string)(nil), s4.Name)
|
||||
|
||||
s4 = struct{ Name *string }{}
|
||||
awsutil.SetValueAtPath(&s4, "Name", &str)
|
||||
assert.Equal(t, str, *s4.Name)
|
||||
}
|
||||
103
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go
generated
vendored
Normal file
103
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/prettify.go
generated
vendored
Normal file
@@ -0,0 +1,103 @@
|
||||
package awsutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// Prettify returns the string representation of a value.
|
||||
func Prettify(i interface{}) string {
|
||||
var buf bytes.Buffer
|
||||
prettify(reflect.ValueOf(i), 0, &buf)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// prettify will recursively walk value v to build a textual
|
||||
// representation of the value.
|
||||
func prettify(v reflect.Value, indent int, buf *bytes.Buffer) {
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.Struct:
|
||||
strtype := v.Type().String()
|
||||
if strtype == "time.Time" {
|
||||
fmt.Fprintf(buf, "%s", v.Interface())
|
||||
break
|
||||
} else if strings.HasPrefix(strtype, "io.") {
|
||||
buf.WriteString("<buffer>")
|
||||
break
|
||||
}
|
||||
|
||||
buf.WriteString("{\n")
|
||||
|
||||
names := []string{}
|
||||
for i := 0; i < v.Type().NumField(); i++ {
|
||||
name := v.Type().Field(i).Name
|
||||
f := v.Field(i)
|
||||
if name[0:1] == strings.ToLower(name[0:1]) {
|
||||
continue // ignore unexported fields
|
||||
}
|
||||
if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice || f.Kind() == reflect.Map) && f.IsNil() {
|
||||
continue // ignore unset fields
|
||||
}
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
for i, n := range names {
|
||||
val := v.FieldByName(n)
|
||||
buf.WriteString(strings.Repeat(" ", indent+2))
|
||||
buf.WriteString(n + ": ")
|
||||
prettify(val, indent+2, buf)
|
||||
|
||||
if i < len(names)-1 {
|
||||
buf.WriteString(",\n")
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
|
||||
case reflect.Slice:
|
||||
nl, id, id2 := "", "", ""
|
||||
if v.Len() > 3 {
|
||||
nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
|
||||
}
|
||||
buf.WriteString("[" + nl)
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
buf.WriteString(id2)
|
||||
prettify(v.Index(i), indent+2, buf)
|
||||
|
||||
if i < v.Len()-1 {
|
||||
buf.WriteString("," + nl)
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteString(nl + id + "]")
|
||||
case reflect.Map:
|
||||
buf.WriteString("{\n")
|
||||
|
||||
for i, k := range v.MapKeys() {
|
||||
buf.WriteString(strings.Repeat(" ", indent+2))
|
||||
buf.WriteString(k.String() + ": ")
|
||||
prettify(v.MapIndex(k), indent+2, buf)
|
||||
|
||||
if i < v.Len()-1 {
|
||||
buf.WriteString(",\n")
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
|
||||
default:
|
||||
format := "%v"
|
||||
switch v.Interface().(type) {
|
||||
case string:
|
||||
format = "%q"
|
||||
case io.ReadSeeker, io.Reader:
|
||||
format = "buffer(%p)"
|
||||
}
|
||||
fmt.Fprintf(buf, format, v.Interface())
|
||||
}
|
||||
}
|
||||
89
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go
generated
vendored
Normal file
89
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/awsutil/string_value.go
generated
vendored
Normal file
@@ -0,0 +1,89 @@
|
||||
package awsutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// StringValue returns the string representation of a value.
|
||||
func StringValue(i interface{}) string {
|
||||
var buf bytes.Buffer
|
||||
stringValue(reflect.ValueOf(i), 0, &buf)
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func stringValue(v reflect.Value, indent int, buf *bytes.Buffer) {
|
||||
for v.Kind() == reflect.Ptr {
|
||||
v = v.Elem()
|
||||
}
|
||||
|
||||
switch v.Kind() {
|
||||
case reflect.Struct:
|
||||
buf.WriteString("{\n")
|
||||
|
||||
names := []string{}
|
||||
for i := 0; i < v.Type().NumField(); i++ {
|
||||
name := v.Type().Field(i).Name
|
||||
f := v.Field(i)
|
||||
if name[0:1] == strings.ToLower(name[0:1]) {
|
||||
continue // ignore unexported fields
|
||||
}
|
||||
if (f.Kind() == reflect.Ptr || f.Kind() == reflect.Slice) && f.IsNil() {
|
||||
continue // ignore unset fields
|
||||
}
|
||||
names = append(names, name)
|
||||
}
|
||||
|
||||
for i, n := range names {
|
||||
val := v.FieldByName(n)
|
||||
buf.WriteString(strings.Repeat(" ", indent+2))
|
||||
buf.WriteString(n + ": ")
|
||||
stringValue(val, indent+2, buf)
|
||||
|
||||
if i < len(names)-1 {
|
||||
buf.WriteString(",\n")
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
|
||||
case reflect.Slice:
|
||||
nl, id, id2 := "", "", ""
|
||||
if v.Len() > 3 {
|
||||
nl, id, id2 = "\n", strings.Repeat(" ", indent), strings.Repeat(" ", indent+2)
|
||||
}
|
||||
buf.WriteString("[" + nl)
|
||||
for i := 0; i < v.Len(); i++ {
|
||||
buf.WriteString(id2)
|
||||
stringValue(v.Index(i), indent+2, buf)
|
||||
|
||||
if i < v.Len()-1 {
|
||||
buf.WriteString("," + nl)
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteString(nl + id + "]")
|
||||
case reflect.Map:
|
||||
buf.WriteString("{\n")
|
||||
|
||||
for i, k := range v.MapKeys() {
|
||||
buf.WriteString(strings.Repeat(" ", indent+2))
|
||||
buf.WriteString(k.String() + ": ")
|
||||
stringValue(v.MapIndex(k), indent+2, buf)
|
||||
|
||||
if i < v.Len()-1 {
|
||||
buf.WriteString(",\n")
|
||||
}
|
||||
}
|
||||
|
||||
buf.WriteString("\n" + strings.Repeat(" ", indent) + "}")
|
||||
default:
|
||||
format := "%v"
|
||||
switch v.Interface().(type) {
|
||||
case string:
|
||||
format = "%q"
|
||||
}
|
||||
fmt.Fprintf(buf, format, v.Interface())
|
||||
}
|
||||
}
|
||||
120
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
Normal file
120
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/client.go
generated
vendored
Normal file
@@ -0,0 +1,120 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"net/http/httputil"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws"
|
||||
"github.com/aws/aws-sdk-go/aws/client/metadata"
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
)
|
||||
|
||||
// A Config provides configuration to a service client instance.
|
||||
type Config struct {
|
||||
Config *aws.Config
|
||||
Handlers request.Handlers
|
||||
Endpoint, SigningRegion string
|
||||
}
|
||||
|
||||
// ConfigProvider provides a generic way for a service client to receive
|
||||
// the ClientConfig without circular dependencies.
|
||||
type ConfigProvider interface {
|
||||
ClientConfig(serviceName string, cfgs ...*aws.Config) Config
|
||||
}
|
||||
|
||||
// A Client implements the base client request and response handling
|
||||
// used by all service clients.
|
||||
type Client struct {
|
||||
request.Retryer
|
||||
metadata.ClientInfo
|
||||
|
||||
Config aws.Config
|
||||
Handlers request.Handlers
|
||||
}
|
||||
|
||||
// New will return a pointer to a new initialized service client.
|
||||
func New(cfg aws.Config, info metadata.ClientInfo, handlers request.Handlers, options ...func(*Client)) *Client {
|
||||
svc := &Client{
|
||||
Config: cfg,
|
||||
ClientInfo: info,
|
||||
Handlers: handlers,
|
||||
}
|
||||
|
||||
switch retryer, ok := cfg.Retryer.(request.Retryer); {
|
||||
case ok:
|
||||
svc.Retryer = retryer
|
||||
case cfg.Retryer != nil && cfg.Logger != nil:
|
||||
s := fmt.Sprintf("WARNING: %T does not implement request.Retryer; using DefaultRetryer instead", cfg.Retryer)
|
||||
cfg.Logger.Log(s)
|
||||
fallthrough
|
||||
default:
|
||||
maxRetries := aws.IntValue(cfg.MaxRetries)
|
||||
if cfg.MaxRetries == nil || maxRetries == aws.UseServiceDefaultRetries {
|
||||
maxRetries = 3
|
||||
}
|
||||
svc.Retryer = DefaultRetryer{NumMaxRetries: maxRetries}
|
||||
}
|
||||
|
||||
svc.AddDebugHandlers()
|
||||
|
||||
for _, option := range options {
|
||||
option(svc)
|
||||
}
|
||||
|
||||
return svc
|
||||
}
|
||||
|
||||
// NewRequest returns a new Request pointer for the service API
|
||||
// operation and parameters.
|
||||
func (c *Client) NewRequest(operation *request.Operation, params interface{}, data interface{}) *request.Request {
|
||||
return request.New(c.Config, c.ClientInfo, c.Handlers, c.Retryer, operation, params, data)
|
||||
}
|
||||
|
||||
// AddDebugHandlers injects debug logging handlers into the service to log request
|
||||
// debug information.
|
||||
func (c *Client) AddDebugHandlers() {
|
||||
if !c.Config.LogLevel.AtLeast(aws.LogDebug) {
|
||||
return
|
||||
}
|
||||
|
||||
c.Handlers.Send.PushFront(logRequest)
|
||||
c.Handlers.Send.PushBack(logResponse)
|
||||
}
|
||||
|
||||
const logReqMsg = `DEBUG: Request %s/%s Details:
|
||||
---[ REQUEST POST-SIGN ]-----------------------------
|
||||
%s
|
||||
-----------------------------------------------------`
|
||||
|
||||
func logRequest(r *request.Request) {
|
||||
logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
|
||||
dumpedBody, _ := httputil.DumpRequestOut(r.HTTPRequest, logBody)
|
||||
|
||||
if logBody {
|
||||
// Reset the request body because dumpRequest will re-wrap the r.HTTPRequest's
|
||||
// Body as a NoOpCloser and will not be reset after read by the HTTP
|
||||
// client reader.
|
||||
r.Body.Seek(r.BodyStart, 0)
|
||||
r.HTTPRequest.Body = ioutil.NopCloser(r.Body)
|
||||
}
|
||||
|
||||
r.Config.Logger.Log(fmt.Sprintf(logReqMsg, r.ClientInfo.ServiceName, r.Operation.Name, string(dumpedBody)))
|
||||
}
|
||||
|
||||
const logRespMsg = `DEBUG: Response %s/%s Details:
|
||||
---[ RESPONSE ]--------------------------------------
|
||||
%s
|
||||
-----------------------------------------------------`
|
||||
|
||||
func logResponse(r *request.Request) {
|
||||
var msg = "no reponse data"
|
||||
if r.HTTPResponse != nil {
|
||||
logBody := r.Config.LogLevel.Matches(aws.LogDebugWithHTTPBody)
|
||||
dumpedBody, _ := httputil.DumpResponse(r.HTTPResponse, logBody)
|
||||
msg = string(dumpedBody)
|
||||
} else if r.Error != nil {
|
||||
msg = r.Error.Error()
|
||||
}
|
||||
r.Config.Logger.Log(fmt.Sprintf(logRespMsg, r.ClientInfo.ServiceName, r.Operation.Name, msg))
|
||||
}
|
||||
45
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/default_retryer.go
generated
vendored
Normal file
45
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/default_retryer.go
generated
vendored
Normal file
@@ -0,0 +1,45 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"math"
|
||||
"math/rand"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/request"
|
||||
)
|
||||
|
||||
// DefaultRetryer implements basic retry logic using exponential backoff for
|
||||
// most services. If you want to implement custom retry logic, implement the
|
||||
// request.Retryer interface or create a structure type that composes this
|
||||
// struct and override the specific methods. For example, to override only
|
||||
// the MaxRetries method:
|
||||
//
|
||||
// type retryer struct {
|
||||
// service.DefaultRetryer
|
||||
// }
|
||||
//
|
||||
// // This implementation always has 100 max retries
|
||||
// func (d retryer) MaxRetries() uint { return 100 }
|
||||
type DefaultRetryer struct {
|
||||
NumMaxRetries int
|
||||
}
|
||||
|
||||
// MaxRetries returns the number of maximum returns the service will use to make
|
||||
// an individual API request.
|
||||
func (d DefaultRetryer) MaxRetries() int {
|
||||
return d.NumMaxRetries
|
||||
}
|
||||
|
||||
// RetryRules returns the delay duration before retrying this request again
|
||||
func (d DefaultRetryer) RetryRules(r *request.Request) time.Duration {
|
||||
delay := int(math.Pow(2, float64(r.RetryCount))) * (rand.Intn(30) + 30)
|
||||
return time.Duration(delay) * time.Millisecond
|
||||
}
|
||||
|
||||
// ShouldRetry returns if the request should be retried.
|
||||
func (d DefaultRetryer) ShouldRetry(r *request.Request) bool {
|
||||
if r.HTTPResponse.StatusCode >= 500 {
|
||||
return true
|
||||
}
|
||||
return r.IsErrorRetryable()
|
||||
}
|
||||
12
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go
generated
vendored
Normal file
12
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/client/metadata/client_info.go
generated
vendored
Normal file
@@ -0,0 +1,12 @@
|
||||
package metadata
|
||||
|
||||
// ClientInfo wraps immutable data from the client.Client structure.
|
||||
type ClientInfo struct {
|
||||
ServiceName string
|
||||
APIVersion string
|
||||
Endpoint string
|
||||
SigningName string
|
||||
SigningRegion string
|
||||
JSONVersion string
|
||||
TargetPrefix string
|
||||
}
|
||||
270
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config.go
generated
vendored
Normal file
270
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config.go
generated
vendored
Normal file
@@ -0,0 +1,270 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
)
|
||||
|
||||
// UseServiceDefaultRetries instructs the config to use the service's own default
|
||||
// number of retries. This will be the default action if Config.MaxRetries
|
||||
// is nil also.
|
||||
const UseServiceDefaultRetries = -1
|
||||
|
||||
// RequestRetryer is an alias for a type that implements the request.Retryer interface.
|
||||
type RequestRetryer interface{}
|
||||
|
||||
// A Config provides service configuration for service clients. By default,
|
||||
// all clients will use the {defaults.DefaultConfig} structure.
|
||||
type Config struct {
|
||||
// The credentials object to use when signing requests. Defaults to
|
||||
// a chain of credential providers to search for credentials in environment
|
||||
// variables, shared credential file, and EC2 Instance Roles.
|
||||
Credentials *credentials.Credentials
|
||||
|
||||
// An optional endpoint URL (hostname only or fully qualified URI)
|
||||
// that overrides the default generated endpoint for a client. Set this
|
||||
// to `""` to use the default generated endpoint.
|
||||
//
|
||||
// @note You must still provide a `Region` value when specifying an
|
||||
// endpoint for a client.
|
||||
Endpoint *string
|
||||
|
||||
// The region to send requests to. This parameter is required and must
|
||||
// be configured globally or on a per-client basis unless otherwise
|
||||
// noted. A full list of regions is found in the "Regions and Endpoints"
|
||||
// document.
|
||||
//
|
||||
// @see http://docs.aws.amazon.com/general/latest/gr/rande.html
|
||||
// AWS Regions and Endpoints
|
||||
Region *string
|
||||
|
||||
// Set this to `true` to disable SSL when sending requests. Defaults
|
||||
// to `false`.
|
||||
DisableSSL *bool
|
||||
|
||||
// The HTTP client to use when sending requests. Defaults to
|
||||
// `http.DefaultClient`.
|
||||
HTTPClient *http.Client
|
||||
|
||||
// An integer value representing the logging level. The default log level
|
||||
// is zero (LogOff), which represents no logging. To enable logging set
|
||||
// to a LogLevel Value.
|
||||
LogLevel *LogLevelType
|
||||
|
||||
// The logger writer interface to write logging messages to. Defaults to
|
||||
// standard out.
|
||||
Logger Logger
|
||||
|
||||
// The maximum number of times that a request will be retried for failures.
|
||||
// Defaults to -1, which defers the max retry setting to the service specific
|
||||
// configuration.
|
||||
MaxRetries *int
|
||||
|
||||
// Retryer guides how HTTP requests should be retried in case of recoverable failures.
|
||||
//
|
||||
// When nil or the value does not implement the request.Retryer interface,
|
||||
// the request.DefaultRetryer will be used.
|
||||
//
|
||||
// When both Retryer and MaxRetries are non-nil, the former is used and
|
||||
// the latter ignored.
|
||||
//
|
||||
// To set the Retryer field in a type-safe manner and with chaining, use
|
||||
// the request.WithRetryer helper function:
|
||||
//
|
||||
// cfg := request.WithRetryer(aws.NewConfig(), myRetryer)
|
||||
//
|
||||
Retryer RequestRetryer
|
||||
|
||||
// Disables semantic parameter validation, which validates input for missing
|
||||
// required fields and/or other semantic request input errors.
|
||||
DisableParamValidation *bool
|
||||
|
||||
// Disables the computation of request and response checksums, e.g.,
|
||||
// CRC32 checksums in Amazon DynamoDB.
|
||||
DisableComputeChecksums *bool
|
||||
|
||||
// Set this to `true` to force the request to use path-style addressing,
|
||||
// i.e., `http://s3.amazonaws.com/BUCKET/KEY`. By default, the S3 client will
|
||||
// use virtual hosted bucket addressing when possible
|
||||
// (`http://BUCKET.s3.amazonaws.com/KEY`).
|
||||
//
|
||||
// @note This configuration option is specific to the Amazon S3 service.
|
||||
// @see http://docs.aws.amazon.com/AmazonS3/latest/dev/VirtualHosting.html
|
||||
// Amazon S3: Virtual Hosting of Buckets
|
||||
S3ForcePathStyle *bool
|
||||
|
||||
SleepDelay func(time.Duration)
|
||||
}
|
||||
|
||||
// NewConfig returns a new Config pointer that can be chained with builder methods to
|
||||
// set multiple configuration values inline without using pointers.
|
||||
//
|
||||
// svc := s3.New(aws.NewConfig().WithRegion("us-west-2").WithMaxRetries(10))
|
||||
//
|
||||
func NewConfig() *Config {
|
||||
return &Config{}
|
||||
}
|
||||
|
||||
// WithCredentials sets a config Credentials value returning a Config pointer
|
||||
// for chaining.
|
||||
func (c *Config) WithCredentials(creds *credentials.Credentials) *Config {
|
||||
c.Credentials = creds
|
||||
return c
|
||||
}
|
||||
|
||||
// WithEndpoint sets a config Endpoint value returning a Config pointer for
|
||||
// chaining.
|
||||
func (c *Config) WithEndpoint(endpoint string) *Config {
|
||||
c.Endpoint = &endpoint
|
||||
return c
|
||||
}
|
||||
|
||||
// WithRegion sets a config Region value returning a Config pointer for
|
||||
// chaining.
|
||||
func (c *Config) WithRegion(region string) *Config {
|
||||
c.Region = ®ion
|
||||
return c
|
||||
}
|
||||
|
||||
// WithDisableSSL sets a config DisableSSL value returning a Config pointer
|
||||
// for chaining.
|
||||
func (c *Config) WithDisableSSL(disable bool) *Config {
|
||||
c.DisableSSL = &disable
|
||||
return c
|
||||
}
|
||||
|
||||
// WithHTTPClient sets a config HTTPClient value returning a Config pointer
|
||||
// for chaining.
|
||||
func (c *Config) WithHTTPClient(client *http.Client) *Config {
|
||||
c.HTTPClient = client
|
||||
return c
|
||||
}
|
||||
|
||||
// WithMaxRetries sets a config MaxRetries value returning a Config pointer
|
||||
// for chaining.
|
||||
func (c *Config) WithMaxRetries(max int) *Config {
|
||||
c.MaxRetries = &max
|
||||
return c
|
||||
}
|
||||
|
||||
// WithDisableParamValidation sets a config DisableParamValidation value
|
||||
// returning a Config pointer for chaining.
|
||||
func (c *Config) WithDisableParamValidation(disable bool) *Config {
|
||||
c.DisableParamValidation = &disable
|
||||
return c
|
||||
}
|
||||
|
||||
// WithDisableComputeChecksums sets a config DisableComputeChecksums value
|
||||
// returning a Config pointer for chaining.
|
||||
func (c *Config) WithDisableComputeChecksums(disable bool) *Config {
|
||||
c.DisableComputeChecksums = &disable
|
||||
return c
|
||||
}
|
||||
|
||||
// WithLogLevel sets a config LogLevel value returning a Config pointer for
|
||||
// chaining.
|
||||
func (c *Config) WithLogLevel(level LogLevelType) *Config {
|
||||
c.LogLevel = &level
|
||||
return c
|
||||
}
|
||||
|
||||
// WithLogger sets a config Logger value returning a Config pointer for
|
||||
// chaining.
|
||||
func (c *Config) WithLogger(logger Logger) *Config {
|
||||
c.Logger = logger
|
||||
return c
|
||||
}
|
||||
|
||||
// WithS3ForcePathStyle sets a config S3ForcePathStyle value returning a Config
|
||||
// pointer for chaining.
|
||||
func (c *Config) WithS3ForcePathStyle(force bool) *Config {
|
||||
c.S3ForcePathStyle = &force
|
||||
return c
|
||||
}
|
||||
|
||||
// WithSleepDelay overrides the function used to sleep while waiting for the
|
||||
// next retry. Defaults to time.Sleep.
|
||||
func (c *Config) WithSleepDelay(fn func(time.Duration)) *Config {
|
||||
c.SleepDelay = fn
|
||||
return c
|
||||
}
|
||||
|
||||
// MergeIn merges the passed in configs into the existing config object.
|
||||
func (c *Config) MergeIn(cfgs ...*Config) {
|
||||
for _, other := range cfgs {
|
||||
mergeInConfig(c, other)
|
||||
}
|
||||
}
|
||||
|
||||
func mergeInConfig(dst *Config, other *Config) {
|
||||
if other == nil {
|
||||
return
|
||||
}
|
||||
|
||||
if other.Credentials != nil {
|
||||
dst.Credentials = other.Credentials
|
||||
}
|
||||
|
||||
if other.Endpoint != nil {
|
||||
dst.Endpoint = other.Endpoint
|
||||
}
|
||||
|
||||
if other.Region != nil {
|
||||
dst.Region = other.Region
|
||||
}
|
||||
|
||||
if other.DisableSSL != nil {
|
||||
dst.DisableSSL = other.DisableSSL
|
||||
}
|
||||
|
||||
if other.HTTPClient != nil {
|
||||
dst.HTTPClient = other.HTTPClient
|
||||
}
|
||||
|
||||
if other.LogLevel != nil {
|
||||
dst.LogLevel = other.LogLevel
|
||||
}
|
||||
|
||||
if other.Logger != nil {
|
||||
dst.Logger = other.Logger
|
||||
}
|
||||
|
||||
if other.MaxRetries != nil {
|
||||
dst.MaxRetries = other.MaxRetries
|
||||
}
|
||||
|
||||
if other.Retryer != nil {
|
||||
dst.Retryer = other.Retryer
|
||||
}
|
||||
|
||||
if other.DisableParamValidation != nil {
|
||||
dst.DisableParamValidation = other.DisableParamValidation
|
||||
}
|
||||
|
||||
if other.DisableComputeChecksums != nil {
|
||||
dst.DisableComputeChecksums = other.DisableComputeChecksums
|
||||
}
|
||||
|
||||
if other.S3ForcePathStyle != nil {
|
||||
dst.S3ForcePathStyle = other.S3ForcePathStyle
|
||||
}
|
||||
|
||||
if other.SleepDelay != nil {
|
||||
dst.SleepDelay = other.SleepDelay
|
||||
}
|
||||
}
|
||||
|
||||
// Copy will return a shallow copy of the Config object. If any additional
|
||||
// configurations are provided they will be merged into the new config returned.
|
||||
func (c *Config) Copy(cfgs ...*Config) *Config {
|
||||
dst := &Config{}
|
||||
dst.MergeIn(c)
|
||||
|
||||
for _, cfg := range cfgs {
|
||||
dst.MergeIn(cfg)
|
||||
}
|
||||
|
||||
return dst
|
||||
}
|
||||
86
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config_test.go
generated
vendored
Normal file
86
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/config_test.go
generated
vendored
Normal file
@@ -0,0 +1,86 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"reflect"
|
||||
"testing"
|
||||
|
||||
"github.com/aws/aws-sdk-go/aws/credentials"
|
||||
)
|
||||
|
||||
var testCredentials = credentials.NewStaticCredentials("AKID", "SECRET", "SESSION")
|
||||
|
||||
var copyTestConfig = Config{
|
||||
Credentials: testCredentials,
|
||||
Endpoint: String("CopyTestEndpoint"),
|
||||
Region: String("COPY_TEST_AWS_REGION"),
|
||||
DisableSSL: Bool(true),
|
||||
HTTPClient: http.DefaultClient,
|
||||
LogLevel: LogLevel(LogDebug),
|
||||
Logger: NewDefaultLogger(),
|
||||
MaxRetries: Int(3),
|
||||
DisableParamValidation: Bool(true),
|
||||
DisableComputeChecksums: Bool(true),
|
||||
S3ForcePathStyle: Bool(true),
|
||||
}
|
||||
|
||||
func TestCopy(t *testing.T) {
|
||||
want := copyTestConfig
|
||||
got := copyTestConfig.Copy()
|
||||
if !reflect.DeepEqual(*got, want) {
|
||||
t.Errorf("Copy() = %+v", got)
|
||||
t.Errorf(" want %+v", want)
|
||||
}
|
||||
|
||||
got.Region = String("other")
|
||||
if got.Region == want.Region {
|
||||
t.Errorf("Expect setting copy values not not reflect in source")
|
||||
}
|
||||
}
|
||||
|
||||
func TestCopyReturnsNewInstance(t *testing.T) {
|
||||
want := copyTestConfig
|
||||
got := copyTestConfig.Copy()
|
||||
if got == &want {
|
||||
t.Errorf("Copy() = %p; want different instance as source %p", got, &want)
|
||||
}
|
||||
}
|
||||
|
||||
var mergeTestZeroValueConfig = Config{}
|
||||
|
||||
var mergeTestConfig = Config{
|
||||
Credentials: testCredentials,
|
||||
Endpoint: String("MergeTestEndpoint"),
|
||||
Region: String("MERGE_TEST_AWS_REGION"),
|
||||
DisableSSL: Bool(true),
|
||||
HTTPClient: http.DefaultClient,
|
||||
LogLevel: LogLevel(LogDebug),
|
||||
Logger: NewDefaultLogger(),
|
||||
MaxRetries: Int(10),
|
||||
DisableParamValidation: Bool(true),
|
||||
DisableComputeChecksums: Bool(true),
|
||||
S3ForcePathStyle: Bool(true),
|
||||
}
|
||||
|
||||
var mergeTests = []struct {
|
||||
cfg *Config
|
||||
in *Config
|
||||
want *Config
|
||||
}{
|
||||
{&Config{}, nil, &Config{}},
|
||||
{&Config{}, &mergeTestZeroValueConfig, &Config{}},
|
||||
{&Config{}, &mergeTestConfig, &mergeTestConfig},
|
||||
}
|
||||
|
||||
func TestMerge(t *testing.T) {
|
||||
for i, tt := range mergeTests {
|
||||
got := tt.cfg.Copy()
|
||||
got.MergeIn(tt.in)
|
||||
if !reflect.DeepEqual(got, tt.want) {
|
||||
t.Errorf("Config %d %+v", i, tt.cfg)
|
||||
t.Errorf(" Merge(%+v)", tt.in)
|
||||
t.Errorf(" got %+v", got)
|
||||
t.Errorf(" want %+v", tt.want)
|
||||
}
|
||||
}
|
||||
}
|
||||
357
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/convert_types.go
generated
vendored
Normal file
357
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/convert_types.go
generated
vendored
Normal file
@@ -0,0 +1,357 @@
|
||||
package aws
|
||||
|
||||
import "time"
|
||||
|
||||
// String returns a pointer to of the string value passed in.
|
||||
func String(v string) *string {
|
||||
return &v
|
||||
}
|
||||
|
||||
// StringValue returns the value of the string pointer passed in or
|
||||
// "" if the pointer is nil.
|
||||
func StringValue(v *string) string {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// StringSlice converts a slice of string values into a slice of
|
||||
// string pointers
|
||||
func StringSlice(src []string) []*string {
|
||||
dst := make([]*string, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// StringValueSlice converts a slice of string pointers into a slice of
|
||||
// string values
|
||||
func StringValueSlice(src []*string) []string {
|
||||
dst := make([]string, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// StringMap converts a string map of string values into a string
|
||||
// map of string pointers
|
||||
func StringMap(src map[string]string) map[string]*string {
|
||||
dst := make(map[string]*string)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// StringValueMap converts a string map of string pointers into a string
|
||||
// map of string values
|
||||
func StringValueMap(src map[string]*string) map[string]string {
|
||||
dst := make(map[string]string)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Bool returns a pointer to of the bool value passed in.
|
||||
func Bool(v bool) *bool {
|
||||
return &v
|
||||
}
|
||||
|
||||
// BoolValue returns the value of the bool pointer passed in or
|
||||
// false if the pointer is nil.
|
||||
func BoolValue(v *bool) bool {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// BoolSlice converts a slice of bool values into a slice of
|
||||
// bool pointers
|
||||
func BoolSlice(src []bool) []*bool {
|
||||
dst := make([]*bool, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// BoolValueSlice converts a slice of bool pointers into a slice of
|
||||
// bool values
|
||||
func BoolValueSlice(src []*bool) []bool {
|
||||
dst := make([]bool, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// BoolMap converts a string map of bool values into a string
|
||||
// map of bool pointers
|
||||
func BoolMap(src map[string]bool) map[string]*bool {
|
||||
dst := make(map[string]*bool)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// BoolValueMap converts a string map of bool pointers into a string
|
||||
// map of bool values
|
||||
func BoolValueMap(src map[string]*bool) map[string]bool {
|
||||
dst := make(map[string]bool)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int returns a pointer to of the int value passed in.
|
||||
func Int(v int) *int {
|
||||
return &v
|
||||
}
|
||||
|
||||
// IntValue returns the value of the int pointer passed in or
|
||||
// 0 if the pointer is nil.
|
||||
func IntValue(v *int) int {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// IntSlice converts a slice of int values into a slice of
|
||||
// int pointers
|
||||
func IntSlice(src []int) []*int {
|
||||
dst := make([]*int, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntValueSlice converts a slice of int pointers into a slice of
|
||||
// int values
|
||||
func IntValueSlice(src []*int) []int {
|
||||
dst := make([]int, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntMap converts a string map of int values into a string
|
||||
// map of int pointers
|
||||
func IntMap(src map[string]int) map[string]*int {
|
||||
dst := make(map[string]*int)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// IntValueMap converts a string map of int pointers into a string
|
||||
// map of int values
|
||||
func IntValueMap(src map[string]*int) map[string]int {
|
||||
dst := make(map[string]int)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64 returns a pointer to of the int64 value passed in.
|
||||
func Int64(v int64) *int64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Int64Value returns the value of the int64 pointer passed in or
|
||||
// 0 if the pointer is nil.
|
||||
func Int64Value(v *int64) int64 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Int64Slice converts a slice of int64 values into a slice of
|
||||
// int64 pointers
|
||||
func Int64Slice(src []int64) []*int64 {
|
||||
dst := make([]*int64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64ValueSlice converts a slice of int64 pointers into a slice of
|
||||
// int64 values
|
||||
func Int64ValueSlice(src []*int64) []int64 {
|
||||
dst := make([]int64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64Map converts a string map of int64 values into a string
|
||||
// map of int64 pointers
|
||||
func Int64Map(src map[string]int64) map[string]*int64 {
|
||||
dst := make(map[string]*int64)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Int64ValueMap converts a string map of int64 pointers into a string
|
||||
// map of int64 values
|
||||
func Int64ValueMap(src map[string]*int64) map[string]int64 {
|
||||
dst := make(map[string]int64)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64 returns a pointer to of the float64 value passed in.
|
||||
func Float64(v float64) *float64 {
|
||||
return &v
|
||||
}
|
||||
|
||||
// Float64Value returns the value of the float64 pointer passed in or
|
||||
// 0 if the pointer is nil.
|
||||
func Float64Value(v *float64) float64 {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
// Float64Slice converts a slice of float64 values into a slice of
|
||||
// float64 pointers
|
||||
func Float64Slice(src []float64) []*float64 {
|
||||
dst := make([]*float64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64ValueSlice converts a slice of float64 pointers into a slice of
|
||||
// float64 values
|
||||
func Float64ValueSlice(src []*float64) []float64 {
|
||||
dst := make([]float64, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64Map converts a string map of float64 values into a string
|
||||
// map of float64 pointers
|
||||
func Float64Map(src map[string]float64) map[string]*float64 {
|
||||
dst := make(map[string]*float64)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Float64ValueMap converts a string map of float64 pointers into a string
|
||||
// map of float64 values
|
||||
func Float64ValueMap(src map[string]*float64) map[string]float64 {
|
||||
dst := make(map[string]float64)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// Time returns a pointer to of the time.Time value passed in.
|
||||
func Time(v time.Time) *time.Time {
|
||||
return &v
|
||||
}
|
||||
|
||||
// TimeValue returns the value of the time.Time pointer passed in or
|
||||
// time.Time{} if the pointer is nil.
|
||||
func TimeValue(v *time.Time) time.Time {
|
||||
if v != nil {
|
||||
return *v
|
||||
}
|
||||
return time.Time{}
|
||||
}
|
||||
|
||||
// TimeSlice converts a slice of time.Time values into a slice of
|
||||
// time.Time pointers
|
||||
func TimeSlice(src []time.Time) []*time.Time {
|
||||
dst := make([]*time.Time, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
dst[i] = &(src[i])
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// TimeValueSlice converts a slice of time.Time pointers into a slice of
|
||||
// time.Time values
|
||||
func TimeValueSlice(src []*time.Time) []time.Time {
|
||||
dst := make([]time.Time, len(src))
|
||||
for i := 0; i < len(src); i++ {
|
||||
if src[i] != nil {
|
||||
dst[i] = *(src[i])
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// TimeMap converts a string map of time.Time values into a string
|
||||
// map of time.Time pointers
|
||||
func TimeMap(src map[string]time.Time) map[string]*time.Time {
|
||||
dst := make(map[string]*time.Time)
|
||||
for k, val := range src {
|
||||
v := val
|
||||
dst[k] = &v
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// TimeValueMap converts a string map of time.Time pointers into a string
|
||||
// map of time.Time values
|
||||
func TimeValueMap(src map[string]*time.Time) map[string]time.Time {
|
||||
dst := make(map[string]time.Time)
|
||||
for k, val := range src {
|
||||
if val != nil {
|
||||
dst[k] = *val
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
437
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/convert_types_test.go
generated
vendored
Normal file
437
Godeps/_workspace/src/github.com/aws/aws-sdk-go/aws/convert_types_test.go
generated
vendored
Normal file
@@ -0,0 +1,437 @@
|
||||
package aws
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
var testCasesStringSlice = [][]string{
|
||||
{"a", "b", "c", "d", "e"},
|
||||
{"a", "b", "", "", "e"},
|
||||
}
|
||||
|
||||
func TestStringSlice(t *testing.T) {
|
||||
for idx, in := range testCasesStringSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := StringSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := StringValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesStringValueSlice = [][]*string{
|
||||
{String("a"), String("b"), nil, String("c")},
|
||||
}
|
||||
|
||||
func TestStringValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesStringValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := StringValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := StringSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesStringMap = []map[string]string{
|
||||
{"a": "1", "b": "2", "c": "3"},
|
||||
}
|
||||
|
||||
func TestStringMap(t *testing.T) {
|
||||
for idx, in := range testCasesStringMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := StringMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := StringValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesBoolSlice = [][]bool{
|
||||
{true, true, false, false},
|
||||
}
|
||||
|
||||
func TestBoolSlice(t *testing.T) {
|
||||
for idx, in := range testCasesBoolSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := BoolSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := BoolValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesBoolValueSlice = [][]*bool{}
|
||||
|
||||
func TestBoolValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesBoolValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := BoolValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := BoolSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesBoolMap = []map[string]bool{
|
||||
{"a": true, "b": false, "c": true},
|
||||
}
|
||||
|
||||
func TestBoolMap(t *testing.T) {
|
||||
for idx, in := range testCasesBoolMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := BoolMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := BoolValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesIntSlice = [][]int{
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
func TestIntSlice(t *testing.T) {
|
||||
for idx, in := range testCasesIntSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := IntSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := IntValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesIntValueSlice = [][]*int{}
|
||||
|
||||
func TestIntValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesIntValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := IntValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := IntSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesIntMap = []map[string]int{
|
||||
{"a": 3, "b": 2, "c": 1},
|
||||
}
|
||||
|
||||
func TestIntMap(t *testing.T) {
|
||||
for idx, in := range testCasesIntMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := IntMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := IntValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesInt64Slice = [][]int64{
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
func TestInt64Slice(t *testing.T) {
|
||||
for idx, in := range testCasesInt64Slice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Int64Slice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Int64ValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesInt64ValueSlice = [][]*int64{}
|
||||
|
||||
func TestInt64ValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesInt64ValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Int64ValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := Int64Slice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesInt64Map = []map[string]int64{
|
||||
{"a": 3, "b": 2, "c": 1},
|
||||
}
|
||||
|
||||
func TestInt64Map(t *testing.T) {
|
||||
for idx, in := range testCasesInt64Map {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Int64Map(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Int64ValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesFloat64Slice = [][]float64{
|
||||
{1, 2, 3, 4},
|
||||
}
|
||||
|
||||
func TestFloat64Slice(t *testing.T) {
|
||||
for idx, in := range testCasesFloat64Slice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Float64Slice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Float64ValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesFloat64ValueSlice = [][]*float64{}
|
||||
|
||||
func TestFloat64ValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesFloat64ValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Float64ValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := Float64Slice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesFloat64Map = []map[string]float64{
|
||||
{"a": 3, "b": 2, "c": 1},
|
||||
}
|
||||
|
||||
func TestFloat64Map(t *testing.T) {
|
||||
for idx, in := range testCasesFloat64Map {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := Float64Map(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := Float64ValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesTimeSlice = [][]time.Time{
|
||||
{time.Now(), time.Now().AddDate(100, 0, 0)},
|
||||
}
|
||||
|
||||
func TestTimeSlice(t *testing.T) {
|
||||
for idx, in := range testCasesTimeSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := TimeSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := TimeValueSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesTimeValueSlice = [][]*time.Time{}
|
||||
|
||||
func TestTimeValueSlice(t *testing.T) {
|
||||
for idx, in := range testCasesTimeValueSlice {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := TimeValueSlice(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, out[i], "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, *(in[i]), out[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
|
||||
out2 := TimeSlice(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out2 {
|
||||
if in[i] == nil {
|
||||
assert.Empty(t, *(out2[i]), "Unexpected value at idx %d", idx)
|
||||
} else {
|
||||
assert.Equal(t, in[i], out2[i], "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var testCasesTimeMap = []map[string]time.Time{
|
||||
{"a": time.Now().AddDate(-100, 0, 0), "b": time.Now()},
|
||||
}
|
||||
|
||||
func TestTimeMap(t *testing.T) {
|
||||
for idx, in := range testCasesTimeMap {
|
||||
if in == nil {
|
||||
continue
|
||||
}
|
||||
out := TimeMap(in)
|
||||
assert.Len(t, out, len(in), "Unexpected len at idx %d", idx)
|
||||
for i := range out {
|
||||
assert.Equal(t, in[i], *(out[i]), "Unexpected value at idx %d", idx)
|
||||
}
|
||||
|
||||
out2 := TimeValueMap(out)
|
||||
assert.Len(t, out2, len(in), "Unexpected len at idx %d", idx)
|
||||
assert.Equal(t, in, out2, "Unexpected value at idx %d", idx)
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user