Compare commits
1587 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 26c148dccc | |||
| 8497056185 | |||
| 5498e2c2bb | |||
| 602a8ce08c | |||
| 7e82524c4e | |||
| 783973b9da | |||
| 096cd1ef73 | |||
| 07b01fa318 | |||
| 0ba253c61d | |||
| 5da7f034e9 | |||
| 8eebd4ccae | |||
| c47e254efe | |||
| 3f35749619 | |||
| e818197365 | |||
| 1ffcc853e1 | |||
| 284e440b7e | |||
| 50597b5715 | |||
| 9d7519d591 | |||
| f35110309a | |||
| c73860d144 | |||
| 1842c78c5d | |||
| da39eb3ceb | |||
| baef12eb2a | |||
| 5389a018b3 | |||
| 00487c87fc | |||
| 4dbcfc6907 | |||
| 8ba319b9d9 | |||
| 2d6ea3c57c | |||
| c2433a336c | |||
| 44e76adbd1 | |||
| 3f348e00cf | |||
| bd40428ad9 | |||
| 9dc99d5e35 | |||
| ea92608f84 | |||
| fc7c2523c2 | |||
| 7397541259 | |||
| f921e891a3 | |||
| 69acaabec1 | |||
| 72b1fb1d60 | |||
| 34e7440517 | |||
| 0769b634e0 | |||
| 9e6947f62c | |||
| 4a43b97f64 | |||
| 6372d393ee | |||
| 0b51cb703d | |||
| af8dc17f5e | |||
| a4155ad6d8 | |||
| 0c727a2817 | |||
| 8222234f86 | |||
| 345aac8d5b | |||
| 0da9f108a3 | |||
| abb88f20f9 | |||
| 7c9652d966 | |||
| 65571f4ee2 | |||
| 5e01da2013 | |||
| b0756b0b0e | |||
| b4de7fd64a | |||
| 1f1a4ac15c | |||
| f0fb66be7d | |||
| 7f09814973 | |||
| dc5f3c1f27 | |||
| 96aa442855 | |||
| 6dfaaffdfe | |||
| 19c39341f7 | |||
| 2b6c6b3022 | |||
| e53fe669ef | |||
| f37fe60bd5 | |||
| ef5fc2e7b2 | |||
| 3af09bfe9f | |||
| c000ef0b5c | |||
| 9e1b4e1c52 | |||
| a242d13bb9 | |||
| 2fb6588160 | |||
| 3777ea9a7d | |||
| dd63ff850c | |||
| 4730ee317b | |||
| 398c75ca4d | |||
| 4b2ddbdbdd | |||
| 5e9f73b114 | |||
| 85b18eec05 | |||
| fc7db11c6c | |||
| a0f7dbbc60 | |||
| 7aaf024397 | |||
| 41f5d7d113 | |||
| 18e0eda7d3 | |||
| 85938e5432 | |||
| 733fb7ed33 | |||
| 237fcbead6 | |||
| ad12026e29 | |||
| 7f5d22b587 | |||
| ad72ba6c6a | |||
| fdf0182ffe | |||
| 789a9434c1 | |||
| 01a2988737 | |||
| 8177d08df2 | |||
| 1e5db34679 | |||
| 23c86ecc4a | |||
| 3dff904264 | |||
| f12091df5d | |||
| 2b25de4ae6 | |||
| b0ca59b0ab | |||
| 9b067d3539 | |||
| be1fbcfe04 | |||
| 0ea7bdfe7b | |||
| 043437b725 | |||
| bfbcbdb604 | |||
| 67b348df92 | |||
| fee48e9dee | |||
| 6967ed1846 | |||
| af46e1a549 | |||
| ef4710b6cc | |||
| afa27ce872 | |||
| 08991dc98c | |||
| c0ccc79604 | |||
| b59c7d8af6 | |||
| 1b20f0be0d | |||
| 1f25847cd7 | |||
| 89bdbf500e | |||
| bef6afe359 | |||
| c91776dd5e | |||
| fceb7804b4 | |||
| 3fadfaf632 | |||
| 788ed8b61b | |||
| d926f1b3a2 | |||
| e33498fb56 | |||
| eb220b6db0 | |||
| 759c21cec9 | |||
| 3e36e06d77 | |||
| 0a31ac6ef3 | |||
| bf4b48aa9d | |||
| 6e08a7d8ce | |||
| 0e6465ee14 | |||
| 3bc6bf6da5 | |||
| 2fec8b6b02 | |||
| a2839876c6 | |||
| 5b4c897892 | |||
| a884a9c56c | |||
| caf942db8b | |||
| fb4dfb62f6 | |||
| dcfe0c8bda | |||
| b28d23b8e7 | |||
| 6c7ecaed5b | |||
| 37444a500d | |||
| f645e6ffa9 | |||
| 956d1d53a6 | |||
| 90267338a4 | |||
| 4650940084 | |||
| adf34cd18e | |||
| 838a5e07f7 | |||
| 7d380a6e03 | |||
| 41f0d6f211 | |||
| 05d7ed92fb | |||
| b5f02367ab | |||
| fbfcccc13d | |||
| 37db8516ed | |||
| d7c0a92d9f | |||
| d88ed02a8d | |||
| 4cc31a62c0 | |||
| 8c5e20c8fe | |||
| f049d1b479 | |||
| db2d7687e4 | |||
| c97311607d | |||
| dbd9db780c | |||
| 04775098fe | |||
| 4ede57836e | |||
| 778a557f3c | |||
| 6a94694f16 | |||
| 638f71d80e | |||
| f849ca38fc | |||
| c073ab2731 | |||
| 11aea0f515 | |||
| d803aeb205 | |||
| 9663cfde82 | |||
| fc3c8bab45 | |||
| 1d5a807e0d | |||
| bb59c4708d | |||
| 23fda3a0ed | |||
| 35af025ae3 | |||
| dfc8f3837a | |||
| 19851b6986 | |||
| f36a23dd42 | |||
| 55e1a792da | |||
| 5eedfc2a53 | |||
| a6d9b4b260 | |||
| 4422c5ec52 | |||
| c4fc5a04f9 | |||
| 63bbbbab31 | |||
| fc6dc25224 | |||
| fe914dc339 | |||
| 23136c5f4f | |||
| 1bdd848582 | |||
| a2cb5fac98 | |||
| ee5a834ab0 | |||
| a3f2372b6c | |||
| c209bdde5b | |||
| f35c63fa40 | |||
| 309ca0a765 | |||
| abc2bfa774 | |||
| 3c446a3ba0 | |||
| f30171bcfd | |||
| 80db20fdfb | |||
| 9cd2db5018 | |||
| 02b6b77d38 | |||
| 9241e1fcda | |||
| 122c18e6d7 | |||
| 6e36755de5 | |||
| 190b16626f | |||
| ecc83595c8 | |||
| d073e727cb | |||
| b96e1343c2 | |||
| d272dbf611 | |||
| 814e4c781f | |||
| 5ef067b5f0 | |||
| c36a1e4537 | |||
| f4342ed9cb | |||
| 8517a8e088 | |||
| d3c45bc90f | |||
| 3a0c872587 | |||
| 92b11bf966 | |||
| a7f68fa3d3 | |||
| f59104a6f1 | |||
| 3c2e84fdae | |||
| 9397b34e35 | |||
| 2613d0b5ac | |||
| 5a5ce293d2 | |||
| 4a1113307e | |||
| 86acf0c1ad | |||
| 2ea5a7a293 | |||
| fbc4820ab4 | |||
| 3a487e447b | |||
| ff607aef7a | |||
| 10db2834aa | |||
| 8dc3b032b7 | |||
| 7aa9ae8771 | |||
| a83ea47c25 | |||
| 2ce9d9f7dc | |||
| 4a77afd3c8 | |||
| fd6582f066 | |||
| 6f409fdec2 | |||
| d03152c4f1 | |||
| 09d65a5aae | |||
| cd601d8ada | |||
| 29ae78b1a0 | |||
| 4cefd355ec | |||
| 8404efc521 | |||
| c8cc5278f3 | |||
| 60c66823f8 | |||
| 6a946c8a1c | |||
| 960755b22c | |||
| ae1c0e3c9b | |||
| dc8ab7d00a | |||
| 9a2fd293cd | |||
| 9fa148db4f | |||
| 902efef481 | |||
| 9b8943f80c | |||
| 1c1a4778f9 | |||
| 6c430bd0f5 | |||
| 2660b31370 | |||
| 1d4f6ba813 | |||
| 7baca85f6a | |||
| 8e78c3dfb1 | |||
| 01b3747956 | |||
| 7559fab5ce | |||
| 60910efc53 | |||
| 3f7a5d18f8 | |||
| c0cdf727ca | |||
| 675ce08469 | |||
| 8c1f236e3f | |||
| 344b67d236 | |||
| bd3f7ffcd4 | |||
| 154d36e580 | |||
| 9162be9fb0 | |||
| 940bc0c7de | |||
| b8af6f7987 | |||
| fd993f733f | |||
| f7e097be8e | |||
| e920d3f4b2 | |||
| 9b9173d64f | |||
| e0c0eecaac | |||
| ed4ded79ee | |||
| f11c71599b | |||
| 7109338f68 | |||
| 26a49fbe9f | |||
| 6deb97e356 | |||
| ff0af2f227 | |||
| 2bb5d0b30e | |||
| dffe33569a | |||
| 567863079e | |||
| c571284f40 | |||
| 52bb935604 | |||
| 89c84c7a30 | |||
| d2e8b084f5 | |||
| 99181d5bf4 | |||
| 1f353da33c | |||
| 8c88f8709b | |||
| 0f3a8bff5d | |||
| 0811baef9b | |||
| 7d76e2efbc | |||
| eadd79771d | |||
| 8a3232bd23 | |||
| 0eddf6b755 | |||
| 3c8a5c3a0d | |||
| 6f4ad059ef | |||
| 295f59e236 | |||
| b39b724303 | |||
| 4ca88e48c2 | |||
| 53aed514fa | |||
| 6afb28088d | |||
| 33fdfbbad5 | |||
| a9d6a842b6 | |||
| cbe4154013 | |||
| 02ac44e214 | |||
| 187a32cdc0 | |||
| 2bd9e24cc2 | |||
| 2669a51fe1 | |||
| fd2137ec8d | |||
| 9f1dfb2684 | |||
| 4442afc1fd | |||
| f63456a18f | |||
| 065de778f0 | |||
| 1b5c553a05 | |||
| 113b8d825e | |||
| 3ec31bb64d | |||
| 3b771bf0f7 | |||
| b5c3b85298 | |||
| b744962066 | |||
| 882fa42e2d | |||
| 2d79188433 | |||
| 9a4c022ea3 | |||
| 808fc14b32 | |||
| 92f0d0d2ea | |||
| 9180ab4442 | |||
| 4e1e9e0687 | |||
| c264368042 | |||
| ff8ea3ec6b | |||
| c85185bdb0 | |||
| 43fd34ab80 | |||
| 794c7fc389 | |||
| e0b1507056 | |||
| c7fabf84ba | |||
| d7e97ac771 | |||
| ef7be48cc5 | |||
| 88b6f4e436 | |||
| 5fdaa451b8 | |||
| 18cd9ea1e8 | |||
| 888f8cfc56 | |||
| d36ec60039 | |||
| b9d7046bbc | |||
| 09dd5cf879 | |||
| 06f014df61 | |||
| f622a9154b | |||
| d7d36c34be | |||
| 6f6c29ce43 | |||
| 26a004210e | |||
| d9459661eb | |||
| 2da5a522b0 | |||
| 7a9a4a2fab | |||
| 6c526b24a0 | |||
| 1f1bb37a57 | |||
| 959caf4d04 | |||
| ec1d013004 | |||
| fe648c8069 | |||
| 017b5353db | |||
| 66f9eb01c7 | |||
| 390514cd9d | |||
| 309e0e6dc8 | |||
| cf6a8956cd | |||
| 438261beb8 | |||
| 9488df823a | |||
| 1294512ce8 | |||
| baead95c33 | |||
| c7c1c7e8fa | |||
| 132b729dd9 | |||
| c2dae6f5a0 | |||
| e2bcf59b0f | |||
| e9752cd5e1 | |||
| 45f959fb6b | |||
| ef897b2d3e | |||
| 9e21a72515 | |||
| e17d2fbfc0 | |||
| 9b5455c186 | |||
| 05317bb5e6 | |||
| 157b66dc4c | |||
| 874ec142bf | |||
| 596157f90b | |||
| 2a080da666 | |||
| c8e65f085b | |||
| 014e50a13a | |||
| 9a2aa8fff0 | |||
| 9fc3dfdbee | |||
| 565c9ef95d | |||
| 973a6471f3 | |||
| a87987e5e9 | |||
| dad318834f | |||
| 4e099f7509 | |||
| abf61417ad | |||
| d3ad0b8e03 | |||
| 7cc300f59c | |||
| 615d57a78b | |||
| 6ac654a36b | |||
| ec78e99ca0 | |||
| 912b101d0a | |||
| 130dabfdce | |||
| d697e46f24 | |||
| 1296214400 | |||
| e7932b6ae4 | |||
| 12dbb0ec20 | |||
| 24e9136f57 | |||
| 1fc09cda0f | |||
| 43d3d6b235 | |||
| 66b2ad9fdb | |||
| 65d68aefad | |||
| c2039ef01f | |||
| 722bc7b110 | |||
| 73b9374006 | |||
| c24683b014 | |||
| c0f102f1e0 | |||
| ca993187b0 | |||
| 861b2c61a8 | |||
| 9daae665e4 | |||
| 972a9da2f1 | |||
| 7a07649e2b | |||
| a03173da4d | |||
| c841f32ba6 | |||
| cf2938151f | |||
| 1908725a9a | |||
| 6ffcea8aae | |||
| 0e41c2dfcd | |||
| 072c1a6764 | |||
| 2051caaa01 | |||
| 20293fb50d | |||
| 7e77cd334d | |||
| 229e6dd043 | |||
| a8ad55ef3c | |||
| 41407d27d0 | |||
| 7cec861323 | |||
| b4a941e367 | |||
| 5a8f37ff02 | |||
| 9e35748040 | |||
| 374011ec9e | |||
| 2a2cea0b7d | |||
| c56dc63150 | |||
| 57c9acc874 | |||
| f9761ad2f8 | |||
| f2fafbc631 | |||
| 583b25a85d | |||
| f966c38513 | |||
| f8b6b8c9ad | |||
| 39b2e6543c | |||
| 92f85fad4a | |||
| ebe224fb6e | |||
| 8521a405f7 | |||
| 13d6dfd234 | |||
| 914a8fdc2b | |||
| 7aa413d558 | |||
| f416fc6919 | |||
| 85c9e66cee | |||
| ca13782e2a | |||
| 2607e5b5a1 | |||
| 9ca298543f | |||
| ad633c7606 | |||
| 47cfe9c6c0 | |||
| 37871f4de5 | |||
| 7132ccdd99 | |||
| 7250b3d491 | |||
| 02de09eaf7 | |||
| 7c43fbd0c6 | |||
| 6f139cd72a | |||
| 97d4d48c4d | |||
| e644b63ba6 | |||
| 52be2d7864 | |||
| 9d5b089227 | |||
| 1f37fb2c67 | |||
| 916340f1f4 | |||
| 00bcef3ba6 | |||
| f4983a2b21 | |||
| ec9d4dc565 | |||
| 80412f56ee | |||
| 2bae3e2eda | |||
| 3caafc03f1 | |||
| 6bcf1e4cd8 | |||
| ef28f23c61 | |||
| 860def507b | |||
| fdfdd541e3 | |||
| e9a31437e1 | |||
| d3c8b46e00 | |||
| 416cea796e | |||
| e34926acd6 | |||
| b63af8b56f | |||
| 75d685ef43 | |||
| 0af18b2376 | |||
| 10207a1c50 | |||
| 8f7bc1a083 | |||
| a9fd88567e | |||
| cabc3b7567 | |||
| 579dc058aa | |||
| a57658b274 | |||
| 8dbc4cb2c5 | |||
| e74112ee2a | |||
| be9db43e21 | |||
| 8b86c372dc | |||
| 06d813736d | |||
| c087f09071 | |||
| 6637cc47ee | |||
| 0d3ea107c5 | |||
| b7f187b69a | |||
| 534788cc38 | |||
| 5466287063 | |||
| 49e35367f1 | |||
| e8aa6701ef | |||
| b3696c29cc | |||
| afd8e7d404 | |||
| 14365e3894 | |||
| 3587039406 | |||
| 3750ebf882 | |||
| 8df060fb00 | |||
| 570ca464e7 | |||
| ecf9a928d7 | |||
| a697608529 | |||
| 9c3e8b8e3c | |||
| b931ce0123 | |||
| fccd0b4f42 | |||
| b10c0e7f4c | |||
| c23d6f12ac | |||
| 0a168986cb | |||
| 618897aa3f | |||
| e6e619b967 | |||
| a5467bc277 | |||
| c0af8de493 | |||
| 9bc1f1e468 | |||
| d181ab193f | |||
| b6b44e30f6 | |||
| 41a3dc862e | |||
| 40f04f7510 | |||
| 96a89c0166 | |||
| 451f894976 | |||
| 43fdd691fe | |||
| 2f7ddb20db | |||
| 372d0f7c3c | |||
| 7affbbd186 | |||
| d4d90e1d4d | |||
| 082bf484ed | |||
| 1879cfe029 | |||
| 7caf7e6a78 | |||
| 9f04a9de9c | |||
| ffccad642e | |||
| c95340ab78 | |||
| 9cd9470f87 | |||
| cc4815200e | |||
| 3c1b8de323 | |||
| 2386845347 | |||
| 619d24ec3c | |||
| 0e9b7bfccc | |||
| 7a615133ff | |||
| c1f3de7e5c | |||
| 98eae84d56 | |||
| 0364e1b176 | |||
| c2cfdfd746 | |||
| d12fa45571 | |||
| ee87d00ffe | |||
| 6a05c556b5 | |||
| ed81214e87 | |||
| 0439812607 | |||
| a0519be6a8 | |||
| f40af21e55 | |||
| 3c27f95397 | |||
| 79ce8a29ae | |||
| 2a532e6993 | |||
| ef07efcfba | |||
| 9e16d92c99 | |||
| aca08a8021 | |||
| 4f4dc922e0 | |||
| 69a103ce3d | |||
| fa7382d073 | |||
| 53adf532d1 | |||
| 3c8a870dfa | |||
| de2322e384 | |||
| 2c9b128daf | |||
| 77168c7d10 | |||
| cfca39274f | |||
| 59f67ffd19 | |||
| 427d4e4655 | |||
| 931baffb45 | |||
| d38c856923 | |||
| 549a030d91 | |||
| 1dab7e5261 | |||
| 52b7be0f15 | |||
| 35660a2131 | |||
| 6fac55595d | |||
| f343d98391 | |||
| b515f24c16 | |||
| 8f31ea7b3d | |||
| c56b983cd6 | |||
| db230aa45d | |||
| 8359ea5862 | |||
| e350ab89ca | |||
| b3a8161b25 | |||
| 449b6af70e | |||
| 7e4f2957a3 | |||
| 8ad4848536 | |||
| f91bc1604a | |||
| 4b120827cf | |||
| 69d1f4e0cd | |||
| 5af5264764 | |||
| f015c0f27f | |||
| 8462c7efbb | |||
| 7660e10098 | |||
| 058033527d | |||
| 7f7cceb90f | |||
| 7e32dbc544 | |||
| 5d3309dbf1 | |||
| ba66b4dd36 | |||
| da4e63719f | |||
| 833d6ac722 | |||
| 413e1b35b6 | |||
| eba94c994b | |||
| d1273f2ba9 | |||
| 580ea66ea5 | |||
| c0e36822b3 | |||
| 58e14d3e6d | |||
| 00b3234124 | |||
| eff70db87e | |||
| 51ab9e32de | |||
| e6842a1020 | |||
| 35ca13c83a | |||
| 9b8f4c1a9a | |||
| 48362f50ba | |||
| 52a9fced07 | |||
| 69272d2a20 | |||
| 60d558508f | |||
| 32f061b555 | |||
| 6251dc1acf | |||
| 1e9e13ea6a | |||
| 3f48f8c8e1 | |||
| 722510aee1 | |||
| 1de3f01207 | |||
| d25c16025b | |||
| d9b10b294e | |||
| 42dcaf9ccd | |||
| a860e6b324 | |||
| 0f818c4e0a | |||
| 5f6fdc759a | |||
| 00959a16cc | |||
| 51fc0da379 | |||
| cda4f6a2f0 | |||
| 0a29ad3d21 | |||
| 623fa59a3f | |||
| 8c815554da | |||
| 16cff73f9d | |||
| 31965358c3 | |||
| f083a33d92 | |||
| f7517fa64b | |||
| 9c8d73dcfa | |||
| ffd0adb0f3 | |||
| 477245ee71 | |||
| ce74108848 | |||
| 88ac1f59e7 | |||
| 5fa5f90bfc | |||
| 0c3c5a2a5f | |||
| f402b9e449 | |||
| ee0888e58c | |||
| 7aa47f32c4 | |||
| 70aeb1c09d | |||
| bf9a336344 | |||
| 2142bd978f | |||
| f058ec9c03 | |||
| 68f4aae172 | |||
| d09aeeaf2e | |||
| ecaea2a5b7 | |||
| 774227314e | |||
| 5f7ba058ca | |||
| 9d0c1b5278 | |||
| e0643c8dd0 | |||
| 385f1d6689 | |||
| c0b094f2e8 | |||
| d2500b36d3 | |||
| 476e33bf40 | |||
| 59d68a7fdc | |||
| 083a34275e | |||
| b3d2e49f1a | |||
| bbe15b69b7 | |||
| 3371360bc7 | |||
| 9fb1ce534b | |||
| a4d9790279 | |||
| f6efbcf99f | |||
| 101135b1ea | |||
| 1ac62dcee7 | |||
| 8b6a321897 | |||
| a2b609fc12 | |||
| dd53811698 | |||
| 7cb1ac6acf | |||
| 119cf54e97 | |||
| 96fada7586 | |||
| c0058109b8 | |||
| ad81b193a2 | |||
| f8f94eae32 | |||
| 4724230d2c | |||
| b40d717546 | |||
| b3f4ca13a4 | |||
| 1bb593d264 | |||
| dd49febd77 | |||
| ff5bda551c | |||
| 63a72090a4 | |||
| ef58e3226b | |||
| 4fc929fc64 | |||
| f2aa1ea95b | |||
| 6fdc49fa28 | |||
| be45237830 | |||
| ae3205c429 | |||
| 1ad483df70 | |||
| 1d0ef8980f | |||
| 2c28c82b06 | |||
| 4626041aca | |||
| 7e88696cbc | |||
| f49d057262 | |||
| 8ef213547a | |||
| b3ed3585e4 | |||
| bd5e1a2461 | |||
| a4bd2ae4c7 | |||
| 55401fffbb | |||
| 35bbb5aae4 | |||
| d02a8c0a59 | |||
| 10c71a7381 | |||
| 5c275df83c | |||
| 576ff6d2b9 | |||
| 323954243b | |||
| a9e9eb9bdd | |||
| f62b7dd4fd | |||
| ea9663fa22 | |||
| 35e3a39cc3 | |||
| def3529f12 | |||
| 0e5f52d2e0 | |||
| 46b63e5400 | |||
| d269bae3c4 | |||
| 8e0b89801a | |||
| cac35b6894 | |||
| b16c5f3cdf | |||
| 677f22b008 | |||
| 9875c37cf2 | |||
| 67e36a0d60 | |||
| bcca0528c0 | |||
| 411ff80b3e | |||
| 768e360853 | |||
| 2af5cf97ef | |||
| f420f7a870 | |||
| 6116161fef | |||
| cf6fc2ec78 | |||
| 4f2b7411e9 | |||
| 359201955a | |||
| fe7431b9ab | |||
| 3d19fb57b4 | |||
| ce2e8a147e | |||
| 6235dd282b | |||
| 1fbbd7a576 | |||
| 699bb3272d | |||
| c8f52aa238 | |||
| 94cfbaf0ab | |||
| 042db06ba1 | |||
| b22ee9255d | |||
| d6e7be1b0b | |||
| f0f55156d1 | |||
| ebee70fb61 | |||
| 824c428579 | |||
| fe445f5ecd | |||
| 4f04692afa | |||
| 3d0ef17ab5 | |||
| 9909b10edb | |||
| aa8436f07f | |||
| d4e3a66dc6 | |||
| 7fa66ed914 | |||
| 66a40eb69f | |||
| b5c86f1412 | |||
| 4e6c4d6f7f | |||
| 6bc1ed588b | |||
| 54477f8a79 | |||
| 8e08552ab7 | |||
| 5a0fbd0900 | |||
| b32b23172a | |||
| 3d7d223cb1 | |||
| 2f4bdf1af5 | |||
| 49de3f264c | |||
| cf59067451 | |||
| ebbdb945c4 | |||
| f877e0d1bb | |||
| aa132b29ee | |||
| 3e12908332 | |||
| b207d6a7ad | |||
| 61bde607c7 | |||
| bd7608599b | |||
| a26663653e | |||
| ba408e8c79 | |||
| 545360bdaa | |||
| 9d63b68eb6 | |||
| 4417892337 | |||
| 6cbc3367b1 | |||
| bd7211f8e6 | |||
| 95301fbc2b | |||
| c961ffcef2 | |||
| f034fbccf9 | |||
| 65d9b3b99d | |||
| 6a422fc88d | |||
| ecaa853799 | |||
| bb28d3f4a9 | |||
| 9f90c99350 | |||
| ef580558b1 | |||
| d327299d76 | |||
| 6b625481ff | |||
| 9cfc997ba2 | |||
| 3fecd55c49 | |||
| 1cbb456dcd | |||
| f3375c01d8 | |||
| 8be303cb05 | |||
| 77f0b4e093 | |||
| 59e291f961 | |||
| 50e4825066 | |||
| 7d4ba999cf | |||
| 72fb712bad | |||
| 359b1ac774 | |||
| 9d49ddba7c | |||
| 56ba6c7a1d | |||
| 8b1c506fef | |||
| 6d0307cdc7 | |||
| 81f78e3ec5 | |||
| 4acc3f48bf | |||
| feb16f901f | |||
| 80c585c21e | |||
| 4708293b18 | |||
| 4235963fce | |||
| 7d2bbb64b1 | |||
| b72e0ba30b | |||
| f6c03c1fe1 | |||
| 383d5527bb | |||
| b16ea2c9bf | |||
| b1be0f2dae | |||
| 785dc4864a | |||
| 07ccdfb7af | |||
| a380683833 | |||
| 4171fc7bfa | |||
| 02a00eca49 | |||
| 12ea56261f | |||
| 913364b2c7 | |||
| 2022ca6d64 | |||
| 500cd9da19 | |||
| 7372fa1705 | |||
| 9ec1d20d51 | |||
| 0e4bcc96e7 | |||
| 82c7bc45a7 | |||
| 10484a2240 | |||
| 8d41d106d0 | |||
| 8e18778bc2 | |||
| 8068641120 | |||
| b08343fe76 | |||
| 388f9e3a1e | |||
| 51b77669cb | |||
| f04335ef7d | |||
| aca0249c0f | |||
| d66e951b68 | |||
| 9c33f1b1c9 | |||
| 884d49a349 | |||
| e630faa185 | |||
| 44529f266e | |||
| faad17a92e | |||
| 3be22bd6a7 | |||
| 3520f2d1e4 | |||
| f29167eb59 | |||
| 598566198d | |||
| 20cd36026e | |||
| 27891e304d | |||
| f848746f33 | |||
| 3b4e1ea3d6 | |||
| 09006352f7 | |||
| 5e3a8b4694 | |||
| e034bd4a1f | |||
| 90a53ddcc7 | |||
| acab866b29 | |||
| cb1a0897eb | |||
| fde1d6f6fb | |||
| 8337500356 | |||
| 4577ec1016 | |||
| d91e3e90c6 | |||
| 02c02a3abe | |||
| 939cac264a | |||
| 2715d49630 | |||
| 083fbbf3c6 | |||
| 9b0bf28d15 | |||
| 945271cb67 | |||
| 94a65fa628 | |||
| 6dae192497 | |||
| 9388089b9e | |||
| 3978d0c529 | |||
| 4670ba9fe0 | |||
| c89423946a | |||
| 297c4a8e73 | |||
| 78fe1015aa | |||
| 5a43f6b6fe | |||
| 66b0d4e3b6 | |||
| 74ce567702 | |||
| 0571970a92 | |||
| a63b3889e7 | |||
| 72e0eabb4b | |||
| 0745ed87c2 | |||
| c3d7bd5fdf | |||
| b60e7246fb | |||
| 73d6f81d67 | |||
| 9e9648cbb8 | |||
| 34b2349cd7 | |||
| d43d432d2f | |||
| e4fafd55c8 | |||
| 3c9ba6502a | |||
| bd7aea31ee | |||
| dd7d6ba392 | |||
| 2f93601544 | |||
| 0512a13ef1 | |||
| aaf88a8488 | |||
| 56d54de3b3 | |||
| ab8472780a | |||
| 98648b12f1 | |||
| a3e0f908de | |||
| 73ee972d37 | |||
| d166591ee5 | |||
| 06ee6e3845 | |||
| 6e8214e697 | |||
| 0eceb3c7fc | |||
| 9008e6af88 | |||
| bf1024c1b0 | |||
| 5013c5f526 | |||
| b5333fe2d6 | |||
| d9df6e12be | |||
| adde66d3e9 | |||
| eb6da7a41a | |||
| 33be5a4960 | |||
| 3f6ac3fcd6 | |||
| b98aa215c3 | |||
| d07bd58deb | |||
| ed1d7fb2c5 | |||
| d8ba0d352e | |||
| c2aa3e9d06 | |||
| 11a0b36ff0 | |||
| 764a706143 | |||
| a9a274dea5 | |||
| ccd8ecd055 | |||
| 394fa9215a | |||
| faf9800235 | |||
| bc06d7b20c | |||
| 7287d8c565 | |||
| 99589789dd | |||
| e789cb8875 | |||
| f208fc65d0 | |||
| e7c1d3dd2e | |||
| 379ac8a3cb | |||
| 8202dbcc5b | |||
| 8172789537 | |||
| 08dd74322a | |||
| d4f884df74 | |||
| aa582658ac | |||
| 8953021784 | |||
| 2330ff334b | |||
| 0b7426aa3f | |||
| 8444423201 | |||
| 6697c67f38 | |||
| 4dbec70f00 | |||
| 0e72c34973 | |||
| da4e519e4b | |||
| 42a6872685 | |||
| 2b5ef7b45c | |||
| a8cf6e8426 | |||
| fefb6e4454 | |||
| d167e7bf0b | |||
| 01927e1e53 | |||
| 825f785a2b | |||
| 632e401d33 | |||
| 062a47f2aa | |||
| f92a03b996 | |||
| 1255eed84c | |||
| fe2ff696c5 | |||
| 240c205765 | |||
| 03019e9676 | |||
| 697cc7a420 | |||
| 8961f930e3 | |||
| 2d3ef8d311 | |||
| 02afb1e774 | |||
| 222cb25cfd | |||
| cca3c5df78 | |||
| 1b42a2a6ac | |||
| 87df9b8f04 | |||
| 6188629da6 | |||
| 2c04a02d62 | |||
| 0216bea233 | |||
| ccc8868f68 | |||
| 328f83c0c7 | |||
| b8a77b8661 | |||
| 6d84e1bb40 | |||
| 0aec09a258 | |||
| 078e45b7ea | |||
| 2de0d5e09f | |||
| 504b6cb079 | |||
| 90e6769169 | |||
| fd3e6f4d9c | |||
| 3cfd9c5b00 | |||
| b75cf3bc76 | |||
| e907a085bd | |||
| 9e826004d8 | |||
| 33b7f355c9 | |||
| 5d79d01457 | |||
| 6c0c59f731 | |||
| a24fd55b43 | |||
| e26b8ae6d9 | |||
| cde7f0fa18 | |||
| 3398de7fdb | |||
| e6a354876d | |||
| 40791e1266 | |||
| 6ae538d555 | |||
| 18f790d180 | |||
| 79f95f4243 | |||
| 437855979d | |||
| 867ccaf2b1 | |||
| 2f331de7b4 | |||
| abbb119fc9 | |||
| 3743fc1c29 | |||
| 82b5e0be02 | |||
| b5f0bc7234 | |||
| 9621bb0391 | |||
| 3829936d06 | |||
| 5e39dd3ed0 | |||
| a07c43a790 | |||
| 07b0faadd9 | |||
| 4f8973a043 | |||
| 721a239d4a | |||
| 6c5f07f201 | |||
| 3862ff9076 | |||
| 2248e310d9 | |||
| 38eae90640 | |||
| e0f97feb1c | |||
| 454eb82a1f | |||
| 3a9b2069af | |||
| f473ff8795 | |||
| f5499b1755 | |||
| bfa93ec76f | |||
| 8f87381c01 | |||
| 1cd4862803 | |||
| ac788320a2 | |||
| 985385bb30 | |||
| 5b227ab2a0 | |||
| 0d68a3fb4f | |||
| a2aa318e18 | |||
| 5ed5ebf054 | |||
| ea1d557ee5 | |||
| 63512462fd | |||
| e86ca6c361 | |||
| 07349bcd71 | |||
| b73769d4c7 | |||
| 9838977806 | |||
| 82f70ac453 | |||
| 264d545325 | |||
| 6de4d85783 | |||
| d10aec9e68 | |||
| fefe5660ef | |||
| 00c62804a8 | |||
| 5d978a62fd | |||
| 6208a3ec73 | |||
| 3da596eedf | |||
| 518ccd5686 | |||
| 9e1d19d56a | |||
| 936b8ab5fe | |||
| 91396e561f | |||
| ac04abe59b | |||
| a7ba4a155e | |||
| 2fade20656 | |||
| c5af3e51b0 | |||
| 685a052339 | |||
| 6e2222d357 | |||
| 559fece3e9 | |||
| 6868279909 | |||
| 49062d3ede | |||
| 41865d76fb | |||
| 2c41f3dbfa | |||
| 9b08a73210 | |||
| 00e0dbaa65 | |||
| 4705a6bc10 | |||
| 7853245fe4 | |||
| fa88efbf5e | |||
| 6f6252b616 | |||
| 3d5d2648ff | |||
| 04c4a8cd34 | |||
| 7a85a82094 | |||
| c86e2b3031 | |||
| a293ff0200 | |||
| d7a8d433de | |||
| 4c50ab6042 | |||
| 2d0d5c179b | |||
| 6510dce9d4 | |||
| 5670fc14e0 | |||
| 8b96efc02e | |||
| 66894e81e1 | |||
| fa0b3049ee | |||
| 1cd231fdb9 | |||
| 7947970817 | |||
| 76717eb720 | |||
| 7c5fe63d0b | |||
| cd0c9a39f3 | |||
| 91ca72b56d | |||
| 355209354e | |||
| 96ce2882a2 | |||
| 068ad19492 | |||
| 6fb4f8fc8b | |||
| baba390c7b | |||
| a3a14c8339 | |||
| e4bd0e975e | |||
| e7fce9120e | |||
| 76c924fbaa | |||
| bd07a1ba5c | |||
| f535f6d324 | |||
| 93b470f15c | |||
| 1cef87ee34 | |||
| 373fad6efe | |||
| 21dbd1e402 | |||
| 129e094b09 | |||
| c3c24eba4f | |||
| 145858a302 | |||
| c13e3ec220 | |||
| 6ce24bf1a1 | |||
| 6c61eb2d69 | |||
| 76bf84f8ea | |||
| a8ba8598f2 | |||
| 6e7bb41190 | |||
| 7387379aea | |||
| 50659787ee | |||
| 3da120ce33 | |||
| de9f4f8d0b | |||
| 20ecb6a779 | |||
| 40f2558a70 | |||
| f44c5ad757 | |||
| 8e7630cd9c | |||
| 1cf63bd471 | |||
| 07a263b794 | |||
| c2236b7b97 | |||
| 9e3db051c9 | |||
| 70d1bed396 | |||
| a6ea270d93 | |||
| a39a9b7a89 | |||
| 8c815cf47e | |||
| 2b7966dc55 | |||
| fe1a4f7d4f | |||
| 9b17468c43 | |||
| 6bedc1020b | |||
| fc56126820 | |||
| c6fa0e560a | |||
| 34de58e0dc | |||
| 056bcaff96 | |||
| 8985d514ec | |||
| f38df3753c | |||
| 7fd78aaf2e | |||
| 9bba6f4b9b | |||
| 5128c23413 | |||
| 3c82315782 | |||
| b565b8be77 | |||
| 2e2e76c92a | |||
| 1bc3fdd07c | |||
| c1e0b86554 | |||
| bf7591aaa0 | |||
| 6c5abf14bd | |||
| 8044ccbf27 | |||
| 95c6de5534 | |||
| 2c124e87dd | |||
| c655873b7d | |||
| ea6c466323 | |||
| 6e647d87fa | |||
| deaf26109b | |||
| 07e7068c22 | |||
| 971114e0fd | |||
| 03977c4806 | |||
| 842d5049b5 | |||
| 58751577c6 | |||
| debe0d811c | |||
| 8d09243473 | |||
| e4d1415627 | |||
| 5cd80daa3f | |||
| 2b4cf7d185 | |||
| 9040b1a3cb | |||
| 9a8f71dd81 | |||
| d05819e125 | |||
| 5dad26cb92 | |||
| 491ce00c17 | |||
| b7c7e8e84b | |||
| 095704d297 | |||
| 09d03161ce | |||
| 9c65ed92f1 | |||
| 3f35eca999 | |||
| aa4dc64a57 | |||
| d78fa85307 | |||
| 0ee056aafc | |||
| 68f0a64136 | |||
| f9f108ef33 | |||
| 573b8a0701 | |||
| 4ce6f5c3b0 | |||
| f2b78c06ef | |||
| d27594d4af | |||
| 7239ce97aa | |||
| 18b7581879 | |||
| 8535ff1d01 | |||
| 4f366bbdda | |||
| 86c554e3d3 | |||
| d97d1c427e | |||
| 600979d129 | |||
| 8be861809a | |||
| 8642a52a12 | |||
| d90ccbb7f0 | |||
| 9c1451ecd3 | |||
| 4a86244924 | |||
| c890421f55 | |||
| 6d1f42c9b6 | |||
| b1faade9b0 | |||
| 5bc229801b | |||
| f3e509ad55 | |||
| 9e8239f05b | |||
| 6051891280 | |||
| 70e4ea5502 | |||
| 216aaec7f2 | |||
| db160cdc85 | |||
| d1191c0693 | |||
| 9ac7df82ad | |||
| 389fb100bb | |||
| 7728dfa853 | |||
| 177bba5e73 | |||
| ee9f150483 | |||
| 85c739aed4 | |||
| 0e19ec7495 | |||
| 6e61450788 | |||
| 736190f93c | |||
| 02f95053b8 | |||
| 3f73452bc7 | |||
| 5247a9d143 | |||
| 912d89cdb3 | |||
| 1a82f93722 | |||
| 8a5ca2c4b4 | |||
| b1eeb5b193 | |||
| 97cb752cda | |||
| 5a991c9424 | |||
| ff505531c2 | |||
| 1b2a964001 | |||
| 1d5751a1e5 | |||
| b8c5a389d2 | |||
| 5d37df182a | |||
| d13a6f5f58 | |||
| aa35b28349 | |||
| 6104dcafd5 | |||
| 71ed99f080 | |||
| bb0f6fe0e3 | |||
| 73b5694aad | |||
| 63d7768653 | |||
| ed0886b040 | |||
| 9474c78de8 | |||
| 8388eca503 | |||
| cc7febcc6d | |||
| c5de31cce3 | |||
| 48c70604a9 | |||
| 650441b1f6 | |||
| 324cd7e98f | |||
| 7a92691bf5 | |||
| 506365b8ff | |||
| a5bbf3d832 | |||
| 101d92ca2d | |||
| 912711bfa0 | |||
| 677bf71a94 | |||
| b35d28c568 | |||
| 3495331005 | |||
| bcf46eceb6 | |||
| d04a573888 | |||
| 41144bb7f7 | |||
| 5798d8e57b | |||
| e2478e5cd4 | |||
| c4027898cb | |||
| 2704111497 | |||
| 8a9caad23d | |||
| 1fc0b32fc2 | |||
| 11a4040da7 | |||
| b5ec775833 | |||
| 329f90922c | |||
| 4eca4ac291 | |||
| f447294c0b | |||
| 46c7290e4f | |||
| c33bdf1f27 | |||
| a545c3c333 | |||
| aaa1ac0700 | |||
| 93adda2e4a | |||
| 5c96b32c64 | |||
| 2246e5bc2f | |||
| a5f1ad6da1 | |||
| d56af5872d | |||
| a4cc67f732 | |||
| 64d467e071 | |||
| 394e7f3d6d | |||
| 211267d500 | |||
| a695b8aed5 | |||
| 6fe9c4d4df | |||
| 9843f3a5fd | |||
| efc56c015f | |||
| 638b6e9cdc | |||
| fb759e3923 | |||
| c308b081a1 | |||
| 6c77313a82 | |||
| 7c42d29eb0 | |||
| 106955f6c3 | |||
| fcefae078e | |||
| e3754fb62f | |||
| db2d75c3f5 | |||
| 0a45f8f51c | |||
| adfc8769e6 | |||
| 6548154261 | |||
| 630212f66f | |||
| a4b5e08a73 | |||
| be4ea93d12 | |||
| 8f11edc17a | |||
| fc860d5061 | |||
| 03c574a97c | |||
| f407c3b2b3 | |||
| 39f9449dc7 | |||
| 171a82e233 | |||
| 459479a7b8 | |||
| 1bdf064437 | |||
| f1521ad752 | |||
| 92b9184706 | |||
| ff7c74ec8a | |||
| dbf310caf1 | |||
| 2afd257838 | |||
| 19edfdb2a4 | |||
| 6faa2ff177 | |||
| c8d2ea141b | |||
| 310a31b03e | |||
| 0a18306d40 | |||
| 0a5db8f97b | |||
| a4b24bf198 | |||
| 92d88d5a4c | |||
| 6db5ebf6f9 | |||
| a7f9628b48 | |||
| 9a2797303b | |||
| 51d608125d | |||
| 890b5f30a1 | |||
| 038fc87a40 | |||
| 954098eb7e | |||
| 51061fe4ba | |||
| bcd0c95ec1 | |||
| 7dd1efb29f | |||
| 6959e595f5 | |||
| ce8775b3e7 | |||
| 9ffca1bcab | |||
| 27390afe86 | |||
| 923fdf9199 | |||
| 908589277a | |||
| 8873fa9dd4 | |||
| a26d7747b6 | |||
| 1a99d0e4d0 | |||
| da0fe5e5a3 | |||
| b492641633 | |||
| 8f13fa3ae5 | |||
| aa46e1e282 | |||
| dbf1b1e0d4 | |||
| 9407f75522 | |||
| dbad0d261e | |||
| 5b555d35d3 | |||
| f6984438a0 | |||
| 335cf65663 | |||
| c19dbeda23 | |||
| 73567ffdce | |||
| ad6a745681 | |||
| 59b6665ff3 | |||
| 3cdc0e1142 | |||
| 270f3a75ff | |||
| 12d56cd201 | |||
| cb3cba5b05 | |||
| ffd85b4e94 | |||
| 23c40cbf2c | |||
| e99c519032 | |||
| c435597d7e | |||
| c71d00cd7e | |||
| 40f94d23d4 | |||
| f3bf5d86d2 | |||
| 16aac382d1 | |||
| ef3b3326fc | |||
| 79f303ddcf | |||
| 87f9e8c72e | |||
| aba5e849c1 | |||
| ef2fd52482 | |||
| 7b82208677 | |||
| 23333710f5 | |||
| 2e38f7b27b | |||
| c5ca61f249 | |||
| 6db75d4226 | |||
| 43ca9593d4 | |||
| a1cd80a0f6 | |||
| f49fa7b567 | |||
| d552d5dadb | |||
| de2784c281 | |||
| 7c05f2e86c | |||
| e9bfad3c09 | |||
| 9044c9328d | |||
| 48641166b9 | |||
| 6dfb618efe | |||
| 7e383ea961 | |||
| 5e14af7d38 | |||
| 312b2ff435 | |||
| 6b9adfa929 | |||
| a69019aea0 | |||
| d30ec335b8 | |||
| e820d2a4aa | |||
| 5aa490cbff | |||
| f1a8da2876 | |||
| 27f6560a00 | |||
| 7a181bd281 | |||
| 4a0cd87a38 | |||
| 861e5908a7 | |||
| ae5a5bd2c0 | |||
| 7d349ef518 | |||
| 395575dbe4 | |||
| 5dfa0e7446 | |||
| 9325d30e7c | |||
| d99beb0c8b | |||
| e9f0e98d2c | |||
| 6d6be4e6a4 | |||
| fbc9c6aed6 | |||
| 386dc1a14d | |||
| 8fc33f6aea | |||
| 6c8e39876f | |||
| bfca8c555e | |||
| c84087e96b | |||
| d4252a3dc8 | |||
| 6b12fe7c57 | |||
| 04da7cfd20 | |||
| d5ebe12983 | |||
| 5d1abaa713 | |||
| e9e0274ad8 | |||
| 966de9b9f4 | |||
| c46d4e9e43 | |||
| ee853f0189 | |||
| 1d0d6e78de | |||
| 8ae27ecc27 | |||
| 642ce36f59 | |||
| db5ffd6b29 | |||
| 9384cd0f27 | |||
| 0262b4aa76 | |||
| 158eb18de0 | |||
| 03ac073c02 | |||
| 96761efe4d | |||
| 8e02aad2bb | |||
| 75fb070825 | |||
| 8a0f32e980 | |||
| a68e37c67b | |||
| dea47dfafe | |||
| f5163ed0c2 | |||
| 694f3d71e2 | |||
| 5b1bdd84ee | |||
| 15eb40aedb | |||
| 49251271e9 | |||
| cc3e75dc63 | |||
| 4f17ecbdee | |||
| ec7b038569 | |||
| d4244d3807 | |||
| eeaf17c857 | |||
| 46487fa466 | |||
| 21a8395142 | |||
| f25233ac2b | |||
| 759e1f2e5a | |||
| 415810ecfe | |||
| fd3129f166 | |||
| 58e4e2398a | |||
| 392965bb3a | |||
| 61cd59b237 | |||
| 7d171b1e95 | |||
| d63061fade | |||
| 362261e879 | |||
| af8c00d075 | |||
| 68b440e494 | |||
| 0c328ef30e | |||
| ef47e85741 | |||
| 26af63549f | |||
| 70e3f895da | |||
| e6a69ccb0d | |||
| f80a27f5d7 | |||
| f3d68276fe | |||
| 0c191a3ef7 | |||
| 2872d0b0a2 | |||
| 97548df146 | |||
| ebf3ab3a41 | |||
| c97822a430 | |||
| 319bd783ff | |||
| e234eb22f6 | |||
| d45112f2ab | |||
| 6b3c6eba8d | |||
| f7719773f2 | |||
| 15c6e28354 | |||
| b5b643e04c | |||
| dc589f9b96 | |||
| 7a4ff7b9c0 | |||
| a92361bd00 | |||
| f7ce8af24d | |||
| 9ac96f24aa | |||
| eca5b6e4e6 | |||
| 2dd7c5210f | |||
| 3a854688e0 | |||
| 1594adf3ed | |||
| 23fcb38d69 | |||
| 7571949ad0 | |||
| d45c3520d4 | |||
| b7c04575fa | |||
| 588f5a3789 | |||
| b535a45898 | |||
| e3faa05435 | |||
| aebfc33037 | |||
| a5aa1b4db7 | |||
| 1b56c55300 | |||
| 29d9dcffb8 | |||
| b0f0a7afc4 | |||
| 30f8885aa9 | |||
| 94ed741dd5 | |||
| b6d5ac6a01 | |||
| 4664266b8d | |||
| c61fd65463 | |||
| 1e2598a3a3 | |||
| 5003a55aca | |||
| b5415844b8 | |||
| 19241995e8 | |||
| b53400ceca | |||
| 828dbaedfb | |||
| 52701f0056 | |||
| c802171f38 | |||
| 81c5c66e15 | |||
| 79515cdae7 | |||
| 99ce7c0736 | |||
| d9b1598fa2 | |||
| c630e5ef8e | |||
| fe5896c85f | |||
| 28cbb0a517 | |||
| 0597b43014 | |||
| a124d77670 | |||
| 1076b882fb | |||
| 4a47c5e129 | |||
| 6d052aeeac | |||
| 5380b62504 | |||
| 354505fde3 | |||
| 9b33c8a0e2 | |||
| 07fc6753f5 | |||
| 967178cb92 | |||
| fe44494936 | |||
| 793c9470c2 | |||
| cabcb08b98 | |||
| 78121dd0f2 | |||
| 95d40049f5 | |||
| f003c3602c | |||
| 862fdf27e4 | |||
| 6abd778fd9 | |||
| 639ef53c88 | |||
| 7225ec29fe | |||
| cf1069e0e1 | |||
| 99ce88228c | |||
| 23612d7599 | |||
| 73565d9be1 | |||
| a623e4034c | |||
| b0ab408fda | |||
| cf871196f2 | |||
| b962d2a9d3 | |||
| 36d6b6a254 | |||
| 29bb86ea13 | |||
| fa171e4553 | |||
| 0b63eb9430 | |||
| d7ddbfec35 | |||
| d260a9dc88 | |||
| 587d9b6d6c | |||
| 4babcbf96e | |||
| 20216df8cf | |||
| be2ed0e8da | |||
| 863679b386 | |||
| c040cfefcd | |||
| bf1a90020c | |||
| 3d326158ca | |||
| a388657dbb | |||
| a861d306c9 | |||
| 802a4386c3 | |||
| 899265c5c5 | |||
| 0752ef06b1 | |||
| 404fc40127 | |||
| 647d3e8792 | |||
| d980ffe783 | |||
| 6861453166 | |||
| 5f263ad851 | |||
| e501f0f612 | |||
| 7aeea96e23 | |||
| afc2363163 |
@@ -8,10 +8,23 @@ root = true
|
||||
# Use 4 spaces as indentation
|
||||
[*]
|
||||
insert_final_newline = true
|
||||
end_of_line = lf
|
||||
end_of_line = crlf
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
|
||||
# Trim trailing whitespace, limited support.
|
||||
# https://github.com/editorconfig/editorconfig/wiki/Property-research:-Trim-trailing-spaces
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.{cs,vb}]
|
||||
dotnet_style_predefined_type_for_locals_parameters_members = true:error
|
||||
|
||||
dotnet_naming_rule.private_members_with_underscore.symbols = private_fields
|
||||
dotnet_naming_rule.private_members_with_underscore.style = prefix_underscore
|
||||
dotnet_naming_rule.private_members_with_underscore.severity = suggestion
|
||||
|
||||
dotnet_naming_symbols.private_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_fields.applicable_accessibilities = private
|
||||
|
||||
dotnet_naming_style.prefix_underscore.capitalization = camel_case
|
||||
dotnet_naming_style.prefix_underscore.required_prefix = _
|
||||
@@ -1,3 +1,8 @@
|
||||
#
|
||||
# Umbraco Cms Git Ignore
|
||||
#
|
||||
|
||||
# common files
|
||||
*.obj
|
||||
*.pdb
|
||||
*.user
|
||||
@@ -9,21 +14,29 @@
|
||||
*.vs10x
|
||||
*.ndproj
|
||||
|
||||
# common directories
|
||||
.DS_Store
|
||||
._.DS_Store
|
||||
.vs/
|
||||
/local/
|
||||
|
||||
[Bb]in
|
||||
# build directories
|
||||
[Bb]in/
|
||||
[Db]ebug*/
|
||||
obj/
|
||||
[Rr]elease*/
|
||||
obj/
|
||||
|
||||
# tools
|
||||
_ReSharper*/
|
||||
|
||||
_NCrunch_*/
|
||||
*.ncrunchsolution
|
||||
*.ncrunchsolution.user
|
||||
*.ncrunchproject
|
||||
*.crunchsolution.cache
|
||||
tools/NDepend/
|
||||
|
||||
|
||||
|
||||
|
||||
[Tt]est[Rr]esult*
|
||||
[Bb]uild[Ll]og.*
|
||||
@@ -57,7 +70,7 @@ umbraco/presentation/packages/uComponents/MultiNodePicker/CustomTreeService.asmx
|
||||
src/Umbraco.Tests/config/applications.config
|
||||
src/Umbraco.Tests/config/trees.config
|
||||
src/Umbraco.Web.UI/web.config
|
||||
src/Umbraco.Web.UI/Config/ClientDependency.config
|
||||
src/Umbraco.Web.UI/[Cc]onfig/ClientDependency.config
|
||||
src/Umbraco.Tests/config/404handlers.config
|
||||
src/Umbraco.Web.UI/[Vv]iews/*.cshtml
|
||||
src/Umbraco.Web.UI/[Vv]iews/*.vbhtml
|
||||
@@ -74,18 +87,15 @@ lib-bower
|
||||
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ib/*
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/umbraco.*
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/*.loader.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/init.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.dev.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/loader.dev.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/main.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/app.js
|
||||
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.panel.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.palettes.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.loader.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.front.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/tuning.config.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/canvasdesigner.*.js
|
||||
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
|
||||
@@ -97,43 +107,34 @@ src/Umbraco.Web.UI.Client/[Bb]uild/[Bb]elle/
|
||||
src/Umbraco.Web.UI/[Uu]ser[Cc]ontrols/
|
||||
|
||||
src/Umbraco.Web.UI.Client/src/[Ll]ess/*.css
|
||||
tools/NDepend/
|
||||
|
||||
src/Umbraco.Web.UI/App_Plugins/*
|
||||
src/*.psess
|
||||
src/*.vspx
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Jj]s/routes.js.*
|
||||
|
||||
NDependOut/*
|
||||
QueryResult.htm
|
||||
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Aa]ssets/*
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Ll]ib/*
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.html
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/[Vv]iews/**/*.js
|
||||
|
||||
src/Umbraco.Web.UI/[Cc]onfig/appSettings.config
|
||||
src/Umbraco.Web.UI/[Cc]onfig/connectionStrings.config
|
||||
src/Umbraco.Web.UI/umbraco/plugins/*
|
||||
src/Umbraco.Web.UI/umbraco/js/init.js
|
||||
src/Umbraco.Web.UI/[Uu]mbraco/plugins/*
|
||||
build/ApiDocs/*
|
||||
build/ApiDocs/Output/*
|
||||
src/Umbraco.Web.UI.Client/bower_components/*
|
||||
/src/Umbraco.Web.UI/Umbraco/preview
|
||||
/src/Umbraco.Web.UI/Umbraco/preview.old
|
||||
/src/Umbraco.Web.UI/[Uu]mbraco/preview
|
||||
/src/Umbraco.Web.UI/[Uu]mbraco/preview.old
|
||||
|
||||
# ignore rule for clearing out Belle (avoid rebuilding all the time)
|
||||
preserve.belle
|
||||
|
||||
#Ignore Rule for output of generated documentation files from Grunt docserve
|
||||
src/Umbraco.Web.UI.Client/docs/api
|
||||
src/*.boltdata/
|
||||
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.loader.js
|
||||
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.palettes.js
|
||||
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.panel.js
|
||||
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.config.js
|
||||
/src/Umbraco.Web.UI/Umbraco/Js/canvasdesigner.front.js
|
||||
src/umbraco.sln.ide/*
|
||||
src/.vs/
|
||||
src/Umbraco.Web.UI/umbraco/js/install.loader.js
|
||||
src/Umbraco.Web.UI/js/*
|
||||
src/Umbraco.Tests/media
|
||||
|
||||
src/Umbraco.Web.UI/[Jj]s/*
|
||||
src/Umbraco.Tests/[Mm]edia
|
||||
tools/docfx/*
|
||||
apidocs/_site/*
|
||||
src/*/project.lock.json
|
||||
@@ -143,7 +144,6 @@ apidocs/api/*
|
||||
build/docs.zip
|
||||
build/ui-docs.zip
|
||||
build/csharp-docs.zip
|
||||
.vs/
|
||||
src/packages/
|
||||
src/PrecompiledWeb/*
|
||||
|
||||
@@ -152,3 +152,7 @@ build.out/
|
||||
build.tmp/
|
||||
build/hooks/
|
||||
build/temp/
|
||||
|
||||
|
||||
|
||||
# eof
|
||||
@@ -1,80 +0,0 @@
|
||||
# Code of Conduct
|
||||
|
||||
## 1. Purpose
|
||||
|
||||
A primary goal of Umbraco CMS is to be inclusive to the largest number of contributors, with the most varied and diverse backgrounds possible. As such, we are committed to providing a friendly, safe and welcoming environment for all, regardless of gender, sexual orientation, ability, ethnicity, socioeconomic status, and religion (or lack thereof).
|
||||
|
||||
This code of conduct outlines our expectations for all those who participate in our community, as well as the consequences for unacceptable behavior.
|
||||
|
||||
We invite all those who participate in Umbraco CMS to help us create safe and positive experiences for everyone.
|
||||
|
||||
## 2. Open Source Citizenship
|
||||
|
||||
A supplemental goal of this Code of Conduct is to increase open source citizenship by encouraging participants to recognize and strengthen the relationships between our actions and their effects on our community.
|
||||
|
||||
Communities mirror the societies in which they exist and positive action is essential to counteract the many forms of inequality and abuses of power that exist in society.
|
||||
|
||||
If you see someone who is making an extra effort to ensure our community is welcoming, friendly, and encourages all participants to contribute to the fullest extent, we want to know.
|
||||
|
||||
## 3. Expected Behavior
|
||||
|
||||
The following behaviors are expected and requested of all community members:
|
||||
|
||||
* Participate in an authentic and active way. In doing so, you contribute to the health and longevity of this community.
|
||||
* Exercise consideration and respect in your speech and actions.
|
||||
* Attempt collaboration before conflict.
|
||||
* Refrain from demeaning, discriminatory, or harassing behavior and speech.
|
||||
* Be mindful of your surroundings and of your fellow participants. Alert community leaders if you notice a dangerous situation, someone in distress, or violations of this Code of Conduct, even if they seem inconsequential.
|
||||
* Remember that community event venues may be shared with members of the public; please be respectful to all patrons of these locations.
|
||||
|
||||
## 4. Unacceptable Behavior
|
||||
|
||||
The following behaviors are considered harassment and are unacceptable within our community:
|
||||
|
||||
* Violence, threats of violence or violent language directed against another person.
|
||||
* Sexist, racist, homophobic, transphobic, ableist or otherwise discriminatory jokes and language.
|
||||
* Posting or displaying sexually explicit or violent material.
|
||||
* Posting or threatening to post other people’s personally identifying information ("doxing").
|
||||
* Personal insults, particularly those related to gender, sexual orientation, race, religion, or disability.
|
||||
* Inappropriate photography or recording.
|
||||
* Inappropriate physical contact. You should have someone’s consent before touching them.
|
||||
* Unwelcome sexual attention. This includes, sexualized comments or jokes; inappropriate touching, groping, and unwelcomed sexual advances.
|
||||
* Deliberate intimidation, stalking or following (online or in person).
|
||||
* Advocating for, or encouraging, any of the above behavior.
|
||||
* Sustained disruption of community events, including talks and presentations.
|
||||
|
||||
## 5. Consequences of Unacceptable Behavior
|
||||
|
||||
Unacceptable behavior from any community member, including sponsors and those with decision-making authority, will not be tolerated.
|
||||
|
||||
Anyone asked to stop unacceptable behavior is expected to comply immediately.
|
||||
|
||||
If a community member engages in unacceptable behavior, the community organizers may take any action they deem appropriate, up to and including a temporary ban or permanent expulsion from the community without warning (and without refund in the case of a paid event).
|
||||
|
||||
## 6. Reporting Guidelines
|
||||
|
||||
If you are subject to or witness unacceptable behavior, or have any other concerns, please notify a community organizer as soon as possible. Please contact Sebastiaan Janssen - [sj@umbraco.dk](mailto:sj@umbraco.dk).
|
||||
|
||||
Additionally, community organizers are available to help community members engage with local law enforcement or to otherwise help those experiencing unacceptable behavior feel safe. In the context of in-person events, organizers will also provide escorts as desired by the person experiencing distress.
|
||||
|
||||
## 7. Addressing Grievances
|
||||
|
||||
If you feel you have been falsely or unfairly accused of violating this Code of Conduct, you should notify Umbraco with a concise description of your grievance. Your grievance will be handled in accordance with our existing governing policies.
|
||||
|
||||
## 8. Scope
|
||||
|
||||
We expect all community participants (contributors, paid or otherwise; sponsors; and other guests) to abide by this Code of Conduct in all community venues–online and in-person–as well as in all one-on-one communications pertaining to community business.
|
||||
|
||||
This code of conduct and its related procedures also applies to unacceptable behavior occurring outside the scope of community activities when such behavior has the potential to adversely affect the safety and well-being of community members.
|
||||
|
||||
## 9. Contact info
|
||||
|
||||
Sebastiaan Janssen - [sj@umbraco.dk](mailto:sj@umbraco.dk)
|
||||
|
||||
## 10. License and attribution
|
||||
|
||||
This Code of Conduct is distributed under a [Creative Commons Attribution-ShareAlike license](http://creativecommons.org/licenses/by-sa/3.0/).
|
||||
|
||||
Portions of text derived from the [Django Code of Conduct](https://www.djangoproject.com/conduct/) and the [Geek Feminism Anti-Harassment Policy](http://geekfeminism.wikia.com/wiki/Conference_anti-harassment/Policy).
|
||||
|
||||
Retrieved on November 22, 2016 from [http://citizencodeofconduct.org/](http://citizencodeofconduct.org/)
|
||||
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<!--
|
||||
this is Umbraco's NuGet configuration,
|
||||
content of this file is merged with the system-wide configuration,
|
||||
at %APPDATA%\NuGet\NuGet.config
|
||||
-->
|
||||
<packageSources>
|
||||
<add key="UmbracoCoreMyGet" value="https://www.myget.org/F/umbracocore/api/v3/index.json" />
|
||||
<add key="ExamineAppVeyor" value="https://ci.appveyor.com/nuget/examine-f73l6qv0oqfh/" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
@@ -1,5 +0,0 @@
|
||||
|
||||
- name: Umbraco.Core Documentation
|
||||
href: https://our.umbraco.org/apidocs/csharp/api/Umbraco.Core.html
|
||||
- name: Umbraco.Web Documentation
|
||||
href: https://our.umbraco.org/apidocs/csharp/api/Umbraco.Web.html
|
||||
@@ -1,63 +0,0 @@
|
||||
@ECHO OFF
|
||||
SETLOCAL
|
||||
REM SETLOCAL is on, so changes to the path not persist to the actual user's path
|
||||
|
||||
git.exe --version
|
||||
IF %ERRORLEVEL%==9009 GOTO :trydefaultpath
|
||||
REM OK, DONE
|
||||
GOTO :EOF
|
||||
|
||||
:trydefaultpath
|
||||
PATH=C:\Program Files (x86)\Git\cmd;C:\Program Files\Git\cmd;%PATH%
|
||||
git.exe --version
|
||||
IF %ERRORLEVEL%==9009 GOTO :showerror
|
||||
REM OK, DONE
|
||||
GOTO :EOF
|
||||
|
||||
:showerror
|
||||
ECHO Git is not in your path and could not be found in C:\Program Files (x86)\Git\cmd nor in C:\Program Files\Git\cmd
|
||||
SET /p install=" Do you want to install Git through Chocolatey [y/n]? " %=%
|
||||
IF %install%==y (
|
||||
:: Create a temporary batch file to execute either after elevating to admin or as-is when the user is already admin
|
||||
ECHO @ECHO OFF > "%temp%\ChocoInstallGit.cmd"
|
||||
ECHO SETLOCAL >> "%temp%\ChocoInstallGit.cmd"
|
||||
ECHO ECHO Installing Chocolatey first >> "%temp%\ChocoInstallGit.cmd"
|
||||
ECHO @powershell -NoProfile -ExecutionPolicy Bypass -Command "iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))" >> "%temp%\ChocoInstallGit.cmd"
|
||||
ECHO SET PATH=%%PATH%%;%%ALLUSERSPROFILE%%\chocolatey\bin >> "%temp%\ChocoInstallGit.cmd"
|
||||
ECHO choco install git -y >> "%temp%\ChocoInstallGit.cmd"
|
||||
|
||||
GOTO :installgit
|
||||
) ELSE (
|
||||
GOTO :cantcontinue
|
||||
)
|
||||
|
||||
:cantcontinue
|
||||
ECHO Can't complete the build without Git being in the path. Please add it to be able to continue.
|
||||
GOTO :EOF
|
||||
|
||||
:installgit
|
||||
pushd %~dp0
|
||||
:: Running prompt elevated
|
||||
|
||||
:: --> Check for permissions
|
||||
>nul 2>&1 "%SYSTEMROOT%\system32\cacls.exe" "%SYSTEMROOT%\system32\config\system"
|
||||
|
||||
:: --> If error flag set, we do not have admin.
|
||||
IF '%errorlevel%' NEQ '0' (
|
||||
GOTO UACPrompt
|
||||
) ELSE ( GOTO gotAdmin )
|
||||
|
||||
:UACPrompt
|
||||
ECHO You're not currently running this with admin privileges, we'll now try to execute the install of Git through Chocolatey after elevating to admin privileges
|
||||
ECHO Set UAC = CreateObject^("Shell.Application"^) > "%temp%\getadmin.vbs"
|
||||
ECHO UAC.ShellExecute "%temp%\ChocoInstallGit.cmd", "", "", "runas", 1 >> "%temp%\getadmin.vbs"
|
||||
|
||||
"%temp%\getadmin.vbs"
|
||||
EXIT /B
|
||||
|
||||
:gotAdmin
|
||||
IF EXIST "%temp%\getadmin.vbs" ( DEL "%temp%\getadmin.vbs" )
|
||||
pushd "%CD%"
|
||||
CD /D "%~dp0"
|
||||
|
||||
CALL "%temp%\ChocoInstallGit.cmd"
|
||||
@@ -15,51 +15,66 @@
|
||||
<language>en-US</language>
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.4,6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.4,6.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.0, 5.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0, 5.0.0)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[4.0.0, 5.0.0)" />
|
||||
<dependency id="MiniProfiler" version="[3.2.0.157, 3.9.999)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.7.2, 2.0.0)" />
|
||||
<dependency id="Lucene.Net" version="[3.0.3, 4.0.0.0)" />
|
||||
<dependency id="MySql.Data" version="[6.10.6, 7.0.0)" />
|
||||
<dependency id="ClientDependency" version="[1.9.6, 2.0.0)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0.0, 2.0.0)" />
|
||||
<dependency id="AutoMapper" version="[6.2.2, 7.0.0)" />
|
||||
<dependency id="LightInject" version="[5.1.2, 6.0.0)" />
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0, 3.0.0)" />
|
||||
<dependency id="LightInject.Web" version="[2.0.0, 3.0.0)" />
|
||||
<dependency id="LightInject.WebApi" version="[2.0.0, 3.0.0)" />
|
||||
<dependency id="Newtonsoft.Json" version="[11.0.2, 12.0.0)" />
|
||||
<dependency id="Examine" version="[1.0.0-beta025, 1.666.666)" />
|
||||
<dependency id="ImageProcessor" version="[2.6.0, 3.0.0)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.8.7, 5.0.0)" />
|
||||
<dependency id="semver" version="[2.0.4, 3.0.0)" />
|
||||
<dependency id="Markdown" version="[2.2.1, 3.0.0)" />
|
||||
<dependency id="log4net" version="[2.0.8, 3.0.0)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.8.0, 5.0.0)" />
|
||||
<dependency id="System.ValueTuple" version="[4.4.0, 5.0.0)" />
|
||||
<dependency id="NPoco" version="3.9.0" />
|
||||
<dependency id="NuGet.Core" version="2.14.0" />
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="AutoMapper" version="[7.0.1,7.999999)" />
|
||||
<dependency id="ClientDependency" version="[1.9.6,1.999999)" />
|
||||
<dependency id="ClientDependency-Mvc5" version="[1.8.0,1.999999)" />
|
||||
<dependency id="CSharpTest.Net.Collections" version="[14.906.1403.1082,14.999999)" />
|
||||
<dependency id="Examine" version="[1.0.0-beta025,1.999999)" />
|
||||
<dependency id="HtmlAgilityPack" version="[1.7.2,1.999999)" />
|
||||
<dependency id="ImageProcessor" version="[2.6.1.19,2.999999)" />
|
||||
<dependency id="ImageProcessor.Web" version="[4.9.2.19,4.999999)" />
|
||||
<dependency id="ImageProcessor.Web.Config" version="[2.4.1.19,2.999999)" />
|
||||
<dependency id="LightInject" version="[5.1.2,5.999999)" />
|
||||
<dependency id="LightInject.Annotation" version="[1.1.0,1.999999)" />
|
||||
<dependency id="LightInject.Mvc" version="[2.0.0,2.999999)" />
|
||||
<dependency id="LightInject.WebApi" version="[2.0.0,2.999999)" />
|
||||
<dependency id="log4net" version="[2.0.8,2.999999)" />
|
||||
<dependency id="Log4Net.Async" version="[2.0.4,2.999999)" />
|
||||
<dependency id="Lucene.Net.Contrib" version="[3.0.3,3.999999)" />
|
||||
<dependency id="Markdown" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Identity.Owin" version="[2.2.1,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.Mvc" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3,2.999999)" />
|
||||
<dependency id="Microsoft.AspNet.WebApi" version="[5.2.6,5.999999)" />
|
||||
<dependency id="Microsoft.CodeAnalysis.CSharp" version="[2.8.0,2.999999)" />
|
||||
<dependency id="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" version="[1.0.8,1.999999)" />
|
||||
<dependency id="Microsoft.Net.Compilers" version="[2.8.0,2.999999)" />
|
||||
<dependency id="Microsoft.Owin.Host.SystemWeb" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.Cookies" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Owin.Security.OAuth" version="[4.0.0,4.999999)" />
|
||||
<dependency id="Microsoft.Web.Xdt" version="[2.1.2,2.999999)" />
|
||||
<dependency id="MiniProfiler" version="[3.2.0.157,3.999999)" />
|
||||
<dependency id="MySql.Data" version="[6.10.7,6.999999)" />
|
||||
<dependency id="Newtonsoft.Json" version="[11.0.2,11.999999)" />
|
||||
<dependency id="NPoco" version="[3.9.3,3.999999)" />
|
||||
<dependency id="Semver" version="[2.0.4,2.999999)" />
|
||||
<dependency id="System.Reflection.Primitives" version="[4.3.0,4.999999)" />
|
||||
<dependency id="System.Runtime.Handles" version="[4.3.0,4.999999)" />
|
||||
<dependency id="System.Security.Cryptography.X509Certificates" version="[4.3.2,4.999999)" />
|
||||
<dependency id="System.Threading.Tasks.Dataflow" version="[4.8.0,4.999999)" />
|
||||
<dependency id="Umbraco.SqlServerCE" version="[4.0.0.1,4.999999)" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
<file src="$BuildTmp$\WebApp\bin\System.Data.SqlServerCe.dll" target="lib\System.Data.SqlServerCe.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\System.Data.SqlServerCe.Entity.dll" target="lib\System.Data.SqlServerCe.Entity.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.dll" target="lib\Umbraco.Core.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.dll" target="lib\net472\Umbraco.Core.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.dll" target="lib\net472\Umbraco.Web.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.dll" target="lib\net472\Umbraco.Web.UI.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\net472\Umbraco.Examine.dll" />
|
||||
|
||||
<!-- docs -->
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Core.xml" target="lib\Umbraco.Core.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.dll" target="lib\Umbraco.Web.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.xml" target="lib\Umbraco.Web.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.dll" target="lib\Umbraco.Web.UI.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Web.UI.xml" target="lib\Umbraco.Web.UI.xml" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.dll" target="lib\Umbraco.Examine.dll" />
|
||||
<file src="$BuildTmp$\WebApp\bin\Umbraco.Examine.xml" target="lib\Umbraco.Examine.xml" />
|
||||
|
||||
<file src="tools\install.core.ps1" target="tools\install.ps1" />
|
||||
|
||||
<!-- produce symbols package -->
|
||||
<!-- symbols -->
|
||||
<file src="$BuildTmp$\bin\Umbraco.Core.pdb" target="lib" />
|
||||
<file src="$BuildTmp$\..\src\Umbraco.Core\**\*.cs" exclude="$BuildTmp$\..\src\**\TemporaryGeneratedFile*.cs" target="src\Umbraco.Core" />
|
||||
<file src="$BuildTmp$\bin\Umbraco.Web.pdb" target="lib" />
|
||||
|
||||
@@ -16,8 +16,13 @@
|
||||
<tags>umbraco</tags>
|
||||
<dependencies>
|
||||
<dependency id="UmbracoCms.Core" version="[$version$]" />
|
||||
<dependency id="Umbraco.ModelsBuilder" version="[8.0.0-alpha.17, 9.0.0)" />
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3, 3.0.0)" />
|
||||
<!--
|
||||
note: dependencies are specified as [x.y.z,x.999999) eg [2.1.0,2.999999) and NOT [2.1.0,3.0.0) because
|
||||
the latter would pick anything below 3.0.0 and that includes prereleases such as 3.0.0-alpha, and we do
|
||||
not want this to happen as the alpha of the next major is, really, the next major already.
|
||||
-->
|
||||
<dependency id="Microsoft.AspNet.SignalR.Core" version="[2.2.3, 2.999999)" />
|
||||
<dependency id="Umbraco.ModelsBuilder.Ui" version="[8.0.0-alpha.20]" />
|
||||
</dependencies>
|
||||
</metadata>
|
||||
<files>
|
||||
@@ -27,14 +32,17 @@
|
||||
<file src="$BuildTmp$\WebApp\Global.asax" target="Content\Global.asax" />
|
||||
<file src="$BuildTmp$\WebApp\Web.config" target="UmbracoFiles\Web.config" />
|
||||
<file src="$BuildTmp$\WebApp\App_Browsers\**" target="UmbracoFiles\App_Browsers" />
|
||||
<file src="$BuildTmp$\WebApp\bin\amd64\**" target="UmbracoFiles\bin\amd64" />
|
||||
<file src="$BuildTmp$\WebApp\bin\x86\**" target="UmbracoFiles\bin\x86" />
|
||||
<file src="$BuildTmp$\WebApp\config\splashes\**" target="UmbracoFiles\Config\splashes" />
|
||||
<file src="$BuildTmp$\WebApp\config\BackOfficeTours\**" target="Content\Config\BackOfficeTours" />
|
||||
<file src="$BuildTmp$\WebApp\umbraco\**" target="UmbracoFiles\umbraco" />
|
||||
<file src="$BuildTmp$\WebApp\umbraco_client\**" target="UmbracoFiles\umbraco_client" />
|
||||
<file src="$BuildTmp$\WebApp\Media\Web.config" target="Content\Media\Web.config" />
|
||||
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.htm" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.htm" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.controller.js" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.controller.js" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\modelsbuilder.resource.js" target="Content\App_Plugins\ModelsBuilder\modelsbuilder.resource.js" />
|
||||
<file src="$BuildTmp$\WebApp\App_Plugins\ModelsBuilder\package.manifest" target="Content\App_Plugins\ModelsBuilder\package.manifest" />
|
||||
|
||||
<file src="tools\install.ps1" target="tools\install.ps1" />
|
||||
<file src="tools\Readme.txt" target="tools\Readme.txt" />
|
||||
<file src="tools\ReadmeUpgrade.txt" target="tools\ReadmeUpgrade.txt" />
|
||||
|
||||
@@ -1,26 +1,26 @@
|
||||
|
||||
_ _ __ __ ____ _____ _____ ____
|
||||
| | | | \/ | _ \| __ \ /\ / ____/ __ \
|
||||
| | | | \ / | |_) | |__) | / \ | | | | | |
|
||||
| | | | |\/| | _ <| _ / / /\ \| | | | | |
|
||||
| |__| | | | | |_) | | \ \ / ____ | |___| |__| |
|
||||
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
|
||||
When upgrading your website using NuGet you should answer "No" to the questions to overwrite the Web.config
|
||||
file (and config files in the config folder).
|
||||
|
||||
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
|
||||
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
|
||||
Publish this won't affect you.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, umbraco_client, config\splashes and global.asax.
|
||||
|
||||
Please read the release notes on our.umbraco.org:
|
||||
http://our.umbraco.org/contribute/releases
|
||||
|
||||
|
||||
_ _ __ __ ____ _____ _____ ____
|
||||
| | | | \/ | _ \| __ \ /\ / ____/ __ \
|
||||
| | | | \ / | |_) | |__) | / \ | | | | | |
|
||||
| | | | |\/| | _ <| _ / / /\ \| | | | | |
|
||||
| |__| | | | | |_) | | \ \ / ____ | |___| |__| |
|
||||
\____/|_| |_|____/|_| \_/_/ \_\_____\____/
|
||||
|
||||
----------------------------------------------------
|
||||
|
||||
Don't forget to build!
|
||||
|
||||
|
||||
When upgrading your website using NuGet you should answer "No" to the questions to overwrite the Web.config
|
||||
file (and config files in the config folder).
|
||||
|
||||
This NuGet package includes build targets that extend the creation of a deploy package, which is generated by
|
||||
Publishing from Visual Studio. The targets will only work once Publishing is configured, so if you don't use
|
||||
Publish this won't affect you.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, umbraco_client, config\splashes and global.asax.
|
||||
|
||||
Please read the release notes on our.umbraco.com:
|
||||
http://our.umbraco.com/contribute/releases
|
||||
|
||||
- Umbraco
|
||||
@@ -11,7 +11,7 @@
|
||||
*** IMPORTANT NOTICE FOR UPGRADES FROM VERSIONS BELOW 7.7.0 ***
|
||||
|
||||
Be sure to read the version specific upgrade information before proceeding:
|
||||
https://our.umbraco.org/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-7-0
|
||||
https://our.umbraco.com/documentation/Getting-Started/Setup/Upgrading/version-specific#version-7-7-0
|
||||
|
||||
Depending on the version you are upgrading from, you may need to make some changes to your web.config
|
||||
and you will need to be aware of the breaking changes listed there to see if these affect your installation.
|
||||
@@ -33,7 +33,7 @@ Publish this won't affect you.
|
||||
The following items will now be automatically included when creating a deploy package or publishing to the file
|
||||
system: umbraco, umbraco_client, config\splashes and global.asax.
|
||||
|
||||
Please read the release notes on our.umbraco.org:
|
||||
http://our.umbraco.org/contribute/releases
|
||||
Please read the release notes on our.umbraco.com:
|
||||
http://our.umbraco.com/contribute/releases
|
||||
|
||||
- Umbraco
|
||||
@@ -1,42 +1,32 @@
|
||||
<?xml version="1.0"?>
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<configSections>
|
||||
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(name)"
|
||||
xdt:Transform="SetAttributes(type)">
|
||||
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(name)"
|
||||
xdt:Transform="SetAttributes(type)" />
|
||||
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(name)"
|
||||
xdt:Transform="SetAttributes(type)" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
|
||||
<system.web.webPages.razor>
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(factoryType)"
|
||||
xdt:Transform="SetAttributes(factoryType)" />
|
||||
<pages pageBaseType="System.Web.Mvc.WebViewPage">
|
||||
<namespaces>
|
||||
<add namespace="Umbraco.Web.PublishedContentModels" xdt:Transform="InsertIfMissing" />
|
||||
</namespaces>
|
||||
</pages>
|
||||
</system.web.webPages.razor>
|
||||
|
||||
<system.web>
|
||||
<pages
|
||||
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(pageParserFilterType,pageBaseType,userControlBaseType)"
|
||||
xdt:Transform="SetAttributes(pageParserFilterType,pageBaseType,userControlBaseType)">
|
||||
<controls>
|
||||
<add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc"
|
||||
xdt:Locator="Match(namespace)"
|
||||
xdt:Transform="SetAttributes(assembly)" />
|
||||
</controls>
|
||||
</pages>
|
||||
</system.web>
|
||||
|
||||
</configuration>
|
||||
<configSections>
|
||||
<sectionGroup name="system.web.webPages.razor" type="System.Web.WebPages.Razor.Configuration.RazorWebSectionGroup, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(name)" xdt:Transform="SetAttributes(type)">
|
||||
<section name="host" type="System.Web.WebPages.Razor.Configuration.HostSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(name)" xdt:Transform="SetAttributes(type)" />
|
||||
<section name="pages" type="System.Web.WebPages.Razor.Configuration.RazorPagesSection, System.Web.WebPages.Razor, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(name)" xdt:Transform="SetAttributes(type)" />
|
||||
</sectionGroup>
|
||||
</configSections>
|
||||
|
||||
<system.web.webPages.razor>
|
||||
<host factoryType="System.Web.Mvc.MvcWebRazorHostFactory, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(factoryType)" xdt:Transform="SetAttributes(factoryType)" />
|
||||
<pages pageBaseType="System.Web.Mvc.WebViewPage">
|
||||
<namespaces>
|
||||
<add namespace="Umbraco.Web.PublishedContentModels" xdt:Transform="InsertIfMissing" />
|
||||
</namespaces>
|
||||
</pages>
|
||||
</system.web.webPages.razor>
|
||||
|
||||
<system.web>
|
||||
<pages
|
||||
pageParserFilterType="System.Web.Mvc.ViewTypeParserFilter, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
pageBaseType="System.Web.Mvc.ViewPage, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
userControlBaseType="System.Web.Mvc.ViewUserControl, System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35"
|
||||
xdt:Locator="Match(pageParserFilterType,pageBaseType,userControlBaseType)"
|
||||
xdt:Transform="SetAttributes(pageParserFilterType,pageBaseType,userControlBaseType)">
|
||||
<controls>
|
||||
<add assembly="System.Web.Mvc, Version=5.2.3.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" namespace="System.Web.Mvc" xdt:Locator="Match(namespace)" xdt:Transform="SetAttributes(assembly)" />
|
||||
</controls>
|
||||
</pages>
|
||||
</system.web>
|
||||
|
||||
</configuration>
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
<configuration xmlns:xdt="http://schemas.microsoft.com/XML-Document-Transform">
|
||||
<configSections xdt:Transform="InsertIfMissing" />
|
||||
<configSections>
|
||||
<section name="BaseRestExtensions" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<section name="FileSystemProviders" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<section name="ExamineLuceneIndexSets" type="Examine.LuceneEngine.Config.IndexSets, Examine" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="SetAttributes(type,requirePermission)" />
|
||||
<section name="ExamineLuceneIndexSets" type="Umbraco.Examine.Config.IndexSets, Umbraco.Examine" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="SetAttributes(type,requirePermission)" />
|
||||
|
||||
<sectionGroup name="applicationSettings" xdt:Locator="Match(name)">
|
||||
<section name="umbraco.presentation.Properties.Settings" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
@@ -12,7 +11,6 @@
|
||||
<sectionGroup name="system.web.webPages.razor" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<sectionGroup name="umbracoConfiguration" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing">
|
||||
<section name="settings" type="Umbraco.Core.Configuration.UmbracoSettings.UmbracoSettingsSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="BaseRestExtensions" type="Umbraco.Core.Configuration.BaseRest.BaseRestSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="FileSystemProviders" type="Umbraco.Core.Configuration.FileSystemProvidersSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="dashBoard" type="Umbraco.Core.Configuration.Dashboard.DashboardSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
<section name="HealthChecks" type="Umbraco.Core.Configuration.HealthChecks.HealthChecksSection, Umbraco.Core" requirePermission="false" xdt:Locator="Match(name)" xdt:Transform="InsertIfMissing" />
|
||||
@@ -29,14 +27,12 @@
|
||||
|
||||
<umbracoConfiguration xdt:Transform="InsertIfMissing">
|
||||
<settings configSource="config\umbracoSettings.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
<BaseRestExtensions configSource="config\BaseRestExtensions.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
<FileSystemProviders configSource="config\FileSystemProviders.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
<dashBoard configSource="config\Dashboard.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
<HealthChecks configSource="config\HealthChecks.config" xdt:Locator="Match(configSource)" xdt:Transform="InsertIfMissing" />
|
||||
</umbracoConfiguration>
|
||||
|
||||
<FileSystemProviders xdt:Transform="Remove" />
|
||||
<BaseRestExtensions xdt:Transform="Remove" />
|
||||
|
||||
<system.data xdt:Transform="InsertIfMissing">
|
||||
<DbProviderFactories xdt:Transform="InsertIfMissing">
|
||||
@@ -61,196 +57,12 @@
|
||||
<httpRuntime xdt:Transform="InsertIfMissing" />
|
||||
<httpRuntime maxRequestLength="51200" fcnMode="Single" xdt:Transform="SetAttributes(fcnMode,maxRequestLength)" />
|
||||
<httpRuntime targetFramework="4.5" xdt:Locator="Condition(count(@targetFramework) != 1)" xdt:Transform="SetAttributes(targetFramework)" />
|
||||
|
||||
|
||||
<membership defaultProvider="DefaultMembershipProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove" />
|
||||
<roleManager defaultProvider="DefaultRoleProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>
|
||||
<profile defaultProvider="DefaultProfileProvider" xdt:Locator="Match(defaultProvider)" xdt:Transform="Remove"/>>
|
||||
<sessionState customProvider="DefaultSessionProvider" xdt:Locator="Match(customProvider)" xdt:Transform="Remove"/>
|
||||
<compilation xdt:Transform="InsertIfMissing" />
|
||||
<compilation>
|
||||
<assemblies xdt:Transform="InsertIfMissing" />
|
||||
<assemblies>
|
||||
<add assembly="System.Net.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Web.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<add assembly="System.Core, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<add assembly="System.Web.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<add assembly="System.Xml.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<add assembly="System.Data.DataSetExtensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<add assembly="System.Web.Extensions.Design, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<add assembly="System.Web.Abstractions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<add assembly="System.Web.Helpers, Version=1.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<add assembly="System.Web.Routing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<add assembly="System.Web.Mvc, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<add assembly="System.Web.WebPages, Version=2.0.0.0, Culture=neutral, PublicKeyToken=31BF3856AD364E35" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<add assembly="System.Collections, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Collections.Concurrent, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.ComponentModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.ComponentModel.Annotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.ComponentModel.EventBasedAsync, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Diagnostics.Contracts, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Diagnostics.Debug, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Diagnostics.Tools, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Diagnostics.Tracing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Dynamic.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Globalization, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.IO, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Linq, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Linq.Expressions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Linq.Parallel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Linq.Queryable, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Net.NetworkInformation, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Net.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Net.Requests, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.ObjectModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Reflection, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Reflection.Emit, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Reflection.Emit.ILGeneration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Reflection.Emit.Lightweight, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Reflection.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Reflection.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Resources.ResourceManager, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Runtime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Runtime.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Runtime.InteropServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Runtime.InteropServices.WindowsRuntime, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Runtime.Numerics, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Runtime.Serialization.Json, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Runtime.Serialization.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Runtime.Serialization.Xml, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Security.Principal, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.ServiceModel.Duplex, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.ServiceModel.Http, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.ServiceModel.NetTcp, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.ServiceModel.Primitives, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.ServiceModel.Security, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Text.Encoding, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Text.Encoding.Extensions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Text.RegularExpressions, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Threading, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Threading.Tasks, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Threading.Tasks.Parallel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Xml.ReaderWriter, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Xml.XDocument, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
<add assembly="System.Xml.XmlSerializer, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" xdt:Locator="Match(assembly)" xdt:Transform="InsertIfMissing" />
|
||||
</assemblies>
|
||||
</compilation>
|
||||
|
||||
<compilation>
|
||||
<assemblies>
|
||||
<remove assembly="System.Web.Http" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Net.Http" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Collections" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Collections.Concurrent" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.ComponentModel" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.ComponentModel.Annotations" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.ComponentModel.EventBasedAsync" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Diagnostics.Contracts" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Diagnostics.Debug" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Diagnostics.Tools" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Diagnostics.Tracing" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Dynamic.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Globalization" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.IO" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Linq" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Linq.Expressions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Linq.Parallel" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Linq.Queryable" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Net.NetworkInformation" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Net.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Net.Requests" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.ObjectModel" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Reflection" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Reflection.Emit" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Reflection.Emit.ILGeneration" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Reflection.Emit.Lightweight" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Reflection.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Reflection.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Resources.ResourceManager" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Runtime.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Runtime.InteropServices" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Runtime.InteropServices.WindowsRuntime" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Runtime.Numerics" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Runtime.Serialization.Json" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Runtime.Serialization.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Runtime.Serialization.Xml" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Security.Principal" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.ServiceModel.Duplex" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.ServiceModel.Http" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.ServiceModel.NetTcp" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.ServiceModel.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.ServiceModel.Security" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Text.Encoding" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Text.Encoding.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Text.RegularExpressions" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Threading" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Threading.Tasks" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Threading.Tasks.Parallel" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Xml.ReaderWriter" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Xml.XDocument" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
<remove assembly="System.Xml.XmlSerializer" xdt:Locator="Match(assembly)" xdt:Transform="Remove" />
|
||||
</assemblies>
|
||||
</compilation>
|
||||
<compilation>
|
||||
<assemblies>
|
||||
<remove assembly="System.Web.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Net.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Collections" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Collections.Concurrent" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.ComponentModel" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.ComponentModel.Annotations" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.ComponentModel.EventBasedAsync" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Diagnostics.Contracts" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Diagnostics.Debug" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Diagnostics.Tools" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Diagnostics.Tracing" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Dynamic.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Globalization" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.IO" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Linq" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Linq.Expressions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Linq.Parallel" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Linq.Queryable" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Net.NetworkInformation" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Net.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Net.Requests" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.ObjectModel" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Reflection" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Reflection.Emit" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Reflection.Emit.ILGeneration" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Reflection.Emit.Lightweight" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Reflection.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Reflection.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Resources.ResourceManager" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Runtime" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Runtime.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Runtime.InteropServices" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Runtime.InteropServices.WindowsRuntime" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Runtime.Numerics" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Runtime.Serialization.Json" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Runtime.Serialization.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Runtime.Serialization.Xml" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Security.Principal" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.ServiceModel.Duplex" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.ServiceModel.Http" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.ServiceModel.NetTcp" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.ServiceModel.Primitives" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.ServiceModel.Security" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Text.Encoding" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Text.Encoding.Extensions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Text.RegularExpressions" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Threading" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Threading.Tasks" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Threading.Tasks.Parallel" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Xml.ReaderWriter" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Xml.XDocument" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
<remove assembly="System.Xml.XmlSerializer" xdt:Locator="Match(assembly)" xdt:Transform="InsertBefore(/configuration/system.web/compilation/assemblies/add)" />
|
||||
</assemblies>
|
||||
</compilation>
|
||||
|
||||
<xhtmlConformance xdt:Transform="Remove" />
|
||||
|
||||
@@ -276,9 +88,6 @@
|
||||
<remove name="umbracoRequestModule" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<remove name="viewstateMoverModule" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<remove name="umbracoBaseRequestModule" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<remove name="WebDAVModule" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<!-- Inserts it as the first element. Also see http://stackoverflow.com/a/19041487/5018 -->
|
||||
<remove name="WebDAVModule" xdt:Locator="Match(name)" xdt:Transform="Insert" />
|
||||
|
||||
<add name="umbracoRequestModule" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
<add name="viewstateMoverModule" xdt:Locator="Match(name)" xdt:Transform="Remove" />
|
||||
@@ -341,62 +150,42 @@
|
||||
|
||||
<runtime>
|
||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="HtmlAgilityPack" publicKeyToken="bd319b19eaf3b43a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.5.1.0" newVersion="1.5.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="AutoMapper" publicKeyToken="be96cd2c38ef1005" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.3.1.0" newVersion="3.3.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.WebPages.Razor" publicKeyToken="31bf3856ad364e35" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-3.1.0.0" newVersion="3.1.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Net.Http.Formatting" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.3.0" newVersion="5.2.3.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Data.SqlServerCe" publicKeyToken="89845DCD8080CC91" culture="neutral"/>
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.1" newVersion="4.0.0.1"/>
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="log4net" publicKeyToken="669e0ddf0bb1aa2a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-2.0.8.0" newVersion="2.0.8.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.Cookies" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Microsoft.Owin.Security.OAuth" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-1.2.1.0" newVersion="1.2.1.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.Http" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.6.0" newVersion="5.2.6.0" />
|
||||
</dependentAssembly>
|
||||
<dependentAssembly xdt:Transform="Insert">
|
||||
<assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" culture="neutral" />
|
||||
<bindingRedirect oldVersion="0.0.0.0-5.2.6.0" newVersion="5.2.6.0" />
|
||||
</dependentAssembly>
|
||||
</assemblyBinding>
|
||||
</runtime>
|
||||
|
||||
@@ -416,4 +205,4 @@
|
||||
</system.webServer>
|
||||
</location>
|
||||
|
||||
</configuration>
|
||||
</configuration>
|
||||
|
||||
@@ -1,162 +1,162 @@
|
||||
param($installPath, $toolsPath, $package, $project)
|
||||
|
||||
Write-Host "installPath:" "${installPath}"
|
||||
Write-Host "toolsPath:" "${toolsPath}"
|
||||
|
||||
Write-Host " "
|
||||
|
||||
if ($project) {
|
||||
$dateTime = Get-Date -Format yyyyMMdd-HHmmss
|
||||
|
||||
# Create paths and list them
|
||||
$projectPath = (Get-Item $project.Properties.Item("FullPath").Value).FullName
|
||||
Write-Host "projectPath:" "${projectPath}"
|
||||
$backupPath = Join-Path $projectPath "App_Data\NuGetBackup\$dateTime"
|
||||
Write-Host "backupPath:" "${backupPath}"
|
||||
$copyLogsPath = Join-Path $backupPath "CopyLogs"
|
||||
Write-Host "copyLogsPath:" "${copyLogsPath}"
|
||||
$webConfigSource = Join-Path $projectPath "Web.config"
|
||||
Write-Host "webConfigSource:" "${webConfigSource}"
|
||||
$configFolder = Join-Path $projectPath "Config"
|
||||
Write-Host "configFolder:" "${configFolder}"
|
||||
|
||||
# Create backup folder and logs folder if it doesn't exist yet
|
||||
New-Item -ItemType Directory -Force -Path $backupPath
|
||||
New-Item -ItemType Directory -Force -Path $copyLogsPath
|
||||
|
||||
# Create a backup of original web.config
|
||||
Copy-Item $webConfigSource $backupPath -Force
|
||||
|
||||
# Backup config files folder
|
||||
if(Test-Path $configFolder) {
|
||||
$umbracoBackupPath = Join-Path $backupPath "Config"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoBackupPath
|
||||
|
||||
robocopy $configFolder $umbracoBackupPath /e /LOG:$copyLogsPath\ConfigBackup.log
|
||||
}
|
||||
|
||||
# Copy umbraco and umbraco_files from package to project folder
|
||||
$umbracoFolder = Join-Path $projectPath "Umbraco"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoFolder
|
||||
$umbracoFolderSource = Join-Path $installPath "UmbracoFiles\Umbraco"
|
||||
$umbracoBackupPath = Join-Path $backupPath "Umbraco"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoBackupPath
|
||||
robocopy $umbracoFolder $umbracoBackupPath /e /LOG:$copyLogsPath\UmbracoBackup.log
|
||||
robocopy $umbracoFolderSource $umbracoFolder /is /it /e /xf UI.xml /LOG:$copyLogsPath\UmbracoCopy.log
|
||||
|
||||
$umbracoClientFolder = Join-Path $projectPath "Umbraco_Client"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoClientFolder
|
||||
$umbracoClientFolderSource = Join-Path $installPath "UmbracoFiles\Umbraco_Client"
|
||||
$umbracoClientBackupPath = Join-Path $backupPath "Umbraco_Client"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoClientBackupPath
|
||||
robocopy $umbracoClientFolder $umbracoClientBackupPath /e /LOG:$copyLogsPath\UmbracoClientBackup.log
|
||||
robocopy $umbracoClientFolderSource $umbracoClientFolder /is /it /e /LOG:$copyLogsPath\UmbracoClientCopy.log
|
||||
|
||||
$copyWebconfig = $true
|
||||
$destinationWebConfig = Join-Path $projectPath "Web.config"
|
||||
|
||||
if(Test-Path $destinationWebConfig)
|
||||
{
|
||||
Try
|
||||
{
|
||||
[xml]$config = Get-Content $destinationWebConfig
|
||||
|
||||
$config.configuration.appSettings.ChildNodes | ForEach-Object {
|
||||
if($_.key -eq "umbracoConfigurationStatus")
|
||||
{
|
||||
# The web.config has an umbraco-specific appSetting in it
|
||||
# don't overwrite it and let config transforms do their thing
|
||||
$copyWebconfig = $false
|
||||
}
|
||||
}
|
||||
}
|
||||
Catch { }
|
||||
}
|
||||
|
||||
if($copyWebconfig -eq $true)
|
||||
{
|
||||
$packageWebConfigSource = Join-Path $installPath "UmbracoFiles\Web.config"
|
||||
Copy-Item $packageWebConfigSource $destinationWebConfig -Force
|
||||
|
||||
# Copy files that don't get automatically copied for Website projects
|
||||
# We do this here, when copyWebconfig is true because we only want to do it for new installs
|
||||
# If this is an upgrade then the files should already be there
|
||||
$splashesSource = Join-Path $installPath "UmbracoFiles\Config\splashes\*.*"
|
||||
$splashesDestination = Join-Path $projectPath "Config\splashes\"
|
||||
New-Item $splashesDestination -Type directory
|
||||
Copy-Item $splashesSource $splashesDestination -Force
|
||||
|
||||
$sqlCe64Source = Join-Path $installPath "UmbracoFiles\bin\amd64\*"
|
||||
$sqlCe64Destination = Join-Path $projectPath "bin\amd64\"
|
||||
Copy-Item $sqlCe64Source $sqlCe64Destination -Force
|
||||
|
||||
$sqlCex86Source = Join-Path $installPath "UmbracoFiles\bin\x86\*"
|
||||
$sqlCex86Destination = Join-Path $projectPath "bin\x86\"
|
||||
Copy-Item $sqlCex86source $sqlCex86Destination -Force
|
||||
|
||||
$umbracoUIXMLSource = Join-Path $installPath "UmbracoFiles\Umbraco\Config\Create\UI.xml"
|
||||
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
|
||||
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
|
||||
} else {
|
||||
# This part only runs for upgrades
|
||||
|
||||
$upgradeViewSource = Join-Path $umbracoFolderSource "Views\install\*"
|
||||
$upgradeView = Join-Path $umbracoFolder "Views\install\"
|
||||
Write-Host "Copying2 ${upgradeViewSource} to ${upgradeView}"
|
||||
Copy-Item $upgradeViewSource $upgradeView -Force
|
||||
|
||||
Try
|
||||
{
|
||||
# Disable tours for upgrades, presumably Umbraco experience is already available
|
||||
$umbracoSettingsConfigPath = Join-Path $configFolder "umbracoSettings.config"
|
||||
$content = (Get-Content $umbracoSettingsConfigPath).Replace('<tours enable="true">','<tours enable="false">')
|
||||
# Saves with UTF-8 encoding without BOM which makes sure Umbraco can still read it
|
||||
# Reference: https://stackoverflow.com/a/32951824/5018
|
||||
[IO.File]::WriteAllLines($umbracoSettingsConfigPath, $content)
|
||||
}
|
||||
Catch
|
||||
{
|
||||
# Not a big problem if this fails, let it go
|
||||
}
|
||||
|
||||
Try
|
||||
{
|
||||
$uiXmlConfigPath = Join-Path $umbracoFolder -ChildPath "Config" | Join-Path -ChildPath "create" | Join-Path -ChildPath "UI.xml"
|
||||
$uiXmlFile = Join-Path $umbracoFolder -ChildPath "Config" | Join-Path -ChildPath "create" | Join-Path -ChildPath "UI.xml"
|
||||
|
||||
$uiXml = New-Object System.Xml.XmlDocument
|
||||
$uiXml.PreserveWhitespace = $true
|
||||
|
||||
$uiXml.Load($uiXmlFile)
|
||||
$createExists = $uiXml.SelectNodes("//nodeType[@alias='macros']/tasks/create")
|
||||
|
||||
if($createExists.Count -eq 0)
|
||||
{
|
||||
$macrosTasksNode = $uiXml.SelectNodes("//nodeType[@alias='macros']/tasks")
|
||||
|
||||
#Creating: <create assembly="umbraco" type="macroTasks" />
|
||||
$createNode = $uiXml.CreateElement("create")
|
||||
$createNode.SetAttribute("assembly", "umbraco")
|
||||
$createNode.SetAttribute("type", "macroTasks")
|
||||
$macrosTasksNode.AppendChild($createNode)
|
||||
$uiXml.Save($uiXmlFile)
|
||||
}
|
||||
}
|
||||
Catch { }
|
||||
}
|
||||
|
||||
$installFolder = Join-Path $projectPath "Install"
|
||||
if(Test-Path $installFolder) {
|
||||
Remove-Item $installFolder -Force -Recurse -Confirm:$false
|
||||
}
|
||||
|
||||
# Open appropriate readme
|
||||
if($copyWebconfig -eq $true)
|
||||
{
|
||||
$DTE.ItemOperations.OpenFile($toolsPath + '\Readme.txt')
|
||||
}
|
||||
else
|
||||
{
|
||||
$DTE.ItemOperations.OpenFile($toolsPath + '\ReadmeUpgrade.txt')
|
||||
}
|
||||
param($installPath, $toolsPath, $package, $project)
|
||||
|
||||
Write-Host "installPath:" "${installPath}"
|
||||
Write-Host "toolsPath:" "${toolsPath}"
|
||||
|
||||
Write-Host " "
|
||||
|
||||
if ($project) {
|
||||
$dateTime = Get-Date -Format yyyyMMdd-HHmmss
|
||||
|
||||
# Create paths and list them
|
||||
$projectPath = (Get-Item $project.Properties.Item("FullPath").Value).FullName
|
||||
Write-Host "projectPath:" "${projectPath}"
|
||||
$backupPath = Join-Path $projectPath "App_Data\NuGetBackup\$dateTime"
|
||||
Write-Host "backupPath:" "${backupPath}"
|
||||
$copyLogsPath = Join-Path $backupPath "CopyLogs"
|
||||
Write-Host "copyLogsPath:" "${copyLogsPath}"
|
||||
$webConfigSource = Join-Path $projectPath "Web.config"
|
||||
Write-Host "webConfigSource:" "${webConfigSource}"
|
||||
$configFolder = Join-Path $projectPath "Config"
|
||||
Write-Host "configFolder:" "${configFolder}"
|
||||
|
||||
# Create backup folder and logs folder if it doesn't exist yet
|
||||
New-Item -ItemType Directory -Force -Path $backupPath
|
||||
New-Item -ItemType Directory -Force -Path $copyLogsPath
|
||||
|
||||
# Create a backup of original web.config
|
||||
Copy-Item $webConfigSource $backupPath -Force
|
||||
|
||||
# Backup config files folder
|
||||
if(Test-Path $configFolder) {
|
||||
$umbracoBackupPath = Join-Path $backupPath "Config"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoBackupPath
|
||||
|
||||
robocopy $configFolder $umbracoBackupPath /e /LOG:$copyLogsPath\ConfigBackup.log
|
||||
}
|
||||
|
||||
# Copy umbraco and umbraco_files from package to project folder
|
||||
$umbracoFolder = Join-Path $projectPath "Umbraco"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoFolder
|
||||
$umbracoFolderSource = Join-Path $installPath "UmbracoFiles\Umbraco"
|
||||
$umbracoBackupPath = Join-Path $backupPath "Umbraco"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoBackupPath
|
||||
robocopy $umbracoFolder $umbracoBackupPath /e /LOG:$copyLogsPath\UmbracoBackup.log
|
||||
robocopy $umbracoFolderSource $umbracoFolder /is /it /e /xf UI.xml /LOG:$copyLogsPath\UmbracoCopy.log
|
||||
|
||||
$umbracoClientFolder = Join-Path $projectPath "Umbraco_Client"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoClientFolder
|
||||
$umbracoClientFolderSource = Join-Path $installPath "UmbracoFiles\Umbraco_Client"
|
||||
$umbracoClientBackupPath = Join-Path $backupPath "Umbraco_Client"
|
||||
New-Item -ItemType Directory -Force -Path $umbracoClientBackupPath
|
||||
robocopy $umbracoClientFolder $umbracoClientBackupPath /e /LOG:$copyLogsPath\UmbracoClientBackup.log
|
||||
robocopy $umbracoClientFolderSource $umbracoClientFolder /is /it /e /LOG:$copyLogsPath\UmbracoClientCopy.log
|
||||
|
||||
$copyWebconfig = $true
|
||||
$destinationWebConfig = Join-Path $projectPath "Web.config"
|
||||
|
||||
if(Test-Path $destinationWebConfig)
|
||||
{
|
||||
Try
|
||||
{
|
||||
[xml]$config = Get-Content $destinationWebConfig
|
||||
|
||||
$config.configuration.appSettings.ChildNodes | ForEach-Object {
|
||||
if($_.key -eq "umbracoConfigurationStatus")
|
||||
{
|
||||
# The web.config has an umbraco-specific appSetting in it
|
||||
# don't overwrite it and let config transforms do their thing
|
||||
$copyWebconfig = $false
|
||||
}
|
||||
}
|
||||
}
|
||||
Catch { }
|
||||
}
|
||||
|
||||
if($copyWebconfig -eq $true)
|
||||
{
|
||||
$packageWebConfigSource = Join-Path $installPath "UmbracoFiles\Web.config"
|
||||
Copy-Item $packageWebConfigSource $destinationWebConfig -Force
|
||||
|
||||
# Copy files that don't get automatically copied for Website projects
|
||||
# We do this here, when copyWebconfig is true because we only want to do it for new installs
|
||||
# If this is an upgrade then the files should already be there
|
||||
$splashesSource = Join-Path $installPath "UmbracoFiles\Config\splashes\*.*"
|
||||
$splashesDestination = Join-Path $projectPath "Config\splashes\"
|
||||
New-Item $splashesDestination -Type directory
|
||||
Copy-Item $splashesSource $splashesDestination -Force
|
||||
|
||||
$sqlCe64Source = Join-Path $installPath "UmbracoFiles\bin\amd64\*"
|
||||
$sqlCe64Destination = Join-Path $projectPath "bin\amd64\"
|
||||
Copy-Item $sqlCe64Source $sqlCe64Destination -Force
|
||||
|
||||
$sqlCex86Source = Join-Path $installPath "UmbracoFiles\bin\x86\*"
|
||||
$sqlCex86Destination = Join-Path $projectPath "bin\x86\"
|
||||
Copy-Item $sqlCex86source $sqlCex86Destination -Force
|
||||
|
||||
$umbracoUIXMLSource = Join-Path $installPath "UmbracoFiles\Umbraco\Config\Create\UI.xml"
|
||||
$umbracoUIXMLDestination = Join-Path $projectPath "Umbraco\Config\Create\UI.xml"
|
||||
Copy-Item $umbracoUIXMLSource $umbracoUIXMLDestination -Force
|
||||
} else {
|
||||
# This part only runs for upgrades
|
||||
|
||||
$upgradeViewSource = Join-Path $umbracoFolderSource "Views\install\*"
|
||||
$upgradeView = Join-Path $umbracoFolder "Views\install\"
|
||||
Write-Host "Copying2 ${upgradeViewSource} to ${upgradeView}"
|
||||
Copy-Item $upgradeViewSource $upgradeView -Force
|
||||
|
||||
Try
|
||||
{
|
||||
# Disable tours for upgrades, presumably Umbraco experience is already available
|
||||
$umbracoSettingsConfigPath = Join-Path $configFolder "umbracoSettings.config"
|
||||
$content = (Get-Content $umbracoSettingsConfigPath).Replace('<tours enable="true">','<tours enable="false">')
|
||||
# Saves with UTF-8 encoding without BOM which makes sure Umbraco can still read it
|
||||
# Reference: https://stackoverflow.com/a/32951824/5018
|
||||
[IO.File]::WriteAllLines($umbracoSettingsConfigPath, $content)
|
||||
}
|
||||
Catch
|
||||
{
|
||||
# Not a big problem if this fails, let it go
|
||||
}
|
||||
|
||||
Try
|
||||
{
|
||||
$uiXmlConfigPath = Join-Path $umbracoFolder -ChildPath "Config" | Join-Path -ChildPath "create" | Join-Path -ChildPath "UI.xml"
|
||||
$uiXmlFile = Join-Path $umbracoFolder -ChildPath "Config" | Join-Path -ChildPath "create" | Join-Path -ChildPath "UI.xml"
|
||||
|
||||
$uiXml = New-Object System.Xml.XmlDocument
|
||||
$uiXml.PreserveWhitespace = $true
|
||||
|
||||
$uiXml.Load($uiXmlFile)
|
||||
$createExists = $uiXml.SelectNodes("//nodeType[@alias='macros']/tasks/create")
|
||||
|
||||
if($createExists.Count -eq 0)
|
||||
{
|
||||
$macrosTasksNode = $uiXml.SelectNodes("//nodeType[@alias='macros']/tasks")
|
||||
|
||||
#Creating: <create assembly="umbraco" type="macroTasks" />
|
||||
$createNode = $uiXml.CreateElement("create")
|
||||
$createNode.SetAttribute("assembly", "umbraco")
|
||||
$createNode.SetAttribute("type", "macroTasks")
|
||||
$macrosTasksNode.AppendChild($createNode)
|
||||
$uiXml.Save($uiXmlFile)
|
||||
}
|
||||
}
|
||||
Catch { }
|
||||
}
|
||||
|
||||
$installFolder = Join-Path $projectPath "Install"
|
||||
if(Test-Path $installFolder) {
|
||||
Remove-Item $installFolder -Force -Recurse -Confirm:$false
|
||||
}
|
||||
|
||||
# Open appropriate readme
|
||||
if($copyWebconfig -eq $true)
|
||||
{
|
||||
$DTE.ItemOperations.OpenFile($toolsPath + '\Readme.txt')
|
||||
}
|
||||
else
|
||||
{
|
||||
$DTE.ItemOperations.OpenFile($toolsPath + '\ReadmeUpgrade.txt')
|
||||
}
|
||||
}
|
||||
@@ -4,18 +4,18 @@
|
||||
<add alias="content" application="content"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="RemoveAttributes(silent)" />
|
||||
<add initialize="false" sortOrder="0" alias="contentRecycleBin" application="content" title="Recycle Bin" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.cms.presentation.Trees.ContentRecycleBin, umbraco"
|
||||
<add initialize="false" sortOrder="0" alias="contentRecycleBin" application="content" title="Recycle Bin" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.cms.presentation.Trees.ContentRecycleBin, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add initialize="true" sortOrder="0" alias="content" application="content" title="Content" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.ContentTreeController, umbraco"
|
||||
<add initialize="true" sortOrder="0" alias="content" application="content" title="Content" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.ContentTreeController, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
|
||||
<!--Media-->
|
||||
<add initialize="true" sortOrder="0" alias="media" application="media" title="Media" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.MediaTreeController, umbraco"
|
||||
<add initialize="true" sortOrder="0" alias="media" application="media" title="Media" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.MediaTreeController, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add initialize="false" sortOrder="0" alias="mediaRecycleBin" application="media" title="Recycle Bin" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.cms.presentation.Trees.MediaRecycleBin, umbraco"
|
||||
<add initialize="false" sortOrder="0" alias="mediaRecycleBin" application="media" title="Recycle Bin" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.cms.presentation.Trees.MediaRecycleBin, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
|
||||
@@ -23,39 +23,39 @@
|
||||
<add application="settings" alias="nodeTypes"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="Remove" />
|
||||
<add initialize="true" sortOrder="0" alias="documentTypes" application="settings" title="Document Types" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.ContentTypeTreeController, umbraco"
|
||||
<add initialize="true" sortOrder="0" alias="documentTypes" application="settings" title="Document Types" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.ContentTypeTreeController, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="InsertIfMissing" />
|
||||
<add application="settings" alias="stylesheets" title="Stylesheets" type="umbraco.loadStylesheets, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="3"
|
||||
<add application="settings" alias="stylesheets" title="Stylesheets" type="umbraco.loadStylesheets, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="3"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="stylesheetProperty" title="Stylesheet Property" type="umbraco.loadStylesheetProperty, umbraco" iconClosed="" iconOpen="" initialize="false" sortOrder="0"
|
||||
<add application="settings" alias="stylesheetProperty" title="Stylesheet Property" type="umbraco.loadStylesheetProperty, Umbraco.Web" iconClosed="" iconOpen="" initialize="false" sortOrder="0"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="templates" title="Templates" type="Umbraco.Web.Trees.TemplatesTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="1"
|
||||
<add application="settings" alias="templates" title="Templates" type="Umbraco.Web.Trees.TemplatesTreeController, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="1"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
|
||||
<add application="settings" alias="partialViews" type="Umbraco.Web.Trees.PartialViewsTree, umbraco"
|
||||
<add application="settings" alias="partialViews" type="Umbraco.Web.Trees.PartialViewsTree, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias,type)"
|
||||
xdt:Transform="Remove()" />
|
||||
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTreeController, umbraco" sortOrder="2"
|
||||
<add application="settings" alias="partialViews" title="Partial Views" silent="false" initialize="true" iconClosed="icon-folder" iconOpen="icon-folder" type="Umbraco.Web.Trees.PartialViewsTreeController, Umbraco.Web" sortOrder="2"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="InsertIfMissing" />
|
||||
|
||||
<add application="settings" alias="scripts" title="Scripts" type="Umbraco.Web.Trees.ScriptTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
|
||||
<add application="settings" alias="scripts" title="Scripts" type="Umbraco.Web.Trees.ScriptTreeController, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" alias="dictionary" title="Dictionary" type="umbraco.loadDictionary, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="6"
|
||||
<add application="settings" alias="dictionary" title="Dictionary" type="Umbraco.Web.Trees.DictionaryTreeController, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="8"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add alias="dictionary" application="settings"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="RemoveAttributes(action)" />
|
||||
<add application="settings" alias="languages" title="Languages" type="Umbraco.Web.Trees.LanguageTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="5"
|
||||
<add application="settings" alias="languages" title="Languages" type="Umbraco.Web.Trees.LanguageTreeController, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="5"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="settings" initialize="true" alias="mediaTypes" title="Media Types" type="Umbraco.Web.Trees.MediaTypeTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="7"
|
||||
<add application="settings" initialize="true" alias="mediaTypes" title="Media Types" type="Umbraco.Web.Trees.MediaTypeTreeController, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder-open" sortOrder="7"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
|
||||
@@ -66,12 +66,12 @@
|
||||
<add alias="packagerPackages" application="developer"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="Remove" />
|
||||
<add initialize="true" sortOrder="0" alias="packager" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.PackagesTreeController, umbraco"
|
||||
<add initialize="true" sortOrder="0" alias="packager" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.PackagesTreeController, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="InsertIfMissing" />
|
||||
|
||||
<!-- Before 7.4 this tree had the alias 'dataType', without the 's' on the end, this is here to rename it -->
|
||||
<add sortOrder="1" alias="dataTypes" application="developer" type="Umbraco.Web.Trees.DataTypeTreeController, umbraco"
|
||||
<add sortOrder="1" alias="dataTypes" application="developer" type="Umbraco.Web.Trees.DataTypeTreeController, Umbraco.Web"
|
||||
xdt:Locator="Match(application,type)"
|
||||
xdt:Transform="SetAttributes(alias,sortOrder)" />
|
||||
|
||||
@@ -80,20 +80,17 @@
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes(sortOrder)" />
|
||||
|
||||
<add initialize="true" sortOrder="2" alias="macros" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MacroTreeController, umbraco"
|
||||
<add initialize="true" sortOrder="2" alias="macros" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MacroTreeController, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="developer" alias="relationTypes" title="Relation Types" type="umbraco.loadRelationTypes, umbraco" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add initialize="true" sortOrder="5" alias="xslt" application="developer" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.XsltTreeController, umbraco"
|
||||
<add application="developer" alias="relationTypes" title="Relation Types" type="umbraco.loadRelationTypes, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder" sortOrder="4"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
|
||||
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, umbraco"
|
||||
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTree, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias,type)"
|
||||
xdt:Transform="Remove()" />
|
||||
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTreeController, umbraco" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder"
|
||||
<add application="developer" alias="partialViewMacros" type="Umbraco.Web.Trees.PartialViewMacrosTreeController, Umbraco.Web" silent="false" initialize="true" sortOrder="6" title="Partial View Macro Files" iconClosed="icon-folder" iconOpen="icon-folder"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="InsertIfMissing" />
|
||||
|
||||
@@ -102,7 +99,7 @@
|
||||
xdt:Transform="Remove" />
|
||||
|
||||
<!--Users-->
|
||||
<add initialize="true" sortOrder="0" alias="users" application="users" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.UserTreeController, umbraco"
|
||||
<add initialize="true" sortOrder="0" alias="users" application="users" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.UserTreeController, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
|
||||
@@ -114,30 +111,30 @@
|
||||
xdt:Transform="Remove" />
|
||||
|
||||
<!--Members-->
|
||||
<add initialize="true" sortOrder="0" alias="member" application="member" title="Members" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberTreeController, umbraco"
|
||||
<add initialize="true" sortOrder="0" alias="member" application="member" title="Members" iconClosed="icon-folder" iconOpen="icon-folder-open" type="Umbraco.Web.Trees.MemberTreeController, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add application="member" alias="memberGroup"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="Remove" />
|
||||
<add application="member" sortOrder="2" alias="memberGroups" title="Member Groups" type="umbraco.loadMemberGroups, umbraco" iconClosed="icon-folder" iconOpen="icon-folder"
|
||||
<add application="member" sortOrder="2" alias="memberGroups" title="Member Groups" type="umbraco.loadMemberGroups, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="InsertIfMissing" />
|
||||
<add application="member" alias="memberType"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="Remove" />
|
||||
<add application="member" sortOrder="1" alias="memberTypes" initialize="true" title="Member Types" type="Umbraco.Web.Trees.MemberTypeTreeController, umbraco" iconClosed="icon-folder" iconOpen="icon-folder-open"
|
||||
<add application="member" sortOrder="1" alias="memberTypes" initialize="true" title="Member Types" type="Umbraco.Web.Trees.MemberTypeTreeController, Umbraco.Web" iconClosed="icon-folder" iconOpen="icon-folder-open"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="InsertIfMissing" />
|
||||
|
||||
<!--Translation-->
|
||||
<add silent="false" initialize="true" sortOrder="1" alias="openTasks" application="translation" title="Tasks assigned to you" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.loadOpenTasks, umbraco"
|
||||
<add silent="false" initialize="true" sortOrder="1" alias="openTasks" application="translation" title="Tasks assigned to you" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.loadOpenTasks, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add alias="openTasks" application="translation"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="RemoveAttributes(action)" />
|
||||
<add silent="false" initialize="true" sortOrder="2" alias="yourTasks" application="translation" title="Tasks created by you" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.loadYourTasks, umbraco"
|
||||
<add silent="false" initialize="true" sortOrder="2" alias="yourTasks" application="translation" title="Tasks created by you" iconClosed="icon-folder" iconOpen="icon-folder" type="umbraco.loadYourTasks, Umbraco.Web"
|
||||
xdt:Locator="Match(application,alias)"
|
||||
xdt:Transform="SetAttributes()" />
|
||||
<add alias="yourTasks" application="translation"
|
||||
|
||||
@@ -5,4 +5,6 @@
|
||||
</content>
|
||||
|
||||
<webservices xdt:Transform="Remove" />
|
||||
|
||||
<repositories xdt:Transform="Remove" />
|
||||
</settings>
|
||||
@@ -1,127 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
:choice
|
||||
set /P c=WARNING! Are you sure you want to continue, this will remove all package files, view files, sqlce database, etc... Press 'Y' to auto-remove all files/folders, 'N' to cancel or 'C' to prompt for each folder removal?
|
||||
if /I "%c%" EQU "C" goto :prompt
|
||||
if /I "%c%" EQU "Y" goto :auto
|
||||
if /I "%c%" EQU "N" goto :exit
|
||||
goto :choice
|
||||
|
||||
|
||||
:prompt
|
||||
|
||||
echo Current folder: %CD%
|
||||
|
||||
echo Removing sqlce database
|
||||
del ..\src\Umbraco.Web.UI\App_Data\Umbraco.sdf
|
||||
|
||||
echo Resetting installedPackages.config
|
||||
echo ^<?xml version="1.0" encoding="utf-8"?^>^<packages^>^</packages^> >..\src\Umbraco.Web.UI\App_Data\packages\installed\installedPackages.config
|
||||
|
||||
echo Removing plugin cache files
|
||||
del ..\src\Umbraco.Web.UI\App_Data\TEMP\PluginCache\*.*
|
||||
|
||||
echo Removing cache files and examine index
|
||||
del ..\src\Umbraco.Web.UI\App_Data\TEMP\*.*
|
||||
|
||||
echo Removing log files
|
||||
del ..\src\Umbraco.Web.UI\App_Data\Logs\*.*
|
||||
|
||||
echo Removing packages
|
||||
del ..\src\Umbraco.Web.UI\App_Data\packages\*.*
|
||||
|
||||
echo Removing previews
|
||||
del ..\src\Umbraco.Web.UI\App_Data\preview\*.*
|
||||
|
||||
echo Removing app code files (typically added by starterkits)
|
||||
del ..\src\Umbraco.Web.UI\App_Code\*.*
|
||||
|
||||
echo Removing xslt files
|
||||
del ..\src\Umbraco.Web.UI\xslt\*.*
|
||||
|
||||
echo Removing user control files
|
||||
del ..\src\Umbraco.Web.UI\UserControls\*.*
|
||||
|
||||
echo Removing masterpage files
|
||||
del ..\src\Umbraco.Web.UI\masterpages\*.*
|
||||
|
||||
echo Removing razor files
|
||||
del ..\src\Umbraco.Web.UI\macroScripts\*.*
|
||||
|
||||
echo Removing media files
|
||||
del ..\src\Umbraco.Web.UI\media\*.*
|
||||
|
||||
echo Removing script files
|
||||
del ..\src\Umbraco.Web.UI\scripts\*.*
|
||||
|
||||
echo Removing css files
|
||||
del ..\src\Umbraco.Web.UI\css\*.*
|
||||
|
||||
echo "Umbraco install reverted to clean install"
|
||||
pause
|
||||
exit
|
||||
|
||||
|
||||
|
||||
:auto
|
||||
|
||||
echo Current folder: %CD%
|
||||
|
||||
echo Removing sqlce database
|
||||
del ..\src\Umbraco.Web.UI\App_Data\Umbraco.sdf
|
||||
|
||||
echo Resetting installedPackages.config
|
||||
echo ^<?xml version="1.0" encoding="utf-8"?^>^<packages^>^</packages^> >..\src\Umbraco.Web.UI\App_Data\packages\installed\installedPackages.config
|
||||
|
||||
echo Removing plugin cache files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\TEMP\PluginCache\*.*) DO DEL %%A
|
||||
|
||||
echo Removing cache files and examine index
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\TEMP\*.*) DO DEL %%A
|
||||
|
||||
echo Removing log files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\Logs\*.*) DO DEL %%A
|
||||
|
||||
echo Removing packages
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\packages\*.*) DO DEL %%A
|
||||
|
||||
echo Removing previews
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\preview\*.*) DO DEL %%A
|
||||
|
||||
echo Removing app code files (typically added by starterkits)
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Code\*.*) DO DEL %%A
|
||||
|
||||
echo Removing xslt files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\xslt\*.*) DO DEL %%A
|
||||
|
||||
echo Removing masterpage files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\masterpages\*.*) DO DEL %%A
|
||||
|
||||
echo Removing user control files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\usercontrols\*.*) DO DEL %%A
|
||||
|
||||
echo Removing view files
|
||||
ATTRIB +H ..\src\Umbraco.Web.UI\Views\Partials\Grid\*.cshtml /S
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\Views\) DO DEL /Q /S *.cshtml -H
|
||||
ATTRIB -H ..\src\Umbraco.Web.UI\Views\Partials\Grid\*.cshtml /S
|
||||
|
||||
echo Removing razor files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\macroScripts\*.*) DO DEL %%A
|
||||
|
||||
echo Removing media files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\media\*.*) DO DEL %%A
|
||||
|
||||
echo Removing script files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\scripts\*.*) DO DEL %%A
|
||||
|
||||
echo Removing css files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\css\*.*) DO DEL %%A
|
||||
|
||||
echo "Umbraco install reverted to clean install"
|
||||
pause
|
||||
exit
|
||||
|
||||
|
||||
|
||||
:exit
|
||||
exit
|
||||
@@ -1,163 +0,0 @@
|
||||
@ECHO OFF
|
||||
|
||||
:choice
|
||||
set /P c=WARNING! Are you sure you want to continue, this will remove all package files, view files, sqlce database, etc... Press 'Y' to auto-remove all files/folders, 'N' to cancel or 'C' to prompt for each folder removal?
|
||||
if /I "%c%" EQU "C" goto :prompt
|
||||
if /I "%c%" EQU "Y" goto :auto
|
||||
if /I "%c%" EQU "N" goto :exit
|
||||
goto :choice
|
||||
|
||||
|
||||
:prompt
|
||||
|
||||
echo Current folder: %CD%
|
||||
|
||||
echo Regenerating SQL CE database
|
||||
SET buildfolder=%CD%
|
||||
CD ..\tools\RegenerateUmbracoSQLCEDatabase\
|
||||
RegenerateUmbracoSQLCEDatabase.exe %CD%\..\..\src\Umbraco.Web.UI
|
||||
CD %buildfolder%
|
||||
|
||||
echo Removing bin files
|
||||
del ..\src\Umbraco.Web.UI\bin\*.*
|
||||
|
||||
echo Building solution
|
||||
"%ProgramFiles(x86)%"\MSBuild\14.0\Bin\MSBuild.exe ..\src\umbraco.sln /t:Clean,Build
|
||||
|
||||
echo Resetting installedPackages.config
|
||||
echo ^<?xml version="1.0" encoding="utf-8"?^>^<packages^>^</packages^> >..\src\Umbraco.Web.UI\App_Data\packages\installed\installedPackages.config
|
||||
|
||||
echo Removing plugin cache files
|
||||
del ..\src\Umbraco.Web.UI\App_Data\TEMP\PluginCache\*.*
|
||||
|
||||
echo Removing cache files and examine index
|
||||
del ..\src\Umbraco.Web.UI\App_Data\TEMP\*.*
|
||||
|
||||
echo Removing log files
|
||||
del ..\src\Umbraco.Web.UI\App_Data\Logs\*.*
|
||||
|
||||
echo Removing packages
|
||||
del ..\src\Umbraco.Web.UI\App_Data\packages\*.*
|
||||
|
||||
echo Removing previews
|
||||
del ..\src\Umbraco.Web.UI\App_Data\preview\*.*
|
||||
|
||||
echo Removing app code files (typically added by starterkits)
|
||||
del ..\src\Umbraco.Web.UI\App_Code\*.*
|
||||
|
||||
echo Removing xslt files
|
||||
del ..\src\Umbraco.Web.UI\xslt\*.*
|
||||
|
||||
echo Removing user control files
|
||||
del ..\src\Umbraco.Web.UI\UserControls\*.*
|
||||
|
||||
echo Removing masterpage files
|
||||
del ..\src\Umbraco.Web.UI\masterpages\*.*
|
||||
|
||||
echo Removing razor files
|
||||
del ..\src\Umbraco.Web.UI\macroScripts\*.*
|
||||
|
||||
echo Removing media files
|
||||
del ..\src\Umbraco.Web.UI\media\*.*
|
||||
|
||||
echo Removing script files
|
||||
del ..\src\Umbraco.Web.UI\scripts\*.*
|
||||
|
||||
echo Removing css files
|
||||
del ..\src\Umbraco.Web.UI\css\*.*
|
||||
|
||||
echo "Umbraco install reverted to clean install"
|
||||
pause
|
||||
exit
|
||||
|
||||
|
||||
|
||||
:auto
|
||||
|
||||
echo Current folder: %CD%
|
||||
|
||||
echo Regenerating SQL CE database
|
||||
SET buildfolder=%CD%
|
||||
CD ..\tools\RegenerateUmbracoSQLCEDatabase\
|
||||
RegenerateUmbracoSQLCEDatabase.exe %CD%\..\..\src\Umbraco.Web.UI
|
||||
CD %buildfolder%
|
||||
|
||||
echo Removing bin files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\bin\*.*) DO DEL %%A
|
||||
|
||||
echo Building solution
|
||||
"%ProgramFiles(x86)%"\MSBuild\14.0\Bin\MSBuild.exe ..\src\umbraco.sln /t:Clean,Build
|
||||
|
||||
echo Resetting installedPackages.config
|
||||
echo ^<?xml version="1.0" encoding="utf-8"?^>^<packages^>^</packages^> >..\src\Umbraco.Web.UI\App_Data\packages\installed\installedPackages.config
|
||||
|
||||
echo Removing plugin cache files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\TEMP\PluginCache\*.*) DO DEL %%A
|
||||
|
||||
echo Removing cache files and examine index
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\TEMP\*.*) DO DEL %%A
|
||||
|
||||
echo Removing log files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\Logs\*.*) DO DEL %%A
|
||||
|
||||
echo Removing packages
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\packages\*.*) DO DEL %%A
|
||||
|
||||
echo Removing previews
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Data\preview\*.*) DO DEL %%A
|
||||
|
||||
echo Removing app code files (typically added by starterkits)
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\App_Code\*.*) DO DEL %%A
|
||||
|
||||
echo Removing xslt files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\xslt\*.*) DO DEL %%A
|
||||
|
||||
echo Removing masterpage files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\masterpages\*.*) DO DEL %%A
|
||||
|
||||
echo Removing user control files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\usercontrols\*.*) DO DEL %%A
|
||||
|
||||
echo Removing view files
|
||||
ATTRIB +H ..\src\Umbraco.Web.UI\Views\Partials\Grid\*.cshtml /S
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\Views\) DO DEL /Q /S *.cshtml -H
|
||||
ATTRIB -H ..\src\Umbraco.Web.UI\Views\Partials\Grid\*.cshtml /S
|
||||
|
||||
echo Removing razor files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\macroScripts\*.*) DO DEL %%A
|
||||
|
||||
echo Removing media files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\media\*.*) DO DEL %%A
|
||||
|
||||
echo Removing script files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\scripts\*.*) DO DEL %%A
|
||||
|
||||
echo Removing css files
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\css\*.*) DO DEL %%A
|
||||
|
||||
echo Removing Courier files
|
||||
del ..\src\Umbraco.Web.UI\config\courier.config
|
||||
del ..\src\Umbraco.Web.UI\umbraco\images\tray\courier.jpg
|
||||
rmdir "..\src\Umbraco.Web.UI\umbraco\plugins\courier\" /S /Q
|
||||
|
||||
echo Removing Contour files
|
||||
del ..\src\Umbraco.Web.UI\umbraco\images\tray\contour.png
|
||||
FOR %%A IN (..\src\Umbraco.Web.UI\umbraco\images\umbraco\icon_*.*) DO DEL %%A
|
||||
rmdir "..\src\Umbraco.Web.UI\umbraco\plugins\umbracoContour\" /S /Q
|
||||
del ..\src\Umbraco.Web.UI\umbraco\xslt\templates\UmbracoContour*.* /S /Q
|
||||
rmdir "..\src\Umbraco.Web.UI\usercontrols\umbracoContour\" /S /Q
|
||||
|
||||
echo Start with a clean web.config
|
||||
copy ..\src\Umbraco.Web.UI\web.Template.config ..\src\Umbraco.Web.UI\web.config /Y
|
||||
|
||||
echo Start with a clean web.config
|
||||
copy ..\src\Umbraco.Web.UI\web.Template.config ..\src\Umbraco.Web.UI\web.config /Y
|
||||
|
||||
echo "Umbraco install reverted to clean install"
|
||||
pause
|
||||
exit
|
||||
|
||||
|
||||
|
||||
:exit
|
||||
exit
|
||||
@@ -5,7 +5,7 @@
|
||||
# . "$PSScriptRoot\build-bootstrap.ps1"
|
||||
|
||||
# THIS FILE IS DISTRIBUTED AS PART OF UMBRACO.BUILD
|
||||
# DO NOT MODIFY IT - ALWAYS USED THE COMMON VERSION
|
||||
# DO NOT MODIFY IT - ALWAYS USED THE COMMON VERSION
|
||||
|
||||
# ################################################################
|
||||
# BOOTSTRAP
|
||||
@@ -41,12 +41,28 @@
|
||||
throw "Failed to locate NuGet.exe."
|
||||
}
|
||||
|
||||
# NuGet notes
|
||||
# As soon as we use -ConfigFile, NuGet uses that file, and only that file, and does not
|
||||
# merge configuration from system level. See comments in NuGet.Client solution, class
|
||||
# NuGet.Configuration.Settings, method LoadDefaultSettings.
|
||||
# For NuGet to merge configurations, it needs to "find" the file in the current directory,
|
||||
# or above. Which means we cannot really use -ConfigFile but instead have to have Umbraco's
|
||||
# NuGet.config file at root, and always run NuGet.exe while at root or in a directory below
|
||||
# root.
|
||||
|
||||
$solutionRoot = "$scriptRoot\.."
|
||||
$testPwd = [System.IO.Path]::GetFullPath($pwd.Path) + "\"
|
||||
$testRoot = [System.IO.Path]::GetFullPath($solutionRoot) + "\"
|
||||
if (-not $testPwd.ToLower().StartsWith($testRoot.ToLower()))
|
||||
{
|
||||
throw "Cannot run outside of the solution's root."
|
||||
}
|
||||
|
||||
# get the build system
|
||||
if (-not $local)
|
||||
{
|
||||
$solutionRoot = "$scriptRoot\.."
|
||||
$nugetConfig = @{$true="$solutionRoot\src\NuGet.config.user";$false="$solutionRoot\src\NuGet.config"}[(test-path "$solutionRoot\src\NuGet.config.user")]
|
||||
&$nuget install Umbraco.Build -OutputDirectory $scriptTemp -Verbosity quiet -PreRelease -ConfigFile $nugetConfig
|
||||
$params = "-OutputDirectory", $scriptTemp, "-Verbosity", "quiet", "-PreRelease"
|
||||
&$nuget install Umbraco.Build @params
|
||||
if (-not $?) { throw "Failed to download Umbraco.Build." }
|
||||
}
|
||||
|
||||
@@ -63,7 +79,7 @@
|
||||
|
||||
# at that point the build.ps1 script must boot the build system
|
||||
# eg
|
||||
# $ubuild.Boot($ubuildPath.FullName, [System.IO.Path]::GetFullPath("$scriptRoot\.."),
|
||||
# $ubuild.Boot($ubuildPath.FullName, [System.IO.Path]::GetFullPath("$scriptRoot\.."),
|
||||
# @{ Local = $local; With7Zip = $false; WithNode = $false },
|
||||
# @{ continue = $continue })
|
||||
# if (-not $?) { throw "Failed to boot the build system." }
|
||||
@@ -73,4 +89,4 @@
|
||||
# Write-Host "Umbraco.Whatever Build"
|
||||
# Write-Host "Umbraco.Build v$($ubuild.BuildVersion)"
|
||||
|
||||
# eof
|
||||
# eof
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
$global:node_path = $env:path
|
||||
$nodePath = $this.BuildEnv.NodePath
|
||||
$gitExe = (Get-Command git).Source
|
||||
if (-not $gitExe) { $gitExe = (Get-Command git).Path }
|
||||
$gitPath = [System.IO.Path]::GetDirectoryName($gitExe)
|
||||
$env:path = "$nodePath;$gitPath"
|
||||
|
||||
@@ -235,7 +236,6 @@
|
||||
/t:Build `
|
||||
/tv:"$($this.BuildEnv.VisualStudio.ToolsVersion)" `
|
||||
/p:UmbracoBuild=True `
|
||||
/p:NugetPackages="$($this.SolutionRoot)\src\packages" `
|
||||
> $log
|
||||
|
||||
if (-not $?) { throw "Failed to compile tests." }
|
||||
@@ -298,11 +298,15 @@
|
||||
|
||||
# copy libs
|
||||
Write-Host "Copy SqlCE libraries"
|
||||
$nugetPackages = [System.Environment]::ExpandEnvironmentVariables("%userprofile%\.nuget\packages")
|
||||
$this.CopyFiles("$nugetPackages\SqlServerCE\4.0.0.1", "*.*", "$tmp\bin", `
|
||||
{ -not $_.Extension.StartsWith(".nu") -and -not $_.RelativeName.StartsWith("lib\") })
|
||||
$this.CopyFiles("$nugetPackages\SqlServerCE\4.0.0.1", "*.*", "$tmp\WebApp\bin", `
|
||||
{ -not $_.Extension.StartsWith(".nu") -and -not $_.RelativeName.StartsWith("lib\") })
|
||||
$nugetPackages = $env:NUGET_PACKAGES
|
||||
if (-not $nugetPackages)
|
||||
{
|
||||
$nugetPackages = [System.Environment]::ExpandEnvironmentVariables("%userprofile%\.nuget\packages")
|
||||
}
|
||||
$this.CopyFiles("$nugetPackages\umbraco.sqlserverce\4.0.0.1\runtimes\win-x86\native", "*.*", "$tmp\bin\x86")
|
||||
$this.CopyFiles("$nugetPackages\umbraco.sqlserverce\4.0.0.1\runtimes\win-x64\native", "*.*", "$tmp\bin\amd64")
|
||||
$this.CopyFiles("$nugetPackages\umbraco.sqlserverce\4.0.0.1\runtimes\win-x86\native", "*.*", "$tmp\WebApp\bin\x86")
|
||||
$this.CopyFiles("$nugetPackages\umbraco.sqlserverce\4.0.0.1\runtimes\win-x64\native", "*.*", "$tmp\WebApp\bin\amd64")
|
||||
|
||||
# copy Belle
|
||||
Write-Host "Copy Belle"
|
||||
@@ -343,13 +347,13 @@
|
||||
$this.TempStoreFile("$($this.SolutionRoot)\src\Umbraco.Web.UI\web.config")
|
||||
Write-Host "Create clean web.config"
|
||||
$this.CopyFile("$($this.SolutionRoot)\src\Umbraco.Web.UI\web.Template.config", "$($this.SolutionRoot)\src\Umbraco.Web.UI\web.config")
|
||||
|
||||
|
||||
Write-host "Set environment"
|
||||
$env:UMBRACO_VERSION=$this.Version.Semver.ToString()
|
||||
$env:UMBRACO_RELEASE=$this.Version.Release
|
||||
$env:UMBRACO_COMMENT=$this.Version.Comment
|
||||
$env:UMBRACO_BUILD=$this.Version.Build
|
||||
|
||||
|
||||
if ($args -and $args[0] -eq "vso")
|
||||
{
|
||||
Write-host "Set VSO environment"
|
||||
@@ -373,15 +377,13 @@
|
||||
Write-Host "Add web.config transforms to NuGet package"
|
||||
mv "$($this.BuildTemp)\WebApp\Views\Web.config" "$($this.BuildTemp)\WebApp\Views\Web.config.transform"
|
||||
|
||||
# fixme - that one does not exist in .bat build either?
|
||||
#mv "$($this.BuildTemp)\WebApp\Xslt\Web.config" "$($this.BuildTemp)\WebApp\Xslt\Web.config.transform"
|
||||
})
|
||||
|
||||
$ubuild.DefineMethod("RestoreNuGet",
|
||||
{
|
||||
Write-Host "Restore NuGet"
|
||||
Write-Host "Logging to $($this.BuildTemp)\nuget.restore.log"
|
||||
&$this.BuildEnv.NuGet restore "$($this.SolutionRoot)\src\Umbraco.sln" -ConfigFile $this.BuildEnv.NuGetConfig > "$($this.BuildTemp)\nuget.restore.log"
|
||||
&$this.BuildEnv.NuGet restore "$($this.SolutionRoot)\src\Umbraco.sln" > "$($this.BuildTemp)\nuget.restore.log"
|
||||
if (-not $?) { throw "Failed to restore NuGet packages." }
|
||||
})
|
||||
|
||||
@@ -391,11 +393,6 @@
|
||||
|
||||
Write-Host "Create NuGet packages"
|
||||
|
||||
# see https://docs.microsoft.com/en-us/nuget/schema/nuspec
|
||||
# note - warnings about SqlCE native libs being outside of 'lib' folder,
|
||||
# nothing much we can do about it as it's intentional yet there does not
|
||||
# seem to be a way to disable the warning
|
||||
|
||||
&$this.BuildEnv.NuGet Pack "$nuspecs\UmbracoCms.Core.nuspec" `
|
||||
-Properties BuildTmp="$($this.BuildTemp)" `
|
||||
-Version "$($this.Version.Semver.ToString())" `
|
||||
@@ -433,6 +430,8 @@
|
||||
|
||||
$ubuild.DefineMethod("Build",
|
||||
{
|
||||
$error.Clear()
|
||||
|
||||
$this.PrepareBuild()
|
||||
if ($this.OnError()) { return }
|
||||
$this.RestoreNuGet()
|
||||
|
||||
@@ -6,19 +6,13 @@ Umbraco Cms Build
|
||||
|
||||
To build Umbraco, fire PowerShell and move to Umbraco's repository root (the directory that contains `src`, `build`, `README.md`...). There, trigger the build with the following command:
|
||||
|
||||
build\build.ps1
|
||||
build/build.ps1
|
||||
|
||||
By default, this builds the current version. It is possible to specify a different version as a parameter to the build script:
|
||||
|
||||
build\build.ps1 7.6.44
|
||||
|
||||
Valid version strings are defined in the `Set-UmbracoVersion` documentation below.
|
||||
|
||||
## PowerShell Quirks
|
||||
|
||||
There is a good chance that running `build.ps1` ends up in error, with messages such as
|
||||
|
||||
>The file ...\build\build.ps1 is not digitally signed. You cannot run this script on the current system. For more information about running scripts and setting execution policy, see about_Execution_Policies.
|
||||
>The file ...\build.ps1 is not digitally signed. You cannot run this script on the current system. For more information about running scripts and setting execution policy, see about_Execution_Policies.
|
||||
|
||||
PowerShell has *Execution Policies* that may prevent the script from running. You can check the current policies with:
|
||||
|
||||
@@ -42,7 +36,7 @@ Alternatively, you can do it at machine level, from within an elevated PowerShel
|
||||
|
||||
And *then* the script should run. It *might* however still complain about executing scripts, with messages such as:
|
||||
|
||||
>Security warning - Run only scripts that you trust. While scripts from the internet can be useful, this script can potentially harm your computer. If you trust this script, use the Unblock-File cmdlet to allow the script to run without this warning message. Do you want to run ...\build\build.ps1?
|
||||
>Security warning - Run only scripts that you trust. While scripts from the internet can be useful, this script can potentially harm your computer. If you trust this script, use the Unblock-File cmdlet to allow the script to run without this warning message. Do you want to run ...\build.ps1?
|
||||
[D] Do not run [R] Run once [S] Suspend [?] Help (default is "D"):
|
||||
|
||||
This is usually caused by the scripts being *blocked*. And that usually happens when the source code has been downloaded as a Zip file. When Windows downloads Zip files, they are marked as *blocked* (technically, they have a Zone.Identifier alternate data stream, with a value of "3" to indicate that they were downloaded from the Internet). And when such a Zip file is un-zipped, each and every single file is also marked as blocked.
|
||||
@@ -51,34 +45,20 @@ The best solution is to unblock the Zip file before un-zipping: right-click the
|
||||
|
||||
PS> Get-ChildItem -Recurse *.* | Unblock-File
|
||||
|
||||
## Notes
|
||||
## Git Quirks
|
||||
|
||||
Git might have issues dealing with long file paths during build. You may want/need to enable `core.longpaths` support (see [this page](https://github.com/msysgit/msysgit/wiki/Git-cannot-create-a-file-or-directory-with-a-long-path) for details).
|
||||
|
||||
If PowerShell does not execute the script due to a security error, you may have to run the following command from an administrator prompt:
|
||||
# Build Infrastructure
|
||||
|
||||
Set-ExecutionPolicy -ExecutionPolicy RemoteSigned
|
||||
The Umbraco Build infrastructure relies on a PowerShell object. The object can be retrieved with:
|
||||
|
||||
# Build
|
||||
$ubuild = build/build.ps1 -get
|
||||
|
||||
The Umbraco Build solution relies on a PowerShell module. The module needs to be imported into PowerShell. From within Umbraco's repository root:
|
||||
|
||||
build\build.ps1 -ModuleOnly
|
||||
|
||||
Or the abbreviated form:
|
||||
|
||||
build\build.ps1 -mo
|
||||
|
||||
Once the module has been imported, a set of commands are added to PowerShell.
|
||||
|
||||
## Get-UmbracoBuildEnv
|
||||
|
||||
Gets the Umbraco build environment ie NuGet, Semver, Visual Studio, etc. Downloads things that can be downloaded such as NuGet. Examples:
|
||||
|
||||
$uenv = Get-UmbracoBuildEnv
|
||||
Write-Host $uenv.SolutionRoot
|
||||
&$uenv.NuGet help
|
||||
The object exposes various properties and methods that can be used to fine-grain build Umbraco. Some, but not all, of them are detailed below.
|
||||
|
||||
## Properties
|
||||
|
||||
The object exposes the following properties:
|
||||
|
||||
* `SolutionRoot`: the absolute path to the solution root
|
||||
@@ -96,11 +76,11 @@ The Visual Studio object is `null` when Visual Studio has not been detected (eg
|
||||
* `Minor`: Visual Studio minor version
|
||||
* `MsBUild`: the absolute path to the MsBuild executable
|
||||
|
||||
## Get-UmbracoVersion
|
||||
## GetUmbracoVersion
|
||||
|
||||
Gets an object representing the current Umbraco version. Example:
|
||||
|
||||
$v = Get-UmbracoVersion
|
||||
$v = $ubuild.GetUmbracoVersion()
|
||||
Write-Host $v.Semver
|
||||
|
||||
The object exposes the following properties:
|
||||
@@ -110,28 +90,24 @@ The object exposes the following properties:
|
||||
* `Comment`: the pre release part of the version (eg `alpha02`)
|
||||
* `Build`: the build number part of the version (eg `1234`)
|
||||
|
||||
## Set-UmbracoVersion
|
||||
## SetUmbracoVersion
|
||||
|
||||
Modifies Umbraco files with the new version.
|
||||
|
||||
>This entirely replaces the legacy `UmbracoVersion.txt` file.
|
||||
>This entirely replaces the legacy `UmbracoVersion.txt` file. Do *not* edit version infos in files.
|
||||
|
||||
The version must be a valid semver version. It can include a *pre release* part (eg `alpha02`) and/or a *build number* (eg `1234`). Examples:
|
||||
|
||||
Set-UmbracoVersion 7.6.33
|
||||
Set-UmbracoVersion 7.6.33-alpha02
|
||||
Set-UmbracoVersion 7.6.33+1234
|
||||
Set-UmbracoVersion 7.6.33-beta05+5678
|
||||
$ubuild.SetUmbracoVersion("7.6.33")
|
||||
$ubuild.SetUmbracoVersion("7.6.33-alpha.2")
|
||||
$ubuild.SetUmbracoVersion("7.6.33+1234")
|
||||
$ubuild.SetUmbracoVersion("7.6.33-beta.5+5678")
|
||||
|
||||
Note that `Set-UmbracoVersion` enforces a slightly more restrictive naming scheme than what semver would tolerate. The pre release part can only be composed of a-z and 0-9, therefore `alpha033` is considered valid but not `alpha.033` nor `alpha033-preview` nor `RC2` (would need to be lowercased `rc2`).
|
||||
|
||||
>It is considered best to add trailing zeroes to pre releases, else NuGet gets the order of versions wrong. So if you plan to have more than 10, but no more that 100 alpha versions, number the versions `alpha00`, `alpha01`, etc.
|
||||
|
||||
## Build-Umbraco
|
||||
## Build
|
||||
|
||||
Builds Umbraco. Temporary files are generated in `build.tmp` while the actual artifacts (zip files, NuGet packages...) are produced in `build.out`. Example:
|
||||
|
||||
Build-Umbraco
|
||||
$ubuild.Build()
|
||||
|
||||
Some log files, such as MsBuild logs, are produced in `build.tmp` too. The `build` directory should remain clean during a build.
|
||||
|
||||
@@ -185,6 +161,4 @@ We should increment versions as soon as a version is released. Ie, as soon as `7
|
||||
|
||||
NuGet / NuSpec consistency checks are performed in tests. We should move it so it is done as part of the PowerShell script even before we try to compile and run the tests.
|
||||
|
||||
There are still a few commands in `build` (to build docs, install Git or cleanup the install) that will need to be migrated to PowerShell.
|
||||
|
||||
/eof
|
||||
@@ -0,0 +1,34 @@
|
||||
Umbraco Cms Clear
|
||||
--
|
||||
----
|
||||
|
||||
Once the solution has been used to run a site, one may want to "reset" the solution in order to run a fresh new site again.
|
||||
|
||||
## Fast
|
||||
|
||||
At the very minimum, you want
|
||||
|
||||
git clean -Xdf src/Umbraco.Web.UI/App_Data
|
||||
rm src/Umbraco.Web.UI/web.config
|
||||
|
||||
Then, a simple 'Rebuild All' in Visual Studio will recreate a fresh `web.config` but should be quite fast (since it does not really need to rebuild anything).
|
||||
|
||||
The `clean` Git command force (`-f`) removes (`-X`, note the capital X) all files and directories (`-d`) that are ignored by Git.
|
||||
|
||||
This will leave medias and views around, but in most cases, it will be enough.
|
||||
|
||||
## More
|
||||
|
||||
To perform a more complete clear, you will want to also delete the content of the media, views, masterpages, scripts... directories.
|
||||
|
||||
## Full
|
||||
|
||||
The following command will force remove all untracked files and directories, be they ignored by Git or not. Combined with `git reset` it can recreate a pristine working directory.
|
||||
|
||||
git clean -xdf .
|
||||
|
||||
## Docs
|
||||
|
||||
See
|
||||
* git [clean](<https://git-scm.com/docs/git-clean>)
|
||||
* git [reset](<https://git-scm.com/docs/git-reset>)
|
||||
@@ -0,0 +1,32 @@
|
||||
# Code Of Conduct
|
||||
|
||||
Our informal code of conduct concentrates on the values we, as Umbraco HQ, have set for ourselves and for our community. We expect you to be a friend.
|
||||
Instead of listing out all the exact "do's" and "don't's" we want to challenge you to think about our values and apply them:
|
||||
|
||||
If there's a need to talk to Umbraco HQ about anything, please make sure to send a mail to [Sebastiaan Janssen - sj@umbraco.dk](mailto:sj@umbraco.dk).
|
||||
|
||||
## Be a Friend
|
||||
|
||||
We welcome and thank you for registering at Our Umbraco. Find below the values that govern Umbraco and which you accept by using Our Umbraco.
|
||||
|
||||
## Trust
|
||||
|
||||
Assume positive intent and try to understand before being understood.
|
||||
|
||||
## Respect
|
||||
|
||||
Treat others as you would like to be treated.
|
||||
|
||||
This also goes for treating the HQ with respect. For example: don’t promote products on [our.umbraco.org](https://our.umbraco.org) that directly compete with our commercial offerings which enables us to work for a sustainable Umbraco.
|
||||
|
||||
## Open
|
||||
|
||||
Be honest and straightforward. Tell it as it is. Share thoughts and knowledge and engage in collaboration.
|
||||
|
||||
## Hungry
|
||||
|
||||
Don't rest on your laurels and never accept the status quo. Contribute and give back to fellow Umbracians.
|
||||
|
||||
## Friendly
|
||||
|
||||
Don’t judge upon mistakes made but rather upon the speed and quality with which mistakes are corrected. Friendly posts and contributions generate smiles and builds long lasting relationships.
|
||||
@@ -0,0 +1,99 @@
|
||||
_Looking for Umbraco version 8? [Click here](https://github.com/umbraco/Umbraco-CMS/blob/temp8/docs/CONTRIBUTING.md) to go to the v8 branch_
|
||||
# Contributing to Umbraco CMS
|
||||
|
||||
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
|
||||
|
||||
The following is a set of guidelines for contributing to Umbraco CMS.
|
||||
|
||||
These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
|
||||
|
||||
Remember, we're a friendly bunch and are happy with whatever contribution you might provide. Below are guidelines for success that we've gathered over the years. If you choose to ignore them then we still love you 💖.
|
||||
|
||||
## Contributing code changes
|
||||
|
||||
This document gives you a quick overview on how to get started, we will link to in-depth documentation throughout if you need some more background info.
|
||||
|
||||
|
||||
## Guidelines for contributions we welcome
|
||||
|
||||
Not all changes are wanted so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes and we'll be nice about it, thanking you for spending your valueable time.
|
||||
|
||||
We have [documented what we consider small and large changes](CONTRIBUTION_GUIDELINES.md), make sure to talk to us before making large changes.
|
||||
|
||||
Remember, if an issue is in the `Up for grabs` list or you've asked for some feedback before you sent us a PR, your PR will not be closed as unwanted.
|
||||
|
||||
## How do I begin?
|
||||
|
||||
Great question! The short version goes like this:
|
||||
|
||||
* **Fork** - create a fork of [`Umbraco-CMS` on GitHub](https://github.com/umbraco/Umbraco-CMS)
|
||||
|
||||

|
||||
|
||||
* **Clone** - when GitHub has created your fork, you can clone it in your favorite Git tool
|
||||
|
||||

|
||||
|
||||
* **Build** - build your fork of Umbraco locally as described in [building Umbraco from source code](BUILD.md)
|
||||
* **Change** - make your changes, experiment, have fun, explore and learn, and don't be afraid. We welcome all contributions and will [happily give feedback](#questions)
|
||||
* **Commit** - done? Yay! 🎉 It is recommended to create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-U4-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `U4-12345`
|
||||
* **Push** - great, now you can push the changes up to your fork on GitHub
|
||||
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
|
||||
|
||||

|
||||
|
||||
### Further reading
|
||||
|
||||
At this point you might want to [read on about contributing in depth](CONTRIBUTING_DETAILED.md).
|
||||
|
||||
### Reviews
|
||||
|
||||
You've sent us your first contribution, congratulations! Now what?
|
||||
|
||||
The [pull request team](#the-pr-team) can now start reviewing your proposed changes and give you feedback on them. If it's not perfect, we'll either fix up what we need or we can request you to make some additional changes.
|
||||
|
||||
We have [a process in place which you can read all about](REVIEW_PROCESS.md). The very abbreviated version is:
|
||||
|
||||
- Your PR will get a reply within 48 hours
|
||||
- An in-depth reply will be added within at most 2 weeks
|
||||
- The PR will be either merged or rejected within at most 4 weeks
|
||||
- Sometimes it is difficult to meet these timelines and we'll talk to you
|
||||
|
||||
## Styleguides
|
||||
|
||||
To be honest, we don't like rules very much. We trust you have the best of intentions and we encourage you to create working code. If it doesn't look perfect then we'll happily help clean it up.
|
||||
|
||||
That said, the Umbraco development team likes to follow the hints that ReSharper gives us (no problem if you don't have this installed) and we've added a `.editorconfig` file so that Visual Studio knows what to do with whitespace, line endings, etc.
|
||||
|
||||
## The PR team
|
||||
|
||||
The pull request team consists of a member of Umbraco HQ, [Sebastiaan](https://github.com/nul800sebastiaan), who gets assistance from the following community members
|
||||
|
||||
- [Anders Bjerner](https://github.com/abjerner)
|
||||
- [Dave Woestenborghs](https://github.com/dawoe)
|
||||
- [Emma Burstow](https://github.com/emmaburstow)
|
||||
- [Kyle Weems](https://github.com/cssquirrel)
|
||||
- [Poornima Nayar](https://github.com/poornimanayar)
|
||||
|
||||
These wonderful volunteers will provide you with a first reply to your PR, review and test out your changes and might ask more questions. After that they'll let Umbraco HQ know if everything seems okay.
|
||||
|
||||
## Questions?
|
||||
|
||||
You can get in touch with [the PR team](#the-pr-team) in multiple ways, we love open conversations and we are a friendly bunch. No question you have is stupid. Any questions you have usually helps out multiple people with the same question. Ask away:
|
||||
|
||||
- If there's an existing issue on the issue tracker then that's a good place to leave questions and discuss how to start or move forward
|
||||
- Unsure where to start? Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.org/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely
|
||||
- We're also [active in the Gitter chatroom](https://gitter.im/umbraco/Umbraco-CMS)
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project and everyone participating in it is governed by the [our Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [Sebastiaan Janssen - sj@umbraco.dk](mailto:sj@umbraco.dk).
|
||||
|
||||
|
||||
## Contributing to Umbraco, in depth
|
||||
|
||||
There are other ways to contribute, and there's a few more things that you might be wondering about. We will answer the [most common questions and ways to contribute in our detailed documentation](CONTRIBUTING_DETAILED.md).
|
||||
|
||||
## Credits
|
||||
|
||||
This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
|
||||
@@ -1,17 +1,11 @@
|
||||
# Contributing to Umbraco CMS
|
||||
# Contributing in detail
|
||||
|
||||
👍🎉 First off, thanks for taking the time to contribute! 🎉👍
|
||||
There's more than one way to contribute to Umbraco, there's some more suggestions below.
|
||||
|
||||
The following is a set of guidelines for contributing to Umbraco CMS.
|
||||
|
||||
These are mostly guidelines, not rules. Use your best judgment, and feel free to propose changes to this document in a pull request.
|
||||
|
||||
Remember, we're a friendly bunch and are happy with whatever contribution you might provide. Below are guidelines for success that we've gathered over the years. If you choose to ignore them then we still love you 💖.
|
||||
When contributing code to Umbraco there's plenty of things you'll want to know, skip down to [What should I know before I get started](#what-should-i-know-before-i-get-started) for the answers to your burning questions.
|
||||
|
||||
#### Table Of Contents
|
||||
|
||||
[Code of Conduct](#code-of-conduct)
|
||||
|
||||
[How Can I Contribute?](#how-can-i-contribute)
|
||||
* [Reporting Bugs](#reporting-bugs)
|
||||
* [Suggesting Enhancements](#suggesting-enhancements)
|
||||
@@ -26,22 +20,12 @@ Remember, we're a friendly bunch and are happy with whatever contribution you mi
|
||||
* [Building Umbraco from source code](#building-umbraco-from-source-code)
|
||||
* [Keeping your Umbraco fork in sync with the main repository](#keeping-your-umbraco-fork-in-sync-with-the-main-repository)
|
||||
|
||||
[How do I even begin?](#how-do-i-even-begin)
|
||||
|
||||
[Problems?](#problems)
|
||||
|
||||
[Credits](#credits)
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
This project and everyone participating in it is governed by the [our Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. Please report unacceptable behavior to [Sebastiaan Janssen - sj@umbraco.dk](mailto:sj@umbraco.dk).
|
||||
|
||||
## How Can I Contribute?
|
||||
|
||||
### Reporting Bugs
|
||||
This section guides you through submitting a bug report for Umbraco CMS. Following these guidelines helps maintainers and the community understand your report 📝, reproduce the behavior 💻 💻, and find related reports 🔎.
|
||||
|
||||
Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](ISSUE_TEMPLATE.md), the information it asks for helps us resolve issues faster.
|
||||
Before creating bug reports, please check [this list](#before-submitting-a-bug-report) as you might find out that you don't need to create one. When you are creating a bug report, please [include as many details as possible](#how-do-i-submit-a-good-bug-report). Fill out [the required template](http://issues.umbraco.org/issues#newissue=61-30118), the information it asks for helps us resolve issues faster.
|
||||
|
||||
> **Note:** If you find a **Closed** issue that seems like it is the same thing that you're experiencing, open a new issue and include a link to the original issue in the body of your new one.
|
||||
|
||||
@@ -52,7 +36,7 @@ Before creating bug reports, please check [this list](#before-submitting-a-bug-r
|
||||
* **Use the Google**. Whatever you're experiencing, Google it plus "Umbraco" - usually you can get some pretty good hints from the search results, including open issues and further troubleshooting hints.
|
||||
* If you do find and existing issue has **and the issue is still open**, add a comment to the existing issue if you have additional information. If you have the same problem and no new info to add, just "star" the issue.
|
||||
|
||||
Explain the problem and include additional details to help maintainers reproduce the problem. The following is a long description which we've boiled down into a few very simple question in the issue tracker when you create a new issue. We're listing the following hints to indicate that the most successful reports usually have a lot of this ground covered:
|
||||
Explain the problem and include additional details to help maintainers reproduce the problem. The following is a long description which we've boiled down into a few very simple questions in the issue tracker when you create a new issue. We're listing the following hints to indicate that the most successful reports usually have a lot of this ground covered:
|
||||
|
||||
* **Use a clear and descriptive title** for the issue to identify the problem.
|
||||
* **Describe the exact steps which reproduce the problem** in as many details as possible. For example, start by explaining which steps you took in the backoffice to get to a certain undesireable result, e.g. you created a document type, inherting 3 levels deep, added a certain datatype, tried to save it and you got an error.
|
||||
@@ -74,7 +58,7 @@ Include details about your configuration and environment:
|
||||
|
||||
### Suggesting Enhancements
|
||||
|
||||
This section guides you through submitting an enhancement suggestion for Atom, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion 📝 and find related suggestions 🔎.
|
||||
This section guides you through submitting an enhancement suggestion for Umbraco, including completely new features and minor improvements to existing functionality. Following these guidelines helps maintainers and the community understand your suggestion 📝 and find related suggestions 🔎.
|
||||
|
||||
Most of the suggestions in the [reporting bugs](#reporting-bugs) section also count for suggesting enhancements.
|
||||
|
||||
@@ -100,6 +84,10 @@ The most successful pull requests usually look a like this:
|
||||
|
||||
Again, these are guidelines, not strict requirements.
|
||||
|
||||
## Making changes after the PR was opened
|
||||
|
||||
If you make the corrections we ask for in the same branch and push them to your fork again, the pull request automatically updates with the additional commit(s) so we can review it again. If all is well, we'll merge the code and your commits are forever part of Umbraco!
|
||||
|
||||
## Styleguides
|
||||
|
||||
To be honest, we don't like rules very much. We trust you have the best of intentions and we encourage you to create working code. If it doesn't look perfect then we'll happily help clean it up.
|
||||
@@ -135,7 +123,7 @@ To find the general areas of something you're looking to fix or improve, have a
|
||||
|
||||
We like to use [Gitflow as much as possible](https://jeffkreeftmeijer.com/git-flow/), don't worry if you are not familiar with it. The most important thing you need to know is that when you fork the Umbraco repository, the default branch is set to something, usually `dev-v7`. Whatever the default is, that's where we'd like you to target your contributions.
|
||||
|
||||

|
||||

|
||||
|
||||
### Building Umbraco from source code
|
||||
|
||||
@@ -143,7 +131,7 @@ The easiest way to get started is to run `build.bat` which will build both the b
|
||||
|
||||
Alternatively, you can open `src\umbraco.sln` in Visual Studio 2017 ([the community edition is free](https://www.visualstudio.com/thank-you-downloading-visual-studio/?sku=Community&rel=15) for you to use to contribute to Open Source projects). In Visual Studio, find the Task Runner Explorer (in the View menu under Other Windows) and run the build task under the gulpfile.
|
||||
|
||||

|
||||

|
||||
|
||||
After this build completes, you should be able to hit `F5` in Visual Studio to build and run the project. A IISExpress webserver will start and the Umbraco installer will pop up in your browser, follow the directions there to get a working Umbraco install up and running.
|
||||
|
||||
@@ -168,40 +156,4 @@ git rebase upstream/dev-v7
|
||||
|
||||
In this command we're syncing with the `dev-v7` branch, but you can of course choose another one if needed.
|
||||
|
||||
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
|
||||
|
||||
## How do I even begin?
|
||||
|
||||
Great question! The short version goes like this:
|
||||
|
||||
* **Fork** - create a fork of [`Umbraco-CMS` on GitHub](https://github.com/umbraco/Umbraco-CMS)
|
||||
|
||||

|
||||
|
||||
* **Clone** - when GitHub has created your fork, you can clone it in your favorite Git tool
|
||||
|
||||

|
||||
|
||||
* **Build** - build your fork of Umbraco locally as described in [building Umbraco from source code](#building-umbraco-from-source-code)
|
||||
* **Change** - make your changes, experiment, have fun, explore and learn, and don't be afraid. We welcome all contributions and will happily give feedback
|
||||
* **Commit** - done? Yay! 🎉 It is recommended to create a new branch now and name it after the issue you're fixing, we usually follow the format: `temp-U4-12345`. This means it's a temporary branch for the particular issue you're working on, in this case `U4-12345`
|
||||
* **Push** - great, now you can push the changes up to your fork on GitHub
|
||||
* **Create pull request** - exciting! You're ready to show us your changes (or not quite ready, you just need some feedback to progress). GitHub has picked up on the new branch you've pushed and will offer to create a Pull Request. Click that green button and away you go.
|
||||
|
||||

|
||||
|
||||
The Umbraco development team can now start reviewing your proposed changes and give you feedback on them. If it's not perfect, we'll either fix up what we need or we can request you to make some additional changes.
|
||||
|
||||
If you make the corrections we ask for in the same branch and push them to your fork again, the pull request automatically updates with the additional commit(s) so we can review it again. If all is well, we'll merge the code and your commits are forever part of Umbraco!
|
||||
|
||||
Not all changes are wanted so on occassion we might close a PR without merging it. We will give you feedback why we can't accept your changes at this and we'll be nice about it, thanking you for spending your valueable time.
|
||||
|
||||
Remember, if an issue is in the `Up for grabs` list or you've asked for some feedback before you send us a PR, your PR will not be closed as unwanted.
|
||||
|
||||
## Problems?
|
||||
|
||||
Did something not work as expected? Try leaving a note in the ["Contributing to Umbraco"](https://our.umbraco.org/forum/contributing-to-umbraco-cms/) forum, the team monitors that one closely!
|
||||
|
||||
## Credits
|
||||
|
||||
This contribution guide borrows heavily from the excellent work on [the Atom contribution guide](https://github.com/atom/atom/blob/master/CONTRIBUTING.md). A big [#h5yr](http://h5yr.com/) to them!
|
||||
(More info on how this works: [http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated](http://robots.thoughtbot.com/post/5133345960/keeping-a-git-fork-updated))
|
||||
@@ -0,0 +1,33 @@
|
||||
# Contributing to Umbraco CMS
|
||||
|
||||
When you’re considering creating a pull request for Umbraco CMS, we will categorize them in two different sizes, small and large.
|
||||
|
||||
The process for both sizes is very similar, as [explained in the contribution document](CONTRIBUTING.md#how-do-i-begin).
|
||||
|
||||
## Small PRs
|
||||
Bug fixes and small improvements - can be recognized by seeing a small number of changes and possibly a small number of new files.
|
||||
|
||||
We’re usually able to handle small PRs pretty quickly. A community volunteer will do the initial review and flag it for Umbraco HQ as “community tested”. If everything looks good, it will be merged pretty quickly [as per the described process](REVIEW_PROCESS.md).
|
||||
|
||||
### Up for grabs
|
||||
|
||||
Umbraco HQ will regularly mark newly created issues on the issue tracker with the `Up for grabs` tag. This means that the proposed changes are wanted in Umbraco but the HQ does not have the time to make them at this time. These issues are usually small enough to fit in the "Small PRs" category and we encourage anyone to pick them up and help out.
|
||||
|
||||
If you do start working on something, make sure leave a small comment on the issue saying something like: "I'm working on this". That way other people stumbling upon the issue know they don't need to pick it up, someone already has.
|
||||
|
||||
## Large PRs
|
||||
New features and large refactorings - can be recognized by seeing a large number of changes, plenty of new files, updates to package manager files (NuGet’s packages.config, NPM’s packages.json, etc.).
|
||||
|
||||
We would love to follow the same process for larger PRs but this is not always possible due to time limitations and priorities that need to be aligned. We don’t want to put up any barriers, but this document should set the correct expectations.
|
||||
|
||||
Please make sure to describe your idea in an issue, it helps to put in mockup screenshots or videos.
|
||||
|
||||
If the change makes sense for HQ to include in Umbraco CMS we will leave you some feedback on how we’d like to see it being implemented.
|
||||
|
||||
If a larger pull request is encouraged by Umbraco HQ, the process will be similar to what is described in the [small PRs process](#small-prs) above, we’ll get feedback to you within 14 days. Finalizing and merging the PR might take longer though as it will likely need to be picked up by the development team to make sure everything is in order. We’ll keep you posted on the progress.
|
||||
|
||||
### Pull request or package?
|
||||
|
||||
If it doesn’t fit in CMS right now, we will likely encourage you to make it into a package instead. A package is a great way to check out popularity of a feature, learn how people use it, validate good usability and to fix bugs.
|
||||
|
||||
Eventually, a package could "graduate" to be included in the CMS.
|
||||
@@ -1,45 +1,51 @@
|
||||
Umbraco CMS
|
||||
===========
|
||||
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 443,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
|
||||
|
||||
[](https://vimeo.com/172382998/)
|
||||
|
||||
## Umbraco CMS
|
||||
Umbraco is a free open source Content Management System built on the ASP.NET platform. Our mission is to help you deliver delightful digital experiences by making Umbraco friendly, simpler and social.
|
||||
|
||||
## Watch an introduction video
|
||||
|
||||
[](https://umbraco.tv/videos/umbraco-v7/content-editor/basics/introduction/cms-explanation/)
|
||||
|
||||
## Umbraco - The Friendly CMS
|
||||
|
||||
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box.
|
||||
|
||||
Umbraco is not only loved by developers, but is a content editors dream. Enjoy intuitive editing tools, media management, responsive views and approval workflows to send your content live.
|
||||
|
||||
Used by more than 443,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 220,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
|
||||
|
||||
To view more examples, please visit [https://umbraco.com/why-umbraco/#caseStudies](https://umbraco.com/why-umbraco/#caseStudies)
|
||||
|
||||
## Why Open Source?
|
||||
As an Open Source platform, Umbraco is more than just a CMS. We are transparent with our roadmap for future versions, our incremental sprint planning notes are publicly accessible and community contributions and packages are available for all to use.
|
||||
|
||||
## Trying out Umbraco CMS
|
||||
|
||||
[Umbraco Cloud](https://umbraco.com) is the easiest and fastest way to use Umbraco yet with full support for all your custom .NET code and intergrations. You're up and running in less than a minute and your life will be made easier with automated upgrades and a built-in deployment engine. We offer a free 14 day trial, no credit card needed.
|
||||
|
||||
If you want to DIY you can [download Umbraco](https://our.umbraco.org/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
|
||||
|
||||
## Community
|
||||
|
||||
Our friendly community is available 24/7 at the community hub we call ["Our Umbraco"](https://our.umbraco.org). Our Umbraco feature forums for questions and answers, documentation, downloadable plugins for Umbraco and a rich collection of community resources.
|
||||
|
||||
## Contribute to Umbraco
|
||||
|
||||
Umbraco is contribution focused and community driven. If you want to contribute back to Umbraco please check out our [guide to contributing](CONTRIBUTING.md).
|
||||
|
||||
## Found a bug?
|
||||
|
||||
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](https://our.umbraco.org/contribute/report-an-issue-or-request-a-feature).
|
||||
|
||||
To view existing issues, please visit [http://issues.umbraco.org](http://issues.umbraco.org).
|
||||
_You are browsing the Umbraco v8 branch._
|
||||
|
||||
_Looking for Umbraco version 7? [Click here](https://github.com/umbraco/Umbraco-CMS) to go to the v7 branch._
|
||||
|
||||
_Ready to try out Version 8? [See the quick start guide](V8_GETTING_STARTED.md)._
|
||||
|
||||
Umbraco CMS
|
||||
===========
|
||||
The friendliest, most flexible and fastest growing ASP.NET CMS used by more than 443,000 websites worldwide: [https://umbraco.com](https://umbraco.com)
|
||||
|
||||
[](https://vimeo.com/172382998/)
|
||||
|
||||
## Umbraco CMS
|
||||
Umbraco is a free open source Content Management System built on the ASP.NET platform. Our mission is to help you deliver delightful digital experiences by making Umbraco friendly, simpler and social.
|
||||
|
||||
## Watch an introduction video
|
||||
|
||||
[](https://umbraco.tv/videos/umbraco-v7/content-editor/basics/introduction/cms-explanation/)
|
||||
|
||||
## Umbraco - The Friendly CMS
|
||||
|
||||
For the first time on the Microsoft platform, there is a free user and developer friendly CMS that makes it quick and easy to create websites - or a breeze to build complex web applications. Umbraco has award-winning integration capabilities and supports ASP.NET MVC or Web Forms, including User and Custom Controls, out of the box.
|
||||
|
||||
Umbraco is not only loved by developers, but is a content editors dream. Enjoy intuitive editing tools, media management, responsive views and approval workflows to send your content live.
|
||||
|
||||
Used by more than 443,000 active websites including Carlsberg, Segway, Amazon and Heinz and **The Official ASP.NET and IIS.NET website from Microsoft** ([https://asp.net](https://asp.net) / [https://iis.net](https://iis.net)), you can be sure that the technology is proven, stable and scales. Backed by the team at Umbraco HQ, and supported by a dedicated community of over 220,000 craftspeople globally, you can trust that Umbraco is a safe choice and is here to stay.
|
||||
|
||||
To view more examples, please visit [https://umbraco.com/case-studies-testimonials/](https://umbraco.com/case-studies-testimonials/)
|
||||
|
||||
## Why Open Source?
|
||||
As an Open Source platform, Umbraco is more than just a CMS. We are transparent with our roadmap for future versions, our incremental sprint planning notes are publicly accessible and community contributions and packages are available for all to use.
|
||||
|
||||
## Trying out Umbraco CMS
|
||||
|
||||
[Umbraco Cloud](https://umbraco.com/cloud) is the easiest and fastest way to use Umbraco yet with full support for all your custom .NET code and intergrations. You're up and running in less than a minute and your life will be made easier with automated upgrades and a built-in deployment engine. We offer a free 14 day trial, no credit card needed.
|
||||
|
||||
If you want to DIY you can [download Umbraco](https://our.umbraco.com/download) either as a ZIP file or via NuGet. It's the same version of Umbraco CMS that powers Umbraco Cloud, but you'll need to find a place to host yourself and handling deployments and upgrades is all down to you.
|
||||
|
||||
## Community
|
||||
|
||||
Our friendly community is available 24/7 at the community hub we call ["Our Umbraco"](https://our.umbraco.com). Our Umbraco feature forums for questions and answers, documentation, downloadable plugins for Umbraco and a rich collection of community resources.
|
||||
|
||||
## Contribute to Umbraco
|
||||
|
||||
Umbraco is contribution focused and community driven. If you want to contribute back to Umbraco please check out our [guide to contributing](CONTRIBUTING.md).
|
||||
|
||||
## Found a bug?
|
||||
|
||||
Another way you can contribute to Umbraco is by providing issue reports. For information on how to submit an issue report refer to our [online guide for reporting issues](CONTRIBUTING_DETAILED.md#reporting-bugs).
|
||||
|
||||
To view existing issues, please visit [http://issues.umbraco.org](http://issues.umbraco.org).
|
||||
@@ -0,0 +1,25 @@
|
||||
# Review process
|
||||
|
||||
You're an awesome person and have sent us your contribution in the form of a pull request! It's now time to relax for a bit and wait for our response.
|
||||
|
||||
In order to set some expectations, here's what happens next.
|
||||
|
||||
## Review process
|
||||
|
||||
You will get an initial reply within 48 hours (workdays) to acknowledge that we’ve seen your PR and we’ll pick it up as soon as we can.
|
||||
|
||||
You will get feedback within at most 14 days after opening the PR. You’ll most likely get feedback sooner though. Then there are a few possible outcomes:
|
||||
|
||||
- Your proposed change is awesome! We merge it in and it will be included in the next minor release of Umbraco
|
||||
- If the change is a high priority bug fix, we will cherry-pick it into the next patch release as well so that we can release it as soon as possible
|
||||
- Your proposed change is awesome but needs a bit more work, we’ll give you feedback on the changes we’d like to see
|
||||
- Your proposed change is awesome but.. not something we’re looking to include at this point. We’ll close your PR and the related issue (we’ll be nice about it!)
|
||||
|
||||
## Are you still available?
|
||||
|
||||
We understand you have other things to do and can't just drop everything to help us out.
|
||||
So if we’re asking for your help to improve the PR we’ll wait for two weeks to give you a fair chance to make changes. We’ll ask for an update if we don’t hear back from you after that time.
|
||||
|
||||
If we don’t hear back from you for 4 weeks, we’ll close the PR so that it doesn’t just hang around forever. You’re very welcome to re-open it once you have some more time to spend on it.
|
||||
|
||||
There will be times that we really like your proposed changes and we’ll finish the final improvements we’d like to see ourselves. You still get the credits and your commits will live on in the git repository.
|
||||
@@ -0,0 +1,37 @@
|
||||
## A quick start guide for getting up and runnning with Umbraco v8
|
||||
|
||||
### What you need:
|
||||
|
||||
* [Visual Studio 2017 Community (Free)](https://www.visualstudio.com/vs/community/), or Professional, Enterprise, etc... _(**Minimum of Version 15.7** or higher, this is important, you WILL get issues with lesser versions)_
|
||||
* .NET Framework 4.7.2 installed, get it here: https://www.microsoft.com/net/download/thank-you/net472?survey=false
|
||||
* .NET Framework 4.7.2 developer pack, get it here: https://www.microsoft.com/net/download/thank-you/net472-developer-pack _(be sure this is the ENU file which will be named `NDP472-DevPack-ENU.exe`)_
|
||||
* Clone the Umbraco repository using the `temp8` branch. If your git client doesn't support specifying the branch as you clone then use the command `git clone --single-branch -b temp8 <your fork url>`. _(If you clone the repo using the default v7 branch and then checkout the `temp8` branch you **might** get problems)_
|
||||
|
||||
### Start the solution
|
||||
|
||||
* Open the `/src/umbraco.sln` Visual Studio solution
|
||||
* Start the solution (easiest way is to use `ctrl + F5`)
|
||||
* When the solution is first built this may take some time since it will restore all nuget, npm and bower packages, build the .net solution and also build the angular solution
|
||||
* When the website starts you'll see the Umbraco installer and just follow the prompts
|
||||
* You're all set!
|
||||
|
||||
### Want to run from a zip instead?
|
||||
|
||||
If you just want to try out a few things, you can run the site from a zip file which you can download from here https://github.com/umbraco/Umbraco-CMS/releases/tag/temp8-cg18.
|
||||
|
||||
We recommend running the site with the Visual Studio since you'll be able to remain up to date with the latest source code changes.
|
||||
|
||||
### Making code changes
|
||||
|
||||
* _[The process for making code changes in v8 is the same as v7](https://github.com/umbraco/Umbraco-CMS/blob/dev-v7/docs/CONTRIBUTING.md)_
|
||||
* Any .NET changes you make you just need to compile
|
||||
* Any Angular/JS changes you make you will need to make sure you are running the Gulp build. Easiest way to do this is from within Visual Studio in the `Task Runner Explorer`. You can find this window by pressing `ctrl + q` and typing in `Task Runner Explorer`. In this window you'll see all Gulp tasks, double click on the `dev` task, this will compile the angular solution and start a file watcher, then any html/js changes you make are automatically built.
|
||||
* When making js changes, you should have the chrome developer tools open to ensure that cache is disabled
|
||||
* If you are only making C# changes and are not touching the UI code at all, you can significantly speed up the VS build by adding an empty file specifically called `~/src/preserve.belle`. The UI (Belle) build will then be skipped during a Rebuild.
|
||||
|
||||
### What to work on?
|
||||
|
||||
We are keeping track of [known issues and limitations here](http://issues.umbraco.org/issue/U4-11279). These line items will eventually be turned into actual tasks to be worked on. Feel free to help us keep this list updated if you find issues and even help fix some of these items. If there is a particular item you'd like to help fix please mention this on the task and we'll create a sub task for the item to continue discussion there.
|
||||
|
||||
There's [a list of tasks for v8 that haven't been completed](http://issues.umbraco.org/issues/U4?q=Due+in+version%3A+8.0.0+%23Unresolved+). If you are interested in helping out with any of these please mention this on the task. This list will be constantly updated as we begin to document and design some of the other tasks that still need to get done.
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 27 KiB |
@@ -0,0 +1,5 @@
|
||||
|
||||
- name: Umbraco.Core Documentation
|
||||
href: https://our.umbraco.com/apidocs/csharp/api/Umbraco.Core.html
|
||||
- name: Umbraco.Web Documentation
|
||||
href: https://our.umbraco.com/apidocs/csharp/api/Umbraco.Web.html
|
||||
@@ -1,8 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
|
||||
<add key="umbracocore" value="https://www.myget.org/F/umbracocore/api/v3/index.json" />
|
||||
<add key="examineAppVeyor" value="https://ci.appveyor.com/nuget/examine-f73l6qv0oqfh/" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
@@ -1,20 +1,22 @@
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
[assembly: AssemblyCompany("Umbraco")]
|
||||
[assembly: AssemblyCopyright("Copyright © Umbraco 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: NeutralResourcesLanguage("en-US")]
|
||||
|
||||
// versions
|
||||
// read https://stackoverflow.com/questions/64602/what-are-differences-between-assemblyversion-assemblyfileversion-and-assemblyin
|
||||
|
||||
// this is the ONLY ONE the CLR cares about for compatibility
|
||||
// should change ONLY when "hard" breaking compatibility (manual change)
|
||||
[assembly: AssemblyVersion("8.0.0")]
|
||||
|
||||
// these are FYI and changed automatically
|
||||
[assembly: AssemblyFileVersion("8.0.0")]
|
||||
[assembly: AssemblyInformationalVersion("8.0.0-alpha.32")]
|
||||
using System.Reflection;
|
||||
using System.Resources;
|
||||
|
||||
[assembly: AssemblyCompany("Umbraco")]
|
||||
[assembly: AssemblyCopyright("Copyright © Umbraco 2017")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
[assembly: NeutralResourcesLanguage("en-US")]
|
||||
|
||||
// versions
|
||||
// read https://stackoverflow.com/questions/64602/what-are-differences-between-assemblyversion-assemblyfileversion-and-assemblyin
|
||||
|
||||
// note: do NOT change anything here manually, use the build scripts
|
||||
|
||||
// this is the ONLY ONE the CLR cares about for compatibility
|
||||
// should change ONLY when "hard" breaking compatibility (manual change)
|
||||
[assembly: AssemblyVersion("8.0.0")]
|
||||
|
||||
// these are FYI and changed automatically
|
||||
[assembly: AssemblyFileVersion("8.0.0")]
|
||||
[assembly: AssemblyInformationalVersion("8.0.0-alpha.44")]
|
||||
|
||||
@@ -1,72 +1,72 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
internal static class AssemblyExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the file used to load the assembly
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <returns></returns>
|
||||
public static FileInfo GetAssemblyFile(this Assembly assembly)
|
||||
{
|
||||
var codeBase = assembly.CodeBase;
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
return new FileInfo(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the assembly is the App_Code assembly
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAppCodeAssembly(this Assembly assembly)
|
||||
{
|
||||
if (assembly.FullName.StartsWith("App_Code"))
|
||||
{
|
||||
try
|
||||
{
|
||||
Assembly.Load("App_Code");
|
||||
return true;
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
//this will occur if it cannot load the assembly
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the assembly is the compiled global asax.
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsGlobalAsaxAssembly(this Assembly assembly)
|
||||
{
|
||||
//only way I can figure out how to test is by the name
|
||||
return assembly.FullName.StartsWith("App_global.asax");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the file used to load the assembly
|
||||
/// </summary>
|
||||
/// <param name="assemblyName"></param>
|
||||
/// <returns></returns>
|
||||
public static FileInfo GetAssemblyFile(this AssemblyName assemblyName)
|
||||
{
|
||||
var codeBase = assemblyName.CodeBase;
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
return new FileInfo(path);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
internal static class AssemblyExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Returns the file used to load the assembly
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <returns></returns>
|
||||
public static FileInfo GetAssemblyFile(this Assembly assembly)
|
||||
{
|
||||
var codeBase = assembly.CodeBase;
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
return new FileInfo(path);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the assembly is the App_Code assembly
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsAppCodeAssembly(this Assembly assembly)
|
||||
{
|
||||
if (assembly.FullName.StartsWith("App_Code"))
|
||||
{
|
||||
try
|
||||
{
|
||||
Assembly.Load("App_Code");
|
||||
return true;
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
//this will occur if it cannot load the assembly
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns true if the assembly is the compiled global asax.
|
||||
/// </summary>
|
||||
/// <param name="assembly"></param>
|
||||
/// <returns></returns>
|
||||
public static bool IsGlobalAsaxAssembly(this Assembly assembly)
|
||||
{
|
||||
//only way I can figure out how to test is by the name
|
||||
return assembly.FullName.StartsWith("App_global.asax");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns the file used to load the assembly
|
||||
/// </summary>
|
||||
/// <param name="assemblyName"></param>
|
||||
/// <returns></returns>
|
||||
public static FileInfo GetAssemblyFile(this AssemblyName assemblyName)
|
||||
{
|
||||
var codeBase = assemblyName.CodeBase;
|
||||
var uri = new Uri(codeBase);
|
||||
var path = uri.LocalPath;
|
||||
return new FileInfo(path);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,126 +1,126 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides ways to create attempts.
|
||||
/// </summary>
|
||||
public static class Attempt
|
||||
{
|
||||
// note:
|
||||
// cannot rely on overloads only to differenciate between with/without status
|
||||
// in some cases it will always be ambiguous, so be explicit w/ 'WithStatus' methods
|
||||
|
||||
/// <summary>
|
||||
/// Creates a successful attempt with a result.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The successful attempt.</returns>
|
||||
public static Attempt<TResult> Succeed<TResult>(TResult result)
|
||||
{
|
||||
return Attempt<TResult>.Succeed(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a successful attempt with a result and a status.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
|
||||
/// <param name="status">The status of the attempt.</param>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The successful attempt.</returns>
|
||||
public static Attempt<TResult, TStatus> SucceedWithStatus<TResult, TStatus>(TStatus status, TResult result)
|
||||
{
|
||||
return Attempt<TResult, TStatus>.Succeed(status, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a failed attempt.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <returns>The failed attempt.</returns>
|
||||
public static Attempt<TResult> Fail<TResult>()
|
||||
{
|
||||
return Attempt<TResult>.Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a failed attempt with a result.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The failed attempt.</returns>
|
||||
public static Attempt<TResult> Fail<TResult>(TResult result)
|
||||
{
|
||||
return Attempt<TResult>.Fail(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a failed attempt with a result and a status.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
|
||||
/// <param name="status">The status of the attempt.</param>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The failed attempt.</returns>
|
||||
public static Attempt<TResult, TStatus> FailWithStatus<TResult, TStatus>(TStatus status, TResult result)
|
||||
{
|
||||
return Attempt<TResult, TStatus>.Fail(status, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a failed attempt with a result and an exception.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <param name="exception">The exception causing the failure of the attempt.</param>
|
||||
/// <returns>The failed attempt.</returns>
|
||||
public static Attempt<TResult> Fail<TResult>(TResult result, Exception exception)
|
||||
{
|
||||
return Attempt<TResult>.Fail(result, exception);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a failed attempt with a result, an exception and a status.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
|
||||
/// <param name="status">The status of the attempt.</param>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <param name="exception">The exception causing the failure of the attempt.</param>
|
||||
/// <returns>The failed attempt.</returns>
|
||||
public static Attempt<TResult, TStatus> FailWithStatus<TResult, TStatus>(TStatus status, TResult result, Exception exception)
|
||||
{
|
||||
return Attempt<TResult, TStatus>.Fail(status, result, exception);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a successful or a failed attempt, with a result.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <param name="condition">A value indicating whether the attempt is successful.</param>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The attempt.</returns>
|
||||
public static Attempt<TResult> If<TResult>(bool condition, TResult result)
|
||||
{
|
||||
return Attempt<TResult>.If(condition, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a successful or a failed attempt, with a result.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
|
||||
/// <param name="condition">A value indicating whether the attempt is successful.</param>
|
||||
/// <param name="succStatus">The status of the successful attempt.</param>
|
||||
/// <param name="failStatus">The status of the failed attempt.</param>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The attempt.</returns>
|
||||
public static Attempt<TResult, TStatus> IfWithStatus<TResult, TStatus>(bool condition, TStatus succStatus, TStatus failStatus, TResult result)
|
||||
{
|
||||
return Attempt<TResult, TStatus>.If(condition, succStatus, failStatus, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Provides ways to create attempts.
|
||||
/// </summary>
|
||||
public static class Attempt
|
||||
{
|
||||
// note:
|
||||
// cannot rely on overloads only to differenciate between with/without status
|
||||
// in some cases it will always be ambiguous, so be explicit w/ 'WithStatus' methods
|
||||
|
||||
/// <summary>
|
||||
/// Creates a successful attempt with a result.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The successful attempt.</returns>
|
||||
public static Attempt<TResult> Succeed<TResult>(TResult result)
|
||||
{
|
||||
return Attempt<TResult>.Succeed(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a successful attempt with a result and a status.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
|
||||
/// <param name="status">The status of the attempt.</param>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The successful attempt.</returns>
|
||||
public static Attempt<TResult, TStatus> SucceedWithStatus<TResult, TStatus>(TStatus status, TResult result)
|
||||
{
|
||||
return Attempt<TResult, TStatus>.Succeed(status, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a failed attempt.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <returns>The failed attempt.</returns>
|
||||
public static Attempt<TResult> Fail<TResult>()
|
||||
{
|
||||
return Attempt<TResult>.Fail();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a failed attempt with a result.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The failed attempt.</returns>
|
||||
public static Attempt<TResult> Fail<TResult>(TResult result)
|
||||
{
|
||||
return Attempt<TResult>.Fail(result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a failed attempt with a result and a status.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
|
||||
/// <param name="status">The status of the attempt.</param>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The failed attempt.</returns>
|
||||
public static Attempt<TResult, TStatus> FailWithStatus<TResult, TStatus>(TStatus status, TResult result)
|
||||
{
|
||||
return Attempt<TResult, TStatus>.Fail(status, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a failed attempt with a result and an exception.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <param name="exception">The exception causing the failure of the attempt.</param>
|
||||
/// <returns>The failed attempt.</returns>
|
||||
public static Attempt<TResult> Fail<TResult>(TResult result, Exception exception)
|
||||
{
|
||||
return Attempt<TResult>.Fail(result, exception);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Creates a failed attempt with a result, an exception and a status.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
|
||||
/// <param name="status">The status of the attempt.</param>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <param name="exception">The exception causing the failure of the attempt.</param>
|
||||
/// <returns>The failed attempt.</returns>
|
||||
public static Attempt<TResult, TStatus> FailWithStatus<TResult, TStatus>(TStatus status, TResult result, Exception exception)
|
||||
{
|
||||
return Attempt<TResult, TStatus>.Fail(status, result, exception);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a successful or a failed attempt, with a result.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <param name="condition">A value indicating whether the attempt is successful.</param>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The attempt.</returns>
|
||||
public static Attempt<TResult> If<TResult>(bool condition, TResult result)
|
||||
{
|
||||
return Attempt<TResult>.If(condition, result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a successful or a failed attempt, with a result.
|
||||
/// </summary>
|
||||
/// <typeparam name="TResult">The type of the attempted operation result.</typeparam>
|
||||
/// <typeparam name="TStatus">The type of the attempted operation status.</typeparam>
|
||||
/// <param name="condition">A value indicating whether the attempt is successful.</param>
|
||||
/// <param name="succStatus">The status of the successful attempt.</param>
|
||||
/// <param name="failStatus">The status of the failed attempt.</param>
|
||||
/// <param name="result">The result of the attempt.</param>
|
||||
/// <returns>The attempt.</returns>
|
||||
public static Attempt<TResult, TStatus> IfWithStatus<TResult, TStatus>(bool condition, TStatus succStatus, TStatus failStatus, TResult result)
|
||||
{
|
||||
return Attempt<TResult, TStatus>.If(condition, succStatus, failStatus, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,19 +46,6 @@ namespace Umbraco.Core.Auditing
|
||||
/// </summary>
|
||||
public string Username { get; private set; }
|
||||
|
||||
[Obsolete("Use the method that has the affectedUser parameter instead")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public IdentityAuditEventArgs(AuditEvent action, string ipAddress, int performingUser = -1)
|
||||
{
|
||||
DateTimeUtc = DateTime.UtcNow;
|
||||
Action = action;
|
||||
|
||||
IpAddress = ipAddress;
|
||||
|
||||
PerformingUser = performingUser == -1
|
||||
? GetCurrentRequestBackofficeUserId()
|
||||
: performingUser;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Default constructor
|
||||
|
||||
@@ -1,8 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Web;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
@@ -53,15 +50,6 @@ namespace Umbraco.Core.Cache
|
||||
{
|
||||
}
|
||||
|
||||
[Obsolete("Use the constructor the specifies all dependencies")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public CacheHelper(
|
||||
IRuntimeCacheProvider httpCacheProvider,
|
||||
ICacheProvider staticCacheProvider,
|
||||
ICacheProvider requestCacheProvider)
|
||||
: this(httpCacheProvider, staticCacheProvider, requestCacheProvider, new IsolatedRuntimeCache(t => new ObjectCacheRuntimeCacheProvider()))
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance based on the provided providers
|
||||
@@ -106,317 +94,6 @@ namespace Umbraco.Core.Cache
|
||||
/// </summary>
|
||||
public IsolatedRuntimeCache IsolatedRuntimeCache { get; internal set; }
|
||||
|
||||
#region Legacy Runtime/Http Cache accessors
|
||||
|
||||
/// <summary>
|
||||
/// Clears the item in umbraco's runtime cache
|
||||
/// </summary>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void ClearAllCache()
|
||||
{
|
||||
RuntimeCache.ClearAllCache();
|
||||
IsolatedRuntimeCache.ClearAllCaches();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the item in umbraco's runtime cache with the given key
|
||||
/// </summary>
|
||||
/// <param name="key">Key</param>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void ClearCacheItem(string key)
|
||||
{
|
||||
RuntimeCache.ClearCacheItem(key);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Clears all objects in the System.Web.Cache with the System.Type name as the
|
||||
/// input parameter. (using [object].GetType())
|
||||
/// </summary>
|
||||
/// <param name="typeName">The name of the System.Type which should be cleared from cache ex "System.Xml.XmlDocument"</param>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
public void ClearCacheObjectTypes(string typeName)
|
||||
{
|
||||
RuntimeCache.ClearCacheObjectTypes(typeName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all objects in the System.Web.Cache with the System.Type specified
|
||||
/// </summary>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void ClearCacheObjectTypes<T>()
|
||||
{
|
||||
RuntimeCache.ClearCacheObjectTypes<T>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all cache items that starts with the key passed.
|
||||
/// </summary>
|
||||
/// <param name="keyStartsWith">The start of the key</param>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void ClearCacheByKeySearch(string keyStartsWith)
|
||||
{
|
||||
RuntimeCache.ClearCacheByKeySearch(keyStartsWith);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears all cache items that have a key that matches the regular expression
|
||||
/// </summary>
|
||||
/// <param name="regexString"></param>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void ClearCacheByKeyExpression(string regexString)
|
||||
{
|
||||
RuntimeCache.ClearCacheByKeyExpression(regexString);
|
||||
}
|
||||
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public IEnumerable<T> GetCacheItemsByKeySearch<T>(string keyStartsWith)
|
||||
{
|
||||
return RuntimeCache.GetCacheItemsByKeySearch<T>(keyStartsWith);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a cache item by key, does not update the cache if it isn't there.
|
||||
/// </summary>
|
||||
/// <typeparam name="TT"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public TT GetCacheItem<TT>(string cacheKey)
|
||||
{
|
||||
return RuntimeCache.GetCacheItem<TT>(cacheKey);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets (and adds if necessary) an item from the cache with all of the default parameters
|
||||
/// </summary>
|
||||
/// <typeparam name="TT"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public TT GetCacheItem<TT>(string cacheKey, Func<TT> getCacheItem)
|
||||
{
|
||||
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
|
||||
/// </summary>
|
||||
/// <typeparam name="TT"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public TT GetCacheItem<TT>(string cacheKey,
|
||||
TimeSpan timeout, Func<TT> getCacheItem)
|
||||
{
|
||||
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
|
||||
/// </summary>
|
||||
/// <typeparam name="TT"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="refreshAction"></param>
|
||||
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public TT GetCacheItem<TT>(string cacheKey,
|
||||
CacheItemRemovedCallback refreshAction, TimeSpan timeout,
|
||||
Func<TT> getCacheItem)
|
||||
{
|
||||
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, removedCallback: refreshAction);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
|
||||
/// </summary>
|
||||
/// <typeparam name="TT"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="refreshAction"></param>
|
||||
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public TT GetCacheItem<TT>(string cacheKey,
|
||||
CacheItemPriority priority, CacheItemRemovedCallback refreshAction, TimeSpan timeout,
|
||||
Func<TT> getCacheItem)
|
||||
{
|
||||
return RuntimeCache.GetCacheItem<TT>(cacheKey, getCacheItem, timeout, false, priority, refreshAction);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets (and adds if necessary) an item from the cache with the specified absolute expiration date (from NOW)
|
||||
/// </summary>
|
||||
/// <typeparam name="TT"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="refreshAction"></param>
|
||||
/// <param name="cacheDependency"></param>
|
||||
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
|
||||
public TT GetCacheItem<TT>(string cacheKey,
|
||||
CacheItemPriority priority,
|
||||
CacheItemRemovedCallback refreshAction,
|
||||
CacheDependency cacheDependency,
|
||||
TimeSpan timeout,
|
||||
Func<TT> getCacheItem)
|
||||
{
|
||||
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
|
||||
if (cache != null)
|
||||
{
|
||||
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
|
||||
return result == null ? default(TT) : result.TryConvertTo<TT>().Result;
|
||||
}
|
||||
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets (and adds if necessary) an item from the cache
|
||||
/// </summary>
|
||||
/// <typeparam name="TT"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="cacheDependency"></param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <returns></returns>
|
||||
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
|
||||
public TT GetCacheItem<TT>(string cacheKey,
|
||||
CacheItemPriority priority,
|
||||
CacheDependency cacheDependency,
|
||||
Func<TT> getCacheItem)
|
||||
{
|
||||
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
|
||||
if (cache != null)
|
||||
{
|
||||
var result = cache.GetCacheItem(cacheKey, () => getCacheItem(), null, false, priority, null, cacheDependency);
|
||||
return result == null ? default(TT) : result.TryConvertTo<TT>().Result;
|
||||
}
|
||||
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void InsertCacheItem<T>(string cacheKey,
|
||||
CacheItemPriority priority,
|
||||
Func<T> getCacheItem)
|
||||
{
|
||||
RuntimeCache.InsertCacheItem<T>(cacheKey, getCacheItem, priority: priority);
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
[Obsolete("Do not use this method, access the runtime cache from the RuntimeCache property")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public void InsertCacheItem<T>(string cacheKey,
|
||||
CacheItemPriority priority,
|
||||
TimeSpan timeout,
|
||||
Func<T> getCacheItem)
|
||||
{
|
||||
RuntimeCache.InsertCacheItem<T>(cacheKey, getCacheItem, timeout, priority: priority);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="cacheDependency"></param>
|
||||
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
|
||||
public void InsertCacheItem<T>(string cacheKey,
|
||||
CacheItemPriority priority,
|
||||
CacheDependency cacheDependency,
|
||||
TimeSpan timeout,
|
||||
Func<T> getCacheItem)
|
||||
{
|
||||
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
|
||||
if (cache != null)
|
||||
{
|
||||
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, null, cacheDependency);
|
||||
}
|
||||
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inserts an item into the cache, if it already exists in the cache it will be replaced
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="refreshAction"></param>
|
||||
/// <param name="cacheDependency"></param>
|
||||
/// <param name="timeout">This will set an absolute expiration from now until the timeout</param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
[Obsolete("Do not use this method, we no longer support the caching overloads with references to CacheDependency, use the overloads specifying a file collection instead")]
|
||||
public void InsertCacheItem<T>(string cacheKey,
|
||||
CacheItemPriority priority,
|
||||
CacheItemRemovedCallback refreshAction,
|
||||
CacheDependency cacheDependency,
|
||||
TimeSpan? timeout,
|
||||
Func<T> getCacheItem)
|
||||
{
|
||||
var cache = GetHttpRuntimeCacheProvider(RuntimeCache);
|
||||
if (cache != null)
|
||||
{
|
||||
cache.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, false, priority, refreshAction, cacheDependency);
|
||||
}
|
||||
throw new InvalidOperationException("Cannot use this obsoleted overload when the current provider is not of type " + typeof(HttpRuntimeCacheProvider));
|
||||
}
|
||||
#endregion
|
||||
|
||||
private HttpRuntimeCacheProvider GetHttpRuntimeCacheProvider(IRuntimeCacheProvider runtimeCache)
|
||||
{
|
||||
HttpRuntimeCacheProvider cache;
|
||||
var wrapper = RuntimeCache as IRuntimeCacheProviderWrapper;
|
||||
if (wrapper != null)
|
||||
{
|
||||
cache = wrapper.InnerProvider as HttpRuntimeCacheProvider;
|
||||
}
|
||||
else
|
||||
{
|
||||
cache = RuntimeCache as HttpRuntimeCacheProvider;
|
||||
}
|
||||
return cache;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,93 +1,15 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using Umbraco.Core.CodeAnnotations;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Constants storing cache keys used in caching
|
||||
/// </summary>
|
||||
public static class CacheKeys
|
||||
{
|
||||
public const string ApplicationTreeCacheKey = "ApplicationTreeCache";
|
||||
public const string ApplicationsCacheKey = "ApplicationCache";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string UserTypeCacheKey = "UserTypeCache";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future - it is referenced but no cache is stored against this key")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string ContentItemCacheKey = "contentItem";
|
||||
|
||||
[UmbracoWillObsolete("This cache key is only used for the legacy 'library' caching, remove in v8")]
|
||||
public const string MediaCacheKey = "UL_GetMedia";
|
||||
|
||||
public const string MacroXsltCacheKey = "macroXslt_";
|
||||
|
||||
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
|
||||
public const string MacroCacheKey = "UmbracoMacroCache";
|
||||
|
||||
public const string MacroContentCacheKey = "macroContent_"; // for macro contents
|
||||
|
||||
[UmbracoWillObsolete("This cache key is only used for legacy 'library' member caching, remove in v8")]
|
||||
public const string MemberLibraryCacheKey = "UL_GetMember";
|
||||
|
||||
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
|
||||
public const string MemberBusinessLogicCacheKey = "MemberCacheItem_";
|
||||
|
||||
[UmbracoWillObsolete("This cache key is only used for legacy template business logic caching, remove in v8")]
|
||||
public const string TemplateFrontEndCacheKey = "template";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string TemplateBusinessLogicCacheKey = "UmbracoTemplateCache";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string UserContextCacheKey = "UmbracoUserContext";
|
||||
|
||||
public const string UserContextTimeoutCacheKey = "UmbracoUserContextTimeout";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string UserCacheKey = "UmbracoUser";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string UserGroupPermissionsCacheKey = "UmbracoUserGroupPermissions";
|
||||
|
||||
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
|
||||
public const string ContentTypeCacheKey = "UmbracoContentType";
|
||||
|
||||
[UmbracoWillObsolete("This cache key is only used for legacy business logic caching, remove in v8")]
|
||||
public const string ContentTypePropertiesCacheKey = "ContentType_PropertyTypes_Content:";
|
||||
|
||||
[Obsolete("No longer used and will be removed in v8")]
|
||||
public const string PropertyTypeCacheKey = "UmbracoPropertyTypeCache";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string LanguageCacheKey = "UmbracoLanguageCache";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string DomainCacheKey = "UmbracoDomainList";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string StylesheetCacheKey = "UmbracoStylesheet";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string StylesheetPropertyCacheKey = "UmbracoStylesheetProperty";
|
||||
|
||||
[Obsolete("This is no longer used and will be removed from the codebase in the future")]
|
||||
[EditorBrowsable(EditorBrowsableState.Never)]
|
||||
public const string DataTypeCacheKey = "UmbracoDataTypeDefinition";
|
||||
public const string DataTypePreValuesCacheKey = "UmbracoPreVal";
|
||||
|
||||
public const string IdToKeyCacheKey = "UI2K__";
|
||||
public const string KeyToIdCacheKey = "UK2I__";
|
||||
}
|
||||
}
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Constants storing cache keys used in caching
|
||||
/// </summary>
|
||||
public static class CacheKeys
|
||||
{
|
||||
public const string ApplicationTreeCacheKey = "ApplicationTreeCache"; // used by ApplicationTreeService
|
||||
public const string ApplicationsCacheKey = "ApplicationCache"; // used by SectionService
|
||||
|
||||
public const string TemplateFrontEndCacheKey = "template"; // fixme usage?
|
||||
|
||||
public const string MacroContentCacheKey = "macroContent_"; // used in MacroRenderers
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for strongly typed access
|
||||
/// </summary>
|
||||
public static class CacheProviderExtensions
|
||||
{
|
||||
public static T GetCacheItem<T>(this IRuntimeCacheProvider provider,
|
||||
string cacheKey,
|
||||
Func<T> getCacheItem,
|
||||
TimeSpan? timeout,
|
||||
bool isSliding = false,
|
||||
CacheItemPriority priority = CacheItemPriority.Normal,
|
||||
CacheItemRemovedCallback removedCallback = null,
|
||||
string[] dependentFiles = null)
|
||||
{
|
||||
var result = provider.GetCacheItem(cacheKey, () => getCacheItem(), timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
return result == null ? default(T) : result.TryConvertTo<T>().Result;
|
||||
}
|
||||
|
||||
public static void InsertCacheItem<T>(this IRuntimeCacheProvider provider,
|
||||
string cacheKey,
|
||||
Func<T> getCacheItem,
|
||||
TimeSpan? timeout = null,
|
||||
bool isSliding = false,
|
||||
CacheItemPriority priority = CacheItemPriority.Normal,
|
||||
CacheItemRemovedCallback removedCallback = null,
|
||||
string[] dependentFiles = null)
|
||||
{
|
||||
provider.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> GetCacheItemsByKeySearch<T>(this ICacheProvider provider, string keyStartsWith)
|
||||
{
|
||||
var result = provider.GetCacheItemsByKeySearch(keyStartsWith);
|
||||
return result.Select(x => x.TryConvertTo<T>().Result);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> GetCacheItemsByKeyExpression<T>(this ICacheProvider provider, string regexString)
|
||||
{
|
||||
var result = provider.GetCacheItemsByKeyExpression(regexString);
|
||||
return result.Select(x => x.TryConvertTo<T>().Result);
|
||||
}
|
||||
|
||||
public static T GetCacheItem<T>(this ICacheProvider provider, string cacheKey)
|
||||
{
|
||||
var result = provider.GetCacheItem(cacheKey);
|
||||
if (result == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
return result.TryConvertTo<T>().Result;
|
||||
}
|
||||
|
||||
public static T GetCacheItem<T>(this ICacheProvider provider, string cacheKey, Func<T> getCacheItem)
|
||||
{
|
||||
var result = provider.GetCacheItem(cacheKey, () => getCacheItem());
|
||||
if (result == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
return result.TryConvertTo<T>().Result;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Extensions for strongly typed access
|
||||
/// </summary>
|
||||
public static class CacheProviderExtensions
|
||||
{
|
||||
public static T GetCacheItem<T>(this IRuntimeCacheProvider provider,
|
||||
string cacheKey,
|
||||
Func<T> getCacheItem,
|
||||
TimeSpan? timeout,
|
||||
bool isSliding = false,
|
||||
CacheItemPriority priority = CacheItemPriority.Normal,
|
||||
CacheItemRemovedCallback removedCallback = null,
|
||||
string[] dependentFiles = null)
|
||||
{
|
||||
var result = provider.GetCacheItem(cacheKey, () => getCacheItem(), timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
return result == null ? default(T) : result.TryConvertTo<T>().Result;
|
||||
}
|
||||
|
||||
public static void InsertCacheItem<T>(this IRuntimeCacheProvider provider,
|
||||
string cacheKey,
|
||||
Func<T> getCacheItem,
|
||||
TimeSpan? timeout = null,
|
||||
bool isSliding = false,
|
||||
CacheItemPriority priority = CacheItemPriority.Normal,
|
||||
CacheItemRemovedCallback removedCallback = null,
|
||||
string[] dependentFiles = null)
|
||||
{
|
||||
provider.InsertCacheItem(cacheKey, () => getCacheItem(), timeout, isSliding, priority, removedCallback, dependentFiles);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> GetCacheItemsByKeySearch<T>(this ICacheProvider provider, string keyStartsWith)
|
||||
{
|
||||
var result = provider.GetCacheItemsByKeySearch(keyStartsWith);
|
||||
return result.Select(x => x.TryConvertTo<T>().Result);
|
||||
}
|
||||
|
||||
public static IEnumerable<T> GetCacheItemsByKeyExpression<T>(this ICacheProvider provider, string regexString)
|
||||
{
|
||||
var result = provider.GetCacheItemsByKeyExpression(regexString);
|
||||
return result.Select(x => x.TryConvertTo<T>().Result);
|
||||
}
|
||||
|
||||
public static T GetCacheItem<T>(this ICacheProvider provider, string cacheKey)
|
||||
{
|
||||
var result = provider.GetCacheItem(cacheKey);
|
||||
if (result == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
return result.TryConvertTo<T>().Result;
|
||||
}
|
||||
|
||||
public static T GetCacheItem<T>(this ICacheProvider provider, string cacheKey, Func<T> getCacheItem)
|
||||
{
|
||||
var result = provider.GetCacheItem(cacheKey, () => getCacheItem());
|
||||
if (result == null)
|
||||
{
|
||||
return default(T);
|
||||
}
|
||||
return result.TryConvertTo<T>().Result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,120 +1,120 @@
|
||||
using System;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for cache refreshers that handles events.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInstanceType">The actual cache refresher type.</typeparam>
|
||||
/// <remarks>The actual cache refresher type is used for strongly typed events.</remarks>
|
||||
public abstract class CacheRefresherBase<TInstanceType> : ICacheRefresher
|
||||
where TInstanceType : class, ICacheRefresher
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CacheRefresherBase{TInstanceType}"/>.
|
||||
/// </summary>
|
||||
/// <param name="cacheHelper">A cache helper.</param>
|
||||
protected CacheRefresherBase(CacheHelper cacheHelper)
|
||||
{
|
||||
CacheHelper = cacheHelper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers when the cache is updated on the server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggers on each server configured for an Umbraco project whenever a cache refresher is updated.
|
||||
/// </remarks>
|
||||
public static event TypedEventHandler<TInstanceType, CacheRefresherEventArgs> CacheUpdated;
|
||||
|
||||
#region Define
|
||||
|
||||
/// <summary>
|
||||
/// Gets the typed 'this' for events.
|
||||
/// </summary>
|
||||
protected abstract TInstanceType This { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique identifier of the refresher.
|
||||
/// </summary>
|
||||
public abstract Guid RefresherUniqueId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the refresher.
|
||||
/// </summary>
|
||||
public abstract string Name { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Refresher
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes all entities.
|
||||
/// </summary>
|
||||
public virtual void RefreshAll()
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(null, MessageType.RefreshAll));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes an entity.
|
||||
/// </summary>
|
||||
/// <param name="id">The entity's identifier.</param>
|
||||
public virtual void Refresh(int id)
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(id, MessageType.RefreshById));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes an entity.
|
||||
/// </summary>
|
||||
/// <param name="id">The entity's identifier.</param>
|
||||
public virtual void Refresh(Guid id)
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(id, MessageType.RefreshById));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an entity.
|
||||
/// </summary>
|
||||
/// <param name="id">The entity's identifier.</param>
|
||||
public virtual void Remove(int id)
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(id, MessageType.RemoveById));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cache helper.
|
||||
/// </summary>
|
||||
protected CacheHelper CacheHelper { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Clears the cache for all repository entities of a specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">The type of the entities.</typeparam>
|
||||
protected void ClearAllIsolatedCacheByEntityType<TEntity>()
|
||||
where TEntity : class, IEntity
|
||||
{
|
||||
CacheHelper.IsolatedRuntimeCache.ClearCache<TEntity>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the CacheUpdated event.
|
||||
/// </summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="args">The event arguments.</param>
|
||||
protected static void OnCacheUpdated(TInstanceType sender, CacheRefresherEventArgs args)
|
||||
{
|
||||
CacheUpdated?.Invoke(sender, args);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using Umbraco.Core.Events;
|
||||
using Umbraco.Core.Models.Entities;
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for cache refreshers that handles events.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInstanceType">The actual cache refresher type.</typeparam>
|
||||
/// <remarks>The actual cache refresher type is used for strongly typed events.</remarks>
|
||||
public abstract class CacheRefresherBase<TInstanceType> : ICacheRefresher
|
||||
where TInstanceType : class, ICacheRefresher
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CacheRefresherBase{TInstanceType}"/>.
|
||||
/// </summary>
|
||||
/// <param name="cacheHelper">A cache helper.</param>
|
||||
protected CacheRefresherBase(CacheHelper cacheHelper)
|
||||
{
|
||||
CacheHelper = cacheHelper;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triggers when the cache is updated on the server.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Triggers on each server configured for an Umbraco project whenever a cache refresher is updated.
|
||||
/// </remarks>
|
||||
public static event TypedEventHandler<TInstanceType, CacheRefresherEventArgs> CacheUpdated;
|
||||
|
||||
#region Define
|
||||
|
||||
/// <summary>
|
||||
/// Gets the typed 'this' for events.
|
||||
/// </summary>
|
||||
protected abstract TInstanceType This { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique identifier of the refresher.
|
||||
/// </summary>
|
||||
public abstract Guid RefresherUniqueId { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the name of the refresher.
|
||||
/// </summary>
|
||||
public abstract string Name { get; }
|
||||
|
||||
#endregion
|
||||
|
||||
#region Refresher
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes all entities.
|
||||
/// </summary>
|
||||
public virtual void RefreshAll()
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(null, MessageType.RefreshAll));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes an entity.
|
||||
/// </summary>
|
||||
/// <param name="id">The entity's identifier.</param>
|
||||
public virtual void Refresh(int id)
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(id, MessageType.RefreshById));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes an entity.
|
||||
/// </summary>
|
||||
/// <param name="id">The entity's identifier.</param>
|
||||
public virtual void Refresh(Guid id)
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(id, MessageType.RefreshById));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes an entity.
|
||||
/// </summary>
|
||||
/// <param name="id">The entity's identifier.</param>
|
||||
public virtual void Remove(int id)
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(id, MessageType.RemoveById));
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Protected
|
||||
|
||||
/// <summary>
|
||||
/// Gets the cache helper.
|
||||
/// </summary>
|
||||
protected CacheHelper CacheHelper { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Clears the cache for all repository entities of a specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="TEntity">The type of the entities.</typeparam>
|
||||
protected void ClearAllIsolatedCacheByEntityType<TEntity>()
|
||||
where TEntity : class, IEntity
|
||||
{
|
||||
CacheHelper.IsolatedRuntimeCache.ClearCache<TEntity>();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Raises the CacheUpdated event.
|
||||
/// </summary>
|
||||
/// <param name="sender">The event sender.</param>
|
||||
/// <param name="args">The event arguments.</param>
|
||||
protected static void OnCacheUpdated(TInstanceType sender, CacheRefresherEventArgs args)
|
||||
{
|
||||
CacheUpdated?.Invoke(sender, args);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
using System;
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Event args for cache refresher updates
|
||||
/// </summary>
|
||||
public class CacheRefresherEventArgs : EventArgs
|
||||
{
|
||||
public CacheRefresherEventArgs(object msgObject, MessageType type)
|
||||
{
|
||||
MessageType = type;
|
||||
MessageObject = msgObject;
|
||||
}
|
||||
public object MessageObject { get; private set; }
|
||||
public MessageType MessageType { get; private set; }
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Event args for cache refresher updates
|
||||
/// </summary>
|
||||
public class CacheRefresherEventArgs : EventArgs
|
||||
{
|
||||
public CacheRefresherEventArgs(object msgObject, MessageType type)
|
||||
{
|
||||
MessageType = type;
|
||||
MessageObject = msgObject;
|
||||
}
|
||||
public object MessageObject { get; private set; }
|
||||
public MessageType MessageType { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,257 +1,313 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
internal abstract class DictionaryCacheProviderBase : ICacheProvider
|
||||
{
|
||||
// prefix cache keys so we know which one are ours
|
||||
protected const string CacheItemPrefix = "umbrtmche";
|
||||
|
||||
// an object that represent a value that has not been created yet
|
||||
protected internal static readonly object ValueNotCreated = new object();
|
||||
|
||||
// manupulate the underlying cache entries
|
||||
// these *must* be called from within the appropriate locks
|
||||
// and use the full prefixed cache keys
|
||||
protected abstract IEnumerable<DictionaryEntry> GetDictionaryEntries();
|
||||
protected abstract void RemoveEntry(string key);
|
||||
protected abstract object GetEntry(string key);
|
||||
|
||||
// read-write lock the underlying cache
|
||||
protected abstract IDisposable ReadLock { get; }
|
||||
protected abstract IDisposable WriteLock { get; }
|
||||
|
||||
protected string GetCacheKey(string key)
|
||||
{
|
||||
return string.Format("{0}-{1}", CacheItemPrefix, key);
|
||||
}
|
||||
|
||||
protected internal static Lazy<object> GetSafeLazy(Func<object> getCacheItem)
|
||||
{
|
||||
// try to generate the value and if it fails,
|
||||
// wrap in an ExceptionHolder - would be much simpler
|
||||
// to just use lazy.IsValueFaulted alas that field is
|
||||
// internal
|
||||
return new Lazy<object>(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return getCacheItem();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return new ExceptionHolder(ExceptionDispatchInfo.Capture(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected internal static object GetSafeLazyValue(Lazy<object> lazy, bool onlyIfValueIsCreated = false)
|
||||
{
|
||||
// if onlyIfValueIsCreated, do not trigger value creation
|
||||
// must return something, though, to differenciate from null values
|
||||
if (onlyIfValueIsCreated && lazy.IsValueCreated == false) return ValueNotCreated;
|
||||
|
||||
// if execution has thrown then lazy.IsValueCreated is false
|
||||
// and lazy.IsValueFaulted is true (but internal) so we use our
|
||||
// own exception holder (see Lazy<T> source code) to return null
|
||||
if (lazy.Value is ExceptionHolder) return null;
|
||||
|
||||
// we have a value and execution has not thrown so returning
|
||||
// here does not throw - unless we're re-entering, take care of it
|
||||
try
|
||||
{
|
||||
return lazy.Value;
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
throw new InvalidOperationException("The method that computes a value for the cache has tried to read that value from the cache.", e);
|
||||
}
|
||||
}
|
||||
|
||||
internal class ExceptionHolder
|
||||
{
|
||||
public ExceptionHolder(ExceptionDispatchInfo e)
|
||||
{
|
||||
Exception = e;
|
||||
}
|
||||
|
||||
public ExceptionDispatchInfo Exception { get; }
|
||||
}
|
||||
|
||||
#region Clear
|
||||
|
||||
public virtual void ClearAllCache()
|
||||
{
|
||||
using (WriteLock)
|
||||
{
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
.ToArray())
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheItem(string key)
|
||||
{
|
||||
var cacheKey = GetCacheKey(key);
|
||||
using (WriteLock)
|
||||
{
|
||||
RemoveEntry(cacheKey);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes(string typeName)
|
||||
{
|
||||
var type = TypeFinder.GetTypeByName(typeName);
|
||||
if (type == null) return;
|
||||
var isInterface = type.IsInterface;
|
||||
using (WriteLock)
|
||||
{
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
.Where(x =>
|
||||
{
|
||||
// entry.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type));
|
||||
})
|
||||
.ToArray())
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>()
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
using (WriteLock)
|
||||
{
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
.Where(x =>
|
||||
{
|
||||
// entry.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// compare on exact type, don't use "is"
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT));
|
||||
})
|
||||
.ToArray())
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
var plen = CacheItemPrefix.Length + 1;
|
||||
using (WriteLock)
|
||||
{
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
.Where(x =>
|
||||
{
|
||||
// entry.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// compare on exact type, don't use "is"
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
if (value == null) return true;
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return (isInterface ? (value is T) : (value.GetType() == typeOfT))
|
||||
// run predicate on the 'public key' part only, ie without prefix
|
||||
&& predicate(((string) x.Key).Substring(plen), (T) value);
|
||||
}))
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeySearch(string keyStartsWith)
|
||||
{
|
||||
var plen = CacheItemPrefix.Length + 1;
|
||||
using (WriteLock)
|
||||
{
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
.Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith))
|
||||
.ToArray())
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeyExpression(string regexString)
|
||||
{
|
||||
var plen = CacheItemPrefix.Length + 1;
|
||||
using (WriteLock)
|
||||
{
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
.Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString))
|
||||
.ToArray())
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get
|
||||
|
||||
public virtual IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
|
||||
{
|
||||
var plen = CacheItemPrefix.Length + 1;
|
||||
IEnumerable<DictionaryEntry> entries;
|
||||
using (ReadLock)
|
||||
{
|
||||
entries = GetDictionaryEntries()
|
||||
.Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith))
|
||||
.ToArray(); // evaluate while locked
|
||||
}
|
||||
return entries
|
||||
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
|
||||
.Where(x => x != null); // backward compat, don't store null values in the cache
|
||||
}
|
||||
|
||||
public virtual IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
|
||||
{
|
||||
const string prefix = CacheItemPrefix + "-";
|
||||
var plen = prefix.Length;
|
||||
IEnumerable<DictionaryEntry> entries;
|
||||
using (ReadLock)
|
||||
{
|
||||
entries = GetDictionaryEntries()
|
||||
.Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString))
|
||||
.ToArray(); // evaluate while locked
|
||||
}
|
||||
return entries
|
||||
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
|
||||
.Where(x => x != null); // backward compat, don't store null values in the cache
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey)
|
||||
{
|
||||
cacheKey = GetCacheKey(cacheKey);
|
||||
Lazy<object> result;
|
||||
using (ReadLock)
|
||||
{
|
||||
result = GetEntry(cacheKey) as Lazy<object>; // null if key not found
|
||||
}
|
||||
return result == null ? null : GetSafeLazyValue(result); // return exceptions as null
|
||||
}
|
||||
|
||||
public abstract object GetCacheItem(string cacheKey, Func<object> getCacheItem);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.ExceptionServices;
|
||||
using System.Text.RegularExpressions;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
internal abstract class DictionaryCacheProviderBase : ICacheProvider
|
||||
{
|
||||
// prefix cache keys so we know which one are ours
|
||||
protected const string CacheItemPrefix = "umbrtmche";
|
||||
|
||||
// an object that represent a value that has not been created yet
|
||||
protected internal static readonly object ValueNotCreated = new object();
|
||||
|
||||
// manupulate the underlying cache entries
|
||||
// these *must* be called from within the appropriate locks
|
||||
// and use the full prefixed cache keys
|
||||
protected abstract IEnumerable<DictionaryEntry> GetDictionaryEntries();
|
||||
protected abstract void RemoveEntry(string key);
|
||||
protected abstract object GetEntry(string key);
|
||||
|
||||
// read-write lock the underlying cache
|
||||
//protected abstract IDisposable ReadLock { get; }
|
||||
//protected abstract IDisposable WriteLock { get; }
|
||||
|
||||
protected abstract void EnterReadLock();
|
||||
protected abstract void ExitReadLock();
|
||||
protected abstract void EnterWriteLock();
|
||||
protected abstract void ExitWriteLock();
|
||||
|
||||
protected string GetCacheKey(string key)
|
||||
{
|
||||
return string.Format("{0}-{1}", CacheItemPrefix, key);
|
||||
}
|
||||
|
||||
protected internal static Lazy<object> GetSafeLazy(Func<object> getCacheItem)
|
||||
{
|
||||
// try to generate the value and if it fails,
|
||||
// wrap in an ExceptionHolder - would be much simpler
|
||||
// to just use lazy.IsValueFaulted alas that field is
|
||||
// internal
|
||||
return new Lazy<object>(() =>
|
||||
{
|
||||
try
|
||||
{
|
||||
return getCacheItem();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
return new ExceptionHolder(ExceptionDispatchInfo.Capture(e));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected internal static object GetSafeLazyValue(Lazy<object> lazy, bool onlyIfValueIsCreated = false)
|
||||
{
|
||||
// if onlyIfValueIsCreated, do not trigger value creation
|
||||
// must return something, though, to differenciate from null values
|
||||
if (onlyIfValueIsCreated && lazy.IsValueCreated == false) return ValueNotCreated;
|
||||
|
||||
// if execution has thrown then lazy.IsValueCreated is false
|
||||
// and lazy.IsValueFaulted is true (but internal) so we use our
|
||||
// own exception holder (see Lazy<T> source code) to return null
|
||||
if (lazy.Value is ExceptionHolder) return null;
|
||||
|
||||
// we have a value and execution has not thrown so returning
|
||||
// here does not throw - unless we're re-entering, take care of it
|
||||
try
|
||||
{
|
||||
return lazy.Value;
|
||||
}
|
||||
catch (InvalidOperationException e)
|
||||
{
|
||||
throw new InvalidOperationException("The method that computes a value for the cache has tried to read that value from the cache.", e);
|
||||
}
|
||||
}
|
||||
|
||||
internal class ExceptionHolder
|
||||
{
|
||||
public ExceptionHolder(ExceptionDispatchInfo e)
|
||||
{
|
||||
Exception = e;
|
||||
}
|
||||
|
||||
public ExceptionDispatchInfo Exception { get; }
|
||||
}
|
||||
|
||||
#region Clear
|
||||
|
||||
public virtual void ClearAllCache()
|
||||
{
|
||||
try
|
||||
{
|
||||
EnterWriteLock();
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
.ToArray())
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheItem(string key)
|
||||
{
|
||||
var cacheKey = GetCacheKey(key);
|
||||
try
|
||||
{
|
||||
EnterWriteLock();
|
||||
RemoveEntry(cacheKey);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes(string typeName)
|
||||
{
|
||||
var type = TypeFinder.GetTypeByName(typeName);
|
||||
if (type == null) return;
|
||||
var isInterface = type.IsInterface;
|
||||
try
|
||||
{
|
||||
EnterWriteLock();
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
.Where(x =>
|
||||
{
|
||||
// entry.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = GetSafeLazyValue((Lazy<object>) x.Value, true);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type));
|
||||
})
|
||||
.ToArray())
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>()
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
try
|
||||
{
|
||||
EnterWriteLock();
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
.Where(x =>
|
||||
{
|
||||
// entry.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// compare on exact type, don't use "is"
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = GetSafeLazyValue((Lazy<object>) x.Value, true);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT));
|
||||
})
|
||||
.ToArray())
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
var plen = CacheItemPrefix.Length + 1;
|
||||
try
|
||||
{
|
||||
EnterWriteLock();
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
.Where(x =>
|
||||
{
|
||||
// entry.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// compare on exact type, don't use "is"
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = GetSafeLazyValue((Lazy<object>) x.Value, true);
|
||||
if (value == null) return true;
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return (isInterface ? (value is T) : (value.GetType() == typeOfT))
|
||||
// run predicate on the 'public key' part only, ie without prefix
|
||||
&& predicate(((string) x.Key).Substring(plen), (T) value);
|
||||
}))
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeySearch(string keyStartsWith)
|
||||
{
|
||||
var plen = CacheItemPrefix.Length + 1;
|
||||
try
|
||||
{
|
||||
EnterWriteLock();
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
.Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith))
|
||||
.ToArray())
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeyExpression(string regexString)
|
||||
{
|
||||
var plen = CacheItemPrefix.Length + 1;
|
||||
try
|
||||
{
|
||||
EnterWriteLock();
|
||||
foreach (var entry in GetDictionaryEntries()
|
||||
.Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString))
|
||||
.ToArray())
|
||||
RemoveEntry((string) entry.Key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get
|
||||
|
||||
public virtual IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
|
||||
{
|
||||
var plen = CacheItemPrefix.Length + 1;
|
||||
IEnumerable<DictionaryEntry> entries;
|
||||
try
|
||||
{
|
||||
EnterReadLock();
|
||||
entries = GetDictionaryEntries()
|
||||
.Where(x => ((string)x.Key).Substring(plen).InvariantStartsWith(keyStartsWith))
|
||||
.ToArray(); // evaluate while locked
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitReadLock();
|
||||
}
|
||||
|
||||
return entries
|
||||
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
|
||||
.Where(x => x != null); // backward compat, don't store null values in the cache
|
||||
}
|
||||
|
||||
public virtual IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
|
||||
{
|
||||
const string prefix = CacheItemPrefix + "-";
|
||||
var plen = prefix.Length;
|
||||
IEnumerable<DictionaryEntry> entries;
|
||||
try
|
||||
{
|
||||
EnterReadLock();
|
||||
entries = GetDictionaryEntries()
|
||||
.Where(x => Regex.IsMatch(((string)x.Key).Substring(plen), regexString))
|
||||
.ToArray(); // evaluate while locked
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitReadLock();
|
||||
}
|
||||
return entries
|
||||
.Select(x => GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
|
||||
.Where(x => x != null); // backward compat, don't store null values in the cache
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey)
|
||||
{
|
||||
cacheKey = GetCacheKey(cacheKey);
|
||||
Lazy<object> result;
|
||||
try
|
||||
{
|
||||
EnterReadLock();
|
||||
result = GetEntry(cacheKey) as Lazy<object>; // null if key not found
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitReadLock();
|
||||
}
|
||||
return result == null ? null : GetSafeLazyValue(result); // return exceptions as null
|
||||
}
|
||||
|
||||
public abstract object GetCacheItem(string cacheKey, Func<object> getCacheItem);
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ namespace Umbraco.Core.Cache
|
||||
}
|
||||
|
||||
// does NOT clone anything, so be nice with the returned values
|
||||
private IEnumerable<TEntity> GetAllCached(Func<TId[], IEnumerable<TEntity>> performGetAll)
|
||||
internal IEnumerable<TEntity> GetAllCached(Func<TId[], IEnumerable<TEntity>> performGetAll)
|
||||
{
|
||||
// try the cache first
|
||||
var all = Cache.GetCacheItem<DeepCloneableList<TEntity>>(GetEntityTypeCacheKey());
|
||||
|
||||
@@ -1,154 +1,161 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A cache provider that caches items in the HttpContext.Items
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the Items collection is null, then this provider has no effect
|
||||
/// </remarks>
|
||||
internal class HttpRequestCacheProvider : DictionaryCacheProviderBase
|
||||
{
|
||||
// context provider
|
||||
// the idea is that there is only one, application-wide HttpRequestCacheProvider instance,
|
||||
// that is initialized with a method that returns the "current" context.
|
||||
// NOTE
|
||||
// but then it is initialized with () => new HttpContextWrapper(HttpContent.Current)
|
||||
// which is higly inefficient because it creates a new wrapper each time we refer to _context()
|
||||
// so replace it with _context1 and _context2 below + a way to get context.Items.
|
||||
//private readonly Func<HttpContextBase> _context;
|
||||
|
||||
// NOTE
|
||||
// and then in almost 100% cases _context2 will be () => HttpContext.Current
|
||||
// so why not bring that logic in here and fallback on to HttpContext.Current when
|
||||
// _context1 is null?
|
||||
//private readonly HttpContextBase _context1;
|
||||
//private readonly Func<HttpContext> _context2;
|
||||
private readonly HttpContextBase _context;
|
||||
|
||||
private IDictionary ContextItems
|
||||
{
|
||||
//get { return _context1 != null ? _context1.Items : _context2().Items; }
|
||||
get { return _context != null ? _context.Items : HttpContext.Current.Items; }
|
||||
}
|
||||
|
||||
private bool HasContextItems
|
||||
{
|
||||
get { return (_context != null && _context.Items != null) || HttpContext.Current != null; }
|
||||
}
|
||||
|
||||
// for unit tests
|
||||
public HttpRequestCacheProvider(HttpContextBase context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// main constructor
|
||||
// will use HttpContext.Current
|
||||
public HttpRequestCacheProvider(/*Func<HttpContext> context*/)
|
||||
{
|
||||
//_context2 = context;
|
||||
}
|
||||
|
||||
protected override IEnumerable<DictionaryEntry> GetDictionaryEntries()
|
||||
{
|
||||
const string prefix = CacheItemPrefix + "-";
|
||||
|
||||
if (HasContextItems == false) return Enumerable.Empty<DictionaryEntry>();
|
||||
|
||||
return ContextItems.Cast<DictionaryEntry>()
|
||||
.Where(x => x.Key is string && ((string)x.Key).StartsWith(prefix));
|
||||
}
|
||||
|
||||
protected override void RemoveEntry(string key)
|
||||
{
|
||||
if (HasContextItems == false) return;
|
||||
|
||||
ContextItems.Remove(key);
|
||||
}
|
||||
|
||||
protected override object GetEntry(string key)
|
||||
{
|
||||
return HasContextItems ? ContextItems[key] : null;
|
||||
}
|
||||
|
||||
#region Lock
|
||||
|
||||
protected override IDisposable ReadLock
|
||||
{
|
||||
// there's no difference between ReadLock and WriteLock here
|
||||
get { return WriteLock; }
|
||||
}
|
||||
|
||||
protected override IDisposable WriteLock
|
||||
{
|
||||
// NOTE
|
||||
// could think about just overriding base.Locker to return a different
|
||||
// object but then we'd create a ReaderWriterLockSlim per request,
|
||||
// which is less efficient than just using a basic monitor lock.
|
||||
|
||||
get
|
||||
{
|
||||
return HasContextItems
|
||||
? (IDisposable) new MonitorLock(ContextItems.SyncRoot)
|
||||
: new NoopLocker();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get
|
||||
|
||||
public override object GetCacheItem(string cacheKey, Func<object> getCacheItem)
|
||||
{
|
||||
//no place to cache so just return the callback result
|
||||
if (HasContextItems == false) return getCacheItem();
|
||||
|
||||
cacheKey = GetCacheKey(cacheKey);
|
||||
|
||||
Lazy<object> result;
|
||||
|
||||
using (WriteLock)
|
||||
{
|
||||
result = ContextItems[cacheKey] as Lazy<object>; // null if key not found
|
||||
|
||||
// cannot create value within the lock, so if result.IsValueCreated is false, just
|
||||
// do nothing here - means that if creation throws, a race condition could cause
|
||||
// more than one thread to reach the return statement below and throw - accepted.
|
||||
|
||||
if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
|
||||
{
|
||||
result = GetSafeLazy(getCacheItem);
|
||||
ContextItems[cacheKey] = result;
|
||||
}
|
||||
}
|
||||
|
||||
// using GetSafeLazy and GetSafeLazyValue ensures that we don't cache
|
||||
// exceptions (but try again and again) and silently eat them - however at
|
||||
// some point we have to report them - so need to re-throw here
|
||||
|
||||
// this does not throw anymore
|
||||
//return result.Value;
|
||||
|
||||
var value = result.Value; // will not throw (safe lazy)
|
||||
if (value is ExceptionHolder eh) eh.Exception.Throw(); // throw once!
|
||||
return value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Insert
|
||||
#endregion
|
||||
|
||||
private class NoopLocker : DisposableObjectSlim
|
||||
{
|
||||
protected override void DisposeResources()
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A cache provider that caches items in the HttpContext.Items
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// If the Items collection is null, then this provider has no effect
|
||||
/// </remarks>
|
||||
internal class HttpRequestCacheProvider : DictionaryCacheProviderBase
|
||||
{
|
||||
// context provider
|
||||
// the idea is that there is only one, application-wide HttpRequestCacheProvider instance,
|
||||
// that is initialized with a method that returns the "current" context.
|
||||
// NOTE
|
||||
// but then it is initialized with () => new HttpContextWrapper(HttpContent.Current)
|
||||
// which is higly inefficient because it creates a new wrapper each time we refer to _context()
|
||||
// so replace it with _context1 and _context2 below + a way to get context.Items.
|
||||
//private readonly Func<HttpContextBase> _context;
|
||||
|
||||
// NOTE
|
||||
// and then in almost 100% cases _context2 will be () => HttpContext.Current
|
||||
// so why not bring that logic in here and fallback on to HttpContext.Current when
|
||||
// _context1 is null?
|
||||
//private readonly HttpContextBase _context1;
|
||||
//private readonly Func<HttpContext> _context2;
|
||||
private readonly HttpContextBase _context;
|
||||
|
||||
private IDictionary ContextItems
|
||||
{
|
||||
//get { return _context1 != null ? _context1.Items : _context2().Items; }
|
||||
get { return _context != null ? _context.Items : HttpContext.Current.Items; }
|
||||
}
|
||||
|
||||
private bool HasContextItems
|
||||
{
|
||||
get { return (_context != null && _context.Items != null) || HttpContext.Current != null; }
|
||||
}
|
||||
|
||||
// for unit tests
|
||||
public HttpRequestCacheProvider(HttpContextBase context)
|
||||
{
|
||||
_context = context;
|
||||
}
|
||||
|
||||
// main constructor
|
||||
// will use HttpContext.Current
|
||||
public HttpRequestCacheProvider(/*Func<HttpContext> context*/)
|
||||
{
|
||||
//_context2 = context;
|
||||
}
|
||||
|
||||
protected override IEnumerable<DictionaryEntry> GetDictionaryEntries()
|
||||
{
|
||||
const string prefix = CacheItemPrefix + "-";
|
||||
|
||||
if (HasContextItems == false) return Enumerable.Empty<DictionaryEntry>();
|
||||
|
||||
return ContextItems.Cast<DictionaryEntry>()
|
||||
.Where(x => x.Key is string && ((string)x.Key).StartsWith(prefix));
|
||||
}
|
||||
|
||||
protected override void RemoveEntry(string key)
|
||||
{
|
||||
if (HasContextItems == false) return;
|
||||
|
||||
ContextItems.Remove(key);
|
||||
}
|
||||
|
||||
protected override object GetEntry(string key)
|
||||
{
|
||||
return HasContextItems ? ContextItems[key] : null;
|
||||
}
|
||||
|
||||
#region Lock
|
||||
|
||||
private bool _entered;
|
||||
|
||||
protected override void EnterReadLock() => EnterWriteLock();
|
||||
|
||||
protected override void EnterWriteLock()
|
||||
{
|
||||
if (HasContextItems)
|
||||
{
|
||||
System.Threading.Monitor.Enter(ContextItems.SyncRoot, ref _entered);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void ExitReadLock() => ExitWriteLock();
|
||||
|
||||
protected override void ExitWriteLock()
|
||||
{
|
||||
if (_entered)
|
||||
{
|
||||
_entered = false;
|
||||
System.Threading.Monitor.Exit(ContextItems.SyncRoot);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get
|
||||
|
||||
public override object GetCacheItem(string cacheKey, Func<object> getCacheItem)
|
||||
{
|
||||
//no place to cache so just return the callback result
|
||||
if (HasContextItems == false) return getCacheItem();
|
||||
|
||||
cacheKey = GetCacheKey(cacheKey);
|
||||
|
||||
Lazy<object> result;
|
||||
|
||||
try
|
||||
{
|
||||
EnterWriteLock();
|
||||
result = ContextItems[cacheKey] as Lazy<object>; // null if key not found
|
||||
|
||||
// cannot create value within the lock, so if result.IsValueCreated is false, just
|
||||
// do nothing here - means that if creation throws, a race condition could cause
|
||||
// more than one thread to reach the return statement below and throw - accepted.
|
||||
|
||||
if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
|
||||
{
|
||||
result = GetSafeLazy(getCacheItem);
|
||||
ContextItems[cacheKey] = result;
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
ExitWriteLock();
|
||||
}
|
||||
|
||||
// using GetSafeLazy and GetSafeLazyValue ensures that we don't cache
|
||||
// exceptions (but try again and again) and silently eat them - however at
|
||||
// some point we have to report them - so need to re-throw here
|
||||
|
||||
// this does not throw anymore
|
||||
//return result.Value;
|
||||
|
||||
var value = result.Value; // will not throw (safe lazy)
|
||||
if (value is ExceptionHolder eh) eh.Exception.Throw(); // throw once!
|
||||
return value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Insert
|
||||
#endregion
|
||||
|
||||
private class NoopLocker : DisposableObjectSlim
|
||||
{
|
||||
protected override void DisposeResources()
|
||||
{ }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,217 +1,241 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web.Caching;
|
||||
using CacheItemPriority = System.Web.Caching.CacheItemPriority;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A CacheProvider that wraps the logic of the HttpRuntime.Cache
|
||||
/// </summary>
|
||||
internal class HttpRuntimeCacheProvider : DictionaryCacheProviderBase, IRuntimeCacheProvider
|
||||
{
|
||||
// locker object that supports upgradeable read locking
|
||||
// does not need to support recursion if we implement the cache correctly and ensure
|
||||
// that methods cannot be reentrant, ie we do NOT create values while holding a lock.
|
||||
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
|
||||
|
||||
private readonly System.Web.Caching.Cache _cache;
|
||||
|
||||
/// <summary>
|
||||
/// Used for debugging
|
||||
/// </summary>
|
||||
internal Guid InstanceId { get; private set; }
|
||||
|
||||
public HttpRuntimeCacheProvider(System.Web.Caching.Cache cache)
|
||||
{
|
||||
_cache = cache;
|
||||
InstanceId = Guid.NewGuid();
|
||||
}
|
||||
|
||||
protected override IEnumerable<DictionaryEntry> GetDictionaryEntries()
|
||||
{
|
||||
const string prefix = CacheItemPrefix + "-";
|
||||
return _cache.Cast<DictionaryEntry>()
|
||||
.Where(x => x.Key is string && ((string)x.Key).StartsWith(prefix));
|
||||
}
|
||||
|
||||
protected override void RemoveEntry(string key)
|
||||
{
|
||||
_cache.Remove(key);
|
||||
}
|
||||
|
||||
protected override object GetEntry(string key)
|
||||
{
|
||||
return _cache.Get(key);
|
||||
}
|
||||
|
||||
#region Lock
|
||||
|
||||
protected override IDisposable ReadLock
|
||||
{
|
||||
get { return new ReadLock(_locker); }
|
||||
}
|
||||
|
||||
protected override IDisposable WriteLock
|
||||
{
|
||||
get { return new WriteLock(_locker); }
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get
|
||||
|
||||
/// <summary>
|
||||
/// Gets (and adds if necessary) an item from the cache with all of the default parameters
|
||||
/// </summary>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <returns></returns>
|
||||
public override object GetCacheItem(string cacheKey, Func<object> getCacheItem)
|
||||
{
|
||||
return GetCacheItem(cacheKey, getCacheItem, null, dependentFiles: null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This overload is here for legacy purposes
|
||||
/// </summary>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <param name="timeout"></param>
|
||||
/// <param name="isSliding"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="removedCallback"></param>
|
||||
/// <param name="dependency"></param>
|
||||
/// <returns></returns>
|
||||
internal object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null)
|
||||
{
|
||||
cacheKey = GetCacheKey(cacheKey);
|
||||
|
||||
// NOTE - because we don't know what getCacheItem does, how long it will take and whether it will hang,
|
||||
// getCacheItem should run OUTSIDE of the global application lock else we run into lock contention and
|
||||
// nasty performance issues.
|
||||
|
||||
// So.... we insert a Lazy<object> in the cache while holding the global application lock, and then rely
|
||||
// on the Lazy lock to ensure that getCacheItem runs once and everybody waits on it, while the global
|
||||
// application lock has been released.
|
||||
|
||||
// NOTE
|
||||
// The Lazy value creation may produce a null value.
|
||||
// Must make sure (for backward compatibility) that we pretend they are not in the cache.
|
||||
// So if we find an entry in the cache that already has its value created and is null,
|
||||
// pretend it was not there. If value is not already created, wait... and return null, that's
|
||||
// what prior code did.
|
||||
|
||||
// NOTE
|
||||
// The Lazy value creation may throw.
|
||||
|
||||
// So... the null value _will_ be in the cache but never returned
|
||||
|
||||
Lazy<object> result;
|
||||
|
||||
// Fast!
|
||||
// Only one thread can enter an UpgradeableReadLock at a time, but it does not prevent other
|
||||
// threads to enter a ReadLock in the meantime -- only upgrading to WriteLock will prevent all
|
||||
// reads. We first try with a normal ReadLock for maximum concurrency and take the penalty of
|
||||
// having to re-lock in case there's no value. Would need to benchmark to figure out whether
|
||||
// it's worth it, though...
|
||||
using (new ReadLock(_locker))
|
||||
{
|
||||
result = _cache.Get(cacheKey) as Lazy<object>; // null if key not found
|
||||
}
|
||||
var value = result == null ? null : GetSafeLazyValue(result);
|
||||
if (value != null) return value;
|
||||
|
||||
using (var lck = new UpgradeableReadLock(_locker))
|
||||
{
|
||||
result = _cache.Get(cacheKey) as Lazy<object>; // null if key not found
|
||||
|
||||
// cannot create value within the lock, so if result.IsValueCreated is false, just
|
||||
// do nothing here - means that if creation throws, a race condition could cause
|
||||
// more than one thread to reach the return statement below and throw - accepted.
|
||||
|
||||
if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
|
||||
{
|
||||
result = GetSafeLazy(getCacheItem);
|
||||
var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
|
||||
var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);
|
||||
|
||||
lck.UpgradeToWriteLock();
|
||||
//NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update!
|
||||
_cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
|
||||
}
|
||||
}
|
||||
|
||||
// using GetSafeLazy and GetSafeLazyValue ensures that we don't cache
|
||||
// exceptions (but try again and again) and silently eat them - however at
|
||||
// some point we have to report them - so need to re-throw here
|
||||
|
||||
// this does not throw anymore
|
||||
//return result.Value;
|
||||
|
||||
value = result.Value; // will not throw (safe lazy)
|
||||
if (value is ExceptionHolder eh) eh.Exception.Throw(); // throw once!
|
||||
return value;
|
||||
}
|
||||
|
||||
public object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
CacheDependency dependency = null;
|
||||
if (dependentFiles != null && dependentFiles.Any())
|
||||
{
|
||||
dependency = new CacheDependency(dependentFiles);
|
||||
}
|
||||
return GetCacheItem(cacheKey, getCacheItem, timeout, isSliding, priority, removedCallback, dependency);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Insert
|
||||
|
||||
/// <summary>
|
||||
/// This overload is here for legacy purposes
|
||||
/// </summary>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <param name="timeout"></param>
|
||||
/// <param name="isSliding"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="removedCallback"></param>
|
||||
/// <param name="dependency"></param>
|
||||
internal void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null)
|
||||
{
|
||||
// NOTE - here also we must insert a Lazy<object> but we can evaluate it right now
|
||||
// and make sure we don't store a null value.
|
||||
|
||||
var result = GetSafeLazy(getCacheItem);
|
||||
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
|
||||
if (value == null) return; // do not store null values (backward compat)
|
||||
|
||||
cacheKey = GetCacheKey(cacheKey);
|
||||
|
||||
var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
|
||||
var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);
|
||||
|
||||
using (new WriteLock(_locker))
|
||||
{
|
||||
//NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update!
|
||||
_cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
|
||||
}
|
||||
}
|
||||
|
||||
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
CacheDependency dependency = null;
|
||||
if (dependentFiles != null && dependentFiles.Any())
|
||||
{
|
||||
dependency = new CacheDependency(dependentFiles);
|
||||
}
|
||||
InsertCacheItem(cacheKey, getCacheItem, timeout, isSliding, priority, removedCallback, dependency);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Web.Caching;
|
||||
using CacheItemPriority = System.Web.Caching.CacheItemPriority;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A CacheProvider that wraps the logic of the HttpRuntime.Cache
|
||||
/// </summary>
|
||||
internal class HttpRuntimeCacheProvider : DictionaryCacheProviderBase, IRuntimeCacheProvider
|
||||
{
|
||||
// locker object that supports upgradeable read locking
|
||||
// does not need to support recursion if we implement the cache correctly and ensure
|
||||
// that methods cannot be reentrant, ie we do NOT create values while holding a lock.
|
||||
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.NoRecursion);
|
||||
|
||||
private readonly System.Web.Caching.Cache _cache;
|
||||
|
||||
/// <summary>
|
||||
/// Used for debugging
|
||||
/// </summary>
|
||||
internal Guid InstanceId { get; private set; }
|
||||
|
||||
public HttpRuntimeCacheProvider(System.Web.Caching.Cache cache)
|
||||
{
|
||||
_cache = cache;
|
||||
InstanceId = Guid.NewGuid();
|
||||
}
|
||||
|
||||
protected override IEnumerable<DictionaryEntry> GetDictionaryEntries()
|
||||
{
|
||||
const string prefix = CacheItemPrefix + "-";
|
||||
return _cache.Cast<DictionaryEntry>()
|
||||
.Where(x => x.Key is string && ((string)x.Key).StartsWith(prefix));
|
||||
}
|
||||
|
||||
protected override void RemoveEntry(string key)
|
||||
{
|
||||
_cache.Remove(key);
|
||||
}
|
||||
|
||||
protected override object GetEntry(string key)
|
||||
{
|
||||
return _cache.Get(key);
|
||||
}
|
||||
|
||||
#region Lock
|
||||
|
||||
protected override void EnterReadLock()
|
||||
{
|
||||
_locker.EnterReadLock();
|
||||
}
|
||||
|
||||
protected override void EnterWriteLock()
|
||||
{
|
||||
_locker.EnterWriteLock();;
|
||||
}
|
||||
|
||||
protected override void ExitReadLock()
|
||||
{
|
||||
if (_locker.IsReadLockHeld)
|
||||
_locker.ExitReadLock();
|
||||
}
|
||||
|
||||
protected override void ExitWriteLock()
|
||||
{
|
||||
if (_locker.IsWriteLockHeld)
|
||||
_locker.ExitWriteLock();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get
|
||||
|
||||
/// <summary>
|
||||
/// Gets (and adds if necessary) an item from the cache with all of the default parameters
|
||||
/// </summary>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <returns></returns>
|
||||
public override object GetCacheItem(string cacheKey, Func<object> getCacheItem)
|
||||
{
|
||||
return GetCacheItem(cacheKey, getCacheItem, null, dependentFiles: null);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// This overload is here for legacy purposes
|
||||
/// </summary>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <param name="timeout"></param>
|
||||
/// <param name="isSliding"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="removedCallback"></param>
|
||||
/// <param name="dependency"></param>
|
||||
/// <returns></returns>
|
||||
internal object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null)
|
||||
{
|
||||
cacheKey = GetCacheKey(cacheKey);
|
||||
|
||||
// NOTE - because we don't know what getCacheItem does, how long it will take and whether it will hang,
|
||||
// getCacheItem should run OUTSIDE of the global application lock else we run into lock contention and
|
||||
// nasty performance issues.
|
||||
|
||||
// So.... we insert a Lazy<object> in the cache while holding the global application lock, and then rely
|
||||
// on the Lazy lock to ensure that getCacheItem runs once and everybody waits on it, while the global
|
||||
// application lock has been released.
|
||||
|
||||
// NOTE
|
||||
// The Lazy value creation may produce a null value.
|
||||
// Must make sure (for backward compatibility) that we pretend they are not in the cache.
|
||||
// So if we find an entry in the cache that already has its value created and is null,
|
||||
// pretend it was not there. If value is not already created, wait... and return null, that's
|
||||
// what prior code did.
|
||||
|
||||
// NOTE
|
||||
// The Lazy value creation may throw.
|
||||
|
||||
// So... the null value _will_ be in the cache but never returned
|
||||
|
||||
Lazy<object> result;
|
||||
|
||||
// Fast!
|
||||
// Only one thread can enter an UpgradeableReadLock at a time, but it does not prevent other
|
||||
// threads to enter a ReadLock in the meantime -- only upgrading to WriteLock will prevent all
|
||||
// reads. We first try with a normal ReadLock for maximum concurrency and take the penalty of
|
||||
// having to re-lock in case there's no value. Would need to benchmark to figure out whether
|
||||
// it's worth it, though...
|
||||
try
|
||||
{
|
||||
_locker.EnterReadLock();
|
||||
result = _cache.Get(cacheKey) as Lazy<object>; // null if key not found
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsReadLockHeld)
|
||||
_locker.ExitReadLock();
|
||||
}
|
||||
var value = result == null ? null : GetSafeLazyValue(result);
|
||||
if (value != null) return value;
|
||||
|
||||
using (var lck = new UpgradeableReadLock(_locker))
|
||||
{
|
||||
result = _cache.Get(cacheKey) as Lazy<object>; // null if key not found
|
||||
|
||||
// cannot create value within the lock, so if result.IsValueCreated is false, just
|
||||
// do nothing here - means that if creation throws, a race condition could cause
|
||||
// more than one thread to reach the return statement below and throw - accepted.
|
||||
|
||||
if (result == null || GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
|
||||
{
|
||||
result = GetSafeLazy(getCacheItem);
|
||||
var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
|
||||
var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);
|
||||
|
||||
lck.UpgradeToWriteLock();
|
||||
//NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update!
|
||||
_cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
|
||||
}
|
||||
}
|
||||
|
||||
// using GetSafeLazy and GetSafeLazyValue ensures that we don't cache
|
||||
// exceptions (but try again and again) and silently eat them - however at
|
||||
// some point we have to report them - so need to re-throw here
|
||||
|
||||
// this does not throw anymore
|
||||
//return result.Value;
|
||||
|
||||
value = result.Value; // will not throw (safe lazy)
|
||||
if (value is ExceptionHolder eh) eh.Exception.Throw(); // throw once!
|
||||
return value;
|
||||
}
|
||||
|
||||
public object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
CacheDependency dependency = null;
|
||||
if (dependentFiles != null && dependentFiles.Any())
|
||||
{
|
||||
dependency = new CacheDependency(dependentFiles);
|
||||
}
|
||||
return GetCacheItem(cacheKey, getCacheItem, timeout, isSliding, priority, removedCallback, dependency);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Insert
|
||||
|
||||
/// <summary>
|
||||
/// This overload is here for legacy purposes
|
||||
/// </summary>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <param name="getCacheItem"></param>
|
||||
/// <param name="timeout"></param>
|
||||
/// <param name="isSliding"></param>
|
||||
/// <param name="priority"></param>
|
||||
/// <param name="removedCallback"></param>
|
||||
/// <param name="dependency"></param>
|
||||
internal void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, CacheDependency dependency = null)
|
||||
{
|
||||
// NOTE - here also we must insert a Lazy<object> but we can evaluate it right now
|
||||
// and make sure we don't store a null value.
|
||||
|
||||
var result = GetSafeLazy(getCacheItem);
|
||||
var value = result.Value; // force evaluation now - this may throw if cacheItem throws, and then nothing goes into cache
|
||||
if (value == null) return; // do not store null values (backward compat)
|
||||
|
||||
cacheKey = GetCacheKey(cacheKey);
|
||||
|
||||
var absolute = isSliding ? System.Web.Caching.Cache.NoAbsoluteExpiration : (timeout == null ? System.Web.Caching.Cache.NoAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
|
||||
var sliding = isSliding == false ? System.Web.Caching.Cache.NoSlidingExpiration : (timeout ?? System.Web.Caching.Cache.NoSlidingExpiration);
|
||||
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
//NOTE: 'Insert' on System.Web.Caching.Cache actually does an add or update!
|
||||
_cache.Insert(cacheKey, result, dependency, absolute, sliding, priority, removedCallback);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsWriteLockHeld)
|
||||
_locker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
CacheDependency dependency = null;
|
||||
if (dependentFiles != null && dependentFiles.Any())
|
||||
{
|
||||
dependency = new CacheDependency(dependentFiles);
|
||||
}
|
||||
InsertCacheItem(cacheKey, getCacheItem, timeout, isSliding, priority, removedCallback, dependency);
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,68 +1,68 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface for implementing a basic cache provider
|
||||
/// </summary>
|
||||
public interface ICacheProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Removes all items from the cache.
|
||||
/// </summary>
|
||||
void ClearAllCache();
|
||||
|
||||
/// <summary>
|
||||
/// Removes an item from the cache, identified by its key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the item.</param>
|
||||
void ClearCacheItem(string key);
|
||||
|
||||
/// <summary>
|
||||
/// Removes items from the cache, of a specified type.
|
||||
/// </summary>
|
||||
/// <param name="typeName">The name of the type to remove.</param>
|
||||
/// <remarks>
|
||||
/// <para>If the type is an interface, then all items of a type implementing that interface are
|
||||
/// removed. Otherwise, only items of that exact type are removed (items of type inheriting from
|
||||
/// the specified type are not removed).</para>
|
||||
/// <para>Performs a case-sensitive search.</para>
|
||||
/// </remarks>
|
||||
void ClearCacheObjectTypes(string typeName);
|
||||
|
||||
/// <summary>
|
||||
/// Removes items from the cache, of a specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the items to remove.</typeparam>
|
||||
/// <remarks>If the type is an interface, then all items of a type implementing that interface are
|
||||
/// removed. Otherwise, only items of that exact type are removed (items of type inheriting from
|
||||
/// the specified type are not removed).</remarks>
|
||||
void ClearCacheObjectTypes<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Removes items from the cache, of a specified type, satisfying a predicate.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the items to remove.</typeparam>
|
||||
/// <param name="predicate">The predicate to satisfy.</param>
|
||||
/// <remarks>If the type is an interface, then all items of a type implementing that interface are
|
||||
/// removed. Otherwise, only items of that exact type are removed (items of type inheriting from
|
||||
/// the specified type are not removed).</remarks>
|
||||
void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate);
|
||||
|
||||
void ClearCacheByKeySearch(string keyStartsWith);
|
||||
void ClearCacheByKeyExpression(string regexString);
|
||||
|
||||
IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith);
|
||||
IEnumerable<object> GetCacheItemsByKeyExpression(string regexString);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an item with a given key
|
||||
/// </summary>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <returns></returns>
|
||||
object GetCacheItem(string cacheKey);
|
||||
|
||||
object GetCacheItem(string cacheKey, Func<object> getCacheItem);
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// An interface for implementing a basic cache provider
|
||||
/// </summary>
|
||||
public interface ICacheProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// Removes all items from the cache.
|
||||
/// </summary>
|
||||
void ClearAllCache();
|
||||
|
||||
/// <summary>
|
||||
/// Removes an item from the cache, identified by its key.
|
||||
/// </summary>
|
||||
/// <param name="key">The key of the item.</param>
|
||||
void ClearCacheItem(string key);
|
||||
|
||||
/// <summary>
|
||||
/// Removes items from the cache, of a specified type.
|
||||
/// </summary>
|
||||
/// <param name="typeName">The name of the type to remove.</param>
|
||||
/// <remarks>
|
||||
/// <para>If the type is an interface, then all items of a type implementing that interface are
|
||||
/// removed. Otherwise, only items of that exact type are removed (items of type inheriting from
|
||||
/// the specified type are not removed).</para>
|
||||
/// <para>Performs a case-sensitive search.</para>
|
||||
/// </remarks>
|
||||
void ClearCacheObjectTypes(string typeName);
|
||||
|
||||
/// <summary>
|
||||
/// Removes items from the cache, of a specified type.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the items to remove.</typeparam>
|
||||
/// <remarks>If the type is an interface, then all items of a type implementing that interface are
|
||||
/// removed. Otherwise, only items of that exact type are removed (items of type inheriting from
|
||||
/// the specified type are not removed).</remarks>
|
||||
void ClearCacheObjectTypes<T>();
|
||||
|
||||
/// <summary>
|
||||
/// Removes items from the cache, of a specified type, satisfying a predicate.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the items to remove.</typeparam>
|
||||
/// <param name="predicate">The predicate to satisfy.</param>
|
||||
/// <remarks>If the type is an interface, then all items of a type implementing that interface are
|
||||
/// removed. Otherwise, only items of that exact type are removed (items of type inheriting from
|
||||
/// the specified type are not removed).</remarks>
|
||||
void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate);
|
||||
|
||||
void ClearCacheByKeySearch(string keyStartsWith);
|
||||
void ClearCacheByKeyExpression(string regexString);
|
||||
|
||||
IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith);
|
||||
IEnumerable<object> GetCacheItemsByKeyExpression(string regexString);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an item with a given key
|
||||
/// </summary>
|
||||
/// <param name="cacheKey"></param>
|
||||
/// <returns></returns>
|
||||
object GetCacheItem(string cacheKey);
|
||||
|
||||
object GetCacheItem(string cacheKey, Func<object> getCacheItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,33 +1,33 @@
|
||||
using System;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// The IcacheRefresher Interface is used for loadbalancing.
|
||||
///
|
||||
/// </summary>
|
||||
public interface ICacheRefresher : IDiscoverable
|
||||
{
|
||||
Guid RefresherUniqueId { get; }
|
||||
string Name { get; }
|
||||
void RefreshAll();
|
||||
void Refresh(int id);
|
||||
void Remove(int id);
|
||||
void Refresh(Guid id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Strongly type cache refresher that is able to refresh cache of real instances of objects as well as IDs
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <remarks>
|
||||
/// This is much better for performance when we're not running in a load balanced environment so we can refresh the cache
|
||||
/// against a already resolved object instead of looking the object back up by id.
|
||||
/// </remarks>
|
||||
interface ICacheRefresher<T> : ICacheRefresher
|
||||
{
|
||||
void Refresh(T instance);
|
||||
void Remove(T instance);
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using Umbraco.Core.Composing;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// The IcacheRefresher Interface is used for loadbalancing.
|
||||
///
|
||||
/// </summary>
|
||||
public interface ICacheRefresher : IDiscoverable
|
||||
{
|
||||
Guid RefresherUniqueId { get; }
|
||||
string Name { get; }
|
||||
void RefreshAll();
|
||||
void Refresh(int id);
|
||||
void Remove(int id);
|
||||
void Refresh(Guid id);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Strongly type cache refresher that is able to refresh cache of real instances of objects as well as IDs
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <remarks>
|
||||
/// This is much better for performance when we're not running in a load balanced environment so we can refresh the cache
|
||||
/// against a already resolved object instead of looking the object back up by id.
|
||||
/// </remarks>
|
||||
interface ICacheRefresher<T> : ICacheRefresher
|
||||
{
|
||||
void Refresh(T instance);
|
||||
void Remove(T instance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A cache refresher that supports refreshing or removing cache based on a custom Json payload
|
||||
/// </summary>
|
||||
interface IJsonCacheRefresher : ICacheRefresher
|
||||
{
|
||||
/// <summary>
|
||||
/// Refreshes, clears, etc... any cache based on the information provided in the json
|
||||
/// </summary>
|
||||
/// <param name="json"></param>
|
||||
void Refresh(string json);
|
||||
}
|
||||
}
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A cache refresher that supports refreshing or removing cache based on a custom Json payload
|
||||
/// </summary>
|
||||
interface IJsonCacheRefresher : ICacheRefresher
|
||||
{
|
||||
/// <summary>
|
||||
/// Refreshes, clears, etc... any cache based on the information provided in the json
|
||||
/// </summary>
|
||||
/// <param name="json"></param>
|
||||
void Refresh(string json);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
using System;
|
||||
using System.Runtime.Caching;
|
||||
using System.Text;
|
||||
using System.Web.Caching;
|
||||
using CacheItemPriority = System.Web.Caching.CacheItemPriority;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// An abstract class for implementing a runtime cache provider
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
public interface IRuntimeCacheProvider : ICacheProvider
|
||||
{
|
||||
object GetCacheItem(
|
||||
string cacheKey,
|
||||
Func<object> getCacheItem,
|
||||
TimeSpan? timeout,
|
||||
bool isSliding = false,
|
||||
CacheItemPriority priority = CacheItemPriority.Normal,
|
||||
CacheItemRemovedCallback removedCallback = null,
|
||||
string[] dependentFiles = null);
|
||||
|
||||
void InsertCacheItem(
|
||||
string cacheKey,
|
||||
Func<object> getCacheItem,
|
||||
TimeSpan? timeout = null,
|
||||
bool isSliding = false,
|
||||
CacheItemPriority priority = CacheItemPriority.Normal,
|
||||
CacheItemRemovedCallback removedCallback = null,
|
||||
string[] dependentFiles = null);
|
||||
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Runtime.Caching;
|
||||
using System.Text;
|
||||
using System.Web.Caching;
|
||||
using CacheItemPriority = System.Web.Caching.CacheItemPriority;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// An abstract class for implementing a runtime cache provider
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// </remarks>
|
||||
public interface IRuntimeCacheProvider : ICacheProvider
|
||||
{
|
||||
object GetCacheItem(
|
||||
string cacheKey,
|
||||
Func<object> getCacheItem,
|
||||
TimeSpan? timeout,
|
||||
bool isSliding = false,
|
||||
CacheItemPriority priority = CacheItemPriority.Normal,
|
||||
CacheItemRemovedCallback removedCallback = null,
|
||||
string[] dependentFiles = null);
|
||||
|
||||
void InsertCacheItem(
|
||||
string cacheKey,
|
||||
Func<object> getCacheItem,
|
||||
TimeSpan? timeout = null,
|
||||
bool isSliding = false,
|
||||
CacheItemPriority priority = CacheItemPriority.Normal,
|
||||
CacheItemRemovedCallback removedCallback = null,
|
||||
string[] dependentFiles = null);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +1,29 @@
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for "json" cache refreshers.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInstanceType">The actual cache refresher type.</typeparam>
|
||||
/// <remarks>The actual cache refresher type is used for strongly typed events.</remarks>
|
||||
public abstract class JsonCacheRefresherBase<TInstanceType> : CacheRefresherBase<TInstanceType>, IJsonCacheRefresher
|
||||
where TInstanceType : class, ICacheRefresher
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonCacheRefresherBase{TInstanceType}"/>.
|
||||
/// </summary>
|
||||
/// <param name="cacheHelper">A cache helper.</param>
|
||||
protected JsonCacheRefresherBase(CacheHelper cacheHelper) : base(cacheHelper)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes as specified by a json payload.
|
||||
/// </summary>
|
||||
/// <param name="json">The json payload.</param>
|
||||
public virtual void Refresh(string json)
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(json, MessageType.RefreshByJson));
|
||||
}
|
||||
}
|
||||
}
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for "json" cache refreshers.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInstanceType">The actual cache refresher type.</typeparam>
|
||||
/// <remarks>The actual cache refresher type is used for strongly typed events.</remarks>
|
||||
public abstract class JsonCacheRefresherBase<TInstanceType> : CacheRefresherBase<TInstanceType>, IJsonCacheRefresher
|
||||
where TInstanceType : class, ICacheRefresher
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonCacheRefresherBase{TInstanceType}"/>.
|
||||
/// </summary>
|
||||
/// <param name="cacheHelper">A cache helper.</param>
|
||||
protected JsonCacheRefresherBase(CacheHelper cacheHelper) : base(cacheHelper)
|
||||
{ }
|
||||
|
||||
/// <summary>
|
||||
/// Refreshes as specified by a json payload.
|
||||
/// </summary>
|
||||
/// <param name="json">The json payload.</param>
|
||||
public virtual void Refresh(string json)
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(json, MessageType.RefreshByJson));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,66 +1,66 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a cache provider that does not cache anything.
|
||||
/// </summary>
|
||||
public class NullCacheProvider : IRuntimeCacheProvider
|
||||
{
|
||||
private NullCacheProvider() { }
|
||||
|
||||
public static NullCacheProvider Instance { get; } = new NullCacheProvider();
|
||||
|
||||
public virtual void ClearAllCache()
|
||||
{ }
|
||||
|
||||
public virtual void ClearCacheItem(string key)
|
||||
{ }
|
||||
|
||||
public virtual void ClearCacheObjectTypes(string typeName)
|
||||
{ }
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>()
|
||||
{ }
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
|
||||
{ }
|
||||
|
||||
public virtual void ClearCacheByKeySearch(string keyStartsWith)
|
||||
{ }
|
||||
|
||||
public virtual void ClearCacheByKeyExpression(string regexString)
|
||||
{ }
|
||||
|
||||
public virtual IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
|
||||
{
|
||||
return Enumerable.Empty<object>();
|
||||
}
|
||||
|
||||
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
|
||||
{
|
||||
return Enumerable.Empty<object>();
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey)
|
||||
{
|
||||
return default(object);
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey, Func<object> getCacheItem)
|
||||
{
|
||||
return getCacheItem();
|
||||
}
|
||||
|
||||
public object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
return getCacheItem();
|
||||
}
|
||||
|
||||
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Web.Caching;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a cache provider that does not cache anything.
|
||||
/// </summary>
|
||||
public class NullCacheProvider : IRuntimeCacheProvider
|
||||
{
|
||||
private NullCacheProvider() { }
|
||||
|
||||
public static NullCacheProvider Instance { get; } = new NullCacheProvider();
|
||||
|
||||
public virtual void ClearAllCache()
|
||||
{ }
|
||||
|
||||
public virtual void ClearCacheItem(string key)
|
||||
{ }
|
||||
|
||||
public virtual void ClearCacheObjectTypes(string typeName)
|
||||
{ }
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>()
|
||||
{ }
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
|
||||
{ }
|
||||
|
||||
public virtual void ClearCacheByKeySearch(string keyStartsWith)
|
||||
{ }
|
||||
|
||||
public virtual void ClearCacheByKeyExpression(string regexString)
|
||||
{ }
|
||||
|
||||
public virtual IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
|
||||
{
|
||||
return Enumerable.Empty<object>();
|
||||
}
|
||||
|
||||
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
|
||||
{
|
||||
return Enumerable.Empty<object>();
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey)
|
||||
{
|
||||
return default(object);
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey, Func<object> getCacheItem)
|
||||
{
|
||||
return getCacheItem();
|
||||
}
|
||||
|
||||
public object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
return getCacheItem();
|
||||
}
|
||||
|
||||
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{ }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,299 +1,359 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Caching;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Web.Caching;
|
||||
using Umbraco.Core.Composing;
|
||||
using CacheItemPriority = System.Web.Caching.CacheItemPriority;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a cache provider that caches item in a <see cref="MemoryCache"/>.
|
||||
/// A cache provider that wraps the logic of a System.Runtime.Caching.ObjectCache
|
||||
/// </summary>
|
||||
/// <remarks>The <see cref="MemoryCache"/> is created with name "in-memory". That name is
|
||||
/// used to retrieve configuration options. It does not identify the memory cache, i.e.
|
||||
/// each instance of this class has its own, independent, memory cache.</remarks>
|
||||
public class ObjectCacheRuntimeCacheProvider : IRuntimeCacheProvider
|
||||
{
|
||||
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
|
||||
internal ObjectCache MemoryCache;
|
||||
|
||||
/// <summary>
|
||||
/// Used for debugging
|
||||
/// </summary>
|
||||
internal Guid InstanceId { get; private set; }
|
||||
|
||||
public ObjectCacheRuntimeCacheProvider()
|
||||
{
|
||||
MemoryCache = new MemoryCache("in-memory");
|
||||
InstanceId = Guid.NewGuid();
|
||||
}
|
||||
|
||||
#region Clear
|
||||
|
||||
public virtual void ClearAllCache()
|
||||
{
|
||||
using (new WriteLock(_locker))
|
||||
{
|
||||
MemoryCache.DisposeIfDisposable();
|
||||
MemoryCache = new MemoryCache("in-memory");
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheItem(string key)
|
||||
{
|
||||
using (new WriteLock(_locker))
|
||||
{
|
||||
if (MemoryCache[key] == null) return;
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes(string typeName)
|
||||
{
|
||||
var type = TypeFinder.GetTypeByName(typeName);
|
||||
if (type == null) return;
|
||||
var isInterface = type.IsInterface;
|
||||
using (new WriteLock(_locker))
|
||||
{
|
||||
foreach (var key in MemoryCache
|
||||
.Where(x =>
|
||||
{
|
||||
// x.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type));
|
||||
})
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>()
|
||||
{
|
||||
using (new WriteLock(_locker))
|
||||
{
|
||||
var typeOfT = typeof (T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
foreach (var key in MemoryCache
|
||||
.Where(x =>
|
||||
{
|
||||
// x.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT));
|
||||
|
||||
})
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
|
||||
{
|
||||
using (new WriteLock(_locker))
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
foreach (var key in MemoryCache
|
||||
.Where(x =>
|
||||
{
|
||||
// x.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
if (value == null) return true;
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return (isInterface ? (value is T) : (value.GetType() == typeOfT))
|
||||
&& predicate(x.Key, (T)value);
|
||||
})
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeySearch(string keyStartsWith)
|
||||
{
|
||||
using (new WriteLock(_locker))
|
||||
{
|
||||
foreach (var key in MemoryCache
|
||||
.Where(x => x.Key.InvariantStartsWith(keyStartsWith))
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeyExpression(string regexString)
|
||||
{
|
||||
using (new WriteLock(_locker))
|
||||
{
|
||||
foreach (var key in MemoryCache
|
||||
.Where(x => Regex.IsMatch(x.Key, regexString))
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get
|
||||
|
||||
public IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
|
||||
{
|
||||
KeyValuePair<string, object>[] entries;
|
||||
using (new ReadLock(_locker))
|
||||
{
|
||||
entries = MemoryCache
|
||||
.Where(x => x.Key.InvariantStartsWith(keyStartsWith))
|
||||
.ToArray(); // evaluate while locked
|
||||
}
|
||||
return entries
|
||||
.Select(x => DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
|
||||
.Where(x => x != null) // backward compat, don't store null values in the cache
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
|
||||
{
|
||||
KeyValuePair<string, object>[] entries;
|
||||
using (new ReadLock(_locker))
|
||||
{
|
||||
entries = MemoryCache
|
||||
.Where(x => Regex.IsMatch(x.Key, regexString))
|
||||
.ToArray(); // evaluate while locked
|
||||
}
|
||||
return entries
|
||||
.Select(x => DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
|
||||
.Where(x => x != null) // backward compat, don't store null values in the cache
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public object GetCacheItem(string cacheKey)
|
||||
{
|
||||
Lazy<object> result;
|
||||
using (new ReadLock(_locker))
|
||||
{
|
||||
result = MemoryCache.Get(cacheKey) as Lazy<object>; // null if key not found
|
||||
}
|
||||
return result == null ? null : DictionaryCacheProviderBase.GetSafeLazyValue(result); // return exceptions as null
|
||||
}
|
||||
|
||||
public object GetCacheItem(string cacheKey, Func<object> getCacheItem)
|
||||
{
|
||||
return GetCacheItem(cacheKey, getCacheItem, null);
|
||||
}
|
||||
|
||||
public object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
// see notes in HttpRuntimeCacheProvider
|
||||
|
||||
Lazy<object> result;
|
||||
|
||||
using (var lck = new UpgradeableReadLock(_locker))
|
||||
{
|
||||
result = MemoryCache.Get(cacheKey) as Lazy<object>;
|
||||
if (result == null || DictionaryCacheProviderBase.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
|
||||
{
|
||||
result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem);
|
||||
var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);
|
||||
|
||||
lck.UpgradeToWriteLock();
|
||||
//NOTE: This does an add or update
|
||||
MemoryCache.Set(cacheKey, result, policy);
|
||||
}
|
||||
}
|
||||
|
||||
//return result.Value;
|
||||
|
||||
var value = result.Value; // will not throw (safe lazy)
|
||||
if (value is DictionaryCacheProviderBase.ExceptionHolder eh) eh.Exception.Throw(); // throw once!
|
||||
return value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Insert
|
||||
|
||||
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
// NOTE - here also we must insert a Lazy<object> but we can evaluate it right now
|
||||
// and make sure we don't store a null value.
|
||||
|
||||
var result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem);
|
||||
var value = result.Value; // force evaluation now
|
||||
if (value == null) return; // do not store null values (backward compat)
|
||||
|
||||
var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);
|
||||
//NOTE: This does an add or update
|
||||
MemoryCache.Set(cacheKey, result, policy);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static CacheItemPolicy GetPolicy(TimeSpan? timeout = null, bool isSliding = false, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
var absolute = isSliding ? ObjectCache.InfiniteAbsoluteExpiration : (timeout == null ? ObjectCache.InfiniteAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
|
||||
var sliding = isSliding == false ? ObjectCache.NoSlidingExpiration : (timeout ?? ObjectCache.NoSlidingExpiration);
|
||||
|
||||
var policy = new CacheItemPolicy
|
||||
{
|
||||
AbsoluteExpiration = absolute,
|
||||
SlidingExpiration = sliding
|
||||
};
|
||||
|
||||
if (dependentFiles != null && dependentFiles.Any())
|
||||
{
|
||||
policy.ChangeMonitors.Add(new HostFileChangeMonitor(dependentFiles.ToList()));
|
||||
}
|
||||
|
||||
if (removedCallback != null)
|
||||
{
|
||||
policy.RemovedCallback = arguments =>
|
||||
{
|
||||
//convert the reason
|
||||
var reason = CacheItemRemovedReason.Removed;
|
||||
switch (arguments.RemovedReason)
|
||||
{
|
||||
case CacheEntryRemovedReason.Removed:
|
||||
reason = CacheItemRemovedReason.Removed;
|
||||
break;
|
||||
case CacheEntryRemovedReason.Expired:
|
||||
reason = CacheItemRemovedReason.Expired;
|
||||
break;
|
||||
case CacheEntryRemovedReason.Evicted:
|
||||
reason = CacheItemRemovedReason.Underused;
|
||||
break;
|
||||
case CacheEntryRemovedReason.ChangeMonitorChanged:
|
||||
reason = CacheItemRemovedReason.Expired;
|
||||
break;
|
||||
case CacheEntryRemovedReason.CacheSpecificEviction:
|
||||
reason = CacheItemRemovedReason.Underused;
|
||||
break;
|
||||
}
|
||||
//call the callback
|
||||
removedCallback(arguments.CacheItem.Key, arguments.CacheItem.Value, reason);
|
||||
};
|
||||
}
|
||||
return policy;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Caching;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading;
|
||||
using System.Web.Caching;
|
||||
using Umbraco.Core.Composing;
|
||||
using CacheItemPriority = System.Web.Caching.CacheItemPriority;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a cache provider that caches item in a <see cref="MemoryCache"/>.
|
||||
/// A cache provider that wraps the logic of a System.Runtime.Caching.ObjectCache
|
||||
/// </summary>
|
||||
/// <remarks>The <see cref="MemoryCache"/> is created with name "in-memory". That name is
|
||||
/// used to retrieve configuration options. It does not identify the memory cache, i.e.
|
||||
/// each instance of this class has its own, independent, memory cache.</remarks>
|
||||
public class ObjectCacheRuntimeCacheProvider : IRuntimeCacheProvider
|
||||
{
|
||||
private readonly ReaderWriterLockSlim _locker = new ReaderWriterLockSlim(LockRecursionPolicy.SupportsRecursion);
|
||||
internal ObjectCache MemoryCache;
|
||||
|
||||
/// <summary>
|
||||
/// Used for debugging
|
||||
/// </summary>
|
||||
internal Guid InstanceId { get; private set; }
|
||||
|
||||
public ObjectCacheRuntimeCacheProvider()
|
||||
{
|
||||
MemoryCache = new MemoryCache("in-memory");
|
||||
InstanceId = Guid.NewGuid();
|
||||
}
|
||||
|
||||
#region Clear
|
||||
|
||||
public virtual void ClearAllCache()
|
||||
{
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
MemoryCache.DisposeIfDisposable();
|
||||
MemoryCache = new MemoryCache("in-memory");
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsWriteLockHeld)
|
||||
_locker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheItem(string key)
|
||||
{
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
if (MemoryCache[key] == null) return;
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsWriteLockHeld)
|
||||
_locker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes(string typeName)
|
||||
{
|
||||
var type = TypeFinder.GetTypeByName(typeName);
|
||||
if (type == null) return;
|
||||
var isInterface = type.IsInterface;
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
foreach (var key in MemoryCache
|
||||
.Where(x =>
|
||||
{
|
||||
// x.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (type.IsInstanceOfType(value)) : (value.GetType() == type));
|
||||
})
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsWriteLockHeld)
|
||||
_locker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>()
|
||||
{
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
var typeOfT = typeof (T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
foreach (var key in MemoryCache
|
||||
.Where(x =>
|
||||
{
|
||||
// x.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return value == null || (isInterface ? (value is T) : (value.GetType() == typeOfT));
|
||||
|
||||
})
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsWriteLockHeld)
|
||||
_locker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
|
||||
{
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
var typeOfT = typeof(T);
|
||||
var isInterface = typeOfT.IsInterface;
|
||||
foreach (var key in MemoryCache
|
||||
.Where(x =>
|
||||
{
|
||||
// x.Value is Lazy<object> and not null, its value may be null
|
||||
// remove null values as well, does not hurt
|
||||
// get non-created as NonCreatedValue & exceptions as null
|
||||
var value = DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value, true);
|
||||
if (value == null) return true;
|
||||
|
||||
// if T is an interface remove anything that implements that interface
|
||||
// otherwise remove exact types (not inherited types)
|
||||
return (isInterface ? (value is T) : (value.GetType() == typeOfT))
|
||||
&& predicate(x.Key, (T)value);
|
||||
})
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsWriteLockHeld)
|
||||
_locker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeySearch(string keyStartsWith)
|
||||
{
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
foreach (var key in MemoryCache
|
||||
.Where(x => x.Key.InvariantStartsWith(keyStartsWith))
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsWriteLockHeld)
|
||||
_locker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeyExpression(string regexString)
|
||||
{
|
||||
try
|
||||
{
|
||||
_locker.EnterWriteLock();
|
||||
foreach (var key in MemoryCache
|
||||
.Where(x => Regex.IsMatch(x.Key, regexString))
|
||||
.Select(x => x.Key)
|
||||
.ToArray()) // ToArray required to remove
|
||||
MemoryCache.Remove(key);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsWriteLockHeld)
|
||||
_locker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Get
|
||||
|
||||
public IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
|
||||
{
|
||||
KeyValuePair<string, object>[] entries;
|
||||
try
|
||||
{
|
||||
_locker.EnterReadLock();
|
||||
entries = MemoryCache
|
||||
.Where(x => x.Key.InvariantStartsWith(keyStartsWith))
|
||||
.ToArray(); // evaluate while locked
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsReadLockHeld)
|
||||
_locker.ExitReadLock();
|
||||
}
|
||||
return entries
|
||||
.Select(x => DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
|
||||
.Where(x => x != null) // backward compat, don't store null values in the cache
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
|
||||
{
|
||||
KeyValuePair<string, object>[] entries;
|
||||
try
|
||||
{
|
||||
_locker.EnterReadLock();
|
||||
entries = MemoryCache
|
||||
.Where(x => Regex.IsMatch(x.Key, regexString))
|
||||
.ToArray(); // evaluate while locked
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsReadLockHeld)
|
||||
_locker.ExitReadLock();
|
||||
}
|
||||
return entries
|
||||
.Select(x => DictionaryCacheProviderBase.GetSafeLazyValue((Lazy<object>)x.Value)) // return exceptions as null
|
||||
.Where(x => x != null) // backward compat, don't store null values in the cache
|
||||
.ToList();
|
||||
}
|
||||
|
||||
public object GetCacheItem(string cacheKey)
|
||||
{
|
||||
Lazy<object> result;
|
||||
try
|
||||
{
|
||||
_locker.EnterReadLock();
|
||||
result = MemoryCache.Get(cacheKey) as Lazy<object>; // null if key not found
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_locker.IsReadLockHeld)
|
||||
_locker.ExitReadLock();
|
||||
}
|
||||
return result == null ? null : DictionaryCacheProviderBase.GetSafeLazyValue(result); // return exceptions as null
|
||||
}
|
||||
|
||||
public object GetCacheItem(string cacheKey, Func<object> getCacheItem)
|
||||
{
|
||||
return GetCacheItem(cacheKey, getCacheItem, null);
|
||||
}
|
||||
|
||||
public object GetCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
// see notes in HttpRuntimeCacheProvider
|
||||
|
||||
Lazy<object> result;
|
||||
|
||||
using (var lck = new UpgradeableReadLock(_locker))
|
||||
{
|
||||
result = MemoryCache.Get(cacheKey) as Lazy<object>;
|
||||
if (result == null || DictionaryCacheProviderBase.GetSafeLazyValue(result, true) == null) // get non-created as NonCreatedValue & exceptions as null
|
||||
{
|
||||
result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem);
|
||||
var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);
|
||||
|
||||
lck.UpgradeToWriteLock();
|
||||
//NOTE: This does an add or update
|
||||
MemoryCache.Set(cacheKey, result, policy);
|
||||
}
|
||||
}
|
||||
|
||||
//return result.Value;
|
||||
|
||||
var value = result.Value; // will not throw (safe lazy)
|
||||
if (value is DictionaryCacheProviderBase.ExceptionHolder eh) eh.Exception.Throw(); // throw once!
|
||||
return value;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region Insert
|
||||
|
||||
public void InsertCacheItem(string cacheKey, Func<object> getCacheItem, TimeSpan? timeout = null, bool isSliding = false, CacheItemPriority priority = CacheItemPriority.Normal, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
// NOTE - here also we must insert a Lazy<object> but we can evaluate it right now
|
||||
// and make sure we don't store a null value.
|
||||
|
||||
var result = DictionaryCacheProviderBase.GetSafeLazy(getCacheItem);
|
||||
var value = result.Value; // force evaluation now
|
||||
if (value == null) return; // do not store null values (backward compat)
|
||||
|
||||
var policy = GetPolicy(timeout, isSliding, removedCallback, dependentFiles);
|
||||
//NOTE: This does an add or update
|
||||
MemoryCache.Set(cacheKey, result, policy);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
private static CacheItemPolicy GetPolicy(TimeSpan? timeout = null, bool isSliding = false, CacheItemRemovedCallback removedCallback = null, string[] dependentFiles = null)
|
||||
{
|
||||
var absolute = isSliding ? ObjectCache.InfiniteAbsoluteExpiration : (timeout == null ? ObjectCache.InfiniteAbsoluteExpiration : DateTime.Now.Add(timeout.Value));
|
||||
var sliding = isSliding == false ? ObjectCache.NoSlidingExpiration : (timeout ?? ObjectCache.NoSlidingExpiration);
|
||||
|
||||
var policy = new CacheItemPolicy
|
||||
{
|
||||
AbsoluteExpiration = absolute,
|
||||
SlidingExpiration = sliding
|
||||
};
|
||||
|
||||
if (dependentFiles != null && dependentFiles.Any())
|
||||
{
|
||||
policy.ChangeMonitors.Add(new HostFileChangeMonitor(dependentFiles.ToList()));
|
||||
}
|
||||
|
||||
if (removedCallback != null)
|
||||
{
|
||||
policy.RemovedCallback = arguments =>
|
||||
{
|
||||
//convert the reason
|
||||
var reason = CacheItemRemovedReason.Removed;
|
||||
switch (arguments.RemovedReason)
|
||||
{
|
||||
case CacheEntryRemovedReason.Removed:
|
||||
reason = CacheItemRemovedReason.Removed;
|
||||
break;
|
||||
case CacheEntryRemovedReason.Expired:
|
||||
reason = CacheItemRemovedReason.Expired;
|
||||
break;
|
||||
case CacheEntryRemovedReason.Evicted:
|
||||
reason = CacheItemRemovedReason.Underused;
|
||||
break;
|
||||
case CacheEntryRemovedReason.ChangeMonitorChanged:
|
||||
reason = CacheItemRemovedReason.Expired;
|
||||
break;
|
||||
case CacheEntryRemovedReason.CacheSpecificEviction:
|
||||
reason = CacheItemRemovedReason.Underused;
|
||||
break;
|
||||
}
|
||||
//call the callback
|
||||
removedCallback(arguments.CacheItem.Key, arguments.CacheItem.Value, reason);
|
||||
};
|
||||
}
|
||||
return policy;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,79 +1,79 @@
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a cache provider that statically caches item in a concurrent dictionary.
|
||||
/// </summary>
|
||||
public class StaticCacheProvider : ICacheProvider
|
||||
{
|
||||
internal readonly ConcurrentDictionary<string, object> StaticCache = new ConcurrentDictionary<string, object>();
|
||||
|
||||
public virtual void ClearAllCache()
|
||||
{
|
||||
StaticCache.Clear();
|
||||
}
|
||||
|
||||
public virtual void ClearCacheItem(string key)
|
||||
{
|
||||
object val;
|
||||
StaticCache.TryRemove(key, out val);
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes(string typeName)
|
||||
{
|
||||
StaticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType().ToString().InvariantEquals(typeName));
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>()
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
StaticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT);
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
StaticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT && predicate(kvp.Key, (T)kvp.Value));
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeySearch(string keyStartsWith)
|
||||
{
|
||||
StaticCache.RemoveAll(kvp => kvp.Key.InvariantStartsWith(keyStartsWith));
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeyExpression(string regexString)
|
||||
{
|
||||
StaticCache.RemoveAll(kvp => Regex.IsMatch(kvp.Key, regexString));
|
||||
}
|
||||
|
||||
public virtual IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
|
||||
{
|
||||
return (from KeyValuePair<string, object> c in StaticCache
|
||||
where c.Key.InvariantStartsWith(keyStartsWith)
|
||||
select c.Value).ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
|
||||
{
|
||||
return (from KeyValuePair<string, object> c in StaticCache
|
||||
where Regex.IsMatch(c.Key, regexString)
|
||||
select c.Value).ToList();
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey)
|
||||
{
|
||||
var result = StaticCache[cacheKey];
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey, Func<object> getCacheItem)
|
||||
{
|
||||
return StaticCache.GetOrAdd(cacheKey, key => getCacheItem());
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a cache provider that statically caches item in a concurrent dictionary.
|
||||
/// </summary>
|
||||
public class StaticCacheProvider : ICacheProvider
|
||||
{
|
||||
internal readonly ConcurrentDictionary<string, object> StaticCache = new ConcurrentDictionary<string, object>();
|
||||
|
||||
public virtual void ClearAllCache()
|
||||
{
|
||||
StaticCache.Clear();
|
||||
}
|
||||
|
||||
public virtual void ClearCacheItem(string key)
|
||||
{
|
||||
object val;
|
||||
StaticCache.TryRemove(key, out val);
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes(string typeName)
|
||||
{
|
||||
StaticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType().ToString().InvariantEquals(typeName));
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>()
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
StaticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT);
|
||||
}
|
||||
|
||||
public virtual void ClearCacheObjectTypes<T>(Func<string, T, bool> predicate)
|
||||
{
|
||||
var typeOfT = typeof(T);
|
||||
StaticCache.RemoveAll(kvp => kvp.Value != null && kvp.Value.GetType() == typeOfT && predicate(kvp.Key, (T)kvp.Value));
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeySearch(string keyStartsWith)
|
||||
{
|
||||
StaticCache.RemoveAll(kvp => kvp.Key.InvariantStartsWith(keyStartsWith));
|
||||
}
|
||||
|
||||
public virtual void ClearCacheByKeyExpression(string regexString)
|
||||
{
|
||||
StaticCache.RemoveAll(kvp => Regex.IsMatch(kvp.Key, regexString));
|
||||
}
|
||||
|
||||
public virtual IEnumerable<object> GetCacheItemsByKeySearch(string keyStartsWith)
|
||||
{
|
||||
return (from KeyValuePair<string, object> c in StaticCache
|
||||
where c.Key.InvariantStartsWith(keyStartsWith)
|
||||
select c.Value).ToList();
|
||||
}
|
||||
|
||||
public IEnumerable<object> GetCacheItemsByKeyExpression(string regexString)
|
||||
{
|
||||
return (from KeyValuePair<string, object> c in StaticCache
|
||||
where Regex.IsMatch(c.Key, regexString)
|
||||
select c.Value).ToList();
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey)
|
||||
{
|
||||
var result = StaticCache[cacheKey];
|
||||
return result;
|
||||
}
|
||||
|
||||
public virtual object GetCacheItem(string cacheKey, Func<object> getCacheItem)
|
||||
{
|
||||
return StaticCache.GetOrAdd(cacheKey, key => getCacheItem());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,36 @@
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for "typed" cache refreshers.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInstanceType">The actual cache refresher type.</typeparam>
|
||||
/// <typeparam name="TEntityType">The entity type.</typeparam>
|
||||
/// <remarks>The actual cache refresher type is used for strongly typed events.</remarks>
|
||||
public abstract class TypedCacheRefresherBase<TInstanceType, TEntityType> : CacheRefresherBase<TInstanceType>, ICacheRefresher<TEntityType>
|
||||
where TInstanceType : class, ICacheRefresher
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TypedCacheRefresherBase{TInstanceType, TEntityType}"/>.
|
||||
/// </summary>
|
||||
/// <param name="cacheHelper">A cache helper.</param>
|
||||
protected TypedCacheRefresherBase(CacheHelper cacheHelper)
|
||||
: base(cacheHelper)
|
||||
{ }
|
||||
|
||||
#region Refresher
|
||||
|
||||
public virtual void Refresh(TEntityType instance)
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(instance, MessageType.RefreshByInstance));
|
||||
}
|
||||
|
||||
public virtual void Remove(TEntityType instance)
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(instance, MessageType.RemoveByInstance));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
using Umbraco.Core.Sync;
|
||||
|
||||
namespace Umbraco.Core.Cache
|
||||
{
|
||||
/// <summary>
|
||||
/// A base class for "typed" cache refreshers.
|
||||
/// </summary>
|
||||
/// <typeparam name="TInstanceType">The actual cache refresher type.</typeparam>
|
||||
/// <typeparam name="TEntityType">The entity type.</typeparam>
|
||||
/// <remarks>The actual cache refresher type is used for strongly typed events.</remarks>
|
||||
public abstract class TypedCacheRefresherBase<TInstanceType, TEntityType> : CacheRefresherBase<TInstanceType>, ICacheRefresher<TEntityType>
|
||||
where TInstanceType : class, ICacheRefresher
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="TypedCacheRefresherBase{TInstanceType, TEntityType}"/>.
|
||||
/// </summary>
|
||||
/// <param name="cacheHelper">A cache helper.</param>
|
||||
protected TypedCacheRefresherBase(CacheHelper cacheHelper)
|
||||
: base(cacheHelper)
|
||||
{ }
|
||||
|
||||
#region Refresher
|
||||
|
||||
public virtual void Refresh(TEntityType instance)
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(instance, MessageType.RefreshByInstance));
|
||||
}
|
||||
|
||||
public virtual void Remove(TEntityType instance)
|
||||
{
|
||||
OnCacheUpdated(This, new CacheRefresherEventArgs(instance, MessageType.RemoveByInstance));
|
||||
}
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute to add a Friendly Name string with an UmbracoObjectType enum value
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = false)]
|
||||
internal class FriendlyNameAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// friendly name value
|
||||
/// </summary>
|
||||
private readonly string _friendlyName;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the FriendlyNameAttribute class
|
||||
/// Sets the friendly name value
|
||||
/// </summary>
|
||||
/// <param name="friendlyName">attribute value</param>
|
||||
public FriendlyNameAttribute(string friendlyName)
|
||||
{
|
||||
this._friendlyName = friendlyName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the friendly name
|
||||
/// </summary>
|
||||
/// <returns>string of friendly name</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this._friendlyName;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute to add a Friendly Name string with an UmbracoObjectType enum value
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = false)]
|
||||
internal class FriendlyNameAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// friendly name value
|
||||
/// </summary>
|
||||
private readonly string _friendlyName;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the FriendlyNameAttribute class
|
||||
/// Sets the friendly name value
|
||||
/// </summary>
|
||||
/// <param name="friendlyName">attribute value</param>
|
||||
public FriendlyNameAttribute(string friendlyName)
|
||||
{
|
||||
this._friendlyName = friendlyName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the friendly name
|
||||
/// </summary>
|
||||
/// <returns>string of friendly name</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return this._friendlyName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Marks the program elements that Umbraco is experimenting with and could become public.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Indicates that Umbraco is experimenting with code that potentially could become
|
||||
/// public, but we're not sure, and the code is not stable and can be refactored at any time.</para>
|
||||
/// <para>The issue tracker should contain more details, discussion, and planning.</para>
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = false)]
|
||||
internal sealed class UmbracoExperimentalFeatureAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoExperimentalFeatureAttribute"/> class with a description.
|
||||
/// </summary>
|
||||
/// <param name="description">The text string that describes what is intended.</param>
|
||||
public UmbracoExperimentalFeatureAttribute(string description)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoExperimentalFeatureAttribute"/> class with a tracker url and a description.
|
||||
/// </summary>
|
||||
/// <param name="trackerUrl">The url of a tracker issue containing more details, discussion, and planning.</param>
|
||||
/// <param name="description">The text string that describes what is intended.</param>
|
||||
public UmbracoExperimentalFeatureAttribute(string trackerUrl, string description)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,26 +1,26 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute to associate a GUID string and Type with an UmbracoObjectType Enum value
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
|
||||
internal class UmbracoObjectTypeAttribute : Attribute
|
||||
{
|
||||
public UmbracoObjectTypeAttribute(string objectId)
|
||||
{
|
||||
ObjectId = new Guid(objectId);
|
||||
}
|
||||
|
||||
public UmbracoObjectTypeAttribute(string objectId, Type modelType)
|
||||
{
|
||||
ObjectId = new Guid(objectId);
|
||||
ModelType = modelType;
|
||||
}
|
||||
|
||||
public Guid ObjectId { get; private set; }
|
||||
|
||||
public Type ModelType { get; private set; }
|
||||
}
|
||||
}
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Attribute to associate a GUID string and Type with an UmbracoObjectType Enum value
|
||||
/// </summary>
|
||||
[AttributeUsage(AttributeTargets.Field, AllowMultiple = false, Inherited = false)]
|
||||
internal class UmbracoObjectTypeAttribute : Attribute
|
||||
{
|
||||
public UmbracoObjectTypeAttribute(string objectId)
|
||||
{
|
||||
ObjectId = new Guid(objectId);
|
||||
}
|
||||
|
||||
public UmbracoObjectTypeAttribute(string objectId, Type modelType)
|
||||
{
|
||||
ObjectId = new Guid(objectId);
|
||||
ModelType = modelType;
|
||||
}
|
||||
|
||||
public Guid ObjectId { get; private set; }
|
||||
|
||||
public Type ModelType { get; private set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Marks the program elements that Umbraco is considering making public.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>Indicates that Umbraco considers making the (currently internal) program element public
|
||||
/// at some point in the future, but the decision is not fully made yet and is still pending reviews.</para>
|
||||
/// <para>Note that it is not a commitment to make the program element public. It may not ever become public.</para>
|
||||
/// <para>The issue tracker should contain more details, discussion, and planning.</para>
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple=false, Inherited=false)]
|
||||
internal sealed class UmbracoProposedPublicAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoProposedPublicAttribute"/> class with a description.
|
||||
/// </summary>
|
||||
/// <param name="description">The text string that describes what is intended.</param>
|
||||
public UmbracoProposedPublicAttribute(string description)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoProposedPublicAttribute"/> class with a tracker url and a description.
|
||||
/// </summary>
|
||||
/// <param name="trackerUrl">The url of a tracker issue containing more details, discussion, and planning.</param>
|
||||
/// <param name="description">The text string that describes what is intended.</param>
|
||||
public UmbracoProposedPublicAttribute(string trackerUrl, string description)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
|
||||
namespace Umbraco.Core.CodeAnnotations
|
||||
{
|
||||
/// <summary>
|
||||
/// Marks the program elements that Umbraco will obsolete.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// Indicates that Umbraco will obsolete the program element at some point in the future, but we do not want to
|
||||
/// explicitely mark it [Obsolete] yet to avoid warning messages showing when developers compile Umbraco.
|
||||
/// </remarks>
|
||||
[AttributeUsage(AttributeTargets.All, AllowMultiple = false, Inherited = false)]
|
||||
internal sealed class UmbracoWillObsoleteAttribute : Attribute
|
||||
{
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoWillObsoleteAttribute"/> class with a description.
|
||||
/// </summary>
|
||||
/// <param name="description">The text string that describes what is intended.</param>
|
||||
public UmbracoWillObsoleteAttribute(string description)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="UmbracoWillObsoleteAttribute"/> class with a tracker url and a description.
|
||||
/// </summary>
|
||||
/// <param name="trackerUrl">The url of a tracker issue containing more details, discussion, and planning.</param>
|
||||
/// <param name="description">The text string that describes what is intended.</param>
|
||||
public UmbracoWillObsoleteAttribute(string trackerUrl, string description)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a composite key of (string, string) for fast dictionaries.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The string parts of the key are case-insensitive.</para>
|
||||
/// <para>Null is a valid value for both parts.</para>
|
||||
/// </remarks>
|
||||
public struct CompositeNStringNStringKey : IEquatable<CompositeNStringNStringKey>
|
||||
{
|
||||
private readonly string _key1;
|
||||
private readonly string _key2;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CompositeNStringNStringKey"/> struct.
|
||||
/// </summary>
|
||||
public CompositeNStringNStringKey(string key1, string key2)
|
||||
{
|
||||
_key1 = key1?.ToLowerInvariant() ?? "NULL";
|
||||
_key2 = key2?.ToLowerInvariant() ?? "NULL";
|
||||
}
|
||||
|
||||
public bool Equals(CompositeNStringNStringKey other)
|
||||
=> _key2 == other._key2 && _key1 == other._key1;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
=> obj is CompositeNStringNStringKey other && _key2 == other._key2 && _key1 == other._key1;
|
||||
|
||||
public override int GetHashCode()
|
||||
=> _key2.GetHashCode() * 31 + _key1.GetHashCode();
|
||||
|
||||
public static bool operator ==(CompositeNStringNStringKey key1, CompositeNStringNStringKey key2)
|
||||
=> key1._key2 == key2._key2 && key1._key1 == key2._key1;
|
||||
|
||||
public static bool operator !=(CompositeNStringNStringKey key1, CompositeNStringNStringKey key2)
|
||||
=> key1._key2 != key2._key2 || key1._key1 != key2._key1;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
|
||||
namespace Umbraco.Core.Collections
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a composite key of (string, string) for fast dictionaries.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>The string parts of the key are case-insensitive.</para>
|
||||
/// <para>Null is NOT a valid value for neither parts.</para>
|
||||
/// </remarks>
|
||||
public struct CompositeStringStringKey : IEquatable<CompositeStringStringKey>
|
||||
{
|
||||
private readonly string _key1;
|
||||
private readonly string _key2;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="CompositeStringStringKey"/> struct.
|
||||
/// </summary>
|
||||
public CompositeStringStringKey(string key1, string key2)
|
||||
{
|
||||
_key1 = key1?.ToLowerInvariant() ?? throw new ArgumentNullException(nameof(key1));
|
||||
_key2 = key2?.ToLowerInvariant() ?? throw new ArgumentNullException(nameof(key2));
|
||||
}
|
||||
|
||||
public bool Equals(CompositeStringStringKey other)
|
||||
=> _key2 == other._key2 && _key1 == other._key1;
|
||||
|
||||
public override bool Equals(object obj)
|
||||
=> obj is CompositeStringStringKey other && _key2 == other._key2 && _key1 == other._key1;
|
||||
|
||||
public override int GetHashCode()
|
||||
=> _key2.GetHashCode() * 31 + _key1.GetHashCode();
|
||||
|
||||
public static bool operator ==(CompositeStringStringKey key1, CompositeStringStringKey key2)
|
||||
=> key1._key2 == key2._key2 && key1._key1 == key2._key1;
|
||||
|
||||
public static bool operator !=(CompositeStringStringKey key1, CompositeStringStringKey key2)
|
||||
=> key1._key2 != key2._key2 || key1._key1 != key2._key1;
|
||||
}
|
||||
}
|
||||
@@ -50,10 +50,16 @@ namespace Umbraco.Core.Collections
|
||||
/// <param name="item">The object to remove from the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
|
||||
public bool Remove(T item)
|
||||
{
|
||||
using (new WriteLock(_instanceLocker))
|
||||
try
|
||||
{
|
||||
_instanceLocker.EnterWriteLock();
|
||||
return _innerSet.Remove(item);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_instanceLocker.IsWriteLockHeld)
|
||||
_instanceLocker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -86,10 +92,16 @@ namespace Umbraco.Core.Collections
|
||||
/// <param name="item">The object to add to the <see cref="T:System.Collections.Generic.ICollection`1"/>.</param><exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only.</exception>
|
||||
public void Add(T item)
|
||||
{
|
||||
using (new WriteLock(_instanceLocker))
|
||||
try
|
||||
{
|
||||
_instanceLocker.EnterWriteLock();
|
||||
_innerSet.Add(item);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_instanceLocker.IsWriteLockHeld)
|
||||
_instanceLocker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -101,13 +113,20 @@ namespace Umbraco.Core.Collections
|
||||
{
|
||||
var clone = GetThreadSafeClone();
|
||||
if (clone.Contains(item)) return false;
|
||||
using (new WriteLock(_instanceLocker))
|
||||
try
|
||||
{
|
||||
_instanceLocker.EnterWriteLock();
|
||||
|
||||
//double check
|
||||
if (_innerSet.Contains(item)) return false;
|
||||
_innerSet.Add(item);
|
||||
return true;
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_instanceLocker.IsWriteLockHeld)
|
||||
_instanceLocker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -116,10 +135,16 @@ namespace Umbraco.Core.Collections
|
||||
/// <exception cref="T:System.NotSupportedException">The <see cref="T:System.Collections.Generic.ICollection`1"/> is read-only. </exception>
|
||||
public void Clear()
|
||||
{
|
||||
using (new WriteLock(_instanceLocker))
|
||||
try
|
||||
{
|
||||
_instanceLocker.EnterWriteLock();
|
||||
_innerSet.Clear();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_instanceLocker.IsWriteLockHeld)
|
||||
_instanceLocker.ExitWriteLock();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -147,10 +172,16 @@ namespace Umbraco.Core.Collections
|
||||
private HashSet<T> GetThreadSafeClone()
|
||||
{
|
||||
HashSet<T> clone = null;
|
||||
using (new WriteLock(_instanceLocker))
|
||||
try
|
||||
{
|
||||
_instanceLocker.EnterWriteLock();
|
||||
clone = new HashSet<T>(_innerSet, _innerSet.Comparer);
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (_instanceLocker.IsWriteLockHeld)
|
||||
_instanceLocker.ExitWriteLock();
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,8 +29,7 @@ namespace Umbraco.Core.Components
|
||||
/// <param name="container">The application container.</param>
|
||||
public BootLoader(IServiceContainer container)
|
||||
{
|
||||
if (container == null) throw new ArgumentNullException(nameof(container));
|
||||
_container = container;
|
||||
_container = container ?? throw new ArgumentNullException(nameof(container));
|
||||
_proflog = container.GetInstance<ProfilingLogger>();
|
||||
_logger = container.GetInstance<ILogger>();
|
||||
}
|
||||
@@ -74,8 +73,11 @@ namespace Umbraco.Core.Components
|
||||
var componentTypeList = componentTypes
|
||||
.Where(x =>
|
||||
{
|
||||
// use the min level specified by the attribute if any
|
||||
// otherwise, user components have Run min level, anything else is Unknown (always run)
|
||||
var attr = x.GetCustomAttribute<RuntimeLevelAttribute>();
|
||||
return attr == null || level >= attr.MinLevel;
|
||||
var minLevel = attr?.MinLevel ?? (x.Implements<IUmbracoUserComponent>() ? RuntimeLevel.Run : RuntimeLevel.Unknown);
|
||||
return level >= minLevel;
|
||||
})
|
||||
.ToList();
|
||||
|
||||
@@ -109,7 +111,7 @@ namespace Umbraco.Core.Components
|
||||
catch (Exception e)
|
||||
{
|
||||
// in case of an error, force-dump everything to log
|
||||
_logger.Info<BootLoader>(GetComponentsReport(requirements));
|
||||
_logger.Info<BootLoader>(() => GetComponentsReport(requirements));
|
||||
_logger.Error<BootLoader>("Failed to sort components.", e);
|
||||
throw;
|
||||
}
|
||||
@@ -176,8 +178,7 @@ namespace Umbraco.Core.Components
|
||||
foreach (var attr in componentType.GetCustomAttributes<EnableComponentAttribute>())
|
||||
{
|
||||
var type = attr.EnabledType ?? componentType;
|
||||
EnableInfo enableInfo;
|
||||
if (enabled.TryGetValue(type, out enableInfo) == false) enableInfo = enabled[type] = new EnableInfo();
|
||||
if (enabled.TryGetValue(type, out var enableInfo) == false) enableInfo = enabled[type] = new EnableInfo();
|
||||
var weight = type == componentType ? 1 : 2;
|
||||
if (enableInfo.Weight > weight) continue;
|
||||
|
||||
@@ -188,8 +189,7 @@ namespace Umbraco.Core.Components
|
||||
{
|
||||
var type = attr.DisabledType ?? componentType;
|
||||
if (type == typeof(UmbracoCoreComponent)) throw new InvalidOperationException("Cannot disable UmbracoCoreComponent.");
|
||||
EnableInfo enableInfo;
|
||||
if (enabled.TryGetValue(type, out enableInfo) == false) enableInfo = enabled[type] = new EnableInfo();
|
||||
if (enabled.TryGetValue(type, out var enableInfo) == false) enableInfo = enabled[type] = new EnableInfo();
|
||||
var weight = type == componentType ? 1 : 2;
|
||||
if (enableInfo.Weight > weight) continue;
|
||||
|
||||
@@ -353,8 +353,9 @@ namespace Umbraco.Core.Components
|
||||
|
||||
using (_proflog.DebugDuration<BootLoader>($"Terminating. (log components when >{LogThresholdMilliseconds}ms)", "Terminated."))
|
||||
{
|
||||
foreach (var component in _components)
|
||||
for (var i = _components.Length - 1; i >= 0; i--) // terminate components in reverse order
|
||||
{
|
||||
var component = _components[i];
|
||||
var componentType = component.GetType();
|
||||
using (_proflog.DebugDuration<BootLoader>($"Terminating {componentType.FullName}.", $"Terminated {componentType.FullName}.", thresholdMilliseconds: LogThresholdMilliseconds))
|
||||
{
|
||||
|
||||
@@ -7,7 +7,7 @@ namespace Umbraco.Core.Composing.CompositionRoots
|
||||
{
|
||||
public void Compose(IServiceRegistry container)
|
||||
{
|
||||
container.Register<IdentityProfile>();
|
||||
container.Register<IdentityMapperProfile>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,6 @@ namespace Umbraco.Core.Composing.CompositionRoots
|
||||
container.RegisterSingleton<IPartialViewRepository, PartialViewRepository>();
|
||||
container.RegisterSingleton<IScriptRepository, ScriptRepository>();
|
||||
container.RegisterSingleton<IStylesheetRepository, StylesheetRepository>();
|
||||
container.RegisterSingleton<IXsltFileRepository, XsltFileRepository>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ namespace Umbraco.Core.Composing
|
||||
private static ILogger _logger;
|
||||
private static IProfiler _profiler;
|
||||
private static ProfilingLogger _profilingLogger;
|
||||
private static IPublishedValueFallback _publishedValueFallback;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DI container.
|
||||
@@ -63,6 +64,7 @@ namespace Umbraco.Core.Composing
|
||||
_logger = null;
|
||||
_profiler = null;
|
||||
_profilingLogger = null;
|
||||
_publishedValueFallback = null;
|
||||
|
||||
Resetted?.Invoke(null, EventArgs.Empty);
|
||||
}
|
||||
@@ -153,6 +155,9 @@ namespace Umbraco.Core.Composing
|
||||
public static IPublishedContentTypeFactory PublishedContentTypeFactory
|
||||
=> Container.GetInstance<IPublishedContentTypeFactory>();
|
||||
|
||||
public static IPublishedValueFallback PublishedValueFallback
|
||||
=> _publishedValueFallback ?? Container.GetInstance<IPublishedValueFallback>() ?? new NoopPublishedValueFallback();
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
|
||||
@@ -311,15 +311,15 @@ namespace Umbraco.Core.Composing
|
||||
// we HAVE to let LightInject throw - and catch at THE OUTERMOST if InvalidOperationException in LightInject.Anything!
|
||||
|
||||
return factory.GetInstance(tService, serviceName, args);
|
||||
try
|
||||
{
|
||||
return factory.GetInstance(tService, serviceName, args);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LightInjectException.TryThrow(e, implementingType);
|
||||
throw;
|
||||
}
|
||||
//try
|
||||
//{
|
||||
// return factory.GetInstance(tService, serviceName, args);
|
||||
//}
|
||||
//catch (Exception e)
|
||||
//{
|
||||
// LightInjectException.TryThrow(e, implementingType);
|
||||
// throw;
|
||||
//}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
||||
@@ -494,7 +494,7 @@ namespace Umbraco.Core.Composing
|
||||
if (--attempts == 0)
|
||||
throw;
|
||||
|
||||
_logger.Logger.Debug<TypeLoader>($"Attempted to get filestream for file {path} failed, {attempts} attempts left, pausing for {pauseMilliseconds} milliseconds");
|
||||
_logger.Logger.Debug<TypeLoader>(() => $"Attempted to get filestream for file {path} failed, {attempts} attempts left, pausing for {pauseMilliseconds} milliseconds");
|
||||
Thread.Sleep(pauseMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// A case-insensitive configuration converter for enumerations.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the enumeration.</typeparam>
|
||||
public class CaseInsensitiveEnumConfigConverter<T> : ConfigurationConverterBase
|
||||
where T : struct
|
||||
{
|
||||
public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException("data");
|
||||
|
||||
//return Enum.Parse(typeof(T), (string)data, true);
|
||||
|
||||
T value;
|
||||
if (Enum.TryParse((string)data, true, out value))
|
||||
return value;
|
||||
|
||||
throw new Exception(string.Format("\"{0}\" is not valid {1} value. Valid values are: {2}.",
|
||||
data, typeof(T).Name,
|
||||
string.Join(", ", Enum.GetValues(typeof(T)).Cast<T>())));
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.ComponentModel;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// A case-insensitive configuration converter for enumerations.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of the enumeration.</typeparam>
|
||||
public class CaseInsensitiveEnumConfigConverter<T> : ConfigurationConverterBase
|
||||
where T : struct
|
||||
{
|
||||
public override object ConvertFrom(ITypeDescriptorContext ctx, CultureInfo ci, object data)
|
||||
{
|
||||
if (data == null)
|
||||
throw new ArgumentNullException("data");
|
||||
|
||||
//return Enum.Parse(typeof(T), (string)data, true);
|
||||
|
||||
T value;
|
||||
if (Enum.TryParse((string)data, true, out value))
|
||||
return value;
|
||||
|
||||
throw new Exception(string.Format("\"{0}\" is not valid {1} value. Valid values are: {2}.",
|
||||
data, typeof(T).Name,
|
||||
string.Join(", ", Enum.GetValues(typeof(T)).Cast<T>())));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,178 +1,178 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Xml.Linq;
|
||||
using ClientDependency.Core.CompositeFiles.Providers;
|
||||
using ClientDependency.Core.Config;
|
||||
using Semver;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// A utility class for working with CDF config and cache files - use sparingly!
|
||||
/// </summary>
|
||||
public class ClientDependencyConfiguration
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly string _fileName;
|
||||
|
||||
public ClientDependencyConfiguration(ILogger logger)
|
||||
{
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
_logger = logger;
|
||||
_fileName = IOHelper.MapPath(string.Format("{0}/ClientDependency.config", SystemDirectories.Config));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the version number in ClientDependency.config to a hashed value for the version and the DateTime.Day
|
||||
/// </summary>
|
||||
/// <param name="version">The <see cref="SemVersion">version</see> of Umbraco we're upgrading to</param>
|
||||
/// <param name="date">A <see cref="DateTime">date</see> value to use in the hash to prevent this method from updating the version on each startup</param>
|
||||
/// <param name="dateFormat">Allows the developer to specify the <see cref="string">date precision</see> for the hash (i.e. "yyyyMMdd" would be a precision for the day)</param>
|
||||
/// <returns>Boolean to indicate succesful update of the ClientDependency.config file</returns>
|
||||
public bool UpdateVersionNumber(SemVersion version, DateTime date, string dateFormat)
|
||||
{
|
||||
var byteContents = Encoding.Unicode.GetBytes(version + date.ToString(dateFormat));
|
||||
|
||||
//This is a way to convert a string to a long
|
||||
//see https://www.codeproject.com/Articles/34309/Convert-String-to-bit-Integer
|
||||
//We could much more easily use MD5 which would create us an INT but since that is not compliant with
|
||||
//hashing standards we have to use SHA
|
||||
int intHash;
|
||||
using (var hash = SHA256.Create())
|
||||
{
|
||||
var bytes = hash.ComputeHash(byteContents);
|
||||
|
||||
var longResult = new[] { 0, 8, 16, 24 }
|
||||
.Select(i => BitConverter.ToInt64(bytes, i))
|
||||
.Aggregate((x, y) => x ^ y);
|
||||
|
||||
//CDF requires an INT, and although this isn't fail safe, it will work for our purposes. We are not hashing for crypto purposes
|
||||
//so there could be some collisions with this conversion but it's not a problem for our purposes
|
||||
//It's also important to note that the long.GetHashCode() implementation in .NET is this: return (int) this ^ (int) (this >> 32);
|
||||
//which means that this value will not change per appdomain like some GetHashCode implementations.
|
||||
intHash = longResult.GetHashCode();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var clientDependencyConfigXml = XDocument.Load(_fileName, LoadOptions.PreserveWhitespace);
|
||||
if (clientDependencyConfigXml.Root != null)
|
||||
{
|
||||
|
||||
var versionAttribute = clientDependencyConfigXml.Root.Attribute("version");
|
||||
|
||||
//Set the new version to the hashcode of now
|
||||
var oldVersion = versionAttribute.Value;
|
||||
var newVersion = Math.Abs(intHash).ToString();
|
||||
|
||||
//don't update if it's the same version
|
||||
if (oldVersion == newVersion)
|
||||
return false;
|
||||
|
||||
versionAttribute.SetValue(newVersion);
|
||||
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
|
||||
|
||||
_logger.Info<ClientDependencyConfiguration>(string.Format("Updated version number from {0} to {1}", oldVersion, newVersion));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<ClientDependencyConfiguration>("Couldn't update ClientDependency version number", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the version number in ClientDependency.config to a random value to avoid stale caches
|
||||
/// </summary>
|
||||
/// <seealso cref="UpdateVersionNumber(SemVersion, DateTime, string)" />
|
||||
[Obsolete("Use the UpdateVersionNumber method specifying the version, date and dateFormat instead")]
|
||||
public bool IncreaseVersionNumber()
|
||||
{
|
||||
try
|
||||
{
|
||||
var clientDependencyConfigXml = XDocument.Load(_fileName, LoadOptions.PreserveWhitespace);
|
||||
if (clientDependencyConfigXml.Root != null)
|
||||
{
|
||||
|
||||
var versionAttribute = clientDependencyConfigXml.Root.Attribute("version");
|
||||
|
||||
//Set the new version to the hashcode of now
|
||||
var oldVersion = versionAttribute.Value;
|
||||
var newVersion = Math.Abs(DateTime.UtcNow.GetHashCode());
|
||||
|
||||
versionAttribute.SetValue(newVersion);
|
||||
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
|
||||
|
||||
_logger.Info<ClientDependencyConfiguration>(string.Format("Updated version number from {0} to {1}", oldVersion, newVersion));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<ClientDependencyConfiguration>("Couldn't update ClientDependency version number", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the temporary files stored for the ClientDependency folder
|
||||
/// </summary>
|
||||
/// <param name="currentHttpContext"></param>
|
||||
public bool ClearTempFiles(HttpContextBase currentHttpContext)
|
||||
{
|
||||
var cdfTempDirectories = new HashSet<string>();
|
||||
foreach (BaseCompositeFileProcessingProvider provider in ClientDependencySettings.Instance
|
||||
.CompositeFileProcessingProviderCollection)
|
||||
{
|
||||
var path = provider.CompositeFilePath.FullName;
|
||||
cdfTempDirectories.Add(path);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var fullPath = currentHttpContext.Server.MapPath(XmlFileMapper.FileMapVirtualFolder);
|
||||
if (fullPath != null)
|
||||
{
|
||||
cdfTempDirectories.Add(fullPath);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//invalid path format or something... try/catch to be safe
|
||||
_logger.Error<ClientDependencyConfiguration>("Could not get path from ClientDependency.config", ex);
|
||||
}
|
||||
|
||||
var success = true;
|
||||
foreach (var directory in cdfTempDirectories)
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(directory);
|
||||
if (directoryInfo.Exists == false)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
directoryInfo.Delete(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Something could be locking the directory or the was another error, making sure we don't break the upgrade installer
|
||||
_logger.Error<ClientDependencyConfiguration>("Could not clear temp files", ex);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Web;
|
||||
using System.Xml.Linq;
|
||||
using ClientDependency.Core.CompositeFiles.Providers;
|
||||
using ClientDependency.Core.Config;
|
||||
using Semver;
|
||||
using Umbraco.Core.IO;
|
||||
using Umbraco.Core.Logging;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// A utility class for working with CDF config and cache files - use sparingly!
|
||||
/// </summary>
|
||||
public class ClientDependencyConfiguration
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
private readonly string _fileName;
|
||||
|
||||
public ClientDependencyConfiguration(ILogger logger)
|
||||
{
|
||||
if (logger == null) throw new ArgumentNullException("logger");
|
||||
_logger = logger;
|
||||
_fileName = IOHelper.MapPath(string.Format("{0}/ClientDependency.config", SystemDirectories.Config));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the version number in ClientDependency.config to a hashed value for the version and the DateTime.Day
|
||||
/// </summary>
|
||||
/// <param name="version">The <see cref="SemVersion">version</see> of Umbraco we're upgrading to</param>
|
||||
/// <param name="date">A <see cref="DateTime">date</see> value to use in the hash to prevent this method from updating the version on each startup</param>
|
||||
/// <param name="dateFormat">Allows the developer to specify the <see cref="string">date precision</see> for the hash (i.e. "yyyyMMdd" would be a precision for the day)</param>
|
||||
/// <returns>Boolean to indicate succesful update of the ClientDependency.config file</returns>
|
||||
public bool UpdateVersionNumber(SemVersion version, DateTime date, string dateFormat)
|
||||
{
|
||||
var byteContents = Encoding.Unicode.GetBytes(version + date.ToString(dateFormat));
|
||||
|
||||
//This is a way to convert a string to a long
|
||||
//see https://www.codeproject.com/Articles/34309/Convert-String-to-bit-Integer
|
||||
//We could much more easily use MD5 which would create us an INT but since that is not compliant with
|
||||
//hashing standards we have to use SHA
|
||||
int intHash;
|
||||
using (var hash = SHA256.Create())
|
||||
{
|
||||
var bytes = hash.ComputeHash(byteContents);
|
||||
|
||||
var longResult = new[] { 0, 8, 16, 24 }
|
||||
.Select(i => BitConverter.ToInt64(bytes, i))
|
||||
.Aggregate((x, y) => x ^ y);
|
||||
|
||||
//CDF requires an INT, and although this isn't fail safe, it will work for our purposes. We are not hashing for crypto purposes
|
||||
//so there could be some collisions with this conversion but it's not a problem for our purposes
|
||||
//It's also important to note that the long.GetHashCode() implementation in .NET is this: return (int) this ^ (int) (this >> 32);
|
||||
//which means that this value will not change per appdomain like some GetHashCode implementations.
|
||||
intHash = longResult.GetHashCode();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var clientDependencyConfigXml = XDocument.Load(_fileName, LoadOptions.PreserveWhitespace);
|
||||
if (clientDependencyConfigXml.Root != null)
|
||||
{
|
||||
|
||||
var versionAttribute = clientDependencyConfigXml.Root.Attribute("version");
|
||||
|
||||
//Set the new version to the hashcode of now
|
||||
var oldVersion = versionAttribute.Value;
|
||||
var newVersion = Math.Abs(intHash).ToString();
|
||||
|
||||
//don't update if it's the same version
|
||||
if (oldVersion == newVersion)
|
||||
return false;
|
||||
|
||||
versionAttribute.SetValue(newVersion);
|
||||
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
|
||||
|
||||
_logger.Info<ClientDependencyConfiguration>(() => $"Updated version number from {oldVersion} to {newVersion}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<ClientDependencyConfiguration>("Couldn't update ClientDependency version number", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Changes the version number in ClientDependency.config to a random value to avoid stale caches
|
||||
/// </summary>
|
||||
/// <seealso cref="UpdateVersionNumber(SemVersion, DateTime, string)" />
|
||||
[Obsolete("Use the UpdateVersionNumber method specifying the version, date and dateFormat instead")]
|
||||
public bool IncreaseVersionNumber()
|
||||
{
|
||||
try
|
||||
{
|
||||
var clientDependencyConfigXml = XDocument.Load(_fileName, LoadOptions.PreserveWhitespace);
|
||||
if (clientDependencyConfigXml.Root != null)
|
||||
{
|
||||
|
||||
var versionAttribute = clientDependencyConfigXml.Root.Attribute("version");
|
||||
|
||||
//Set the new version to the hashcode of now
|
||||
var oldVersion = versionAttribute.Value;
|
||||
var newVersion = Math.Abs(DateTime.UtcNow.GetHashCode());
|
||||
|
||||
versionAttribute.SetValue(newVersion);
|
||||
clientDependencyConfigXml.Save(_fileName, SaveOptions.DisableFormatting);
|
||||
|
||||
_logger.Info<ClientDependencyConfiguration>(() => $"Updated version number from {oldVersion} to {newVersion}");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Error<ClientDependencyConfiguration>("Couldn't update ClientDependency version number", ex);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clears the temporary files stored for the ClientDependency folder
|
||||
/// </summary>
|
||||
/// <param name="currentHttpContext"></param>
|
||||
public bool ClearTempFiles(HttpContextBase currentHttpContext)
|
||||
{
|
||||
var cdfTempDirectories = new HashSet<string>();
|
||||
foreach (BaseCompositeFileProcessingProvider provider in ClientDependencySettings.Instance
|
||||
.CompositeFileProcessingProviderCollection)
|
||||
{
|
||||
var path = provider.CompositeFilePath.FullName;
|
||||
cdfTempDirectories.Add(path);
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
var fullPath = currentHttpContext.Server.MapPath(XmlFileMapper.FileMapVirtualFolder);
|
||||
if (fullPath != null)
|
||||
{
|
||||
cdfTempDirectories.Add(fullPath);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
//invalid path format or something... try/catch to be safe
|
||||
_logger.Error<ClientDependencyConfiguration>("Could not get path from ClientDependency.config", ex);
|
||||
}
|
||||
|
||||
var success = true;
|
||||
foreach (var directory in cdfTempDirectories)
|
||||
{
|
||||
var directoryInfo = new DirectoryInfo(directory);
|
||||
if (directoryInfo.Exists == false)
|
||||
continue;
|
||||
|
||||
try
|
||||
{
|
||||
directoryInfo.Delete(true);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
// Something could be locking the directory or the was another error, making sure we don't break the upgrade installer
|
||||
_logger.Error<ClientDependencyConfiguration>("Could not clear temp files", ex);
|
||||
success = false;
|
||||
}
|
||||
}
|
||||
|
||||
return success;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,70 +1,70 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a configuration section that contains inner text that is comma delimited
|
||||
/// </summary>
|
||||
internal class CommaDelimitedConfigurationElement : InnerTextConfigurationElement<CommaDelimitedStringCollection>, IEnumerable<string>
|
||||
{
|
||||
public override CommaDelimitedStringCollection Value
|
||||
{
|
||||
get
|
||||
{
|
||||
var converter = new CommaDelimitedStringCollectionConverter();
|
||||
return (CommaDelimitedStringCollection) converter.ConvertFrom(RawValue);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator<string> IEnumerable<string>.GetEnumerator()
|
||||
{
|
||||
return new InnerEnumerator(Value.GetEnumerator());
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return new InnerEnumerator(Value.GetEnumerator());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A wrapper for StringEnumerator since it doesn't explicitly implement IEnumerable
|
||||
/// </summary>
|
||||
private class InnerEnumerator : IEnumerator<string>
|
||||
{
|
||||
private readonly StringEnumerator _stringEnumerator;
|
||||
|
||||
public InnerEnumerator(StringEnumerator stringEnumerator)
|
||||
{
|
||||
_stringEnumerator = stringEnumerator;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
return _stringEnumerator.MoveNext();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_stringEnumerator.Reset();
|
||||
}
|
||||
|
||||
string IEnumerator<string>.Current
|
||||
{
|
||||
get { return _stringEnumerator.Current; }
|
||||
}
|
||||
|
||||
public object Current
|
||||
{
|
||||
get { return _stringEnumerator.Current; }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ObjectExtensions.DisposeIfDisposable(_stringEnumerator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration
|
||||
{
|
||||
/// <summary>
|
||||
/// Defines a configuration section that contains inner text that is comma delimited
|
||||
/// </summary>
|
||||
internal class CommaDelimitedConfigurationElement : InnerTextConfigurationElement<CommaDelimitedStringCollection>, IEnumerable<string>
|
||||
{
|
||||
public override CommaDelimitedStringCollection Value
|
||||
{
|
||||
get
|
||||
{
|
||||
var converter = new CommaDelimitedStringCollectionConverter();
|
||||
return (CommaDelimitedStringCollection) converter.ConvertFrom(RawValue);
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator<string> IEnumerable<string>.GetEnumerator()
|
||||
{
|
||||
return new InnerEnumerator(Value.GetEnumerator());
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return new InnerEnumerator(Value.GetEnumerator());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A wrapper for StringEnumerator since it doesn't explicitly implement IEnumerable
|
||||
/// </summary>
|
||||
private class InnerEnumerator : IEnumerator<string>
|
||||
{
|
||||
private readonly StringEnumerator _stringEnumerator;
|
||||
|
||||
public InnerEnumerator(StringEnumerator stringEnumerator)
|
||||
{
|
||||
_stringEnumerator = stringEnumerator;
|
||||
}
|
||||
|
||||
public bool MoveNext()
|
||||
{
|
||||
return _stringEnumerator.MoveNext();
|
||||
}
|
||||
|
||||
public void Reset()
|
||||
{
|
||||
_stringEnumerator.Reset();
|
||||
}
|
||||
|
||||
string IEnumerator<string>.Current
|
||||
{
|
||||
get { return _stringEnumerator.Current; }
|
||||
}
|
||||
|
||||
public object Current
|
||||
{
|
||||
get { return _stringEnumerator.Current; }
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
ObjectExtensions.DisposeIfDisposable(_stringEnumerator);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class AccessElement : RawXmlConfigurationElement, IAccess
|
||||
{
|
||||
public AccessElement()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public AccessElement(XElement rawXml)
|
||||
:base(rawXml)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<IAccessItem> Rules
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = new List<AccessItem>();
|
||||
if (RawXml != null)
|
||||
{
|
||||
result.AddRange(RawXml.Elements("deny").Select(x => new AccessItem {Action = AccessType.Deny, Value = x.Value }));
|
||||
result.AddRange(RawXml.Elements("grant").Select(x => new AccessItem { Action = AccessType.Grant, Value = x.Value }));
|
||||
result.AddRange(RawXml.Elements("grantBySection").Select(x => new AccessItem { Action = AccessType.GrantBySection, Value = x.Value }));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class AccessElement : RawXmlConfigurationElement, IAccess
|
||||
{
|
||||
public AccessElement()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public AccessElement(XElement rawXml)
|
||||
:base(rawXml)
|
||||
{
|
||||
}
|
||||
|
||||
public IEnumerable<IAccessItem> Rules
|
||||
{
|
||||
get
|
||||
{
|
||||
var result = new List<AccessItem>();
|
||||
if (RawXml != null)
|
||||
{
|
||||
result.AddRange(RawXml.Elements("deny").Select(x => new AccessItem {Action = AccessType.Deny, Value = x.Value }));
|
||||
result.AddRange(RawXml.Elements("grant").Select(x => new AccessItem { Action = AccessType.Grant, Value = x.Value }));
|
||||
result.AddRange(RawXml.Elements("grantBySection").Select(x => new AccessItem { Action = AccessType.GrantBySection, Value = x.Value }));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class AccessItem : IAccessItem
|
||||
{
|
||||
/// <summary>
|
||||
/// This can be grant, deny or grantBySection
|
||||
/// </summary>
|
||||
public AccessType Action { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The value of the action
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
}
|
||||
}
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class AccessItem : IAccessItem
|
||||
{
|
||||
/// <summary>
|
||||
/// This can be grant, deny or grantBySection
|
||||
/// </summary>
|
||||
public AccessType Action { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The value of the action
|
||||
/// </summary>
|
||||
public string Value { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
public enum AccessType
|
||||
{
|
||||
Grant,
|
||||
Deny,
|
||||
GrantBySection
|
||||
}
|
||||
}
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
public enum AccessType
|
||||
{
|
||||
Grant,
|
||||
Deny,
|
||||
GrantBySection
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,32 +1,32 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class AreaCollection : ConfigurationElementCollection, IEnumerable<IArea>
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new AreaElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((AreaElement) element).Value;
|
||||
}
|
||||
|
||||
IEnumerator<IArea> IEnumerable<IArea>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return BaseGet(i) as IArea;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class AreaCollection : ConfigurationElementCollection, IEnumerable<IArea>
|
||||
{
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new AreaElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((AreaElement) element).Value;
|
||||
}
|
||||
|
||||
IEnumerator<IArea> IEnumerable<IArea>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return BaseGet(i) as IArea;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class AreaElement : InnerTextConfigurationElement<string>, IArea
|
||||
{
|
||||
string IArea.AreaName
|
||||
{
|
||||
get { return Value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class AreaElement : InnerTextConfigurationElement<string>, IArea
|
||||
{
|
||||
string IArea.AreaName
|
||||
{
|
||||
get { return Value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class AreasElement : ConfigurationElement
|
||||
{
|
||||
[ConfigurationCollection(typeof(SectionCollection), AddItemName = "area")]
|
||||
[ConfigurationProperty("", IsDefaultCollection = true)]
|
||||
public AreaCollection AreaCollection
|
||||
{
|
||||
get { return (AreaCollection)base[""]; }
|
||||
set { base[""] = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class AreasElement : ConfigurationElement
|
||||
{
|
||||
[ConfigurationCollection(typeof(SectionCollection), AddItemName = "area")]
|
||||
[ConfigurationProperty("", IsDefaultCollection = true)]
|
||||
public AreaCollection AreaCollection
|
||||
{
|
||||
get { return (AreaCollection)base[""]; }
|
||||
set { base[""] = value; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,37 @@
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class ControlCollection : ConfigurationElementCollection, IEnumerable<IDashboardControl>
|
||||
{
|
||||
internal void Add(ControlElement c)
|
||||
{
|
||||
BaseAdd(c);
|
||||
}
|
||||
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new ControlElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((ControlElement)element).ControlPath;
|
||||
}
|
||||
|
||||
IEnumerator<IDashboardControl> IEnumerable<IDashboardControl>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return BaseGet(i) as IDashboardControl;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class ControlCollection : ConfigurationElementCollection, IEnumerable<IDashboardControl>
|
||||
{
|
||||
internal void Add(ControlElement c)
|
||||
{
|
||||
BaseAdd(c);
|
||||
}
|
||||
|
||||
protected override ConfigurationElement CreateNewElement()
|
||||
{
|
||||
return new ControlElement();
|
||||
}
|
||||
|
||||
protected override object GetElementKey(ConfigurationElement element)
|
||||
{
|
||||
return ((ControlElement)element).ControlPath;
|
||||
}
|
||||
|
||||
IEnumerator<IDashboardControl> IEnumerable<IDashboardControl>.GetEnumerator()
|
||||
{
|
||||
for (var i = 0; i < Count; i++)
|
||||
{
|
||||
yield return BaseGet(i) as IDashboardControl;
|
||||
}
|
||||
}
|
||||
|
||||
IEnumerator IEnumerable.GetEnumerator()
|
||||
{
|
||||
return GetEnumerator();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,74 +1,74 @@
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
|
||||
internal class ControlElement : RawXmlConfigurationElement, IDashboardControl
|
||||
{
|
||||
public bool ShowOnce
|
||||
{
|
||||
get
|
||||
{
|
||||
return RawXml.Attribute("showOnce") == null
|
||||
? false
|
||||
: bool.Parse(RawXml.Attribute("showOnce").Value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool AddPanel
|
||||
{
|
||||
get
|
||||
{
|
||||
return RawXml.Attribute("addPanel") == null
|
||||
? true
|
||||
: bool.Parse(RawXml.Attribute("addPanel").Value);
|
||||
}
|
||||
}
|
||||
|
||||
public string PanelCaption
|
||||
{
|
||||
get
|
||||
{
|
||||
return RawXml.Attribute("panelCaption") == null
|
||||
? ""
|
||||
: RawXml.Attribute("panelCaption").Value;
|
||||
}
|
||||
}
|
||||
|
||||
public AccessElement Access
|
||||
{
|
||||
get
|
||||
{
|
||||
var access = RawXml.Element("access");
|
||||
if (access == null)
|
||||
{
|
||||
return new AccessElement();
|
||||
}
|
||||
return new AccessElement(access);
|
||||
}
|
||||
}
|
||||
|
||||
public string ControlPath
|
||||
{
|
||||
get
|
||||
{
|
||||
//we need to return the first (and only) text element of the children (wtf... who designed this configuration ! :P )
|
||||
var txt = RawXml.Nodes().OfType<XText>().FirstOrDefault();
|
||||
if (txt == null)
|
||||
{
|
||||
throw new ConfigurationErrorsException("The control element must contain a text node indicating the control path");
|
||||
}
|
||||
return txt.Value.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IAccess IDashboardControl.AccessRights
|
||||
{
|
||||
get { return Access; }
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
|
||||
internal class ControlElement : RawXmlConfigurationElement, IDashboardControl
|
||||
{
|
||||
public bool ShowOnce
|
||||
{
|
||||
get
|
||||
{
|
||||
return RawXml.Attribute("showOnce") == null
|
||||
? false
|
||||
: bool.Parse(RawXml.Attribute("showOnce").Value);
|
||||
}
|
||||
}
|
||||
|
||||
public bool AddPanel
|
||||
{
|
||||
get
|
||||
{
|
||||
return RawXml.Attribute("addPanel") == null
|
||||
? true
|
||||
: bool.Parse(RawXml.Attribute("addPanel").Value);
|
||||
}
|
||||
}
|
||||
|
||||
public string PanelCaption
|
||||
{
|
||||
get
|
||||
{
|
||||
return RawXml.Attribute("panelCaption") == null
|
||||
? ""
|
||||
: RawXml.Attribute("panelCaption").Value;
|
||||
}
|
||||
}
|
||||
|
||||
public AccessElement Access
|
||||
{
|
||||
get
|
||||
{
|
||||
var access = RawXml.Element("access");
|
||||
if (access == null)
|
||||
{
|
||||
return new AccessElement();
|
||||
}
|
||||
return new AccessElement(access);
|
||||
}
|
||||
}
|
||||
|
||||
public string ControlPath
|
||||
{
|
||||
get
|
||||
{
|
||||
//we need to return the first (and only) text element of the children (wtf... who designed this configuration ! :P )
|
||||
var txt = RawXml.Nodes().OfType<XText>().FirstOrDefault();
|
||||
if (txt == null)
|
||||
{
|
||||
throw new ConfigurationErrorsException("The control element must contain a text node indicating the control path");
|
||||
}
|
||||
return txt.Value.Trim();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IAccess IDashboardControl.AccessRights
|
||||
{
|
||||
get { return Access; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +1,24 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class DashboardSection : ConfigurationSection, IDashboardSection
|
||||
{
|
||||
[ConfigurationCollection(typeof(SectionCollection), AddItemName = "section")]
|
||||
[ConfigurationProperty("", IsDefaultCollection = true)]
|
||||
public SectionCollection SectionCollection
|
||||
{
|
||||
get { return (SectionCollection)base[""]; }
|
||||
set { base[""] = value; }
|
||||
}
|
||||
|
||||
IEnumerable<ISection> IDashboardSection.Sections
|
||||
{
|
||||
get { return SectionCollection; }
|
||||
}
|
||||
}
|
||||
}
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Configuration;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
internal class DashboardSection : ConfigurationSection, IDashboardSection
|
||||
{
|
||||
[ConfigurationCollection(typeof(SectionCollection), AddItemName = "section")]
|
||||
[ConfigurationProperty("", IsDefaultCollection = true)]
|
||||
public SectionCollection SectionCollection
|
||||
{
|
||||
get { return (SectionCollection)base[""]; }
|
||||
set { base[""] = value; }
|
||||
}
|
||||
|
||||
IEnumerable<ISection> IDashboardSection.Sections
|
||||
{
|
||||
get { return SectionCollection; }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
public interface IAccess
|
||||
{
|
||||
IEnumerable<IAccessItem> Rules { get; }
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
public interface IAccess
|
||||
{
|
||||
IEnumerable<IAccessItem> Rules { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
public interface IAccessItem
|
||||
{
|
||||
/// <summary>
|
||||
/// This can be grant, deny or grantBySection
|
||||
/// </summary>
|
||||
AccessType Action { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The value of the action
|
||||
/// </summary>
|
||||
string Value { get; set; }
|
||||
}
|
||||
}
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
public interface IAccessItem
|
||||
{
|
||||
/// <summary>
|
||||
/// This can be grant, deny or grantBySection
|
||||
/// </summary>
|
||||
AccessType Action { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The value of the action
|
||||
/// </summary>
|
||||
string Value { get; set; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
public interface IArea
|
||||
{
|
||||
string AreaName { get; }
|
||||
}
|
||||
}
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
public interface IArea
|
||||
{
|
||||
string AreaName { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
public interface IDashboardControl
|
||||
{
|
||||
bool ShowOnce { get; }
|
||||
|
||||
bool AddPanel { get; }
|
||||
|
||||
string PanelCaption { get; }
|
||||
|
||||
string ControlPath { get; }
|
||||
|
||||
IAccess AccessRights { get; }
|
||||
}
|
||||
}
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
public interface IDashboardControl
|
||||
{
|
||||
bool ShowOnce { get; }
|
||||
|
||||
bool AddPanel { get; }
|
||||
|
||||
string PanelCaption { get; }
|
||||
|
||||
string ControlPath { get; }
|
||||
|
||||
IAccess AccessRights { get; }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
public interface IDashboardSection
|
||||
{
|
||||
IEnumerable<ISection> Sections { get; }
|
||||
}
|
||||
}
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Umbraco.Core.Configuration.Dashboard
|
||||
{
|
||||
public interface IDashboardSection
|
||||
{
|
||||
IEnumerable<ISection> Sections { get; }
|
||||
}
|
||||
}
|
||||
|
||||